change-voice.vue 15 KB

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