soundSetCore.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. <template>
  2. <div>
  3. <div class="soundBtnWrap">
  4. <el-button
  5. type="primary"
  6. @click="allin"
  7. v-if="teamStatus != 'resetTeam' && !basdisabled"
  8. >全选</el-button
  9. >
  10. <el-button
  11. type="danger"
  12. @click="deleteRow"
  13. v-if="teamStatus != 'resetTeam' && !basdisabled"
  14. >删除</el-button
  15. >
  16. <el-button type="primary" @click="soundVisible = true" v-if="!basdisabled"
  17. >添加</el-button
  18. >
  19. </div>
  20. <div class="coreWrap">
  21. <el-checkbox-group v-model="checkList" @change="lookCheck">
  22. <el-collapse v-model="chioseActiveSound">
  23. <el-collapse-item
  24. v-for="(item, index) in activeSoundList"
  25. :name="item.id"
  26. :key="index"
  27. >
  28. <template slot="title">
  29. <div class="coreItemTitle">
  30. <el-checkbox :label="item.id" :disabled="basdisabled">{{
  31. item.sound
  32. }}</el-checkbox>
  33. </div>
  34. </template>
  35. <div class="coreItem">
  36. <div class="coreItemRow">
  37. <p class="title">计划招生人数:</p>
  38. <el-input
  39. :disabled="basdisabled"
  40. style="width: 180px"
  41. v-model="item.expectedStudentNum"
  42. ></el-input>
  43. </div>
  44. </div>
  45. <el-divider></el-divider>
  46. <chioseMusic
  47. :activeSoundList="activeSoundList"
  48. :item="item"
  49. @lookMusic="lookMusic"
  50. :basdisabled="basdisabled"
  51. />
  52. <div class="coreItemRow">
  53. <p class="title">教辅:</p>
  54. <el-select
  55. style="width: 558px !important"
  56. v-model="item.markChioseList"
  57. :disabled="basdisabled"
  58. clearable
  59. filterable
  60. multiple
  61. >
  62. <el-option
  63. v-for="(item, index) in item.markList"
  64. :key="index"
  65. :label="item.name"
  66. :value="item.id"
  67. >
  68. <span style="float: left">{{ item.name }}</span>
  69. <span
  70. style="
  71. float: right;
  72. color: #8492a6;
  73. font-size: 13px;
  74. padding-right: 20px;
  75. "
  76. >{{ item.groupPurchasePrice | moneyFormat }}元</span
  77. >
  78. </el-option>
  79. </el-select>
  80. </div>
  81. </el-collapse-item>
  82. </el-collapse>
  83. </el-checkbox-group>
  84. </div>
  85. <el-dialog title="声部选择" :visible.sync="soundVisible" destroy-on-close>
  86. <chioseSoundList
  87. :soundList="soundList"
  88. :activeSound="activeSound"
  89. @chioseSound="chioseSound"
  90. />
  91. </el-dialog>
  92. </div>
  93. </template>
  94. <script>
  95. import store from "@/store";
  96. import { formatData } from "@/utils/utils";
  97. import {
  98. getSubject,
  99. getDefaultSubject,
  100. getGoods,
  101. createTeam,
  102. getSoundTree,
  103. findMusicGroupSubjectInfo,
  104. updateSubjectInfo,
  105. auditSuccess,
  106. auditFailed,
  107. getSubjectGoods,
  108. } from "@/api/buildTeam";
  109. import dayjs from "dayjs";
  110. import chioseSoundList from "./chioseSoundList";
  111. import chioseMusic from "./chioseMusic";
  112. import { findIndex } from "lodash";
  113. import numeral from "numeral";
  114. export default {
  115. components: { chioseSoundList, chioseMusic },
  116. data() {
  117. return {
  118. soundList: [], // 接口返回的一级二级声部
  119. soundVisible: false, // 设置声部弹窗
  120. childSoundList: [],
  121. activeSoundList: [], //列表上的声部
  122. activeSound: null, // 展开的列表
  123. chioseActiveSound: [],
  124. soundList: [], // 接口返回的一级二级声部
  125. childSoundList: [],
  126. teamStatus: "", // 乐团状态
  127. checkList: [],
  128. basdisabled: false,
  129. };
  130. },
  131. mounted() {
  132. this.init();
  133. },
  134. activated() {
  135. this.init();
  136. },
  137. methods: {
  138. init() {
  139. // 获取第一页的数据
  140. this.topfor = this.$store.getters.topinfo;
  141. let type = this.topfor.type;
  142. let section = this.topfor.section;
  143. this.teamStatus = this.$route.query.type;
  144. if (this.$route.query.search) {
  145. this.Fsearch = this.$route.query.search;
  146. }
  147. if (this.$route.query.rules) {
  148. this.Frules = this.$route.query.rules;
  149. }
  150. if (
  151. this.teamStatus == "look" ||
  152. this.teamStatus == "teamAudit" ||
  153. this.teamStatus == "feeAudit" ||
  154. this.teamStatus == "teamCanceled"
  155. ) {
  156. this.basdisabled = true;
  157. } else {
  158. this.basdisabled = false;
  159. }
  160. getSoundTree({ tenantId: 1 }).then((res) => {
  161. if (res.code == 200) {
  162. this.soundList = res.data.rows;
  163. if (this.teamStatus == "newTeam" && type && section) {
  164. getDefaultSubject({
  165. chargeTypeId: type,
  166. organId: section,
  167. number: 1,
  168. }).then((res) => {
  169. if (res.code == 200) {
  170. let activeSound = [];
  171. this.activeSoundList = res.data.map((item) => {
  172. activeSound.push(item.id);
  173. return this.initSound(item);
  174. });
  175. this.activeSound = activeSound;
  176. this.chioseActiveSound = activeSound;
  177. this.changeActiveSound(activeSound.join(","));
  178. }
  179. });
  180. } else {
  181. this.teamid = this.$route.query.id;
  182. if (this.teamid) {
  183. findMusicGroupSubjectInfo({ musicGroupId: this.teamid }).then(
  184. (res) => {
  185. if (res.code == 200) {
  186. let activeSound = [];
  187. this.activeSoundList = res.data?.musicGroupSubjectPlans.map(
  188. (item) => {
  189. activeSound.push(item.subjectId);
  190. return {
  191. id: parseInt(item.subjectId),
  192. sound: item.subName,
  193. expectedStudentNum: item.expectedStudentNum,
  194. chioseMusic: [],
  195. markChioseList: [],
  196. goodsList: [],
  197. markList: [],
  198. };
  199. }
  200. );
  201. this.activeSound = activeSound;
  202. this.chioseActiveSound = activeSound;
  203. this.changeActiveSound(activeSound.join(","));
  204. // 格式化商品和教辅
  205. res.data.musicGroupSubjectGoodsGroups.forEach((shop) => {
  206. let index = findIndex(this.activeSoundList, (o) => {
  207. return o.id == shop.subjectId;
  208. });
  209. if (index != -1) {
  210. if (shop.type == "ACCESSORIES") {
  211. shop.goodsIdList.split(",").forEach((item) => {
  212. this.activeSoundList[index].markChioseList.push(
  213. parseInt(item)
  214. );
  215. });
  216. } else if (shop.type == "INSTRUMENT") {
  217. // 商品
  218. let typeJson = Object.keys(
  219. JSON.parse(shop.kitGroupPurchaseTypeJson)
  220. );
  221. this.activeSoundList[index].chioseMusic.push({
  222. musical: parseInt(shop.goodsIdList),
  223. type: typeJson,
  224. groupPrice: shop.price,
  225. borrowPrice: shop.depositFee,
  226. groupRemissionCourseFee: Boolean(
  227. shop.groupRemissionCourseFee
  228. ),
  229. });
  230. }
  231. }
  232. });
  233. }
  234. // console.log(this.activeSoundList);
  235. }
  236. );
  237. }
  238. }
  239. }
  240. });
  241. getSubject({ tenantId: 1 }).then((res) => {
  242. if (res.code == 200) {
  243. this.childSoundList = res.data;
  244. }
  245. });
  246. },
  247. lookCheck(val) {
  248. this.checkList = [...new Set(val)];
  249. },
  250. chioseSound(activeSound) {
  251. // 同步数据
  252. this.activeSound = [...new Set(activeSound)];
  253. let newSoundList = [];
  254. for (let i in this.childSoundList) {
  255. if (this.activeSound.includes(this.childSoundList[i].id)) {
  256. newSoundList.push(this.initSound(this.childSoundList[i]));
  257. }
  258. }
  259. let idList = this.activeSoundList.map((item) => {
  260. return item.id;
  261. });
  262. for (let x in newSoundList) {
  263. const indexof = idList.indexOf(newSoundList[x]?.id);
  264. if (indexof > -1) {
  265. newSoundList[x] = this.activeSoundList[indexof];
  266. }
  267. }
  268. this.activeSoundList = newSoundList;
  269. let newActiveSound = [];
  270. this.activeSoundList.forEach((item) => {
  271. newActiveSound.push(item.id);
  272. });
  273. this.activeSound = newActiveSound;
  274. this.chioseActiveSound = newActiveSound;
  275. this.changeActiveSound(newActiveSound.join(","));
  276. this.soundVisible = false;
  277. },
  278. initSound(item) {
  279. let obj = {
  280. id: item.id,
  281. sound: item.name,
  282. expectedStudentNum: item.expectedStudentNum,
  283. chioseMusic: [
  284. {
  285. musical: "",
  286. type: ["GROUP"],
  287. groupPrice: 0,
  288. borrowPrice: 1500,
  289. groupRemissionCourseFee: Boolean(item.groupRemissionCourseFee),
  290. },
  291. ],
  292. markChioseList: [],
  293. goodsList: [],
  294. markList: [],
  295. };
  296. return obj;
  297. },
  298. changeActiveSound(val) {
  299. // 写入声部商品和辅件
  300. getSubjectGoods({
  301. subjectIds: val,
  302. chargeTypeId: this.topfor.type,
  303. }).then((res) => {
  304. if (res.code == 200) {
  305. if (res.data) {
  306. let keys = Object.keys(res.data);
  307. this.activeSoundList.forEach((item) => {
  308. if (keys.indexOf(item.id + "") != -1) {
  309. let goodList = [];
  310. let markList = [];
  311. res.data[item.id].forEach((shop) => {
  312. if (shop.type == "INSTRUMENT") {
  313. goodList.push(shop);
  314. } else if (shop.type == "ACCESSORIES") {
  315. markList.push(shop);
  316. }
  317. });
  318. item.goodsList = goodList;
  319. item.markList = markList;
  320. }
  321. });
  322. }
  323. }
  324. });
  325. },
  326. lookMusic() {},
  327. submitInfo(type) {
  328. // 计划招生人数
  329. // 可选乐器
  330. // 教辅
  331. if (this.activeSoundList.length <= 0) {
  332. this.$message.error(`请至少设置一个声部`);
  333. return;
  334. }
  335. let flag = true;
  336. this.activeSoundList.forEach((item) => {
  337. if (!item.expectedStudentNum) {
  338. this.$message.error(`请填写${item.sound}的预计招生人数`);
  339. flag = false;
  340. return;
  341. }
  342. if (!item.chioseMusic[0]?.musical) {
  343. this.$message.error(`请至少一个选择${item.sound}的可选乐器`);
  344. flag = false;
  345. return;
  346. }
  347. item.chioseMusic.forEach((music) => {
  348. if (music.type.indexOf("LEASE") != -1) {
  349. if (!music.borrowPrice || parseFloat(music.borrowPrice) <= 0) {
  350. this.$message.error(`请填写正确的${item.sound}租赁押金`);
  351. flag = false;
  352. }
  353. }
  354. });
  355. });
  356. if (!flag) return;
  357. // 新建团
  358. let obj = {};
  359. if (this.teamStatus == "newTeam") {
  360. this.initCreateTeam(obj);
  361. }
  362. // 初始化声部
  363. obj.musicGroupSubjectGoodsGroups = [];
  364. obj.musicGroupSubjectPlans = [];
  365. this.activeSoundList.forEach((active) => {
  366. // 格式化声部数据
  367. let item = {
  368. expectedStudentNum: active.expectedStudentNum,
  369. subName: active.sound,
  370. subjectId: active.id,
  371. };
  372. obj.musicGroupSubjectPlans.push(item);
  373. // 格式化商品数据 chioseMusic: [{ musical: '', type: ["GROUP"], groupPrice: 0, borrowPrice: 1500 }],
  374. active.chioseMusic.forEach((music) => {
  375. // console.log(music);
  376. let goodsItem = null;
  377. let depositFee = music.borrowPrice;
  378. let price = music.groupPrice;
  379. let groupRemissionCourseFee;
  380. if (music.type.indexOf("GROUP") != -1) {
  381. groupRemissionCourseFee = music.groupRemissionCourseFee * 1;
  382. } else {
  383. groupRemissionCourseFee = 0;
  384. }
  385. let index = findIndex(active.goodsList, (o) => {
  386. return o.id == music.musical;
  387. });
  388. if (index != -1) {
  389. goodsItem = active.goodsList[index];
  390. }
  391. let kitGroupPurchaseTypeJson = {};
  392. music.type.forEach((type) => {
  393. kitGroupPurchaseTypeJson[type] = 0;
  394. });
  395. // if (Array.isArray(music.type)) {
  396. // music.type.forEach((type) => {
  397. // kitGroupPurchaseTypeJson[type] = 0;
  398. // });
  399. // }else{
  400. // // 字符串
  401. // let arr = [ music.type]
  402. // arr.forEach((type) => {
  403. // kitGroupPurchaseTypeJson[type] = 0;
  404. // });
  405. // }
  406. kitGroupPurchaseTypeJson = JSON.stringify(kitGroupPurchaseTypeJson);
  407. if (goodsItem) {
  408. let some = {
  409. subjectId: active.id,
  410. type: "INSTRUMENT",
  411. goodsIdList: music.musical,
  412. name: goodsItem.name,
  413. kitGroupPurchaseTypeJson,
  414. depositFee,
  415. price,
  416. groupRemissionCourseFee,
  417. };
  418. obj.musicGroupSubjectGoodsGroups.push(some);
  419. }
  420. });
  421. // 格式化辅件
  422. // markChioseList: [],
  423. // goodsList: [],
  424. // markList: [],
  425. active.markChioseList.forEach((ass) => {
  426. let index = findIndex(active.markList, (o) => {
  427. return o.id == ass;
  428. });
  429. let goodsItem = null;
  430. if (index != -1) {
  431. goodsItem = active.markList[index];
  432. }
  433. if (goodsItem) {
  434. let some = {
  435. subjectId: active.id,
  436. type: "ACCESSORIES",
  437. goodsIdList: ass,
  438. name: goodsItem.name,
  439. price: goodsItem.groupPurchasePrice,
  440. };
  441. obj.musicGroupSubjectGoodsGroups.push(some);
  442. }
  443. });
  444. });
  445. if (this.teamStatus == "newTeam") {
  446. createTeam(obj).then((res) => {
  447. if (res.code == 200) {
  448. // type=teamDraft&id=21030215002600001
  449. if (type) {
  450. this.teamStatus = "teamDraft";
  451. this.$confirm("乐团创建成功,是否提交审核?", "提示", {
  452. confirmButtonText: "确定",
  453. cancelButtonText: "取消",
  454. type: "warning",
  455. })
  456. .then(() => {
  457. this.teamid = res.data;
  458. this.submitInfo(1);
  459. })
  460. .catch(() => {
  461. this.teamid = res.data;
  462. this.$router.push({
  463. path: "/business/teamBuild",
  464. query: { type: "teamDraft", id: res.data },
  465. });
  466. });
  467. } else {
  468. this.$message.success("保存成功");
  469. this.teamid = res.data;
  470. this.teamStatus = "DRAFT";
  471. }
  472. this.$router.push({
  473. path: "/business/teamBuild",
  474. query: { type: "teamDraft", id: res.data },
  475. });
  476. // 把第3步单独拆出来做成独立的模块
  477. }
  478. });
  479. } else {
  480. obj.musicGroupId = this.teamid;
  481. console.log(obj,type)
  482. if (type) {
  483. obj.musicGroupStatus = "AUDIT";
  484. } else {
  485. obj.musicGroupStatus = "DRAFT";
  486. }
  487. if (type == 2) {
  488. this.$confirm("是否提交审核?", "提示", {
  489. confirmButtonText: "确定",
  490. cancelButtonText: "取消",
  491. type: "warning",
  492. })
  493. .then(() => {
  494. updateSubjectInfo(obj).then((res) => {
  495. if (res.code == 200) {
  496. this.$message.success("提交成功");
  497. this.$store.dispatch("delVisitedViews", this.$route);
  498. this.$router.push({
  499. path: "/business/teamDetail",
  500. });
  501. }
  502. });
  503. })
  504. .catch(() => {});
  505. }else{
  506. updateSubjectInfo(obj).then((res) => {
  507. if (res.code == 200) {
  508. // this.$emit("chiosetab", 2);
  509. // 创建乐团,只会到声部了
  510. if (type && type == 2) {
  511. this.$message.success("提交成功");
  512. this.$store.dispatch("delVisitedViews", this.$route);
  513. this.$router.push({
  514. path: "/business/teamDetail",
  515. });
  516. } else {
  517. this.$message.success("提交成功");
  518. }
  519. }
  520. });
  521. }
  522. }
  523. },
  524. deleteRow() {
  525. if (this.checkList.length < 1) {
  526. this.$message.error("请至少勾选一个");
  527. return;
  528. }
  529. for (let i = 0; i < this.activeSoundList.length; i++) {
  530. let index = this.checkList.indexOf(this.activeSoundList[i].id);
  531. if (index != -1) {
  532. this.activeSoundList.splice(i, 1);
  533. this.activeSound.splice(i, 1);
  534. i--;
  535. }
  536. }
  537. this.checkList = [];
  538. },
  539. allin() {
  540. this.checkList = [];
  541. this.activeSoundList.forEach((item, index) => {
  542. this.checkList.push(item.id);
  543. });
  544. },
  545. initCreateTeam(obj) {
  546. let enrollClasses;
  547. this.topfor.startClass
  548. ? (enrollClasses = this.topfor.startClass.join(","))
  549. : (enrollClasses = null);
  550. obj.musicGroup = {
  551. settlementType: this.topfor.salary,
  552. applyExpireDate: dayjs(this.topfor.time).format("YYYY-MM-DD HH:mm:ss"),
  553. chargeTypeId: this.topfor.type,
  554. cooperationOrganId: this.topfor.school,
  555. teamTeacherId: this.topfor.boss,
  556. educationalTeacherId: this.topfor.teacher,
  557. enrollClasses,
  558. name: this.topfor.name,
  559. organId: this.topfor.section,
  560. paymentPattern: this.topfor.paymentPattern,
  561. paymentValidStartDate: this.topfor.paymentValidStartDate
  562. ? dayjs(this.topfor.paymentValidStartDate).format("YYYY-MM-DD")
  563. : this.topfor.paymentValidStartDate,
  564. paymentValidEndDate: this.topfor.paymentValidEndDate
  565. ? dayjs(this.topfor.paymentValidEndDate).format("YYYY-MM-DD")
  566. : this.topfor.paymentValidEndDate,
  567. // paymentMonths:obj.months 有待确认
  568. schoolId: this.topfor.address,
  569. expectStartGroupDate: this.topfor.startTime,
  570. isClassroomLessons: this.topfor.isClass,
  571. status: "DRAFT",
  572. ownershipType: this.topfor.ownershipType,
  573. repairUserId: this.topfor.repairUserId,
  574. feeType: this.topfor.feeType,
  575. directorUserId: this.topfor.head,
  576. };
  577. return obj;
  578. },
  579. },
  580. watch: {
  581. activeSoundList: {
  582. immediate: true,
  583. deep: true,
  584. handler(n) {
  585. let chioseSoundNum = 0;
  586. let PlannedCount = 0;
  587. let activeSoundList = this.activeSoundList;
  588. if (n) {
  589. let Count = 0;
  590. if (n.length > 0) {
  591. for (let item in n) {
  592. Count += parseInt(n[item]?.expectedStudentNum) || 0;
  593. }
  594. }
  595. chioseSoundNum = n.length;
  596. PlannedCount = Count;
  597. this.$emit("getNumber", chioseSoundNum, PlannedCount);
  598. }
  599. },
  600. },
  601. },
  602. };
  603. </script>
  604. <style lang="scss" scoped>
  605. .soundBtnWrap {
  606. margin-bottom: 20px;
  607. }
  608. /deep/.el-collapse-item__header {
  609. background-color: #edeef0;
  610. }
  611. .coreItemTitle {
  612. background-color: #edeef0;
  613. height: 46px;
  614. line-height: 46px;
  615. padding: 0 20px;
  616. }
  617. .coreItem {
  618. padding: 25px 0 0;
  619. }
  620. .coreItemRow {
  621. padding: 0 20px;
  622. line-height: 50px;
  623. display: flex;
  624. flex-direction: row;
  625. align-items: center;
  626. p {
  627. margin-right: 10px;
  628. }
  629. .title {
  630. width: 140px;
  631. text-align: right;
  632. }
  633. }
  634. .marginLeft10 {
  635. margin-left: 10px;
  636. }
  637. /deep/.el-collapse-item__header {
  638. border-bottom: 1px solid #fff;
  639. }
  640. </style>