change-voice.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. <template>
  2. <div>
  3. <el-form :model="form" :rules="rules" ref="form" label-width="110px">
  4. <el-form-item label="原乐器" prop="name">
  5. <span>{{ originalMusicalGoods || "无" }}</span>
  6. </el-form-item>
  7. <el-form-item label="原教辅" prop="name">
  8. <span>{{ originalAccessoriesGoods || "无" }}</span>
  9. </el-form-item>
  10. <el-form-item
  11. label="更改声部"
  12. prop="subjectId"
  13. :rules="[
  14. { required: true, message: '请选择更改声部', trigger: 'change' },
  15. ]"
  16. >
  17. <el-select
  18. style="width: 100% !important"
  19. v-model="form.subjectId"
  20. clearable
  21. v-if="!changeInfo"
  22. @change="subjectChange"
  23. placeholder="请选择声部"
  24. >
  25. <el-option
  26. v-for="item in filterVoiceList"
  27. :key="item.subjectId"
  28. :label="item.subjectName"
  29. :value="item.subjectId"
  30. >
  31. </el-option>
  32. </el-select>
  33. <span v-else>{{ changeSubjectName }}</span>
  34. </el-form-item>
  35. <el-form-item
  36. label="更改乐器"
  37. prop="musicalGoods"
  38. :rules="[
  39. { required: true, message: '请选择更改乐器', trigger: 'change' },
  40. ]"
  41. >
  42. <el-select
  43. style="width: 100% !important"
  44. v-model="form.musicalGoods"
  45. clearable
  46. v-if="!changeInfo"
  47. @change="musicalGoodsChange"
  48. placeholder="请选择乐器"
  49. >
  50. <el-option label="自备乐器" value="OWNED"> </el-option>
  51. <el-option
  52. v-for="item in musicalGoods"
  53. :key="item.goodsIdList"
  54. :label="item.name"
  55. :value="item.goodsIdList"
  56. >
  57. </el-option>
  58. </el-select>
  59. <span v-else-if="changeInfo && changeInfo.changeMusicalGoods">{{
  60. changeInfo.changeMusicalGoods.name
  61. }}</span>
  62. </el-form-item>
  63. <el-form-item
  64. v-if="
  65. changeInfo ||
  66. (form.musicalGoods &&
  67. musicalGoodsById[form.musicalGoods] &&
  68. musicalGoodsById[form.musicalGoods].kitGroupPurchaseTypeJsonParse)
  69. "
  70. label="乐器提供方式"
  71. prop="type"
  72. :rules="[
  73. { required: true, message: '请选择乐器提供方式', trigger: 'change' },
  74. ]"
  75. >
  76. <el-radio-group v-if="!changeInfo" v-model="form.type">
  77. <el-radio
  78. :label="key"
  79. v-for="(item, key) in musicalGoodsById[form.musicalGoods]
  80. .kitGroupPurchaseTypeJsonParse"
  81. :key="key"
  82. >{{
  83. `${kitGroupPurchaseTypeFormater[key]} ${
  84. (musicalGoodsById[form.musicalGoods][typeAndprice[key]] || 0) >
  85. 0
  86. ? musicalGoodsById[form.musicalGoods][typeAndprice[key]] +
  87. "元"
  88. : "免费"
  89. }`
  90. }}</el-radio
  91. >
  92. </el-radio-group>
  93. <span v-else-if="changeInfo && changeInfo.kitGroupPurchaseType">{{
  94. kitGroupPurchaseTypeFormater[changeInfo.kitGroupPurchaseType]
  95. }}</span>
  96. </el-form-item>
  97. <template>
  98. <el-form-item
  99. v-show="
  100. (courseViewType == 2 && form.musicalGoods == 'OWNED') ||
  101. courseViewType != 2
  102. "
  103. v-if="activeAccessories.length || groupList.length || changeInfo"
  104. label="更换教辅"
  105. class="is-required"
  106. >
  107. <accessories
  108. ref='accessories'
  109. :list.sync="activeAccessories"
  110. :groupList.sync="groupList"
  111. @change="accessoriesChange"
  112. v-if="!changeInfo"
  113. />
  114. <span v-else-if="changeInfo">{{ changeAccessoriesGoods }}</span>
  115. <!-- <el-select style="width: 100%" v-model="form.accessories" clearable placeholder="请选择教辅">
  116. <el-option
  117. v-for="item in accessories"
  118. :key="item.id"
  119. :label="item.name"
  120. :value="item.id">
  121. </el-option>
  122. </el-select> -->
  123. </el-form-item>
  124. </template>
  125. <el-form-item label="查看链接" prop="name" v-if="changeInfo">
  126. <div class="viewlink">
  127. <el-tooltip
  128. class="item"
  129. effect="dark"
  130. :content="copyLink"
  131. placement="top"
  132. >
  133. <span class="link">{{ copyLink }}</span>
  134. </el-tooltip>
  135. <el-popover placement="top" width="220" trigger="click">
  136. <div class="left-code">
  137. <div id="qrcode" class="qrcode code" ref="qrCodeUrl"></div>
  138. <p class="code-url" v-if="copyLink">
  139. {{ copyLink }}
  140. <el-link
  141. @click="copyUrl(copyLink)"
  142. class="linkbtn"
  143. type="primary"
  144. >复制</el-link
  145. >
  146. </p>
  147. </div>
  148. <el-button
  149. type="primary"
  150. class="btn"
  151. slot="reference"
  152. @click="onCreateQRCode"
  153. >二维码</el-button
  154. >
  155. </el-popover>
  156. </div>
  157. </el-form-item>
  158. <el-form-item label="支付差价" prop="name">
  159. <span style="color: red" v-if="!changeInfo"
  160. >{{ spread | moneyFormat }}元</span
  161. >
  162. <span style="color: red" v-else>{{ editSpread | moneyFormat }}元</span>
  163. </el-form-item>
  164. </el-form>
  165. <div slot="footer" class="dialog-footer" style="text-align: right">
  166. <el-button @click="$listeners.close">取 消</el-button>
  167. <el-button
  168. @click="cancel"
  169. type="danger"
  170. v-permission="'subjectChange/cancel'"
  171. v-if="changeInfo && changeInfo.status !== 1"
  172. >取消订单</el-button
  173. >
  174. <el-button
  175. type="primary"
  176. v-if="!changeInfo"
  177. v-permission="'subjectChange/add'"
  178. @click="submit"
  179. >确 定</el-button
  180. >
  181. </div>
  182. </div>
  183. </template>
  184. <script>
  185. import QRCode from "qrcodejs2";
  186. import copy from "copy-to-clipboard";
  187. import numeral from "numeral";
  188. import {
  189. getStudentOriginal,
  190. getSubjectGoodsAndInfo,
  191. subjectChangeAdd,
  192. subjectChangeCancel,
  193. getChangeInfo,
  194. } from "@/api/buildTeam";
  195. import { vaildStudentUrl } from "@/utils/validate";
  196. import accessories from "./accessories";
  197. import { kitGroupPurchaseType } from "@/constant";
  198. const formatAllGoods = (data, kitGroupPurchaseType) => {
  199. const accessories = [];
  200. const accessoriesById = {};
  201. const musicalGoods = [];
  202. const musicalGoodsById = {};
  203. const groupList = [];
  204. const groupListById = {};
  205. const accessoriesByGoods = {};
  206. if (data) {
  207. const { musicGroupSubjectGoodsGroupList } = data;
  208. const types = {};
  209. for (const item of musicGroupSubjectGoodsGroupList) {
  210. if (!types[item.type]) {
  211. types[item.type] = [];
  212. }
  213. types[item.type].push(item);
  214. }
  215. const typesKeys = Object.keys(types);
  216. for (const key of typesKeys) {
  217. for (const item of types[key]) {
  218. if (key === "INSTRUMENT") {
  219. let json = {};
  220. let courseJson = {};
  221. try {
  222. json = JSON.parse(item.kitGroupPurchaseTypeJson);
  223. } catch (error) {}
  224. try {
  225. courseJson = JSON.parse(item.coursePurchaseTypeJson);
  226. } catch (error) {}
  227. // if (json[kitGroupPurchaseType] !== undefined) {
  228. const _item = {
  229. ...item,
  230. kitGroupPurchaseTypeJsonParse: json,
  231. kitGroupPurchaseTypePrice: json[kitGroupPurchaseType] || 0,
  232. coursePurchaseTypeJsonTypePrice:
  233. courseJson[kitGroupPurchaseType] || 0,
  234. _calculated_price:
  235. kitGroupPurchaseType === "FREE"
  236. ? 0
  237. : kitGroupPurchaseType === "LEASE"
  238. ? item.depositFee
  239. : item.price,
  240. };
  241. musicalGoods.push(_item);
  242. musicalGoodsById[item.goodsIdList] = _item;
  243. if (!types.ACCESSORIES) {
  244. if (!accessoriesByGoods[item.goodsIdList]) {
  245. accessoriesByGoods[item.goodsIdList] = [];
  246. }
  247. const acs = item.goodsList[0].goodsList
  248. ? item.goodsList[0].goodsList
  249. : [];
  250. for (const goods of acs) {
  251. accessoriesByGoods[item.goodsIdList].push(goods);
  252. accessoriesById[goods.id] = goods;
  253. }
  254. }
  255. // }
  256. } else if (item.type === "ACCESSORIES") {
  257. groupList.push(item);
  258. groupListById[item.id] = item;
  259. }
  260. }
  261. }
  262. }
  263. return {
  264. accessories,
  265. accessoriesById,
  266. musicalGoods,
  267. musicalGoodsById,
  268. groupList,
  269. groupListById,
  270. accessoriesByGoods,
  271. };
  272. };
  273. const typeAndprice = {
  274. GROUP: "price",
  275. LEASE: "depositFee",
  276. };
  277. export default {
  278. props: ["detail", "musicGroupId", "voiceList", "courseViewType"],
  279. components: {
  280. accessories,
  281. },
  282. data() {
  283. return {
  284. typeAndprice,
  285. kitGroupPurchaseTypeFormater: kitGroupPurchaseType,
  286. changeInfo: null,
  287. oldAllMoney: 0,
  288. accessories: [],
  289. accessoriesByid: {},
  290. musicalGoods: [],
  291. musicalGoodsById: {},
  292. groupList: [],
  293. groupListById: {},
  294. accessoriesByGoods: {},
  295. selectAccessories: [],
  296. selectAccessoriesMoney: 0,
  297. kitGroupPurchaseTypePrice: 0,
  298. coursePurchaseTypeJsonTypePrice: 0,
  299. form: {
  300. subjectId: "",
  301. accessories: "",
  302. musicalGoods: "",
  303. type: "",
  304. },
  305. rules: {},
  306. item: {},
  307. originalMusicalGoods: "",
  308. originalAccessoriesGoods: "",
  309. originalAccessoriesPrice: 0,
  310. originalMusicalPrice: 0,
  311. originalCourseFee: 0,
  312. musicGroupSubjectPlanFee: 0,
  313. musicalPrice: 0,
  314. };
  315. },
  316. watch: {
  317. detail() {
  318. if (this.detail) {
  319. this.fetchDetail();
  320. }
  321. },
  322. "form.musicalGoods"() {
  323. this.$set(this.form, "type", "");
  324. },
  325. "form.type"() {
  326. this.musicalGoodsChange(this.form.musicalGoods);
  327. },
  328. },
  329. computed: {
  330. copyLink() {
  331. if (this.changeInfo) {
  332. return vaildStudentUrl() + "/#/change-voice?id=" + this.changeInfo.id;
  333. }
  334. return "";
  335. },
  336. filterVoiceList() {
  337. return this.voiceList.filter(
  338. (item) => item.subjectId != this.detail.actualSubjectId
  339. );
  340. },
  341. activeAccessories() {
  342. const { musicalGoods } = this.form || {};
  343. return musicalGoods ? this.accessoriesByGoods[musicalGoods] || [] : [];
  344. },
  345. changeSubjectName() {
  346. let name = "";
  347. if (this.item.changeSubjectId) {
  348. for (const item of this.voiceList) {
  349. if (item.subjectId === this.item.changeSubjectId) {
  350. name = item.subjectName;
  351. break;
  352. }
  353. }
  354. }
  355. return name;
  356. },
  357. changeAccessoriesGoods() {
  358. const subjectChange = this.changeInfo || {};
  359. const items = (subjectChange.changeAccessoriesGoods || [])
  360. .map((item) => item.name)
  361. .join(",");
  362. return items || "未选择教辅";
  363. },
  364. editSpread() {
  365. const data = this.changeInfo || {};
  366. const payed =
  367. (data.originalAccessoriesPrice || 0) +
  368. (data.originalCourseFee || 0) +
  369. (data.originalMusicalPrice || 0);
  370. // console.log(payed, data.changeMusicalPrice, data.changeAccessoriesPrice, data.changeCourseFee, {...data})
  371. return (
  372. (data.changeMusicalPrice || 0) +
  373. (data.changeAccessoriesPrice || 0) +
  374. (data.changeCourseFee || 0) -
  375. payed
  376. );
  377. },
  378. spread() {
  379. const money = this.numFormat(
  380. this.musicalPrice +
  381. this.selectAccessoriesMoney +
  382. this.musicGroupSubjectPlanFee -
  383. this.originalAccessoriesPrice -
  384. this.originalMusicalPrice -
  385. this.originalCourseFee -
  386. this.coursePurchaseTypeJsonTypePrice -
  387. this.kitGroupPurchaseTypePrice
  388. );
  389. // console.log(
  390. // this.item.kitGroupPurchaseType,
  391. // '乐器价格', this.musicalPrice,
  392. // '已选附件价格', this.selectAccessoriesMoney,
  393. // '选择课程费用', this.musicGroupSubjectPlanFee,
  394. // '原附件价格', this.originalAccessoriesPrice,
  395. // '原乐器价格', this.originalMusicalPrice,
  396. // '原课程费用', this.originalCourseFee,
  397. // '原课程减免费用', this.coursePurchaseTypeJsonTypePrice,
  398. // '乐器减免费用', this.kitGroupPurchaseTypePrice,
  399. // '结果价格', money
  400. // )
  401. return money;
  402. },
  403. },
  404. mounted() {
  405. if (this.detail && this.detail.userId) {
  406. this.fetchDetail();
  407. }
  408. },
  409. methods: {
  410. copyUrl(url) {
  411. copy(url);
  412. this.$message.success("复制成功");
  413. },
  414. async fetchDetail() {
  415. const setRes = (res) => {
  416. const { data } = res;
  417. this.item = data || {};
  418. if (data) {
  419. this.$set(this.form, "type", this.item.kitGroupPurchaseType);
  420. this.originalAccessoriesPrice = data.originalAccessoriesPrice;
  421. this.originalMusicalPrice = data.originalMusicalPrice;
  422. this.originalCourseFee = data.originalCourseFee;
  423. this.originalMusicalGoods =
  424. data.originalMusicalGoods && data.originalMusicalGoods.name;
  425. this.originalAccessoriesGoods = (data.originalAccessoriesGoods || [])
  426. .map((item) => item.name)
  427. .join();
  428. }
  429. };
  430. if (this.detail.subjectChange) {
  431. await getChangeInfo({
  432. id: this.detail.subjectChange.id,
  433. }).then((res) => {
  434. setRes(res);
  435. this.changeInfo = res.data;
  436. });
  437. } else {
  438. this.changeInfo = this.detail.subjectChange;
  439. await getStudentOriginal({
  440. musicGroupId: this.musicGroupId,
  441. studentId: this.detail.studentId,
  442. }).then(setRes);
  443. }
  444. },
  445. async subjectChange(id) {
  446. this.$set(this.form, "musicalGoods", "");
  447. let data = null;
  448. if (id) {
  449. try {
  450. const res = await getSubjectGoodsAndInfo({
  451. musicGroupId: this.musicGroupId,
  452. subjectId: id,
  453. });
  454. data = res.data;
  455. this.musicGroupSubjectPlanFee = res.data.musicGroupSubjectPlan.fee;
  456. } catch (e) {
  457. console.log(e);
  458. }
  459. } else {
  460. this.musicGroupSubjectPlanFee = 0;
  461. }
  462. const items = formatAllGoods(data, this.item.kitGroupPurchaseType);
  463. for (const key in items) {
  464. if (items.hasOwnProperty(key)) {
  465. const item = items[key];
  466. this[key] = item;
  467. }
  468. }
  469. this.musicalGoodsChange();
  470. },
  471. musicalGoodsChange(val) {
  472. this.$refs["form"].clearValidate();
  473. this.accessoriesChange([],0)
  474. console.log(this.$refs.accessories)
  475. if(this.$refs.accessories){
  476. this.$refs.accessories.checkeds = []
  477. this.$refs.accessories.isIndeterminate = false;
  478. }
  479. // if (val != "OWNED") {
  480. // this.selectAccessories = [];
  481. // this.selectAccessoriesMoney = 0;
  482. // }
  483. const item = this.musicalGoodsById[val];
  484. if (item) {
  485. this.musicalPrice = this.numFormat(
  486. item[typeAndprice[this.form.type]] || 0
  487. );
  488. // this.kitGroupPurchaseTypePrice = this.numFormat(item[typeAndprice[this.form.type]] || 0)
  489. this.coursePurchaseTypeJsonTypePrice = this.numFormat(
  490. item.coursePurchaseTypeJsonTypePrice
  491. );
  492. this.types = item.kitGroupPurchaseTypeJsonParse;
  493. } else {
  494. this.musicalPrice = 0;
  495. // this.kitGroupPurchaseTypePrice = 0
  496. this.coursePurchaseTypeJsonTypePrice = 0;
  497. this.$set(this.form, "type", "");
  498. }
  499. this.$forceUpdate()
  500. },
  501. accessoriesChange(ids, money) {
  502. this.selectAccessories = ids;
  503. this.selectAccessoriesMoney = money;
  504. },
  505. numFormat(num) {
  506. let _num = parseFloat(num);
  507. if (isNaN(_num)) {
  508. _num = 0;
  509. }
  510. return parseFloat(_num.toFixed(2));
  511. },
  512. onCreateQRCode() {
  513. setTimeout(() => {
  514. this.$refs.qrCodeUrl.innerHTML = "";
  515. this.qrcode = new QRCode(this.$refs.qrCodeUrl, {
  516. width: 200,
  517. height: 200,
  518. colorDark: "#000000",
  519. colorLight: "#ffffff",
  520. correctLevel: QRCode.CorrectLevel.H,
  521. });
  522. this.qrcode.makeCode(this.copyLink);
  523. this.codeUrl = this.copyLink;
  524. }, 500);
  525. },
  526. submit() {
  527. this.$refs["form"].validate((valid) => {
  528. this.detail.subjectId;
  529. if (valid) {
  530. if (
  531. this.courseViewType == 2 &&
  532. this.form.musicalGoods == "OWNED" &&
  533. this.selectAccessories &&
  534. this.selectAccessories.length <= 0
  535. ) {
  536. this.$message.error("请至少选择一个教辅");
  537. return;
  538. }
  539. subjectChangeAdd({
  540. changeCourseFee: this.numFormat(
  541. this.musicGroupSubjectPlanFee -
  542. this.coursePurchaseTypeJsonTypePrice
  543. ),
  544. changeAccessories: this.selectAccessories.join(",") || null,
  545. changeAccessoriesPrice: this.numFormat(this.selectAccessoriesMoney),
  546. changeMusicalPrice: this.numFormat(this.musicalPrice),
  547. originalCourseFee: this.originalCourseFee,
  548. originalMusicalPrice: this.originalMusicalPrice,
  549. originalMusical: this.item.originalMusical,
  550. originalAccessories: this.item.originalAccessories,
  551. originalAccessoriesPrice: this.originalAccessoriesPrice,
  552. cooperationOrganId: this.item.cooperationOrganId,
  553. kitGroupPurchaseType:
  554. this.form.musicalGoods === "OWNED"
  555. ? this.form.musicalGoods
  556. : this.form.type,
  557. musicGroupId: this.musicGroupId,
  558. studentId: this.detail.studentId,
  559. changeMusical:
  560. this.form.musicalGoods === "OWNED" ? 0 : this.form.musicalGoods,
  561. originalCost: this.item.originalCost,
  562. organId: this.item.organId,
  563. originalSubjectId: this.detail?.actualSubjectId,
  564. changeSubjectId: this.form.subjectId,
  565. }).then((res) => {
  566. this.$listeners.close();
  567. this.$listeners.submited();
  568. this.$message.success("提交成功!");
  569. });
  570. }
  571. });
  572. },
  573. cancel() {
  574. this.$confirm("是否确认取消订单?", "提示", {
  575. onfirmButtonText: "确定",
  576. cancelButtonText: "取消",
  577. type: "warning",
  578. }).then(() => {
  579. subjectChangeCancel({
  580. id: this.detail.subjectChange.id,
  581. }).then((res) => {
  582. this.$listeners.close();
  583. this.$listeners.submited();
  584. this.$message.success("取消成功!");
  585. });
  586. });
  587. },
  588. },
  589. };
  590. </script>
  591. <style lang="less" scoped>
  592. .viewlink {
  593. display: flex;
  594. .link {
  595. flex: 1;
  596. overflow: hidden;
  597. text-overflow: ellipsis;
  598. display: block;
  599. white-space: nowrap;
  600. }
  601. .btn {
  602. width: 100px;
  603. margin-left: 20px;
  604. }
  605. }
  606. .left-code {
  607. height: 255px;
  608. .code-url {
  609. margin-top: 10px;
  610. .linkbtn {
  611. margin-top: 0;
  612. margin-bottom: 0;
  613. font-size: 12px;
  614. }
  615. }
  616. }
  617. </style>