index.ts 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  1. // index.ts
  2. import { api_queryByParamNameList, api_shopInstruments, api_shopProduct } from "../../api/login";
  3. import { api_getOpenId, api_trackPointLog } from "../../api/new";
  4. import { debounce, formatPrice, formatTime } from "../../utils/util";
  5. // 获取应用实例
  6. const app = getApp<IAppOption>();
  7. const PURCHASE_TYPE = {
  8. STUDENT: "WECHAT_MINI",
  9. TEACHER: "TEACHER_VIP",
  10. };
  11. const TEACHER_VIP_PARAM_NAME = "teacher_vip_purchase_list";
  12. const purchaseDataCache: any = {};
  13. function getProductImage(item: any, userType: string) {
  14. if (!item) {
  15. return "";
  16. }
  17. if (userType === PURCHASE_TYPE.TEACHER) {
  18. return item.coverImg || item.pic || "";
  19. }
  20. return item.pic || item.coverImg || "";
  21. }
  22. function parseTeacherVipList(paramValue: any) {
  23. if (!paramValue) {
  24. return [];
  25. }
  26. const value = typeof paramValue === "string" ? JSON.parse(paramValue) : paramValue;
  27. if (Array.isArray(value)) {
  28. return value;
  29. }
  30. return value.list || value.goodsList || value.packages || [];
  31. }
  32. function formatPeriodText(num: any, type: string) {
  33. const unitText: any = {
  34. DAY: "天",
  35. MONTH: "个月",
  36. YEAR: "年",
  37. };
  38. if (!num || !type) {
  39. return "";
  40. }
  41. return `${num}${unitText[type] || ""}`;
  42. }
  43. function formatGiftText(item: any) {
  44. if (!item) {
  45. return "";
  46. }
  47. if (item.free?.number && item.free?.unit) {
  48. return formatPeriodText(item.free.number, item.free.unit);
  49. }
  50. if (item.giftFlag && item.giftVipDay && item.giftPeriod) {
  51. return formatPeriodText(item.giftVipDay, item.giftPeriod);
  52. }
  53. return "";
  54. }
  55. function buildPeriodList(list: any[]) {
  56. return list.map((item: any, index: number) => ({
  57. label: item.typeName || item.title || item.name || formatPeriodText(item.num, item.period),
  58. value: String(item.id),
  59. disabled: Number(item.stockNum ?? 1) <= 0,
  60. viewId: `period-${index}`,
  61. }));
  62. }
  63. function getPeriodScrollIntoView(periodList: any[], selectedPeriod: string) {
  64. return periodList.find((item: any) => String(item.value) === String(selectedPeriod))?.viewId || "";
  65. }
  66. function selectDefaultTeacherVip(list: any[]) {
  67. const saleableList = list.filter((item: any) => Number(item.stockNum ?? 1) > 0);
  68. const candidates = saleableList.length ? saleableList : list;
  69. const getSearchText = (item: any) => [
  70. item.name,
  71. item.title,
  72. item.label,
  73. item.typeName,
  74. ].filter(Boolean).join("");
  75. const isOneYear = (item: any) => {
  76. const text = getSearchText(item);
  77. return (Number(item.num) === 1 && item.period === "YEAR") || /(?:1|一)年/.test(text);
  78. };
  79. const isTrial = (item: any) => /体验卡/.test(getSearchText(item));
  80. return candidates.find((item: any) => isOneYear(item) && isTrial(item))
  81. || candidates.find(isOneYear)
  82. || candidates.find((item: any) => item.isHot)
  83. || candidates[0]
  84. || {};
  85. }
  86. // pages/orders/orders.ts
  87. Page({
  88. /**
  89. * 页面的初始数据
  90. */
  91. data: {
  92. imgList: [
  93. // 'https://oss.dayaedu.com/ktyq/1732585725698.png',
  94. // 'https://oss.dayaedu.com/ktyq/1732519468124.png',
  95. // 'https://oss.dayaedu.com/ktyq/1732519479416.png',
  96. // 'https://oss.dayaedu.com/ktyq/1733110029242.png',
  97. // 'https://oss.dayaedu.com/ktyq/1732519500580.png'
  98. "https://oss.dayaedu.com/ktyq/1733449062928.png",
  99. "https://oss.dayaedu.com/ktyq/1733449075055.png",
  100. "https://oss.dayaedu.com/ktyq/1733449085983.png",
  101. "https://oss.dayaedu.com/ktyq/1733449097054.png",
  102. ],
  103. goodsImgList: [
  104. "https://oss.dayaedu.com/ktyq/1739353790443.png",
  105. "https://oss.dayaedu.com/ktyq/1739353815962.png",
  106. "https://oss.dayaedu.com/ktyq/1739353843494.png",
  107. "https://oss.dayaedu.com/ktyq/03/1772550951364.png",
  108. ],
  109. detailImgList: [
  110. {
  111. url: "https://oss.dayaedu.com/ktyq/1733403675345.png",
  112. text: "合作学校音乐数字课堂公开课",
  113. },
  114. {
  115. url: "https://oss.dayaedu.com/ktyq/1733403707851.png",
  116. text: "音乐课课堂器乐教学",
  117. },
  118. {
  119. url: "https://oss.dayaedu.com/ktyq/1733403725644.png",
  120. text: "学期末汇报演出",
  121. },
  122. ],
  123. serviceShow: true,
  124. scrollTop: 0,
  125. current: 0,
  126. detailCurrent: 0,
  127. autoplay: false,
  128. interval: 5000,
  129. duration: 500,
  130. popupShow: false,
  131. videoHeight: "255px",
  132. list: [] as any,
  133. instrumentList: [] as any,
  134. isOverSaled: false, // 是否所有商品都没有库存
  135. selected: {} as any,
  136. selectInstrumentId: '', // 选中的乐器
  137. selectedInstrument: {} as any,
  138. formatSelectGood: {
  139. typeName: '',
  140. name: '',
  141. productImage: '',
  142. giftText: '',
  143. showSalePrice: '', // 显示的现价
  144. originalPrice: 0, // 原价
  145. salePrice: 0, // 现价
  146. discountPrice: '' // 已省
  147. } as any, // 格式化所有选中的数据
  148. opacity: 0,
  149. // showSelectedProduct: false, // 是否显示选中商品值
  150. scrolIntoViewStr: "",
  151. scrolIntoView: "",
  152. scrollDiscount: false, // 是否扣减启
  153. isScrollTT: false,
  154. scrollIntoViewType: false,
  155. headerHeight: 0, // 头部的高度
  156. initialScrollHeight: 0, // 滚动高度
  157. isFromPreviewImage: false,
  158. bannerPlay: false, // 视频是否播放
  159. titleControls: false, // 详情是否显示控制条
  160. liuControls: false, // 详情是否显示控制条
  161. bannerImageloaded: false, // Banner 图片是否加载完成
  162. userTypes: PURCHASE_TYPE.STUDENT, // 用户类型:WECHAT_MINI | TEACHER_VIP
  163. periodList: [] as any,
  164. selectedPeriod: '', // 选中的期限
  165. periodScrollIntoView: '',
  166. showBonusGift: false, // 是否显示额外赠送
  167. },
  168. /**
  169. * 生命周期函数--监听页面加载
  170. */
  171. onLoad() {
  172. // this.onInit()
  173. const wxWindowInfo = wx.getWindowInfo();
  174. this.setData({
  175. videoHeight: (wxWindowInfo.windowWidth / 16) * 9 + "px",
  176. });
  177. // 首页进入页面埋点
  178. this.onHomePageTrackPoint()
  179. },
  180. onHomePageTrackPoint() {
  181. // openId
  182. const openId = wx.getStorageSync("openId")
  183. if(openId) {
  184. this.onTrackPoint({
  185. openId,
  186. elementName: '首页'
  187. })
  188. } else {
  189. wx.login({
  190. success: async (res) => {
  191. await api_getOpenId({
  192. code: res.code,
  193. appId: app.globalData.appId
  194. }).then((res: any) => {
  195. // 存储 openId
  196. const openId = res.data.data
  197. wx.setStorageSync("openId", openId);
  198. this.onTrackPoint({
  199. openId,
  200. elementName: '首页'
  201. })
  202. })
  203. }
  204. })
  205. }
  206. },
  207. onReady() {
  208. const that = this;
  209. wx.createSelectorQuery()
  210. .select("#scroll-header")
  211. .boundingClientRect(function (rect) {
  212. that.setData({
  213. headerHeight: rect.height,
  214. });
  215. })
  216. .exec();
  217. wx.createSelectorQuery()
  218. .select("#scroll-view")
  219. .boundingClientRect(function (rect) {
  220. // console.log(rect, 'rect')
  221. that.setData({
  222. initialScrollHeight: rect.height,
  223. });
  224. })
  225. .exec();
  226. },
  227. onBannerVideoLoad() {
  228. this.setData({
  229. bannerImageloaded: true,
  230. });
  231. },
  232. onBannerPlay() {
  233. const bannerVideo = wx.createVideoContext("bannerVideo");
  234. const titleVideo = wx.createVideoContext("titleVideo");
  235. //
  236. this.setData(
  237. {
  238. bannerPlay: true,
  239. },
  240. () => {
  241. bannerVideo.play();
  242. titleVideo.pause();
  243. // liuVideo.stop()
  244. }
  245. );
  246. },
  247. onBannerVideoPlay() {
  248. const titleVideo = wx.createVideoContext("titleVideo");
  249. titleVideo.pause();
  250. // const liuVideo = wx.createVideoContext('liuVideo')
  251. // liuVideo.stop()
  252. },
  253. onTitlePlay() {
  254. const bannerVideo = wx.createVideoContext("bannerVideo");
  255. bannerVideo.pause();
  256. // const liuVideo = wx.createVideoContext('liuVideo')
  257. // liuVideo.stop()
  258. },
  259. onTItleVideoPlay() {
  260. const bannerVideo = wx.createVideoContext("bannerVideo");
  261. const titleVideo = wx.createVideoContext("titleVideo");
  262. // const liuVideo = wx.createVideoContext('liuVideo')
  263. this.setData(
  264. {
  265. titleControls: true,
  266. },
  267. () => {
  268. titleVideo.play();
  269. bannerVideo.pause();
  270. // liuVideo.stop()
  271. }
  272. );
  273. },
  274. onLiuPlay() {
  275. const bannerVideo = wx.createVideoContext("bannerVideo");
  276. bannerVideo.pause();
  277. const titleVideo = wx.createVideoContext("titleVideo");
  278. titleVideo.pause();
  279. },
  280. onLiuVideoPlay() {
  281. const bannerVideo = wx.createVideoContext("bannerVideo");
  282. const titleVideo = wx.createVideoContext("titleVideo");
  283. // const liuVideo = wx.createVideoContext('liuVideo')
  284. bannerVideo.pause();
  285. titleVideo.pause();
  286. this.setData(
  287. {
  288. liuControls: true,
  289. },
  290. () => {
  291. // liuVideo.play()
  292. }
  293. );
  294. },
  295. /**
  296. * 获取基础信息
  297. */
  298. async onInit() {
  299. const userType = this.data.userTypes;
  300. if (purchaseDataCache[userType]) {
  301. this.applyPurchaseData(purchaseDataCache[userType]);
  302. return
  303. }
  304. if (userType === PURCHASE_TYPE.TEACHER) {
  305. await this.onInitTeacherVip()
  306. return
  307. }
  308. try {
  309. const result = await api_shopInstruments({ appId: app.globalData.appId })
  310. const instrumentList = result.data.data || []
  311. instrumentList.forEach((item: any) => {
  312. item.showSalePrice = formatPrice(item.salePrice || 0, 'ALL')
  313. item.showOriginalPrice = formatPrice(item.originalPrice || 0, 'ALL')
  314. })
  315. const { data } = await api_shopProduct({ appId: app.globalData.appId });
  316. const list = data.data || [];
  317. let selected: any = {};
  318. let isOverSaled = true; // 是否销售完
  319. list.forEach((item: any) => {
  320. const salePrice = Number(item.salePrice || 0);
  321. const originalPrice = Number(item.originalPrice || salePrice);
  322. item.originalPrice = originalPrice;
  323. item.salePrice = salePrice;
  324. item.showSalePrice = formatPrice(salePrice, "ALL");
  325. item.showOriginalPrice = formatPrice(originalPrice, "ALL");
  326. item.typeName = this.formatPeriod(Number(item.num), item.period);
  327. item.discountPrice = formatPrice(
  328. originalPrice - salePrice,
  329. "ALL"
  330. );
  331. const prices: any = formatPrice(salePrice);
  332. item.integerPart = prices.integerPart;
  333. item.decimalPart = prices.decimalPart;
  334. // 格式化赠送内容
  335. item.giftLongTime = item.giftFlag
  336. ? this.formatGiftPeriod(item.giftVipDay, item.giftPeriod)
  337. : "";
  338. if (item.stockNum > 0) {
  339. isOverSaled = false;
  340. if (!selected.id) {
  341. selected = item;
  342. }
  343. }
  344. });
  345. if (isOverSaled) {
  346. // 没有可销售商品则默认选中第一个商品
  347. selected = list[0];
  348. }
  349. const purchaseData = {
  350. list,
  351. periodList: buildPeriodList(list),
  352. selectedPeriod: selected?.id ? String(selected.id) : '',
  353. instrumentList, // 乐器列表
  354. isOverSaled,
  355. selected,
  356. selectInstrumentId: '',
  357. selectedInstrument: {},
  358. showBonusGift: Boolean(formatGiftText(selected))
  359. };
  360. purchaseDataCache[userType] = purchaseData;
  361. this.applyPurchaseData(purchaseData);
  362. } catch (e) {
  363. console.log(e, "e");
  364. }
  365. },
  366. // 格式化类型
  367. applyPurchaseData(purchaseData: any) {
  368. const periodScrollIntoView = getPeriodScrollIntoView(
  369. purchaseData.periodList,
  370. purchaseData.selectedPeriod
  371. );
  372. this.setData({
  373. list: purchaseData.list,
  374. periodList: purchaseData.periodList,
  375. selectedPeriod: purchaseData.selectedPeriod,
  376. periodScrollIntoView,
  377. instrumentList: purchaseData.instrumentList,
  378. isOverSaled: purchaseData.isOverSaled,
  379. selected: purchaseData.selected,
  380. selectInstrumentId: purchaseData.selectInstrumentId,
  381. selectedInstrument: purchaseData.selectedInstrument,
  382. showBonusGift: purchaseData.showBonusGift
  383. }, () => {
  384. this.onFormatGoods()
  385. });
  386. },
  387. async onInitTeacherVip() {
  388. try {
  389. const { data } = await api_queryByParamNameList({
  390. paramNames: TEACHER_VIP_PARAM_NAME
  391. });
  392. const configList = data.data || [];
  393. const config = Array.isArray(configList)
  394. ? configList.find((item: any) => item.paramName === TEACHER_VIP_PARAM_NAME) || configList[0]
  395. : configList;
  396. const list = parseTeacherVipList(config?.paramValue).map((item: any, index: number) => {
  397. const salePrice = Number(item.salePrice ?? item.currentPrice ?? item.price ?? item.paymentCashAmount ?? 0);
  398. const originalPrice = Number(item.originalPrice ?? item.marketPrice ?? item.originalAmount ?? salePrice);
  399. const period = item.period || item.unit;
  400. const num = item.num ?? item.number;
  401. const typeName = item.typeName || item.label || item.title || item.name || formatPeriodText(num, period);
  402. const prices: any = formatPrice(salePrice);
  403. return {
  404. ...item,
  405. id: item.id || item.goodsId || item.value || `${TEACHER_VIP_PARAM_NAME}_${index}`,
  406. name: item.name || item.title || typeName,
  407. pic: item.pic || item.coverImg || "",
  408. coverImg: item.coverImg || item.pic || "",
  409. shopId: item.shopId || "",
  410. stockNum: item.stockNum ?? 999999,
  411. originalPrice,
  412. salePrice,
  413. num,
  414. period,
  415. showSalePrice: formatPrice(salePrice, "ALL"),
  416. showOriginalPrice: formatPrice(originalPrice, "ALL"),
  417. discountPrice: formatPrice(originalPrice - salePrice, "ALL"),
  418. typeName,
  419. giftFlag: Boolean(item.free || item.giftFlag),
  420. giftVipDay: item.free?.number ?? item.giftVipDay,
  421. giftPeriod: item.free?.unit ?? item.giftPeriod,
  422. integerPart: prices.integerPart,
  423. decimalPart: prices.decimalPart,
  424. goodsType: item.goodsType || PURCHASE_TYPE.TEACHER,
  425. };
  426. });
  427. const selected = selectDefaultTeacherVip(list);
  428. const periodList = buildPeriodList(list);
  429. const purchaseData = {
  430. list,
  431. periodList,
  432. selectedPeriod: selected?.id ? String(selected.id) : '',
  433. instrumentList: [],
  434. isOverSaled: !list.some((item: any) => item.stockNum > 0),
  435. selected,
  436. selectInstrumentId: '',
  437. selectedInstrument: {},
  438. showBonusGift: Boolean(formatGiftText(selected))
  439. };
  440. purchaseDataCache[PURCHASE_TYPE.TEACHER] = purchaseData;
  441. this.applyPurchaseData(purchaseData);
  442. } catch (e) {
  443. console.log(e, "e");
  444. this.setData({
  445. list: [],
  446. instrumentList: [],
  447. isOverSaled: true,
  448. selected: {},
  449. selectInstrumentId: '',
  450. selectedInstrument: {},
  451. showBonusGift: false
  452. }, () => {
  453. this.onFormatGoods()
  454. });
  455. }
  456. },
  457. formatPeriod(num: number, type: string) {
  458. const template: any = {
  459. DAY: "天卡",
  460. MONTH: "月卡",
  461. YEAR: "年卡",
  462. };
  463. if (type === "YEAR" && num >= 99) {
  464. return "永久卡";
  465. }
  466. return num + template[type];
  467. },
  468. formatGiftPeriod(num: number, type: string) {
  469. if (!num || !type) {
  470. return "";
  471. }
  472. const template: any = {
  473. DAY: "天",
  474. MONTH: "个月",
  475. YEAR: "年",
  476. };
  477. return num + template[type];
  478. },
  479. // 选择
  480. onSelectGoods(e: any) {
  481. const { dataset } = e.currentTarget;
  482. const item = this.data.list.find((item: any) => item.id === dataset.id);
  483. // 判断是否有库存
  484. if (item.stockNum <= 0) {
  485. return;
  486. }
  487. this.setData({
  488. selected: item || {}
  489. }, () => {
  490. this.onFormatGoods()
  491. });
  492. },
  493. /** 选中乐器 */
  494. onSelectInstrument(e: any) {
  495. if (this.data.userTypes === PURCHASE_TYPE.TEACHER) {
  496. return
  497. }
  498. const { dataset } = e.currentTarget;
  499. if (dataset.id === this.data.selectInstrumentId) {
  500. this.setData({
  501. selectInstrumentId: '',
  502. selectedInstrument: {}
  503. }, () => {
  504. this.onFormatGoods()
  505. })
  506. } else {
  507. const item = this.data.instrumentList.find((item: any) => item.id === dataset.id);
  508. this.setData({
  509. selectInstrumentId: dataset.id,
  510. selectedInstrument: item || {}
  511. }, () => {
  512. this.onFormatGoods()
  513. })
  514. }
  515. },
  516. /** 格式化选中的商品 */
  517. onFormatGoods() {
  518. const selected = this.data.selected;
  519. const selectedInstrument = this.data.selectedInstrument
  520. const params: any = {
  521. typeName: '',
  522. name: '',
  523. productImage: '',
  524. giftText: '',
  525. showSalePrice: '' as any, // 显示的现价
  526. originalPrice: 0, // 原价
  527. salePrice: 0, // 现价
  528. discountPrice: '' as any, // 已省
  529. integerPart: '',
  530. decimalPart: '',
  531. }
  532. // 选中期限
  533. if (selected.id) {
  534. params.typeName = selected.typeName
  535. params.name = selected.name
  536. params.productImage = getProductImage(selected, this.data.userTypes)
  537. params.giftText = formatGiftText(selected)
  538. params.showSalePrice = selected.showSalePrice
  539. params.originalPrice = selected.originalPrice
  540. params.salePrice = selected.salePrice
  541. params.discountPrice = selected.discountPrice
  542. const prices: any = formatPrice(params.salePrice);
  543. params.integerPart = prices.integerPart
  544. params.decimalPart = prices.decimalPart
  545. }
  546. // 选中乐器
  547. if (selectedInstrument.id) {
  548. params.typeName = selected.typeName ? selected.typeName + '+' + selectedInstrument.name : selectedInstrument.name
  549. params.name = selected.name ? selected.name + '+' + selectedInstrument.name : selectedInstrument.name
  550. params.originalPrice = Number(selected.originalPrice) + Number(selectedInstrument.originalPrice)
  551. params.salePrice = Number(selected.salePrice) + Number(selectedInstrument.salePrice)
  552. params.showSalePrice = formatPrice(params.salePrice, "ALL");
  553. params.discountPrice = formatPrice(
  554. params.originalPrice - params.salePrice,
  555. "ALL"
  556. );
  557. const prices: any = formatPrice(params.salePrice);
  558. params.integerPart = prices.integerPart
  559. params.decimalPart = prices.decimalPart
  560. }
  561. this.setData({
  562. formatSelectGood: params
  563. })
  564. },
  565. // 事件处理函数
  566. changeSwiper(e: any) {
  567. const detail = e.detail;
  568. if (detail.source === "touch" || detail.source == "autoplay") {
  569. this.setData({
  570. current: detail.current,
  571. });
  572. this.onTitlePlay();
  573. }
  574. },
  575. changeSwiperDetail(e: any) {
  576. const detail = e.detail;
  577. if (detail.source === "touch" || detail.source == "autoplay") {
  578. this.setData({
  579. detailCurrent: detail.current,
  580. });
  581. }
  582. },
  583. isLogin() {
  584. // 判断是否登录
  585. if (!app.globalData.isLogin) {
  586. wx.navigateTo({
  587. url: "../login/login",
  588. });
  589. return false;
  590. }
  591. return true;
  592. },
  593. /** 我的订单 */
  594. onOrder() {
  595. wx.navigateTo({
  596. url: "../orders/orders",
  597. });
  598. },
  599. onBuyShop() {
  600. this.setData({
  601. popupShow: true,
  602. // showSelectedProduct: true,
  603. });
  604. },
  605. /** 切换学生端/老师端 */
  606. onSwitchUserType(e: any) {
  607. const { dataset } = e.currentTarget;
  608. if (dataset.type === this.data.userTypes) {
  609. return
  610. }
  611. this.setData({
  612. userTypes: dataset.type
  613. }, () => {
  614. // 这里可以根据用户类型重新加载商品数据
  615. // 目前先保持逻辑不变,后续可根据后端 API 扩展
  616. this.onInit()
  617. })
  618. },
  619. /** 选择期限 */
  620. onSelectPeriod(e: any) {
  621. const { value } = e.currentTarget.dataset
  622. const periodItem = this.data.periodList.find((item: any) => item.value === value)
  623. if (periodItem?.disabled) {
  624. return
  625. }
  626. const selectedItem = this.data.list.find((item: any) => String(item.id) === String(value))
  627. if (!selectedItem) {
  628. return
  629. }
  630. this.setData({
  631. selectedPeriod: String(value),
  632. selected: selectedItem,
  633. periodScrollIntoView: getPeriodScrollIntoView(this.data.periodList, String(value)),
  634. showBonusGift: Boolean(formatGiftText(selectedItem))
  635. }, () => {
  636. // 根据选中的期限更新商品
  637. this.onFormatGoods()
  638. })
  639. },
  640. /** 根据期限更新商品列表 */
  641. onUpdatePeriodList() {
  642. if (this.data.userTypes === PURCHASE_TYPE.TEACHER) {
  643. return
  644. }
  645. const { selectedPeriod, list } = this.data
  646. const selectedItem = list.find((item: any) => String(item.id) === String(selectedPeriod))
  647. if (!selectedItem || Number(selectedItem.stockNum ?? 1) <= 0) {
  648. return
  649. }
  650. this.setData({
  651. selected: selectedItem,
  652. showBonusGift: Boolean(formatGiftText(selectedItem))
  653. }, () => {
  654. this.onFormatGoods()
  655. })
  656. },
  657. // 进行埋点
  658. onTrackPoint(options: { openId: string, elementName: string }) {
  659. const traceId = wx.getStorageSync("traceId");
  660. const deviceInfo = wx.getDeviceInfo();
  661. api_trackPointLog({
  662. traceId,
  663. openId: options.openId,
  664. elementName: options.elementName,
  665. deviceInfo: deviceInfo.brand + '_' + deviceInfo.model + '_' + deviceInfo.system + '_' + deviceInfo.platform,
  666. appName: "音乐数字 AI",
  667. // extParams: '',
  668. clickTime: formatTime(new Date(), '-') // 点击时间
  669. })
  670. },
  671. onClose() {
  672. this.setData({
  673. popupShow: false,
  674. });
  675. },
  676. onSubmit() {
  677. // 判断是否登录
  678. const that = this;
  679. debounce(function () {
  680. // if (!that.isLogin()) {
  681. // return;
  682. // }
  683. const params = [] as any
  684. const selected = that.data.selected
  685. if (selected.id) {
  686. params.push({
  687. pic: selected.pic,
  688. name: selected.name,
  689. originalPrice: selected.originalPrice,
  690. salePrice: selected.salePrice,
  691. shopId: selected.shopId,
  692. id: selected.id,
  693. goodsType: selected.goodsType || 'ACTIVATION_CODE', // INSTRUMENTS
  694. })
  695. }
  696. const selectedInstrument = that.data.selectedInstrument
  697. if (selectedInstrument.id) {
  698. params.push({
  699. pic: selectedInstrument.pic,
  700. name: selectedInstrument.name,
  701. originalPrice: selectedInstrument.originalPrice,
  702. salePrice: selectedInstrument.salePrice,
  703. shopId: selectedInstrument.shopId,
  704. id: selectedInstrument.id,
  705. goodsType: 'INSTRUMENTS', // INSTRUMENTS
  706. })
  707. }
  708. // openId
  709. const openId = wx.getStorageSync("openId")
  710. that.onTrackPoint({
  711. openId,
  712. elementName: "立即购买"
  713. })
  714. let info = JSON.stringify({
  715. ...params
  716. });
  717. info = encodeURIComponent(info);
  718. wx.navigateTo({
  719. url: `../orders/order-detail?orderInfo=${info}&orderType=${that.data.userTypes}`,
  720. success: () => {
  721. that.setData({
  722. popupShow: false,
  723. });
  724. },
  725. });
  726. }, 200)();
  727. },
  728. onPreivewBannerImg(e: { currentTarget: { dataset: any } }) {
  729. wx.previewImage({
  730. current: e.currentTarget.dataset.src,
  731. urls: this.data.imgList,
  732. success: () => {
  733. this.setData({
  734. isFromPreviewImage: true,
  735. });
  736. },
  737. });
  738. },
  739. onPreivewDetailImg(e: { currentTarget: { dataset: any } }) {
  740. wx.previewImage({
  741. current: e.currentTarget.dataset.src,
  742. urls: [
  743. "https://oss.dayaedu.com/ktyq/1733403675345.png",
  744. "https://oss.dayaedu.com/ktyq/1733403707851.png",
  745. "https://oss.dayaedu.com/ktyq/1733403725644.png",
  746. ],
  747. success: () => {
  748. this.setData({
  749. isFromPreviewImage: true,
  750. });
  751. },
  752. });
  753. },
  754. onPreivewDetailImg2(e: { currentTarget: { dataset: any } }) {
  755. wx.previewImage({
  756. current: e.currentTarget.dataset.src,
  757. urls: [
  758. "https://oss.dayaedu.com/ktyq/03/1772461866051.png",
  759. ],
  760. success: () => {
  761. this.setData({
  762. isFromPreviewImage: true,
  763. });
  764. },
  765. });
  766. },
  767. onPreivewGoodsImg(e: { currentTarget: { dataset: any } }) {
  768. wx.previewImage({
  769. current: e.currentTarget.dataset.src,
  770. urls: this.data.goodsImgList,
  771. success: () => {
  772. this.setData({
  773. isFromPreviewImage: true,
  774. });
  775. },
  776. });
  777. },
  778. onPreivewGoods(e: { currentTarget: { dataset: any } }) {
  779. wx.previewImage({
  780. current: e.currentTarget.dataset.src,
  781. urls: [e.currentTarget.dataset.src],
  782. success: () => {
  783. this.setData({
  784. isFromPreviewImage: true,
  785. });
  786. },
  787. });
  788. },
  789. /**
  790. * 生命周期函数--监听页面显示
  791. */
  792. onShow() {
  793. if (!this.data.isFromPreviewImage) {
  794. this.onInit();
  795. } else {
  796. this.setData({
  797. isFromPreviewImage: false,
  798. });
  799. }
  800. this.setData({
  801. serviceShow: true,
  802. });
  803. },
  804. onHide() {
  805. this.setData({
  806. serviceShow: false,
  807. });
  808. },
  809. // 页面滚动时颜色变化
  810. onScrollView(e: { detail: any }) {
  811. const top = e.detail.scrollTop || 0;
  812. // const scrollHeight = e.detail.scrollHeight || 0;
  813. // 从 100 开始显示
  814. this.setData({
  815. // opacity: top < 100 ? 0 : (top - 100) > 150 ? 1 : (top - 100) / 150
  816. opacity: top < 100 ? 0 : top - 100 > 150 ? 1 : 1,
  817. });
  818. // if (top + this.data.initialScrollHeight >= scrollHeight - 80) {
  819. // // console.log('已经滑动到底部了');
  820. // // 相应业务逻辑处理
  821. // this.setData({
  822. // scrolIntoViewStr: "type2",
  823. // });
  824. // } else {
  825. // console.log(this.data.scrollDiscount, top, this.data.headerHeight, "top");
  826. if (this.data.scrollIntoViewType) {
  827. this.setData({
  828. scrollTop: this.data.scrollDiscount
  829. ? top - this.data.headerHeight
  830. : top,
  831. scrollIntoViewType: false,
  832. scrollDiscount: false,
  833. isScrollTT: true,
  834. });
  835. } else {
  836. if (!this.data.isScrollTT) {
  837. this.onChangeScroll();
  838. } else {
  839. this.setData({
  840. isScrollTT: false,
  841. });
  842. }
  843. }
  844. // }
  845. },
  846. onChangeScroll() {
  847. const that = this;
  848. debounce(function () {
  849. wx.createSelectorQuery()
  850. .select("#type3")
  851. .boundingClientRect(function (rect) {
  852. let check = false;
  853. if (rect.top > 0 && rect.top <= that.data.headerHeight) {
  854. that.setData({
  855. scrolIntoViewStr: "type3",
  856. });
  857. check = true;
  858. }
  859. if (rect.top > 0 && rect.top > that.data.headerHeight) {
  860. that.setData({
  861. scrolIntoViewStr: "type1",
  862. });
  863. check = true;
  864. }
  865. // console.log('checked', check)
  866. if (!check) {
  867. wx.createSelectorQuery()
  868. .select("#type2")
  869. .boundingClientRect(function (rect) {
  870. if (rect.top > 0 && rect.top <= that.data.headerHeight) {
  871. that.setData({
  872. scrolIntoViewStr: "type2",
  873. });
  874. }
  875. if (rect.top > 0 && rect.top > that.data.headerHeight) {
  876. that.setData({
  877. scrolIntoViewStr: "type3",
  878. });
  879. }
  880. })
  881. .exec();
  882. }
  883. })
  884. .exec();
  885. }, 100)();
  886. },
  887. onTapAnchor(e: { currentTarget: { dataset: any } }) {
  888. const type = e.currentTarget.dataset.type;
  889. this.setData({
  890. scrolIntoView: type,
  891. scrolIntoViewStr: type,
  892. scrollDiscount: true, // type !== 'type2' ? true : false,
  893. scrollIntoViewType: true,
  894. });
  895. },
  896. onShareAppMessage() {
  897. return {
  898. title: "音乐数字 AI",
  899. path: "/pages/index/index",
  900. imageUrl: "https://oss.dayaedu.com/ktyq/1739870592907.png",
  901. };
  902. },
  903. onShareTimeline() {
  904. return {
  905. title: "音乐数字 AI",
  906. path: "/pages/index/index",
  907. imageUrl: "https://oss.dayaedu.com/ktyq/1739870592907.png",
  908. };
  909. },
  910. });