accompanyList.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. <template>
  2. <div class>
  3. <!-- <h2>
  4. <div class="squrt"></div>网管课列表
  5. </h2>-->
  6. <div class="topWrap">
  7. <div class="newBand"
  8. v-permission="'export/practiceGroup'"
  9. @click="onStudentExport"
  10. style="width: 120px;">网管课续费提醒</div>
  11. <div class="newBand"
  12. v-permission="'export/practiceGroupList'"
  13. @click="onPracticeExport"
  14. style="width: 120px;">网管课导出</div>
  15. </div>
  16. <div class="m-core">
  17. <save-form :inline="true"
  18. class="searchForm"
  19. @submit="search"
  20. @reset="onReSet"
  21. :model.sync="searchForm">
  22. <!-- 状态 指导老师 活动方案-->
  23. <el-form-item>
  24. <el-input v-model.trim="searchForm.search"
  25. clearable
  26. placeholder="课程组名称"></el-input>
  27. </el-form-item>
  28. <el-form-item>
  29. <el-select class="multiple"
  30. v-model.trim="searchForm.organIdList"
  31. filterable
  32. clearable
  33. placeholder="请选择分部">
  34. <el-option v-for="(item,index) in selects.branchs"
  35. :key="index"
  36. :label="item.name"
  37. :value="item.id"></el-option>
  38. </el-select>
  39. </el-form-item>
  40. <el-form-item>
  41. <el-select v-model.trim="searchForm.practiceGroupType"
  42. clearable
  43. filterable
  44. placeholder="课程组类型">
  45. <el-option v-for="(item,index) in practiceGroupType"
  46. :key="index"
  47. :value="item.value"
  48. :label="item.label"></el-option>
  49. </el-select>
  50. </el-form-item>
  51. <el-form-item prop="status">
  52. <el-select class="multiple"
  53. v-model.trim="searchForm.hasEducationalTeacherId"
  54. filterable
  55. clearable
  56. placeholder="是否有乐团主管">
  57. <el-option label="是"
  58. value="true"></el-option>
  59. <el-option label="否"
  60. value="false"></el-option>
  61. </el-select>
  62. </el-form-item>
  63. <el-form-item>
  64. <el-select v-model.trim="searchForm.teacherId"
  65. clearable
  66. filterable
  67. :filter-method="filterMethod"
  68. placeholder="指导老师">
  69. <el-option v-for="(item,index) in selects.teachers"
  70. :key="index"
  71. :value="item.id"
  72. :label="item.realName"></el-option>
  73. </el-select>
  74. </el-form-item>
  75. <el-form-item>
  76. <el-select v-model.trim="searchForm.groupStatus"
  77. clearable
  78. filterable
  79. placeholder="课程组状态">
  80. <el-option v-for="(item,index) in commGroupStatus"
  81. :key="index"
  82. :value="item.value"
  83. :label="item.label"></el-option>
  84. </el-select>
  85. </el-form-item>
  86. <el-form-item>
  87. <el-select v-model.trim="searchForm.firstOrRenew"
  88. clearable
  89. filterable
  90. placeholder="是否续费">
  91. <el-option label="首充"
  92. value="1"></el-option>
  93. <el-option label="续费"
  94. value="0"></el-option>
  95. <el-option label="免费"
  96. value="2"></el-option>
  97. </el-select>
  98. </el-form-item>
  99. <el-form-item>
  100. <el-button native-type="submit"
  101. type="danger">搜索</el-button>
  102. <el-button native-type="reset"
  103. type="primary">重置</el-button>
  104. </el-form-item>
  105. </save-form>
  106. <!-- tab -->
  107. <div class="tableWrap">
  108. <el-table style="width: 100%"
  109. :header-cell-style="{background:'#EDEEF0',color:'#444'}"
  110. :data="tableData">
  111. <el-table-column align="center"
  112. prop="id"
  113. label="课程组编号"
  114. width="100">
  115. <template slot-scope="scope">
  116. <copy-text>{{scope.row.id}}</copy-text>
  117. </template>
  118. </el-table-column>
  119. <el-table-column align="center"
  120. prop="name"
  121. label="课程组名称"
  122. width="100">
  123. <template slot-scope="scope">
  124. <copy-text>{{scope.row.name}}</copy-text>
  125. </template>
  126. </el-table-column>
  127. <el-table-column align="center"
  128. prop="type"
  129. label="课程组类型"
  130. width="100">
  131. <template slot-scope="scope">
  132. <div>
  133. <p>{{scope.row.type | comType}}</p>
  134. </div>
  135. </template>
  136. </el-table-column>
  137. <el-table-column align="center"
  138. prop="organName"
  139. label="所属分部"></el-table-column>
  140. <!-- educationalTeacherId -->
  141. <el-table-column align="center"
  142. prop="educationalTeacherName"
  143. label="乐团主管"></el-table-column>
  144. <el-table-column align="center"
  145. prop="teacherName"
  146. label="指导老师"></el-table-column>
  147. <el-table-column align="center"
  148. prop="studentNum"
  149. label="班级人数"></el-table-column>
  150. <!-- <el-table-column align="center" label="课程单价">
  151. <template slot-scope="scope">
  152. <div>
  153. <p>线上:{{scope.row.onlineClassesUnitPrice}}</p>
  154. <p>线下:{{scope.row.offlineClassesUnitPrice}}</p>
  155. </div>
  156. </template>
  157. </el-table-column>-->
  158. <el-table-column align="center"
  159. label="当前课次">
  160. <template slot-scope="scope">
  161. <div>
  162. <p>{{scope.row.currentClassTimes + '/' + scope.row.totalClassTimes}}</p>
  163. </div>
  164. </template>
  165. </el-table-column>
  166. <el-table-column align="center"
  167. prop="coursesStartDate"
  168. label="开课时间"
  169. width="120">
  170. <template slot-scope="scope">
  171. <div>
  172. <p>{{scope.row.coursesStartDate | formatTimer}}</p>
  173. </div>
  174. </template>
  175. </el-table-column>
  176. <el-table-column align="center"
  177. prop="coursesExpireDate"
  178. label="结束时间"
  179. width="120">
  180. <template slot-scope="scope">
  181. <div>
  182. <p>{{scope.row.coursesExpireDate | formatTimer}}</p>
  183. </div>
  184. </template>
  185. </el-table-column>
  186. <el-table-column align="center"
  187. prop="groupStatus"
  188. label="课程组状态"
  189. width="100">
  190. <template slot-scope="scope">
  191. <div>
  192. <p>{{scope.row.groupStatus | comCourseGroup}}</p>
  193. </div>
  194. </template>
  195. </el-table-column>
  196. <el-table-column align="center"
  197. label="是否续费"
  198. fixed="right">
  199. <template slot-scope="scope">
  200. <div>
  201. <p v-if="scope.row.buyMonths == 0">免费</p>
  202. <p v-if="scope.row.buyMonths > 0">{{scope.row.beRenewGroupId>0?'续费':'首充'}}</p>
  203. </div>
  204. </template>
  205. </el-table-column>
  206. <el-table-column width="150"
  207. prop="memo"
  208. label="备注"
  209. fixed="right">
  210. <template slot-scope="scope">
  211. <overflow-text :text="scope.row.memo" width="150px"></overflow-text>
  212. </template>
  213. </el-table-column>
  214. <el-table-column align="center"
  215. width="200"
  216. fixed="right"
  217. label="操作">
  218. <template slot-scope="scope">
  219. <div>
  220. <!-- v-permission="'courseSchedule/classStartDateAdjust'" v-if="!scope.row.isSettlement" -->
  221. <el-button type="text"
  222. @click="lookCrouse(scope.row)">查看</el-button>
  223. <el-button type="text"
  224. v-if="scope.row.groupStatus == 'NORMAL' && permission('practiceGroupManage/cancelGroup')"
  225. @click="closeCrouse(scope.row)">关闭</el-button>
  226. <el-button type="text"
  227. v-if="permission('practiceGroupManage/updateMemo')"
  228. @click="resetMemo(scope.row)">修改备注</el-button>
  229. </div>
  230. </template>
  231. </el-table-column>
  232. </el-table>
  233. <pagination :total="rules.total"
  234. :page.sync="rules.page"
  235. :limit.sync="rules.limit"
  236. :page-sizes="rules.page_size"
  237. @pagination="getList" />
  238. </div>
  239. </div>
  240. <el-dialog title="关闭课程组"
  241. width="400px"
  242. :visible.sync="closeVisible">
  243. <el-form :model="closeForm"
  244. ref="closeForm"
  245. label-position="right"
  246. label-width="80px;"
  247. :inline="true">
  248. <el-form-item label="是否退费"
  249. prop="isBasck">
  250. <el-radio v-model="closeForm.isBack"
  251. :label="true">是</el-radio>
  252. <el-radio v-model="closeForm.isBack"
  253. :label="false">否</el-radio>
  254. </el-form-item>
  255. <el-form-item label="退费金额"
  256. v-if="closeForm.isBack"
  257. prop="money">
  258. <el-input type="number"
  259. @mousewheel.native.prevent
  260. v-model.trim="closeForm.money"></el-input>
  261. </el-form-item>
  262. </el-form>
  263. <div slot="footer"
  264. class="dialog-footer">
  265. <el-button @click="closeVisible = false">取 消</el-button>
  266. <el-button type="primary"
  267. @click="submieCloseCrouse">确 定</el-button>
  268. </div>
  269. </el-dialog>
  270. <el-dialog title="备注"
  271. width="400px"
  272. :visible.sync="memoVisible">
  273. <el-input type="textarea"
  274. v-model.trim="memoForm.memo"
  275. :rows="7"
  276. :maxlength="255"
  277. show-word-limit></el-input>
  278. <div slot="footer"
  279. class="dialog-footer">
  280. <el-button @click="memoVisible = false">取 消</el-button>
  281. <el-button type="primary"
  282. @click="subMemo">确 定</el-button>
  283. </div>
  284. </el-dialog>
  285. </div>
  286. </template>
  287. <script>
  288. import pagination from "@/components/Pagination/index";
  289. import { permission } from "@/utils/directivePage";
  290. import cleanDeep from 'clean-deep'
  291. import { commGroupStatus, practiceGroupType } from "@/utils/searchArray";
  292. import {
  293. getTeacher,
  294. getEmployeeOrgan,
  295. practiceGroupManage,
  296. cancelGroup,
  297. practiceUpdateMemo
  298. } from "@/api/buildTeam";
  299. import axios from "axios";
  300. import { getToken } from "@/utils/auth";
  301. import load from "@/utils/loading";
  302. export default {
  303. components: { pagination },
  304. data () {
  305. return {
  306. searchForm: {
  307. search: null,
  308. status: null,
  309. teacherId: null,
  310. organIdList: null,
  311. firstOrRenew: null,
  312. practiceGroupType: null,
  313. groupStatus: null
  314. },
  315. closeForm: {
  316. isBack: false,
  317. money: null
  318. },
  319. memoForm: {
  320. memo: "",
  321. groupId: ""
  322. },
  323. memoVisible: false,
  324. closeVisible: false,
  325. activeRow: null,
  326. organList: [],
  327. statusList: [],
  328. teacherList: [],
  329. tableData: [],
  330. practiceGroupType: practiceGroupType,
  331. commGroupStatus: commGroupStatus,
  332. rules: {
  333. // 分页规则
  334. limit: 10, // 限制显示条数
  335. page: 1, // 当前页
  336. total: 0, // 总条数
  337. page_size: [10, 20, 40, 50] // 选择限制显示条数
  338. }
  339. };
  340. },
  341. mounted () {
  342. if (this.$route.query.searchForm) {
  343. this.$route.query.searchForm instanceof Object
  344. ? (this.searchForm = this.$route.query.searchForm)
  345. : (this.searchForm = JSON.parse(this.$route.query.searchForm));
  346. }
  347. if (this.$route.query.rules) {
  348. this.$route.query.rules instanceof Object
  349. ? (this.rules = this.$route.query.rules)
  350. : (this.rules = JSON.parse(this.$route.query.rules));
  351. }
  352. this.init();
  353. },
  354. activated () {
  355. this.init();
  356. },
  357. methods: {
  358. filterMethod(inp) {
  359. this.teacherList = this.selects.teachers.filter(item => (item.realName || '').indexOf(inp) > -1).slice(0, 49)
  360. },
  361. init () {
  362. this.$store.dispatch('setBranchs')
  363. this.$store.dispatch('setTeachers')
  364. .then(() => {
  365. this.teacherList = [...this.selects.teachers].slice(0, 49)
  366. })
  367. this.getList();
  368. },
  369. permission (str, parent) {
  370. return permission(str, parent);
  371. },
  372. search () {
  373. this.rules.page = 1;
  374. this.getList();
  375. },
  376. onReSet () {
  377. this.searchForm = {
  378. search: null,
  379. status: null,
  380. teacherId: null,
  381. organIdList: null,
  382. firstOrRenew: null,
  383. practiceGroupType: null,
  384. groupStatus: null
  385. };
  386. this.search();
  387. },
  388. onStudentExport () {
  389. // 导出VIP课
  390. // let searchForm = this.searchForm;
  391. let data = {
  392. // teacherId: searchForm.teacherId || null,
  393. // activityId: searchForm.activityId || null,
  394. // organId: searchForm.orgin || null,
  395. // status: searchForm.status || null,
  396. // search: searchForm.search || null
  397. };
  398. let url = "/api-web/export/practiceGroup";
  399. const options = {
  400. method: "get",
  401. headers: {
  402. Authorization: getToken()
  403. },
  404. params: data,
  405. url,
  406. responseType: "blob"
  407. };
  408. this.$confirm("网管课续费提醒导出?", "提示", {
  409. confirmButtonText: "确定",
  410. cancelButtonText: "取消",
  411. type: "warning"
  412. })
  413. .then(() => {
  414. load.startLoading();
  415. axios(options)
  416. .then(res => {
  417. let blob = new Blob([res.data], {
  418. // type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
  419. type: "application/vnd.ms-excel;charset=utf-8"
  420. //word文档为application/msword,pdf文档为application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
  421. });
  422. let text = new Response(blob).text();
  423. text.then(res => {
  424. // 判断是否报错
  425. if (res.indexOf("code") != -1) {
  426. let json = JSON.parse(res);
  427. this.$message.error(json.msg);
  428. } else {
  429. let objectUrl = URL.createObjectURL(blob);
  430. let link = document.createElement("a");
  431. let fname = "网管课续费提醒" + new Date().getTime(); //下载文件的名字
  432. link.href = objectUrl;
  433. link.setAttribute("download", fname);
  434. document.body.appendChild(link);
  435. link.click();
  436. }
  437. });
  438. load.endLoading();
  439. })
  440. .catch(error => {
  441. this.$message.error("导出数据失败,请联系管理员");
  442. load.endLoading();
  443. });
  444. })
  445. .catch(() => { });
  446. },
  447. onPracticeExport () {
  448. // 导出VIP课
  449. let searchForm = this.searchForm;
  450. let obj = {
  451. search: searchForm.search || null,
  452. teacherId: searchForm.teacherId || null,
  453. organId: searchForm.organIdList || null,
  454. hasEducationalTeacherId: searchForm.hasEducationalTeacherId || null,
  455. type: searchForm.firstOrRenew || null,
  456. practiceGroupType: searchForm.practiceGroupType || null,
  457. groupStatus: searchForm.groupStatus || null
  458. };
  459. let url = "/api-web/export/practiceGroupList";
  460. const options = {
  461. method: "get",
  462. headers: {
  463. Authorization: getToken()
  464. },
  465. params: cleanDeep(obj),
  466. url,
  467. responseType: "blob"
  468. };
  469. this.$confirm("网管课导出?", "提示", {
  470. confirmButtonText: "确定",
  471. cancelButtonText: "取消",
  472. type: "warning"
  473. })
  474. .then(() => {
  475. load.startLoading();
  476. axios(options)
  477. .then(res => {
  478. let blob = new Blob([res.data], {
  479. // type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
  480. type: "application/vnd.ms-excel;charset=utf-8"
  481. //word文档为application/msword,pdf文档为application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
  482. });
  483. let text = new Response(blob).text();
  484. text.then(res => {
  485. // 判断是否报错
  486. if (res.indexOf("code") != -1) {
  487. let json = JSON.parse(res);
  488. this.$message.error(json.msg);
  489. } else {
  490. let objectUrl = URL.createObjectURL(blob);
  491. let link = document.createElement("a");
  492. let fname = "网管课" + new Date().getTime(); //下载文件的名字
  493. link.href = objectUrl;
  494. link.setAttribute("download", fname);
  495. document.body.appendChild(link);
  496. link.click();
  497. }
  498. });
  499. load.endLoading();
  500. })
  501. .catch(error => {
  502. this.$message.error("导出数据失败,请联系管理员");
  503. load.endLoading();
  504. });
  505. })
  506. .catch(() => { });
  507. },
  508. getList () {
  509. let obj = {
  510. search: this.searchForm.search || null,
  511. teacherId: this.searchForm.teacherId || null,
  512. organId: this.searchForm.organIdList || null,
  513. page: this.rules.page,
  514. rows: this.rules.limit,
  515. hasEducationalTeacherId:
  516. this.searchForm.hasEducationalTeacherId || null,
  517. type: this.searchForm.firstOrRenew || null,
  518. practiceGroupType: this.searchForm.practiceGroupType || null,
  519. groupStatus: this.searchForm.groupStatus || null
  520. };
  521. practiceGroupManage(obj).then(res => {
  522. if (res.code == 200) {
  523. this.tableData = res.data.rows;
  524. this.rules.total = res.data.total;
  525. }
  526. });
  527. },
  528. lookCrouse (row) {
  529. let rules = JSON.stringify(this.rules);
  530. let searchForm = JSON.stringify(this.searchForm);
  531. this.$router.push({
  532. path: "/business/accompanys",
  533. query: { id: row.id, type: row.type }
  534. });
  535. },
  536. closeCrouse (row) {
  537. this.activeRow = row;
  538. this.closeVisible = true;
  539. },
  540. courseVisibleClose () {
  541. // 关闭弹窗前
  542. },
  543. submieCloseCrouse () {
  544. // 提交关闭课程组
  545. if (this.closeForm.isBack) {
  546. if (!this.closeForm.money) {
  547. this.$message.error("请输入退费金额");
  548. return;
  549. }
  550. } else {
  551. this.closeForm.money = null;
  552. }
  553. // 请求数据
  554. cancelGroup({
  555. groupId: this.activeRow.id,
  556. groupType: "PRACTICE",
  557. refundAmount: this.closeForm.money
  558. }).then(res => {
  559. if (res.code == 200) {
  560. this.$message.success("关闭成功");
  561. this.getList();
  562. this.closeVisible = false;
  563. }
  564. });
  565. },
  566. resetMemo (row) {
  567. this.$set(this.memoForm, "memo", row.memo);
  568. this.$set(this.memoForm, "groupId", row.id);
  569. this.memoVisible = true;
  570. },
  571. subMemo () {
  572. practiceUpdateMemo(this.memoForm).then(res => {
  573. if (res.code == 200) {
  574. this.$message.success("修改成功");
  575. this.memoVisible = false;
  576. this.getList();
  577. }
  578. });
  579. }
  580. },
  581. watch: {
  582. closeVisible (val) {
  583. if (!val) {
  584. this.activeRow = null;
  585. (this.closeForm = {
  586. isBack: false,
  587. money: null
  588. }),
  589. this.$refs.closeForm.resetFields();
  590. this.closeVisible = false;
  591. }
  592. }
  593. }
  594. };
  595. </script>
  596. <style lang='scss' scoped>
  597. .topWrap {
  598. display: flex;
  599. flex-direction: row;
  600. justify-content: flex-start;
  601. div {
  602. margin-right: 10px;
  603. }
  604. }
  605. </style>