studentList.vue 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100
  1. <template>
  2. <div class="m-container">
  3. <h2>
  4. <div class="squrt"></div>
  5. 学员列表
  6. </h2>
  7. <div class="m-core">
  8. <div
  9. class="newBand"
  10. v-permission="'studentManage/register'"
  11. @click="addStudent"
  12. >
  13. 新增学员
  14. </div>
  15. <div class="newBand" @click="onCreateQRCode">学员激活列表</div>
  16. <!-- 搜索标题 -->
  17. <save-form
  18. :inline="true"
  19. class="searchForm"
  20. @submit="onSearch"
  21. @reset="onReSet"
  22. :model.sync="searchForm"
  23. >
  24. <el-form-item>
  25. <el-input
  26. clearable
  27. placeholder="学生姓名或电话"
  28. @keyup.enter.native="onSearch"
  29. v-model.trim="searchForm.search"
  30. ></el-input>
  31. </el-form-item>
  32. <el-form-item prop="organId">
  33. <el-select
  34. class="multiple"
  35. filterable
  36. v-model.trim="searchForm.organId"
  37. clearable
  38. placeholder="请选择分部"
  39. >
  40. <el-option
  41. v-for="(item, index) in selects.branchs"
  42. :key="index"
  43. :label="item.name"
  44. :value="item.id"
  45. ></el-option>
  46. </el-select>
  47. </el-form-item>
  48. <el-form-item>
  49. <remote-search
  50. :commit="'setTeachers'"
  51. v-model="searchForm.teacherId"
  52. />
  53. <!-- <el-select
  54. placeholder="指导老师"
  55. v-model="searchForm.teacherId"
  56. clearable
  57. filterable
  58. >
  59. <el-option
  60. v-for="(item, index) in selects.teachers"
  61. :label="item.realName"
  62. :value="item.id"
  63. :key="index"
  64. ></el-option>
  65. </el-select> -->
  66. </el-form-item>
  67. <el-form-item prop="isActive">
  68. <el-select
  69. class="multiple"
  70. v-model.trim="searchForm.isActive"
  71. clearable
  72. placeholder="是否激活"
  73. >
  74. <el-option label="是" value="true"></el-option>
  75. <el-option label="否" value="false"></el-option>
  76. </el-select>
  77. </el-form-item>
  78. <el-form-item prop="operatingTag">
  79. <el-select
  80. class="multiple"
  81. v-model.trim="searchForm.operatingTag"
  82. clearable
  83. placeholder="是否运营"
  84. >
  85. <el-option label="是" :value="1"></el-option>
  86. <el-option label="否" :value="0"></el-option>
  87. </el-select>
  88. </el-form-item>
  89. <el-form-item prop="serviceTag">
  90. <el-select
  91. class="multiple"
  92. v-model.trim="searchForm.serviceTag"
  93. clearable
  94. placeholder="是否服务"
  95. >
  96. <el-option label="是" :value="1"></el-option>
  97. <el-option label="否" :value="0"></el-option>
  98. </el-select>
  99. </el-form-item>
  100. <el-form-item prop="carePackage">
  101. <el-select
  102. class="multiple"
  103. v-model.trim="searchForm.carePackage"
  104. clearable
  105. placeholder="关心包"
  106. >
  107. <el-option label="不可用" :value="0"></el-option>
  108. <el-option label="可用" :value="1"></el-option>
  109. <el-option label="已使用" :value="2"></el-option>
  110. </el-select>
  111. </el-form-item>
  112. <el-form-item prop="comeOnPackage">
  113. <el-select
  114. class="multiple"
  115. v-model.trim="searchForm.comeOnPackage"
  116. clearable
  117. placeholder="加油包"
  118. >
  119. <el-option label="不可用" :value="0"></el-option>
  120. <el-option label="可用" :value="1"></el-option>
  121. <el-option label="已使用" :value="2"></el-option>
  122. </el-select>
  123. </el-form-item>
  124. <el-form-item>
  125. <el-button native-type="submit" type="danger">搜索</el-button>
  126. <el-button native-type="reset" type="primary">重置</el-button>
  127. <el-button
  128. type="primary"
  129. v-permission="'export/studentHasCourse'"
  130. @click="downLoadStudent"
  131. >导出名单</el-button
  132. >
  133. </el-form-item>
  134. </save-form>
  135. <!-- 列表 -->
  136. <div class="tableWrap">
  137. <el-table
  138. :data="tableList"
  139. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  140. >
  141. <el-table-column align="center" prop="userId" label="学员编号">
  142. <template slot-scope="scope">
  143. <copy-text>{{ scope.row.userId }}</copy-text>
  144. </template>
  145. </el-table-column>
  146. <el-table-column align="center" prop="username" label="学员姓名">
  147. <template slot-scope="scope">
  148. <copy-text>{{ scope.row.username }}</copy-text>
  149. </template>
  150. </el-table-column>
  151. <el-table-column align="center" prop="organName" label="所属分部">
  152. <template slot-scope="scope">
  153. <copy-text>{{ scope.row.organName }}</copy-text>
  154. </template>
  155. </el-table-column>
  156. <el-table-column
  157. align="center"
  158. prop="cooperationOrganName"
  159. label="所属学校"
  160. ></el-table-column>
  161. <el-table-column
  162. align="center"
  163. prop="subjectName"
  164. label="声部"
  165. ></el-table-column>
  166. <el-table-column align="center" prop="teacherName" label="指导老师">
  167. <template slot-scope="scope">
  168. <copy-text>{{ scope.row.teacherName }}</copy-text>
  169. </template>
  170. </el-table-column>
  171. <el-table-column align="center" label="性别">
  172. <template slot-scope="scope">{{
  173. scope.row.gender ? "男" : "女"
  174. }}</template>
  175. </el-table-column>
  176. <el-table-column
  177. align="center"
  178. prop="realName"
  179. label="家长姓名"
  180. ></el-table-column>
  181. <el-table-column
  182. align="center"
  183. width="120px"
  184. prop="parentsPhone"
  185. label="家长联系电话"
  186. ></el-table-column>
  187. <el-table-column align="center">
  188. <template slot="header">
  189. <p style="position: relative">
  190. 是否激活
  191. <el-tooltip placement="top" popper-class="mTooltip">
  192. <div slot="content">学员是否设置密码</div>
  193. <i
  194. class="el-icon-question"
  195. style="font-size: 18px; color: #f56c6c"
  196. ></i>
  197. </el-tooltip>
  198. </p>
  199. </template>
  200. <template slot-scope="scope">{{
  201. scope.row.isActive ? "是" : "否"
  202. }}</template>
  203. </el-table-column>
  204. <el-table-column align="center" label="未上课时">
  205. <template slot-scope="scope">{{
  206. scope.row.hasCourse ? "有" : "无"
  207. }}</template>
  208. </el-table-column>
  209. <!-- <el-table-column align="center" label="预约网管课">
  210. <template slot-scope="scope">{{ scope.row.isMake ? '是' : '否' }}</template>
  211. </el-table-column> -->
  212. <el-table-column align="center" label="是否有网管课">
  213. <template slot-scope="scope">{{
  214. scope.row.hasPracticeCourse ? "是" : "否"
  215. }}</template>
  216. </el-table-column>
  217. <el-table-column align="center" label="是否运营">
  218. <template slot-scope="scope">{{
  219. scope.row.operatingTag ? "是" : "否"
  220. }}</template>
  221. </el-table-column>
  222. <el-table-column align="center" label="是否服务">
  223. <template slot-scope="scope">{{
  224. scope.row.serviceTag ? "是" : "否"
  225. }}</template>
  226. </el-table-column>
  227. <el-table-column align="center" label="是否是新用户">
  228. <template slot="header">
  229. <p style="position: relative">
  230. 是否是新用户
  231. <el-tooltip placement="top" popper-class="mTooltip">
  232. <div slot="content">
  233. 没有有效的VIP课程或未参与2020年双十一活动的用户为新用户
  234. </div>
  235. <i
  236. class="el-icon-question"
  237. style="font-size: 18px; color: #f56c6c"
  238. ></i>
  239. </el-tooltip>
  240. </p>
  241. </template>
  242. <template slot-scope="scope">
  243. {{ scope.row.isNewUser ? "是" : "否" }}
  244. </template>
  245. </el-table-column>
  246. <el-table-column
  247. align="center"
  248. prop="courseBalance"
  249. label="课程余额(元)"
  250. >
  251. <template slot-scope="scope">
  252. <div>
  253. {{ scope.row.courseBalance | moneyFormat }}
  254. </div>
  255. </template>
  256. </el-table-column>
  257. <el-table-column align="center" prop="carePackage" label="关心包">
  258. <template slot-scope="scope">{{
  259. scope.row.carePackage | studentPackage
  260. }}</template>
  261. </el-table-column>
  262. <el-table-column align="center" prop="comeOnPackage" label="加油包">
  263. <template slot-scope="scope">{{
  264. scope.row.comeOnPackage | studentPackage
  265. }}</template>
  266. </el-table-column>
  267. <el-table-column
  268. align="center"
  269. fixed="right"
  270. width="250px"
  271. label="操作"
  272. >
  273. <template slot-scope="scope">
  274. <router-link
  275. v-permission="'/studentDetail'"
  276. class="el-button--text"
  277. :to="{
  278. path: `/studentManager/studentDetail`,
  279. query: { ...scope.row },
  280. }"
  281. >查看</router-link
  282. >
  283. <el-button
  284. type="text"
  285. style="padding-left: 10px"
  286. v-permission="'studentManage/studentUpdate'"
  287. @click="resetStudent(scope.row)"
  288. >修改</el-button
  289. >
  290. <!-- api-auth/user/updatePassword2 -->
  291. <el-button
  292. v-permission="'api-auth/user/updatePassword2'"
  293. @click="resetPassWrod(scope.row)"
  294. type="text"
  295. >修改密码</el-button
  296. >
  297. <el-button
  298. v-if="scope.row.isSignedContract"
  299. type="text"
  300. @click="lookContracts(scope.row)"
  301. v-permission="'sysUserContracts/getLatest'"
  302. >下载协议</el-button
  303. >
  304. </template>
  305. </el-table-column>
  306. </el-table>
  307. <pagination
  308. sync
  309. :total.sync="pageInfo.total"
  310. :page.sync="pageInfo.page"
  311. :limit.sync="pageInfo.limit"
  312. :page-sizes="pageInfo.page_size"
  313. @pagination="getList"
  314. />
  315. </div>
  316. </div>
  317. <el-dialog
  318. :title="maskName"
  319. width="700px"
  320. label-position="right"
  321. class="studentInfo"
  322. @close="onMaskClose('studentForm')"
  323. :close-on-click-modal="false"
  324. :visible.sync="studentVisible"
  325. >
  326. <el-form
  327. :model="studentForm"
  328. :inline="true"
  329. label-width="130px"
  330. label-position="right"
  331. ref="studentForm"
  332. :rules="studentRules"
  333. >
  334. <el-alert
  335. title="课程信息"
  336. type="info"
  337. :closable="false"
  338. style="margin-bottom: 15px"
  339. ></el-alert>
  340. <el-form-item label="学生姓名" prop="name">
  341. <el-input v-model.trim="studentForm.name"></el-input>
  342. </el-form-item>
  343. <el-form-item label="学生性别" prop="sex">
  344. <el-select
  345. class="multiple"
  346. filterable
  347. v-model.trim="studentForm.sex"
  348. clearable
  349. placeholder="请选择性别"
  350. >
  351. <el-option :value="1" label="男"></el-option>
  352. <el-option :value="0" label="女"></el-option>
  353. </el-select>
  354. </el-form-item>
  355. <el-form-item label="出生日期" prop="date">
  356. <el-date-picker
  357. v-model.trim="studentForm.date"
  358. style="width: 185px"
  359. value-format="yyyy-MM-dd"
  360. type="date"
  361. :picker-options="{
  362. firstDayOfWeek: 1,
  363. }"
  364. placeholder="选择日期"
  365. ></el-date-picker>
  366. </el-form-item>
  367. <el-form-item label="学生声部" prop="subjectIdList">
  368. <el-select
  369. v-model.trim="studentForm.subjectIdList"
  370. filterable
  371. clearable
  372. placeholder="学员声部"
  373. >
  374. <el-option-group
  375. v-for="group in subjectList"
  376. :key="group.label"
  377. :label="group.label"
  378. >
  379. <el-option
  380. v-for="item in group.options"
  381. :key="item.value"
  382. :label="item.label"
  383. :value="item.value"
  384. ></el-option>
  385. </el-option-group>
  386. </el-select>
  387. </el-form-item>
  388. <el-form-item label="家长姓名" prop="parseName">
  389. <el-input v-model.trim="studentForm.parseName"></el-input>
  390. </el-form-item>
  391. <el-form-item
  392. label="联系电话"
  393. prop="phone"
  394. :rules="[
  395. { required: true, message: '请输入手机号' },
  396. {
  397. pattern: /^1\d{10}$/,
  398. message: '请输入正确的手机号',
  399. trigger: 'blur',
  400. },
  401. ]"
  402. >
  403. <!-- @blur="checkPhone(studentForm.phone)" -->
  404. <el-input :maxlength="11" v-model.trim="studentForm.phone"></el-input>
  405. </el-form-item>
  406. <el-form-item label="所属分部" prop="organId">
  407. <el-select
  408. class="multiple"
  409. v-model.trim="studentForm.organId"
  410. filterable
  411. clearable
  412. placeholder="请选择分部"
  413. @change="changeStudentOrgan"
  414. >
  415. <el-option
  416. v-for="(item, index) in selects.branchs"
  417. :key="index"
  418. :label="item.name"
  419. :value="item.id"
  420. ></el-option>
  421. </el-select>
  422. </el-form-item>
  423. <el-form-item prop="school" label="所属学校">
  424. <el-select v-model.trim="studentForm.school" filterable clearable :disabled='!studentForm.organId'>
  425. <el-option
  426. v-for="(item, index) in cooperationList"
  427. :key="index"
  428. :label="item.name"
  429. :value="item.id"
  430. ></el-option>
  431. </el-select>
  432. </el-form-item>
  433. <el-form-item label="指导老师" prop="teacherId">
  434. <el-select
  435. class="multiple"
  436. v-model.trim="studentForm.teacherId"
  437. clearable
  438. filterable
  439. >
  440. <el-option
  441. v-for="(item, index) in maskTeacherList"
  442. :label="item.realName"
  443. :value="item.id"
  444. :key="index"
  445. ></el-option>
  446. </el-select>
  447. </el-form-item>
  448. <el-alert
  449. title="课程信息"
  450. type="info"
  451. :closable="false"
  452. style="margin-bottom: 15px"
  453. ></el-alert>
  454. <el-form-item label="是否运营" prop="operatingTag">
  455. <el-select
  456. class="multiple"
  457. v-model.trim="studentForm.operatingTag"
  458. clearable
  459. >
  460. <el-option :value="1" label="是"></el-option>
  461. <el-option :value="0" label="否"></el-option>
  462. </el-select>
  463. </el-form-item>
  464. <el-form-item label="是否服务" prop="serviceTag">
  465. <el-select
  466. class="multiple"
  467. v-model.trim="studentForm.serviceTag"
  468. clearable
  469. >
  470. <el-option :value="1" label="是"></el-option>
  471. <el-option :value="0" label="否"></el-option>
  472. </el-select>
  473. </el-form-item>
  474. <el-form-item label="是否是新用户" prop="isNewUser">
  475. <template #label>
  476. <p style="position: relative; display: inline-block">
  477. 是否是新用户
  478. <el-tooltip placement="top" popper-class="mTooltip">
  479. <div slot="content">
  480. 没有有效的VIP课程或未参与2020年双十一活动的用户为新用户
  481. </div>
  482. <i
  483. class="el-icon-question"
  484. style="font-size: 18px; color: #f56c6c"
  485. ></i>
  486. </el-tooltip>
  487. </p>
  488. </template>
  489. <el-select
  490. class="multiple"
  491. v-model.trim="studentForm.isNewUser"
  492. clearable
  493. >
  494. <el-option :value="1" label="是"></el-option>
  495. <el-option :value="0" label="否"></el-option>
  496. </el-select>
  497. </el-form-item>
  498. <el-form-item label="关心包" prop="carePackage">
  499. <el-select
  500. class="multiple"
  501. v-model.trim="studentForm.carePackage"
  502. clearable
  503. :disabled="!isNew && studentUpdatePackage.carePackage == 2"
  504. placeholder="请选择关心包"
  505. >
  506. <el-option label="不可用" :value="0"></el-option>
  507. <el-option label="可用" :value="1"></el-option>
  508. <el-option disabled label="已使用" :value="2"></el-option>
  509. </el-select>
  510. </el-form-item>
  511. <el-form-item label="加油包" prop="comeOnPackage">
  512. <el-select
  513. class="multiple"
  514. v-model.trim="studentForm.comeOnPackage"
  515. clearable
  516. :disabled="!isNew && studentUpdatePackage.comeOnPackage == 2"
  517. placeholder="请选择加油包"
  518. >
  519. <el-option label="不可用" :value="0"></el-option>
  520. <el-option label="可用" :value="1"></el-option>
  521. <el-option disabled label="已使用" :value="2"></el-option>
  522. </el-select>
  523. </el-form-item>
  524. </el-form>
  525. <div slot="footer" class="dialog-footer">
  526. <el-button @click="studentVisible = false">取 消</el-button>
  527. <el-button type="primary" v-if="isNew" @click="submitAddStudent"
  528. >确 定</el-button
  529. >
  530. <el-button type="primary" v-if="!isNew" @click="resetStudentSubmie"
  531. >确 定</el-button
  532. >
  533. </div>
  534. </el-dialog>
  535. <!-- 学员激活列表 -->
  536. <qr-code v-model="qrcodeStatus" title="学员激活列表" :codeUrl="qrcodeUrl" />
  537. <el-dialog
  538. title="修改密码"
  539. :visible.sync="passwrodVisiable"
  540. :before-close="closePassWord"
  541. width="400px"
  542. >
  543. <el-form :model="passwrodForm" ref="passwrodForm" :inline="true">
  544. <el-form-item
  545. label="手机号"
  546. prop="phone"
  547. label-width="120px"
  548. :rules="[
  549. { required: true, message: '手机号不能为空', trigger: 'blur' },
  550. {
  551. pattern: /^1\d{10}$/,
  552. message: '请输入正确的手机号',
  553. trigger: 'blur',
  554. },
  555. ]"
  556. >
  557. <copy-text>{{ passwrodForm.phone }}</copy-text>
  558. </el-form-item>
  559. <el-form-item
  560. label="输入密码"
  561. prop="password"
  562. label-width="120px"
  563. :rules="[
  564. { required: true, message: '密码不能为空', trigger: 'blur' },
  565. {
  566. pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/,
  567. message: '密码为6-20位数字和字母组合',
  568. trigger: 'blur',
  569. },
  570. ]"
  571. >
  572. <el-input v-model.trim="passwrodForm.password"></el-input>
  573. </el-form-item>
  574. <el-form-item
  575. label="再次输入"
  576. prop="password2"
  577. label-width="120px"
  578. :rules="[
  579. { required: true, message: '密码不能为空', trigger: 'blur' },
  580. {
  581. pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/,
  582. message: '密码为6-20位数字和字母组合',
  583. trigger: 'blur',
  584. },
  585. ]"
  586. >
  587. <el-input v-model.trim="passwrodForm.password2"></el-input>
  588. </el-form-item>
  589. </el-form>
  590. <span slot="footer" class="dialog-footer">
  591. <el-button @click="passwrodVisiable = false">取 消</el-button>
  592. <el-button type="primary" @click="submitResetPassWord">确 定</el-button>
  593. </span>
  594. </el-dialog>
  595. <el-dialog title="协议下载" :visible.sync="protocolVisible" width="600px">
  596. <div v-if="protocolVisible">
  597. <!-- <el-alert
  598. title="点击下载"
  599. :closable="false"
  600. type="info">
  601. </el-alert>
  602. <p style="font-size: 14px; color: #14928A; line-height: 1.5; padding: 8px 16px; cursor: pointer;" v-for="item in protocolVersions" :key="item.id" @click="onDownloadProtocol(item)">
  603. 产品与服务协议{{ item.version == 2 ? "(含课程)" : "(含系统)" }}
  604. </p> -->
  605. <el-table
  606. style="width: 100%"
  607. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  608. :data="protocolVersions"
  609. >
  610. <el-table-column align="center" prop="studentId" label="协议名称">
  611. <template slot-scope="scope">
  612. 产品与服务协议{{
  613. scope.row.version == 2 ? "(含课程)" : "(含系统)"
  614. }}
  615. </template>
  616. </el-table-column>
  617. <el-table-column align="center" label="签署时间" prop="createTime">
  618. </el-table-column>
  619. <el-table-column align="center" width="150px" label="操作">
  620. <template slot-scope="scope">
  621. <div>
  622. <el-button type="text" @click="onDownloadProtocol(scope.row)"
  623. >下载</el-button
  624. >
  625. </div>
  626. </template>
  627. </el-table-column>
  628. </el-table>
  629. </div>
  630. <span slot="footer" class="dialog-footer">
  631. <el-button @click="protocolVisible = false">取 消</el-button>
  632. </span>
  633. </el-dialog>
  634. </div>
  635. </template>
  636. <script>
  637. import pagination from "@/components/Pagination/index";
  638. import {
  639. queryStudentList,
  640. getStudentInfoByPhone,
  641. registerStudent,
  642. updateStudent,
  643. studentHasCourse,
  644. getLatest,
  645. } from "@/api/studentManager";
  646. import { queryByOrganId } from "@/api/systemManage";
  647. import qrCode from "@/components/QrCode/index";
  648. import cleanDeep from "clean-deep";
  649. import { vaildStudentUrl } from "@/utils/validate";
  650. import { getEmployeeOrgan, resetPassword2, getTeacher } from "@/api/buildTeam";
  651. import { subjectListTree } from "@/api/specialSetting";
  652. import axios from "axios";
  653. import qs from "qs";
  654. import { packageStatus } from "@/constant/index";
  655. import { getToken } from "@/utils/auth";
  656. import load from "@/utils/loading";
  657. import { permission } from "@/utils/directivePage";
  658. export default {
  659. name: "studentList",
  660. components: { pagination, qrCode },
  661. data() {
  662. return {
  663. studentVisible: false,
  664. searchForm: {
  665. organId: null,
  666. search: null,
  667. studentName: null,
  668. isActive: null,
  669. hasCourse: null,
  670. // isMake: null,
  671. hasPracticeCourse: null,
  672. operatingTag: null,
  673. serviceTag: null,
  674. teacherId: null,
  675. carePackage: null,
  676. comeOnPackage: null,
  677. },
  678. searchList: [],
  679. tableList: [],
  680. organList: [],
  681. teacherList: [],
  682. maskTeacherList: [],
  683. subjectList: [], // 声部列表
  684. pageInfo: {
  685. // 分页规则
  686. limit: 10, // 限制显示条数
  687. page: 1, // 当前页
  688. total: 0, // 总条数
  689. page_size: [10, 20, 40, 50], // 选择限制显示条数
  690. },
  691. studentForm: {
  692. phone: "",
  693. organId: "",
  694. name: "",
  695. sex: "",
  696. parseName: "",
  697. date: "",
  698. serviceTag: null,
  699. operatingTag: null,
  700. teacherId: null,
  701. subjectIdList: null,
  702. isNewUser: null,
  703. carePackage: 0,
  704. comeOnPackage: 0,
  705. school:null
  706. },
  707. studentUpdatePackage: {
  708. carePackage: 0,
  709. comeOnPackage: 0,
  710. },
  711. studentRules: {
  712. name: [{ required: true, message: "请输入学生姓名" }],
  713. sex: [{ required: true, message: "请选择学生性别" }],
  714. date: [{ required: true, message: "请选择出生日期" }],
  715. organId: [{ required: true, message: "请选择分部" }],
  716. subjectIdList: [{ required: true, message: "请选择声部" }],
  717. serviceTag: [{ required: true, message: "请选择是否参与服务" }],
  718. isNewUser: [{ required: true, message: "请选择是否是新用户" }],
  719. operatingTag: [{ required: true, message: "请选择是否参与运营" }],
  720. teacherId: [{ required: true, message: "请选择指导老师" }],
  721. },
  722. isNew: false,
  723. active: null,
  724. maskName: "新增学员",
  725. qrcodeStatus: false,
  726. qrcodeUrl: null,
  727. activeRow: null,
  728. passwrodVisiable: false,
  729. passwrodForm: {
  730. phone: "",
  731. password: "",
  732. password2: "",
  733. },
  734. activatedRow: null,
  735. protocolVisible: false,
  736. protocolVersions: [],
  737. cooperationList: [],
  738. };
  739. },
  740. mounted() {
  741. this.$store.dispatch("setBranchs");
  742. this.$store.dispatch("setTeachers");
  743. this.getList();
  744. },
  745. methods: {
  746. onSearch() {
  747. this.pageInfo.page = 1;
  748. this.getList();
  749. },
  750. onCreateQRCode() {
  751. // 生成报名二维码
  752. this.qrcodeStatus = true;
  753. this.qrcodeUrl = vaildStudentUrl() + `/#/queryStudentPer`;
  754. },
  755. getList() {
  756. let params = this.searchForm;
  757. params.rows = this.pageInfo.limit;
  758. params.page = this.pageInfo.page;
  759. params.organId ? params.organId : (params.organId = null);
  760. queryStudentList(params).then((res) => {
  761. if (res.code == 200) {
  762. this.tableList = res.data.rows;
  763. this.pageInfo.total = res.data.total;
  764. }
  765. });
  766. },
  767. onReSet() {
  768. this.searchForm = {
  769. organId: null,
  770. search: null,
  771. studentName: null,
  772. isActive: null,
  773. hasCourse: null,
  774. // isMake: null,
  775. hasPracticeCourse: null,
  776. operatingTag: null,
  777. serviceTag: null,
  778. teacherId: null,
  779. };
  780. this.getList();
  781. },
  782. downLoadStudent() {
  783. let url = "/api-web/export/studentHasCourse";
  784. let searchForm = this.searchForm;
  785. let data = {
  786. organId: searchForm.organId ? searchForm.organId : null,
  787. search: searchForm.search ? searchForm.search : null,
  788. isActive: searchForm.isActive ? searchForm.isActive : null,
  789. hasCourse: searchForm.hasCourse == "" ? null : searchForm.hasCourse,
  790. // isMake: searchForm.isMake ? searchForm.isMake : null,
  791. hasPracticeCourse: searchForm.hasPracticeCourse
  792. ? searchForm.hasPracticeCourse
  793. : null,
  794. operatingTag: searchForm.operatingTag ? searchForm.operatingTag : null,
  795. serviceTag: searchForm.serviceTag ? searchForm.serviceTag : null,
  796. teacherId: searchForm.teacherId ? searchForm.teacherId : null,
  797. };
  798. const options = {
  799. method: "POST",
  800. headers: {
  801. Authorization: getToken(),
  802. },
  803. url,
  804. data: qs.stringify(data),
  805. responseType: "blob",
  806. };
  807. this.$confirm("确定导出学员名单?", "提示", {
  808. confirmButtonText: "确定",
  809. cancelButtonText: "取消",
  810. type: "warning",
  811. })
  812. .then(() => {
  813. load.startLoading();
  814. axios(options)
  815. .then((res) => {
  816. let blob = new Blob([res.data], {
  817. // type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8',
  818. type: "application/vnd.ms-excel;charset=utf-8",
  819. // word文档为application/msword,pdf文档为application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
  820. });
  821. let text = new Response(blob).text();
  822. text.then((res) => {
  823. // 判断是否报错
  824. if (res.indexOf("code") != -1) {
  825. let json = JSON.parse(res);
  826. this.$message.error(json.msg);
  827. } else {
  828. let objectUrl = URL.createObjectURL(blob);
  829. let link = document.createElement("a");
  830. let nowTime = new Date();
  831. let ymd =
  832. nowTime.getFullYear() +
  833. (nowTime.getMonth() + 1) +
  834. nowTime.getDate();
  835. let fname = `导出学员名单` + ymd + ".xlsx"; //下载文件的名字
  836. link.href = objectUrl;
  837. link.setAttribute("download", fname);
  838. document.body.appendChild(link);
  839. link.click();
  840. }
  841. });
  842. load.endLoading();
  843. })
  844. .catch((error) => {
  845. this.$message.error("导出数据失败,请联系管理员");
  846. load.endLoading();
  847. });
  848. })
  849. .catch(() => {});
  850. },
  851. checkPhone(val) {
  852. var regu = /^1\d{10}$/;
  853. var re = new RegExp(regu);
  854. if (re.test(val)) {
  855. getStudentInfoByPhone({ mobile: this.studentForm.phone }).then(
  856. (res) => {
  857. if (res.code == 200) {
  858. if (res.data) {
  859. this.studentForm = {
  860. name: res.data.name,
  861. sex: res.data.gender,
  862. parseName: res.data.parentsName,
  863. // sound: parseInt(res.data.subjectIdList),
  864. phone: val,
  865. date: res.data.birthdate,
  866. };
  867. }
  868. }
  869. }
  870. );
  871. }
  872. },
  873. submitAddStudent() {
  874. const studentForm = this.studentForm;
  875. // 效验 然后组数据提交
  876. this.$refs["studentForm"].validate((item) => {
  877. if (item) {
  878. let obj = {
  879. phone: studentForm.phone,
  880. username: studentForm.name,
  881. gender: studentForm.sex,
  882. realName: studentForm.parseName,
  883. birthdate: studentForm.date,
  884. organId: studentForm.organId,
  885. serviceTag: studentForm.serviceTag,
  886. operatingTag: studentForm.operatingTag,
  887. teacherId: studentForm.teacherId,
  888. isNewUser: studentForm.isNewUser,
  889. subjectIdList: studentForm.subjectIdList,
  890. carePackage: studentForm.carePackage,
  891. comeOnPackage: studentForm.comeOnPackage,
  892. cooperationOrganId:studentForm.school
  893. };
  894. registerStudent(obj).then((res) => {
  895. if (res.code == 200) {
  896. this.$message.success("添加成功");
  897. this.studentVisible = false;
  898. this.getList();
  899. }
  900. });
  901. }
  902. });
  903. },
  904. // 修改学生信息
  905. resetStudentSubmie() {
  906. const studentForm = this.studentForm;
  907. this.$refs["studentForm"].validate((item) => {
  908. if (item) {
  909. let obj = {
  910. phone: studentForm.phone,
  911. username: studentForm.name,
  912. gender: studentForm.sex,
  913. realName: studentForm.parseName,
  914. birthdate: studentForm.date,
  915. organId: studentForm.organId,
  916. id: this.active.userId,
  917. serviceTag: studentForm.serviceTag,
  918. operatingTag: studentForm.operatingTag,
  919. teacherId: studentForm.teacherId,
  920. isNewUser: studentForm.isNewUser,
  921. subjectIdList: studentForm.subjectIdList,
  922. carePackage: studentForm.carePackage,
  923. comeOnPackage: studentForm.comeOnPackage,
  924. cooperationOrganId:studentForm.school
  925. };
  926. updateStudent(obj).then((res) => {
  927. if (res.code == 200) {
  928. this.$message.success("修改成功");
  929. this.studentVisible = false;
  930. this.getList();
  931. }
  932. });
  933. }
  934. });
  935. },
  936. async getSubjectList() {
  937. await subjectListTree({
  938. delFlag: "NO",
  939. tenantId: 1,
  940. rows: 9999,
  941. }).then((res) => {
  942. let result = res.data;
  943. if (res.code == 200) {
  944. let tempArray = [];
  945. result.rows.forEach((item, index) => {
  946. let subject = [];
  947. item.subjects.forEach((s) => {
  948. subject.push({
  949. value: s.id,
  950. label: s.name,
  951. });
  952. });
  953. tempArray[index] = {
  954. label: item.name,
  955. options: subject,
  956. };
  957. });
  958. this.subjectList = tempArray;
  959. }
  960. });
  961. },
  962. async addStudent() {
  963. await this.getSubjectList();
  964. this.isNew = true;
  965. this.studentVisible = true;
  966. this.maskName = "新增学员";
  967. },
  968. async resetStudent(row) {
  969. let organId = row.organId;
  970. await this.getSubjectList();
  971. await this.changeStudentOrgan(row.organId);
  972. this.isNew = false;
  973. this.active = row;
  974. this.studentVisible = true;
  975. this.maskName = "修改学员";
  976. this.$nextTick(() => {
  977. this.studentForm = {
  978. phone: row.parentsPhone || null,
  979. name: row.username || null,
  980. sex: row.gender,
  981. parseName: row.realName || null,
  982. date: row.birthdate || null,
  983. organId: row.organId || null,
  984. serviceTag: row.serviceTag,
  985. operatingTag: row.operatingTag,
  986. teacherId: row.teacherId || null,
  987. isNewUser: row.isNewUser,
  988. subjectIdList: Number(row.subjectIdList) || null,
  989. carePackage: row.carePackage,
  990. comeOnPackage: row.comeOnPackage,
  991. school:row.cooperationOrganId
  992. };
  993. this.studentUpdatePackage = {
  994. carePackage: row.carePackage,
  995. comeOnPackage: row.comeOnPackage,
  996. };
  997. });
  998. },
  999. onMaskClose(formName) {
  1000. this.$refs[formName].resetFields();
  1001. },
  1002. resetPassWrod(row) {
  1003. this.activatedRow = row;
  1004. this.passwrodForm.phone = row.parentsPhone;
  1005. this.passwrodVisiable = true;
  1006. },
  1007. closePassWord() {
  1008. this.activatedRow = null;
  1009. this.passwrodForm = {
  1010. phone: "",
  1011. password: "",
  1012. password2: "",
  1013. };
  1014. this.$refs["passwrodForm"].resetFields();
  1015. this.passwrodVisiable = false;
  1016. },
  1017. submitResetPassWord() {
  1018. if (this.passwrodForm.password !== this.passwrodForm.password2) {
  1019. this.$message.error("两次密码必须相同");
  1020. return;
  1021. }
  1022. this.$refs["passwrodForm"].validate((res) => {
  1023. if (res) {
  1024. // 发请求
  1025. resetPassword2({
  1026. mobile: this.passwrodForm.phone,
  1027. newPassword: this.passwrodForm.password,
  1028. userId: this.activatedRow.userId,
  1029. }).then((res) => {
  1030. if (res.code == 200) {
  1031. // 修改成功
  1032. this.$message.success("修改成功");
  1033. this.closePassWord();
  1034. }
  1035. });
  1036. }
  1037. });
  1038. },
  1039. async changeStudentOrgan(val) {
  1040. this.studentForm.teacherId = null;
  1041. if (val) {
  1042. await getTeacher({ organId: val }).then((res) => {
  1043. if (res.code == 200) {
  1044. this.maskTeacherList = res.data;
  1045. }
  1046. });
  1047. queryByOrganId({ organId: val }).then((res) => {
  1048. if (res.code == 200) {
  1049. this.cooperationList = res.data;
  1050. }
  1051. });
  1052. } else {
  1053. this.maskTeacherList = [];
  1054. }
  1055. },
  1056. async lookContracts(row) {
  1057. await getLatest({ userId: row.userId }).then((res) => {
  1058. if (res.code == 200) {
  1059. if (res.data) {
  1060. this.protocolVersions = res.data;
  1061. this.protocolVisible = true;
  1062. }
  1063. }
  1064. });
  1065. },
  1066. onDownloadProtocol(item) {
  1067. window.location.href = item.url;
  1068. },
  1069. },
  1070. };
  1071. </script>
  1072. <style lang="scss" scoped>
  1073. .newBand {
  1074. display: inline-block;
  1075. margin-right: 10px;
  1076. }
  1077. .right-code {
  1078. // width: 50%;
  1079. // float: left;
  1080. .title {
  1081. font-size: 18px;
  1082. text-align: center;
  1083. padding-bottom: 8px;
  1084. }
  1085. }
  1086. /deep/.studentInfo {
  1087. .multiple.el-select {
  1088. width: 185px !important;
  1089. }
  1090. }
  1091. </style>