subject-preview.vue 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  1. <template>
  2. <div style="background: #F3F4F8;">
  3. <div class="noticeInfo">
  4. <h2>注册说明</h2>
  5. 1、您注册时所选择的乐团声部,即为乐团录取最终确认的声部,请您务必仔细填写;<br />
  6. 2、为避免因部分已注册家长放弃名额导致乐团声部失衡,系统设定各声部限额放大20%比例开放注册,系统自动按照完全完成注册的先后顺序确认录取名单,因此,超员后有可能出现无法注册的情况,请您理解。如果其他声部仍有名额,在您孩子的身体条件适合该乐器的前提下,我们将优先予以调配。
  7. </div>
  8. <div class="section">
  9. <h2 class="title">{{ courseViewType == 1 ? '服务' : '乐团课程' }}</h2>
  10. <p style="font-size: 14px; padding: 2px 0; color: #f85043" v-if="serviceValidDate && courseViewType == 1">服务有效期:{{ serviceValidDate }}</p>
  11. <!-- 所有不可选的课程合集 -->
  12. <template v-if="courseShowStatus && courseViewType == 1">
  13. <el-row class="option-row" v-for="(item, index) in courseShowInfo" :class="[!item.isStudentOptional ? 'disabled' : '']" :key="index" @click.native="onCourseChange(item)">
  14. <el-col :span="16">
  15. <i class="check_default" :class="[item.isStatus ? 'check_active' : '']"></i>
  16. <span style="display: flex; align-items: center;">
  17. <template v-if="item.courseType == 'PROJECT'">{{ chargeTypeName }} </template><template v-else>{{ item.courseType | coursesType }}</template>
  18. </span>
  19. <el-icon v-if="item.courseType == 'PROJECT'" class="el-icon-question" @click.native="onQuestions('amr')" />
  20. </el-col>
  21. <el-col :span="8">
  22. <span style="color: #1A1A1A">¥{{ item.courseCurrentPrice | moneyFormat }}</span>
  23. </el-col>
  24. </el-row>
  25. </template>
  26. <el-row class="title-row" v-if="courseViewType == 0">
  27. <el-col :span="12">课程类型</el-col>
  28. <!-- <el-col :span="5" :offset="1" style="text-align: right;">原价</el-col> -->
  29. <el-col :span="11" style="text-align: right;">现价</el-col>
  30. </el-row>
  31. <!-- 可选课程信息集合 -->
  32. <template v-for="(item, index) in courseInfo">
  33. <el-row class="option-row" :key="index" @click.native="onCourseChange(item)" v-if="courseViewType == 0">
  34. <el-col :span="12">
  35. <i class="check_default" :class="[item.isStatus ? 'check_active' : '', !item.isStudentOptional ? 'disabled' : '']"></i><template v-if="item.courseType == 'PROJECT'">{{ item.name }}</template><template v-else>{{ item.courseType | coursesType }}</template>
  36. </el-col>
  37. <!-- <el-col :span="6">
  38. <del style="color: #AAA; font-size: 12px;">¥{{ item.courseOriginalPrice | moneyFormat }}</del>
  39. </el-col> -->
  40. <el-col :span="11">
  41. <span style="color: #1A1A1A">¥{{ item.courseCurrentPrice | moneyFormat }}</span>
  42. </el-col>
  43. </el-row>
  44. </template>
  45. </div>
  46. <div class="section" v-if="courseInfo && courseInfo.length > 0 && isClickStatus && courseViewType == 1">
  47. <h2 class="title">{{ '乐团课程' }}</h2>
  48. <el-row class="title-row">
  49. <el-col :span="12">课程类型</el-col>
  50. <!-- <el-col :span="5" :offset="1" style="text-align: right;">原价</el-col> -->
  51. <el-col :span="6" style="text-align: right;">现价</el-col>
  52. </el-row>
  53. <!-- 可选课程信息集合 -->
  54. <template v-for="(item, index) in courseInfo">
  55. <el-row class="option-row" :key="index" @click.native="onCourseChange(item)" v-if="item.isStudentOptional">
  56. <el-col :span="12">
  57. <i class="check_default" :class="[item.isStatus ? 'check_active' : '', !item.isStudentOptional ? 'disabled' : '']"></i><template v-if="item.courseType == 'PROJECT'">{{ item.name }}</template><template v-else>{{ item.courseType | coursesType }}</template>
  58. </el-col>
  59. <!-- <el-col :span="6">
  60. <del style="color: #AAA; font-size: .12rem;">¥{{ item.courseOriginalPrice | moneyFormat }}</del>
  61. </el-col> -->
  62. <el-col :span="11">
  63. <span style="color: #1A1A1A">¥{{ item.courseCurrentPrice | moneyFormat }}</span>
  64. </el-col>
  65. </el-row>
  66. </template>
  67. </div>
  68. <div class="section" v-if="instrumentResult.length > 0">
  69. <h2 class="title">乐器</h2>
  70. <div v-for="(i, index) in instrumentResultList" :key="index">
  71. <el-row class="title-row">
  72. <el-col :span="12">
  73. <template v-if="i[0]['kitType'] == 'GROUP'">团购乐器</template>
  74. <template v-if="i[0]['kitType'] == 'LEASE'">乐器租赁</template>
  75. <template v-if="i[0]['kitType'] == 'FREE'">免费使用</template>
  76. <template v-if="i[0]['kitType'] == 'owned'">自备乐器</template>
  77. </el-col>
  78. <el-col :span="5" :offset="1" style="text-align: right;">
  79. <template v-if="['GROUP', 'LEASE', 'FREE'].includes(i[0]['kitType'])">原价</template>
  80. </el-col>
  81. <el-col :span="5" :offset="1" style="text-align: right;">
  82. <template v-if="['GROUP', 'FREE'].includes(i[0]['kitType'])">现价</template>
  83. <template v-if="i[0]['kitType'] == 'LEASE'">租赁押金</template>
  84. </el-col>
  85. </el-row>
  86. <el-row class="option-row" v-for="(con, index) in i" :key="index" @click.native="instrumentF(con)">
  87. <el-col :span="12">
  88. <i class="check_default" :class="[ con.checked ? 'check_active' : '' ]"></i>
  89. <div>
  90. {{ con.name }}
  91. <div v-if="con.goodsList" style="font-size: .12rem; color: #aaa">
  92. {{ con.goodsList[0].specification }}
  93. </div>
  94. </div>
  95. </el-col>
  96. <el-col :span="6">
  97. <del style="color: #AAA; font-size: 12px;" v-if="con.kitType != 'owned'">¥{{ con.marketPrice | moneyFormat }}</del>
  98. </el-col>
  99. <el-col :span="6">
  100. <span style="color: #1A1A1A" v-if="(con.kitType == 'LEASE')">¥{{ Number((con.depositFee - con.coupon).toFixed(2)) | moneyFormat }}</span>
  101. <span style="color: #1A1A1A" v-if="con.kitType == 'FREE'">¥{{ 0 | moneyFormat }}</span>
  102. <span style="color: #1A1A1A" v-if="con.kitType == 'GROUP'">¥{{ Number((con.price - con.coupon).toFixed(2)) | moneyFormat }}</span>
  103. </el-col>
  104. </el-row>
  105. </div>
  106. <div v-if="leBaoStatus">
  107. <el-row class="title-row">
  108. <el-col :span="12" :offset="1">服务项目</el-col>
  109. <!-- <el-col :span="5" :offset="1" style="text-align: right;">原价</el-col> -->
  110. <el-col :span="11" style="text-align: right;">现价</el-col>
  111. </el-row>
  112. <el-row class="option-row" @click.native="onLeBao">
  113. <el-col :span="12">
  114. <i class="check_default" :class="[ buyMaintenance ? 'check_active' : '' ]"></i>乐器保养(一年)<el-icon style="padding-left: 0;" name="question" @click.stop.native="onQuestions('instrument')" />
  115. </el-col>
  116. <!-- <el-col :span="6">
  117. <del style="color: #AAA; font-size: .12rem;">¥{{ 500 | moneyFormat }}</del>
  118. </el-col> -->
  119. <el-col :span="11" :offset="1">
  120. <span style="color: #1A1A1A">¥{{ 300 | moneyFormat }}</span>
  121. </el-col>
  122. </el-row>
  123. </div>
  124. </div>
  125. <div class="section" v-if="accessOries.length > 0" key="accessOries">
  126. <h2 class="title">辅件</h2>
  127. <el-row class="title-row">
  128. <el-col :span="12">服务项目</el-col>
  129. <el-col :span="5" :offset="1" style="text-align: right;">原价</el-col>
  130. <el-col :span="5" :offset="1" style="text-align: right;">现价</el-col>
  131. </el-row>
  132. <div v-for="(instr, index) in accessOries" :key="index">
  133. <el-row class="option-row" @click.native="onAuxiliarie(instr)">
  134. <el-col :span="12">
  135. <i class="check_default" :class="[ instr.checked ? 'check_active' : '' ]"></i>{{ instr.name }}
  136. </el-col>
  137. <el-col :span="6">
  138. <del style="color: #AAA; font-size: 12px;">¥{{ instr.goodsList[0] ? instr.goodsList[0].marketPrice : 0 | moneyFormat }}</del>
  139. </el-col>
  140. <el-col :span="6">
  141. <span style="color: #1A1A1A" v-if="instr.price == 0">免费</span>
  142. <span style="color: #1A1A1A" v-else>¥{{ instr.price | moneyFormat }}</span>
  143. </el-col>
  144. </el-row>
  145. <el-row style="padding-left: 24px;" v-if="instr.childGoodsList">
  146. <el-col>
  147. <span v-for="(child, index) in instr.childGoodsList" :key="child.id" style="font-size: 12px; color: #aaaaaa;">{{ child.name }} {{instr.childGoodsList.length - 1 == index ? '' : ','}}</span>
  148. </el-col>
  149. </el-row>
  150. </div>
  151. <!-- <el-row class="option-row lines">
  152. <el-col :span="12" class="fontBold">
  153. 仅需支付
  154. </el-col>
  155. <el-col :span="6">
  156. <del style="color: #f85043; font-size: 12px;">¥{{ orderInfo.accessMarketPrice | moneyFormat }}</del>
  157. </el-col>
  158. <el-col :span="6">
  159. <span class="fontBold" style="color: #f85043;">¥{{ orderInfo.accessPrice | moneyFormat }}</span>
  160. </el-col>
  161. </el-row> -->
  162. </div>
  163. <!-- 原价现价 -->
  164. <!-- <div class="section">
  165. <div class="needprice markerprice">
  166. <del>原价</del>
  167. <del>¥{{ orderInfo.marketPrice | moneyFormat }}</del>
  168. </div>
  169. <div class="needprice grouopprice">
  170. <span>仅需支付</span>
  171. <span>¥{{ orderInfo.amount | moneyFormat }}</span>
  172. </div>
  173. </div> -->
  174. <div class="buy">
  175. <div class="price">
  176. <!-- <p class="use_price">
  177. <img class="logo" src="@/assets/images/mycard.png" alt="">
  178. <span>¥{{ needPrice | moneyFormat }}</span>
  179. </p> -->
  180. <p class="oldprice">
  181. <del class="text">原价</del>
  182. <del style=" font-size: 13px;">¥{{ orderInfo.marketPrice | moneyFormat }}</del>
  183. </p>
  184. <p class="now_price">
  185. <span class="text">仅需支付</span>
  186. <span style="font-weight: bold">¥{{ needPrice | moneyFormat }}</span>
  187. </p>
  188. </div>
  189. <a class="btn-submit">购买</a>
  190. </div>
  191. </div>
  192. </template>
  193. <script>
  194. import { permission } from '@/utils/directivePage'
  195. import { getSubjectGoodsAndInfoPreview, getType } from '@/api/buildTeam'
  196. import dayjs from 'dayjs'
  197. const paymentPatternType = {
  198. 0: '按月',
  199. 1: '按学期',
  200. 2: '一次性'
  201. }
  202. export default {
  203. props: ["subjectId", "calenderId"],
  204. data() {
  205. const query = this.$route.query
  206. return {
  207. musicGroupId: query.id,
  208. result: {}, // 返回结果
  209. instrument: {}, // 乐器类型
  210. baseInfo: {}, // 其它类
  211. money: 580,
  212. balance: 0, // 余额
  213. needPrice: 0, // 还需支付
  214. payType: false, // 是否余额支付
  215. orderInfo: {
  216. marketPrice: 0,
  217. amount: 0, // 现价总金额
  218. groupPurchasePrice: 0, // 现价
  219. goodsGroupIds: null,
  220. goodsIds: null,
  221. contractGoodsIds: null, // 选中所有商品ID
  222. couponPrice: 0, //
  223. musicClassFee: 0, // 课程现价
  224. musicMarketClassFee: 0, // 课程原价
  225. accessPrice: 0, // 辅件现价
  226. accessMarketPrice: 0, // 辅件原价
  227. goodsPrice: 0, // 乐器现价
  228. goodsMarketPrice: 0, // 乐器原价
  229. }, // 金额列表,金额计算
  230. courseInfo: null, // 课程信息
  231. musicGroupSubject: null, // 基本信息
  232. instrumentResult: [], //乐器
  233. accessOries: [], // 辅件(打包)
  234. agreeStatus: true,
  235. authStatus: false,
  236. buyList: [], // 信息列表
  237. ids: [],
  238. chargeTypeId: null,
  239. paymentStatus: null,
  240. paymentPattern: null,
  241. serviceValidDate: null, // 服务时间
  242. courseShowStatus: false,
  243. chargeTypeList: [],
  244. chargeTypeName: null,
  245. courseViewType: 0, // 收费模式,0 课程显示,1 AMR系统
  246. leBaoStatus: false,
  247. buyMaintenance: false, // 是否开启乐保
  248. isClickStatus: false,
  249. accessStatus: false, // 是否有辅件乐保
  250. };
  251. },
  252. mounted() {
  253. this.__init()
  254. },
  255. methods: {
  256. async __init() {
  257. // 获取数据
  258. let params = {
  259. musicGroupId: this.musicGroupId,
  260. subjectId: this.subjectId,
  261. calenderId: this.calenderId
  262. }
  263. await getType().then(res => {
  264. let result = res.data
  265. if(res.code == 200) {
  266. this.chargeTypeList = result.rows || []
  267. }
  268. })
  269. await getSubjectGoodsAndInfoPreview(params).then(res => {
  270. let result = res
  271. if (result.code == 200) {
  272. let tempResult = result.data
  273. this.courseViewType = tempResult.musicGroup.courseViewType || 0
  274. this.paymentPattern = 2
  275. if(tempResult.musicGroupPaymentCalender) {
  276. this.paymentPattern = tempResult.musicGroupPaymentCalender.paymentPattern
  277. this.serviceValidDate = dayjs(tempResult.musicGroupPaymentCalender.paymentValidStartDate).format('YYYY/MM/DD') + '~' + dayjs(tempResult.musicGroupPaymentCalender.paymentValidEndDate).format('YYYY/MM/DD')
  278. }
  279. let tempInfo = tempResult.musicGroupPaymentCalender? tempResult.musicGroupPaymentCalender.musicGroupPaymentCalenderCourseSettingsList : null
  280. // 判断是否有课程
  281. if (tempInfo && tempInfo.length > 0) {
  282. let tempCourse = {
  283. courseCurrentPrice: 0,
  284. courseOriginalPrice: 0,
  285. courseType: null,
  286. name: '器乐练习系统'
  287. }
  288. tempInfo.forEach(info => {
  289. if(!info.isStudentOptional) {
  290. this.courseShowStatus = true
  291. tempCourse = {
  292. courseCurrentPrice: (info.courseCurrentPrice + tempCourse.courseCurrentPrice),
  293. courseOriginalPrice: (info.courseCurrentPrice + tempCourse.courseCurrentPrice),
  294. courseType: 'PROJECT',
  295. isStatus: true,
  296. name: '器乐练习系统'
  297. }
  298. }
  299. })
  300. this.courseShowInfo = [tempCourse]
  301. // 默认课程都选中
  302. this.courseInfo = tempInfo
  303. } else {
  304. // 判断是否有课程,如果没有课程则默认显示0
  305. this.courseInfo = [{
  306. id: -1,
  307. courseCurrentPrice: 0,
  308. courseOriginalPrice: 0,
  309. isStudentOptional: false,
  310. courseType: 'MUSIC'
  311. }]
  312. }
  313. this.isClickStatus = false
  314. this.courseInfo.forEach(item => {
  315. if(item.isStudentOptional) {
  316. item.isStatus = false
  317. this.isClickStatus = true
  318. } else {
  319. item.isStatus = true
  320. }
  321. })
  322. // console.log(this.isClickStatus)
  323. this.musicGroupSubject = tempResult.musicGroupSubjectPlan
  324. let instrumentInfo = {}
  325. let tempInstrument = []
  326. tempResult.musicGroupSubjectGoodsGroupList.forEach((item) => {
  327. if (item.type == "INSTRUMENT") {
  328. // 获取乐器所有提供方式
  329. let KGPTJ = item.kitGroupPurchaseTypeJson ? JSON.parse(item.kitGroupPurchaseTypeJson) : {}
  330. for (let single in KGPTJ) {
  331. let tempItem = Object.assign({}, item) // 深拷贝
  332. tempItem.marketPrice = tempItem.goodsList[0].marketPrice
  333. tempItem.kitType = single // 优惠模式
  334. tempItem.coupon = KGPTJ[single] // 优惠金额
  335. if (instrumentInfo.id) {
  336. tempItem.checked = false
  337. if (single == 'GROUP') { // 团购
  338. if ((instrumentInfo.kitType == 'GROUP' && instrumentInfo.price < tempItem.price) || instrumentInfo.kitType ==
  339. 'LEASE' || instrumentInfo.kitType == 'FREE') {
  340. this.instrumentResult.forEach(instrRes => {
  341. instrRes.checked = false
  342. })
  343. tempItem.checked = true
  344. instrumentInfo = {
  345. id: tempItem.id,
  346. price: tempItem.price,
  347. kitType: single
  348. }
  349. }
  350. } else if (single == 'LEASE') { // 租赁
  351. if (instrumentInfo.kitType == 'LEASE' && instrumentInfo.price < tempItem.price) {
  352. this.instrumentResult.forEach(instrRes => {
  353. instrRes.checked = false
  354. })
  355. tempItem.checked = true
  356. instrumentInfo = {
  357. id: tempItem.id,
  358. price: tempItem.price,
  359. kitType: single
  360. }
  361. }
  362. } else if (single == 'FREE') { // 免费
  363. if (instrumentInfo.kitType == 'FREE' && instrumentInfo.price < tempItem.price) {
  364. this.instrumentResult.forEach(instrRes => {
  365. instrRes.checked = false
  366. })
  367. tempItem.checked = true
  368. instrumentInfo = {
  369. id: tempItem.id,
  370. price: tempItem.price,
  371. kitType: single
  372. }
  373. }
  374. }
  375. } else {
  376. tempItem.checked = true
  377. instrumentInfo = {
  378. id: tempItem.id,
  379. price: tempItem.price,
  380. kitType: single
  381. }
  382. }
  383. this.instrumentResult.push(tempItem)
  384. tempInstrument.push(tempItem)
  385. }
  386. } else if (item.type == "ACCESSORIES") {
  387. item.checked = true
  388. this.accessOries.push(item)
  389. }
  390. })
  391. // 添加自备选项
  392. if (this.instrumentResult.length > 0) {
  393. // this.instrumentResult.push({
  394. // id: -1,
  395. // kitType: 'owned',
  396. // name: '自备',
  397. // price: 0,
  398. // marketPrice: 0,
  399. // checked: false
  400. // })
  401. let owned = {
  402. id: -1,
  403. kitType: 'owned',
  404. name: '自备乐器',
  405. price: 0,
  406. marketPrice: 0,
  407. checked: false
  408. }
  409. tempInstrument.push(owned)
  410. this.instrumentResult.push(owned)
  411. let sorted = this.groupBy(tempInstrument, (item) => {
  412. return [item.kitType];
  413. });
  414. this.instrumentResultList = sorted
  415. this.chargeTypeList.forEach(item => {
  416. if(item.id == tempResult.musicGroup.chargeTypeId) {
  417. this.chargeTypeName = item.description
  418. }
  419. })
  420. // 判断辅件是否有乐器维护(编号固定76)
  421. let accessStatus = false // 是否有乐保
  422. this.accessOries.forEach(item => {
  423. // 判断子商品是否有乐保
  424. if(item.childGoodsList && item.childGoodsList.length > 0) {
  425. item.childGoodsList.forEach(child => {
  426. if(child.id == 76) {
  427. accessStatus = true
  428. }
  429. })
  430. }
  431. if(item.goodsIdList == 76) {
  432. accessStatus = true
  433. }
  434. })
  435. this.accessStatus = accessStatus
  436. // 所有打击乐声部没有乐保【23】
  437. if(this.subjectId == 23) {
  438. this.accessStatus = true
  439. accessStatus = true
  440. }
  441. // 乐保服务初始化
  442. this.instrumentResult.forEach(item => {
  443. if(item.checked && item.kitType == "GROUP" && !accessStatus) {
  444. this.leBaoStatus = true
  445. this.buyMaintenance = true
  446. }
  447. })
  448. }
  449. }
  450. // 初始化计算金额
  451. this.calcPrice()
  452. })
  453. },
  454. onLeBao() {
  455. this.buyMaintenance = !this.buyMaintenance
  456. this.calcPrice()
  457. },
  458. groupBy(array, f) {
  459. var groups = {};
  460. array.forEach(function (o) {
  461. var group = JSON.stringify(f(o));
  462. groups[group] = groups[group] || [];
  463. groups[group].push(o);
  464. });
  465. return Object.keys(groups).map(function (group) {
  466. return groups[group];
  467. });
  468. },
  469. onQuestions(type) {
  470. if(type == 'amr') {
  471. this.$alert(`<b>革命性的“AMR器乐练习系统”</b><br />它的诞生是基于世界上最优秀的华人管乐指导专家唐嘉宏先生的教育理念,创新开发的一种新型“音乐感官植入程序”,这个程序抛弃了传统的“数线式识谱、机械式节奏、死记式乐理”,它营造出沉浸式可变速演奏过程,采用画面与音乐刺激序列组合而成的特定场景,在趣味性挑战的反复刺激中逐步促进器乐演奏的三核心:“音质→音准→音型”,从而达成演奏各环节水准的均匀提高,产生永久性条件反射式大脑记忆,将多板块知识融会贯通,让抽象的音乐知识刻入脑海里!<br /><br /><b>本练习系统的特点:</b><br /> 1.轻松快速掌握要点,让练习者沉浸其中,远离枯燥!<br /> 2.不假思索就能瞬间唤起反射式记忆,演奏识谱不再慢吞吞!<br /> 3.真正的实践记忆,摆脱纸上谈兵,与实际演奏紧密结合!<br />4.思维+肌肉的双重强化!无缝整合复习系统!<br /> 5.每条练习都经过严谨的编曲,你以为你只是在练习旋律线?其实是整个乐团在为你伴奏!`, 'AMR器乐练习系统', {
  472. confirmButtonText: '确定',
  473. dangerouslyUseHTMLString: true,
  474. callback: action => {
  475. }
  476. });
  477. } else if(type == 'instrument') {
  478. this.$alert(`<p style="text-align: justify">1.乐器保养是管乐迷针对乐团学员提供的乐器检查、保养及维修优惠特权;<br />2.该特权为包年制,从开通特权之日起365天内有效;<br />3.特权用户可享受管乐迷提供专业的高级乐器维修技师一年不低于两次下校检查乐器使用情况;<br />4.特权有效期内凭该特权绑定的乐器编号可享受保养人工费减免、非返厂维修人工费优惠等特权;<br />感谢您的信任和支持!</p>`, '乐器保养特权', {
  479. confirmButtonText: '确定',
  480. dangerouslyUseHTMLString: true,
  481. callback: action => {
  482. }
  483. });
  484. }
  485. },
  486. onCourseChange(item) {
  487. // 判断用户是否可以选择
  488. if (item.isStudentOptional) {
  489. item.isStatus = !item.isStatus
  490. this.calcPrice()
  491. }
  492. },
  493. onClickCheckbox() { //是否使用余额支付
  494. if (!this.payType) {
  495. if (this.orderInfo.amount >= this.balance) {
  496. this.needPrice = Number((this.orderInfo.amount - this.balance).toFixed(2))
  497. } else {
  498. this.needPrice = 0
  499. }
  500. } else {
  501. this.needPrice = this.orderInfo.amount
  502. }
  503. this.payType = !this.payType
  504. },
  505. onAuxiliarie(item) {
  506. // 辅件切换状态
  507. item.checked = !item.checked
  508. // 重新计算金额
  509. this.calcPrice()
  510. },
  511. instrumentF(item) {
  512. // 乐器切换状态
  513. this.instrumentResult.forEach(item => {
  514. item.checked = false
  515. })
  516. item.checked = true
  517. if(!this.accessStatus) {
  518. if(item.kitType != "owned") {
  519. this.leBaoStatus = true
  520. this.buyMaintenance = true
  521. } else {
  522. this.leBaoStatus = false
  523. this.buyMaintenance = false
  524. }
  525. }
  526. // 重新计算金额
  527. this.calcPrice()
  528. },
  529. calcPrice() {
  530. let buyList = [],
  531. ids = []
  532. let amount = 0,
  533. marketPrice = 0,
  534. goodsPrice = 0, // 乐器两现价
  535. goodsMarketPrice = 0, // 乐器原价
  536. goodsGroupIds = {},
  537. courseKeys = [],
  538. couponPrice = 0, // 优惠金额
  539. goodsIds = [],
  540. tempCourseFee = 0,
  541. musicClassFee = 0,
  542. musicMarketClassFee = 0,
  543. tempAccessPrice = 0,
  544. tempAccessMarketPrice = 0,
  545. tempGroupRemissionCourseFee = 0, // 乐团减免费用
  546. contractGoodsIds = '' // 合同所需要的商品Id (只需要乐器编号)
  547. // 课程
  548. let mgs = this.musicGroupSubject
  549. let csi = this.courseInfo
  550. // 加上判断是否有课程信息
  551. if (mgs) {
  552. let tempCourse = this.courseShowInfo
  553. // if (tempCourse.length > 0 && this.courseViewType == 1) {
  554. // tempCourse.forEach(item => {
  555. // if (item.id > 0) {
  556. // courseKeys.push(item.id)
  557. // }
  558. // musicClassFee += parseFloat(item.courseCurrentPrice)
  559. // marketPrice += parseFloat(item.courseOriginalPrice)
  560. // // 不可选的课程才会减免课程费用
  561. // if (!item.isStudentOptional) {
  562. // tempGroupRemissionCourseFee += parseFloat(item.courseCurrentPrice)
  563. // }
  564. // });
  565. // buyList.unshift({
  566. // name: this.chargeTypeName,
  567. // type: paymentPatternType[this.paymentPattern],
  568. // price: Number((musicClassFee).toFixed(2))
  569. // })
  570. // } else {
  571. if (tempCourse.length > 0 && this.courseViewType == 1) {
  572. let m = 0
  573. tempCourse.forEach(item => {
  574. m += parseFloat(item.courseCurrentPrice)
  575. // 不可选的课程才会减免课程费用
  576. // if (!item.isStudentOptional) {
  577. // tempGroupRemissionCourseFee += parseFloat(item.courseCurrentPrice)
  578. // }
  579. });
  580. marketPrice += parseFloat(m)
  581. buyList.unshift({
  582. name: this.chargeTypeName,
  583. type: paymentPatternType[this.paymentPattern],
  584. price: Number((m).toFixed(2))
  585. })
  586. }
  587. csi.forEach(item => {
  588. if (item.isStatus) {
  589. musicClassFee += parseFloat(item.courseCurrentPrice)
  590. // marketPrice += parseFloat(item.courseOriginalPrice)
  591. if (item.id > 0) {
  592. courseKeys.push(item.id)
  593. }
  594. // 不可选的课程才会减免课程费用
  595. if (!item.isStudentOptional) {
  596. tempGroupRemissionCourseFee += parseFloat(item.courseCurrentPrice)
  597. } else {
  598. marketPrice += parseFloat(item.courseCurrentPrice)
  599. }
  600. if(this.courseViewType == 0 && !item.isStudentOptional) {
  601. marketPrice += parseFloat(item.courseCurrentPrice)
  602. }
  603. }
  604. })
  605. // }
  606. }
  607. // 乐器
  608. let ir = this.instrumentResult
  609. if (ir.length > 0) {
  610. ir.forEach(item => {
  611. if (item.checked) {
  612. if (item.name != '自备') {
  613. contractGoodsIds += item.goodsIdList
  614. }
  615. if (item.kitType == 'FREE') {
  616. amount += 0
  617. couponPrice = 0 // 优惠金额
  618. } else if (item.kitType == 'LEASE') {
  619. couponPrice = item.coupon // 优惠金额
  620. if (item.name != '自备') {
  621. amount += item.depositFee
  622. goodsPrice += item.depositFee
  623. } else {
  624. amount += 0
  625. }
  626. } else {
  627. amount += parseFloat(item.price)
  628. goodsPrice += parseFloat(item.price)
  629. couponPrice = item.coupon ? item.coupon : 0
  630. }
  631. if (item.kitType == 'LEASE') {
  632. if (item.name != '自备') {
  633. marketPrice += parseFloat(item.marketPrice)
  634. goodsMarketPrice += item.depositFee
  635. }
  636. } else {
  637. marketPrice += parseFloat(item.marketPrice)
  638. goodsMarketPrice += parseFloat(item.marketPrice)
  639. }
  640. // item.id ? goodsGroupIds[item.id] : null
  641. if (item.id) {
  642. goodsGroupIds[item.id] = item.kitType
  643. }
  644. if (item.kitType == 'LEASE') {
  645. buyList.push({
  646. name: item.name,
  647. type: '租赁',
  648. price: item.depositFee
  649. })
  650. } else if (item.kitType == 'GROUP') {
  651. // && parseFloat(item.price - couponPrice) > 0
  652. buyList.push({
  653. name: item.name,
  654. type: '团购',
  655. price: parseFloat(item.price - couponPrice)
  656. })
  657. } else if(item.kitType == 'FREE') {
  658. buyList.push({
  659. name: item.name,
  660. type: '免费',
  661. price: 0
  662. })
  663. }
  664. // 是否减免课程费用,必须团购,并且开启了减免课程费用
  665. if(item.kitType == 'GROUP' && item.groupRemissionCourseFee == 1) {
  666. musicClassFee = parseFloat(musicClassFee - tempGroupRemissionCourseFee)
  667. }
  668. }
  669. })
  670. }
  671. if(this.leBaoStatus && this.buyMaintenance) {
  672. // 判断是否使用乐保
  673. // marketPrice += 500
  674. marketPrice += 300
  675. amount += 300
  676. buyList.push({
  677. name: '乐器保养',
  678. time: dayjs().format('YYYY/MM/DD') + '~' + dayjs().add(365, 'day').format('YYYY/MM/DD'),
  679. type: '包年',
  680. price: 300
  681. })
  682. }
  683. amount += parseFloat(tempCourseFee + musicClassFee)
  684. if (parseFloat(tempCourseFee + musicClassFee) > 0 && this.courseViewType == 0) {
  685. buyList.unshift({
  686. name: '乐团课',
  687. type: paymentPatternType[this.paymentPattern],
  688. price: Number((tempCourseFee + musicClassFee).toFixed(2))
  689. })
  690. }
  691. // 辅件
  692. if (this.accessOries.length > 0) {
  693. this.accessOries.forEach(item => {
  694. if (item.checked) {
  695. tempAccessPrice += parseFloat(item.price)
  696. amount += parseFloat(item.price)
  697. if (item.goodsList && item.goodsList.length > 0) {
  698. item.goodsList.forEach(childGoods => {
  699. tempAccessMarketPrice += parseFloat(childGoods.marketPrice)
  700. marketPrice += parseFloat(childGoods.marketPrice)
  701. })
  702. }
  703. goodsGroupIds[item.id] = 'ACCESSORIES'
  704. buyList.push({
  705. name: item.name,
  706. type: '团购',
  707. price: item.price
  708. })
  709. }
  710. })
  711. // if (tempAccessPrice > 0) {
  712. // buyList.push({
  713. // name: '辅件',
  714. // type: '团购',
  715. // price: tempAccessPrice
  716. // })
  717. // }
  718. }
  719. let tempGroupPurchasePrice = amount
  720. // 判断减去优惠金额,是否大于0(这里有可能出现负数)
  721. if (amount - couponPrice >= 0) {
  722. amount = Number((amount - couponPrice).toFixed(2))
  723. this.errorPrice = false
  724. } else {
  725. amount = 0
  726. this.errorPrice = true // 订单金额是否异常
  727. }
  728. if (amount - tempCourseFee - musicClassFee > 0) {
  729. ids.push(1, 2)
  730. }
  731. if (parseFloat(tempCourseFee + musicClassFee) > 0) {
  732. ids.push(3, 4, 5)
  733. }
  734. this.ids = ids
  735. // 计算是否使用过余额
  736. if (this.payType) {
  737. let tempPrice = Number((amount - this.balance).toFixed(2))
  738. if (tempPrice > 0) {
  739. this.needPrice = tempPrice
  740. } else {
  741. this.needPrice = 0
  742. }
  743. } else {
  744. this.needPrice = Number(amount.toFixed(2))
  745. }
  746. this.buyList = buyList
  747. this.orderInfo = {
  748. amount: Number(amount.toFixed(2)),
  749. marketPrice: Number(marketPrice.toFixed(2)),
  750. groupPurchasePrice: tempGroupPurchasePrice,
  751. couponPrice: couponPrice,
  752. goodsGroupIds: goodsGroupIds,
  753. goodsIds: goodsIds.join(','),
  754. contractGoodsIds: contractGoodsIds,
  755. courseKeys: courseKeys,
  756. musicClassFee: musicClassFee,
  757. musicMarketClassFee: musicMarketClassFee,
  758. accessMarketPrice: tempAccessMarketPrice,
  759. accessPrice: tempAccessPrice,
  760. goodsPrice: goodsPrice,
  761. goodsMarketPrice: goodsMarketPrice
  762. }
  763. },
  764. permission(str){
  765. return permission(str)
  766. }
  767. },
  768. };
  769. </script>
  770. <style lang="less" scoped>
  771. .noticeInfo {
  772. line-height: 1.8;
  773. h2 {
  774. font-size: 18px;
  775. color: #1a1a1a;
  776. line-height: 28px;
  777. height: 26px !important;
  778. font-weight: bold;
  779. }
  780. position: relative;
  781. background: #fff;
  782. padding: 0 16px 10px;
  783. font-size: 14px;
  784. color: #808080;
  785. margin-bottom: 10px;
  786. }
  787. .section {
  788. padding: 16px 16px 10px;
  789. background: #fff;
  790. margin-bottom: 10px;
  791. >.title {
  792. font-size: 20px;
  793. line-height: 28px;
  794. height: 26px !important;
  795. font-weight: bold;
  796. &::before {
  797. content: " ";
  798. width: 4px;
  799. height: 15px;
  800. background: #14928a;
  801. display: inline-block;
  802. margin-right: 7px;
  803. border-radius: 8px;
  804. }
  805. }
  806. .indate {
  807. font-size: 14px;
  808. padding: 6px 0;
  809. display: flex;
  810. // justify-content: space-between;
  811. justify-content: flex-end;
  812. span {
  813. color: #fa101d;
  814. }
  815. }
  816. }
  817. .disabled {
  818. opacity: 0.5;
  819. .check_active {
  820. opacity: .5;
  821. }
  822. }
  823. .buy {
  824. height: 60px;
  825. display: flex;
  826. align-items: center;
  827. padding: 0 20px;
  828. border-top: 1px solid #ffe9e9e9;
  829. color: #000000;
  830. font-size: 12px;
  831. background: #fff;
  832. .price {
  833. flex: 1;
  834. font-size: 16px;
  835. }
  836. font-size: 16px;
  837. span {
  838. color: #fa101d;
  839. }
  840. .text {
  841. font-size: 12px;
  842. width: 60px;
  843. display: inline-block;
  844. color: #000;
  845. }
  846. del {
  847. color: #b5b5b5;
  848. &.text {
  849. color: #b5b5b5;
  850. }
  851. }
  852. .btn-submit {
  853. display: inline-block;
  854. font-size: 18px;
  855. color: #fff;
  856. background: #f85043;
  857. border-radius: 100px;
  858. box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.19);
  859. padding: 8px 46px;
  860. }
  861. }
  862. .iframe {
  863. width: 100%;
  864. height: 100%;
  865. -webkit-overflow-scrolling: touch;
  866. overflow-y: scroll;
  867. border-top: none !important;
  868. min-height: calc(100vh - 41px);
  869. }
  870. .countDownContent {
  871. line-height: 40px;
  872. text-align: center;
  873. font-size: 14px;
  874. border-bottom: 1px solid #ccc;
  875. .van-count-down {
  876. display: inline;
  877. color: #f00;
  878. }
  879. }
  880. .loadingOrder {
  881. width: 90%;
  882. height: 180px;
  883. display: flex;
  884. align-items: center;
  885. justify-content: center;
  886. .van-loading__text {
  887. color: #444;
  888. }
  889. }
  890. .pay-section {
  891. margin-bottom: 10px;
  892. padding: 10px 8px;
  893. }
  894. .pay-name {
  895. padding-left: 10px;
  896. flex: 1 auto;
  897. font-weight: bold;
  898. }
  899. .logo {
  900. width: 24px;
  901. height: 24px;
  902. }
  903. .van-checkbox {
  904. float: right;
  905. /deep/.van-checkbox__icon .van-icon {
  906. border-color: #e9eaef;
  907. background-color: #e9eaef;
  908. }
  909. /deep/.van-checkbox__icon--checked .van-icon {
  910. background-color: #2dc7aa;
  911. border-color: #2dc7aa;
  912. }
  913. }
  914. .needprice {
  915. display: flex;
  916. justify-content: space-between;
  917. padding: 2px 0;
  918. del {
  919. font-size: 14px;
  920. color: #aaa;
  921. font-weight: bold;
  922. }
  923. span {
  924. font-size: 18px;
  925. color: #f85043;
  926. font-weight: bold;
  927. }
  928. }
  929. .couponprice {
  930. display: flex;
  931. justify-content: space-between;
  932. }
  933. .use_price {
  934. display: flex;
  935. align-items: center;
  936. font-size: 14px;
  937. font-weight: bold;
  938. img {
  939. padding-right: 8px;
  940. }
  941. span {
  942. font-size: 16px;
  943. }
  944. }
  945. .check_default {
  946. margin-right: 8px;
  947. display: flex;
  948. align-items: center;
  949. height: 26px;
  950. &::before {
  951. display: block;
  952. content: ' ';
  953. width: 18px;
  954. height: 18px;
  955. background-color: #e9eaef;
  956. border-radius: 50%;
  957. }
  958. &.check_active {
  959. &::before {
  960. display: block;
  961. content: ' ';
  962. background: url("../../../assets/images/icon_checkbox.png") no-repeat center;
  963. background-size: contain;
  964. }
  965. }
  966. &.radio_active {
  967. &::before {
  968. display: block;
  969. content: ' ';
  970. background: url("../../../assets/images/icon_radio.png") no-repeat center;
  971. background-size: contain;
  972. }
  973. }
  974. }
  975. // .check_default {
  976. // margin-right: 8px;
  977. // display: block;
  978. // width: 18px;
  979. // height: 18px;
  980. // background-color: #e9eaef;
  981. // border-radius: 50%;
  982. // &.check_active {
  983. // background: url("../../../assets/images/icon_checkbox.png") no-repeat center;
  984. // background-size: contain;
  985. // }
  986. // }
  987. .title-row {
  988. background: #F3F4F8;
  989. color: #1a1a1a;
  990. padding:5px 5px 3px;
  991. border-radius:5px;
  992. font-size: 14px;
  993. }
  994. .option-row {
  995. line-height: 26px;
  996. font-size: 14px;
  997. display: flex;
  998. // align-items: center;
  999. position: relative;
  1000. padding: 10px 0 5px;
  1001. box-sizing: border-box;
  1002. cursor: pointer;
  1003. .el-col {
  1004. display: flex;
  1005. // align-items: center;
  1006. }
  1007. .el-col-6, .el-col-8, .el-col-11{
  1008. display: flex;
  1009. justify-content: flex-end;
  1010. }
  1011. &.lines {
  1012. margin-top: 5px;
  1013. border-top: 1px solid #ededed;
  1014. }
  1015. }
  1016. .el-icon-question {
  1017. font-size: 16px;
  1018. color: #4d4d4d;
  1019. padding-left: 5px;
  1020. padding-top: 5px;
  1021. }
  1022. .fontBold {
  1023. font-weight: bold;
  1024. }
  1025. </style>