vipStudentList.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. <template>
  2. <div>
  3. <div class="newBand"
  4. v-permission="'vipGroupManage/addVipGroupStudents'"
  5. @click="addStudentList">新增学员</div>
  6. <div class="tableWrap">
  7. <el-table :data='tableList'
  8. :header-cell-style="{background:'#EDEEF0',color:'#444'}">
  9. <el-table-column label="学员姓名"
  10. prop="userName"
  11. align="center"
  12. width="180">
  13. </el-table-column>
  14. <el-table-column label="手机号"
  15. align="center"
  16. prop="phone"
  17. width="180">
  18. </el-table-column>
  19. <el-table-column prop="studentStatus"
  20. align="center"
  21. label="学员状态">
  22. <template slot-scope="scope">
  23. <div>
  24. {{ scope.row.studentStatus | studentStatus }}
  25. </div>
  26. </template>
  27. </el-table-column>
  28. <el-table-column prop="courseSalary"
  29. align="center"
  30. label="课程余额"></el-table-column>
  31. <el-table-column prop="applyDate"
  32. align="center"
  33. label="报名时间">
  34. <template slot-scope="scope">
  35. <div>
  36. {{scope.row.applyDate |formatTimer }}
  37. </div>
  38. </template>
  39. </el-table-column>
  40. <el-table-column prop="refundDate"
  41. align="center"
  42. label="退课时间">
  43. <template slot-scope="scope">
  44. <div>
  45. {{scope.row.refundDate |formatTimer }}
  46. </div>
  47. </template>
  48. </el-table-column>
  49. <el-table-column label="操作"
  50. align="center">
  51. <template slot-scope="scope">
  52. <div>
  53. <!-- <el-popover placement="top"
  54. width="160"
  55. trigger="click"
  56. :ref="scope.$index">
  57. <p>请输入退费金额</p>
  58. <el-input style="margin:10px 0;"
  59. type="number"
  60. v-model.trim="scope.row.fee"></el-input>
  61. <div style="text-align: right; margin-top: 20px">
  62. <el-button size="mini"
  63. type="text"
  64. @click="scope._self.$refs[scope.$index].doClose()">取消</el-button>
  65. <el-button type="primary"
  66. size="mini"
  67. @click="leaveSchool(scope)">确定</el-button>
  68. </div>
  69. <el-button type="text"
  70. slot="reference"
  71. @click="lookFee(scope)">退学</el-button>
  72. </el-popover> -->
  73. <el-button type="text"
  74. v-if="scope.row.studentStatus == 0 || scope.row.studentStatus == 3"
  75. v-permission="'vipGroupManage/applyRefundForStudent'"
  76. @click="lookFee(scope)">退学</el-button>
  77. <!-- v-permission="'vipGroupManage/applyRefundForStudent'" -->
  78. <el-button type="text"
  79. v-if="scope.row.studentStatus == 0"
  80. @click="stopCourse(scope)">休学</el-button>
  81. <el-button type="text"
  82. v-if="scope.row.studentStatus == 3"
  83. @click="recoveryCourse(scope)">恢复</el-button>
  84. </div>
  85. </template>
  86. </el-table-column>
  87. </el-table>
  88. </div>
  89. <el-dialog title="学员列表"
  90. width="70%"
  91. :visible.sync="maskVisible">
  92. <el-form :model="maskForm"
  93. :inline="true">
  94. <el-form-item>
  95. <el-input placeholder="请输入学生姓名或手机号"
  96. @keyup.enter.native='search'
  97. v-model.trim='maskForm.search'></el-input>
  98. </el-form-item>
  99. <el-form-item>
  100. <el-button type="danger"
  101. @click="search">搜索</el-button>
  102. </el-form-item>
  103. <el-form-item>
  104. <el-button type="primary"
  105. @click="reset">重置</el-button>
  106. </el-form-item>
  107. </el-form>
  108. <el-table :data="maskStudentList"
  109. :header-cell-style="{background:'#EDEEF0',color:'#444'}">
  110. <el-table-column label=""
  111. width="55">
  112. <template slot-scope="scope">
  113. <el-radio v-model.trim="activeStudent"
  114. :label="scope.row.id"
  115. @change.native="getTemplateRow(scope.$index,scope.row)">&nbsp</el-radio>
  116. </template>
  117. </el-table-column>
  118. <el-table-column prop="userName"
  119. align="center"
  120. label="学生姓名"
  121. width="150"></el-table-column>
  122. <el-table-column prop="phone"
  123. align="center"
  124. label="手机号"
  125. width="200"></el-table-column>
  126. <el-table-column prop="courseSalary"
  127. label="课程余额"></el-table-column>
  128. </el-table>
  129. <pagination :total="rules.total"
  130. :page.sync="rules.page"
  131. :limit.sync="rules.limit"
  132. :page-sizes="rules.page_size"
  133. @pagination="getList" />
  134. <div slot="footer"
  135. class="dialog-footer">
  136. <el-button @click="maskVisible = false">取 消</el-button>
  137. <el-button type="primary"
  138. @click="addStudent">确 定</el-button>
  139. </div>
  140. </el-dialog>
  141. <el-dialog title="学员复学"
  142. width="800px"
  143. :visible.sync="adjustmentVisible">
  144. <el-form :model='adjustmentForm'
  145. label-position="right"
  146. label-width="120px"
  147. ref='adjustmentForm'
  148. :rules="adjustmentRules"
  149. :inline="true">
  150. <el-form-item label="剩余课时">
  151. <el-input disabled
  152. v-model.trim="adjustmentForm.count"></el-input>
  153. </el-form-item>
  154. <el-form-item label="任课老师"
  155. prop="teacher">
  156. <el-select v-model.trim="adjustmentForm.teacher"
  157. clearable
  158. filterable>
  159. <el-option v-for="(item,index) in teacherList"
  160. :key="index"
  161. :label="item.realName"
  162. :value="item.id"></el-option>
  163. </el-select>
  164. </el-form-item>
  165. <!-- <br> -->
  166. <!-- <el-form-item label="单课费用"
  167. prop="fee">
  168. <el-input v-model.trim="adjustmentForm.fee"></el-input>
  169. </el-form-item> -->
  170. <!-- <el-form-item label="课程类型"
  171. prop="courseType">
  172. <el-select clearable
  173. v-model.trim="adjustmentForm.courseType">
  174. <el-option label="线上课"
  175. value="ONLINE"></el-option>
  176. <el-option label="线下课"
  177. value="OFFLINE"></el-option>
  178. </el-select>
  179. </el-form-item> -->
  180. <br>
  181. <el-form-item label="排课起始时间"
  182. prop="courseTime">
  183. <el-date-picker v-model.trim="adjustmentForm.courseTime"
  184. :picker-options="pickerOptions"
  185. style="width:200px!important;"
  186. type="date"
  187. value-format="yyyy-MM-dd"
  188. placeholder="选择日期">
  189. </el-date-picker>
  190. <el-checkbox style='margin-left:10px;'
  191. v-model.trim="adjustmentForm.checked">是否跳过节假日</el-checkbox>
  192. </el-form-item>
  193. </el-form>
  194. <div class="WeekWrap ">
  195. <h3 style="margin-bottom:20px;">循环次数 <el-button type="text"
  196. style='margin-left:10px;'
  197. @click="addWeek">添加</el-button>
  198. </h3>
  199. <div class="countWrap"
  200. style="margin-bottom:10px;">
  201. <div class="countItem"
  202. style="margin-bottom:20px;"
  203. v-for="(item,index) in weekList"
  204. :key="index">
  205. <span>循环周期: </span>
  206. <el-select v-model.trim="item.dayOfWeek"
  207. filterable
  208. clearable>
  209. <el-option v-for="(item,index) in weekDateList"
  210. :key='index'
  211. :label="item.label"
  212. :value="item.value"></el-option>
  213. </el-select>
  214. <span style="margin-left:10px;">开始时间</span>
  215. <el-time-select style="margin-left:10px;"
  216. placeholder=""
  217. v-model.trim="item.startClassTime"
  218. :picker-options="{
  219. start: '04:30',
  220. step: '00:05',
  221. end: '23:55'
  222. }">
  223. </el-time-select>
  224. <el-button style="margin-left:10px;"
  225. type="danger"
  226. @click="removeWeek(item)"
  227. icon="el-icon-delete"
  228. circle></el-button>
  229. </div>
  230. </div>
  231. </div>
  232. <div slot="footer"
  233. class="dialog-footer">
  234. <el-button @click="adjustmentVisible = false">取 消</el-button>
  235. <el-button type="primary"
  236. @click="submieRecover">确 定</el-button>
  237. </div>
  238. </el-dialog>
  239. </div>
  240. </template>
  241. <script>
  242. import pagination from '@/components/Pagination/index'
  243. import { findVipGroupStudents, leaveSchool, getStudentSurplusCourseFee, getHaveCourseBalanceStudents, addVipGroupStudents, vipPauseForStudent, getStudentPauseInfo, recoverForStudent, findTeacherWithVipGroupOrganAndSubject } from '@/api/vipSeting'
  244. export default {
  245. components: { pagination },
  246. data () {
  247. return {
  248. adjustmentVisible: false,
  249. tableList: [],
  250. id: '',
  251. maskStudentList: [],
  252. maskVisible: false,
  253. rules: {
  254. // 分页规则
  255. limit: 10, // 限制显示条数
  256. page: 1, // 当前页
  257. total: 0, // 总条数
  258. page_size: [10, 20, 40, 50] // 选择限制显示条数
  259. },
  260. activeStudent: '',
  261. maskForm: {
  262. search: ''
  263. },
  264. adjustmentForm: {
  265. count: '',
  266. courseTime: '',
  267. checked: false,
  268. addCount: '',
  269. courseType: '',
  270. fee: '',
  271. teacher: ''
  272. },
  273. adjustmentRules: {
  274. courseTime: [{ required: true, message: '请选择开始时间' }],
  275. addCount: [{ required: true, message: '请输入加课次数' }],
  276. courseType: [{ required: true, message: '请选择课程类型' }],
  277. fee: [{ required: true, message: '请输入费用' }],
  278. teacher: [{ required: true, message: '请选择老师' }]
  279. },
  280. weekDateList: [
  281. { value: '1', label: '星期一' },
  282. { value: '2', label: '星期二' },
  283. { value: '3', label: '星期三' },
  284. { value: '4', label: '星期四' },
  285. { value: '5', label: '星期五' },
  286. { value: '6', label: '星期六' },
  287. { value: '7', label: '星期日' },
  288. ],
  289. weekList: [{
  290. dayOfWeek: '',
  291. startTime: '',
  292. endTime: '',
  293. moid: new Date().getTime()
  294. }],
  295. pickerOptions: {
  296. disabledDate (time) {
  297. return time.getTime() + 86400000 <= new Date().getTime()
  298. }
  299. },
  300. teacherList: []
  301. }
  302. },
  303. mounted () {
  304. this.__init()
  305. },
  306. activated () {
  307. this.__init()
  308. },
  309. methods: {
  310. __init () {
  311. let id = this.$route.query.id;
  312. this.id = id;
  313. this.getStudents()
  314. findTeacherWithVipGroupOrganAndSubject({ vipGroupId: this.id }).then(res => {
  315. if (res.code == 200) {
  316. this.teacherList = res.data;
  317. }
  318. })
  319. },
  320. search () {
  321. this.rules.page = 1;
  322. this.getList()
  323. },
  324. reset () {
  325. this.rules.page = 1;
  326. this.maskForm.search = null;
  327. this.activeStudent = '';
  328. this.getList();
  329. },
  330. getStudents () {
  331. findVipGroupStudents({ vipGroupId: this.id }).then(res => {
  332. if (res.code == 200) {
  333. this.tableList = res.data.rows;
  334. for (let i in this.tableList) {
  335. this.tableList[i].fee = 0;
  336. this.tableList[i].visible = false;
  337. }
  338. }
  339. })
  340. },
  341. // 删除循环周
  342. removeWeek (item) {
  343. for (let i in this.weekList) {
  344. if (this.weekList[i].id == item.id) {
  345. this.weekList.splice(i, 1)
  346. }
  347. }
  348. },
  349. leaveSchool (scope) {
  350. let studentId = scope.row.id;
  351. let vipGroupId = this.id;
  352. let amount = scope.row.fee;
  353. leaveSchool({ studentId, vipGroupId, amount }).then(res => {
  354. if (res.code == 200) {
  355. this.$message.success('退学成功')
  356. this.getStudents();
  357. }
  358. })
  359. },
  360. lookFee (scope) {
  361. this.$confirm(`确定是否退学?`, '提示', {
  362. confirmButtonText: '确定',
  363. cancelButtonText: '取消',
  364. type: 'warning'
  365. }).then(() => {
  366. let id = scope.row.id;
  367. if (scope.row.studentStatus == 3) {
  368. this.leaveSchool(scope);
  369. } else {
  370. getStudentSurplusCourseFee({ studentId: id, vipGroupId: this.id }).then(res => {
  371. if (res.code == 200) {
  372. // scope.row.fee =
  373. this.$prompt('请输入退课金额', '提示', {
  374. confirmButtonText: '确定',
  375. cancelButtonText: '取消',
  376. inputValue: res.data.suplusCourseFee
  377. }).then(({ value }) => {
  378. scope.row.fee = value;
  379. this.leaveSchool(scope);
  380. }).catch(res => {
  381. })
  382. }
  383. })
  384. }
  385. }).catch(() => { })
  386. },
  387. addStudentList () {
  388. // 发请求 搜索学生
  389. // if (this.tableList.length <= 0) {
  390. // this.$confirm('添加学员后,该课程组将无法通过购买途径加入,是否确认该操作?', '提示', {
  391. // confirmButtonText: '确定',
  392. // cancelButtonText: '取消',
  393. // type: 'warning'
  394. // }).then(() => {
  395. // this.getList();
  396. // }).catch(() => { })
  397. // } else {
  398. // this.getList();
  399. // }
  400. this.getList();
  401. },
  402. getList () {
  403. let search = this.maskForm.search || null;
  404. getHaveCourseBalanceStudents({ organId: null, page: this.rules.page, rows: this.rules.limit, search }).then(res => {
  405. if (res.code == 200) {
  406. this.rules.total = res.data.total;
  407. this.maskStudentList = res.data.rows;
  408. this.maskVisible = true;
  409. }
  410. })
  411. },
  412. getTemplateRow (index, row) {
  413. this.activeStudent = row.id;
  414. },
  415. addStudent () {
  416. if (!this.activeStudent) {
  417. this.$message.error('请选择一名学生');
  418. return
  419. }
  420. addVipGroupStudents({ vipGroupId: this.id, studentIds: this.activeStudent }).then(res => {
  421. if (res.code == 200) {
  422. this.$message.success('添加成功')
  423. this.getStudents()
  424. }
  425. })
  426. },
  427. stopCourse (scope) {
  428. this.$confirm('是否休学?', '提示', {
  429. confirmButtonText: '确定',
  430. cancelButtonText: '取消',
  431. type: 'warning'
  432. }).then(() => {
  433. // 发请求 申请休学
  434. vipPauseForStudent({ vipGroupId: this.id, studentId: scope.row.id }).then(res => {
  435. if (res.code == 200) {
  436. this.$message.success('休学成功')
  437. this.getStudents()
  438. }
  439. })
  440. }).catch(() => {
  441. });
  442. },
  443. recoveryCourse (scope) {
  444. getStudentPauseInfo({ studentId: scope.row.id, vipGroupId: this.id }).then(res => {
  445. if (res.code == 200) {
  446. if (res.data.isPause == 0) {
  447. // vip状态没暂停 不需要排课
  448. // 课程编号 学生编号
  449. this.$confirm('将按照当前剩余课时安排上课', '提示', {
  450. confirmButtonText: '确定',
  451. cancelButtonText: '取消',
  452. type: 'warning'
  453. }).then(() => {
  454. // 发请求 恢复上课
  455. recoverForStudent({ vipGroupId: this.id, userId: scope.row.id }).then(res => {
  456. if (res.code == 200) {
  457. this.adjustmentVisible = false;
  458. this.getStudents()
  459. }
  460. })
  461. }).catch(() => {
  462. });
  463. } else {
  464. this.activeStudent = res.data.studentId
  465. this.adjustmentVisible = true;
  466. this.adjustmentForm.teacher = res.data.teacherId;
  467. this.adjustmentForm.count = `${res.data.totalCourseTimes}+${res.data.giveCourseTimes}`
  468. }
  469. }
  470. })
  471. // this.$confirm('是否休学?', '提示', {
  472. // confirmButtonText: '确定',
  473. // cancelButtonText: '取消',
  474. // type: 'warning'
  475. // }).then(() => {
  476. // // 发请求 申请休学
  477. // vipPauseForStudent({ vipGroupId: this.id, studentId: scope.row.id }).then(res => {
  478. // if (res.code == 200) {
  479. // this.$message.success('休学成功')
  480. // this.getList()
  481. // }
  482. // })
  483. // }).catch(() => {
  484. // });
  485. },
  486. addWeek () {
  487. // 添加循环周期
  488. this.weekList.push({
  489. dayOfWeek: '',
  490. startClassTime: '',
  491. endClassTime: '',
  492. id: new Date()
  493. })
  494. },
  495. submieRecover () {
  496. if (this.weekList.length <= 0) {
  497. this.$message.error('排课循环次数不能为空')
  498. return
  499. }
  500. this.$refs['adjustmentForm'].validate(res => {
  501. if (res) {
  502. // 发请求
  503. let obj = {}
  504. obj.courseCreateStartTime = this.adjustmentForm.courseTime;
  505. obj.skipHoliday = this.adjustmentForm.checked;
  506. obj.teacherId = this.adjustmentForm.teacher;
  507. obj.userId = this.activeStudent;
  508. obj.courseTimes = [];
  509. obj.courseTimes = this.weekList
  510. obj.vipGroupId = this.id
  511. recoverForStudent(obj).then(res => {
  512. if (res.code == 200) {
  513. this.adjustmentVisible = false;
  514. this.getStudents()
  515. }
  516. })
  517. } else {
  518. this.$message.error('请填写必要参数')
  519. }
  520. })
  521. this.activeStudent;
  522. }
  523. },
  524. }
  525. </script>
  526. <style lang="scss" scoped>
  527. </style>