2026-01-28 18:00:39 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view class="page">
|
|
|
|
|
|
<u-navbar title="推广领取" :border-bottom="false" :background="bgc" back-icon-color="#111827" title-color="#111827"
|
|
|
|
|
|
title-size="34" title-bold height="44" id="navbar">
|
|
|
|
|
|
</u-navbar>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 顶部卡片 -->
|
|
|
|
|
|
<view class="hero">
|
|
|
|
|
|
<view class="hero-bg">
|
|
|
|
|
|
<view class="b b1"></view>
|
|
|
|
|
|
<view class="b b2"></view>
|
|
|
|
|
|
<view class="b b3"></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="hero-content">
|
|
|
|
|
|
<view class="hero-title">专属福利已解锁</view>
|
|
|
|
|
|
<view class="hero-sub">扫码进入后可领取运营区会员卡并购买</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 列表 -->
|
|
|
|
|
|
<view class="list">
|
|
|
|
|
|
<view class="section-title">
|
|
|
|
|
|
<text class="st-main">可购买会员卡</text>
|
|
|
|
|
|
<text class="st-sub" v-if="areaName">运营区:{{ areaName }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="loading" v-if="loading">
|
|
|
|
|
|
<view class="skeleton" v-for="n in 3" :key="n">
|
|
|
|
|
|
<view class="sk-line w60"></view>
|
|
|
|
|
|
<view class="sk-line w40"></view>
|
|
|
|
|
|
<view class="sk-btn"></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<text class="loading-text">加载中...</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view v-else>
|
|
|
|
|
|
<view class="vip-card" v-for="item in vipList" :key="item.id">
|
|
|
|
|
|
<view class="vip-head">
|
|
|
|
|
|
<view class="vip-icon">
|
|
|
|
|
|
<u-icon name="level" size="34" color="#2563EB"></u-icon>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="vip-head-main">
|
|
|
|
|
|
<view class="vip-title-row">
|
|
|
|
|
|
<text class="vip-title">{{ item.name || '会员卡' }}</text>
|
|
|
|
|
|
<view class="tag" v-if="item.discountValue">
|
|
|
|
|
|
<text>{{ item.discountValue }}折</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="vip-desc">{{ formatVipMeta(item) }}</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="vip-footer">
|
|
|
|
|
|
<view class="vf-left">
|
|
|
|
|
|
<template v-if="!isFree(item)">
|
|
|
|
|
|
<text class="vf-yen">¥</text>
|
|
|
|
|
|
<text class="vf-num">{{ item.price }}</text>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
<!-- 0元不展示价格 -->
|
|
|
|
|
|
<text class="vf-free">免费</text>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="vf-btn" :class="[isFree(item) ? 'btn-free' : 'btn-buy']" @click.stop="openBuy(item)">
|
|
|
|
|
|
<text>{{ isFree(item) ? '领取' : '购买' }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<u-empty v-if="vipList.length === 0" mode="data" text="暂无可购买的会员卡" margin-top="120"></u-empty>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 购买弹窗 -->
|
|
|
|
|
|
<u-mask :show="showBuy" :z-index="100" />
|
|
|
|
|
|
<view class="sheet" v-if="showBuy">
|
|
|
|
|
|
<view class="sheet-hd">
|
|
|
|
|
|
<text class="sheet-title">{{ isFree(selectedVip) ? '确认领取' : '确认购买' }}</text>
|
|
|
|
|
|
<text class="sheet-close" @click="closeBuy">×</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="sheet-card">
|
|
|
|
|
|
<view class="sc-top">
|
|
|
|
|
|
<view class="sc-name">
|
|
|
|
|
|
<text class="name">{{ selectedVip.name || '会员卡' }}</text>
|
|
|
|
|
|
<text class="badge" v-if="selectedVip.discountValue">{{ selectedVip.discountValue }}折</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="sc-price">
|
|
|
|
|
|
<template v-if="isFree(selectedVip)">
|
|
|
|
|
|
<text class="free">免费</text>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
|
<text class="yen">¥</text>
|
|
|
|
|
|
<text class="num">{{ selectedVip.price }}</text>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="sc-sub">
|
|
|
|
|
|
{{ formatVipMeta(selectedVip) }}
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="sc-desc" v-if="selectedVip.description">
|
|
|
|
|
|
{{ selectedVip.description }}
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="sheet-actions">
|
|
|
|
|
|
<view class="btn ghost" @click="closeBuy">取消</view>
|
|
|
|
|
|
<view class="btn primary" @click="payNow">
|
|
|
|
|
|
<text>{{ paying ? '处理中...' : (isFree(selectedVip) ? '立即领取' : '立即支付') }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
export default {
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
bgc: { backgroundColor: "#F7F8FA" },
|
|
|
|
|
|
promotionId: '',
|
|
|
|
|
|
rawQ: '',
|
|
|
|
|
|
loading: false,
|
|
|
|
|
|
detail: {},
|
|
|
|
|
|
vipList: [],
|
|
|
|
|
|
areaId: '',
|
|
|
|
|
|
areaName: '',
|
|
|
|
|
|
channelId: '',
|
|
|
|
|
|
showBuy: false,
|
|
|
|
|
|
selectedVip: {},
|
2026-03-16 10:03:51 +08:00
|
|
|
|
paying: false,
|
|
|
|
|
|
redirectVipId: '' // 从登录页带回的 vipId,用于自动重新发起购买
|
2026-01-28 18:00:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
onLoad(option) {
|
|
|
|
|
|
const id = this.extractPromotionId(option || {})
|
|
|
|
|
|
if (!id) {
|
|
|
|
|
|
uni.showToast({ title: '缺少推广参数', icon: 'none' })
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
this.promotionId = String(id)
|
2026-03-16 10:03:51 +08:00
|
|
|
|
if (option && option.vipId) this.redirectVipId = String(option.vipId)
|
2026-01-28 18:00:39 +08:00
|
|
|
|
uni.setStorageSync('areaPromotionId', this.promotionId)
|
|
|
|
|
|
this.getDetail()
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
isFree(vip) {
|
|
|
|
|
|
if (!vip) return false
|
|
|
|
|
|
const p = Number(vip.price)
|
|
|
|
|
|
return !isNaN(p) && p <= 0
|
|
|
|
|
|
},
|
|
|
|
|
|
showCounts(item) {
|
|
|
|
|
|
if (!item) return false
|
|
|
|
|
|
return (item.perUserCount || item.perUserCount === 0) || (item.totalCount || item.totalCount === 0)
|
|
|
|
|
|
},
|
|
|
|
|
|
// 从小程序跳转参数里提取推广ID(兼容:i/id/scene/q)
|
|
|
|
|
|
extractPromotionId(option) {
|
|
|
|
|
|
if (option.i || option.id) return option.i || option.id
|
|
|
|
|
|
|
|
|
|
|
|
// scene 兼容:可能是 "i=2" 或直接 "2"
|
|
|
|
|
|
if (option.scene) {
|
|
|
|
|
|
const sc = decodeURIComponent(String(option.scene))
|
|
|
|
|
|
return this.getQueryValue(sc, 'i') || this.getQueryValue(sc, 'id') || sc
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 微信扫码进入常见:q=encodeURIComponent(完整URL)
|
|
|
|
|
|
if (option.q) {
|
|
|
|
|
|
const decoded = decodeURIComponent(String(option.q))
|
|
|
|
|
|
this.rawQ = decoded
|
|
|
|
|
|
return (
|
|
|
|
|
|
this.getQueryValue(decoded, 'i') ||
|
|
|
|
|
|
this.getQueryValue(decoded, 'id') ||
|
|
|
|
|
|
this.getQueryValue(decoded, 'promotionId') ||
|
|
|
|
|
|
this.getQueryValue(decoded, 'areaPromotionId')
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return ''
|
|
|
|
|
|
},
|
|
|
|
|
|
// 从 URL 或 querystring 中取参数
|
|
|
|
|
|
getQueryValue(urlOrQuery, key) {
|
|
|
|
|
|
if (!urlOrQuery) return ''
|
|
|
|
|
|
let q = String(urlOrQuery)
|
|
|
|
|
|
// 允许传入完整URL
|
|
|
|
|
|
if (q.indexOf('?') > -1) q = q.split('?')[1] || ''
|
|
|
|
|
|
if (q.indexOf('#') > -1) q = q.split('#')[0] || ''
|
|
|
|
|
|
if (!q) return ''
|
|
|
|
|
|
const parts = q.split('&')
|
|
|
|
|
|
for (let i = 0; i < parts.length; i++) {
|
|
|
|
|
|
const kv = parts[i].split('=')
|
|
|
|
|
|
if (!kv.length) continue
|
|
|
|
|
|
const k = decodeURIComponent(kv[0] || '').trim()
|
|
|
|
|
|
if (k !== key) continue
|
|
|
|
|
|
return decodeURIComponent(kv.slice(1).join('=') || '').trim()
|
|
|
|
|
|
}
|
|
|
|
|
|
return ''
|
|
|
|
|
|
},
|
|
|
|
|
|
copyPromotionId() {
|
|
|
|
|
|
if (!this.promotionId) return
|
|
|
|
|
|
uni.setClipboardData({
|
|
|
|
|
|
data: this.promotionId,
|
|
|
|
|
|
success: () => uni.showToast({ title: '已复制', icon: 'success' })
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
getDetail() {
|
|
|
|
|
|
if (!this.promotionId) return
|
|
|
|
|
|
this.loading = true
|
|
|
|
|
|
this.$u.get(`/app/areaPromotion/detail?id=${this.promotionId}`).then(res => {
|
|
|
|
|
|
this.loading = false
|
|
|
|
|
|
if (res.code !== 200) {
|
|
|
|
|
|
uni.showToast({ title: res.msg || '获取详情失败', icon: 'none' })
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
const data = res.data || {}
|
|
|
|
|
|
this.detail = data
|
|
|
|
|
|
|
|
|
|
|
|
let list = []
|
|
|
|
|
|
if (Array.isArray(data)) list = data
|
|
|
|
|
|
else if (Array.isArray(data.list)) list = data.list
|
|
|
|
|
|
else if (Array.isArray(data.rows)) list = data.rows
|
|
|
|
|
|
else if (Array.isArray(data.vipList)) list = data.vipList
|
|
|
|
|
|
else if (Array.isArray(data.couponList)) list = data.couponList
|
|
|
|
|
|
else if (Array.isArray(data.data)) list = data.data
|
|
|
|
|
|
|
|
|
|
|
|
this.vipList = list || []
|
|
|
|
|
|
|
|
|
|
|
|
// areaId:用于获取支付通道(如果接口没给,就从列表项兜底)
|
|
|
|
|
|
this.areaId =
|
|
|
|
|
|
data.areaId ||
|
|
|
|
|
|
data.vipAreaId ||
|
|
|
|
|
|
(this.vipList[0] && (this.vipList[0].areaId || this.vipList[0].vipAreaId)) ||
|
|
|
|
|
|
''
|
|
|
|
|
|
|
|
|
|
|
|
// 运营区名称:用于展示
|
|
|
|
|
|
this.areaName =
|
|
|
|
|
|
data.areaName ||
|
|
|
|
|
|
data.vipAreaName ||
|
|
|
|
|
|
(this.vipList[0] && (this.vipList[0].areaName || this.vipList[0].vipAreaName)) ||
|
|
|
|
|
|
''
|
|
|
|
|
|
|
|
|
|
|
|
if (this.areaId) this.getChannelId()
|
2026-03-16 10:03:51 +08:00
|
|
|
|
|
|
|
|
|
|
// 从登录页带回:自动打开该会员卡并重新发起购买
|
|
|
|
|
|
if (this.redirectVipId) {
|
|
|
|
|
|
const vip = this.vipList.find(v => String(v.id) === String(this.redirectVipId))
|
|
|
|
|
|
const vid = this.redirectVipId
|
|
|
|
|
|
this.redirectVipId = ''
|
|
|
|
|
|
if (vip) {
|
|
|
|
|
|
this.openBuy(vip)
|
|
|
|
|
|
setTimeout(() => this.payNow(), 800)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-28 18:00:39 +08:00
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
this.loading = false
|
|
|
|
|
|
uni.showToast({ title: '网络错误', icon: 'none' })
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
// 列表中展示的简短描述,避免拥挤
|
|
|
|
|
|
formatVipMeta(item) {
|
|
|
|
|
|
if (!item) return ''
|
|
|
|
|
|
const parts = []
|
|
|
|
|
|
if (item.validDays || item.validDays === 0) parts.push(`有效期${item.validDays}天`)
|
|
|
|
|
|
if (item.limitTotal || item.limitTotal === 0) parts.push(`共${item.limitTotal}次`)
|
|
|
|
|
|
if (item.enableLimit) {
|
|
|
|
|
|
const r = item.limitRound
|
|
|
|
|
|
const c = item.limitCount
|
|
|
|
|
|
if ((r || r === 0) && (c || c === 0)) parts.push(`每${r}天${c}次`)
|
|
|
|
|
|
} else if (item.enableLimit === false) {
|
|
|
|
|
|
parts.push('无频率限制')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (item.perUserCount || item.perUserCount === 0) parts.push(`每人限购${item.perUserCount}`)
|
|
|
|
|
|
|
|
|
|
|
|
// 使用门槛(minAmount):0/空 => 无门槛
|
|
|
|
|
|
const min = Number(item.minAmount)
|
|
|
|
|
|
if (!isNaN(min) && min > 0) parts.push(`使用门槛¥${item.minAmount}`)
|
|
|
|
|
|
else parts.push('无门槛')
|
|
|
|
|
|
|
|
|
|
|
|
return parts.length ? parts.join(' · ') : '—'
|
|
|
|
|
|
},
|
|
|
|
|
|
getChannelId() {
|
|
|
|
|
|
if (!this.areaId) return
|
|
|
|
|
|
const appId = this.$store && this.$store.state ? this.$store.state.appid : ''
|
|
|
|
|
|
if (!appId) return
|
|
|
|
|
|
this.$u.get(`/app/channel/list?appId=${appId}&areaId=${this.areaId}&bstType=3&appType=1`).then(res => {
|
|
|
|
|
|
if (res.code === 200 && res.data && res.data.length) {
|
|
|
|
|
|
this.channelId = res.data[0].id
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
openBuy(item) {
|
|
|
|
|
|
this.selectedVip = item || {}
|
|
|
|
|
|
this.showBuy = true
|
|
|
|
|
|
// 弹出时尽量提前准备支付通道
|
|
|
|
|
|
if (!this.channelId && this.areaId) this.getChannelId()
|
|
|
|
|
|
},
|
|
|
|
|
|
closeBuy() {
|
|
|
|
|
|
this.showBuy = false
|
|
|
|
|
|
this.selectedVip = {}
|
|
|
|
|
|
},
|
2026-03-16 10:03:51 +08:00
|
|
|
|
// 静默登录(仅用 wx.login 的 code 换 token)
|
|
|
|
|
|
silentLogin() {
|
|
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
|
|
|
wx.login({
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
if (!res.code) {
|
|
|
|
|
|
resolve(false)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
const data = { loginCode: res.code, appId: this.$store.state.appid }
|
|
|
|
|
|
this.$u.post('/wxLogin', data).then((loginRes) => {
|
|
|
|
|
|
if (loginRes.code === 200) {
|
|
|
|
|
|
uni.setStorageSync('token', loginRes.token)
|
|
|
|
|
|
resolve(true)
|
|
|
|
|
|
}else if(res.code == 401){
|
|
|
|
|
|
resolve(false)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
resolve(false)
|
|
|
|
|
|
}
|
|
|
|
|
|
}).catch(() => resolve(false))
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: () => resolve(false)
|
|
|
|
|
|
})
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
// #ifndef MP-WEIXIN
|
|
|
|
|
|
resolve(false)
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
// 跳转登录页,登录成功后带参数回到本页重新购买
|
|
|
|
|
|
goLoginWithRedirect() {
|
|
|
|
|
|
const backUrl = '/pages/tuihuang?i=' + encodeURIComponent(this.promotionId) + '&vipId=' + encodeURIComponent(this.selectedVip.id)
|
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
|
url: '/pages/login/login?redirect=' + encodeURIComponent(backUrl)
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
2026-01-28 18:00:39 +08:00
|
|
|
|
payNow() {
|
|
|
|
|
|
if (this.paying) return
|
|
|
|
|
|
if (!this.selectedVip || !this.selectedVip.id) {
|
|
|
|
|
|
uni.showToast({ title: '缺少会员卡信息', icon: 'none' })
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!this.channelId) {
|
|
|
|
|
|
uni.showToast({ title: '支付通道未准备好,请稍后重试', icon: 'none' })
|
|
|
|
|
|
if (this.areaId) this.getChannelId()
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
const appId = this.$store && this.$store.state ? this.$store.state.appid : ''
|
|
|
|
|
|
if (!appId) {
|
|
|
|
|
|
uni.showToast({ title: '缺少appId配置', icon: 'none' })
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.paying = true
|
|
|
|
|
|
uni.showLoading({ title: '加载中...', mask: true })
|
|
|
|
|
|
|
|
|
|
|
|
const vip = this.selectedVip
|
|
|
|
|
|
const data = {
|
|
|
|
|
|
channelId: this.channelId,
|
|
|
|
|
|
appId,
|
|
|
|
|
|
appType: 1,
|
|
|
|
|
|
vipId: vip.id,
|
|
|
|
|
|
vip
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-16 10:03:51 +08:00
|
|
|
|
const doPayResult = (res) => {
|
2026-01-28 18:00:39 +08:00
|
|
|
|
if (res.data && res.data.needPay) {
|
|
|
|
|
|
uni.requestPayment({
|
|
|
|
|
|
provider: 'wxpay',
|
|
|
|
|
|
timeStamp: res.data.payParams.timeStamp,
|
|
|
|
|
|
nonceStr: res.data.payParams.nonceStr,
|
|
|
|
|
|
package: res.data.payParams.packageVal,
|
|
|
|
|
|
signType: res.data.payParams.signType,
|
|
|
|
|
|
paySign: res.data.payParams.paySign,
|
|
|
|
|
|
success: () => {
|
|
|
|
|
|
this.$u.put(`/app/pay/refreshPayResult?no=${res.data.pay.no}`).then(() => {
|
|
|
|
|
|
this.paying = false
|
|
|
|
|
|
this.showBuy = false
|
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
|
uni.showToast({ title: '购买成功', icon: 'success', duration: 2000 })
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
this.paying = false
|
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
|
uni.showToast({ title: '支付结果刷新失败', icon: 'none' })
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: () => {
|
|
|
|
|
|
this.paying = false
|
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
|
uni.showToast({ title: '已取消支付', icon: 'none' })
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.paying = false
|
|
|
|
|
|
this.showBuy = false
|
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
|
uni.showToast({ title: '购买成功', icon: 'success', duration: 2000 })
|
|
|
|
|
|
}
|
2026-03-16 10:03:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.$u.post(`/app/vipOrder`, data).then(res => {
|
|
|
|
|
|
if (res.code === 401) {
|
|
|
|
|
|
this.silentLogin().then((silentOk) => {
|
|
|
|
|
|
if (silentOk) {
|
|
|
|
|
|
// 静默登录成功,用新 token 再请求一次并直接调起支付
|
|
|
|
|
|
this.$u.post(`/app/vipOrder`, data).then(res2 => {
|
|
|
|
|
|
if (res2.code !== 200) {
|
|
|
|
|
|
this.paying = false
|
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
|
uni.showToast({ title: res2.msg || '下单失败', icon: 'none', duration: 5000 })
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
doPayResult(res2)
|
|
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
this.paying = false
|
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
|
uni.showToast({ title: '网络错误', icon: 'none', duration: 5000 })
|
|
|
|
|
|
})
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.paying = false
|
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
|
this.goLoginWithRedirect()
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if (res.code !== 200) {
|
|
|
|
|
|
this.paying = false
|
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
|
uni.showToast({ title: res.msg || '下单失败', icon: 'none' ,duration:5000})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
doPayResult(res)
|
2026-01-28 18:00:39 +08:00
|
|
|
|
}).catch(() => {
|
|
|
|
|
|
this.paying = false
|
|
|
|
|
|
uni.hideLoading()
|
|
|
|
|
|
uni.showToast({ title: '网络错误', icon: 'none',duration:5000 })
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
|
|
page {
|
|
|
|
|
|
background: #F7F8FA;
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.page {
|
|
|
|
|
|
padding-bottom: constant(safe-area-inset-bottom);
|
|
|
|
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.hero {
|
|
|
|
|
|
margin: 18rpx 24rpx 8rpx;
|
|
|
|
|
|
border-radius: 28rpx;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
background: linear-gradient(135deg, #EAF2FF 0%, #F7FBFF 40%, #FFFFFF 100%);
|
|
|
|
|
|
border: 1rpx solid rgba(37, 99, 235, 0.12);
|
|
|
|
|
|
box-shadow: 0 18rpx 40rpx rgba(17, 24, 39, 0.08);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.hero-bg {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
inset: 0;
|
|
|
|
|
|
.b {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
filter: blur(40rpx);
|
|
|
|
|
|
opacity: 0.5;
|
|
|
|
|
|
}
|
|
|
|
|
|
.b1 { width: 360rpx; height: 360rpx; background: #60A5FA; top: -140rpx; right: -120rpx; }
|
|
|
|
|
|
.b2 { width: 280rpx; height: 280rpx; background: #34D399; bottom: -140rpx; left: -120rpx; opacity: 0.35; }
|
|
|
|
|
|
.b3 { width: 240rpx; height: 240rpx; background: #A78BFA; top: 40rpx; left: 120rpx; opacity: 0.22; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.hero-content {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
padding: 30rpx 28rpx 26rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.hero-title {
|
|
|
|
|
|
font-size: 38rpx;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
color: #111827;
|
|
|
|
|
|
letter-spacing: 1rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.hero-sub {
|
|
|
|
|
|
margin-top: 10rpx;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #4B5563;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.hero-meta {
|
|
|
|
|
|
margin-top: 18rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 12rpx;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.meta-pill {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 10rpx;
|
|
|
|
|
|
padding: 12rpx 16rpx;
|
|
|
|
|
|
border-radius: 999rpx;
|
|
|
|
|
|
background: rgba(37, 99, 235, 0.08);
|
|
|
|
|
|
border: 1rpx solid rgba(37, 99, 235, 0.12);
|
|
|
|
|
|
.meta-text {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #1F2937;
|
|
|
|
|
|
}
|
|
|
|
|
|
&.ghost {
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.7);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.list {
|
|
|
|
|
|
padding: 14rpx 28rpx 90rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.section-title {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: baseline;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
margin: 14rpx 6rpx 10rpx;
|
|
|
|
|
|
.st-main {
|
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
color: #111827;
|
|
|
|
|
|
}
|
|
|
|
|
|
.st-sub {
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
color: #9CA3AF;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vip-card {
|
|
|
|
|
|
background: linear-gradient(180deg, #FFFFFF 0%, #FBFDFF 100%);
|
|
|
|
|
|
border-radius: 28rpx;
|
|
|
|
|
|
padding: 32rpx 28rpx 26rpx;
|
|
|
|
|
|
margin-bottom: 22rpx;
|
|
|
|
|
|
box-shadow: 0 18rpx 44rpx rgba(17, 24, 39, 0.08);
|
|
|
|
|
|
border: 1rpx solid rgba(37, 99, 235, 0.08);
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
&:active { transform: scale(0.99); }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vip-card::after {
|
|
|
|
|
|
content: '';
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
right: -120rpx;
|
|
|
|
|
|
top: -120rpx;
|
|
|
|
|
|
width: 240rpx;
|
|
|
|
|
|
height: 240rpx;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
background: radial-gradient(circle at 30% 30%, rgba(66, 151, 243, 0.18), rgba(66, 151, 243, 0));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vip-head {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 18rpx;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vip-icon {
|
|
|
|
|
|
width: 84rpx;
|
|
|
|
|
|
height: 84rpx;
|
|
|
|
|
|
border-radius: 26rpx;
|
|
|
|
|
|
background: linear-gradient(135deg, rgba(37, 99, 235, 0.14) 0%, rgba(99, 102, 241, 0.12) 100%);
|
|
|
|
|
|
border: 1rpx solid rgba(37, 99, 235, 0.16);
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vip-left { display: none; }
|
|
|
|
|
|
.vip-right { display: none; }
|
|
|
|
|
|
.vip-head-main { flex: 1; min-width: 0; }
|
|
|
|
|
|
|
|
|
|
|
|
.vip-name-row { display: none; }
|
|
|
|
|
|
.vip-title-row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 12rpx;
|
|
|
|
|
|
.tag {
|
|
|
|
|
|
padding: 4rpx 12rpx;
|
|
|
|
|
|
border-radius: 999rpx;
|
|
|
|
|
|
background: rgba(245, 158, 11, 0.12);
|
|
|
|
|
|
color: #B45309;
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
border: 1rpx solid rgba(245, 158, 11, 0.18);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vip-title {
|
|
|
|
|
|
font-size: 36rpx;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
color: #0F172A;
|
|
|
|
|
|
max-width: 520rpx;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
letter-spacing: 1rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vip-desc {
|
|
|
|
|
|
margin-top: 10rpx;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #64748B;
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vip-footer {
|
|
|
|
|
|
margin-top: 18rpx;
|
|
|
|
|
|
height: 96rpx;
|
|
|
|
|
|
border-radius: 22rpx;
|
|
|
|
|
|
background: #F8FAFC;
|
|
|
|
|
|
border: 1rpx solid rgba(15, 23, 42, 0.08);
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
padding: 0 18rpx 0 22rpx;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vf-left {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: baseline;
|
|
|
|
|
|
min-width: 220rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vf-yen {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
color: #EF4444;
|
|
|
|
|
|
margin-right: 6rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vf-num {
|
|
|
|
|
|
font-size: 44rpx;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
color: #EF4444;
|
|
|
|
|
|
font-family: 'DIN Alternate', sans-serif;
|
|
|
|
|
|
letter-spacing: 1rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vf-free {
|
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
color: #16A34A;
|
|
|
|
|
|
background: rgba(22, 163, 74, 0.10);
|
|
|
|
|
|
border: 1rpx solid rgba(22, 163, 74, 0.16);
|
|
|
|
|
|
padding: 10rpx 16rpx;
|
|
|
|
|
|
border-radius: 999rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vf-btn {
|
|
|
|
|
|
height: 72rpx;
|
|
|
|
|
|
min-width: 176rpx;
|
|
|
|
|
|
border-radius: 999rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
padding: 0 26rpx;
|
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
letter-spacing: 2rpx;
|
|
|
|
|
|
color: #FFFFFF;
|
|
|
|
|
|
box-shadow: 0 12rpx 24rpx rgba(37, 99, 235, 0.25);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.btn-buy {
|
|
|
|
|
|
background: linear-gradient(135deg, #3B82F6 0%, #2563EB 55%, #1D4ED8 100%);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.btn-free {
|
|
|
|
|
|
background: linear-gradient(135deg, #22C55E 0%, #16A34A 60%, #15803D 100%);
|
|
|
|
|
|
box-shadow: 0 12rpx 24rpx rgba(22, 163, 74, 0.22);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vip-counts { display: none; }
|
|
|
|
|
|
.vip-chips {
|
|
|
|
|
|
margin-top: 16rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 12rpx;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.count-pill { display: none; }
|
|
|
|
|
|
.chip {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8rpx;
|
|
|
|
|
|
padding: 10rpx 14rpx;
|
|
|
|
|
|
border-radius: 999rpx;
|
|
|
|
|
|
background: rgba(2, 132, 199, 0.06);
|
|
|
|
|
|
border: 1rpx solid rgba(2, 132, 199, 0.12);
|
|
|
|
|
|
.chip-label {
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
color: #475569;
|
|
|
|
|
|
}
|
|
|
|
|
|
.chip-val {
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
color: #0F172A;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vip-note {
|
|
|
|
|
|
margin-top: 10rpx;
|
|
|
|
|
|
background: #F9FAFB;
|
|
|
|
|
|
border-radius: 14rpx;
|
|
|
|
|
|
padding: 14rpx 14rpx;
|
|
|
|
|
|
.note-label { font-size: 22rpx; color: #9CA3AF; }
|
|
|
|
|
|
.note-text {
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
color: #4B5563;
|
|
|
|
|
|
line-clamp: 2;
|
|
|
|
|
|
display: -webkit-box;
|
|
|
|
|
|
-webkit-line-clamp: 2;
|
|
|
|
|
|
-webkit-box-orient: vertical;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.buy-btn { display: none; }
|
|
|
|
|
|
.buy-price { display: none; }
|
|
|
|
|
|
.buy-split { display: none; }
|
|
|
|
|
|
.buy-text { display: none; }
|
|
|
|
|
|
|
|
|
|
|
|
.vip-action {
|
|
|
|
|
|
margin-top: 18rpx;
|
|
|
|
|
|
height: 96rpx;
|
|
|
|
|
|
border-radius: 24rpx;
|
|
|
|
|
|
padding: 0 22rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
background: linear-gradient(135deg, #3B82F6 0%, #2563EB 55%, #1D4ED8 100%);
|
|
|
|
|
|
box-shadow: 0 16rpx 34rpx rgba(37, 99, 235, 0.30);
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.vip-action::before {
|
|
|
|
|
|
content: '';
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
left: -80rpx;
|
|
|
|
|
|
top: -80rpx;
|
|
|
|
|
|
width: 200rpx;
|
|
|
|
|
|
height: 200rpx;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.va-left, .va-right {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: baseline;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.va-yen {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
margin-right: 6rpx;
|
|
|
|
|
|
opacity: 0.95;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.va-num {
|
|
|
|
|
|
font-size: 42rpx;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
font-family: 'DIN Alternate', sans-serif;
|
|
|
|
|
|
letter-spacing: 1rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.va-free {
|
|
|
|
|
|
font-size: 34rpx;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
letter-spacing: 2rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.va-right {
|
|
|
|
|
|
gap: 10rpx;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.va-text {
|
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
letter-spacing: 2rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.loading {
|
|
|
|
|
|
padding: 10rpx 0 0;
|
|
|
|
|
|
.loading-text {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
margin-top: 18rpx;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #9CA3AF;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.skeleton {
|
|
|
|
|
|
background: #FFFFFF;
|
|
|
|
|
|
border-radius: 24rpx;
|
|
|
|
|
|
padding: 26rpx 24rpx;
|
|
|
|
|
|
margin-bottom: 18rpx;
|
|
|
|
|
|
box-shadow: 0 10rpx 28rpx rgba(17, 24, 39, 0.04);
|
|
|
|
|
|
border: 1rpx solid rgba(17, 24, 39, 0.06);
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
&::after {
|
|
|
|
|
|
content: '';
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: -40%;
|
|
|
|
|
|
width: 40%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.6) 50%, rgba(255,255,255,0) 100%);
|
|
|
|
|
|
animation: sk 1.2s infinite;
|
|
|
|
|
|
}
|
|
|
|
|
|
.sk-line {
|
|
|
|
|
|
height: 26rpx;
|
|
|
|
|
|
border-radius: 999rpx;
|
|
|
|
|
|
background: #F3F4F6;
|
|
|
|
|
|
margin-bottom: 14rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.w60 { width: 60%; }
|
|
|
|
|
|
.w40 { width: 40%; }
|
|
|
|
|
|
.sk-btn {
|
|
|
|
|
|
width: 160rpx;
|
|
|
|
|
|
height: 64rpx;
|
|
|
|
|
|
border-radius: 999rpx;
|
|
|
|
|
|
background: #E5E7EB;
|
|
|
|
|
|
margin-top: 10rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes sk {
|
|
|
|
|
|
0% { left: -40%; }
|
|
|
|
|
|
100% { left: 120%; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.sheet {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
z-index: 101;
|
|
|
|
|
|
background: #FFFFFF;
|
|
|
|
|
|
border-radius: 32rpx 32rpx 0 0;
|
|
|
|
|
|
padding: 22rpx 24rpx 24rpx;
|
|
|
|
|
|
padding-bottom: calc(24rpx + constant(safe-area-inset-bottom));
|
|
|
|
|
|
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
|
|
|
|
|
box-shadow: 0 -14rpx 36rpx rgba(17, 24, 39, 0.18);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.sheet-hd {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
.sheet-title {
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
color: #111827;
|
|
|
|
|
|
}
|
|
|
|
|
|
.sheet-close {
|
|
|
|
|
|
font-size: 52rpx;
|
|
|
|
|
|
color: #9CA3AF;
|
|
|
|
|
|
line-height: 1;
|
|
|
|
|
|
padding: 0 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.sheet-card {
|
|
|
|
|
|
margin-top: 18rpx;
|
|
|
|
|
|
border-radius: 24rpx;
|
|
|
|
|
|
padding: 22rpx 22rpx 20rpx;
|
|
|
|
|
|
background: linear-gradient(180deg, #FFFFFF 0%, #F9FBFF 100%);
|
|
|
|
|
|
border: 1rpx solid rgba(66, 151, 243, 0.12);
|
|
|
|
|
|
.sc-top {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
gap: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.sc-name {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 12rpx;
|
|
|
|
|
|
.name {
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
color: #111827;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
}
|
|
|
|
|
|
.badge {
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
color: #D97706;
|
|
|
|
|
|
background: rgba(217, 119, 6, 0.12);
|
|
|
|
|
|
padding: 4rpx 12rpx;
|
|
|
|
|
|
border-radius: 999rpx;
|
|
|
|
|
|
border: 1rpx solid rgba(217, 119, 6, 0.16);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.sc-price {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: baseline;
|
|
|
|
|
|
color: #EF4444;
|
|
|
|
|
|
.yen { font-size: 22rpx; font-weight: 800; margin-right: 4rpx; }
|
|
|
|
|
|
.num { font-size: 44rpx; font-weight: 900; font-family: 'DIN Alternate', sans-serif; }
|
|
|
|
|
|
}
|
|
|
|
|
|
.sc-sub {
|
|
|
|
|
|
margin-top: 12rpx;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #64748B;
|
|
|
|
|
|
line-height: 1.7;
|
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
.sc-desc {
|
|
|
|
|
|
margin-top: 14rpx;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #4B5563;
|
|
|
|
|
|
background: #F9FAFB;
|
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
|
padding: 14rpx 14rpx;
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.sheet-actions {
|
|
|
|
|
|
margin-top: 18rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 16rpx;
|
|
|
|
|
|
.btn {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
height: 92rpx;
|
|
|
|
|
|
border-radius: 999rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
}
|
|
|
|
|
|
.ghost {
|
|
|
|
|
|
background: #FFFFFF;
|
|
|
|
|
|
color: #374151;
|
|
|
|
|
|
border: 2rpx solid #E5E7EB;
|
|
|
|
|
|
}
|
|
|
|
|
|
.primary {
|
|
|
|
|
|
background: linear-gradient(135deg, #4297F3 0%, #2B76E5 100%);
|
|
|
|
|
|
color: #FFFFFF;
|
|
|
|
|
|
box-shadow: 0 10rpx 22rpx rgba(66, 151, 243, 0.28);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|