studentList.vue 35 KB

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