index.tsx 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. import { computed, defineComponent, onMounted, reactive, shallowRef } from 'vue'
  2. import styles from './index.module.less'
  3. import ColHeader from '@/components/col-header'
  4. import { Button, Image, Popup, Toast } from 'vant'
  5. import { state as baseState, setLogin } from '@/state'
  6. import iconShare from './new-images/icon-share.png'
  7. import { useEventListener } from '@vant/use'
  8. import ColShare from '@/components/col-share'
  9. import iconMemberLogo from './images/member_logo.png'
  10. import iconStudent from '@common/images/icon_student.png'
  11. import iconTeacher from '@common/images/icon_teacher.png'
  12. import iconGift from './new-images/icon-discount-gift.png'
  13. import request from '@/helpers/request'
  14. import MemberInteres from './components/member-interes'
  15. import ColSticky from '@/components/col-sticky'
  16. import { moneyFormat } from '@/helpers/utils'
  17. import { useRoute, useRouter } from 'vue-router'
  18. import deepClone from '@/helpers/deep-clone'
  19. import { memberSimpleType, memberType } from '@/constant'
  20. import dayjs from 'dayjs'
  21. import { orderStatus } from '../order-detail/orderStatus'
  22. export default defineComponent({
  23. name: 'member-center',
  24. setup() {
  25. const route = useRoute()
  26. const router = useRouter()
  27. const vipList = shallowRef([] as any)
  28. const svipList = shallowRef([] as any)
  29. const state = reactive({
  30. activityId: route.query.activityId,
  31. recomUserId: route.query.recomUserId,
  32. titleOpacity: 0,
  33. shareStatus: false, // 分享
  34. dialogVisiable: false,
  35. shareUrl: '',
  36. shareDiscount: 0,
  37. discountTeacher: {
  38. avatar: '',
  39. discount: 0,
  40. username: ''
  41. }, // 优惠折扣老师
  42. apiSuffix:
  43. baseState.platformType === 'STUDENT' ? '/api-student' : '/api-teacher',
  44. tabActive: 'SVIP' as 'SVIP' | 'VIP', // 当前选中
  45. selectMember: {} as any, // 选中的数据
  46. memberShowList: [] // 购买商品信息
  47. })
  48. const userInfo = computed(() => {
  49. const users = baseState.user.data
  50. return {
  51. username: users?.username,
  52. phone: users?.phone,
  53. avatar: users?.heardUrl,
  54. id: users?.userId,
  55. userVip: users?.userVip
  56. }
  57. })
  58. // 是否为永久会员
  59. const isPermanent = computed(() => {
  60. return userInfo.value.userVip?.vipType === 'PERMANENT_SVIP' ? true : false
  61. })
  62. // 购买按钮文案
  63. const btnSubmitText = computed(() => {
  64. if (isPermanent.value) {
  65. return '您已是永久SVIP会员'
  66. } else if (userMemberStatus.value === 'EXPIREVIP') {
  67. return '立即续费'
  68. } else if (userMemberStatus.value === 'NOT_VIP') {
  69. if (state.selectMember?.id) {
  70. // ¥988/永久SVIP 立即开通
  71. return `¥${calcSalePrice(state.selectMember)}/${
  72. memberSimpleType[state.selectMember?.period]
  73. }${state.tabActive} 立即开通`
  74. } else {
  75. return '立即开通'
  76. }
  77. }
  78. return '立即续费'
  79. })
  80. /** 当前用户会员状态 动态判断vip svip */
  81. const userMemberStatus = computed(() => {
  82. // vip类型 VIP:会员 SVIP:SVIP,PERMANENT_SVIP:永久SVIP,NOT_VIP:不是vip
  83. // vip过期类型 VIP:会员 SVIP:SVIP,ALL_VIP:全vip
  84. if (state.tabActive === 'SVIP') {
  85. if (userInfo.value.userVip?.vipType === 'PERMANENT_SVIP') {
  86. return 'PERMANENT'
  87. } else if (
  88. userInfo.value.userVip?.vipType === 'SVIP' ||
  89. userInfo.value.userVip?.svipEndDays > 0
  90. ) {
  91. return 'VIP'
  92. } else if (
  93. ['SVIP', 'ALL_VIP'].includes(userInfo.value.userVip?.expireVipType)
  94. ) {
  95. return 'EXPIREVIP'
  96. } else if (userInfo.value.userVip?.vipType === 'NOT_VIP') {
  97. return 'NOT_VIP'
  98. }
  99. } else if (state.tabActive === 'VIP') {
  100. if (
  101. userInfo.value.userVip?.vipType === 'VIP' ||
  102. userInfo.value.userVip?.vipEndDays > 0
  103. ) {
  104. return 'VIP'
  105. } else if (
  106. ['VIP', 'ALL_VIP'].includes(userInfo.value.userVip?.expireVipType)
  107. ) {
  108. return 'EXPIREVIP'
  109. } else if (userInfo.value.userVip?.vipType === 'NOT_VIP') {
  110. return 'NOT_VIP'
  111. }
  112. }
  113. return 'NOT_VIP'
  114. })
  115. /** 会员信息 */
  116. const memberInfos = computed(() => {
  117. return {
  118. memberLength: state.memberShowList.length,
  119. vipLength: vipList.value.legnth,
  120. svipLength: svipList.value.legnth,
  121. onlyVip:
  122. vipList.value.length > 0 && svipList.value.length <= 0 ? true : false,
  123. onlySVip:
  124. svipList.value.length > 0 && vipList.value.length <= 0 ? true : false,
  125. hasAll:
  126. vipList.value.length > 0 && svipList.value.length > 0 ? true : false
  127. }
  128. })
  129. /** 分享 */
  130. const onShare = async () => {
  131. try {
  132. const res = await request.post('/api-teacher/open/vipProfit', {
  133. data: {
  134. userId: userInfo.value.id
  135. }
  136. })
  137. state.shareUrl = `${location.origin}/teacher#/shareVip?recomUserId=${userInfo.value.id}&userType=${baseState.platformType}`
  138. // 判断是否有我分享的编号
  139. if (res.data && res.data.activityId) {
  140. state.shareUrl = state.shareUrl + '&activityId=' + res.data.activityId
  141. }
  142. state.shareStatus = true
  143. state.shareDiscount = res.data.discount || 0
  144. return
  145. } catch {
  146. //
  147. }
  148. }
  149. useEventListener('scroll', () => {
  150. const height =
  151. window.scrollY ||
  152. window.pageYOffset ||
  153. document.documentElement.scrollTop
  154. state.titleOpacity = height > 100 ? 1 : height / 100
  155. })
  156. /** 切换购买类型 */
  157. const onChangeTab = (type: 'SVIP' | 'VIP') => {
  158. if (type === 'SVIP') {
  159. state.memberShowList = deepClone(svipList.value)
  160. state.selectMember = state.memberShowList[0]
  161. } else if (type === 'VIP') {
  162. state.memberShowList = deepClone(vipList.value)
  163. state.selectMember = state.memberShowList[0]
  164. }
  165. state.tabActive = type
  166. }
  167. const calcSalePrice = (item: any) => {
  168. // discount
  169. if (item.discount === 1) {
  170. const tempPrice = Number(
  171. (item.salePrice - item.discountPrice).toFixed(2)
  172. )
  173. return tempPrice >= 0 ? tempPrice : 0
  174. }
  175. return item.salePrice
  176. }
  177. const onSubmit = async () => {
  178. try {
  179. // 永久会员
  180. if (isPermanent.value) return
  181. const { data } = await request.post(
  182. `${state.apiSuffix}/memberPriceSettings/list`,
  183. {
  184. data: {
  185. status: 1
  186. }
  187. }
  188. )
  189. const result = data.list || []
  190. const selectItem = result.find(
  191. (item: any) => item.id === state.selectMember?.id
  192. )
  193. // 状态、售价变更时
  194. if (
  195. !selectItem ||
  196. (selectItem && selectItem.salePrice !== state.selectMember.salePrice)
  197. ) {
  198. state.dialogVisiable = true
  199. return
  200. }
  201. const member: any = state.selectMember
  202. // 判断是否有会员
  203. let startTime = new Date()
  204. // vip类型 VIP:会员 SVIP:SVIP,PERMANENT_SVIP:永久SVIP,NOT_VIP:不是vip
  205. // vip过期类型 VIP:会员 SVIP:SVIP,ALL_VIP:全vip
  206. if (userInfo.value.userVip.vipType === 'SVIP') {
  207. startTime = dayjs(
  208. userInfo.value.userVip.svipEndDate || new Date()
  209. ).toDate()
  210. } else if (userInfo.value.userVip.vipType === 'VIP') {
  211. startTime = dayjs(
  212. userInfo.value.userVip.vipEndDate || new Date()
  213. ).toDate()
  214. } else if (userInfo.value.userVip.vipType === 'PERMANENT_SVIP') {
  215. Toast('您已是永久SVIP会员')
  216. return
  217. }
  218. let endTime = new Date()
  219. if (member.period === 'MONTH') {
  220. endTime = dayjs(startTime).add(1, 'month').toDate()
  221. } else if (member.period === 'QUARTERLY') {
  222. endTime = dayjs(startTime).add(3, 'month').toDate()
  223. } else if (member.period === 'YEAR_HALF') {
  224. endTime = dayjs(startTime).add(6, 'month').toDate()
  225. } else if (member.period === 'YEAR') {
  226. endTime = dayjs(startTime).add(1, 'year').toDate()
  227. }
  228. orderStatus.orderObject.orderType = state.tabActive
  229. orderStatus.orderObject.orderName = `小酷Ai ${state.tabActive} ${member.title}`
  230. orderStatus.orderObject.orderDesc = `小酷Ai ${state.tabActive} ${member.title}`
  231. orderStatus.orderObject.actualPrice = calcSalePrice(member)
  232. orderStatus.orderObject.recomUserId = state.recomUserId
  233. orderStatus.orderObject.activityId = state.activityId
  234. orderStatus.orderObject.orderNo = ''
  235. orderStatus.orderObject.orderList = [
  236. {
  237. orderType: state.tabActive,
  238. goodsName: `小酷Ai ${state.tabActive} ${member.title}`,
  239. id: member.id,
  240. title: member.title,
  241. num: 1, // 购买个数
  242. salePrice: member.salePrice,
  243. period: member.period,
  244. vipEndDays: userInfo.value.userVip?.vipEndDays || 0, // 会员剩余天数
  245. discount: member.discount, // 是否有折扣
  246. discountPrice: member.discountPrice, // 折扣金额
  247. price: calcSalePrice(member),
  248. startTime: dayjs(startTime).format('YYYY-MM-DD'),
  249. endTime: dayjs(endTime).format('YYYY-MM-DD'),
  250. recomUserId: state.recomUserId
  251. }
  252. ]
  253. router.push({
  254. path: '/orderDetail',
  255. query: {
  256. orderType: state.tabActive
  257. }
  258. })
  259. } catch {
  260. //
  261. }
  262. }
  263. /** 格式化分类信息 */
  264. const formatMemberList = () => {
  265. // console.log(vipList.value, svipList.value, 'vipList.value')
  266. const onlyVip =
  267. vipList.value.length > 0 && svipList.value.length <= 0 ? true : false
  268. const onlySVip =
  269. svipList.value.length > 0 && vipList.value.length <= 0 ? true : false
  270. const hasAll =
  271. vipList.value.length > 0 && svipList.value.length > 0 ? true : false
  272. if (hasAll) {
  273. state.tabActive = 'SVIP'
  274. state.memberShowList = deepClone(svipList.value)
  275. } else if (onlySVip) {
  276. state.tabActive = 'SVIP'
  277. state.memberShowList = deepClone(svipList.value)
  278. } else if (onlyVip) {
  279. state.tabActive = 'VIP'
  280. state.memberShowList = deepClone(vipList.value)
  281. }
  282. if (state.memberShowList.length > 0) {
  283. // 判断是否有数据更新了,需要重新为选择的赋值
  284. const item = state.memberShowList.find(
  285. (item: any) => item.id === state.selectMember?.id
  286. )
  287. if (item) {
  288. state.selectMember = item
  289. } else {
  290. state.selectMember = state.memberShowList[0]
  291. }
  292. }
  293. }
  294. const _init = async () => {
  295. try {
  296. const { data } = await request.post(
  297. `${state.apiSuffix}/memberPriceSettings/list`,
  298. {
  299. data: {
  300. activityId: Number(state.activityId),
  301. userId: state.recomUserId,
  302. status: 1
  303. }
  304. }
  305. )
  306. const { list, ...more } = data
  307. state.discountTeacher = {
  308. ...more
  309. }
  310. const result = list || []
  311. const vipTemp = [] as any
  312. const svipTemp = [] as any
  313. result.forEach((item: any) => {
  314. item.title = memberType[item.period]
  315. if (item.vipType === 'VIP' && item.period !== 'DAY') {
  316. vipTemp.push(item)
  317. } else if (item.vipType === 'SVIP' && item.period !== 'DAY') {
  318. svipTemp.push(item)
  319. }
  320. })
  321. vipList.value = vipTemp ? vipTemp.reverse() : []
  322. svipList.value = svipTemp ? svipTemp.reverse() : []
  323. formatMemberList()
  324. } catch {
  325. //
  326. }
  327. }
  328. onMounted(async () => {
  329. try {
  330. const userInfo = await request.get(
  331. baseState.platformType === 'TEACHER'
  332. ? '/api-teacher/teacher/queryUserInfo'
  333. : '/api-student/student/queryUserInfo'
  334. )
  335. setLogin(userInfo.data)
  336. _init()
  337. } catch {
  338. //
  339. }
  340. })
  341. return () => (
  342. <div class={styles.memberCenter}>
  343. <ColHeader
  344. background={`rgba(255,255,255, ${state.titleOpacity})`}
  345. color={`rgba(0,0,0, ${state.titleOpacity})`}
  346. backIconColor="black"
  347. hideHeader={false}
  348. v-slots={{
  349. right: () => (
  350. <Image
  351. src={iconShare}
  352. class={styles.shareBtn}
  353. onClick={onShare}
  354. />
  355. )
  356. }}
  357. />
  358. <div class={styles.memberContainer}>
  359. <i class={styles.showBrid}></i>
  360. <div class={styles.userSection}>
  361. <div
  362. class={[
  363. styles.userImgSection,
  364. state.tabActive === 'VIP' ? styles.userVip : styles.userSVip,
  365. userMemberStatus.value === 'PERMANENT' ||
  366. userMemberStatus.value === 'VIP'
  367. ? styles.isVip
  368. : ''
  369. // userMemberStatus.value === 'EXPIREVIP' ? styles.expireVip : ''
  370. ]}
  371. >
  372. <Image
  373. class={styles.userImg}
  374. src={userInfo.value.avatar || iconStudent}
  375. fit="cover"
  376. />
  377. <i class={styles.showMemeber}></i>
  378. </div>
  379. <div class={styles.userInfo}>
  380. <div class={styles.userName}>
  381. <span class={styles.name}>{userInfo.value.username}</span>
  382. {userInfo.value.phone && (
  383. <span class={styles.phone}>({userInfo.value.phone})</span>
  384. )}
  385. </div>
  386. <div class={styles.member_time}>
  387. {userMemberStatus.value === 'PERMANENT' && (
  388. <>
  389. 您已是<span>永久SVIP</span>
  390. </>
  391. )}
  392. {userMemberStatus.value === 'VIP' && (
  393. <>
  394. 有效期至{' '}
  395. <span>
  396. {state.tabActive === 'VIP'
  397. ? dayjs(userInfo.value.userVip.vipEndDate).format(
  398. 'YYYY-MM-DD'
  399. )
  400. : dayjs(userInfo.value.userVip.svipEndDate).format(
  401. 'YYYY-MM-DD'
  402. )}
  403. </span>
  404. </>
  405. )}
  406. {userMemberStatus.value === 'EXPIREVIP' && (
  407. <>
  408. 您的{state.tabActive}已过期,续费后{state.tabActive}
  409. 权益可继续使用
  410. </>
  411. )}
  412. {userMemberStatus.value === 'NOT_VIP' && (
  413. <>您还未开通{state.tabActive}会员哦~</>
  414. )}
  415. </div>
  416. </div>
  417. </div>
  418. <div class={styles.memberSection}>
  419. {memberInfos.value.hasAll ? (
  420. <>
  421. <div class={styles.member_tabs}>
  422. <div
  423. class={[
  424. styles.member_tab,
  425. state.tabActive === 'VIP' ? styles.member_tab_active : ''
  426. ]}
  427. onClick={() => onChangeTab('VIP')}
  428. >
  429. <div class={[styles.top_tab, styles.top_tab_vip]}>
  430. <i class={[styles.icon_member]}></i>
  431. <span class={styles.icon_text}>
  432. <i class={styles.bottom_line}></i>
  433. </span>
  434. </div>
  435. <div class={styles.vip_member_tip}></div>
  436. </div>
  437. <div
  438. class={[
  439. styles.member_tab,
  440. state.tabActive === 'SVIP' ? styles.member_tab_active : ''
  441. ]}
  442. onClick={() => onChangeTab('SVIP')}
  443. >
  444. <div class={[styles.top_tab, styles.top_tab_svip]}>
  445. <i class={[styles.icon_member]}></i>
  446. <span class={styles.icon_text}>
  447. <i class={styles.bottom_line}></i>
  448. </span>
  449. </div>
  450. <div class={styles.svip_member_tip}></div>
  451. </div>
  452. </div>
  453. </>
  454. ) : memberInfos.value.onlyVip ? (
  455. <div class={styles.member_tabs}>
  456. <div
  457. class={[
  458. styles.member_tab,
  459. styles.member_tab_active,
  460. styles.member_tab_single
  461. ]}
  462. >
  463. <div class={[styles.top_tab, styles.top_tab_vip]}>
  464. <i class={[styles.icon_member]}></i>
  465. <span class={styles.icon_text}>
  466. <i class={styles.bottom_line}></i>
  467. </span>
  468. </div>
  469. <div class={styles.vip_member_tip}></div>
  470. </div>
  471. </div>
  472. ) : memberInfos.value.onlySVip ? (
  473. // 只有SVIP
  474. <div class={styles.member_tabs}>
  475. <div
  476. class={[
  477. styles.member_tab,
  478. styles.member_tab_active,
  479. styles.member_tab_single
  480. ]}
  481. >
  482. <div class={[styles.top_tab, styles.top_tab_svip]}>
  483. <i class={[styles.icon_member]}></i>
  484. <span class={styles.icon_text}>
  485. <i class={styles.bottom_line}></i>
  486. </span>
  487. </div>
  488. <div class={styles.svip_member_tip}></div>
  489. </div>
  490. </div>
  491. ) : null}
  492. {/* 判断是否有推荐老师 */}
  493. {state.discountTeacher.discount == 1 && (
  494. <div class={styles.memberDiscount}>
  495. <Image
  496. src={state.discountTeacher.avatar || iconTeacher}
  497. class={styles.discountAvatar}
  498. />
  499. <span class={styles.discountName}>
  500. {state.discountTeacher.username}老师的<span>专属优惠~</span>
  501. </span>
  502. <Image src={iconGift} class={styles.discountGift} />
  503. </div>
  504. )}
  505. {/* 选择会员模式 */}
  506. {(vipList.value.length > 0 || svipList.value.length > 0) && (
  507. <div class={styles.system_list_section}>
  508. <div
  509. class={[
  510. styles['system-list'],
  511. state.tabActive === 'VIP' ? styles.system_list_vip : '',
  512. memberInfos.value.memberLength === 2 ? styles.list_two : '',
  513. memberInfos.value.memberLength === 1 ? styles.list_one : ''
  514. ]}
  515. >
  516. {memberInfos.value.memberLength >= 2 ? (
  517. <>
  518. {state.memberShowList.map((member: any) => (
  519. <div
  520. class={[
  521. styles['system-item'],
  522. member.id === state.selectMember.id
  523. ? styles.active
  524. : '',
  525. member.discount === 1 ? styles.discountItem : ''
  526. ]}
  527. onClick={() => {
  528. state.selectMember = member
  529. }}
  530. >
  531. {/* 只有永久才会有数量提示 */}
  532. {member.period === 'PERPETUAL' && (
  533. <span class={[styles.iconPermanent]}></span>
  534. )}
  535. <p class={styles.s_title}>{member.title}</p>
  536. {member.discount === 1 && (
  537. <span class={styles.discountTag}></span>
  538. )}
  539. <p class={styles.price}>
  540. <span>¥</span>
  541. {moneyFormat(calcSalePrice(member), '0,0[.]00')}
  542. </p>
  543. <del
  544. class={[
  545. styles.originalPrice,
  546. calcSalePrice(member) >= member.originalPrice ||
  547. member.desc
  548. ? styles.originalPriceHide
  549. : ''
  550. ]}
  551. >
  552. ¥{moneyFormat(member.originalPrice, '0,0[.]00')}
  553. </del>
  554. {member.desc && (
  555. <p class={styles.extraTip}>{member.desc}</p>
  556. )}
  557. </div>
  558. ))}
  559. </>
  560. ) : (
  561. <>
  562. {/* 一条数据的样式 */}
  563. {state.memberShowList.map((member: any) => (
  564. <div class={[styles['system-item']]}>
  565. {/* 只有永久才会有数量提示 */}
  566. {member.period === 'PERPETUAL' && (
  567. <span class={[styles.iconPermanent]}></span>
  568. )}
  569. {member.discount === 1 && (
  570. <span class={styles.discountTag}></span>
  571. )}
  572. <div class={styles.oneInfo}>
  573. <div class={styles.priceS}>
  574. <p class={styles.price}>
  575. <span>¥</span>
  576. {moneyFormat(calcSalePrice(member), '0,0[.]00')}
  577. </p>
  578. <p class={styles.s_title}>{member.title}</p>
  579. </div>
  580. {/* 只有永久才会有数量提示 */}
  581. {member.period === 'PERPETUAL' ? (
  582. <div class={styles.oneMaxNum}>限量1000份</div>
  583. ) : (
  584. <div
  585. class={[
  586. styles.oneMaxNum,
  587. styles.oneMaxNumPrice
  588. ]}
  589. >
  590. ¥{member.originalPrice}
  591. </div>
  592. )}
  593. </div>
  594. <span
  595. class={[
  596. styles.oneBtn,
  597. ['EXPIREVIP', 'VIP', 'PERMANENT'].includes(
  598. userMemberStatus.value
  599. )
  600. ? styles.onBtnRenew
  601. : '',
  602. userMemberStatus.value === 'PERMANENT'
  603. ? styles.onBtnDisbled
  604. : ''
  605. ]}
  606. onClick={() => {
  607. if (userMemberStatus.value === 'PERMANENT') return
  608. onSubmit()
  609. }}
  610. ></span>
  611. <i class={styles.itemBg}></i>
  612. </div>
  613. ))}
  614. </>
  615. )}
  616. </div>
  617. </div>
  618. )}
  619. {/* 是选择会员 会员天数大于0 */}
  620. {state.tabActive === 'VIP' &&
  621. userInfo.value.userVip?.vipEndDays > 0 && (
  622. <div class={styles.discountTips}>
  623. 购买VIP的会员续费SVIP年度会员,
  624. <span>原VIP会员天数升级为SVIP</span>
  625. </div>
  626. )}
  627. <MemberInteres type={state.tabActive} />
  628. </div>
  629. </div>
  630. {(vipList.value.length > 0 || svipList.value.length > 0) && (
  631. <ColSticky position="bottom">
  632. <div class={styles.btnGroup}>
  633. <Button
  634. block
  635. color="linear-gradient( 241deg, #FFD984 0%, #FFEAB9 100%)"
  636. class={[
  637. styles.btn,
  638. isPermanent.value ? styles.btnDisabled : ''
  639. ]}
  640. onClick={onSubmit}
  641. >
  642. {btnSubmitText.value}
  643. </Button>
  644. </div>
  645. </ColSticky>
  646. )}
  647. <Popup
  648. v-model:show={state.shareStatus}
  649. style={{ background: 'transparent' }}
  650. >
  651. <ColShare
  652. teacherId={userInfo.value.id}
  653. shareUrl={state.shareUrl}
  654. shareType="vip"
  655. shareLength={2}
  656. >
  657. <div class={styles.shareVip}>
  658. {state.shareDiscount === 1 && (
  659. <div class={styles.tagDiscount}>专属优惠</div>
  660. )}
  661. <img class={styles.icon} src={iconMemberLogo} />
  662. <div class={styles.info}>
  663. <h4 class="van-multi-ellipsis--l2">小酷Ai会员</h4>
  664. <p>海量曲谱、智能评测,专为器乐学习者量身打造</p>
  665. </div>
  666. </div>
  667. </ColShare>
  668. </Popup>
  669. <Popup
  670. v-model:show={state.dialogVisiable}
  671. style={{ background: 'transparent' }}
  672. closeOnClickOverlay={false}
  673. >
  674. <div class={styles.dialogContainer}>
  675. <div class={styles.dialogTitle}>提示</div>
  676. <div class={styles.dialogContent}>产品信息已更新,请重新选择</div>
  677. <div class={styles.dialogBtnGroup}>
  678. <Button
  679. round
  680. type="primary"
  681. block
  682. class={styles.dialogBtn}
  683. onClick={() => {
  684. _init()
  685. state.dialogVisiable = false
  686. }}
  687. >
  688. 重新选择
  689. </Button>
  690. </div>
  691. </div>
  692. </Popup>
  693. </div>
  694. )
  695. }
  696. })