studentList.vue 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304
  1. <template>
  2. <div class='stu-container'>
  3. <!-- 头部展示 -->
  4. <div class="headWrap">
  5. <div class="left">
  6. <div class="headItem">
  7. <p>在读人数:<span>{{studentListInfo.studying}}</span></p>
  8. </div>
  9. <div class="headItem">
  10. <p>退团人数:<span>{{studentListInfo.quit}}</span></p>
  11. </div>
  12. <div class="headItem">
  13. <p>新增人数:<span>{{studentListInfo.add}}</span></p>
  14. </div>
  15. </div>
  16. <div class="right">
  17. <div class="newStudent"
  18. v-permission="'studentRegistration/insertStudent'"
  19. style="margin-bottom:10px;"
  20. @click="addStudentVisible = true">新增学员</div>
  21. <div class="newStudent"
  22. style="margin-bottom:10px;"
  23. @click="onCreateQRCode">报名连接</div>
  24. <div class="newStudent"
  25. @click='gotoSignin'>点名总览</div>
  26. </div>
  27. </div>
  28. <!-- 搜索类型 -->
  29. <el-form :inline="true"
  30. class="searchForm"
  31. v-model="searchForm">
  32. <el-form-item>
  33. <el-input v-model="searchForm.search"
  34. placeholder="学生姓名或电话"
  35. @keyup.enter.native='search'></el-input>
  36. </el-form-item>
  37. <el-form-item>
  38. <el-select v-model="searchForm.studentStatus"
  39. clearable
  40. filterable
  41. placeholder="学员状态">
  42. <el-option label="在读"
  43. value="NORMAL"></el-option>
  44. <el-option label="请假"
  45. value="LEAVE"></el-option>
  46. <el-option label="退团"
  47. value="QUIT"></el-option>
  48. </el-select>
  49. </el-form-item>
  50. <el-form-item>
  51. <el-select v-model="searchForm.classGroupId"
  52. clearable
  53. filterable
  54. placeholder="请选择班级">
  55. <el-option v-for='(item,index) in classList'
  56. :key='index'
  57. :value="item.id"
  58. :label="item.name"></el-option>
  59. </el-select>
  60. </el-form-item>
  61. <el-form-item>
  62. <el-select v-model="searchForm.major"
  63. clearable
  64. filterable
  65. placeholder="所选专业">
  66. <el-option v-for='(item,index) in soundList'
  67. :key='index'
  68. :value="item.id"
  69. :label="item.name"></el-option>
  70. </el-select>
  71. </el-form-item>
  72. <el-form-item>
  73. <el-select v-model="searchForm.isPay"
  74. clearable
  75. filterable
  76. placeholder="报名缴费">
  77. <el-option label="完成缴费"
  78. value="PAID_COMPLETED"></el-option>
  79. <el-option label="未缴费"
  80. value="NON_PAYMENT"></el-option>
  81. <el-option label="缴费中"
  82. value="PROCESSING"></el-option>
  83. </el-select>
  84. </el-form-item>
  85. <el-form-item>
  86. <el-select v-model="searchForm.isActive"
  87. clearable
  88. filterable
  89. placeholder="是否激活">
  90. <el-option label="是"
  91. value="1"></el-option>
  92. <el-option label="否"
  93. value="0"></el-option>
  94. </el-select>
  95. </el-form-item>
  96. <!-- <el-form-item>
  97. <el-select v-model="searchForm.school"
  98. placeholder="所在学校">
  99. <el-option label="item.text"
  100. value="1"></el-option>
  101. </el-select>
  102. </el-form-item> -->
  103. <el-form-item>
  104. <div class='searchBtn'
  105. @click='search'>搜索</div>
  106. </el-form-item>
  107. <el-form-item>
  108. <div class='searchBtn export'
  109. v-permission="'export/musicGroupStudent'"
  110. @click='onMusicGroupExport'>导出</div>
  111. </el-form-item>
  112. </el-form>
  113. <!-- 列表 -->
  114. <div class="tableWrap">
  115. <el-table :data='tableList'
  116. :header-cell-style="{background:'#EDEEF0',color:'#444'}">
  117. <el-table-column label="学员编号"
  118. width="120px;"
  119. prop="userId">
  120. </el-table-column>
  121. <el-table-column label="学员姓名"
  122. width="120px;"
  123. prop="realName">
  124. </el-table-column>
  125. <el-table-column align='center'
  126. prop="gender"
  127. width="50px;"
  128. label="性别">
  129. <template slot-scope="scope">
  130. <div>
  131. {{scope.row.gender| sex }}
  132. </div>
  133. </template>
  134. </el-table-column>
  135. <el-table-column align='center'
  136. prop="phone"
  137. label="联系电话">
  138. </el-table-column>
  139. <!-- <el-table-column align='center'
  140. prop=""
  141. label="所在学校">
  142. </el-table-column> -->
  143. <el-table-column align='center'
  144. label="年级班级">
  145. <template slot-scope="scope">
  146. <div>
  147. {{scope.row.currentGrade+scope.row.currentClass}}
  148. </div>
  149. </template>
  150. </el-table-column>
  151. <el-table-column align='center'
  152. label="专业"
  153. prop="subjectName">
  154. </el-table-column>
  155. <!-- <el-table-column align='center'
  156. label="乐团班级">
  157. </el-table-column>
  158. <el-table-column align='center'
  159. label="合奏班">
  160. </el-table-column> -->
  161. <el-table-column align='center'
  162. prop="studentStatus"
  163. label="学员状态">
  164. <template slot-scope="scope">
  165. <div>
  166. {{ scope.row.studentStatus | musicGroupStudentType}}
  167. </div>
  168. </template>
  169. </el-table-column>
  170. <el-table-column align='center'
  171. label="新增学员">
  172. <template slot-scope="scope">
  173. <div>
  174. {{ scope.row.isNewStudent | yesOrNo}}
  175. </div>
  176. </template>
  177. </el-table-column>
  178. <el-table-column align='center'
  179. label="批量修改缴费">
  180. <template slot-scope="scope">
  181. <div>
  182. {{ scope.row.isLock?'已锁定':'可修改'}}
  183. </div>
  184. </template>
  185. </el-table-column>
  186. <el-table-column align="center"
  187. label="下次缴费日期"
  188. prop="nextPaymentDate">
  189. <template slot-scope="scope">
  190. {{ scope.row.nextPaymentDate | formatTimer }}
  191. </template>
  192. </el-table-column>
  193. <el-table-column align="center"
  194. label="缴费金额"
  195. prop="courseFee">
  196. </el-table-column>
  197. <el-table-column align='center'
  198. label="报名缴费">
  199. <template slot-scope="scope">
  200. <div>
  201. {{ scope.row.paymentStatus | studentPays}}
  202. </div>
  203. </template>
  204. </el-table-column>
  205. <el-table-column align='center'
  206. label="是否激活">
  207. <template slot-scope="scope">
  208. <div>
  209. {{ scope.row.isActive?'是':'否'}}
  210. </div>
  211. </template>
  212. </el-table-column>
  213. <el-table-column align='center'
  214. fixed="right"
  215. width="250px;"
  216. label="操作">
  217. <template slot-scope="scope">
  218. <div v-if="scope.row.studentStatus != 'QUIT'">
  219. <!-- <el-popover placement="top"
  220. v-model="scope.row.typeVisible">
  221. <el-input v-model="remark"
  222. placeholder="请输入退团原因"></el-input>
  223. <el-button type="text"
  224. slot='reference'
  225. class='chiose'>
  226. 退团
  227. </el-button>
  228. <div style="text-align: right; margin-top: 20px">
  229. <el-button size="mini"
  230. type="text"
  231. @click="scope.row.typeVisible = false">取消</el-button>
  232. <el-button type="primary"
  233. size="mini"
  234. @click="chioseType(scope.row)">确定</el-button>
  235. </div>
  236. </el-popover> -->
  237. <el-button type="text"
  238. v-if="permission('studentManage/queryStudentClassGroup')"
  239. @click="lookClass(scope.row)">查看班级</el-button>
  240. <el-button type="text"
  241. v-if="!scope.row.isLock && permission('studentManage/updateStudentFeeIsLock')"
  242. @click="lockStudent(scope.row)">锁定</el-button>
  243. <el-button v-if="scope.row.isLock && permission('studentManage/updateStudentFeeIsLock')"
  244. type="text"
  245. @click="lockStudent(scope.row)">解锁</el-button>
  246. <el-button type="text"
  247. v-if="permission('studentManage/updateStudentFee')"
  248. @click="resetPay(scope.row)">修改缴费</el-button>
  249. <el-button type='text'
  250. v-if="permission('musicGroupQuit/directQuitMusicGroup')"
  251. @click="quieTeamMask(scope.row)">退团</el-button>
  252. </div>
  253. </template>
  254. </el-table-column>
  255. </el-table>
  256. <pagination :total="rules.total"
  257. :page.sync="rules.page"
  258. :limit.sync="rules.limit"
  259. :page-sizes="rules.page_size"
  260. @pagination="getList" />
  261. </div>
  262. <el-dialog title="新增学员"
  263. width="640px"
  264. class="studentInfo"
  265. :visible.sync="addStudentVisible">
  266. <el-form :model="maskForm"
  267. label-position="right"
  268. label-width="100px"
  269. ref='maskForm'
  270. :rules="maskRules"
  271. :inline="true">
  272. <el-divider>基本信息</el-divider>
  273. <el-form-item label="联系电话"
  274. :rules="[{ required: true, message: '请输入手机号' }, { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }]">
  275. <el-input v-model="maskForm.phone"
  276. placeholder="联系电话"
  277. @blur="checkPhone(maskForm.phone)"></el-input>
  278. </el-form-item>
  279. <el-form-item label="学员姓名"
  280. prop="studentName">
  281. <el-input v-model="maskForm.studentName"
  282. placeholder="学员姓名"></el-input>
  283. </el-form-item>
  284. <el-form-item label="学员性别"
  285. prop="sex">
  286. <el-select v-model="maskForm.sex"
  287. clearable>
  288. <el-option label="男"
  289. :value="1"></el-option>
  290. <el-option label="女"
  291. :value="0"></el-option>
  292. </el-select>
  293. </el-form-item>
  294. <el-form-item label="家长姓名"
  295. prop="parentName">
  296. <el-input v-model="maskForm.parentName"
  297. placeholder="家长姓名"></el-input>
  298. </el-form-item>
  299. <el-form-item label="年级"
  300. prop="startClass">
  301. <el-select placeholder="起始年级"
  302. filterable
  303. clearable
  304. v-model="maskForm.startClass">
  305. <el-option value="一年级"
  306. label="一年级"></el-option>
  307. <el-option value="二年级"
  308. label="二年级"></el-option>
  309. <el-option value="三年级"
  310. label="三年级"></el-option>
  311. <el-option value="四年级"
  312. label="四年级"></el-option>
  313. <el-option value="五年级"
  314. label="五年级"></el-option>
  315. <el-option value="六年级"
  316. label="六年级"></el-option>
  317. <el-option value="初一"
  318. label="初一"></el-option>
  319. <el-option value="初二"
  320. label="初二"></el-option>
  321. <el-option value="初三"
  322. label="初三"></el-option>
  323. <el-option value="高一"
  324. label="高一"></el-option>
  325. <el-option value="高二"
  326. label="高二"></el-option>
  327. <el-option value="高三"
  328. label="高三"></el-option>
  329. </el-select>
  330. </el-form-item>
  331. <el-form-item label="班级"
  332. prop="course">
  333. <el-input v-model="maskForm.course"
  334. placeholder="班级"></el-input>
  335. </el-form-item>
  336. <el-form-item label="学员声部"
  337. prop="sound">
  338. <el-select v-model="maskForm.sound"
  339. clearable
  340. filterable
  341. @change="onSoundChange">
  342. <el-option v-for='(item,index) in soundList'
  343. :key='index'
  344. :value="item.id"
  345. :label="item.name"></el-option>
  346. </el-select>
  347. </el-form-item>
  348. <!-- <el-form-item label="证件号"
  349. prop="id">
  350. <el-input v-model="maskForm.id"></el-input>
  351. </el-form-item> -->
  352. <el-form-item label="出生日期"
  353. style="margin-right: 0;"
  354. prop="timer">
  355. <el-col :span="24">
  356. <el-date-picker v-model="maskForm.timer"
  357. value-format="yyyy-MM-dd"
  358. type="date"
  359. placeholder="选择日期">
  360. </el-date-picker>
  361. </el-col>
  362. </el-form-item>
  363. <el-form-item label="课程费用"
  364. prop="courseFee">
  365. <el-input v-model="maskForm.courseFee"
  366. type="number"
  367. @mousewheel.native.prevent
  368. placeholder="续费金额"></el-input>
  369. </el-form-item>
  370. <br>
  371. <el-form-item label="单技班">
  372. <el-select v-model="maskForm.signClass"
  373. filterable
  374. clearable>
  375. <el-option v-for="(item,index) in signList"
  376. :key="index"
  377. :value="item.id"
  378. :label="item.name"></el-option>
  379. </el-select>
  380. </el-form-item>
  381. <el-form-item label="合奏班">
  382. <el-select v-model="maskForm.mixClass"
  383. filterable
  384. clearable>
  385. <el-option v-for="(item,index) in mixList"
  386. :key="index"
  387. :value="item.id"
  388. :label="item.name"></el-option>
  389. </el-select>
  390. </el-form-item>
  391. <el-form-item label="基础技能班">
  392. <el-select v-model="maskForm.highClass"
  393. filterable
  394. clearable>
  395. <el-option v-for="(item,index) in highList"
  396. :key="index"
  397. :value="item.id"
  398. :label="item.name"></el-option>
  399. </el-select>
  400. </el-form-item>
  401. <el-form-item label="临时班">
  402. <el-select v-model="maskForm.snapClass"
  403. filterable
  404. clearable
  405. multiple>
  406. <el-option v-for="(item,index) in snapList"
  407. :key="index"
  408. :value="item.id"
  409. :label="item.name"></el-option>
  410. </el-select>
  411. </el-form-item>
  412. <el-divider>首缴订单信息</el-divider>
  413. <el-form-item label="课程费用"
  414. prop="temporaryCourseFee">
  415. <el-input type='number'
  416. @mousewheel.native.prevent
  417. v-model="maskForm.temporaryCourseFee"
  418. placeholder="首缴课程金额"></el-input>
  419. </el-form-item>
  420. <el-form-item label="乐器"
  421. class="instrList">
  422. <el-col :span="11"
  423. style="width: auto;">
  424. <el-form-item>
  425. <el-select placeholder="选择乐器"
  426. filterable
  427. clearable
  428. @change="onInstrumentChange"
  429. v-model="maskForm.musicGoodsIdList">
  430. <el-option v-for="(item, index) in INSTRUMENTLIST"
  431. :key="index"
  432. :value="item.value"
  433. :label="item.label"></el-option>
  434. </el-select>
  435. </el-form-item>
  436. </el-col>
  437. <el-col :span="1">&nbsp;</el-col>
  438. <el-col :span="11">
  439. <el-form-item>
  440. <el-input type="number" @mousewheel.native.prevent :disabled="kitStatus" v-model="maskForm.musicPrice"
  441. placeholder="输入金额">
  442. <el-select v-model="maskForm.kitGroupPurchaseType"
  443. style="width: 80px !important;"
  444. @change="onKitGroupChnage"
  445. slot="prepend">
  446. <el-option label="免费"
  447. value="FREE"></el-option>
  448. <el-option label="团购"
  449. value="GROUP"></el-option>
  450. <el-option label="租赁"
  451. value="LEASE"></el-option>
  452. </el-select>
  453. </el-input>
  454. </el-form-item>
  455. </el-col>
  456. </el-form-item>
  457. <el-form-item label="辅件">
  458. <el-col :span="11"
  459. style="width: auto;">
  460. <el-form-item>
  461. <el-select filterable
  462. clearable
  463. multiple
  464. placeholder="选择辅件"
  465. v-model="maskForm.instrGoodsIdList">
  466. <el-option v-for="(item, index) in ACCESSORIESLIST"
  467. :key="index"
  468. :value="item.value"
  469. :label="item.label"></el-option>
  470. </el-select>
  471. </el-form-item>
  472. </el-col>
  473. <el-col :span="1">&nbsp;</el-col>
  474. <el-col :span="11">
  475. <el-form-item>
  476. <el-input v-model="maskForm.instrPrice"
  477. placeholder="输入金额"></el-input>
  478. </el-form-item>
  479. </el-col>
  480. </el-form-item>
  481. </el-form>
  482. <div slot="footer"
  483. class="dialog-footer">
  484. <!-- <el-button @click="addStudentVisible = false">取 消</el-button> -->
  485. <el-button type="primary"
  486. @click="addStudent">确 定</el-button>
  487. </div>
  488. </el-dialog>
  489. <el-dialog title="学员所在班级"
  490. width="640px"
  491. :visible.sync="studentClassVisible">
  492. <el-form :model="classMask">
  493. <el-form-item label="学生姓名">
  494. {{ classMask.studentName }}
  495. </el-form-item>
  496. <el-form-item label="所在班级"
  497. v-for="(item,index) in classList"
  498. :key="index">
  499. {{ item.name }}
  500. </el-form-item>
  501. </el-form>
  502. </el-dialog>
  503. <!-- 退团弹窗 -->
  504. <el-dialog title="退团信息确认"
  505. width="640px"
  506. :visible.sync="quitVisible">
  507. <el-form :model="quitForm"
  508. ref="quitForm"
  509. :rules="quitRules">
  510. <el-form-item label="退还课程费用"
  511. prop="isRefundCourseFee">
  512. <el-radio v-model="quitForm.isRefundCourseFee"
  513. :label="true">是</el-radio>
  514. <el-radio v-model="quitForm.isRefundCourseFee"
  515. :label="false">否</el-radio>
  516. </el-form-item>
  517. <el-form-item label="退还乐器费用"
  518. prop="isRefundInstrumentFee">
  519. <el-radio v-model="quitForm.isRefundInstrumentFee"
  520. :label="true">是</el-radio>
  521. <el-radio v-model="quitForm.isRefundInstrumentFee"
  522. :label="false">否</el-radio>
  523. </el-form-item>
  524. <el-form-item label="退还教辅费用"
  525. prop="isRefundTeachingAssistantsFee">
  526. <el-radio v-model="quitForm.isRefundTeachingAssistantsFee"
  527. :label="true">是</el-radio>
  528. <el-radio v-model="quitForm.isRefundTeachingAssistantsFee"
  529. :label="false">否</el-radio>
  530. </el-form-item>
  531. <el-form-item label="退团原因">
  532. <el-input type="textarea"
  533. v-model="quitForm.reason"></el-input>
  534. </el-form-item>
  535. </el-form>
  536. <span slot="footer"
  537. class="dialog-footer">
  538. <el-button @click="quitVisible = false">取 消</el-button>
  539. <el-button type="primary"
  540. @click="chioseType">确 定</el-button>
  541. </span>
  542. </el-dialog>
  543. <el-dialog title="报名二维码"
  544. :visible.sync="qrcodeStatus"
  545. width="300px">
  546. <div class="left-code">
  547. <h2>学员报名连接</h2>
  548. <div id="qrcode"
  549. class="qrcode code"
  550. ref="qrCodeUrl"></div>
  551. <p class="code-url"
  552. v-if="codeUrl">{{ codeUrl }}</p>
  553. </div>
  554. </el-dialog>
  555. <el-dialog title="修改缴费周期"
  556. :before-close='closePayVisible'
  557. width='600px'
  558. :visible.sync="payVisible">
  559. <el-form :model="payForm"
  560. ref="payForm"
  561. :inline="true">
  562. <el-form-item label="学生姓名"
  563. prop="studentName">
  564. <el-input v-model="payForm.studentName"
  565. disabled></el-input>
  566. </el-form-item>
  567. <br>
  568. <el-form-item label="缴费金额"
  569. prop="payMoney">
  570. <el-input type="number"
  571. v-model="payForm.payMoney"
  572. @mousewheel.native.prevent></el-input>
  573. </el-form-item>
  574. <el-form-item label="缴费月份"
  575. prop="payMonth">
  576. <el-checkbox-group v-model="payForm.payMonth"
  577. fill="#14928A"
  578. text-color='#474747'>
  579. <el-checkbox label="1">一月</el-checkbox>
  580. <el-checkbox label="2">二月</el-checkbox>
  581. <el-checkbox label="3">三月</el-checkbox>
  582. <el-checkbox label="4">四月</el-checkbox>
  583. <el-checkbox label="5">五月</el-checkbox>
  584. <el-checkbox label="6">六月</el-checkbox>
  585. <el-checkbox label="7">七月</el-checkbox>
  586. <el-checkbox label="8">八月</el-checkbox>
  587. <el-checkbox label="9">九月</el-checkbox>
  588. <el-checkbox label="10">十月</el-checkbox>
  589. <el-checkbox label="11">十一月</el-checkbox>
  590. <el-checkbox label="12">十二月</el-checkbox>
  591. </el-checkbox-group>
  592. </el-form-item>
  593. <!-- studentName: '',
  594. payMoney: '',
  595. payMonth -->
  596. </el-form>
  597. <div slot="footer"
  598. class="dialog-footer">
  599. <el-button @click="quitVisible = false">取 消</el-button>
  600. <el-button type="primary"
  601. @click="submitPay">确 定</el-button>
  602. </div>
  603. </el-dialog>
  604. </div>
  605. </template>
  606. <script>
  607. import { getTeamStudentList, getTeamStudentInfo, getSingleClass, findSound, StudentQuit, findSubjectPlan, getGoods, getSubject, getMusicGroupAllClass, StudentFeeIsLock, updateStudentFee } from '@/api/buildTeam'
  608. import { addStudent, getStudentClass, getStudentInfoByPhone } from '@/api/studentManager'
  609. import pagination from '@/components/Pagination/index'
  610. import { vaildStudentUrl } from '@/utils/validate'
  611. import QRCode from 'qrcodejs2'
  612. import axios from 'axios'
  613. import { getToken } from '@/utils/auth'
  614. import { permission } from '@/utils/directivePage'
  615. export default {
  616. name: "tstudentList",
  617. props: ['teamid'],
  618. data () {
  619. return {
  620. payVisible: false,
  621. quitVisible: false, // 退团信息确认的弹窗
  622. studentClassVisible: false, // 学员所在班级弹窗
  623. addStudentVisible: false, //新增学员弹窗
  624. topFrom: { // 顶部的禁选框集合
  625. expect: '2', // 预期招生
  626. studing: '5', // 在读人数
  627. allmoney: '100', //实收总额
  628. students: '5', // 实际招生人数
  629. signout: '10', // 退团总数
  630. },
  631. searchForm: {
  632. studentStatus: '', // 学生状态
  633. major: '', // 报名专业
  634. isPay: '', // 是否缴费
  635. search: '',
  636. isActive: '',
  637. classGroupId: null
  638. },
  639. quitForm: { // 退团信息确认
  640. isRefundCourseFee: null,
  641. isRefundInstrumentFee: null,
  642. isRefundTeachingAssistantsFee: null,
  643. reason: ''
  644. },
  645. classMask: {
  646. studentName: ''
  647. },
  648. searchLsit: [],
  649. tableList: [], //
  650. rules: {
  651. // 分页规则
  652. limit: 10, // 限制显示条数
  653. page: 1, // 当前页
  654. total: 0, // 总条数
  655. page_size: [10, 20, 40, 50] // 选择限制显示条数
  656. },
  657. studentListInfo: {
  658. add: '',
  659. quit: '',
  660. studying: ''
  661. },
  662. signList: [],
  663. mixList: [],
  664. highList: [],
  665. snapList: [],
  666. soundList: [],
  667. qrcodeStatus: false, // 生成二维码
  668. qrcodes: true,
  669. qrcode: null,
  670. codeUrl: null,
  671. maskForm: {
  672. studentName: '',
  673. sex: '',
  674. parentName: '',
  675. course: '',
  676. phone: '',
  677. sound: '',
  678. timer: '',
  679. signClass: '',
  680. mixClass: '',
  681. highClass: '',
  682. snapClass: [],
  683. // price: '',
  684. startClass: '',
  685. id: '',
  686. courseFee: null, // 声部费用
  687. temporaryCourseFee: null, // 本次课程费用
  688. musicGoodsIdList: null, // 乐器商品编号
  689. kitGroupPurchaseType: 'GROUP', // 乐器购买方式
  690. musicPrice: null, // 乐器购买金额
  691. instrGoodsIdList: [], // 辅件商品编号
  692. instrPrice: null // 辅件购买金额
  693. },
  694. remark: '', // 退团原因
  695. classList: [],
  696. quitRules: {
  697. isRefundCourseFee: [{ required: true, message: '请选择是否退还课程费用' },],
  698. isRefundInstrumentFee: [{ required: true, message: '选择是否退还乐器费用' },],
  699. isRefundTeachingAssistantsFee: [{ required: true, message: '选择是否退还教辅费用' },],
  700. },
  701. maskRules: {
  702. studentName: [{ required: true, message: '请输入学生姓名' },],
  703. sex: [{ required: true, message: '请选择学生姓名' },],
  704. parentName: [{ required: true, message: '请输入家长姓名' },],
  705. course: [{ required: true, message: '请输入班级' },],
  706. // phone: [{ required: true, message: '请输入手机号' }, { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }],
  707. sound: [{ required: true, message: '请选择声部' },],
  708. timer: [{ required: true, message: '请选择出生日期' },],
  709. signClass: [{ required: true, message: '请选择单技班' },],
  710. // price: [{ required: true, message: '请输入首缴金额' },],
  711. startClass: [{ required: true, message: '请选择年级' }],
  712. id: [{ required: true, message: '请输入证件号' }],
  713. courseFee: [{ required: true, message: '请输入声部费用' }],
  714. temporaryCourseFee: [{ required: true, message: '请输课程费用' }],
  715. musicGoodsIdList: [{ required: true, message: '请选择乐器', trigger: 'change' }],
  716. musicPrice: [{ required: true, message: '请输入乐器购买金额' }],
  717. instrGoodsIdList: [{ required: true, message: '请选择辅件' }],
  718. instrPrice: [{ required: true, message: '请输入辅件金额' }]
  719. },
  720. INSTRUMENTLIST: [], // 乐器列表
  721. ACCESSORIESLIST: [], // 辅件列表
  722. activeRow: null,
  723. Fsearch: null,
  724. Frules: null,
  725. payForm: {
  726. studentName: '',
  727. payMoney: '',
  728. payMonth: []
  729. },
  730. kitStatus: false, // 乐器提供方式
  731. }
  732. },
  733. components: {
  734. pagination
  735. },
  736. created () {
  737. // 判断是否带缓存参数
  738. if (this.$route.query.search) {
  739. this.Fsearch = this.$route.query.search;
  740. }
  741. if (this.$route.query.rules) {
  742. this.Frules = this.$route.query.rules
  743. }
  744. },
  745. /** <el-option label="已开启缴费"
  746. value="1"></el-option>
  747. <el-option label="未缴费"
  748. value="0"></el-option>
  749. <el-option label="已缴费"
  750. value="2"></el-option> */
  751. filters: {
  752. studentPays (val) {
  753. let template = {
  754. 'PAID_COMPLETED': "完成缴费",
  755. 'NON_PAYMENT': "未缴费",
  756. 'PROCESSING': "缴费中"
  757. }
  758. return template[val]
  759. }
  760. },
  761. mounted () {
  762. this.init()
  763. },
  764. activated () {
  765. this.init()
  766. },
  767. methods: {
  768. init () {
  769. // 获取汇总数据
  770. getTeamStudentInfo({ musicGroupId: this.teamid }).then(res => {
  771. if (res.code == 200) {
  772. this.studentListInfo = res.data;
  773. }
  774. });
  775. this.getList();
  776. // 获取乐团内所有声部
  777. findSound({ musicGroupId: this.teamid }).then(res => {
  778. if (res.code == 200) {
  779. this.soundList = res.data;
  780. }
  781. })
  782. // getSubject().then(res => {
  783. // if (res.code == 200) {
  784. // this.soundList = res.data;
  785. // }
  786. // })
  787. // 获取乐团所有单技课班
  788. // getSingleClass({ musicGroupId: this.teamid }).then(res => {
  789. // if (res.code == 200) {
  790. // this.signList = res.data;
  791. // }
  792. // })
  793. // 获取乐团所有合奏课
  794. getMusicGroupAllClass({ musicGroupId: this.teamid }).then(res => {
  795. if (res.code == 200) {
  796. this.classList = res.data;
  797. this.signList = [];
  798. this.mixList = [];
  799. this.highList = [];
  800. this.snapList = [];
  801. this.classList.forEach(item => {
  802. if (item.type == 'NORMAL') {
  803. this.signList.push(item);
  804. } else if (item.type == 'MIX') {
  805. this.mixList.push(item);
  806. } else if (item.type == 'HIGH') {
  807. this.highList.push(item)
  808. } else if (item.type == 'SNAP') {
  809. this.snapList.push(item);
  810. }
  811. })
  812. }
  813. })
  814. },
  815. permission (str) {
  816. return permission(str)
  817. },
  818. onInstrumentChange() { // 乐器切换时
  819. // let tempkitType = this.maskForm.kitGroupPurchaseType
  820. // if(tempkitType == 'GROUP') {
  821. // this.INSTRUMENTLIST.forEach(item => {
  822. // if(item.value == value) {
  823. // this.maskForm.musicPrice = item.marketPrice
  824. // }
  825. // })
  826. // }
  827. },
  828. onKitGroupChnage(value) { // 乐器提供方式
  829. this.kitStatus = false
  830. if(value == 'FREE') {
  831. this.kitStatus = true
  832. this.maskForm.musicPrice = 0
  833. } else {
  834. this.maskForm.musicPrice = null
  835. }
  836. },
  837. onMusicGroupExport () {
  838. let url = '/api-web/export/musicGroupStudent'
  839. let data = {
  840. musicGroupId: this.teamid,
  841. studentStatus: this.searchForm.studentStatus || null,
  842. paymentStatus: this.searchForm.isPay || null,
  843. subjectId: this.searchForm.major || null,
  844. search: this.searchForm.search || null,
  845. isActive: this.searchForm.isActive || null,
  846. classGroupId: this.searchForm.classGroupId || null
  847. }
  848. const options = {
  849. method: 'get',
  850. headers: {
  851. 'Authorization': getToken()
  852. },
  853. url,
  854. params: data,
  855. responseType: 'blob'
  856. }
  857. this.$confirm('您确定导出学员列表?', '提示', {
  858. confirmButtonText: '确定',
  859. cancelButtonText: '取消',
  860. type: 'warning'
  861. }).then(() => {
  862. axios(options).then(res => {
  863. let blob = new Blob([res.data], {
  864. // type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8',
  865. type: 'application/vnd.ms-excel;charset=utf-8'
  866. // word文档为application/msword,pdf文档为application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
  867. })
  868. let objectUrl = URL.createObjectURL(blob)
  869. let link = document.createElement("a")
  870. let fname = this.$route.query.name + '学员列表'
  871. link.href = objectUrl
  872. link.setAttribute("download", fname)
  873. document.body.appendChild(link)
  874. link.click()
  875. })
  876. }).catch(() => { })
  877. },
  878. search () {
  879. this.rules.page = 1;
  880. this.getList()
  881. },
  882. onCreateQRCode () { // 生成报名二维码
  883. this.qrcodeStatus = true
  884. let id = this.$route.query.id
  885. if (this.qrcodes) {
  886. this.qrcodes = false
  887. setTimeout(() => {
  888. this.qrcode = new QRCode('qrcode', {
  889. width: 200,
  890. height: 200,
  891. colorDark: '#000000',
  892. colorLight: '#ffffff',
  893. correctLevel: QRCode.CorrectLevel.H
  894. })
  895. this.qrcode.makeCode(vaildStudentUrl() + '/#/login?musicGroupId=' + id)
  896. this.codeUrl = vaildStudentUrl() + '/#/login?musicGroupId=' + id
  897. }, 500)
  898. }
  899. },
  900. getList () {
  901. let obj = {
  902. musicGroupId: this.teamid,
  903. page: this.rules.page,
  904. rows: this.rules.limit,
  905. studentStatus: this.searchForm.studentStatus || null,
  906. paymentStatus: this.searchForm.isPay || null,
  907. subjectId: this.searchForm.major || null,
  908. search: this.searchForm.search || null,
  909. isActive: this.searchForm.isActive || null,
  910. classGroupId: this.searchForm.classGroupId || null
  911. }
  912. getTeamStudentList(obj).then(res => {
  913. if (res.code == 200) {
  914. this.tableList = res.data.rows;
  915. this.rules.total = res.data.total
  916. }
  917. })
  918. },
  919. gotoSignin () {
  920. this.$router.push({
  921. path: '/business/studentSignin',
  922. query: {
  923. id: this.teamid,
  924. status: this.$route.query.status,
  925. name: this.$route.query.name,
  926. rules: this.Frules, search: this.Fsearch
  927. }
  928. })
  929. },
  930. chioseType () {
  931. this.$refs['quitForm'].validate(res => {
  932. if (res) {
  933. this.$confirm('确定退团?', '提示', {
  934. confirmButtonText: '确定',
  935. cancelButtonText: '取消',
  936. type: 'warning'
  937. }).then(() => {
  938. let row = this.activeRow;
  939. // 发请求 退团
  940. StudentQuit({ musicGroupId: this.teamid, userId: row.userId,
  941. reason: this.quitForm.reason,
  942. isRefundCourseFee: this.quitForm.isRefundCourseFee,
  943. isRefundInstrumentFee: this.quitForm.isRefundInstrumentFee,
  944. isRefundTeachingAssistantsFee: this.quitForm.isRefundTeachingAssistantsFee }).then(res => {
  945. this.quitForm = { // 退团信息确认
  946. isRefundCourseFee: null,
  947. isRefundInstrumentFee: null,
  948. isRefundTeachingAssistantsFee: null,
  949. reason: ''
  950. }
  951. if (res.code == 200) {
  952. this.$message.success('退团成功')
  953. this.getList();
  954. this.quitVisible = false;
  955. }
  956. })
  957. }).catch(() => {
  958. });
  959. } else {
  960. }
  961. })
  962. // row.typeVisible = false;
  963. },
  964. //
  965. addStudent () {
  966. // 发请求添加学员
  967. this.$refs['maskForm'].validate(res => {
  968. if (res) {
  969. // this.maskForm.parentName.timer 少个生日的字段
  970. // classGroupId: maskForm.signClass
  971. /** <!-- signClass: '',
  972. mixClass: '',
  973. highClass: '',
  974. snapClass: [], --> */
  975. let maskForm = this.maskForm
  976. if (!maskForm.signClass && !maskForm.mixClass && !maskForm.highClass) {
  977. if (!maskForm.snapClass || !(maskForm.snapClass && maskForm.snapClass.length >= 1)) {
  978. this.$message.error('该学生必须加入一个班级')
  979. return;
  980. }
  981. }
  982. if(maskForm.musicGoodsIdList && (maskForm.musicPrice === '' || maskForm.musicPrice === null)) {
  983. this.$message.error('请输入乐器金额')
  984. return
  985. }
  986. if(maskForm.instrGoodsIdList && maskForm.instrGoodsIdList.length > 0 && (maskForm.instrPrice === '' || maskForm.instrPrice === null)) {
  987. this.$message.error('请输入辅件金额')
  988. return
  989. }
  990. let snapClassIds;
  991. maskForm.snapClass ? snapClassIds = maskForm.snapClass.join(',') : snapClassIds = null
  992. let params = {
  993. signClassId: maskForm.signClass,
  994. mixClassId: maskForm.mixClass,
  995. snapClassIds,
  996. highClassId: maskForm.highClass,
  997. courseFee: maskForm.courseFee,
  998. temporaryCourseFee: maskForm.temporaryCourseFee,
  999. studentRegistration: {
  1000. name: maskForm.studentName,
  1001. gender: maskForm.sex,
  1002. birthdate: maskForm.timer,
  1003. parentsName: maskForm.parentName,
  1004. parentsPhone: maskForm.phone,
  1005. currentGrade: maskForm.startClass,
  1006. currentClass: maskForm.course,
  1007. subjectId: maskForm.sound,
  1008. musicGroupId: this.teamid,
  1009. }
  1010. }
  1011. params.studentPaymentOrderDetails = []
  1012. if (maskForm.musicGoodsIdList) {
  1013. params.studentPaymentOrderDetails.push({
  1014. goodsIdList: maskForm.musicGoodsIdList,
  1015. kitGroupPurchaseType: maskForm.kitGroupPurchaseType,
  1016. type: 'MUSICAL',
  1017. price: maskForm.musicPrice
  1018. })
  1019. }
  1020. if (maskForm.instrGoodsIdList && maskForm.instrGoodsIdList != '') {
  1021. params.studentPaymentOrderDetails.push({
  1022. goodsIdList: maskForm.instrGoodsIdList.join(','),
  1023. type: 'ACCESSORIES',
  1024. price: maskForm.instrPrice
  1025. })
  1026. }
  1027. addStudent(params).then(res => {
  1028. if (res.code == 200) {
  1029. this.$message.success('添加学生成功');
  1030. this.getList()
  1031. this.addStudentVisible = false
  1032. }
  1033. this.$refs.maskForm.resetFields()
  1034. })
  1035. }
  1036. })
  1037. },
  1038. onSoundChange (value) { // 学员声部切换时
  1039. // this.findSubjectPlan(value)
  1040. this.ACCESSORIESLIST = []
  1041. this.maskForm.instrGoodsIdList = []
  1042. this.maskForm.instrPrice = null
  1043. this.INSTRUMENTLIST = []
  1044. this.maskForm.musicPrice = null
  1045. this.maskForm.musicGoodsIdList = null
  1046. this.getGoodsList(value, 'INSTRUMENT') // 乐器
  1047. this.getGoodsList(value, 'ACCESSORIES') // 辅件
  1048. },
  1049. // 获取购买方式
  1050. findSubjectPlan (subjectId) {
  1051. findSubjectPlan({
  1052. musicGroupId: this.teamid,
  1053. subjectId: subjectId
  1054. }).then(res => {
  1055. let result = res.data
  1056. if (res.code == 200) {
  1057. this.maskForm.musicMode = this.getBranchType(result.kitGroupPurchaseType)
  1058. }
  1059. })
  1060. },
  1061. getGoodsList (subjectId, type) {
  1062. getGoods({
  1063. subjectId: subjectId,
  1064. type: type
  1065. }).then(res => {
  1066. let result = res.data
  1067. if (res.code == 200) {
  1068. let tempArr = []
  1069. result.forEach(item => {
  1070. tempArr.push({
  1071. label: item.name,
  1072. value: item.id,
  1073. marketPrice: item.marketPrice
  1074. })
  1075. })
  1076. if (type == 'ACCESSORIES') {
  1077. this.ACCESSORIESLIST = tempArr
  1078. }
  1079. if (type == 'INSTRUMENT') {
  1080. this.INSTRUMENTLIST = tempArr
  1081. }
  1082. }
  1083. })
  1084. },
  1085. getBranchType (status) {
  1086. let common = {
  1087. FREE: "免费",
  1088. GROUP: "团购",
  1089. LEASE: "租赁"
  1090. }
  1091. return common[status]
  1092. },
  1093. lookClass (row) {
  1094. this.classMask.studentName = row.realName;
  1095. getStudentClass({
  1096. musicGroupId: this.teamid,
  1097. teacherId: row.userId
  1098. }).then(res => {
  1099. if (res.code == 200) {
  1100. this.classList = res.data;
  1101. this.studentClassVisible = true;
  1102. }
  1103. })
  1104. },
  1105. quieTeamMask (row) {
  1106. this.activeRow = row;
  1107. this.quitVisible = true;
  1108. },
  1109. checkPhone (val) {
  1110. var regu = /^1[3456789]\d{9}$/;
  1111. var re = new RegExp(regu);
  1112. if (re.test(val)) {
  1113. getStudentInfoByPhone({ mobile: this.maskForm.phone }).then(res => {
  1114. if (res.code == 200) {
  1115. if (res.data) {
  1116. this.maskForm.studentName = res.data.name
  1117. this.maskForm.sex = res.data.gender
  1118. this.maskForm.parentName = res.data.parentsName
  1119. this.maskForm.course = res.data.currentClass
  1120. this.maskForm.startClass = res.data.currentGrade
  1121. this.maskForm.phone = val
  1122. this.maskForm.timer = res.data.birthdate
  1123. }
  1124. }
  1125. })
  1126. }
  1127. },
  1128. lockStudent (row) {
  1129. this.$confirm('是否锁定/解锁学生缴费周期?', '提示', {
  1130. confirmButtonText: '确定',
  1131. cancelButtonText: '取消',
  1132. type: 'warning'
  1133. }).then(() => {
  1134. let musicGroupId = this.teamid;
  1135. let studentId = row.userId;
  1136. let isLock;
  1137. row.isLock == 0 ? isLock = 1 : isLock = 0;
  1138. StudentFeeIsLock({ musicGroupId, studentId, isLock }).then(res => {
  1139. if (res.code == 200) {
  1140. this.$message.success('修改成功')
  1141. this.getList()
  1142. }
  1143. })
  1144. }).catch(() => {
  1145. });
  1146. },
  1147. resetPay (row) {
  1148. this.activeRow = row;
  1149. this.payVisible = true;
  1150. this.payForm.studentName = row.realName;
  1151. this.payForm.payMoney = row.courseFee;
  1152. this.payForm.payMonth = row.paymentPeriodList.split(',')
  1153. if (this.payForm.payMonth[0] == "") {
  1154. this.payForm.payMonth = []
  1155. }
  1156. },
  1157. submitPay () {
  1158. let studentId = this.activeRow.userId;
  1159. let musicGroupId = this.teamid;
  1160. let month = this.payForm.payMonth.join(',') || null;
  1161. let amount = this.payForm.payMoney;
  1162. let obj = {
  1163. studentId,
  1164. musicGroupId,
  1165. month,
  1166. amount
  1167. }
  1168. updateStudentFee(obj).then(res => {
  1169. if (res.code == 200) {
  1170. this.$message.success('修改成功')
  1171. this.payVisible = false;
  1172. this.getList();
  1173. }
  1174. })
  1175. },
  1176. closePayVisible () {
  1177. this.$refs['payForm'].resetFields();
  1178. this.payVisible = false;
  1179. }
  1180. }
  1181. }
  1182. </script>
  1183. <style lang="scss" scoped>
  1184. // .moreInput {
  1185. // width: 100%;
  1186. // display: flex;
  1187. // /deep/.el-form-item__content {
  1188. // display: flex;
  1189. // flex-direction: row;
  1190. // }
  1191. // }
  1192. .el-select {
  1193. width: 180px !important;
  1194. }
  1195. .headWrap {
  1196. padding: 20px 0;
  1197. }
  1198. /deep/.el-date-editor.el-input {
  1199. width: auto;
  1200. .el-input__inner {
  1201. padding-right: 0;
  1202. }
  1203. }
  1204. .studentInfo {
  1205. /deep/.el-dialog__body {
  1206. padding-top: 0;
  1207. padding-bottom: 0;
  1208. }
  1209. }
  1210. // .instrList {
  1211. // display: flex;
  1212. // /deep/.el-form-item__content {
  1213. // width: 80%;
  1214. // }
  1215. // .el-col {
  1216. // /deep/.el-form-item__content {
  1217. // width: 100%;
  1218. // }
  1219. // }
  1220. // }
  1221. .stu-container {
  1222. .topFrom {
  1223. margin: 20px 30px 0;
  1224. width: 1000px;
  1225. }
  1226. .newStudent {
  1227. width: 121px;
  1228. height: 40px;
  1229. background: rgba(20, 146, 138, 1);
  1230. border-radius: 4px;
  1231. color: #fff;
  1232. text-align: center;
  1233. line-height: 40px;
  1234. font-size: 14px;
  1235. cursor: pointer;
  1236. }
  1237. }
  1238. .left-code,
  1239. .right-code {
  1240. // width: 50%;
  1241. // float: left;
  1242. h2 {
  1243. display: block;
  1244. font-size: 18px;
  1245. text-align: center;
  1246. padding-bottom: 8px;
  1247. line-height: 1;
  1248. height: 30px;
  1249. margin-bottom: 0;
  1250. }
  1251. .qrcode {
  1252. display: flex;
  1253. justify-content: center;
  1254. img {
  1255. width: 200px;
  1256. height: 200px;
  1257. // margin: 0 auto;
  1258. }
  1259. }
  1260. .code-url {
  1261. font-size: 18px;
  1262. text-align: center;
  1263. padding: 15px 15px 0 15px;
  1264. }
  1265. }
  1266. .export {
  1267. background: #14928a;
  1268. }
  1269. </style>