studentList.vue 37 KB

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