studentList.vue 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408
  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="hasMember">
  68. <el-select
  69. class="multiple"
  70. v-model.trim="searchForm.hasMember"
  71. clearable
  72. placeholder="是否是会员"
  73. >
  74. <el-option label="是" value="1"></el-option>
  75. <el-option label="否" value="0"></el-option>
  76. <el-option label="未生效" value="2"></el-option>
  77. </el-select>
  78. </el-form-item>
  79. <el-form-item prop="isActive">
  80. <el-select
  81. class="multiple"
  82. v-model.trim="searchForm.isActive"
  83. clearable
  84. placeholder="是否激活"
  85. >
  86. <el-option label="是" value="true"></el-option>
  87. <el-option label="否" value="false"></el-option>
  88. </el-select>
  89. </el-form-item>
  90. <el-form-item prop="hasTeacher">
  91. <el-select
  92. class="multiple"
  93. v-model.trim="searchForm.hasTeacher"
  94. clearable
  95. placeholder="是否关联老师"
  96. >
  97. <el-option label="是" value="1"></el-option>
  98. <el-option label="否" value="0"></el-option>
  99. </el-select>
  100. </el-form-item>
  101. <el-form-item prop="operatingTag">
  102. <el-select
  103. class="multiple"
  104. v-model.trim="searchForm.operatingTag"
  105. clearable
  106. placeholder="是否运营"
  107. >
  108. <el-option label="是" :value="1"></el-option>
  109. <el-option label="否" :value="0"></el-option>
  110. </el-select>
  111. </el-form-item>
  112. <el-form-item prop="serviceTag">
  113. <el-select
  114. class="multiple"
  115. v-model.trim="searchForm.serviceTag"
  116. clearable
  117. placeholder="是否服务"
  118. >
  119. <el-option label="是" :value="1"></el-option>
  120. <el-option label="否" :value="0"></el-option>
  121. </el-select>
  122. </el-form-item>
  123. <el-form-item prop="carePackage">
  124. <el-select
  125. class="multiple"
  126. v-model.trim="searchForm.carePackage"
  127. clearable
  128. placeholder="关心包"
  129. >
  130. <el-option label="不可用" :value="0"></el-option>
  131. <el-option label="可用" :value="1"></el-option>
  132. <el-option label="已使用" :value="2"></el-option>
  133. </el-select>
  134. </el-form-item>
  135. <el-form-item prop="comeOnPackage">
  136. <el-select
  137. class="multiple"
  138. v-model.trim="searchForm.comeOnPackage"
  139. clearable
  140. placeholder="加油包"
  141. >
  142. <el-option label="不可用" :value="0"></el-option>
  143. <el-option label="可用" :value="1"></el-option>
  144. <el-option label="已使用" :value="2"></el-option>
  145. </el-select>
  146. </el-form-item>
  147. <el-form-item prop="isNewUser">
  148. <el-select
  149. class="multiple"
  150. v-model.trim="searchForm.isNewUser"
  151. clearable
  152. placeholder="是否是新用户"
  153. >
  154. <el-option label="是" :value="1"></el-option>
  155. <el-option label="否" :value="0"></el-option>
  156. </el-select>
  157. </el-form-item>
  158. <el-form-item prop="isRecord">
  159. <el-select
  160. class="multiple"
  161. v-model.trim="searchForm.isRecord"
  162. clearable
  163. placeholder="是否使用云教练"
  164. >
  165. <el-option label="是" value="1"></el-option>
  166. <el-option label="否" value="0"></el-option>
  167. </el-select>
  168. </el-form-item>
  169. <el-form-item>
  170. <el-button native-type="submit" type="danger">搜索</el-button>
  171. <el-button native-type="reset" type="primary">重置</el-button>
  172. <el-button
  173. type="primary"
  174. v-permission="'export/studentHasCourse'"
  175. @click="downLoadStudent"
  176. >导出名单</el-button
  177. >
  178. </el-form-item>
  179. </save-form>
  180. <!-- 列表 -->
  181. <div class="tableWrap">
  182. <el-table
  183. :data="tableList"
  184. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  185. >
  186. <el-table-column type="expand">
  187. <template slot-scope="props">
  188. <el-form label-position="left" class="demo-table-expand">
  189. <el-row>
  190. <el-col :span="6">
  191. <el-form-item label="所属学校">
  192. <div class="schoolWrap">
  193. <overflow-text
  194. width="100%"
  195. :text="props.row.cooperationOrganName"
  196. ></overflow-text>
  197. </div> </el-form-item
  198. ></el-col>
  199. <el-col :span="4">
  200. <el-form-item>
  201. <span slot="label"
  202. >是否激活
  203. <el-tooltip placement="top" popper-class="mTooltip">
  204. <div slot="content">学员是否设置密码</div>
  205. <i
  206. class="el-icon-question"
  207. style="font-size: 18px; color: #f56c6c"
  208. ></i> </el-tooltip
  209. ></span>
  210. <span>{{ props.row.isActive ? "是" : "否" }}</span>
  211. </el-form-item></el-col
  212. >
  213. <el-col :span="4">
  214. <el-form-item label="课程余额(元)">
  215. <span>{{ props.row.courseBalance | moneyFormat }}</span>
  216. </el-form-item></el-col
  217. >
  218. <el-col :span="4">
  219. <el-form-item label="网管课剩余课时">
  220. <span>{{ props.row.noStartPracticeCourseNum }}</span>
  221. </el-form-item></el-col
  222. >
  223. <el-col :span="4">
  224. <el-form-item label="关心包">
  225. <span>
  226. {{ props.row.carePackage | studentPackage }}
  227. </span>
  228. </el-form-item></el-col
  229. >
  230. </el-row>
  231. <el-row>
  232. <el-col :span="6">
  233. <el-form-item label="指导老师">
  234. <span>{{ props.row.teacherName }}</span>
  235. </el-form-item></el-col
  236. >
  237. <el-col :span="4">
  238. <el-form-item label="是否运营">
  239. <span>{{ props.row.operatingTag ? "是" : "否" }}</span>
  240. </el-form-item></el-col
  241. >
  242. <el-col :span="4">
  243. <el-form-item label="账户余额(元)">
  244. <span>{{ props.row.balance | moneyFormat }}</span>
  245. </el-form-item></el-col
  246. >
  247. <el-col :span="4">
  248. <el-form-item label="vip课剩余课时">
  249. <span>{{ props.row.noStartVipCourseNum }}</span>
  250. </el-form-item></el-col
  251. >
  252. <el-col :span="4">
  253. <el-form-item label="加油包">
  254. <span>{{
  255. props.row.comeOnPackage | studentPackage
  256. }}</span>
  257. </el-form-item></el-col
  258. >
  259. </el-row>
  260. </el-form>
  261. </template>
  262. </el-table-column>
  263. <el-table-column align="center" prop="organName" label="所属分部">
  264. <template slot-scope="scope">
  265. <copy-text>{{ scope.row.organName }}</copy-text>
  266. </template>
  267. </el-table-column>
  268. <el-table-column
  269. align="center"
  270. prop="userId"
  271. label="学员信息"
  272. width="140px"
  273. >
  274. <template slot-scope="scope">
  275. {{ scope.row.username }}
  276. ({{ scope.row.gender ? "男" : "女" }})<br />
  277. <copy-text>{{ scope.row.userId }}</copy-text>
  278. </template>
  279. </el-table-column>
  280. <!-- <el-table-column align="center" prop="username" label="学员姓名">
  281. <template slot-scope="scope"> </template>
  282. </el-table-column> -->
  283. <el-table-column
  284. align="center"
  285. prop="realName"
  286. label="家长信息"
  287. width="140px"
  288. >
  289. <template slot-scope="scope">
  290. {{ scope.row.realName }}
  291. <br />
  292. <copy-text>{{ scope.row.parentsPhone }}</copy-text>
  293. </template>
  294. </el-table-column>
  295. <el-table-column
  296. align="center"
  297. prop="subjectName"
  298. label="声部"
  299. ></el-table-column>
  300. <!-- <el-table-column
  301. align="center"
  302. prop="cooperationOrganName"
  303. label="所属学校"
  304. ></el-table-column> -->
  305. <!-- <el-table-column align="center" prop="teacherName" label="指导老师">
  306. <template slot-scope="scope">
  307. <copy-text>{{ scope.row.teacherName }}</copy-text>
  308. </template>
  309. </el-table-column> -->
  310. <!-- <el-table-column align="center" label="性别">
  311. <template slot-scope="scope"></template>
  312. </el-table-column> -->
  313. <!-- <el-table-column
  314. align="center"
  315. prop="leaveNum"
  316. label="本月请假次数"
  317. ></el-table-column> -->
  318. <!-- <el-table-column align="center">
  319. <template slot="header">
  320. <p style="position: relative">
  321. 是否激活
  322. <el-tooltip placement="top" popper-class="mTooltip">
  323. <div slot="content">学员是否设置密码</div>
  324. <i
  325. class="el-icon-question"
  326. style="font-size: 18px; color: #f56c6c"
  327. ></i>
  328. </el-tooltip>
  329. </p>
  330. </template>
  331. <template slot-scope="scope">{{
  332. scope.row.isActive ? "是" : "否"
  333. }}</template>
  334. </el-table-column> -->
  335. <el-table-column align="center" label="未上课时">
  336. <template slot-scope="scope">{{
  337. scope.row.hasCourse ? "有" : "无"
  338. }}</template>
  339. </el-table-column>
  340. <!-- <el-table-column align="center" label="预约网管课">
  341. <template slot-scope="scope">{{ scope.row.isMake ? '是' : '否' }}</template>
  342. </el-table-column> -->
  343. <!-- <el-table-column align="center" label="网管课剩余课时">
  344. <template slot-scope="scope">{{
  345. scope.row.noStartPracticeCourseNum
  346. }}</template>
  347. </el-table-column> -->
  348. <!-- <el-table-column align="center" label="vip课剩余课时">
  349. <template slot-scope="scope">{{
  350. scope.row.noStartVipCourseNum
  351. }}</template>
  352. </el-table-column> -->
  353. <!-- <el-table-column align="center" label="是否运营">
  354. <template slot-scope="scope">{{
  355. scope.row.operatingTag ? "是" : "否"
  356. }}</template>
  357. </el-table-column> -->
  358. <el-table-column align="center" label="是否服务">
  359. <template slot-scope="scope">{{
  360. scope.row.serviceTag ? "是" : "否"
  361. }}</template>
  362. </el-table-column>
  363. <el-table-column align="center" label="是否使用云教练">
  364. <template slot-scope="scope">{{
  365. scope.row.recordUserId > 0 ? "是" : "否"
  366. }}</template>
  367. </el-table-column>
  368. <el-table-column
  369. align="center"
  370. width="120px"
  371. prop="parentsPhone"
  372. label="会员截止日期(剩余天数)"
  373. >
  374. <template slot-scope="scope">
  375. <div v-if="scope.row.membershipEndTime">
  376. <div v-if="scope.row.membershipDay >= 0">
  377. {{ scope.row.membershipEndTime | dayjsFormat }}
  378. <p class="red">剩余{{ scope.row.membershipDay }}天</p>
  379. </div>
  380. <!-- 已过期 -->
  381. <div v-else>
  382. <!-- 有未生效 -->
  383. <div v-if="scope.row.hasNoStartCloudTeacher">
  384. <p>会员未生效</p>
  385. </div>
  386. <!-- 无未生效 -->
  387. <div v-else>
  388. {{ scope.row.membershipEndTime | dayjsFormat }}
  389. <p class="red" v-if="scope.row.membershipDay < 0">
  390. 已过期{{ Math.abs(scope.row.membershipDay) }}天
  391. </p>
  392. </div>
  393. </div>
  394. <!--
  395. <div></div>
  396. <p v-if="scope.row.hasNoStartCloudTeacher">
  397. {{ scope.row.membershipEndTime | dayjsFormat }}
  398. </p> -->
  399. </div>
  400. <div v-else class="red">
  401. <div v-if="scope.row.hasNoStartCloudTeacher">会员未生效</div>
  402. <div v-else>未购买会员</div>
  403. </div>
  404. </template>
  405. </el-table-column>
  406. <el-table-column
  407. label="会员试用结束日期(剩余天数)"
  408. align="center"
  409. width="120px;"
  410. >
  411. <template slot-scope="scope">
  412. <div>
  413. <p>
  414. {{ scope.row.experienceMembershipEndTime | dayjsFormat }}
  415. </p>
  416. <p
  417. class="red"
  418. v-if="
  419. scope.row.experienceMembershipEndTime &&
  420. scope.row.experienceMembershipDay >= 0
  421. "
  422. >
  423. 剩余{{ scope.row.experienceMembershipDay }}天
  424. </p>
  425. <p
  426. class="red"
  427. v-if="
  428. scope.row.membershipEndTime &&
  429. scope.row.experienceMembershipDay < 0
  430. "
  431. >
  432. 已过期{{ Math.abs(scope.row.experienceMembershipDay) }}天
  433. </p>
  434. </div>
  435. </template>
  436. </el-table-column>
  437. <el-table-column align="center" label="是否是新用户">
  438. <template slot="header">
  439. <p style="position: relative">
  440. 是否是新用户
  441. <el-tooltip placement="top" popper-class="mTooltip">
  442. <div slot="content">
  443. 没有有效的VIP课程或未参与2020年双十一活动的用户为新用户
  444. </div>
  445. <i
  446. class="el-icon-question"
  447. style="font-size: 18px; color: #f56c6c"
  448. ></i>
  449. </el-tooltip>
  450. </p>
  451. </template>
  452. <template slot-scope="scope">
  453. {{ scope.row.isNewUser ? "是" : "否" }}
  454. </template>
  455. </el-table-column>
  456. <!-- <el-table-column
  457. align="center"
  458. prop="courseBalance"
  459. label="课程余额(元)"
  460. >
  461. <template slot-scope="scope">
  462. <div>
  463. {{ scope.row.courseBalance | moneyFormat }}
  464. </div>
  465. </template>
  466. </el-table-column> -->
  467. <!-- <el-table-column align="center" prop="balance" label="账户余额(元)">
  468. <template slot-scope="scope">
  469. <div>
  470. {{ scope.row.balance | moneyFormat }}
  471. </div>
  472. </template>
  473. </el-table-column> -->
  474. <!-- <el-table-column align="center" prop="carePackage" label="关心包">
  475. <template slot-scope="scope">{{
  476. scope.row.carePackage | studentPackage
  477. }}</template>
  478. </el-table-column>
  479. <el-table-column align="center" prop="comeOnPackage" label="加油包">
  480. <template slot-scope="scope">{{
  481. scope.row.comeOnPackage | studentPackage
  482. }}</template>
  483. </el-table-column> -->
  484. <el-table-column align="center" width="180px" label="操作">
  485. <template slot-scope="scope">
  486. <router-link
  487. v-permission="'/studentDetail'"
  488. class="el-button--text"
  489. :to="{
  490. path: `/business/studentDetail`,
  491. query: { ...scope.row },
  492. }"
  493. >查看</router-link
  494. >
  495. <el-button
  496. type="text"
  497. style="padding-left: 10px"
  498. v-permission="'studentManage/studentUpdate'"
  499. @click="resetStudent(scope.row)"
  500. >修改</el-button
  501. >
  502. <!-- api-auth/user/updatePassword2 -->
  503. <el-button
  504. v-permission="'api-auth/user/updatePassword2'"
  505. @click="resetPassWrod(scope.row)"
  506. type="text"
  507. >修改密码</el-button
  508. >
  509. <el-button
  510. v-if="scope.row.isSignedContract"
  511. type="text"
  512. @click="lookContracts(scope.row)"
  513. v-permission="'sysUserContracts/getLatest'"
  514. >下载协议</el-button
  515. >
  516. </template>
  517. </el-table-column>
  518. </el-table>
  519. <pagination
  520. sync
  521. :total.sync="pageInfo.total"
  522. :page.sync="pageInfo.page"
  523. :limit.sync="pageInfo.limit"
  524. :page-sizes="pageInfo.page_size"
  525. @pagination="getList"
  526. />
  527. </div>
  528. </div>
  529. <el-dialog
  530. :title="maskName"
  531. width="700px"
  532. label-position="right"
  533. class="studentInfo"
  534. @close="onMaskClose('studentForm')"
  535. :close-on-click-modal="false"
  536. :visible.sync="studentVisible"
  537. >
  538. <el-form
  539. :model="studentForm"
  540. :inline="true"
  541. label-width="130px"
  542. label-position="right"
  543. ref="studentForm"
  544. :rules="studentRules"
  545. >
  546. <el-alert
  547. title="课程信息"
  548. type="info"
  549. :closable="false"
  550. style="margin-bottom: 15px"
  551. ></el-alert>
  552. <el-form-item label="学生姓名" prop="name">
  553. <el-input v-model.trim="studentForm.name"></el-input>
  554. </el-form-item>
  555. <el-form-item label="学生性别" prop="sex">
  556. <el-select
  557. class="multiple"
  558. filterable
  559. v-model.trim="studentForm.sex"
  560. clearable
  561. placeholder="请选择性别"
  562. >
  563. <el-option :value="1" label="男"></el-option>
  564. <el-option :value="0" label="女"></el-option>
  565. </el-select>
  566. </el-form-item>
  567. <el-form-item label="出生日期" prop="date">
  568. <el-date-picker
  569. v-model.trim="studentForm.date"
  570. style="width: 185px"
  571. value-format="yyyy-MM-dd"
  572. type="date"
  573. :picker-options="{
  574. firstDayOfWeek: 1,
  575. }"
  576. placeholder="选择日期"
  577. ></el-date-picker>
  578. </el-form-item>
  579. <el-form-item label="学生声部" prop="subjectIdList">
  580. <el-select
  581. v-model.trim="studentForm.subjectIdList"
  582. filterable
  583. clearable
  584. placeholder="学员声部"
  585. >
  586. <el-option-group
  587. v-for="group in subjectList"
  588. :key="group.label"
  589. :label="group.label"
  590. >
  591. <el-option
  592. v-for="item in group.options"
  593. :key="item.value"
  594. :label="item.label"
  595. :value="item.value"
  596. ></el-option>
  597. </el-option-group>
  598. </el-select>
  599. </el-form-item>
  600. <el-form-item label="家长姓名" prop="parseName">
  601. <el-input
  602. v-model.trim="studentForm.parseName"
  603. :disabled="!isNew"
  604. ></el-input>
  605. </el-form-item>
  606. <el-form-item
  607. label="联系电话"
  608. prop="phone"
  609. :rules="[
  610. { required: true, message: '请输入手机号' },
  611. {
  612. pattern: /^1\d{10}$/,
  613. message: '请输入正确的手机号',
  614. trigger: 'blur',
  615. },
  616. ]"
  617. >
  618. <!-- @blur="checkPhone(studentForm.phone)" -->
  619. <el-input :maxlength="11" v-model.trim="studentForm.phone"></el-input>
  620. </el-form-item>
  621. <el-form-item label="所属分部" prop="organId">
  622. <el-select
  623. class="multiple"
  624. v-model.trim="studentForm.organId"
  625. filterable
  626. clearable
  627. placeholder="请选择分部"
  628. @change="changeStudentOrgan"
  629. >
  630. <el-option
  631. v-for="(item, index) in selects.branchs"
  632. :key="index"
  633. :label="item.name"
  634. :value="item.id"
  635. ></el-option>
  636. </el-select>
  637. </el-form-item>
  638. <el-form-item prop="school" label="所属学校">
  639. <el-select
  640. v-model.trim="studentForm.school"
  641. filterable
  642. clearable
  643. :disabled="!studentForm.organId"
  644. class="multiple"
  645. >
  646. <el-option
  647. v-for="(item, index) in cooperationList"
  648. :key="index"
  649. :label="item.name"
  650. :value="item.id"
  651. ></el-option>
  652. </el-select>
  653. </el-form-item>
  654. <el-form-item label="指导老师" prop="teacherId">
  655. <el-select
  656. class="multiple"
  657. v-model.trim="studentForm.teacherId"
  658. clearable
  659. filterable
  660. >
  661. <el-option
  662. v-for="(item, index) in maskTeacherList"
  663. :label="item.realName"
  664. :value="item.id"
  665. :key="index"
  666. ></el-option>
  667. </el-select>
  668. </el-form-item>
  669. <el-alert
  670. title="课程信息"
  671. type="info"
  672. :closable="false"
  673. style="margin-bottom: 15px"
  674. ></el-alert>
  675. <el-form-item label="是否运营" prop="operatingTag">
  676. <el-select
  677. class="multiple"
  678. v-model.trim="studentForm.operatingTag"
  679. clearable
  680. >
  681. <el-option :value="1" label="是"></el-option>
  682. <el-option :value="0" label="否"></el-option>
  683. </el-select>
  684. </el-form-item>
  685. <el-form-item label="是否服务" prop="serviceTag">
  686. <el-select
  687. class="multiple"
  688. v-model.trim="studentForm.serviceTag"
  689. clearable
  690. >
  691. <el-option :value="1" label="是"></el-option>
  692. <el-option :value="0" label="否"></el-option>
  693. </el-select>
  694. </el-form-item>
  695. <!-- <el-form-item label="是否是新用户" prop="isNewUser">
  696. <template #label>
  697. <p style="position: relative; display: inline-block">
  698. 是否是新用户
  699. <el-tooltip placement="top" popper-class="mTooltip">
  700. <div slot="content">
  701. 没有有效的VIP课程或未参与2020年双十一活动的用户为新用户
  702. </div>
  703. <i
  704. class="el-icon-question"
  705. style="font-size: 18px; color: #f56c6c"
  706. ></i>
  707. </el-tooltip>
  708. </p>
  709. </template>
  710. <el-select
  711. class="multiple"
  712. v-model.trim="studentForm.isNewUser"
  713. clearable
  714. >
  715. <el-option :value="1" label="是"></el-option>
  716. <el-option :value="0" label="否"></el-option>
  717. </el-select>
  718. </el-form-item> -->
  719. <el-form-item label="关心包" prop="carePackage">
  720. <el-select
  721. class="multiple"
  722. v-model.trim="studentForm.carePackage"
  723. clearable
  724. :disabled="!isNew && studentUpdatePackage.carePackage == 2"
  725. placeholder="请选择关心包"
  726. >
  727. <el-option label="不可用" :value="0"></el-option>
  728. <el-option label="可用" :value="1"></el-option>
  729. <el-option disabled label="已使用" :value="2"></el-option>
  730. </el-select>
  731. </el-form-item>
  732. <el-form-item label="加油包" prop="comeOnPackage">
  733. <el-select
  734. class="multiple"
  735. v-model.trim="studentForm.comeOnPackage"
  736. clearable
  737. :disabled="!isNew && studentUpdatePackage.comeOnPackage == 2"
  738. placeholder="请选择加油包"
  739. >
  740. <el-option label="不可用" :value="0"></el-option>
  741. <el-option label="可用" :value="1"></el-option>
  742. <el-option disabled label="已使用" :value="2"></el-option>
  743. </el-select>
  744. </el-form-item>
  745. </el-form>
  746. <div slot="footer" class="dialog-footer">
  747. <el-button @click="studentVisible = false">取 消</el-button>
  748. <el-button type="primary" v-if="isNew" @click="submitAddStudent"
  749. >确 定</el-button
  750. >
  751. <el-button type="primary" v-if="!isNew" @click="resetStudentSubmie"
  752. >确 定</el-button
  753. >
  754. </div>
  755. </el-dialog>
  756. <!-- 学员激活列表 -->
  757. <qr-code v-model="qrcodeStatus" title="学员激活列表" :codeUrl="qrcodeUrl" />
  758. <el-dialog
  759. title="修改密码"
  760. :visible.sync="passwrodVisiable"
  761. :before-close="closePassWord"
  762. width="400px"
  763. >
  764. <el-form :model="passwrodForm" ref="passwrodForm" :inline="true">
  765. <el-form-item
  766. label="手机号"
  767. prop="phone"
  768. label-width="120px"
  769. :rules="[
  770. { required: true, message: '手机号不能为空', trigger: 'blur' },
  771. {
  772. pattern: /^1\d{10}$/,
  773. message: '请输入正确的手机号',
  774. trigger: 'blur',
  775. },
  776. ]"
  777. >
  778. <copy-text>{{ passwrodForm.phone }}</copy-text>
  779. </el-form-item>
  780. <el-form-item
  781. label="输入密码"
  782. prop="password"
  783. label-width="120px"
  784. :rules="[
  785. { required: true, message: '密码不能为空', trigger: 'blur' },
  786. {
  787. pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/,
  788. message: '密码为6-20位数字和字母组合',
  789. trigger: 'blur',
  790. },
  791. ]"
  792. >
  793. <el-input v-model.trim="passwrodForm.password"></el-input>
  794. </el-form-item>
  795. <el-form-item
  796. label="再次输入"
  797. prop="password2"
  798. label-width="120px"
  799. :rules="[
  800. { required: true, message: '密码不能为空', trigger: 'blur' },
  801. {
  802. pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/,
  803. message: '密码为6-20位数字和字母组合',
  804. trigger: 'blur',
  805. },
  806. ]"
  807. >
  808. <el-input v-model.trim="passwrodForm.password2"></el-input>
  809. </el-form-item>
  810. </el-form>
  811. <span slot="footer" class="dialog-footer">
  812. <el-button @click="passwrodVisiable = false">取 消</el-button>
  813. <el-button type="primary" @click="submitResetPassWord">确 定</el-button>
  814. </span>
  815. </el-dialog>
  816. <el-dialog title="协议下载" :visible.sync="protocolVisible" width="650px">
  817. <div v-if="protocolVisible">
  818. <!-- <el-alert
  819. title="点击下载"
  820. :closable="false"
  821. type="info">
  822. </el-alert>
  823. <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)">
  824. 产品与服务协议{{ item.version == 2 ? "(含课程)" : "(含系统)" }}
  825. </p> -->
  826. <el-table
  827. style="width: 100%"
  828. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  829. :data="protocolVersions"
  830. >
  831. <el-table-column align="center" prop="studentId" label="协议名称">
  832. <template slot-scope="scope">
  833. <!-- {{ formatProtocol(scope.row.version) }} -->
  834. <span
  835. v-html="`产品与服务协议${formatProtocol(scope.row.version)}`"
  836. ></span>
  837. </template>
  838. </el-table-column>
  839. <el-table-column align="center" label="签署时间" prop="createTime">
  840. </el-table-column>
  841. <el-table-column align="center" width="150px" label="操作">
  842. <template slot-scope="scope">
  843. <div>
  844. <el-button type="text" @click="onDownloadProtocol(scope.row)"
  845. >下载</el-button
  846. >
  847. </div>
  848. </template>
  849. </el-table-column>
  850. </el-table>
  851. </div>
  852. <span slot="footer" class="dialog-footer">
  853. <el-button @click="protocolVisible = false">取 消</el-button>
  854. </span>
  855. </el-dialog>
  856. </div>
  857. </template>
  858. <script>
  859. import pagination from "@/components/Pagination/index";
  860. import {
  861. queryStudentList,
  862. getStudentInfoByPhone,
  863. registerStudent,
  864. updateStudent,
  865. studentHasCourse,
  866. getLatest,
  867. } from "@/api/studentManager";
  868. import { queryByOrganId } from "@/api/systemManage";
  869. import qrCode from "@/components/QrCode/index";
  870. import cleanDeep from "clean-deep";
  871. import { vaildStudentUrl } from "@/utils/validate";
  872. import { getEmployeeOrgan, resetPassword2, getTeacher } from "@/api/buildTeam";
  873. import { subjectListTree } from "@/api/specialSetting";
  874. import axios from "axios";
  875. import qs from "qs";
  876. import { packageStatus } from "@/constant/index";
  877. import { getToken } from "@/utils/auth";
  878. import load from "@/utils/loading";
  879. import { permission } from "@/utils/directivePage";
  880. export default {
  881. name: "studentManagerList",
  882. components: { pagination, qrCode },
  883. data() {
  884. return {
  885. studentVisible: false,
  886. searchForm: {
  887. organId: null,
  888. search: null,
  889. studentName: null,
  890. isActive: null,
  891. hasCourse: null,
  892. // isMake: null,
  893. hasPracticeCourse: null,
  894. operatingTag: null,
  895. serviceTag: null,
  896. teacherId: null,
  897. carePackage: null,
  898. comeOnPackage: null,
  899. isNewUser: null,
  900. hasTeacher: null,
  901. isRecord: null,
  902. },
  903. searchList: [],
  904. tableList: [],
  905. organList: [],
  906. teacherList: [],
  907. maskTeacherList: [],
  908. subjectList: [], // 声部列表
  909. pageInfo: {
  910. // 分页规则
  911. limit: 10, // 限制显示条数
  912. page: 1, // 当前页
  913. total: 0, // 总条数
  914. page_size: [10, 20, 40, 50], // 选择限制显示条数
  915. },
  916. studentForm: {
  917. phone: "",
  918. organId: "",
  919. name: "",
  920. sex: "",
  921. parseName: "",
  922. date: "",
  923. serviceTag: null,
  924. operatingTag: null,
  925. teacherId: null,
  926. subjectIdList: null,
  927. isNewUser: 1,
  928. carePackage: 0,
  929. comeOnPackage: 0,
  930. school: null,
  931. },
  932. studentUpdatePackage: {
  933. carePackage: 0,
  934. comeOnPackage: 0,
  935. },
  936. studentRules: {
  937. name: [{ required: true, message: "请输入学生姓名" }],
  938. sex: [{ required: true, message: "请选择学生性别" }],
  939. date: [{ required: true, message: "请选择出生日期" }],
  940. organId: [{ required: true, message: "请选择分部" }],
  941. subjectIdList: [{ required: true, message: "请选择声部" }],
  942. serviceTag: [{ required: true, message: "请选择是否参与服务" }],
  943. isNewUser: [{ required: true, message: "请选择是否是新用户" }],
  944. operatingTag: [{ required: true, message: "请选择是否参与运营" }],
  945. teacherId: [{ required: true, message: "请选择指导老师" }],
  946. },
  947. isNew: false,
  948. active: null,
  949. maskName: "新增学员",
  950. qrcodeStatus: false,
  951. qrcodeUrl: null,
  952. activeRow: null,
  953. passwrodVisiable: false,
  954. passwrodForm: {
  955. phone: "",
  956. password: "",
  957. password2: "",
  958. },
  959. activatedRow: null,
  960. protocolVisible: false,
  961. protocolVersions: [],
  962. cooperationList: [],
  963. };
  964. },
  965. mounted() {
  966. if (this.$route.params.search) {
  967. this.searchForm.search = this.$route.params.search;
  968. }
  969. if (this.$route.params.teacherId) {
  970. this.searchForm.teacherId = this.$route.params.teacherId;
  971. }
  972. if (this.$route.params.hasTeacher) {
  973. this.searchForm.hasTeacher = this.$route.params.hasTeacher;
  974. }
  975. if (this.$route.params.organId) {
  976. this.searchForm.organId = this.$route.params.organId;
  977. }
  978. this.$store.dispatch("setBranchs");
  979. this.$store.dispatch("setTeachers");
  980. this.getList();
  981. },
  982. methods: {
  983. onSearch() {
  984. this.pageInfo.page = 1;
  985. this.getList();
  986. },
  987. onCreateQRCode() {
  988. // 生成报名二维码
  989. this.qrcodeStatus = true;
  990. this.qrcodeUrl = vaildStudentUrl() + `/#/queryStudentPer`;
  991. },
  992. formatProtocol(version) {
  993. let str = "(含课程)";
  994. if (version == 3) {
  995. str = "(含系统)";
  996. } else if (version == 4) {
  997. str = "(含云教练)";
  998. } else if (version == 5) {
  999. str = "(含云教练<sup>+</sup>)";
  1000. }
  1001. return str;
  1002. },
  1003. getList() {
  1004. let params = this.searchForm;
  1005. params.rows = this.pageInfo.limit;
  1006. params.page = this.pageInfo.page;
  1007. params.organId ? params.organId : (params.organId = null);
  1008. queryStudentList(params).then((res) => {
  1009. if (res.code == 200) {
  1010. this.tableList = res.data.rows;
  1011. this.pageInfo.total = res.data.total;
  1012. }
  1013. });
  1014. },
  1015. onReSet() {
  1016. this.searchForm = {
  1017. organId: null,
  1018. search: null,
  1019. studentName: null,
  1020. isActive: null,
  1021. hasCourse: null,
  1022. // isMake: null,
  1023. hasPracticeCourse: null,
  1024. operatingTag: null,
  1025. serviceTag: null,
  1026. teacherId: null,
  1027. };
  1028. this.getList();
  1029. },
  1030. downLoadStudent() {
  1031. let url = "/api-web/export/studentHasCourse";
  1032. let searchForm = this.searchForm;
  1033. /**
  1034. * organId: null,
  1035. search: null,
  1036. studentName: null,
  1037. isActive: null,
  1038. hasCourse: null,
  1039. // isMake: null,
  1040. hasPracticeCourse: null,
  1041. operatingTag: null,
  1042. serviceTag: null,
  1043. teacherId: null,
  1044. carePackage: null,
  1045. comeOnPackage: null,
  1046. isNewUser: null,
  1047. hasTeacher: null,
  1048. isRecord: null,
  1049. */
  1050. let data = {
  1051. organId: searchForm.organId+'' ? searchForm.organId : null,
  1052. search: searchForm.search+'' ? searchForm.search : null,
  1053. isActive: searchForm.isActive+'' ? searchForm.isActive : null,
  1054. hasCourse: searchForm.hasCourse == "" ? null : searchForm.hasCourse,
  1055. // isMake: searchForm.isMake ? searchForm.isMake : null,
  1056. hasPracticeCourse: searchForm.hasPracticeCourse+''
  1057. ? searchForm.hasPracticeCourse
  1058. : null,
  1059. operatingTag: searchForm.operatingTag+'' ? searchForm.operatingTag : null,
  1060. serviceTag: searchForm.serviceTag+'' ? searchForm.serviceTag : null,
  1061. teacherId: searchForm.teacherId+'' ? searchForm.teacherId : null,
  1062. carePackage: searchForm.carePackage+'' ? searchForm.carePackage : null,
  1063. comeOnPackage: searchForm.comeOnPackage+'' ? searchForm.comeOnPackage : null,
  1064. isNewUser: searchForm.isNewUser+'' ? searchForm.isNewUser : null,
  1065. hasTeacher: searchForm.hasTeacher+'' ? searchForm.hasTeacher : null,
  1066. isRecord: searchForm.isRecord+'' ? searchForm.isRecord : null,
  1067. };
  1068. const options = {
  1069. method: "POST",
  1070. headers: {
  1071. Authorization: getToken(),
  1072. },
  1073. url,
  1074. data: qs.stringify(data),
  1075. responseType: "blob",
  1076. };
  1077. this.$confirm("确定导出学员名单?", "提示", {
  1078. confirmButtonText: "确定",
  1079. cancelButtonText: "取消",
  1080. type: "warning",
  1081. })
  1082. .then(() => {
  1083. load.startLoading();
  1084. axios(options)
  1085. .then((res) => {
  1086. let blob = new Blob([res.data], {
  1087. // type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8',
  1088. type: "application/vnd.ms-excel;charset=utf-8",
  1089. // word文档为application/msword,pdf文档为application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
  1090. });
  1091. let text = new Response(blob).text();
  1092. text.then((res) => {
  1093. // 判断是否报错
  1094. if (res.indexOf("code") != -1) {
  1095. let json = JSON.parse(res);
  1096. this.$message.error(json.msg);
  1097. } else {
  1098. let objectUrl = URL.createObjectURL(blob);
  1099. let link = document.createElement("a");
  1100. let nowTime = new Date();
  1101. let ymd =
  1102. nowTime.getFullYear() +
  1103. (nowTime.getMonth() + 1) +
  1104. nowTime.getDate();
  1105. let fname = `导出学员名单` + ymd + ".xls"; //下载文件的名字
  1106. link.href = objectUrl;
  1107. link.setAttribute("download", fname);
  1108. document.body.appendChild(link);
  1109. link.click();
  1110. }
  1111. });
  1112. load.endLoading();
  1113. })
  1114. .catch((error) => {
  1115. this.$message.error("导出数据失败,请联系管理员");
  1116. load.endLoading();
  1117. });
  1118. })
  1119. .catch(() => {});
  1120. },
  1121. checkPhone(val) {
  1122. var regu = /^1\d{10}$/;
  1123. var re = new RegExp(regu);
  1124. if (re.test(val)) {
  1125. getStudentInfoByPhone({ mobile: this.studentForm.phone }).then(
  1126. (res) => {
  1127. if (res.code == 200) {
  1128. if (res.data) {
  1129. this.studentForm = {
  1130. name: res.data.name,
  1131. sex: res.data.gender,
  1132. parseName: res.data.parentsName,
  1133. // sound: parseInt(res.data.subjectIdList),
  1134. phone: val,
  1135. date: res.data.birthdate,
  1136. };
  1137. }
  1138. }
  1139. }
  1140. );
  1141. }
  1142. },
  1143. submitAddStudent() {
  1144. const studentForm = this.studentForm;
  1145. // 效验 然后组数据提交
  1146. this.$refs["studentForm"].validate((item) => {
  1147. if (item) {
  1148. let obj = {
  1149. phone: studentForm.phone,
  1150. username: studentForm.name,
  1151. gender: studentForm.sex,
  1152. realName: studentForm.parseName,
  1153. birthdate: studentForm.date,
  1154. organId: studentForm.organId,
  1155. serviceTag: studentForm.serviceTag,
  1156. operatingTag: studentForm.operatingTag,
  1157. teacherId: studentForm.teacherId,
  1158. isNewUser: studentForm.isNewUser,
  1159. subjectIdList: studentForm.subjectIdList,
  1160. carePackage: studentForm.carePackage,
  1161. comeOnPackage: studentForm.comeOnPackage,
  1162. cooperationOrganId: studentForm.school,
  1163. };
  1164. registerStudent(obj).then((res) => {
  1165. if (res.code == 200) {
  1166. this.$message.success("添加成功");
  1167. this.studentVisible = false;
  1168. this.getList();
  1169. }
  1170. });
  1171. }
  1172. });
  1173. },
  1174. // 修改学生信息
  1175. resetStudentSubmie() {
  1176. const studentForm = this.studentForm;
  1177. this.$refs["studentForm"].validate((item) => {
  1178. if (item) {
  1179. let obj = {
  1180. phone: studentForm.phone,
  1181. username: studentForm.name,
  1182. gender: studentForm.sex,
  1183. realName: studentForm.parseName,
  1184. birthdate: studentForm.date,
  1185. organId: studentForm.organId,
  1186. id: this.active.userId,
  1187. serviceTag: studentForm.serviceTag,
  1188. operatingTag: studentForm.operatingTag,
  1189. teacherId: studentForm.teacherId,
  1190. isNewUser: studentForm.isNewUser,
  1191. subjectIdList: studentForm.subjectIdList,
  1192. carePackage: studentForm.carePackage,
  1193. comeOnPackage: studentForm.comeOnPackage,
  1194. cooperationOrganId: studentForm.school,
  1195. };
  1196. updateStudent(obj).then((res) => {
  1197. if (res.code == 200) {
  1198. this.$message.success("修改成功");
  1199. this.studentVisible = false;
  1200. this.getList();
  1201. }
  1202. });
  1203. }
  1204. });
  1205. },
  1206. async getSubjectList() {
  1207. await subjectListTree({
  1208. delFlag: "NO",
  1209. tenantId: 1,
  1210. rows: 9999,
  1211. }).then((res) => {
  1212. let result = res.data;
  1213. if (res.code == 200) {
  1214. let tempArray = [];
  1215. result.rows.forEach((item, index) => {
  1216. let subject = [];
  1217. item.subjects.forEach((s) => {
  1218. subject.push({
  1219. value: s.id,
  1220. label: s.name,
  1221. });
  1222. });
  1223. tempArray[index] = {
  1224. label: item.name,
  1225. options: subject,
  1226. };
  1227. });
  1228. this.subjectList = tempArray;
  1229. }
  1230. });
  1231. },
  1232. async addStudent() {
  1233. await this.getSubjectList();
  1234. this.isNew = true;
  1235. this.studentVisible = true;
  1236. this.maskName = "新增学员";
  1237. },
  1238. async resetStudent(row) {
  1239. let organId = row.organId;
  1240. await this.getSubjectList();
  1241. await this.changeStudentOrgan(row.organId);
  1242. this.isNew = false;
  1243. this.active = row;
  1244. this.studentVisible = true;
  1245. this.maskName = "修改学员";
  1246. this.$nextTick(() => {
  1247. this.studentForm = {
  1248. phone: row.parentsPhone || null,
  1249. name: row.username || null,
  1250. sex: row.gender,
  1251. parseName: row.realName || null,
  1252. date: row.birthdate || null,
  1253. organId: row.organId || null,
  1254. serviceTag: row.serviceTag,
  1255. operatingTag: row.operatingTag,
  1256. teacherId: row.teacherId || null,
  1257. isNewUser: row.isNewUser,
  1258. subjectIdList: Number(row.subjectIdList) || null,
  1259. carePackage: row.carePackage,
  1260. comeOnPackage: row.comeOnPackage,
  1261. school: row.cooperationOrganId,
  1262. };
  1263. this.studentUpdatePackage = {
  1264. carePackage: row.carePackage,
  1265. comeOnPackage: row.comeOnPackage,
  1266. };
  1267. });
  1268. },
  1269. onMaskClose(formName) {
  1270. this.$refs[formName].resetFields();
  1271. },
  1272. resetPassWrod(row) {
  1273. this.activatedRow = row;
  1274. this.passwrodForm.phone = row.parentsPhone;
  1275. this.passwrodVisiable = true;
  1276. },
  1277. closePassWord() {
  1278. this.activatedRow = null;
  1279. this.passwrodForm = {
  1280. phone: "",
  1281. password: "",
  1282. password2: "",
  1283. };
  1284. this.$refs["passwrodForm"].resetFields();
  1285. this.passwrodVisiable = false;
  1286. },
  1287. submitResetPassWord() {
  1288. if (this.passwrodForm.password !== this.passwrodForm.password2) {
  1289. this.$message.error("两次密码必须相同");
  1290. return;
  1291. }
  1292. this.$refs["passwrodForm"].validate((res) => {
  1293. if (res) {
  1294. // 发请求
  1295. resetPassword2({
  1296. mobile: this.passwrodForm.phone,
  1297. newPassword: this.passwrodForm.password,
  1298. userId: this.activatedRow.userId,
  1299. }).then((res) => {
  1300. if (res.code == 200) {
  1301. // 修改成功
  1302. this.$message.success("修改成功");
  1303. this.closePassWord();
  1304. }
  1305. });
  1306. }
  1307. });
  1308. },
  1309. async changeStudentOrgan(val) {
  1310. this.studentForm.teacherId = null;
  1311. this.studentForm.school = null;
  1312. if (val) {
  1313. await getTeacher({ organId: val }).then((res) => {
  1314. if (res.code == 200) {
  1315. this.maskTeacherList = res.data;
  1316. }
  1317. });
  1318. queryByOrganId({ organId: val }).then((res) => {
  1319. if (res.code == 200) {
  1320. this.cooperationList = res.data;
  1321. }
  1322. });
  1323. } else {
  1324. this.maskTeacherList = [];
  1325. }
  1326. },
  1327. async lookContracts(row) {
  1328. await getLatest({ userId: row.userId }).then((res) => {
  1329. if (res.code == 200) {
  1330. if (res.data) {
  1331. this.protocolVersions = res.data;
  1332. this.protocolVisible = true;
  1333. }
  1334. }
  1335. });
  1336. },
  1337. onDownloadProtocol(item) {
  1338. window.location.href = item.url;
  1339. },
  1340. checkDate(dateStr) {
  1341. let dayjs = this.$helpers.dayjs;
  1342. let nowDate = new Date().getTime();
  1343. return nowDate - dayjs(dateStr).valueOf() < 0;
  1344. },
  1345. },
  1346. };
  1347. </script>
  1348. <style lang="scss" scoped>
  1349. .newBand {
  1350. display: inline-block;
  1351. margin-right: 10px;
  1352. }
  1353. .right-code {
  1354. // width: 50%;
  1355. // float: left;
  1356. .title {
  1357. font-size: 18px;
  1358. text-align: center;
  1359. padding-bottom: 8px;
  1360. }
  1361. }
  1362. /deep/.studentInfo {
  1363. .multiple.el-select {
  1364. width: 185px !important;
  1365. }
  1366. }
  1367. .red {
  1368. color: red;
  1369. }
  1370. .demo-table-expand {
  1371. font-size: 0;
  1372. }
  1373. .demo-table-expand label {
  1374. width: 150px;
  1375. color: #99a9bf;
  1376. }
  1377. .demo-table-expand .el-form-item {
  1378. margin-right: 0;
  1379. margin-bottom: 0;
  1380. overflow: hidden;
  1381. text-overflow: ellipsis;
  1382. white-space: nowrap;
  1383. padding-right: 10px;
  1384. }
  1385. /deep/.el-table__expanded-cell[class*="cell"] {
  1386. padding: 20px 0 20px 110px;
  1387. }
  1388. .schoolWrap {
  1389. // width: calc(100% - 75px) !important;
  1390. overflow: hidden;
  1391. text-overflow: ellipsis;
  1392. white-space: nowrap;
  1393. }
  1394. </style>