studentList.vue 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  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. </div>
  598. </template>
  599. <script>
  600. import pagination from "@/components/Pagination/index";
  601. import {
  602. queryStudentList,
  603. getStudentInfoByPhone,
  604. registerStudent,
  605. updateStudent,
  606. studentHasCourse,
  607. getLatest,
  608. } from "@/api/studentManager";
  609. import qrCode from '@/components/QrCode/index';
  610. import cleanDeep from "clean-deep";
  611. import { vaildStudentUrl } from "@/utils/validate";
  612. import { getEmployeeOrgan, resetPassword2, getTeacher } from "@/api/buildTeam";
  613. import { subjectListTree } from "@/api/specialSetting";
  614. import axios from "axios";
  615. import qs from "qs";
  616. import { packageStatus } from '@/constant/index'
  617. import { getToken } from "@/utils/auth";
  618. import load from "@/utils/loading";
  619. import { permission } from "@/utils/directivePage";
  620. export default {
  621. name: "studentList",
  622. components: { pagination, qrCode },
  623. data() {
  624. return {
  625. studentVisible: false,
  626. searchForm: {
  627. organId: null,
  628. search: null,
  629. studentName: null,
  630. isActive: null,
  631. hasCourse: null,
  632. // isMake: null,
  633. hasPracticeCourse: null,
  634. operatingTag: null,
  635. serviceTag: null,
  636. teacherId: null,
  637. carePackage: null,
  638. comeOnPackage: null,
  639. },
  640. searchList: [],
  641. tableList: [],
  642. organList: [],
  643. teacherList: [],
  644. maskTeacherList: [],
  645. subjectList: [], // 声部列表
  646. pageInfo: {
  647. // 分页规则
  648. limit: 10, // 限制显示条数
  649. page: 1, // 当前页
  650. total: 0, // 总条数
  651. page_size: [10, 20, 40, 50], // 选择限制显示条数
  652. },
  653. studentForm: {
  654. phone: "",
  655. organId: "",
  656. name: "",
  657. sex: "",
  658. parseName: "",
  659. date: "",
  660. serviceTag: null,
  661. operatingTag: null,
  662. teacherId: null,
  663. subjectIdList: null,
  664. isNewUser: null,
  665. carePackage: 0,
  666. comeOnPackage: 0,
  667. },
  668. studentUpdatePackage: {
  669. carePackage: 0,
  670. comeOnPackage: 0
  671. },
  672. studentRules: {
  673. name: [{ required: true, message: "请输入学生姓名" }],
  674. sex: [{ required: true, message: "请选择学生性别" }],
  675. date: [{ required: true, message: "请选择出生日期" }],
  676. organId: [{ required: true, message: "请选择分部" }],
  677. subjectIdList: [{ required: true, message: "请选择声部" }],
  678. serviceTag: [{ required: true, message: "请选择是否参与服务" }],
  679. isNewUser: [{ required: true, message: "请选择是否是新用户" }],
  680. operatingTag: [{ required: true, message: "请选择是否参与运营" }],
  681. teacherId: [{ required: true, message: "请选择指导老师" }],
  682. },
  683. isNew: false,
  684. active: null,
  685. maskName: "新增学员",
  686. qrcodeStatus: false,
  687. qrcodeUrl: null,
  688. activeRow: null,
  689. passwrodVisiable: false,
  690. passwrodForm: {
  691. phone: "",
  692. password: "",
  693. password2: "",
  694. },
  695. activatedRow: null,
  696. };
  697. },
  698. mounted() {
  699. this.$store.dispatch("setBranchs");
  700. this.$store.dispatch("setTeachers");
  701. this.getList();
  702. },
  703. methods: {
  704. onSearch() {
  705. this.pageInfo.page = 1;
  706. this.getList();
  707. },
  708. onCreateQRCode() {
  709. // 生成报名二维码
  710. this.qrcodeStatus = true;
  711. this.qrcodeUrl = vaildStudentUrl() + `/#/queryStudentPer`
  712. },
  713. getList() {
  714. let params = this.searchForm;
  715. params.rows = this.pageInfo.limit;
  716. params.page = this.pageInfo.page;
  717. params.organId ? params.organId : (params.organId = null);
  718. queryStudentList(params).then((res) => {
  719. if (res.code == 200) {
  720. this.tableList = res.data.rows;
  721. this.pageInfo.total = res.data.total;
  722. }
  723. });
  724. },
  725. onReSet() {
  726. this.searchForm = {
  727. organId: null,
  728. search: null,
  729. studentName: null,
  730. isActive: null,
  731. hasCourse: null,
  732. // isMake: null,
  733. hasPracticeCourse: null,
  734. operatingTag: null,
  735. serviceTag: null,
  736. teacherId: null,
  737. };
  738. this.getList()
  739. },
  740. downLoadStudent() {
  741. let url = "/api-web/export/studentHasCourse";
  742. let searchForm = this.searchForm;
  743. let data = {
  744. organId: searchForm.organId ? searchForm.organId : null,
  745. search: searchForm.search ? searchForm.search : null,
  746. isActive: searchForm.isActive ? searchForm.isActive : null,
  747. hasCourse: searchForm.hasCourse == "" ? null : searchForm.hasCourse,
  748. // isMake: searchForm.isMake ? searchForm.isMake : null,
  749. hasPracticeCourse: searchForm.hasPracticeCourse
  750. ? searchForm.hasPracticeCourse
  751. : null,
  752. operatingTag: searchForm.operatingTag ? searchForm.operatingTag : null,
  753. serviceTag: searchForm.serviceTag ? searchForm.serviceTag : null,
  754. teacherId: searchForm.teacherId ? searchForm.teacherId : null,
  755. };
  756. const options = {
  757. method: "POST",
  758. headers: {
  759. Authorization: getToken(),
  760. },
  761. url,
  762. data: qs.stringify(data),
  763. responseType: "blob",
  764. };
  765. this.$confirm("确定导出学员名单?", "提示", {
  766. confirmButtonText: "确定",
  767. cancelButtonText: "取消",
  768. type: "warning",
  769. })
  770. .then(() => {
  771. load.startLoading();
  772. axios(options)
  773. .then((res) => {
  774. let blob = new Blob([res.data], {
  775. // type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8',
  776. type: "application/vnd.ms-excel;charset=utf-8",
  777. // word文档为application/msword,pdf文档为application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
  778. });
  779. let text = new Response(blob).text();
  780. text.then((res) => {
  781. // 判断是否报错
  782. if (res.indexOf("code") != -1) {
  783. let json = JSON.parse(res);
  784. this.$message.error(json.msg);
  785. } else {
  786. let objectUrl = URL.createObjectURL(blob);
  787. let link = document.createElement("a");
  788. let nowTime = new Date();
  789. let ymd =
  790. nowTime.getFullYear() +
  791. (nowTime.getMonth() + 1) +
  792. nowTime.getDate();
  793. let fname = `导出学员名单` + ymd + ".xlsx"; //下载文件的名字
  794. link.href = objectUrl;
  795. link.setAttribute("download", fname);
  796. document.body.appendChild(link);
  797. link.click();
  798. }
  799. });
  800. load.endLoading();
  801. })
  802. .catch((error) => {
  803. this.$message.error("导出数据失败,请联系管理员");
  804. load.endLoading();
  805. });
  806. })
  807. .catch(() => {});
  808. },
  809. checkPhone(val) {
  810. var regu = /^1\d{10}$/;
  811. var re = new RegExp(regu);
  812. if (re.test(val)) {
  813. getStudentInfoByPhone({ mobile: this.studentForm.phone }).then(
  814. (res) => {
  815. if (res.code == 200) {
  816. if (res.data) {
  817. this.studentForm = {
  818. name: res.data.name,
  819. sex: res.data.gender,
  820. parseName: res.data.parentsName,
  821. // sound: parseInt(res.data.subjectIdList),
  822. phone: val,
  823. date: res.data.birthdate,
  824. };
  825. }
  826. }
  827. }
  828. );
  829. }
  830. },
  831. submitAddStudent() {
  832. const studentForm = this.studentForm;
  833. // 效验 然后组数据提交
  834. this.$refs["studentForm"].validate((item) => {
  835. if (item) {
  836. let obj = {
  837. phone: studentForm.phone,
  838. username: studentForm.name,
  839. gender: studentForm.sex,
  840. realName: studentForm.parseName,
  841. birthdate: studentForm.date,
  842. organId: studentForm.organId,
  843. serviceTag: studentForm.serviceTag,
  844. operatingTag: studentForm.operatingTag,
  845. teacherId: studentForm.teacherId,
  846. isNewUser: studentForm.isNewUser,
  847. subjectIdList: studentForm.subjectIdList,
  848. carePackage: studentForm.carePackage,
  849. comeOnPackage: studentForm.comeOnPackage
  850. };
  851. registerStudent(obj).then((res) => {
  852. if (res.code == 200) {
  853. this.$message.success("添加成功");
  854. this.studentVisible = false;
  855. this.getList();
  856. }
  857. });
  858. }
  859. });
  860. },
  861. // 修改学生信息
  862. resetStudentSubmie() {
  863. const studentForm = this.studentForm;
  864. this.$refs["studentForm"].validate((item) => {
  865. if (item) {
  866. let obj = {
  867. phone: studentForm.phone,
  868. username: studentForm.name,
  869. gender: studentForm.sex,
  870. realName: studentForm.parseName,
  871. birthdate: studentForm.date,
  872. organId: studentForm.organId,
  873. id: this.active.userId,
  874. serviceTag: studentForm.serviceTag,
  875. operatingTag: studentForm.operatingTag,
  876. teacherId: studentForm.teacherId,
  877. isNewUser: studentForm.isNewUser,
  878. subjectIdList: studentForm.subjectIdList,
  879. carePackage: studentForm.carePackage,
  880. comeOnPackage: studentForm.comeOnPackage
  881. };
  882. updateStudent(obj).then((res) => {
  883. if (res.code == 200) {
  884. this.$message.success("修改成功");
  885. this.studentVisible = false;
  886. this.getList();
  887. }
  888. });
  889. }
  890. });
  891. },
  892. async getSubjectList() {
  893. await subjectListTree({
  894. delFlag: "NO",
  895. tenantId: 1,
  896. rows: 9999,
  897. }).then((res) => {
  898. let result = res.data;
  899. if (res.code == 200) {
  900. let tempArray = [];
  901. result.rows.forEach((item, index) => {
  902. let subject = [];
  903. item.subjects.forEach((s) => {
  904. subject.push({
  905. value: s.id,
  906. label: s.name,
  907. });
  908. });
  909. tempArray[index] = {
  910. label: item.name,
  911. options: subject,
  912. };
  913. });
  914. this.subjectList = tempArray;
  915. }
  916. });
  917. },
  918. async addStudent() {
  919. await this.getSubjectList();
  920. this.isNew = true;
  921. this.studentVisible = true;
  922. this.maskName = "新增学员";
  923. },
  924. async resetStudent(row) {
  925. let organId = row.organId;
  926. await this.getSubjectList();
  927. await this.changeStudentOrgan(row.organId);
  928. this.isNew = false;
  929. this.active = row;
  930. this.studentVisible = true;
  931. this.maskName = "修改学员";
  932. this.$nextTick(() => {
  933. this.studentForm = {
  934. phone: row.parentsPhone || null,
  935. name: row.username || null,
  936. sex: row.gender,
  937. parseName: row.realName || null,
  938. date: row.birthdate || null,
  939. organId: row.organId || null,
  940. serviceTag: row.serviceTag,
  941. operatingTag: row.operatingTag,
  942. teacherId: row.teacherId || null,
  943. isNewUser: row.isNewUser,
  944. subjectIdList: Number(row.subjectIdList) || null,
  945. carePackage: row.carePackage,
  946. comeOnPackage: row.comeOnPackage
  947. };
  948. this.studentUpdatePackage = {
  949. carePackage: row.carePackage,
  950. comeOnPackage: row.comeOnPackage
  951. }
  952. });
  953. },
  954. onMaskClose(formName) {
  955. this.$refs[formName].resetFields();
  956. },
  957. resetPassWrod(row) {
  958. this.activatedRow = row;
  959. this.passwrodForm.phone = row.parentsPhone;
  960. this.passwrodVisiable = true;
  961. },
  962. closePassWord() {
  963. this.activatedRow = null;
  964. this.passwrodForm = {
  965. phone: "",
  966. password: "",
  967. password2: "",
  968. };
  969. this.$refs["passwrodForm"].resetFields();
  970. this.passwrodVisiable = false;
  971. },
  972. submitResetPassWord() {
  973. if (this.passwrodForm.password !== this.passwrodForm.password2) {
  974. this.$message.error("两次密码必须相同");
  975. return;
  976. }
  977. this.$refs["passwrodForm"].validate((res) => {
  978. if (res) {
  979. // 发请求
  980. resetPassword2({
  981. mobile: this.passwrodForm.phone,
  982. newPassword: this.passwrodForm.password,
  983. userId: this.activatedRow.userId,
  984. }).then((res) => {
  985. if (res.code == 200) {
  986. // 修改成功
  987. this.$message.success("修改成功");
  988. this.closePassWord();
  989. }
  990. });
  991. }
  992. });
  993. },
  994. async changeStudentOrgan(val) {
  995. this.studentForm.teacherId = null;
  996. await getTeacher({ organId: val }).then((res) => {
  997. if (res.code == 200) {
  998. this.maskTeacherList = res.data;
  999. }
  1000. });
  1001. },
  1002. lookContracts(row) {
  1003. getLatest({ userId: row.userId }).then((res) => {
  1004. if (res.code == 200) {
  1005. window.location.href = res.data.url
  1006. // window.open(res.data.url);
  1007. }
  1008. });
  1009. },
  1010. },
  1011. };
  1012. </script>
  1013. <style lang="scss" scoped>
  1014. .newBand {
  1015. display: inline-block;
  1016. margin-right: 10px;
  1017. }
  1018. .right-code {
  1019. // width: 50%;
  1020. // float: left;
  1021. .title {
  1022. font-size: 18px;
  1023. text-align: center;
  1024. padding-bottom: 8px;
  1025. }
  1026. }
  1027. /deep/.studentInfo {
  1028. .multiple.el-select {
  1029. width: 185px !important;
  1030. }
  1031. }
  1032. </style>