studentList.vue 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714
  1. <template>
  2. <div class="stu-container">
  3. <!-- 头部展示 -->
  4. <statistic>
  5. <statistic-item>
  6. <span>在读人数</span>
  7. <span>{{ studentListInfo.studying }}</span>
  8. </statistic-item>
  9. <statistic-item>
  10. <span>退团人数</span>
  11. <span>{{ studentListInfo.quit }}</span>
  12. </statistic-item>
  13. <statistic-item>
  14. <span>新增人数</span>
  15. <span>{{ studentListInfo.add }}</span>
  16. </statistic-item>
  17. <statistic-item>
  18. <span>VIP&网管转化率</span>
  19. <span>{{ studentListInfo.courseRate }}</span>
  20. </statistic-item>
  21. </statistic>
  22. <!-- <statistic-item>
  23. <div style="display: flex;">
  24. <div>
  25. <div class="newStudent"
  26. style="margin-bottom:10px;"
  27. v-permission="'studentRegistration/insertStudent'"
  28. @click="addStudentVisible = true">新增学员</div>
  29. <div class="newStudent"
  30. style="margin-bottom:10px;"
  31. v-permission="'teamDetails/studentList/QRCode/822'"
  32. @click="onCreateQRCode">报名连接</div>
  33. <div class="newStudent"
  34. v-permission="'/studentSignin'"
  35. @click="gotoSignin">点名总览</div>
  36. </div>
  37. <div style="margin-left: 10px;">
  38. <div class="newStudent"
  39. style="margin-bottom:10px;"
  40. v-permission="'studentManage/queryStudentSubTotalCourseTimes'"
  41. @click="viewTimer">剩余时长明细</div>
  42. </div>
  43. </div>
  44. </statistic-item> -->
  45. <div style="margin-bottom: 15px;" class="studentListWrap">
  46. <el-button type="primary" v-permission="'studentRegistration/insertStudent'"
  47. @click="createStudentFrom">新增学员</el-button>
  48. <!-- 可以直接去学生考勤查看 -->
  49. <!-- <el-button type="primary" v-permission="'/studentSignin'"
  50. @click="gotoSignin">点名总览</el-button> -->
  51. <el-button type="primary" v-permission="'studentManage/queryStudentSubTotalCourseTimes'"
  52. @click="viewTimer" style="margin-right: 15px;">剩余时长明细</el-button>
  53. </div>
  54. <!-- 搜索类型 -->
  55. <save-form
  56. ref='searchForm'
  57. :inline="true"
  58. :save-key="saveKey"
  59. class="searchForm"
  60. @submit="search"
  61. @reset="onReSet"
  62. :model="searchForm"
  63. >
  64. <el-form-item prop="search">
  65. <el-input
  66. v-model.trim="searchForm.search"
  67. clearable
  68. placeholder="学生姓名或电话"
  69. @keyup.enter.native="search"
  70. ></el-input>
  71. </el-form-item>
  72. <el-form-item prop="studentStatus">
  73. <el-select
  74. v-model.trim="searchForm.studentStatus"
  75. clearable
  76. filterable
  77. placeholder="学员状态"
  78. >
  79. <el-option label="在读" value="NORMAL"></el-option>
  80. <el-option label="请假" value="LEAVE"></el-option>
  81. <el-option label="退团" value="QUIT"></el-option>
  82. <el-option label="报名" value="APPLY"></el-option>
  83. </el-select>
  84. </el-form-item>
  85. <el-form-item prop="createYear">
  86. <el-date-picker
  87. v-model="searchForm.createYear"
  88. type="year"
  89. value-format="yyyy"
  90. placeholder="选择入团年份">
  91. </el-date-picker>
  92. </el-form-item>
  93. <el-form-item prop="currentGrade">
  94. <!-- <el-input
  95. v-model.trim="searchForm.currentGrade"
  96. clearable
  97. placeholder="学员年级"
  98. ></el-input> -->
  99. <el-select v-model.trim="searchForm.currentGrade" filterable clearable placeholder="请输入年级">
  100. <el-option
  101. v-for="(item, index) in gradeList"
  102. :key="index"
  103. :label="item.label"
  104. :value="item.label"
  105. ></el-option>
  106. </el-select>
  107. </el-form-item>
  108. <el-form-item prop="classGroupId">
  109. <el-select
  110. v-model.trim="searchForm.classGroupId"
  111. clearable
  112. filterable
  113. placeholder="请选择班级"
  114. >
  115. <el-option
  116. v-for="(item, index) in classList"
  117. :key="index"
  118. :value="item.id"
  119. :label="item.name"
  120. ></el-option>
  121. </el-select>
  122. </el-form-item>
  123. <el-form-item prop="major">
  124. <el-select
  125. v-model.trim="searchForm.major"
  126. clearable
  127. filterable
  128. placeholder="所选专业"
  129. >
  130. <el-option
  131. v-for="(item, index) in soundList"
  132. :key="index"
  133. :value="item.id"
  134. :label="item.name"
  135. ></el-option>
  136. </el-select>
  137. </el-form-item>
  138. <el-form-item prop="isPay">
  139. <el-select
  140. v-model.trim="searchForm.isPay"
  141. clearable
  142. filterable
  143. placeholder="报名缴费"
  144. >
  145. <el-option label="未缴费" value="0"></el-option>
  146. <el-option label="已缴费" value="1"></el-option>
  147. </el-select>
  148. </el-form-item>
  149. <el-form-item prop="oweFlag">
  150. <el-select
  151. v-model.trim="searchForm.oweFlag"
  152. clearable
  153. filterable
  154. placeholder="是否欠费"
  155. >
  156. <el-option label="否" value="0"></el-option>
  157. <el-option label="是" value="1"></el-option>
  158. </el-select>
  159. </el-form-item>
  160. <el-form-item prop="isActive">
  161. <el-select
  162. v-model.trim="searchForm.isActive"
  163. clearable
  164. filterable
  165. placeholder="是否激活"
  166. >
  167. <el-option label="是" value="1"></el-option>
  168. <el-option label="否" value="0"></el-option>
  169. </el-select>
  170. </el-form-item>
  171. <el-form-item prop="hasCourse">
  172. <el-select
  173. v-model.trim="searchForm.hasCourse"
  174. clearable
  175. placeholder="VIP/网管是否有课"
  176. >
  177. <el-option label="是" value="true"></el-option>
  178. <el-option label="否" value="false"></el-option>
  179. </el-select>
  180. </el-form-item>
  181. <el-form-item prop="carePackage">
  182. <el-select
  183. class="multiple"
  184. v-model.trim="searchForm.carePackage"
  185. clearable
  186. placeholder="关心包"
  187. >
  188. <el-option label="不可用" :value="0"></el-option>
  189. <el-option label="可用" :value="1"></el-option>
  190. <el-option label="已使用" :value="2"></el-option>
  191. </el-select>
  192. </el-form-item>
  193. <el-form-item prop="comeOnPackage">
  194. <el-select
  195. class="multiple"
  196. v-model.trim="searchForm.comeOnPackage"
  197. clearable
  198. placeholder="加油包"
  199. >
  200. <el-option label="不可用" :value="0"></el-option>
  201. <el-option label="可用" :value="1"></el-option>
  202. <el-option label="已使用" :value="2"></el-option>
  203. </el-select>
  204. </el-form-item>
  205. <el-form-item>
  206. <el-button native-type="submit" type="danger">搜索</el-button>
  207. <el-button type="primary" native-type="reset">重置</el-button>
  208. <el-button
  209. type="primary"
  210. v-permission="'export/musicGroupStudent'"
  211. @click="onMusicGroupExport"
  212. >导出</el-button>
  213. </el-form-item>
  214. </save-form>
  215. <!-- 列表 -->
  216. <div class="tableWrap">
  217. <el-table
  218. :data="tableList"
  219. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  220. >
  221. <el-table-column
  222. label="学员编号"
  223. width="120px;"
  224. prop="userId"
  225. >
  226. <template slot-scope="scope">
  227. <copy-text>
  228. {{ scope.row.userId }}
  229. </copy-text>
  230. </template>
  231. </el-table-column>
  232. <el-table-column
  233. label="学员姓名"
  234. width="120px;"
  235. prop="realName"
  236. >
  237. <template slot-scope="scope">
  238. <copy-text>
  239. {{ scope.row.realName }}
  240. </copy-text>
  241. </template>
  242. </el-table-column>
  243. <el-table-column
  244. align="center"
  245. prop="gender"
  246. width="50px;"
  247. label="性别"
  248. >
  249. <template slot-scope="scope">
  250. <div>{{ scope.row.gender | sex }}</div>
  251. </template>
  252. </el-table-column>
  253. <el-table-column
  254. align="center"
  255. prop="phone"
  256. label="联系电话"
  257. >
  258. <template slot-scope="scope">
  259. <copy-text>
  260. {{ scope.row.phone }}
  261. </copy-text>
  262. </template>
  263. </el-table-column>
  264. <el-table-column align="center" label="入团年份">
  265. <template slot-scope="scope">
  266. <div>{{ scope.row.currentGradeDate | dayjsFormat('YYYY年') }}</div>
  267. </template>
  268. </el-table-column>
  269. <el-table-column align="center" label="年级班级">
  270. <template slot-scope="scope">
  271. <div>{{ scope.row.currentGrade + scope.row.currentClass }}</div>
  272. </template>
  273. </el-table-column>
  274. <el-table-column
  275. align="center"
  276. label="专业"
  277. prop="subjectName"
  278. >
  279. <template slot-scope="scope">
  280. <copy-text>
  281. {{ scope.row.subjectName }}
  282. </copy-text>
  283. </template>
  284. </el-table-column>
  285. <el-table-column align="center" prop="studentStatus" label="学员状态">
  286. <template slot-scope="scope">
  287. <div>{{ scope.row.studentStatus | musicGroupStudentType }}</div>
  288. </template>
  289. </el-table-column>
  290. <el-table-column align="center" label="新增学员">
  291. <template slot-scope="scope">
  292. <div>{{ scope.row.isNewStudent | yesOrNo }}</div>
  293. </template>
  294. </el-table-column>
  295. <el-table-column align="center" label="报名缴费">
  296. <template slot-scope="scope">
  297. <div>{{ scope.row.paymentStatus | studentPays }}</div>
  298. </template>
  299. </el-table-column>
  300. <el-table-column align="center" label="是否激活">
  301. <template slot-scope="scope">
  302. <div>{{ scope.row.isActive ? "是" : "否" }}</div>
  303. </template>
  304. </el-table-column>
  305. <el-table-column align="center" label="VIP/网管是否有课">
  306. <template slot-scope="scope">
  307. <div>{{ scope.row.hasCourse ? "是" : "否" }}</div>
  308. </template>
  309. </el-table-column>
  310. <el-table-column
  311. align="center"
  312. label="关心包"
  313. >
  314. <template slot-scope="scope">{{ scope.row.carePackage | studentPackage }}</template>
  315. </el-table-column>
  316. <el-table-column
  317. align="center"
  318. label="加油包"
  319. >
  320. <template slot-scope="scope">{{ scope.row.comeOnPackage | studentPackage }}</template>
  321. </el-table-column>
  322. <el-table-column align="center" label="欠费金额(元)">
  323. <template slot-scope="scope">
  324. <div :class="[scope.row.noPaymentAmount > 0 ? 'error' : null]">{{ scope.row.noPaymentAmount | moneyFormat }}
  325. <!-- musicGroupPaymentCalenderDetail/queryPage/studentList -->
  326. <auth auths="musicGroupPaymentCalenderDetail/queryPage/studentList" :router="['/business/teamDetails']">
  327. <i style="color: #14928A; font-size: 17px;" title="缴费记录" class="el-icon-view" @click="onPaymentDetail(scope.row)"></i>
  328. </auth>
  329. </div>
  330. </template>
  331. </el-table-column>
  332. <el-table-column label="退团原因" align="center">
  333. <template slot-scope="scope">
  334. <div>
  335. <Tooltip :content="scope.row.quitReason" />
  336. </div>
  337. </template>
  338. </el-table-column>
  339. <el-table-column align="center"
  340. fixed="right"
  341. width="360px;"
  342. label="操作">
  343. <template slot-scope="scope">
  344. <div>
  345. <el-button type="text"
  346. v-if="permission('studentManage/queryStudentClassGroup')&&scope.row.studentStatus != 'QUIT'"
  347. @click="lookClass(scope.row)">查看班级</el-button>
  348. <el-button type="text"
  349. v-if="permission('musicGroupPaymentCalender/add') && scope.row.studentStatus == 'APPLY' && scope.row.paymentStatus == '0'"
  350. @click="addPay(scope.row)">添加缴费</el-button>
  351. <el-button type="text"
  352. v-if="permission('musicGroupQuit/directQuitMusicGroup')&&scope.row.studentStatus != 'QUIT'"
  353. @click="quieTeamMask(scope.row)">退团退费</el-button>
  354. <el-button type="text"
  355. v-if="permission('musicGroupQuit/directQuitMusicGroup1')&&scope.row.studentStatus != 'QUIT'"
  356. @click="quieTeam(scope.row)">退团</el-button>
  357. <el-button
  358. type="text"
  359. v-if="permission('visit/add')"
  360. @click="addVisit(scope.row)"
  361. >新增回访</el-button
  362. >
  363. </div>
  364. </template>
  365. </el-table-column>
  366. </el-table>
  367. <pagination
  368. :save-key="saveKey"
  369. sync
  370. :total.sync="rules.total"
  371. :page.sync="rules.page"
  372. :limit.sync="rules.limit"
  373. :page-sizes="rules.page_size"
  374. @pagination="getList"
  375. />
  376. </div>
  377. <el-dialog
  378. title="新增学员"
  379. width="700px"
  380. class="studentInfo"
  381. :visible.sync="addStudentVisible"
  382. >
  383. <el-form
  384. :model="maskForm"
  385. label-position="right"
  386. label-width="120px"
  387. ref="maskForm"
  388. :rules="maskRules"
  389. :inline="true"
  390. >
  391. <el-alert title="基本信息" :closable="false" class="alert" type="info">
  392. </el-alert>
  393. <el-form-item
  394. label="联系电话"
  395. prop="phone"
  396. :rules="[
  397. { required: true, message: '请输入手机号' },
  398. {
  399. pattern: /^1[3456789]\d{9}$/,
  400. message: '请输入正确的手机号',
  401. trigger: 'blur',
  402. },
  403. ]"
  404. >
  405. <el-input
  406. v-model.trim="maskForm.phone"
  407. placeholder="联系电话"
  408. @blur="checkPhone(maskForm.phone)"
  409. ></el-input>
  410. </el-form-item>
  411. <el-form-item label="学员姓名" prop="studentName">
  412. <el-input
  413. v-model.trim="maskForm.studentName"
  414. placeholder="学员姓名"
  415. ></el-input>
  416. </el-form-item>
  417. <el-form-item label="学员性别" prop="sex">
  418. <el-select v-model.trim="maskForm.sex" clearable>
  419. <el-option label="男" :value="1"></el-option>
  420. <el-option label="女" :value="0"></el-option>
  421. </el-select>
  422. </el-form-item>
  423. <el-form-item label="家长姓名" prop="parentName">
  424. <el-input
  425. v-model.trim="maskForm.parentName"
  426. placeholder="家长姓名"
  427. ></el-input>
  428. </el-form-item>
  429. <el-form-item label="年级" prop="currentGradeNum">
  430. <el-select
  431. placeholder="起始年级"
  432. filterable
  433. clearable
  434. v-model.trim="maskForm.currentGradeNum"
  435. >
  436. <el-option v-for="item in gradeList" :key="item.value" :label="item.label" :value="item.value"></el-option>
  437. <!-- <el-option value="一年级" label="一年级"></el-option>
  438. <el-option value="二年级" label="二年级"></el-option>
  439. <el-option value="三年级" label="三年级"></el-option>
  440. <el-option value="四年级" label="四年级"></el-option>
  441. <el-option value="五年级" label="五年级"></el-option>
  442. <el-option value="六年级" label="六年级"></el-option>
  443. <el-option value="初一" label="初一"></el-option>
  444. <el-option value="初二" label="初二"></el-option>
  445. <el-option value="初三" label="初三"></el-option>
  446. <el-option value="高一" label="高一"></el-option>
  447. <el-option value="高二" label="高二"></el-option>
  448. <el-option value="高三" label="高三"></el-option> -->
  449. </el-select>
  450. </el-form-item>
  451. <el-form-item label="班级" prop="course">
  452. <el-input
  453. v-model.trim="maskForm.course"
  454. placeholder="班级"
  455. ></el-input>
  456. </el-form-item>
  457. <el-form-item label="学员声部" prop="sound">
  458. <el-select
  459. v-model.trim="maskForm.sound"
  460. clearable
  461. filterable
  462. @change="onSoundChange"
  463. >
  464. <el-option
  465. v-for="(item, index) in soundList"
  466. :key="index"
  467. :value="item.id"
  468. :label="item.name"
  469. ></el-option>
  470. </el-select>
  471. </el-form-item>
  472. <!-- <el-form-item label="证件号"
  473. prop="id">
  474. <el-input v-model.trim="maskForm.id"></el-input>
  475. </el-form-item>-->
  476. <el-form-item label="出生日期" style="margin-right: 0" prop="timer">
  477. <el-col :span="24">
  478. <el-date-picker v-model.trim="maskForm.timer"
  479. value-format="yyyy-MM-dd"
  480. type="date"
  481. :picker-options="{
  482. firstDayOfWeek:1
  483. }"
  484. placeholder="选择日期"></el-date-picker>
  485. </el-col>
  486. </el-form-item>
  487. </el-form>
  488. <div slot="footer" class="dialog-footer">
  489. <!-- <el-button @click="addStudentVisible = false">取 消</el-button> -->
  490. <el-button type="primary" @click="addStudent">确 定</el-button>
  491. </div>
  492. </el-dialog>
  493. <el-dialog
  494. title="学员所在班级"
  495. width="640px"
  496. :visible.sync="studentClassVisible"
  497. >
  498. <el-form :model="classMask">
  499. <el-form-item label="学生姓名">{{
  500. classMask.studentName
  501. }}</el-form-item>
  502. <el-form-item
  503. label="所在班级"
  504. v-for="(item, index) in classLists"
  505. :key="index"
  506. >{{ item.name }}</el-form-item
  507. >
  508. </el-form>
  509. </el-dialog>
  510. <!-- 退团弹窗 -->
  511. <el-dialog title="退团信息确认" width="640px" :visible.sync="quitVisible">
  512. <el-form :model="quitForm" ref="quitForm" :rules="quitRules">
  513. <el-form-item label="退还课程费用" prop="isRefundCourseFee">
  514. <el-radio v-model.trim="quitForm.isRefundCourseFee" :label="true"
  515. >是</el-radio
  516. >
  517. <el-radio v-model.trim="quitForm.isRefundCourseFee" :label="false"
  518. >否</el-radio
  519. >
  520. </el-form-item>
  521. <el-form-item label="退还乐器费用" prop="isRefundInstrumentFee">
  522. <el-radio v-model.trim="quitForm.isRefundInstrumentFee" :label="true"
  523. >是</el-radio
  524. >
  525. <el-radio v-model.trim="quitForm.isRefundInstrumentFee" :label="false"
  526. >否</el-radio
  527. >
  528. </el-form-item>
  529. <el-form-item label="退还教辅费用" prop="isRefundTeachingAssistantsFee">
  530. <el-radio
  531. v-model.trim="quitForm.isRefundTeachingAssistantsFee"
  532. :label="true"
  533. >是</el-radio
  534. >
  535. <el-radio
  536. v-model.trim="quitForm.isRefundTeachingAssistantsFee"
  537. :label="false"
  538. >否</el-radio
  539. >
  540. </el-form-item>
  541. <el-form-item label="退团原因" prop="reason">
  542. <el-input type="textarea" v-model.trim="quitForm.reason"></el-input>
  543. </el-form-item>
  544. </el-form>
  545. <span slot="footer" class="dialog-footer question">
  546. <div>
  547. <el-popover placement="right" width="500" trigger="click">
  548. <div class="popoverWrap">
  549. <p>乐团退团退费规则:</p>
  550. <p>退还课程费用:缴费总额-已结束课时单价之和</p>
  551. <p>退还乐器费用:报名缴费时缴纳的乐器费用(团购、租金)</p>
  552. <p>退还教辅费用:报名缴费时缴费的教辅费用</p>
  553. </div>
  554. <el-button
  555. type="text"
  556. icon="el-icon-question"
  557. slot="reference"
  558. style="color: red"
  559. >退团退费说明</el-button
  560. >
  561. </el-popover>
  562. </div>
  563. <div>
  564. <el-button @click="quitVisible = false">取 消</el-button>
  565. <el-button type="primary" @click="chioseType">确 定</el-button>
  566. </div>
  567. </span>
  568. </el-dialog>
  569. <el-dialog title="报名二维码" :visible.sync="qrcodeStatus" width="300px">
  570. <div class="left-code">
  571. <h2>学员报名连接</h2>
  572. <div id="qrcode" class="qrcode code" ref="qrCodeUrl"></div>
  573. <p class="code-url" v-if="codeUrl">{{ codeUrl }}</p>
  574. </div>
  575. </el-dialog>
  576. <el-dialog
  577. :visible.sync="timesVisible"
  578. title="查看剩余可排课时长"
  579. >
  580. <times-view
  581. v-if="timesVisible"
  582. @close="timesVisible = false"
  583. />
  584. </el-dialog>
  585. <el-dialog title="修改缴费周期"
  586. :before-close="closePayVisible"
  587. width="600px"
  588. :visible.sync="payVisible">
  589. <el-form :model="payForm"
  590. ref="payForm"
  591. :inline="true">
  592. <el-form-item label="学生姓名"
  593. prop="studentName">
  594. <el-input v-model.trim="payForm.studentName"
  595. disabled></el-input>
  596. </el-form-item>
  597. <br />
  598. <el-form-item label="缴费金额" prop="payMoney">
  599. <el-input
  600. type="number"
  601. v-model.trim="payForm.payMoney"
  602. @mousewheel.native.prevent
  603. ></el-input>
  604. </el-form-item>
  605. <el-form-item label="缴费月份" prop="payMonth">
  606. <el-checkbox-group
  607. v-model.trim="payForm.payMonth"
  608. fill="#14928A"
  609. text-color="#474747"
  610. >
  611. <el-checkbox label="1">一月</el-checkbox>
  612. <el-checkbox label="2">二月</el-checkbox>
  613. <el-checkbox label="3">三月</el-checkbox>
  614. <el-checkbox label="4">四月</el-checkbox>
  615. <el-checkbox label="5">五月</el-checkbox>
  616. <el-checkbox label="6">六月</el-checkbox>
  617. <el-checkbox label="7">七月</el-checkbox>
  618. <el-checkbox label="8">八月</el-checkbox>
  619. <el-checkbox label="9">九月</el-checkbox>
  620. <el-checkbox label="10">十月</el-checkbox>
  621. <el-checkbox label="11">十一月</el-checkbox>
  622. <el-checkbox label="12">十二月</el-checkbox>
  623. </el-checkbox-group>
  624. </el-form-item>
  625. <!-- studentName: '',
  626. payMoney: '',
  627. payMonth-->
  628. </el-form>
  629. <div slot="footer" class="dialog-footer">
  630. <el-button @click="quitVisible = false">取 消</el-button>
  631. <el-button type="primary" @click="submitPay">确 定</el-button>
  632. </div>
  633. </el-dialog>
  634. <el-dialog
  635. title="新增回访"
  636. width="500px"
  637. destroy-on-close
  638. :close-on-click-modal="false"
  639. :visible.sync="visitVisiable"
  640. >
  641. <visit
  642. v-if="visitVisiable && detail"
  643. :detail="detail"
  644. @close="visitVisiable = false"
  645. @submited="getList"
  646. />
  647. </el-dialog>
  648. <el-dialog
  649. title="选择班级"
  650. destroy-on-close
  651. width="700px"
  652. :visible.sync="createUserPayVisible"
  653. >
  654. <createUserPay
  655. :signList="signList"
  656. :mixList="mixList"
  657. :highList="highList"
  658. :snapList="snapList"
  659. :musicGroupId="this.teamid"
  660. :organizationCourseUnitPriceSettings="
  661. organizationCourseUnitPriceSettings
  662. "
  663. :createdUserId="createdUserId"
  664. :baseInfo="baseInfo"
  665. @submited="getList"
  666. @close="createUserPayVisible = false"
  667. />
  668. </el-dialog>
  669. <el-dialog
  670. title="缴费记录"
  671. width="900px"
  672. :visible.sync="paymentDetailVisible"
  673. >
  674. <payment-list
  675. v-if="paymentDetailVisible"
  676. :paymentDetail="paymentDetail"
  677. @close="paymentDetailVisible = false"
  678. />
  679. </el-dialog>
  680. </div>
  681. </template>
  682. <script>
  683. import {
  684. getTeamStudentList,
  685. getTeamStudentInfo,
  686. getSingleClass,
  687. findSound,
  688. StudentQuit,
  689. findSubjectPlan,
  690. getGoods,
  691. getSubject,
  692. getMusicGroup,
  693. getMusicGroupAllClass,
  694. StudentFeeIsLock,
  695. updateStudentFee,
  696. getMusicGroupGradeList
  697. } from "@/api/buildTeam";
  698. import {
  699. addStudent,
  700. getStudentClass,
  701. getStudentInfoByPhone,
  702. } from "@/api/studentManager";
  703. import { getOrganizationCourseUnitPriceSettings } from "@/api/specialSetting";
  704. import { visitChiose } from "@/utils/searchArray";
  705. import pagination from "@/components/Pagination/index";
  706. import { vaildStudentUrl } from "@/utils/validate";
  707. import QRCode from "qrcodejs2";
  708. import axios from "axios";
  709. import { getToken } from "@/utils/auth";
  710. import { permission } from "@/utils/directivePage";
  711. import { addVisit } from "@/views/returnVisitManager/api.js"
  712. import cleanDeep from 'clean-deep'
  713. import createUserPay from './modals/create-user-pay.vue'
  714. import TimesView from './modals/course-time-detail'
  715. import paymentCycle from '../../resetTeaming/modals/payment-cycle'
  716. import paymentList from './modals/payment-list'
  717. import Tooltip from '@/components/Tooltip/index'
  718. import visit from '@/views/withdrawal-application/modals/visit'
  719. export default {
  720. name: "tstudentList",
  721. data() {
  722. return {
  723. detail:null,
  724. teamid: "",
  725. paymentDetailVisible: false,
  726. paymentDetail: {},
  727. payVisible: false,
  728. quitVisible: false, // 退团信息确认的弹窗
  729. studentClassVisible: false, // 学员所在班级弹窗
  730. addStudentVisible: false, //新增学员弹窗
  731. timesVisible: false,
  732. timerDetail: null,
  733. topFrom: {
  734. // 顶部的禁选框集合
  735. expect: "2", // 预期招生
  736. studing: "5", // 在读人数
  737. allmoney: "100", //实收总额
  738. students: "5", // 实际招生人数
  739. signout: "10", // 退团总数
  740. },
  741. searchForm: {
  742. studentStatus: "", // 学生状态
  743. major: "", // 报名专业
  744. isPay: "", // 是否缴费
  745. search: "",
  746. isActive: "",
  747. oweFlag: '',
  748. currentGrade: null,
  749. createYear: null,
  750. classGroupId: null,
  751. hasCourse: null,
  752. carePackage: null,
  753. comeOnPackage: null
  754. },
  755. organizationCourseUnitPriceSettings: [],
  756. quitForm: {
  757. // 退团信息确认
  758. isRefundCourseFee: null,
  759. isRefundInstrumentFee: null,
  760. isRefundTeachingAssistantsFee: null,
  761. reason: "",
  762. },
  763. classMask: {
  764. studentName: "",
  765. },
  766. baseInfo: {},
  767. searchLsit: [],
  768. tableList: [], //
  769. rules: {
  770. // 分页规则
  771. limit: 10, // 限制显示条数
  772. page: 1, // 当前页
  773. total: 0, // 总条数
  774. page_size: [10, 20, 40, 50], // 选择限制显示条数
  775. },
  776. studentListInfo: {
  777. add: "",
  778. quit: "",
  779. studying: "",
  780. courseRate: "",
  781. },
  782. signList: [],
  783. mixList: [],
  784. highList: [],
  785. snapList: [],
  786. soundList: [],
  787. highonlineList: [],
  788. muiscnetworkList: [],
  789. qrcodeStatus: false, // 生成二维码
  790. qrcodes: true,
  791. qrcode: null,
  792. codeUrl: null,
  793. gradeList: [], // 学生
  794. maskForm: {
  795. studentName: "",
  796. sex: "",
  797. parentName: "",
  798. course: "",
  799. phone: "",
  800. sound: "",
  801. timer: "",
  802. signClass: "",
  803. mixClass: "",
  804. highClass: "",
  805. snapClass: [],
  806. highonline: "",
  807. muiscnetwork: "",
  808. startClass: "",
  809. currentGradeNum: null,
  810. id: "",
  811. // courseFee: null, // 声部费用
  812. temporaryCourseFee: null, // 本次课程费用
  813. musicGoodsIdList: null, // 乐器商品编号
  814. kitGroupPurchaseType: "GROUP", // 乐器购买方式
  815. musicPrice: null, // 乐器购买金额
  816. instrGoodsIdList: [], // 辅件商品编号
  817. instrPrice: null, // 辅件购买金额
  818. },
  819. remark: "", // 退团原因
  820. classList: [],
  821. quitRules: {
  822. isRefundCourseFee: [
  823. { required: true, message: "请选择是否退还课程费用" },
  824. ],
  825. isRefundInstrumentFee: [
  826. { required: true, message: "选择是否退还乐器费用" },
  827. ],
  828. isRefundTeachingAssistantsFee: [
  829. { required: true, message: "选择是否退还教辅费用" },
  830. ],
  831. reason: [{ required: true, message: "请填写退团退费原因" }],
  832. },
  833. maskRules: {
  834. studentName: [{ required: true, message: "请输入学生姓名" }],
  835. sex: [{ required: true, message: "请选择学生姓名" }],
  836. parentName: [{ required: true, message: "请输入家长姓名" }],
  837. course: [{ required: true, message: "请输入班级" }],
  838. // phone: [{ required: true, message: '请输入手机号' }, { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }],
  839. sound: [{ required: true, message: "请选择声部" }],
  840. timer: [{ required: true, message: "请选择出生日期" }],
  841. signClass: [{ required: true, message: "请选择声部班" }],
  842. // price: [{ required: true, message: '请输入首缴金额' },],
  843. currentGradeNum: [{ required: true, message: "请选择年级" }],
  844. id: [{ required: true, message: "请输入证件号" }],
  845. // courseFee: [{ required: true, message: "请输入声部费用" }],
  846. temporaryCourseFee: [{ required: true, message: "请输课程费用" }],
  847. musicGoodsIdList: [
  848. { required: true, message: "请选择乐器", trigger: "change" },
  849. ],
  850. musicPrice: [{ required: true, message: "请输入乐器购买金额" }],
  851. instrGoodsIdList: [{ required: true, message: "请选择辅件" }],
  852. instrPrice: [{ required: true, message: "请输入辅件金额" }],
  853. },
  854. INSTRUMENTLIST: [], // 乐器列表
  855. ACCESSORIESLIST: [], // 辅件列表
  856. activeRow: null,
  857. Fsearch: null,
  858. Frules: null,
  859. payForm: {
  860. studentName: "",
  861. payMoney: "",
  862. payMonth: [],
  863. },
  864. kitStatus: false, // 乐器提供方式
  865. // 新增回访记录弹窗
  866. visitVisiable: false,
  867. visitForm: {
  868. musicGroupId: "",
  869. overview: "",
  870. purpose: "",
  871. studentId: "",
  872. type: "",
  873. visitTime: "",
  874. visitType: "",
  875. feedback: "",
  876. studentName: "",
  877. },
  878. cycles: [{}],
  879. collapse: [0],
  880. visitChiose,
  881. visitRules: {
  882. overview: [{ required: true, message: "请输入学生近况" }],
  883. feedback: [{ required: true, message: "请输入家长反馈" }],
  884. visitTime: [{ required: true, message: "请输入回访时间" }],
  885. visitType: [{ required: true, message: "请选择回访类型" }],
  886. },
  887. pickerOptions: null,
  888. classLists: null,
  889. createdUserId: 0,
  890. createUserPayVisible: false,
  891. };
  892. },
  893. components: {
  894. pagination,
  895. paymentCycle,
  896. createUserPay,
  897. Tooltip,
  898. 'times-view': TimesView,
  899. paymentList,
  900. visit
  901. },
  902. created() {
  903. // 判断是否带缓存参数
  904. if (this.$route.query.search) {
  905. this.Fsearch = this.$route.query.search;
  906. }
  907. if (this.$route.query.rules) {
  908. this.Frules = this.$route.query.rules;
  909. }
  910. },
  911. filters: {
  912. studentPays(val) {
  913. let template = {
  914. 0: "未缴费",
  915. 1: "已缴费",
  916. };
  917. return template[val];
  918. }
  919. },
  920. // activated() {
  921. // this.init();
  922. // },
  923. async mounted() {
  924. try {
  925. const res = await getOrganizationCourseUnitPriceSettings({
  926. rows: 9999,
  927. });
  928. this.organizationCourseUnitPriceSettings = res.data.rows;
  929. } catch (error) {}
  930. this.init();
  931. },
  932. methods: {
  933. onPaymentDetail(row) {
  934. this.paymentDetail = row
  935. this.paymentDetailVisible = true
  936. },
  937. viewTimer(row) {
  938. // this.timerDetail = row
  939. this.timesVisible = true
  940. },
  941. permission (str) {
  942. return permission(str);
  943. },
  944. init() {
  945. this.teamid = this.$route.query.id;
  946. getMusicGroupGradeList({ musicGroupId: this.teamid }).then(res => {
  947. let result = res.data
  948. if(res.code == 200 && result) {
  949. for(let i in result) {
  950. this.gradeList.push({
  951. value: i,
  952. label: result[i]
  953. })
  954. }
  955. }
  956. })
  957. // 获取汇总数据
  958. getTeamStudentInfo({ musicGroupId: this.teamid }).then((res) => {
  959. if (res.code == 200) {
  960. this.studentListInfo = res.data;
  961. }
  962. });
  963. this.pickerOptions = this.beginDate();
  964. this.getList();
  965. // 获取乐团内所有声部
  966. findSound({ musicGroupId: this.teamid }).then((res) => {
  967. if (res.code == 200) {
  968. this.soundList = res.data;
  969. }
  970. });
  971. // getSubject().then(res => {
  972. // if (res.code == 200) {
  973. // this.soundList = res.data;
  974. // }
  975. // })
  976. // 获取乐团所有声部课班
  977. // getSingleClass({ musicGroupId: this.teamid }).then(res => {
  978. // if (res.code == 200) {
  979. // this.signList = res.data;
  980. // }
  981. // })
  982. // 获取乐团基本信息
  983. getMusicGroup({ musicGroupId: this.teamid }).then(
  984. (res) => (this.baseInfo = res.data)
  985. );
  986. // 获取乐团所有合奏课
  987. getMusicGroupAllClass({ musicGroupId: this.teamid }).then((res) => {
  988. if (res.code == 200) {
  989. this.classList = res.data;
  990. this.signList = [];
  991. this.mixList = [];
  992. this.highList = [];
  993. this.snapList = [];
  994. this.classList.forEach((item) => {
  995. if (item.type == "NORMAL") {
  996. this.signList.push(item);
  997. } else if (item.type == "MIX") {
  998. this.mixList.push(item);
  999. } else if (item.type == "HIGH") {
  1000. this.highList.push(item);
  1001. } else if (item.type == "SNAP") {
  1002. this.snapList.push(item);
  1003. } else if (item.type == "HIGH_ONLINE") {
  1004. this.highonlineList.push(item);
  1005. } else if (item.type == "MUSIC_NETWORK") {
  1006. this.muiscnetworkList.push(item);
  1007. }
  1008. });
  1009. }
  1010. });
  1011. },
  1012. permission(str) {
  1013. return permission(str);
  1014. },
  1015. onInstrumentChange() {
  1016. // 乐器切换时
  1017. // 乐器切换时
  1018. // let tempkitType = this.maskForm.kitGroupPurchaseType
  1019. // if(tempkitType == 'GROUP') {
  1020. // this.INSTRUMENTLIST.forEach(item => {
  1021. // if(item.value == value) {
  1022. // this.maskForm.musicPrice = item.marketPrice
  1023. // }
  1024. // })
  1025. // }
  1026. },
  1027. onKitGroupChnage(value) {
  1028. // 乐器提供方式
  1029. this.kitStatus = false;
  1030. if (value == "FREE") {
  1031. this.kitStatus = true;
  1032. this.maskForm.musicPrice = 0;
  1033. } else {
  1034. this.maskForm.musicPrice = null;
  1035. }
  1036. },
  1037. onMusicGroupExport() {
  1038. let url = "/api-web/export/musicGroupStudent";
  1039. let data = {
  1040. musicGroupId: this.teamid,
  1041. studentStatus: this.searchForm.studentStatus || null,
  1042. paymentStatus: this.searchForm.isPay || null,
  1043. subjectId: this.searchForm.major || null,
  1044. search: this.searchForm.search || null,
  1045. isActive: this.searchForm.isActive || null,
  1046. classGroupId: this.searchForm.classGroupId || null,
  1047. currentGrade: this.searchForm.currentGrade || null,
  1048. createYear: this.searchForm.createYear || null,
  1049. hasCourse: this.searchForm.hasCourse || null,
  1050. comeOnPackage: this.searchForm.comeOnPackage,
  1051. carePackage: this.searchForm.carePackage,
  1052. };
  1053. const options = {
  1054. method: "get",
  1055. headers: {
  1056. Authorization: getToken(),
  1057. },
  1058. url,
  1059. params: data,
  1060. responseType: "blob",
  1061. };
  1062. this.$confirm("您确定导出学员列表?", "提示", {
  1063. confirmButtonText: "确定",
  1064. cancelButtonText: "取消",
  1065. type: "warning",
  1066. })
  1067. .then(() => {
  1068. axios(options).then((res) => {
  1069. let blob = new Blob([res.data], {
  1070. // type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8',
  1071. type: "application/vnd.ms-excel;charset=utf-8",
  1072. // word文档为application/msword,pdf文档为application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
  1073. });
  1074. let objectUrl = URL.createObjectURL(blob);
  1075. let link = document.createElement("a");
  1076. let fname = this.$route.query.name + "学员列表.xls";
  1077. link.href = objectUrl;
  1078. link.setAttribute("download", fname);
  1079. document.body.appendChild(link);
  1080. link.click();
  1081. });
  1082. })
  1083. .catch(() => {});
  1084. },
  1085. search() {
  1086. this.rules.page = 1;
  1087. this.getList();
  1088. },
  1089. onReSet() {
  1090. this.$refs.searchForm.resetFields()
  1091. this.search()
  1092. },
  1093. onCreateQRCode() {
  1094. // 生成报名二维码
  1095. this.qrcodeStatus = true;
  1096. let id = this.$route.query.id;
  1097. if (this.qrcodes) {
  1098. this.qrcodes = false;
  1099. setTimeout(() => {
  1100. this.qrcode = new QRCode("qrcode", {
  1101. width: 200,
  1102. height: 200,
  1103. colorDark: "#000000",
  1104. colorLight: "#ffffff",
  1105. correctLevel: QRCode.CorrectLevel.H,
  1106. });
  1107. this.qrcode.makeCode(
  1108. vaildStudentUrl() + "/#/login?musicGroupId=" + id
  1109. );
  1110. this.codeUrl = vaildStudentUrl() + "/#/login?musicGroupId=" + id;
  1111. }, 500);
  1112. }
  1113. },
  1114. getList() {
  1115. let obj = {
  1116. musicGroupId: this.teamid,
  1117. page: this.rules.page,
  1118. rows: this.rules.limit,
  1119. studentStatus: this.searchForm.studentStatus || null,
  1120. paymentStatus: this.searchForm.isPay || null,
  1121. subjectId: this.searchForm.major || null,
  1122. search: this.searchForm.search || null,
  1123. isActive: this.searchForm.isActive || null,
  1124. classGroupId: this.searchForm.classGroupId || null,
  1125. currentGrade: this.searchForm.currentGrade || null,
  1126. createYear: this.searchForm.createYear || null,
  1127. oweFlag: this.searchForm.oweFlag || null,
  1128. hasCourse: this.searchForm.hasCourse || null,
  1129. comeOnPackage: this.searchForm.comeOnPackage,
  1130. carePackage: this.searchForm.carePackage,
  1131. };
  1132. getTeamStudentList(obj).then((res) => {
  1133. if (res.code == 200) {
  1134. this.tableList = res.data.rows;
  1135. this.rules.total = res.data.total;
  1136. }
  1137. });
  1138. },
  1139. addPay(row) {
  1140. this.createUserPayVisible = true;
  1141. this.createdUserId = row.userId;
  1142. },
  1143. addCycle() {
  1144. this.cycles.push({});
  1145. this.collapse.push(this.collapse.length);
  1146. },
  1147. removeCycle(index) {
  1148. this.cycles[index] = null;
  1149. this.cycles = this.cycles.filter((item) => !!item);
  1150. this.collapse.pop();
  1151. },
  1152. collapseChange(val) {
  1153. this.collapse = val;
  1154. },
  1155. gotoSignin() {
  1156. this.$router.push({
  1157. path: "/business/studentSignin",
  1158. query: {
  1159. id: this.teamid,
  1160. status: this.$route.query.status,
  1161. name: this.$route.query.name,
  1162. rules: this.Frules,
  1163. search: this.Fsearch,
  1164. },
  1165. });
  1166. },
  1167. chioseType() {
  1168. this.$refs["quitForm"].validate((res) => {
  1169. if (res) {
  1170. this.$confirm("确定退团?", "提示", {
  1171. confirmButtonText: "确定",
  1172. cancelButtonText: "取消",
  1173. type: "warning",
  1174. })
  1175. .then(() => {
  1176. let row = this.activeRow;
  1177. // 发请求 退团
  1178. StudentQuit({
  1179. musicGroupId: this.teamid,
  1180. userId: row.userId,
  1181. reason: this.quitForm.reason,
  1182. isRefundCourseFee: this.quitForm.isRefundCourseFee,
  1183. isRefundInstrumentFee: this.quitForm.isRefundInstrumentFee,
  1184. isRefundTeachingAssistantsFee: this.quitForm
  1185. .isRefundTeachingAssistantsFee,
  1186. }).then((res) => {
  1187. this.quitForm = {
  1188. // 退团信息确认
  1189. isRefundCourseFee: null,
  1190. isRefundInstrumentFee: null,
  1191. isRefundTeachingAssistantsFee: null,
  1192. reason: "",
  1193. };
  1194. if (res.code == 200) {
  1195. this.$message.success("退团成功");
  1196. this.getList();
  1197. this.quitVisible = false;
  1198. }
  1199. });
  1200. })
  1201. .catch(() => {});
  1202. } else {
  1203. }
  1204. });
  1205. // row.typeVisible = false;
  1206. },
  1207. //
  1208. addStudent() {
  1209. // 发请求添加学员
  1210. this.$refs["maskForm"].validate((res) => {
  1211. if (res) {
  1212. // this.maskForm.parentName.timer 少个生日的字段
  1213. // classGroupId: maskForm.signClass
  1214. /** <!-- signClass: '',
  1215. mixClass: '',
  1216. highClass: '',
  1217. snapClass: [], --> */
  1218. let maskForm = this.maskForm;
  1219. // if (
  1220. // !maskForm.signClass &&
  1221. // !maskForm.mixClass &&
  1222. // !maskForm.highClass &&
  1223. // !maskForm.highonline &&
  1224. // !maskForm.muiscnetwork
  1225. // ) {
  1226. // if (
  1227. // !maskForm.snapClass ||
  1228. // !(maskForm.snapClass && maskForm.snapClass.length >= 1)
  1229. // ) {
  1230. // this.$message.error("该学生必须加入一个班级");
  1231. // return;
  1232. // }
  1233. // }
  1234. if (
  1235. maskForm.musicGoodsIdList &&
  1236. (maskForm.musicPrice === "" || maskForm.musicPrice === null)
  1237. ) {
  1238. this.$message.error("请输入乐器金额");
  1239. return;
  1240. }
  1241. if (
  1242. maskForm.instrGoodsIdList &&
  1243. maskForm.instrGoodsIdList.length > 0 &&
  1244. (maskForm.instrPrice === "" || maskForm.instrPrice === null)
  1245. ) {
  1246. this.$message.error("请输入辅件金额");
  1247. return;
  1248. }
  1249. let snapClassIds;
  1250. maskForm.snapClass
  1251. ? (snapClassIds = maskForm.snapClass.join(","))
  1252. : (snapClassIds = null);
  1253. let params = {
  1254. signClassId: maskForm.signClass,
  1255. mixClassId: maskForm.mixClass,
  1256. snapClassIds,
  1257. highClassId: maskForm.highClass,
  1258. courseFee: maskForm.courseFee,
  1259. temporaryCourseFee: maskForm.temporaryCourseFee,
  1260. studentRegistration: {
  1261. name: maskForm.studentName,
  1262. gender: maskForm.sex,
  1263. birthdate: maskForm.timer,
  1264. parentsName: maskForm.parentName,
  1265. parentsPhone: maskForm.phone,
  1266. currentGrade: maskForm.startClass,
  1267. currentGradeNum: maskForm.currentGradeNum,
  1268. currentClass: maskForm.course,
  1269. subjectId: maskForm.sound,
  1270. musicGroupId: this.teamid,
  1271. },
  1272. };
  1273. params.studentPaymentOrderDetails = [];
  1274. if (maskForm.musicGoodsIdList) {
  1275. params.studentPaymentOrderDetails.push({
  1276. goodsIdList: maskForm.musicGoodsIdList,
  1277. kitGroupPurchaseType: maskForm.kitGroupPurchaseType,
  1278. type: "MUSICAL",
  1279. price: maskForm.musicPrice,
  1280. });
  1281. }
  1282. if (maskForm.instrGoodsIdList && maskForm.instrGoodsIdList != "") {
  1283. params.studentPaymentOrderDetails.push({
  1284. goodsIdList: maskForm.instrGoodsIdList.join(","),
  1285. type: "ACCESSORIES",
  1286. price: maskForm.instrPrice,
  1287. });
  1288. }
  1289. addStudent(params).then((res) => {
  1290. if (res.code == 200) {
  1291. this.$message.success("添加学生成功");
  1292. this.getList();
  1293. this.addStudentVisible = false;
  1294. this.createUserPayVisible = true;
  1295. this.createdUserId = res.data;
  1296. }
  1297. this.$refs.maskForm.resetFields();
  1298. });
  1299. }
  1300. });
  1301. },
  1302. onSoundChange(value) {
  1303. // 学员声部切换时
  1304. // this.findSubjectPlan(value)
  1305. this.ACCESSORIESLIST = [];
  1306. this.maskForm.instrGoodsIdList = [];
  1307. this.maskForm.instrPrice = null;
  1308. this.INSTRUMENTLIST = [];
  1309. this.maskForm.musicPrice = null;
  1310. this.maskForm.musicGoodsIdList = null;
  1311. this.getGoodsList(value, "INSTRUMENT"); // 乐器
  1312. this.getGoodsList(value, "ACCESSORIES"); // 辅件
  1313. },
  1314. // 获取购买方式
  1315. findSubjectPlan(subjectId) {
  1316. findSubjectPlan({
  1317. musicGroupId: this.teamid,
  1318. subjectId: subjectId,
  1319. }).then((res) => {
  1320. let result = res.data;
  1321. if (res.code == 200) {
  1322. this.maskForm.musicMode = this.getBranchType(
  1323. result.kitGroupPurchaseType
  1324. );
  1325. }
  1326. });
  1327. },
  1328. getGoodsList(subjectId, type) {
  1329. getGoods({
  1330. subjectId: subjectId,
  1331. type: type,
  1332. }).then((res) => {
  1333. let result = res.data;
  1334. if (res.code == 200) {
  1335. let tempArr = [];
  1336. result.forEach((item) => {
  1337. tempArr.push({
  1338. label: item.name,
  1339. value: item.id,
  1340. marketPrice: item.marketPrice,
  1341. });
  1342. });
  1343. if (type == "ACCESSORIES") {
  1344. this.ACCESSORIESLIST = tempArr;
  1345. }
  1346. if (type == "INSTRUMENT") {
  1347. this.INSTRUMENTLIST = tempArr;
  1348. }
  1349. }
  1350. });
  1351. },
  1352. getBranchType(status) {
  1353. let common = {
  1354. FREE: "免费",
  1355. GROUP: "团购",
  1356. LEASE: "租赁",
  1357. };
  1358. return common[status];
  1359. },
  1360. lookClass(row) {
  1361. this.classMask.studentName = row.realName;
  1362. getStudentClass({
  1363. musicGroupId: this.teamid,
  1364. teacherId: row.userId,
  1365. }).then((res) => {
  1366. if (res.code == 200) {
  1367. this.classLists = res.data;
  1368. this.studentClassVisible = true;
  1369. }
  1370. });
  1371. },
  1372. quieTeamMask(row) {
  1373. this.activeRow = row;
  1374. this.quitVisible = true;
  1375. },
  1376. quieTeam(row) {
  1377. this.$prompt("请输入退团原因", "提示", {
  1378. confirmButtonText: "确定",
  1379. cancelButtonText: "取消",
  1380. type: "warning",
  1381. inputPattern: /\S/,
  1382. inputErrorMessage: "请输入退团原因",
  1383. })
  1384. .then((val) => {
  1385. // 发请求 退团
  1386. StudentQuit({
  1387. musicGroupId: this.teamid,
  1388. userId: row.userId,
  1389. reason: val.value,
  1390. isRefundCourseFee: false,
  1391. isRefundInstrumentFee: false,
  1392. isRefundTeachingAssistantsFee: false,
  1393. }).then((res) => {
  1394. this.quitForm = {
  1395. // 退团信息确认
  1396. isRefundCourseFee: null,
  1397. isRefundInstrumentFee: null,
  1398. isRefundTeachingAssistantsFee: null,
  1399. reason: "",
  1400. };
  1401. if (res.code == 200) {
  1402. this.$message.success("退团成功");
  1403. this.getList();
  1404. this.quitVisible = false;
  1405. }
  1406. });
  1407. })
  1408. .catch(() => {});
  1409. },
  1410. checkPhone(val) {
  1411. var regu = /^1[3456789]\d{9}$/;
  1412. var re = new RegExp(regu);
  1413. if (re.test(val)) {
  1414. getStudentInfoByPhone({ mobile: this.maskForm.phone }).then((res) => {
  1415. if (res.code == 200) {
  1416. if (res.data) {
  1417. this.maskForm.studentName = res.data.name;
  1418. this.maskForm.sex = res.data.gender;
  1419. this.maskForm.parentName = res.data.parentsName;
  1420. this.maskForm.course = res.data.currentClass;
  1421. this.maskForm.startClass = res.data.currentGrade;
  1422. this.maskForm.currentGradeNum = res.data.currentGradeNum;
  1423. this.maskForm.phone = val;
  1424. this.maskForm.timer = res.data.birthdate;
  1425. }
  1426. }
  1427. });
  1428. }
  1429. },
  1430. lockStudent(row) {
  1431. this.$confirm("是否锁定/解锁学生缴费周期?", "提示", {
  1432. confirmButtonText: "确定",
  1433. cancelButtonText: "取消",
  1434. type: "warning",
  1435. })
  1436. .then(() => {
  1437. let musicGroupId = this.teamid;
  1438. let studentId = row.userId;
  1439. let isLock;
  1440. row.isLock == 0 ? (isLock = 1) : (isLock = 0);
  1441. StudentFeeIsLock({ musicGroupId, studentId, isLock }).then((res) => {
  1442. if (res.code == 200) {
  1443. this.$message.success("修改成功");
  1444. this.getList();
  1445. }
  1446. });
  1447. })
  1448. .catch(() => {});
  1449. },
  1450. resetPay(row) {
  1451. this.activeRow = row;
  1452. this.payVisible = true;
  1453. this.payForm.studentName = row.realName;
  1454. this.payForm.payMoney = row.courseFee;
  1455. this.payForm.payMonth = row.paymentPeriodList.split(",");
  1456. if (this.payForm.payMonth[0] == "") {
  1457. this.payForm.payMonth = [];
  1458. }
  1459. },
  1460. submitPay() {
  1461. let studentId = this.activeRow.userId;
  1462. let musicGroupId = this.teamid;
  1463. let month = this.payForm.payMonth.join(",") || null;
  1464. let amount = this.payForm.payMoney;
  1465. let obj = {
  1466. studentId,
  1467. musicGroupId,
  1468. month,
  1469. amount,
  1470. };
  1471. updateStudentFee(obj).then((res) => {
  1472. if (res.code == 200) {
  1473. this.$message.success("修改成功");
  1474. this.payVisible = false;
  1475. this.getList();
  1476. }
  1477. });
  1478. },
  1479. closePayVisible() {
  1480. this.$refs["payForm"].resetFields();
  1481. this.payVisible = false;
  1482. },
  1483. addVisit(row) {
  1484. console.log(row);
  1485. this.detail = row
  1486. // this.visitForm.studentName = row.realName;
  1487. // this.visitForm.musicGroupId = this.teamid;
  1488. // this.visitForm.studentId = row.userId;
  1489. this.visitVisiable = true;
  1490. },
  1491. handleChange(val) {
  1492. this.visitForm.type = val[0];
  1493. this.visitForm.purpose = val[1];
  1494. },
  1495. submitAddVisit() {
  1496. console.log(this.$refs.visitForm);
  1497. this.$refs.visitForm.validate((res) => {
  1498. if (res) {
  1499. addVisit(cleanDeep(this.visitForm)).then((res) => {
  1500. if (res.code === 200) {
  1501. this.$message.success("新增成功");
  1502. this.visitVisiable = false;
  1503. }
  1504. });
  1505. }
  1506. });
  1507. },
  1508. beginDate() {
  1509. let self = this;
  1510. return {
  1511. firstDayOfWeek: 1,
  1512. disabledDate(time) {
  1513. return time.getTime() >= new Date().getTime(); //开始时间不选时,结束时间最大值小于等于当天
  1514. },
  1515. };
  1516. },
  1517. createStudentFrom() {
  1518. this.addStudentVisible = true
  1519. }
  1520. },
  1521. watch: {
  1522. quitVisible(val) {
  1523. if (!val) {
  1524. this.quitForm = {
  1525. // 退团信息确认
  1526. isRefundCourseFee: null,
  1527. isRefundInstrumentFee: null,
  1528. isRefundTeachingAssistantsFee: null,
  1529. reason: "",
  1530. };
  1531. this.$refs["quitForm"].resetFields();
  1532. }
  1533. },
  1534. // visitVisiable(val) {
  1535. // if (!val) {
  1536. // this.$refs["visitForm"].resetFields();
  1537. // }
  1538. // },
  1539. },
  1540. computed:{
  1541. saveKey(){
  1542. // return 'teamDetails-'+this.$route.query.id
  1543. return 'teamDetails-studentList|id|' + this.$route.query.id
  1544. }
  1545. }
  1546. };
  1547. </script>
  1548. <style lang="scss" scoped>
  1549. .dialog-footer.question{
  1550. display: flex;
  1551. flex-direction: row;
  1552. justify-content: space-between;
  1553. }
  1554. // .moreInput {
  1555. // width: 100%;
  1556. // display: flex;
  1557. // /deep/.el-form-item__content {
  1558. // display: flex;
  1559. // flex-direction: row;
  1560. // }
  1561. // }
  1562. .error {
  1563. color: red;
  1564. }
  1565. .el-select {
  1566. width: 180px !important;
  1567. }
  1568. .headWrap {
  1569. padding: 20px 0;
  1570. }
  1571. /deep/.el-date-editor.el-input {
  1572. width: auto;
  1573. .el-input__inner {
  1574. padding-right: 0;
  1575. }
  1576. }
  1577. .studentInfo {
  1578. /deep/.el-dialog__body {
  1579. // padding-top: 0;
  1580. // padding-bottom: 0;
  1581. }
  1582. }
  1583. // .instrList {
  1584. // display: flex;
  1585. // /deep/.el-form-item__content {
  1586. // width: 80%;
  1587. // }
  1588. // .el-col {
  1589. // /deep/.el-form-item__content {
  1590. // width: 100%;
  1591. // }
  1592. // }
  1593. // }
  1594. .stu-container {
  1595. .topFrom {
  1596. margin: 20px 30px 0;
  1597. width: 1000px;
  1598. }
  1599. .newStudent {
  1600. width: 121px;
  1601. height: 40px;
  1602. background: rgba(20, 146, 138, 1);
  1603. border-radius: 4px;
  1604. color: #fff;
  1605. text-align: center;
  1606. line-height: 40px;
  1607. font-size: 14px;
  1608. cursor: pointer;
  1609. }
  1610. }
  1611. .left-code,
  1612. .right-code {
  1613. // width: 50%;
  1614. // float: left;
  1615. h2 {
  1616. display: block;
  1617. font-size: 18px;
  1618. text-align: center;
  1619. padding-bottom: 8px;
  1620. line-height: 1;
  1621. height: 30px;
  1622. margin-bottom: 0;
  1623. }
  1624. .qrcode {
  1625. display: flex;
  1626. justify-content: center;
  1627. img {
  1628. width: 200px;
  1629. height: 200px;
  1630. // margin: 0 auto;
  1631. }
  1632. }
  1633. .code-url {
  1634. font-size: 18px;
  1635. text-align: center;
  1636. padding: 15px 15px 0 15px;
  1637. }
  1638. }
  1639. .export {
  1640. background: #14928a;
  1641. }
  1642. .alert {
  1643. margin-bottom: 10px;
  1644. }
  1645. .collapse-title {
  1646. display: flex;
  1647. justify-content: space-between;
  1648. align-items: center;
  1649. width: 100%;
  1650. .el-icon-circle-close {
  1651. font-size: 16px;
  1652. margin-right: 10px;
  1653. }
  1654. }
  1655. /deep/ .el-collapse-item__wrap {
  1656. padding-top: 20px;
  1657. }
  1658. .cycleForm {
  1659. /deep/ .el-form-item {
  1660. display: flex;
  1661. width: 100%;
  1662. /deep/ .el-form-item__content {
  1663. margin-left: 0 !important;
  1664. flex: 1;
  1665. }
  1666. }
  1667. }
  1668. .statistic {
  1669. padding: 20px 0;
  1670. text-align: center;
  1671. width: 100%;
  1672. margin: auto!important;
  1673. }
  1674. .popoverWrap {
  1675. p{line-height: 25px;}
  1676. }
  1677. .studentListWrap {
  1678. display: flex;
  1679. flex-direction: row;
  1680. justify-content: flex-start;
  1681. height: 36px;
  1682. align-items: center;
  1683. }
  1684. </style>