index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. <template>
  2. <div class="m-container">
  3. <h2>
  4. <div class="squrt"></div>
  5. 退团申请
  6. <auth :auths="['/WithdrawalApplication/abnormal']">
  7. <filter-search
  8. @reload="reloadSearch"
  9. :keys="['visitFlag']"
  10. :moreKeys="['organId']"
  11. />
  12. </auth>
  13. </h2>
  14. <div class="m-core">
  15. <save-form
  16. :inline="true"
  17. @submit="submit"
  18. @reset="onReSet"
  19. ref="searchForm"
  20. :model.sync="searchForm"
  21. >
  22. <el-form-item>
  23. <el-input
  24. v-model.trim="searchForm.search"
  25. clearable
  26. placeholder="学员(乐团)编号、名称"
  27. ></el-input>
  28. </el-form-item>
  29. <el-form-item prop="organId">
  30. <el-select
  31. class="multiple"
  32. style="width: 180px !important"
  33. v-model.trim="searchForm.organId"
  34. filterable
  35. clearable
  36. placeholder="请选择分部"
  37. >
  38. <el-option
  39. v-for="(item, index) in selects.branchs"
  40. :key="index"
  41. :label="item.name"
  42. :value="item.id"
  43. ></el-option>
  44. </el-select>
  45. </el-form-item>
  46. <el-form-item>
  47. <el-select
  48. v-model="searchForm.status"
  49. clearable
  50. placeholder="请选择状态"
  51. >
  52. <el-option
  53. v-for="(item, key) in withdrawalStatus"
  54. :key="key"
  55. :label="item"
  56. :value="key"
  57. ></el-option>
  58. </el-select>
  59. </el-form-item>
  60. <el-form-item>
  61. <el-select
  62. v-model="searchForm.currentApproveRole"
  63. clearable
  64. placeholder="请选择角色"
  65. >
  66. <el-option label="分部经理" value="1"></el-option>
  67. <el-option label="乐团主管" value="2"></el-option>
  68. </el-select>
  69. </el-form-item>
  70. <el-form-item>
  71. <el-button native-type="submit" type="danger">搜索</el-button>
  72. <el-button native-type="reset" type="primary">重置</el-button>
  73. <el-button
  74. @click="onExport"
  75. type="primary"
  76. v-permission="'export/musicGroupQuit'"
  77. >导出</el-button
  78. >
  79. </el-form-item>
  80. </save-form>
  81. <div class="btnList">
  82. <auth :auths="['musicGroupQuit/batchQuitMusicGroup']">
  83. <el-button type="primary" @click="quiteTeamAll">批量处理</el-button>
  84. </auth>
  85. </div>
  86. <el-table
  87. :data="list"
  88. style="width: 100%"
  89. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  90. @selection-change="handleSelectionChange"
  91. >
  92. <el-table-column
  93. type="selection"
  94. width="55"
  95. :selectable="checkSeleabled"
  96. >
  97. </el-table-column>
  98. <el-table-column prop="userId" label="学员编号">
  99. <copy-text slot-scope="scope">{{ scope.row.userId }}</copy-text>
  100. </el-table-column>
  101. <el-table-column prop="userId" label="学员姓名">
  102. <copy-text slot-scope="scope">{{
  103. scope.row.user.username
  104. }}</copy-text>
  105. </el-table-column>
  106. <el-table-column prop="organName" label="所属分部">
  107. <div slot-scope="scope">{{ scope.row.musicGroup.organName }}</div>
  108. </el-table-column>
  109. <el-table-column prop="musicGroupId" label="所属乐团">
  110. <copy-text slot-scope="scope">{{
  111. scope.row.musicGroup.name
  112. }}</copy-text>
  113. </el-table-column>
  114. <el-table-column prop="createTime" label="申请时间">
  115. <template slot-scope="scope">
  116. <div>
  117. {{ scope.row.createTime | dateForMinFormat }}
  118. </div>
  119. </template>
  120. </el-table-column>
  121. <el-table-column prop="applyUserName" label="申请人"></el-table-column>
  122. <el-table-column prop="createTime" label="退费金额">
  123. <template slot-scope="scope">
  124. <div>
  125. <p v-if="!scope.row.returnTotalFee">--</p>
  126. <p v-else>
  127. {{ scope.row.returnTotalFee | moneyFormat }}
  128. </p>
  129. </div>
  130. </template>
  131. </el-table-column>
  132. <el-table-column prop="reasonEnum" label="退团原因">
  133. <template slot-scope="scope">
  134. <p>{{ scope.row.reasonEnum | quiteReasonFilter }}</p>
  135. </template>
  136. </el-table-column>
  137. <el-table-column prop="userComment" label="退团理由">
  138. <overflow-text
  139. width="100%"
  140. slot-scope="scope"
  141. :text="scope.row.userComment"
  142. ></overflow-text>
  143. </el-table-column>
  144. <el-table-column prop="userComment" label="学校审批理由">
  145. <overflow-text
  146. width="100%"
  147. slot-scope="scope"
  148. :text="
  149. scope.row.schoolStaffAuditReason
  150. ? scope.row.schoolStaffAuditReason
  151. : '--'
  152. "
  153. ></overflow-text>
  154. </el-table-column>
  155. <el-table-column label="状态">
  156. <template slot-scope="scope">
  157. <div>
  158. {{ scope.row.status | withdrawalStatus }}
  159. <span v-if="scope.row.status == 'PROCESSING'"
  160. >({{
  161. scope.row.currentApproveRole == 1 ? "分部经理" : "乐团主管"
  162. }})</span
  163. >
  164. </div>
  165. </template>
  166. </el-table-column>
  167. <el-table-column
  168. align="center"
  169. fixed="right"
  170. width="200px;"
  171. label="操作"
  172. v-if="
  173. permission('musicGroupQuit/quitMusicGroup/quit') ||
  174. permission('musicGroupQuit/quitMusicGroup/quit-only') ||
  175. permission('visit/add/tuituanliebiao')
  176. "
  177. >
  178. <template slot-scope="scope">
  179. <div>
  180. <el-button
  181. type="text"
  182. v-if="
  183. permission('musicGroupQuit/quitMusicGroup/quit') && isManage
  184. "
  185. :disabled="
  186. scope.row.status != 'PROCESSING' ||
  187. scope.row.status == 'DENIED' ||
  188. scope.row.status == 'CANCELED' ||
  189. (scope.row.status == 'PROCESSING' &&
  190. isManage == 'manage' &&
  191. scope.row.currentApproveRole == '2') ||
  192. (scope.row.status == 'PROCESSING' &&
  193. isManage == 'staff' &&
  194. scope.row.currentApproveRole == '1')
  195. "
  196. @click="quieTeamMask(scope.row)"
  197. >立即处理</el-button
  198. >
  199. <el-button
  200. type="text"
  201. v-if="
  202. permission('musicGroupQuit/quitMusicGroup/quit') && isManage
  203. "
  204. :disabled="
  205. !(
  206. scope.row.status != 'PROCESSING' ||
  207. scope.row.status == 'DENIED' ||
  208. scope.row.status == 'CANCELED' ||
  209. (scope.row.status == 'PROCESSING' &&
  210. isManage == 'manage' &&
  211. scope.row.currentApproveRole == '2') ||
  212. (scope.row.status == 'PROCESSING' &&
  213. isManage == 'staff' &&
  214. scope.row.currentApproveRole == '1')
  215. )
  216. "
  217. @click="quieTeamMask(scope.row, 'look')"
  218. >查看</el-button
  219. >
  220. <!-- <el-button
  221. type="text"
  222. v-if="permission('musicGroupQuit/quitMusicGroup/quit-only')"
  223. :disabled="scope.row.status != 'PROCESSING'"
  224. @click="quieTeam(scope.row)"
  225. >退团</el-button> -->
  226. <el-button
  227. type="text"
  228. v-if="permission('visit/add/tuituanliebiao')"
  229. @click="addVisit(scope.row)"
  230. >新增回访</el-button
  231. >
  232. </div>
  233. </template>
  234. </el-table-column>
  235. </el-table>
  236. <pagination
  237. sync
  238. :total.sync="rules.total"
  239. :page.sync="rules.page"
  240. :limit.sync="rules.limit"
  241. :page-sizes="rules.page_size"
  242. @pagination="FetchList"
  243. />
  244. </div>
  245. <el-dialog
  246. :title="isDisabled ? '查看' : '立即处理'"
  247. width="700px"
  248. :visible.sync="quitVisible"
  249. >
  250. <quitModal
  251. v-if="quitVisible"
  252. :quitForm="quitForm"
  253. @close="quitVisible = false"
  254. @submited="FetchList"
  255. :isDisabled="isDisabled"
  256. ref="musicForm"
  257. />
  258. <p style="color: red; paddingleft: 150px">退费金额暂不进入账户余额</p>
  259. <span slot="footer" class="dialog-footer question">
  260. <div>
  261. <el-popover placement="right" width="500" trigger="click">
  262. <div class="popoverWrap">
  263. <p>乐团退团退费规则:</p>
  264. <p>退还云练习费用:报名缴费时缴费的云练习费用</p>
  265. <p>退还课程费用:缴费总额-已结束课时单价之和</p>
  266. <p>退还乐器费用:报名缴费时缴纳的乐器费用(团购、租金)</p>
  267. <p>退还教辅费用:报名缴费时缴费的教辅费用</p>
  268. <p v-if="$helpers.tenantId == 1">
  269. 退还乐保费用:报名缴费时缴费的乐保费用
  270. </p>
  271. </div>
  272. <el-button
  273. type="text"
  274. icon="el-icon-question"
  275. slot="reference"
  276. style="color: red"
  277. >退团退费说明</el-button
  278. >
  279. </el-popover>
  280. </div>
  281. <div v-if="!isDisabled">
  282. <el-button
  283. type="primary"
  284. v-permission="'musicGroupQuit/quitMusicGroup'"
  285. v-if="isManage == 'staff'"
  286. @click="submitInfo('PROCESSING')"
  287. >提交审核</el-button
  288. >
  289. <el-button
  290. v-if="isManage == 'super' || isManage == 'manage'"
  291. type="primary"
  292. v-permission="'musicGroupQuit/quitMusicGroup'"
  293. @click="submitInfo('APPROVED')"
  294. >同意</el-button
  295. >
  296. <el-button
  297. type="danger"
  298. v-permission="'musicGroupQuit/quitMusicGroup'"
  299. @click="submitInfo('DENIED')"
  300. >拒绝</el-button
  301. >
  302. </div>
  303. </span>
  304. </el-dialog>
  305. <!-- <el-dialog title="退团" width="500px" :visible.sync="quitOnlyVisible">
  306. <quitOnlyModal
  307. v-if="quitOnlyVisible && detail"
  308. :detail="detail"
  309. @close="quitOnlyVisible = false"
  310. @submited="FetchList"
  311. />
  312. </el-dialog> -->
  313. <el-dialog title="新增回访" width="760px" :visible.sync="visitVisible">
  314. <visit
  315. v-if="visitVisible && detail"
  316. :detail="detail"
  317. @close="visitVisible = false"
  318. @submited="FetchList"
  319. />
  320. </el-dialog>
  321. </div>
  322. </template>
  323. <script>
  324. import pagination from "@/components/Pagination/index";
  325. import { permission } from "@/utils/directivePage";
  326. import quitModal from "@/views/teamDetail/components/modals/quite-team";
  327. import quitOnlyModal from "./modals/quitOnly";
  328. import visit from "./modals/visit";
  329. import { Export } from "@/utils/downLoadFile";
  330. import { quitMusicGroup } from "@/api/journal";
  331. import qs from "qs";
  332. import { musicGroupQuitQeryPage, batchQuitMusicGroup } from "./api";
  333. import cleanDeep from "clean-deep";
  334. import { musicGroupQuit } from "@/api/journal";
  335. import { withdrawalStatus } from "@/constant";
  336. import { quiteReasonFilter } from "@/utils/vueFilter";
  337. let that;
  338. const initSearch = {
  339. search: "",
  340. status: null,
  341. organId: ""
  342. };
  343. export default {
  344. components: { pagination, quitModal, quitOnlyModal, visit },
  345. data() {
  346. return {
  347. withdrawalStatus,
  348. quitVisible: false,
  349. quitOnlyVisible: false,
  350. visitVisible: false,
  351. detail: null,
  352. list: [],
  353. searchForm: {
  354. ...initSearch
  355. },
  356. rules: {
  357. // 分页规则
  358. limit: 10, // 限制显示条数
  359. page: 1, // 当前页
  360. total: 0, // 总条数
  361. page_size: [10, 20, 40, 50] // 选择限制显示条数
  362. },
  363. quitForm: {
  364. // 退团信息确认
  365. isRefundCourseFee: null,
  366. isRefundInstrumentFee: null,
  367. isRefundTeachingAssistantsFee: null,
  368. reason: "",
  369. courseViewType: null,
  370. hasMaintenance: null,
  371. studentName: null,
  372. musicGroupName: null,
  373. isVisit: false,
  374. userComment: null,
  375. schoolStaffAuditReason: null
  376. },
  377. isManage: false,
  378. isDisabled: false,
  379. multipleSelection: []
  380. };
  381. },
  382. async mounted() {
  383. that = this;
  384. let isSuperAdmin = this.$store.getters.isSuperAdmin;
  385. let roles = this.$store.getters.roles; // 岗位
  386. let newRoles = this.$store.getters.newRoles; // 角色 这里判断一半岗位 一半角色 深水炸弹!!!!! 危险 危险 危险
  387. await this.$store.dispatch("setBranchs");
  388. if (isSuperAdmin || newRoles.indexOf(150) != -1) {
  389. console.log("isSuperAdmin");
  390. this.isManage = "super";
  391. } else {
  392. if (roles.indexOf("1") != -1) {
  393. this.isManage = "manage";
  394. }
  395. if (roles.indexOf("2") != -1) {
  396. this.isManage = "staff";
  397. }
  398. }
  399. if (roles.indexOf("1") != -1 && roles.indexOf("2") != -1) {
  400. this.isManage = "super";
  401. }
  402. this.FetchList();
  403. },
  404. methods: {
  405. permission,
  406. reloadSearch() {
  407. this.rules.page = 1;
  408. this.FetchList();
  409. },
  410. submit() {
  411. this.rules.page = 1;
  412. this.FetchList();
  413. },
  414. onReSet() {
  415. this.searchForm = { ...initSearch };
  416. this.submit();
  417. },
  418. async quieTeamMask(row, look) {
  419. await musicGroupQuit({ id: row.id }).then(res => {
  420. if (res.code == 200) {
  421. if (look == "look") {
  422. this.isDisabled = true;
  423. } else {
  424. this.isDisabled = false;
  425. }
  426. this.musicForm = res.data;
  427. this.activeRow = { ...row, ...res.data.returnFeeDto };
  428. this.quitForm.courseViewType = res.data.musicGroup.courseViewType;
  429. this.quitForm.userComment = res.data.userComment;
  430. this.quitForm.isVisit = res.data.isVisit;
  431. this.quitForm.visitTime = res.data.visitTime;
  432. this.quitForm.studentName = res.data.user?.username;
  433. this.quitForm.musicGroupName = res.data.musicGroup?.name;
  434. this.quitForm.hasMaintenance = res.data.hasMaintenance;
  435. this.quitForm.reason = res.data.reason;
  436. this.quitForm.id = res.data.id;
  437. this.quitForm.reasonEnum = res.data.reasonEnum;
  438. this.quitForm.schoolStaffAuditReason =
  439. res.data.schoolStaffAuditReason;
  440. this.quitForm = { ...this.quitForm, ...res.data.returnFeeDto };
  441. console.log(this.quitForm, "this.quitForm");
  442. this.quitVisible = true;
  443. } else {
  444. this.$message.error(res.msg);
  445. }
  446. });
  447. // this.detail = row;
  448. },
  449. quieTeam(row) {
  450. this.quitOnlyVisible = true;
  451. this.detail = row;
  452. },
  453. addVisit(row) {
  454. this.visitVisible = true;
  455. this.detail = row;
  456. },
  457. async FetchList() {
  458. try {
  459. const res = await musicGroupQuitQeryPage({
  460. page: this.rules.page,
  461. rows: this.rules.limit,
  462. visitFlag: this.$route.query.visitFlag,
  463. ...this.searchForm
  464. });
  465. this.rules.total = res.data.total;
  466. this.list = res.data.rows;
  467. } catch (error) {}
  468. },
  469. onExport() {
  470. const { ...rest } = this.searchForm;
  471. Export(
  472. this,
  473. {
  474. url: "/api-web/export/musicGroupQuit",
  475. fileName: "退团申请.xls",
  476. method: "post",
  477. params: qs.stringify({
  478. visitFlag: this.$route.query.visitFlag,
  479. ...rest
  480. })
  481. },
  482. "您确定导出退团申请列表?"
  483. );
  484. },
  485. submitInfo(status) {
  486. this.$confirm("确定此操作吗?", "提示", {
  487. confirmButtonText: "确定",
  488. cancelButtonText: "取消",
  489. type: "warning"
  490. })
  491. .then(async () => {
  492. let query = this.quitForm;
  493. query.status = status;
  494. query.returnFeeDto = {
  495. accessoriesFee: query.accessoriesFee,
  496. courseFee: query.courseFee,
  497. isReturnAccessoriesFee: query.isReturnAccessoriesFee,
  498. isReturnCourseFee: query.isReturnCourseFee,
  499. isReturnMaintenanceFee: query.isReturnMaintenanceFee,
  500. isReturnMemberFee: query.isReturnMemberFee,
  501. isReturnMusicalFee: query.isReturnMusicalFee,
  502. maintenanceFee: query.maintenanceFee,
  503. memberFee: query.memberFee,
  504. musicalFee: query.musicalFee
  505. };
  506. await quitMusicGroup(cleanDeep(query)).then(res => {
  507. this.$message.success("处理成功");
  508. this.activeRow = null;
  509. if (this.$refs["musicForm"].$refs.quitForm) {
  510. this.$refs["musicForm"].$refs.quitForm.resetFields();
  511. }
  512. this.quitVisible = false;
  513. this.FetchList();
  514. });
  515. })
  516. .catch(e => {
  517. console.log(e);
  518. });
  519. // 乐团主管这里
  520. },
  521. handleSelectionChange(val) {
  522. this.multipleSelection = val;
  523. },
  524. quiteTeamAll() {
  525. if (this.multipleSelection.length < 1) {
  526. this.$message.error("请至少选择一名学员");
  527. return;
  528. }
  529. let str = "";
  530. this.multipleSelection.forEach(stu => {
  531. console.log(stu);
  532. str += stu.user.username + ",";
  533. });
  534. str += "的退团申请将批量处理";
  535. this.$prompt(str, "提示", {
  536. distinguishCancelAndClose: true,
  537. confirmButtonText: "同意",
  538. cancelButtonText: "拒绝",
  539. confirmButtonClass: "el-button--primary",
  540. cancelButtonClass: "el-button--danger",
  541. closeOnClickModal: false,
  542. inputPattern: /\S/,
  543. inputType: "textarea",
  544. inputErrorMessage: "请输入审批理由",
  545. inputPlaceholder: "请输入审批理由",
  546. beforeClose: async (val, instance, done) => {
  547. if (val == "confirm") {
  548. // reason
  549. let objList = this.multipleSelection.map(stu => {
  550. return {
  551. id: stu.id,
  552. status: "APPROVED",
  553. reason: instance.inputValue
  554. };
  555. });
  556. try {
  557. const res = await batchQuitMusicGroup(objList);
  558. this.$message.success("审批成功");
  559. done();
  560. this.FetchList();
  561. } catch (e) {
  562. console.log(e);
  563. }
  564. } else if (val == "cancel") {
  565. instance.validate();
  566. let objList = this.multipleSelection.map(stu => {
  567. return {
  568. id: stu.id,
  569. status: "DENIED",
  570. reason: instance.inputValue
  571. };
  572. });
  573. try {
  574. const res = await batchQuitMusicGroup(objList);
  575. this.$message.success("审批成功");
  576. done();
  577. this.FetchList();
  578. } catch (e) {
  579. console.log(e);
  580. }
  581. } else {
  582. done();
  583. }
  584. }
  585. })
  586. .then(() => {
  587. // 同意
  588. })
  589. .catch(msg => {
  590. // close,cancel
  591. console.log(msg);
  592. });
  593. },
  594. checkSeleabled(row) {
  595. // if (row.status == "PROCESSING" && row.currentApproveRole == "1") {
  596. // return 1;
  597. // } else {
  598. // return 0;
  599. // }
  600. if (
  601. row.status != "PROCESSING" ||
  602. row.status == "DENIED" ||
  603. row.status == "CANCELED" ||
  604. (row.status == "PROCESSING" &&
  605. this.isManage == "manage" &&
  606. row.currentApproveRole == "2") ||
  607. (row.status == "PROCESSING" &&
  608. this.isManage == "staff" &&
  609. row.currentApproveRole == "1")
  610. ) {
  611. return 0;
  612. } else {
  613. return 1;
  614. }
  615. }
  616. }
  617. };
  618. </script>
  619. <style lang="scss" scoped>
  620. .dialog-footer.question {
  621. display: flex;
  622. flex-direction: row;
  623. justify-content: space-between;
  624. }
  625. .btnList {
  626. margin-bottom: 20px;
  627. }
  628. .confirmButton {
  629. color: #fff;
  630. background-color: #f56c6c;
  631. border-color: #f56c6c;
  632. }
  633. .cancelButton {
  634. color: #fff;
  635. background-color: var(--color-primary);
  636. border-color: var(--color-primary);
  637. }
  638. </style>