change-voice.vue 17 KB

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