memberList.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. <!-- -->
  2. <template>
  3. <div class="m-container">
  4. <h2>
  5. <div class="squrt"></div>
  6. 乐团会员列表
  7. </h2>
  8. <div class="m-core">
  9. <save-form
  10. :inline="true"
  11. :model="searchForm"
  12. ref="searchForm"
  13. @submit="search"
  14. @reset="onReSet"
  15. >
  16. <el-form-item prop="search">
  17. <el-input
  18. v-model.trim="searchForm.search"
  19. clearable
  20. @keyup.enter.native="
  21. e => {
  22. e.target.blur();
  23. $refs.searchForm.save();
  24. search();
  25. }
  26. "
  27. placeholder="乐团/学员名称编号"
  28. ></el-input>
  29. </el-form-item>
  30. <!-- <el-form-item>
  31. <el-input
  32. v-model.trim="searchForm.search"
  33. @keyup.enter.native="search"
  34. placeholder="学员姓名/编号"
  35. ></el-input>
  36. </el-form-item> -->
  37. <el-form-item prop="organId">
  38. <el-select
  39. class="multiple"
  40. filterable
  41. v-model.trim="searchForm.organId"
  42. clearable
  43. placeholder="请选择分部"
  44. >
  45. <el-option
  46. v-for="(item, index) in selects.branchs"
  47. :key="index"
  48. :label="item.name"
  49. :value="item.id"
  50. ></el-option>
  51. </el-select>
  52. </el-form-item>
  53. <el-form-item prop="hasMember">
  54. <el-select
  55. class="multiple"
  56. v-model.trim="searchForm.hasMember"
  57. placeholder="会员状态"
  58. >
  59. <el-option label="已过期" value="0"></el-option>
  60. <el-option label="即将过期" value="1"></el-option>
  61. <el-option label="待生效" value="2"></el-option>
  62. <el-option label="生效中" value="3"></el-option>
  63. </el-select>
  64. </el-form-item>
  65. <el-form-item prop="visitTime">
  66. <el-date-picker
  67. v-model.trim="searchForm.visitTime"
  68. style="width: 410px"
  69. type="daterange"
  70. value-format="yyyy-MM-dd"
  71. :picker-options="{
  72. firstDayOfWeek: 1
  73. }"
  74. range-separator="至"
  75. start-placeholder="回访开始日期"
  76. end-placeholder="回访结束日期"
  77. ></el-date-picker>
  78. </el-form-item>
  79. <!-- <el-form-item prop="isActive">
  80. <el-select
  81. class="multiple"
  82. v-model.trim="searchForm.isActive"
  83. clearable
  84. placeholder="会员是否即将过期"
  85. >
  86. <el-option label="是" value="true"></el-option>
  87. <el-option label="否" value="false"></el-option>
  88. </el-select>
  89. </el-form-item> -->
  90. <el-form-item>
  91. <el-button native-type="submit" type="primary">搜索</el-button>
  92. <el-button native-type="reset" type="danger">重置</el-button>
  93. </el-form-item>
  94. </save-form>
  95. <div class="tableWrap">
  96. <el-table
  97. style="width: 100%"
  98. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  99. :data="tableList"
  100. >
  101. <el-table-column
  102. align="center"
  103. prop="userId"
  104. label="学员编号"
  105. ></el-table-column>
  106. <el-table-column
  107. align="center"
  108. prop="username"
  109. label="学员姓名"
  110. ></el-table-column>
  111. <el-table-column
  112. align="center"
  113. prop="phone"
  114. label="手机号"
  115. ></el-table-column>
  116. <el-table-column
  117. align="center"
  118. prop="organName"
  119. label="所属分部"
  120. ></el-table-column>
  121. <el-table-column
  122. align="center"
  123. prop="musicGroupName"
  124. label="所属乐团"
  125. >
  126. <template slot-scope="scope">
  127. <el-button
  128. type="text"
  129. @click="gotoMusic(scope.row.musicGroupName)"
  130. >
  131. {{ scope.row.musicGroupName }}
  132. </el-button>
  133. </template>
  134. </el-table-column>
  135. <el-table-column align="center" prop="studentId" label="会员状态">
  136. <template slot-scope="scope">
  137. <div>
  138. {{ scope.row.hasMember | hasMemberFilter }}
  139. </div>
  140. </template>
  141. </el-table-column>
  142. <el-table-column
  143. align="center"
  144. prop="memberDay"
  145. label="会员有效期剩余天数"
  146. >
  147. <template slot-scope="scope">
  148. <div>
  149. {{ scope.row.memberDay >= 0 ? scope.row.memberDay : 0 }}
  150. </div>
  151. </template>
  152. </el-table-column>
  153. <el-table-column align="center" prop="memberDay" label="回访日期">
  154. <template slot-scope="scope">
  155. <div>
  156. {{ scope.row.visitTime | dayjsFormat }}
  157. </div>
  158. </template>
  159. </el-table-column>
  160. <el-table-column align="center" prop="studentId" label="操作">
  161. <template slot-scope="scope">
  162. <div>
  163. <!-- addVisit -->
  164. <auth :auths="'visit/add/4465'">
  165. <el-button type="text" @click="addVisit(scope.row)"
  166. >新增回访</el-button
  167. >
  168. </auth>
  169. <auth :auths="'visit/queryPage'" v-if="scope.row.visitTime">
  170. <el-button type="text" @click="lookVisit(scope.row)"
  171. >查看回访</el-button
  172. >
  173. </auth>
  174. <auth :auths="'musicGroupQuit/directQuitMusicGroup4463'">
  175. <el-button type="text" @click="quitTeam(scope.row)"
  176. >退团退费</el-button
  177. >
  178. </auth>
  179. <auth :auths="'musicGroupQuit/directQuitMusicGroup4462'">
  180. <el-button type="text" @click="onekeyquickTeams(scope.row)"
  181. >退团</el-button
  182. >
  183. </auth>
  184. </div>
  185. </template>
  186. </el-table-column>
  187. </el-table>
  188. <pagination
  189. sync
  190. :total.sync="rules.total"
  191. :page.sync="rules.page"
  192. :limit.sync="rules.limit"
  193. :page-sizes="rules.page_size"
  194. @pagination="getList"
  195. />
  196. </div>
  197. </div>
  198. <!-- 退团弹窗 -->
  199. <el-dialog title="退团信息确认" width="660px" :visible.sync="quitVisible">
  200. <quiteTeam :quitForm="quitForm" :activeRow="activeRow" ref="quitForm" />
  201. <p style="color: red; paddingleft: 150px">退费金额暂不进入账户余额</p>
  202. <span slot="footer" class="dialog-footer question">
  203. <div>
  204. <el-popover placement="right" width="500" trigger="click">
  205. <div class="popoverWrap">
  206. <p>乐团退团退费规则:</p>
  207. <p>退还学练宝费用:报名缴费时缴费的学练宝费用</p>
  208. <p>退还课程费用:缴费总额-已结束课时单价之和</p>
  209. <p>退还乐器费用:报名缴费时缴纳的乐器费用(团购、租金)</p>
  210. <p>退还教辅费用:报名缴费时缴费的教辅费用</p>
  211. <p v-if="tenantId == 1">退还乐保费用:报名缴费时缴费的乐保费用</p>
  212. </div>
  213. <el-button
  214. type="text"
  215. icon="el-icon-question"
  216. slot="reference"
  217. style="color: red"
  218. >退团退费说明</el-button
  219. >
  220. </el-popover>
  221. </div>
  222. <div>
  223. <el-button @click="quitVisible = false">取 消</el-button>
  224. <el-button type="primary" @click="chioseType">确 定</el-button>
  225. </div>
  226. </span>
  227. </el-dialog>
  228. <!-- 退团 -->
  229. <el-dialog title="一键退团" width="660px" :visible.sync="onekeyQuitVisible">
  230. <el-form
  231. :model="quitForm"
  232. ref="onekeyQuitForm"
  233. label-width="150px"
  234. :inline="true"
  235. >
  236. <el-row>
  237. <el-col :span="10">
  238. <el-form-item label="学员姓名">
  239. <span>{{ quitForm.studentName }}</span>
  240. </el-form-item>
  241. </el-col>
  242. <el-col :span="12">
  243. <el-form-item label="乐团名称">
  244. <overflow-text
  245. :text="quitForm.musicGroupName"
  246. width="150px"
  247. ></overflow-text>
  248. <!-- <span>{{}}</span> -->
  249. </el-form-item>
  250. </el-col>
  251. </el-row>
  252. <el-row>
  253. <el-form-item
  254. label="退团原因"
  255. prop="reasonEnum"
  256. :rules="[{ required: true, message: '请选择退团原因' }]"
  257. >
  258. <el-radio-group v-model="quitForm.reasonEnum" :disabled="false">
  259. <el-radio-button
  260. :label="item.value"
  261. v-for="(item, index) in quiteReasonList"
  262. :key="index"
  263. >{{ item.label }}</el-radio-button
  264. >
  265. </el-radio-group>
  266. </el-form-item>
  267. </el-row>
  268. <el-form-item
  269. label="审批理由"
  270. prop="reason"
  271. :rules="[{ required: true, message: '请输入退团理由' }]"
  272. >
  273. <el-input
  274. :disabled="false"
  275. type="textarea"
  276. :rows="3"
  277. v-model.trim="quitForm.reason"
  278. style="width: 455px !important"
  279. ></el-input>
  280. </el-form-item>
  281. </el-form>
  282. <span slot="footer" class="dialog-footer question">
  283. <div>
  284. <el-button @click="onekeyQuitVisible = false">取 消</el-button>
  285. <el-button type="primary" @click="quieTeams">确 定</el-button>
  286. </div>
  287. </span>
  288. </el-dialog>
  289. <!-- 新增回访 -->
  290. <el-dialog
  291. title="新增回访"
  292. width="760px"
  293. :visible.sync="visitVisible"
  294. append-to-body
  295. >
  296. <visit
  297. v-if="visitVisible && activeRow"
  298. :detail="activeRow"
  299. :username="activeRow.username"
  300. @close="visitVisible = false"
  301. @submited="getList"
  302. :useVisitType="['其它', '会员续费']"
  303. />
  304. </el-dialog>
  305. <el-dialog title="退团信息确认" width="660px" :visible.sync="quitVisible">
  306. <quiteTeam :quitForm="quitForm" :activeRow="activeRow" ref="quitForm" />
  307. <p style="color: red; paddingleft: 150px">退费金额暂不进入账户余额</p>
  308. <span slot="footer" class="dialog-footer question">
  309. <div>
  310. <el-popover placement="right" width="500" trigger="click">
  311. <div class="popoverWrap">
  312. <p>乐团退团退费规则:</p>
  313. <p>退还学练宝费用:报名缴费时缴费的学练宝费用</p>
  314. <p>退还课程费用:缴费总额-已结束课时单价之和</p>
  315. <p>退还乐器费用:报名缴费时缴纳的乐器费用(团购、租金)</p>
  316. <p>退还教辅费用:报名缴费时缴费的教辅费用</p>
  317. <p v-if="tenantId == 1">退还乐保费用:报名缴费时缴费的乐保费用</p>
  318. </div>
  319. <el-button
  320. type="text"
  321. icon="el-icon-question"
  322. slot="reference"
  323. style="color: red"
  324. >退团退费说明</el-button
  325. >
  326. </el-popover>
  327. </div>
  328. <div>
  329. <el-button @click="quitVisible = false">取 消</el-button>
  330. <el-button type="primary" @click="chioseType">确 定</el-button>
  331. </div>
  332. </span>
  333. </el-dialog>
  334. </div>
  335. </template>
  336. <script>
  337. import axios from "axios";
  338. import { getToken } from "@/utils/auth";
  339. import pagination from "@/components/Pagination/index";
  340. import quiteTeam from "@/views/teamDetail/components/modals/quite-team";
  341. import { StudentQuit } from "@/api/buildTeam";
  342. import load from "@/utils/loading";
  343. import { getMusicMemberList } from "./api";
  344. import visit from "@/views/withdrawal-application/modals/visit";
  345. import { getTimes } from "@/utils";
  346. import { quiteReasonList } from "@/utils/searchArray";
  347. export default {
  348. components: { pagination, quiteTeam, visit },
  349. data() {
  350. return {
  351. searchForm: {
  352. search: null,
  353. organId: null,
  354. hasMember: "0",
  355. visitTime: []
  356. },
  357. tableList: [{}],
  358. organList: [],
  359. rules: {
  360. // 分页规则
  361. limit: 10, // 限制显示条数
  362. page: 1, // 当前页
  363. total: 0, // 总条数
  364. page_size: [10, 20, 40, 50] // 选择限制显示条数
  365. },
  366. quitForm: {
  367. // 退团信息确认
  368. studentName: null,
  369. musicGroupName: null,
  370. isRefundCourseFee: null,
  371. isRefundInstrumentFee: null,
  372. isRefundTeachingAssistantsFee: null,
  373. isMaintenanceFee: null,
  374. cloudTeacherAmount: null,
  375. isCloudTeacherAmount: null,
  376. isRefundMemberFee: null,
  377. maintenanceFee: 0,
  378. reason: ""
  379. },
  380. quitVisible: false,
  381. activeRow: null,
  382. visitVisible: false,
  383. tenantId: "",
  384. onekeyQuitVisible: false,
  385. quiteReasonList
  386. };
  387. },
  388. //生命周期 - 创建完成(可以访问当前this实例)
  389. created() {},
  390. //生命周期 - 挂载完成(可以访问DOM元素)
  391. mounted() {
  392. // 获取分部
  393. this.tenantId = this.$helpers.tenantId;
  394. this.$store.dispatch("setBranchs");
  395. this.init();
  396. },
  397. methods: {
  398. init() {
  399. if (this.$route.query.hasMember) {
  400. this.$set(this.searchForm, "hasMember", this.$route.query.hasMember);
  401. }
  402. this.getList();
  403. },
  404. async getList() {
  405. // 设置时间
  406. let { visitTime, ...rest } = this.searchForm;
  407. try {
  408. const res = await getMusicMemberList({
  409. ...rest,
  410. ...getTimes(visitTime, ["visitStartTime", "visitEndTime"]),
  411. page: this.rules.page,
  412. rows: this.rules.limit
  413. });
  414. this.tableList = res.data.rows;
  415. this.rules.total = res.data.total;
  416. } catch (e) {
  417. console.log(e);
  418. }
  419. },
  420. search() {
  421. this.rules.page = 1;
  422. this.getList();
  423. },
  424. onReSet() {
  425. this.$refs["searchForm"].resetFields();
  426. this.search();
  427. },
  428. quitTeam(row) {
  429. this.activeRow = row;
  430. this.quitVisible = true;
  431. this.quitForm.cloudTeacherAmount = row.cloudTeacherAmount;
  432. this.quitForm.studentName = row.username;
  433. this.quitForm.musicGroupName = row.musicGroupName;
  434. },
  435. onekeyquickTeams(row) {
  436. this.quitForm.cloudTeacherAmount = row.cloudTeacherAmount;
  437. this.quitForm.studentName = row.username;
  438. this.quitForm.musicGroupName = row.musicGroupName;
  439. this.activeRow = row;
  440. this.onekeyQuitVisible = true;
  441. },
  442. quieTeams() {
  443. this.$refs.onekeyQuitForm.validate(res => {
  444. if (!res) {
  445. return;
  446. }
  447. StudentQuit({
  448. musicGroupId: this.activeRow.musicGroupId,
  449. userId: this.activeRow.userId,
  450. reason: this.quitForm.reason,
  451. reasonEnum: this.quitForm.reasonEnum,
  452. isRefundCourseFee: false,
  453. isRefundInstrumentFee: false,
  454. isRefundTeachingAssistantsFee: false,
  455. isRefundMemberFee: false
  456. }).then(res => {
  457. this.quitForm = {
  458. // 退团信息确认
  459. isRefundCourseFee: null,
  460. isRefundInstrumentFee: null,
  461. isRefundTeachingAssistantsFee: null,
  462. isMaintenanceFee: null,
  463. cloudTeacherAmount: null,
  464. isCloudTeacherAmount: null,
  465. isRefundMemberFee: null,
  466. maintenanceFee: 0,
  467. reason: "",
  468. reasonEnum: ""
  469. };
  470. if (res.code == 200) {
  471. this.$message.success("退团成功");
  472. this.getList();
  473. this.onekeyQuitVisible = false;
  474. }
  475. });
  476. });
  477. },
  478. chioseType() {
  479. this.$refs["quitForm"].$refs["quitForm"].validate(res => {
  480. if (res) {
  481. this.$confirm("确定退团?", "提示", {
  482. confirmButtonText: "确定",
  483. cancelButtonText: "取消",
  484. type: "warning"
  485. })
  486. .then(() => {
  487. let row = this.activeRow;
  488. let params = {
  489. musicGroupId: row.musicGroupId,
  490. userId: row.userId,
  491. reason: this.quitForm.reason,
  492. isRefundCourseFee: this.quitForm.isRefundCourseFee,
  493. isRefundInstrumentFee: this.quitForm.isRefundInstrumentFee,
  494. isRefundTeachingAssistantsFee: this.quitForm
  495. .isRefundTeachingAssistantsFee,
  496. maintenanceFee: this.quitForm.maintenanceFee,
  497. isRefundMemberFee: this.quitForm.isRefundMemberFee
  498. };
  499. // 退还学练宝费用
  500. if (this.quitForm.isRefundMemberFee) {
  501. params.cloudTeacherAmount = this.quitForm.cloudTeacherAmount;
  502. } else {
  503. params.cloudTeacherAmount = 0;
  504. }
  505. // 发请求 退团
  506. StudentQuit(params).then(res => {
  507. this.quitForm = {
  508. // 退团信息确认
  509. isRefundCourseFee: null,
  510. isRefundInstrumentFee: null,
  511. isRefundTeachingAssistantsFee: null,
  512. isMaintenanceFee: null,
  513. cloudTeacherAmount: null,
  514. isCloudTeacherAmount: null,
  515. isRefundMemberFee: null,
  516. maintenanceFee: 0,
  517. reason: ""
  518. };
  519. if (res.code == 200) {
  520. this.$message.success("退团成功");
  521. this.getList();
  522. this.quitVisible = false;
  523. }
  524. });
  525. })
  526. .catch(() => {});
  527. } else {
  528. }
  529. });
  530. // row.typeVisible = false;
  531. },
  532. addVisit(row) {
  533. this.visitVisible = true;
  534. this.activeRow = row;
  535. },
  536. gotoMusic(str) {
  537. this.$router.push({ path: "/teamList", query: { search: str } });
  538. },
  539. lookVisit(row) {
  540. this.$router.push({
  541. path: "/studentManager/returnVisitList",
  542. query: {
  543. search: row.userId,
  544. tabrouter: "2",
  545. typeList: ["其它", "会员续费"]
  546. }
  547. });
  548. }
  549. },
  550. watch: {
  551. quitVisible(val) {
  552. if (!val) {
  553. this.quitForm = {
  554. // 退团信息确认
  555. isRefundCourseFee: null,
  556. isRefundInstrumentFee: null,
  557. isRefundTeachingAssistantsFee: null,
  558. isMaintenanceFee: null,
  559. cloudTeacherAmount: null,
  560. isCloudTeacherAmount: null,
  561. maintenanceFee: 0,
  562. reason: ""
  563. };
  564. this.$refs["quitForm"].$refs["quitForm"].resetFields();
  565. }
  566. }
  567. },
  568. filters: {
  569. hasMemberFilter(val) {
  570. const arr = ["已过期", "即将过期", "待生效", "生效中"];
  571. return arr[val];
  572. }
  573. }
  574. };
  575. </script>
  576. <style lang="scss" scoped></style>