四零语境前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

535 lines
13 KiB

1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
  1. <template>
  2. <view class="container">
  3. <view class="header">
  4. <view class="header-bg">
  5. <image
  6. src="/static/会员背景.png"
  7. class="header-img"
  8. mode="scaleToFill"
  9. />
  10. <text class="header-title">会员开通</text>
  11. <!-- 加一个推出箭头 -->
  12. <view class="header-icon" @click="goBack">
  13. <uv-icon name="arrow-left" color="#000" size="20" />
  14. </view>
  15. <!-- 轮播容器 -->
  16. <view class="uv-demo-block swiper-container">
  17. <uv-swiper
  18. bgColor="transparent"
  19. :list="list"
  20. :loading="!list.length"
  21. @change="changeSwiper"
  22. keyName="img"
  23. previousMargin="70"
  24. nextMargin="70"
  25. acceleration
  26. height="75"
  27. circular
  28. :autoplay="false"
  29. radius="5"
  30. >
  31. </uv-swiper>
  32. <button class="swiper-btn">
  33. 已选择
  34. </button>
  35. <image
  36. class="swiper-arrow"
  37. src="/static/修饰箭头.png"
  38. mode="aspectFill"
  39. />
  40. </view>
  41. </view>
  42. </view>
  43. <!-- 会员套餐选择容器 -->
  44. <view class="membership-container">
  45. <!-- 套餐选择 -->
  46. <view class="package-list">
  47. <view
  48. class="package-item"
  49. :class="{ 'active': selectedPackage === index }"
  50. v-for="(item, index) in packageList"
  51. :key="index"
  52. @click="selectPackage(index)"
  53. >
  54. <view class="info">
  55. <!-- 赠送标识 -->
  56. <view class="gift-tag" v-if="item.content">
  57. {{ item.content }}
  58. </view>
  59. <view class="package-title">{{ item.title }}</view>
  60. <view class="package-price">¥{{ getInt(item.discountedprice) }}.<text class="package-decimal">{{ getDecimal(item.discountedprice) }}</text></view>
  61. <view class="package-original">¥{{ item.originalprice }}</view>
  62. </view>
  63. <view class="package-btn" :class="{ 'active': selectedPackage === index }">
  64. {{ selectedPackage === index ? '已选择' : '点击选择' }}
  65. </view>
  66. </view>
  67. </view>
  68. <!-- 优惠券选择 -->
  69. <view class="coupon-section">
  70. <view class="coupon-title">选择优惠券</view>
  71. <view class="coupon-selector" @click="selectCoupon">
  72. <view v-if="!selectedCoupon" class="coupon-placeholder">
  73. <text class="coupon-text">请选择</text>
  74. <uv-icon name="arrow-right" color="#999" size="16" />
  75. </view>
  76. <view v-else class="coupon-selected">
  77. <view class="coupon-info">
  78. <text class="coupon-name">{{ selectedCoupon.name }}</text>
  79. <text class="coupon-amount">-¥{{ selectedCoupon.money }}</text>
  80. </view>
  81. <uv-icon name="arrow-right" color="#999" size="16" />
  82. </view>
  83. </view>
  84. </view>
  85. </view>
  86. <!-- 立即开通会员按钮 -->
  87. <view class="member-button-section">
  88. <uv-button
  89. type="primary"
  90. text="立即开通会员"
  91. :custom-style="{
  92. width: '100%',
  93. height: '82rpx',
  94. borderRadius: '44rpx',
  95. backgroundColor: '#06DADC',
  96. fontSize: '36rpx',
  97. fontWeight: '500',
  98. border: '1px solid #06DADC'
  99. }"
  100. @click="handleRecharge"
  101. ></uv-button>
  102. </view>
  103. <!-- 会员权益 -->
  104. <view class="benefits-section">
  105. <view class="benefits-title">会员权益</view>
  106. <view class="benefits-list">
  107. <!-- 碎片学习 系统掌握 -->
  108. <view class="benefit-item">
  109. <view class="benefit-content">
  110. <view class="benefit-title">碎片学习 系统掌握</view>
  111. <view class="benefit-desc">根据薄弱点智能推荐每节课3-5分钟碎片化完成系统学习</view>
  112. </view>
  113. <view class="benefit-icon">
  114. <image src="/static/会员图片1.png" mode="aspectFit"></image>
  115. </view>
  116. </view>
  117. <!-- 匹配水平 -->
  118. <view class="benefit-item">
  119. <view class="benefit-content">
  120. <view class="benefit-title">匹配水平</view>
  121. <view class="benefit-desc">依据水平精准推课不做无用功快速提升</view>
  122. </view>
  123. <view class="benefit-icon">
  124. <image src="/static/会员图片2.png" mode="aspectFit"></image>
  125. </view>
  126. </view>
  127. <!-- 科学闭环测 讲练结合 -->
  128. <view class="benefit-item">
  129. <view class="benefit-content">
  130. <view class="benefit-title">科学闭环测 讲练结合</view>
  131. <view class="benefit-desc">精心设计科学的学习流程 测试-讲解-练习-检验知识掌握更牢固</view>
  132. </view>
  133. <view class="benefit-icon">
  134. <image src="/static/会员图片3.png" mode="aspectFit"></image>
  135. </view>
  136. </view>
  137. </view>
  138. </view>
  139. </view>
  140. </template>
  141. <script>
  142. export default {
  143. data() {
  144. return {
  145. list: [
  146. ],
  147. selectedPackage: 0, // 默认选择第一个套餐
  148. selectedMember: 0, // 默认选择第一个会员
  149. defaultPackageList: [
  150. ],
  151. couponId: '',
  152. selectedCoupon: null // 选中的优惠券信息
  153. }
  154. },
  155. computed:{
  156. packageList(){
  157. return this.list[this.selectedMember].setmeals.length ? this.list[this.selectedMember].setmeals : this.defaultPackageList
  158. }
  159. },
  160. methods: {
  161. handleCouponSelected(coupon) {
  162. // 处理选中的优惠券
  163. this.selectedCoupon = coupon
  164. this.couponId = coupon.id
  165. uni.showToast({
  166. title: `已选择优惠券:¥${coupon.money}`,
  167. icon: 'success'
  168. })
  169. },
  170. async handleRecharge(){
  171. // console.log('选中的会员id是:', this.packageList[this.selectedPackage]);
  172. const object = {
  173. // #ifdef H5
  174. type : 'official',
  175. // #endif
  176. memberId: this.list[this.selectedMember].id,
  177. setmealId: this.packageList[this.selectedPackage].id
  178. }
  179. if (this.couponId) {
  180. object.couponId = this.couponId
  181. }
  182. const res = await this.$api.member.openMember({...object})
  183. if (res.code === 200){
  184. if (res.result === 0){
  185. // 零元购
  186. uni.showToast({
  187. title: '充值成功',
  188. icon: 'success'
  189. })
  190. this.goBack()
  191. }else {
  192. // 调起微信支付
  193. this.$utils.wxPay(res.result, (res) => {
  194. setTimeout(() => {
  195. this.goBack()
  196. }, 1000)
  197. })
  198. }
  199. }
  200. },
  201. goBack(){
  202. uni.navigateBack()
  203. },
  204. // 截取价格的整数与小数部分
  205. getInt(pri){
  206. const price = String(pri)
  207. if (price.indexOf('.') === -1) {
  208. return price
  209. }
  210. if (price === null) {
  211. return '0'
  212. }
  213. return String(price).split('.')[0]
  214. },
  215. getDecimal(pri){
  216. const price = String(pri)
  217. if (price === null) return '00'
  218. const parts = price.split('.')
  219. return parts[1] ? parts[1].padEnd(2, '0') : '00'
  220. },
  221. selectPackage(index) {
  222. this.selectedPackage = index
  223. },
  224. selectCoupon() {
  225. uni.navigateTo({
  226. url: '/subPages/user/discount?from=recharge'
  227. })
  228. },
  229. async getMemberList(){
  230. const memberRes = await this.$api.member.getMemberList()
  231. if (memberRes.code === 200){
  232. this.list = memberRes.result
  233. }
  234. },
  235. changeSwiper(e){
  236. this.selectedMember = e.current
  237. this.selectedPackage = 0
  238. }
  239. },
  240. onShow(){
  241. // 监听优惠券选择事件
  242. uni.$on('couponSelected', this.handleCouponSelected)
  243. this.getMemberList()
  244. },
  245. onUnload() {
  246. // 移除事件监听
  247. uni.$off('couponSelected', this.handleCouponSelected)
  248. console.log('接触监听');
  249. },
  250. }
  251. </script>
  252. <style lang="scss" scoped>
  253. .container {
  254. min-height: 100%;
  255. }
  256. .header{
  257. width: 100%;
  258. .header-bg{
  259. position: relative;
  260. width: 100%;
  261. height: 500rpx;
  262. // background: red;
  263. .header-img{
  264. width: 100%;
  265. height: 500rpx;
  266. }
  267. .header-title{
  268. font-size: 32rpx;
  269. color: black;
  270. position: absolute;
  271. top: 100rpx;
  272. font-weight: 500;
  273. left: 50%;
  274. transform: translateX(-50%);
  275. }
  276. .header-icon{
  277. position: absolute;
  278. top: 100rpx;
  279. left: 30rpx;
  280. }
  281. .swiper-container{
  282. margin-top: -300rpx;
  283. .swiper-arrow{
  284. width: 100%;
  285. height: 22rpx;
  286. }
  287. .swiper-btn{
  288. margin: 35rpx auto 15rpx;
  289. width: 150rpx;
  290. height: 52rpx;
  291. border-radius: 999px;
  292. background: #06DADC;
  293. color: white;
  294. font-size: 28rpx;
  295. font-weight: 500;
  296. text-align: center;
  297. line-height: 52rpx;
  298. }
  299. }
  300. }
  301. }
  302. /* 立即开通会员按钮样式 */
  303. .member-button-section {
  304. margin: 0 50rpx 40rpx;
  305. }
  306. // 会员套餐选择容器
  307. .membership-container {
  308. background: linear-gradient(180deg, #DEFFFF 0%, #FBFEFF 22.65%, #FFFFFF 100%);
  309. padding: 40rpx 30rpx;
  310. margin-top: 20rpx;
  311. .package-list {
  312. display: flex;
  313. justify-content: space-between;
  314. gap: 16rpx;
  315. margin-bottom: 20rpx;
  316. .package-item {
  317. position: relative;
  318. flex: 1;
  319. background: #fff;
  320. border-radius: 20rpx;
  321. text-align: center;
  322. border: 2rpx solid #EEEEEE;
  323. transition: all 0.3s;
  324. // width: 119;
  325. height: 210rpx;
  326. // width: 238rpx;
  327. .info{
  328. padding: 16rpx 16rpx 0 16rpx ;
  329. }
  330. &.active {
  331. border-color: $primary-color;
  332. // box-shadow: 0 4rpx 20rpx rgba(34, 242, 235, 0.2);
  333. }
  334. .gift-tag {
  335. position: absolute;
  336. top: -10rpx;
  337. left: 0%;
  338. // transform: translateX(-50%);
  339. background: #FF6B6B;
  340. color: #fff;
  341. font-size: 20rpx;
  342. padding: 8rpx 16rpx;
  343. border-radius: 20rpx 20rpx 20rpx 0;
  344. white-space: nowrap;
  345. }
  346. .package-title {
  347. font-size: 28rpx;
  348. color: #000;
  349. margin-bottom: 16rpx;
  350. font-weight: 500;
  351. }
  352. .package-price {
  353. font-size: 36rpx;
  354. color: #FF4800;
  355. font-weight: 500;
  356. margin-bottom: 8rpx;
  357. .package-decimal{
  358. font-size: 24rpx;
  359. }
  360. }
  361. .package-original {
  362. font-size: 24rpx;
  363. color: #8B8B8B;
  364. line-height: 1.4;
  365. text-decoration: line-through;
  366. margin-bottom: 8rpx;
  367. }
  368. .package-btn {
  369. background: #E4E7EB;
  370. color: #191919;
  371. font-size: 28rpx;
  372. // padding: 12rpx 20rpx;
  373. width: 100%;
  374. // border-radius: 30rpx;
  375. transition: all 0.3s;
  376. height: 52rpx;
  377. line-height: 52rpx;
  378. border-radius: 0 0 24rpx 24rpx;
  379. &.active {
  380. background: $primary-color;
  381. color: #fff;
  382. }
  383. }
  384. }
  385. }
  386. .coupon-section {
  387. .coupon-title {
  388. font-size: 26rpx;
  389. color: #181818;
  390. margin-bottom: 10rpx;
  391. // font-weight: 500;
  392. }
  393. .coupon-selector {
  394. background: #fff;
  395. border-radius: 16rpx;
  396. padding: 10rpx 0;
  397. display: flex;
  398. justify-content: space-between;
  399. align-items: center;
  400. border-bottom: 2rpx solid #f0f0f0;
  401. .coupon-placeholder {
  402. display: flex;
  403. justify-content: space-between;
  404. align-items: center;
  405. width: 100%;
  406. .coupon-text {
  407. font-size: 32rpx;
  408. color: #C6C6C6;
  409. }
  410. }
  411. .coupon-selected {
  412. display: flex;
  413. justify-content: space-between;
  414. align-items: center;
  415. width: 100%;
  416. .coupon-info {
  417. display: flex;
  418. // flex-direction: column;
  419. align-items: center;
  420. justify-content: space-between;
  421. .coupon-name {
  422. font-size: 28rpx;
  423. color: #181818;
  424. margin-bottom: 4rpx;
  425. }
  426. .coupon-amount {
  427. font-size: 28rpx;
  428. color: red;
  429. font-weight: 500;
  430. }
  431. }
  432. }
  433. }
  434. }
  435. }
  436. /* 会员权益样式 */
  437. .benefits-section {
  438. margin-top: 40rpx;
  439. padding: 0 30rpx;
  440. }
  441. .benefits-title {
  442. font-size: 36rpx;
  443. font-weight: bold;
  444. color: #191919;
  445. margin-bottom: 32rpx;
  446. }
  447. .benefits-list {
  448. display: flex;
  449. flex-direction: column;
  450. gap: 32rpx;
  451. }
  452. .benefit-item {
  453. background: #F8F8F8;
  454. border: 1px solid #FFFFFF;
  455. border-radius: 48rpx;
  456. padding: 27rpx 40rpx;
  457. display: flex;
  458. align-items: center;
  459. justify-content: space-between;
  460. }
  461. .benefit-content {
  462. flex: 1;
  463. margin-right: 40rpx;
  464. }
  465. .benefit-title {
  466. font-size: 32rpx;
  467. font-weight: 600;
  468. color: #333;
  469. margin-bottom: 16rpx;
  470. }
  471. .benefit-desc {
  472. font-size: 24rpx;
  473. color: #09B1B3;
  474. line-height: 36rpx;
  475. }
  476. .benefit-icon {
  477. width: 152rpx;
  478. height: 152rpx;
  479. // flex-shrink: 0;
  480. }
  481. .benefit-icon image {
  482. width: 100%;
  483. height: 100%;
  484. }
  485. </style>