change-voice.vue 17 KB

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