feat(uniapp): 对齐兑换券页面黑金尊享卡片与释放计划卡片流设计
这个提交包含在:
@@ -0,0 +1,74 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
function assert(condition, testName, detail = '') {
|
||||
if (condition) {
|
||||
console.log(` [PASS] ${testName}`);
|
||||
passed++;
|
||||
} else {
|
||||
console.error(` [FAIL] ${testName} - ${detail}`);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("========================================================");
|
||||
console.log(" 兑换券页面对齐马豆页面规格与黑金卡片交互测试");
|
||||
console.log("========================================================\n");
|
||||
|
||||
// 1. 验证 voucher.vue 存在性
|
||||
const voucherVuePath = path.resolve(__dirname, '../uniapp/pages/commission/voucher.vue');
|
||||
assert(fs.existsSync(voucherVuePath), 'voucher.vue 文件存在');
|
||||
const content = fs.readFileSync(voucherVuePath, 'utf-8');
|
||||
|
||||
// 2. 验证黑金尊享卡片结构对齐
|
||||
assert(
|
||||
content.includes('asset-card') && content.includes('madow-hero') || content.includes('voucher-hero'),
|
||||
'包含黑金资产大卡片与核心大字数展示结构',
|
||||
'未包含类似 madow.vue 的黑金尊享卡片'
|
||||
);
|
||||
|
||||
// 3. 验证 4 项核心数据指标完整对齐
|
||||
assert(
|
||||
content.includes('voucher_total') &&
|
||||
content.includes('voucher_released') &&
|
||||
content.includes('voucher_used') &&
|
||||
content.includes('voucher_available'),
|
||||
'包含累计获得、已释放、已使用、可用兑换券 4 项核心指标完整绑定',
|
||||
'缺少核心兑换券指标'
|
||||
);
|
||||
|
||||
// 4. 验证胶囊指示栏与规则弹窗
|
||||
assert(
|
||||
content.includes('su-popup') && content.includes('showHelp') && content.includes('释放规则'),
|
||||
'包含释放规则按钮与 su-popup 规则说明弹窗',
|
||||
'缺少规则弹窗交互'
|
||||
);
|
||||
|
||||
// 5. 验证订单卡片流与进度展示
|
||||
assert(
|
||||
content.includes('log-card') || content.includes('plan-card'),
|
||||
'订单释放计划升级为卡片流形式',
|
||||
'仍为旧版普通边框单列表'
|
||||
);
|
||||
|
||||
assert(
|
||||
content.includes('released_days') || content.includes('total_days') || content.includes('planProgress'),
|
||||
'卡片流中计算并展示释放天数与线性进度条',
|
||||
'缺少释放天数或进度条'
|
||||
);
|
||||
|
||||
// 6. 验证快捷兑换入口
|
||||
assert(
|
||||
content.includes('/pages/index/index') || content.includes('/pages/goods/list') || content.includes('去兑换'),
|
||||
'提供前往商城的兑换引导入口',
|
||||
'缺少商城引导'
|
||||
);
|
||||
|
||||
console.log("\n--------------------------------------------------------");
|
||||
console.log(`测试执行结果: 通过 ${passed} 项, 失败 ${failed} 项`);
|
||||
console.log("========================================================");
|
||||
|
||||
process.exit(failed === 0 ? 0 : 1);
|
||||
@@ -1,106 +1,228 @@
|
||||
<template>
|
||||
<s-layout class="wallet-wrap" title="兑换券">
|
||||
<view class="header-box ss-flex ss-row-center ss-col-center">
|
||||
<view class="card-box ui-BG-Main ui-Shadow-Main">
|
||||
<view class="metric-grid">
|
||||
<view class="metric-item">
|
||||
<view class="metric-label">累计获得</view>
|
||||
<view class="metric-value">{{ state.info.voucher_total || '0.00' }}</view>
|
||||
<s-layout class="voucher-wrap" title="兑换券">
|
||||
<!-- 顶部黑金尊享资产卡片 -->
|
||||
<view class="header-box">
|
||||
<view class="asset-card">
|
||||
<!-- 卡片顶栏 -->
|
||||
<view class="card-top ss-flex ss-row-between ss-col-center">
|
||||
<view class="top-tag ss-flex ss-col-center">
|
||||
<text class="tag-badge">兑换权益</text>
|
||||
<text class="top-title">可用兑换券总额</text>
|
||||
</view>
|
||||
<view class="metric-item">
|
||||
<view class="metric-label">已释放</view>
|
||||
<view class="metric-value">{{ state.info.voucher_released || '0.00' }}</view>
|
||||
</view>
|
||||
<view class="metric-item">
|
||||
<view class="metric-label">已使用</view>
|
||||
<view class="metric-value">{{ state.info.voucher_used || '0.00' }}</view>
|
||||
</view>
|
||||
<view class="metric-item">
|
||||
<view class="metric-label">可用</view>
|
||||
<view class="metric-value">{{ state.info.voucher_available || '0.00' }}</view>
|
||||
<view class="rule-btn ss-flex ss-col-center" @tap="state.showHelp = true">
|
||||
<text class="rule-btn-text">释放规则</text>
|
||||
<text class="cicon-help-o ss-m-l-6"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="progress-text">第 {{ state.progress.current || 0 }} / {{ state.progress.total || 365 }} 天</view>
|
||||
<view class="progress-bar">
|
||||
<view class="progress-inner" :style="{ width: progressWidth }"></view>
|
||||
|
||||
<!-- 兑换券核心大字数 -->
|
||||
<view class="voucher-hero ss-flex ss-col-bottom ss-row-between">
|
||||
<view class="hero-left ss-flex ss-col-bottom">
|
||||
<text class="hero-symbol">¥</text>
|
||||
<text class="hero-num">{{ state.info.voucher_available || '0.00' }}</text>
|
||||
<text class="hero-unit">元</text>
|
||||
</view>
|
||||
<button
|
||||
class="ss-reset-button exchange-btn ss-flex ss-row-center ss-col-center"
|
||||
@tap="sheep.$router.go('/pages/index/index')"
|
||||
>
|
||||
<text class="cicon-goods-o ss-m-r-6"></text>
|
||||
<text>去兑换</text>
|
||||
</button>
|
||||
</view>
|
||||
<button class="ss-reset-button exchange-btn" @tap="sheep.$router.go('/pages/index/index')">
|
||||
去兑换
|
||||
|
||||
<!-- 动态指示胶囊 -->
|
||||
<view class="rate-capsule ss-flex ss-row-between ss-col-center">
|
||||
<view class="capsule-left ss-flex ss-col-center">
|
||||
<text class="capsule-dot"></text>
|
||||
<text class="capsule-text">365天按日线性释放 · 每日自动到账可抵扣</text>
|
||||
</view>
|
||||
<text class="capsule-tag">全场通用</text>
|
||||
</view>
|
||||
|
||||
<!-- 底部数据栏:累计获得 / 已释放 / 已使用 -->
|
||||
<view class="card-footer ss-flex ss-row-between ss-col-center">
|
||||
<view class="footer-metric">
|
||||
<text class="metric-label">累计获得</text>
|
||||
<view class="metric-val-wrap ss-flex ss-col-bottom">
|
||||
<text class="currency-symbol">¥</text>
|
||||
<text class="metric-val">{{ state.info.voucher_total || '0.00' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="footer-metric">
|
||||
<text class="metric-label">已释放</text>
|
||||
<view class="metric-val-wrap ss-flex ss-col-bottom">
|
||||
<text class="currency-symbol">¥</text>
|
||||
<text class="metric-val">{{ state.info.voucher_released || '0.00' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="footer-metric">
|
||||
<text class="metric-label">已使用</text>
|
||||
<view class="metric-val-wrap ss-flex ss-col-bottom">
|
||||
<text class="currency-symbol">¥</text>
|
||||
<text class="metric-val">{{ state.info.voucher_used || '0.00' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 列表标题区 -->
|
||||
<view class="section-header ss-flex ss-row-between ss-col-center">
|
||||
<view class="section-title-wrap ss-flex ss-col-center">
|
||||
<view class="title-bar"></view>
|
||||
<text class="section-title">订单释放计划</text>
|
||||
</view>
|
||||
<text class="section-subtitle">按日释放明细</text>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-wrap" v-if="state.inited && state.plans.length === 0">
|
||||
<s-empty
|
||||
icon="/static/data-empty.png"
|
||||
text="下单后将获得 1.5 倍兑换券,分 365 天释放。"
|
||||
></s-empty>
|
||||
</view>
|
||||
|
||||
<!-- 订单释放计划卡片列表 -->
|
||||
<view class="list-container" v-if="state.plans.length > 0">
|
||||
<view
|
||||
class="log-card"
|
||||
v-for="(item, index) in state.plans"
|
||||
:key="item.id || index"
|
||||
>
|
||||
<view class="log-top ss-flex ss-row-between ss-col-center">
|
||||
<view class="log-title-box ss-flex ss-col-center">
|
||||
<view class="coin-icon ss-flex ss-row-center ss-col-center">
|
||||
<text class="cicon-voucher"></text>
|
||||
</view>
|
||||
<view class="log-main-info">
|
||||
<text class="log-title">订单 #{{ item.order_sn || item.order_id || '--' }}</text>
|
||||
<text class="log-date">起算日期: {{ item.start_date || item.createtime || '--' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="log-amount ss-flex ss-col-center">
|
||||
<text class="amount-num">¥{{ item.total_amount || item.total || item.voucher_total || '0.00' }}</text>
|
||||
<text class="amount-status ss-m-l-12" :class="item.status === 2 ? 'finished' : 'releasing'">
|
||||
{{ item.status_text || (item.status === 2 ? '已完成' : '释放中') }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 释放天数进度条 -->
|
||||
<view class="plan-progress-box ss-m-t-20">
|
||||
<view class="progress-info ss-flex ss-row-between ss-col-center ss-m-b-8">
|
||||
<text class="progress-txt">第 {{ planDay(item) }} / {{ planTotal(item) }} 天</text>
|
||||
<text class="progress-percent">{{ planProgress(item) }}</text>
|
||||
</view>
|
||||
<view class="progress-bar">
|
||||
<view class="progress-inner" :style="{ width: planProgress(item) }"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 详细指标标签 -->
|
||||
<view class="log-tags ss-flex ss-col-center ss-m-t-16">
|
||||
<view class="tag-item">
|
||||
<text class="tag-txt">已释放 ¥{{ item.released_amount || item.released || '0.00' }}</text>
|
||||
</view>
|
||||
<view class="tag-item" v-if="item.daily_amount">
|
||||
<text class="tag-txt">每日释放 ¥{{ item.daily_amount }}</text>
|
||||
</view>
|
||||
<view class="tag-item" v-if="calcRemain(item) !== null">
|
||||
<text class="tag-txt">待释放 ¥{{ calcRemain(item) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 规则说明弹窗 -->
|
||||
<su-popup
|
||||
:show="state.showHelp"
|
||||
type="bottom"
|
||||
round="24"
|
||||
@close="state.showHelp = false"
|
||||
showClose
|
||||
>
|
||||
<view class="rule-popup-body">
|
||||
<view class="rule-popup-title ss-m-b-30">兑换券释放与使用规则</view>
|
||||
<view class="rule-item ss-m-b-24">
|
||||
<view class="rule-item-title ss-flex ss-col-center ss-m-b-8">
|
||||
<text class="rule-seq">1</text>
|
||||
<text class="rule-name">赠送与释放天数</text>
|
||||
</view>
|
||||
<view class="rule-item-desc">
|
||||
会员在平台完成符合条件的商城订单后,系统将按订单金额(默认 1.5 倍)生成兑换券计划,分 365 天按日线性释放。
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="rule-item ss-m-b-24">
|
||||
<view class="rule-item-title ss-flex ss-col-center ss-m-b-8">
|
||||
<text class="rule-seq">2</text>
|
||||
<text class="rule-name">每日自动到账</text>
|
||||
</view>
|
||||
<view class="rule-item-desc">
|
||||
系统将于次日 00:30 起统一执行日结核算,按期释放的兑换券将自动计入您的「可用兑换券」账户,无需手动领取。
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="rule-item ss-m-b-36">
|
||||
<view class="rule-item-title ss-flex ss-col-center ss-m-b-8">
|
||||
<text class="rule-seq">3</text>
|
||||
<text class="rule-name">全场购物直接抵扣</text>
|
||||
</view>
|
||||
<view class="rule-item-desc">
|
||||
可用兑换券可在平台商城下单结算时作为现金抵扣使用,尊享优惠抵扣权益。
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<button class="ss-reset-button rule-confirm-btn" @tap="state.showHelp = false">
|
||||
我知道了
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<s-empty
|
||||
v-if="state.inited && state.plans.length === 0"
|
||||
icon="/static/data-empty.png"
|
||||
text="下单后将获得 1.5 倍兑换券,分 365 天释放。"
|
||||
></s-empty>
|
||||
|
||||
<view v-if="state.plans.length > 0">
|
||||
<view class="wallet-list border-bottom" v-for="(item, index) in state.plans" :key="item.id || index">
|
||||
<view class="title-box ss-flex ss-row-between ss-m-b-12">
|
||||
<text class="title">订单 {{ item.order_sn || item.order_id || '--' }}</text>
|
||||
<text class="money">总额 {{ item.total || item.voucher_total || '0.00' }}</text>
|
||||
</view>
|
||||
<view class="desc ss-m-b-16">
|
||||
已释放 {{ item.released || item.voucher_released || '0.00' }} · 可用
|
||||
{{ item.available || item.voucher_available || '0.00' }} · 已用
|
||||
{{ item.used || item.voucher_used || '0.00' }}
|
||||
</view>
|
||||
<view class="progress-bar">
|
||||
<view class="progress-inner dark" :style="{ width: planProgress(item) }"></view>
|
||||
</view>
|
||||
<view class="desc ss-m-t-8">
|
||||
{{ planDay(item) }} / {{ planTotal(item) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</su-popup>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, reactive } from 'vue';
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const headerBg = sheep.$url.css('/assets/addons/shopro/uniapp/user/wallet_card_bg.png');
|
||||
const userInfo = sheep.$store('user').userInfo || {};
|
||||
const agentInfo = sheep.$store('user').agentInfo || {};
|
||||
|
||||
const state = reactive({
|
||||
info: {
|
||||
voucher_total: agentInfo.voucher_total || '0.00',
|
||||
voucher_released: agentInfo.voucher_released || '0.00',
|
||||
voucher_used: agentInfo.voucher_used || '0.00',
|
||||
voucher_total: agentInfo.voucher_total || userInfo.voucher_total || '0.00',
|
||||
voucher_released: agentInfo.voucher_released || userInfo.voucher_released || '0.00',
|
||||
voucher_used: agentInfo.voucher_used || userInfo.voucher_used || '0.00',
|
||||
voucher_available: agentInfo.voucher_available || userInfo.voucher_available || '0.00',
|
||||
},
|
||||
plans: [],
|
||||
inited: false,
|
||||
progress: {
|
||||
current: 0,
|
||||
total: 365,
|
||||
},
|
||||
});
|
||||
|
||||
const progressWidth = computed(() => {
|
||||
const total = Number(state.progress.total) || 365;
|
||||
const current = Number(state.progress.current) || 0;
|
||||
const percent = Math.min(100, Math.max(0, (current / total) * 100));
|
||||
return `${percent}%`;
|
||||
showHelp: false,
|
||||
});
|
||||
|
||||
function planDay(item = {}) {
|
||||
return item.day || item.released_days || item.current_day || 0;
|
||||
return Number(item.released_days || item.day || item.current_day || 0);
|
||||
}
|
||||
|
||||
function planTotal(item = {}) {
|
||||
return item.days || item.total_days || 365;
|
||||
return Number(item.total_days || item.days || 365);
|
||||
}
|
||||
|
||||
function planProgress(item = {}) {
|
||||
const total = Number(planTotal(item)) || 365;
|
||||
const current = Number(planDay(item)) || 0;
|
||||
return `${Math.min(100, Math.max(0, (current / total) * 100))}%`;
|
||||
const total = planTotal(item);
|
||||
const current = planDay(item);
|
||||
const percent = Math.min(100, Math.max(0, Math.round((current / (total || 1)) * 100)));
|
||||
return `${percent}%`;
|
||||
}
|
||||
|
||||
function calcRemain(item = {}) {
|
||||
const total = parseFloat(item.total_amount || item.total || item.voucher_total || 0);
|
||||
const released = parseFloat(item.released_amount || item.released || 0);
|
||||
const remain = Math.max(0, total - released);
|
||||
return remain.toFixed(2);
|
||||
}
|
||||
|
||||
function pickPlans(payload) {
|
||||
@@ -108,39 +230,20 @@
|
||||
if (Array.isArray(payload.plans)) return payload.plans;
|
||||
if (Array.isArray(payload.list)) return payload.list;
|
||||
if (Array.isArray(payload.data)) return payload.data;
|
||||
if (Array.isArray(payload)) return payload;
|
||||
return [];
|
||||
}
|
||||
|
||||
function calcProgress(plans) {
|
||||
if (!plans.length) {
|
||||
state.progress.current = 0;
|
||||
state.progress.total = 365;
|
||||
return;
|
||||
}
|
||||
let maxCurrent = 0;
|
||||
let total = 365;
|
||||
plans.forEach((item) => {
|
||||
const current = Number(planDay(item)) || 0;
|
||||
if (current > maxCurrent) {
|
||||
maxCurrent = current;
|
||||
total = Number(planTotal(item)) || 365;
|
||||
}
|
||||
});
|
||||
state.progress.current = maxCurrent;
|
||||
state.progress.total = total;
|
||||
}
|
||||
|
||||
async function getVoucher() {
|
||||
try {
|
||||
const res = await sheep.$api.partner.voucher();
|
||||
if (res?.code === 1) {
|
||||
const data = res.data || {};
|
||||
state.info.voucher_total = data.voucher_total || state.info.voucher_total;
|
||||
state.info.voucher_released = data.voucher_released || state.info.voucher_released;
|
||||
state.info.voucher_used = data.voucher_used || state.info.voucher_used;
|
||||
state.info.voucher_available = data.voucher_available || state.info.voucher_available;
|
||||
state.info.voucher_total = data.voucher_total ?? state.info.voucher_total;
|
||||
state.info.voucher_released = data.voucher_released ?? state.info.voucher_released;
|
||||
state.info.voucher_used = data.voucher_used ?? state.info.voucher_used;
|
||||
state.info.voucher_available = data.voucher_available ?? state.info.voucher_available;
|
||||
state.plans = pickPlans(data);
|
||||
calcProgress(state.plans);
|
||||
state.inited = true;
|
||||
return;
|
||||
}
|
||||
@@ -160,123 +263,401 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.voucher-wrap {
|
||||
min-height: 100vh;
|
||||
background-color: #f7f8fa;
|
||||
}
|
||||
|
||||
/* 顶部资产区域 */
|
||||
.header-box {
|
||||
background-color: $white;
|
||||
padding: 30rpx;
|
||||
padding: 24rpx 30rpx 10rpx;
|
||||
|
||||
.card-box {
|
||||
.asset-card {
|
||||
width: 100%;
|
||||
min-height: 300rpx;
|
||||
padding: 36rpx 30rpx 30rpx;
|
||||
border-radius: 30rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
padding: 36rpx 32rpx 30rpx;
|
||||
border-radius: 28rpx;
|
||||
background: linear-gradient(138deg, #20222a 0%, #15161a 52%, #2c2419 100%);
|
||||
box-shadow: 0 16rpx 36rpx rgba(18, 19, 23, 0.18), inset 0 1rpx 0 rgba(247, 219, 168, 0.28);
|
||||
border: 1rpx solid rgba(235, 197, 131, 0.26);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::after {
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: v-bind(headerBg) no-repeat;
|
||||
right: -60rpx;
|
||||
top: -60rpx;
|
||||
width: 240rpx;
|
||||
height: 240rpx;
|
||||
background: radial-gradient(circle, rgba(235, 197, 131, 0.16) 0%, rgba(235, 197, 131, 0) 70%);
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.metric-grid,
|
||||
.progress-text,
|
||||
.progress-bar,
|
||||
.exchange-btn {
|
||||
.card-top {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
z-index: 2;
|
||||
|
||||
.top-tag {
|
||||
.tag-badge {
|
||||
font-size: 20rpx;
|
||||
color: #2a2012;
|
||||
background: linear-gradient(90deg, #f7dfa6 0%, #e2be78 100%);
|
||||
padding: 4rpx 14rpx;
|
||||
border-radius: 8rpx;
|
||||
font-weight: 600;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.top-title {
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
font-weight: 400;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.rule-btn {
|
||||
padding: 6rpx 18rpx;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border: 1rpx solid rgba(235, 197, 131, 0.3);
|
||||
border-radius: 24rpx;
|
||||
|
||||
.rule-btn-text {
|
||||
font-size: 22rpx;
|
||||
color: #f2cf8f;
|
||||
}
|
||||
|
||||
.cicon-help-o {
|
||||
font-size: 24rpx;
|
||||
color: #f2cf8f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.metric-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.metric-item {
|
||||
width: 50%;
|
||||
padding: 12rpx 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.metric-label {
|
||||
font-size: 22rpx;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.metric-value {
|
||||
font-size: 32rpx;
|
||||
color: $white;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 22rpx;
|
||||
color: $white;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.exchange-btn {
|
||||
/* 核心数值展示 */
|
||||
.voucher-hero {
|
||||
margin-top: 24rpx;
|
||||
width: 180rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 30rpx;
|
||||
background: $white;
|
||||
color: var(--ui-BG-Main);
|
||||
font-size: 24rpx;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
.hero-left {
|
||||
.hero-symbol {
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
margin-right: 6rpx;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
.hero-num {
|
||||
font-size: 64rpx;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
line-height: 1.1;
|
||||
font-family: OPPOSANS, DIN, -apple-system, sans-serif;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
|
||||
.hero-unit {
|
||||
font-size: 26rpx;
|
||||
color: #f4d397;
|
||||
font-weight: 600;
|
||||
margin-left: 12rpx;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.exchange-btn {
|
||||
height: 56rpx;
|
||||
padding: 0 24rpx;
|
||||
background: linear-gradient(90deg, #f7dfa6 0%, #e2be78 100%);
|
||||
border-radius: 28rpx;
|
||||
color: #3b2b10;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 6rpx 16rpx rgba(226, 190, 120, 0.28);
|
||||
}
|
||||
}
|
||||
|
||||
/* 胶囊指示栏 */
|
||||
.rate-capsule {
|
||||
margin-top: 24rpx;
|
||||
background: rgba(244, 211, 151, 0.1);
|
||||
border: 1rpx solid rgba(244, 211, 151, 0.22);
|
||||
border-radius: 12rpx;
|
||||
padding: 14rpx 20rpx;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
.capsule-left {
|
||||
.capsule-dot {
|
||||
width: 10rpx;
|
||||
height: 10rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #eabf76;
|
||||
margin-right: 12rpx;
|
||||
box-shadow: 0 0 8rpx #eabf76;
|
||||
}
|
||||
|
||||
.capsule-text {
|
||||
font-size: 24rpx;
|
||||
color: #fce8bf;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.capsule-tag {
|
||||
font-size: 20rpx;
|
||||
color: #f7d598;
|
||||
opacity: 0.85;
|
||||
}
|
||||
}
|
||||
|
||||
/* 底部估值栏 */
|
||||
.card-footer {
|
||||
margin-top: 26rpx;
|
||||
padding-top: 22rpx;
|
||||
border-top: 1rpx solid rgba(255, 255, 255, 0.08);
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
.footer-metric {
|
||||
flex: 1;
|
||||
|
||||
.metric-label {
|
||||
font-size: 22rpx;
|
||||
color: rgba(255, 255, 255, 0.55);
|
||||
display: block;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
.metric-val-wrap {
|
||||
.currency-symbol {
|
||||
font-size: 24rpx;
|
||||
color: #f4d397;
|
||||
font-weight: 600;
|
||||
margin-right: 2rpx;
|
||||
margin-bottom: 2rpx;
|
||||
}
|
||||
|
||||
.metric-val {
|
||||
font-size: 30rpx;
|
||||
font-weight: 700;
|
||||
color: #f4d397;
|
||||
font-family: OPPOSANS, DIN, -apple-system, sans-serif;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 12rpx;
|
||||
background: rgba(255, 255, 255, 0.35);
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
/* 列表标题区 */
|
||||
.section-header {
|
||||
padding: 30rpx 32rpx 16rpx;
|
||||
|
||||
.progress-inner {
|
||||
height: 100%;
|
||||
background: $white;
|
||||
border-radius: 8rpx;
|
||||
.section-title-wrap {
|
||||
.title-bar {
|
||||
width: 6rpx;
|
||||
height: 28rpx;
|
||||
border-radius: 4rpx;
|
||||
background: linear-gradient(180deg, #dfb775 0%, #ba8938 100%);
|
||||
margin-right: 14rpx;
|
||||
}
|
||||
|
||||
&.dark {
|
||||
background: var(--ui-BG-Main);
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #22252a;
|
||||
}
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: 22rpx;
|
||||
color: #999ea6;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-wrap {
|
||||
padding: 60rpx 0;
|
||||
}
|
||||
|
||||
/* 计划卡片列表 */
|
||||
.list-container {
|
||||
padding: 0 30rpx 20rpx;
|
||||
|
||||
.log-card {
|
||||
background: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
padding: 26rpx 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(35, 42, 60, 0.04);
|
||||
border: 1rpx solid #f0f1f5;
|
||||
|
||||
.log-top {
|
||||
.log-title-box {
|
||||
.coin-icon {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #fef4e2 0%, #fae6c3 100%);
|
||||
margin-right: 18rpx;
|
||||
|
||||
.cicon-voucher {
|
||||
font-size: 32rpx;
|
||||
color: #bf8d3b;
|
||||
}
|
||||
}
|
||||
|
||||
.log-main-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.log-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #23272e;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
.log-date {
|
||||
font-size: 22rpx;
|
||||
color: #9ea4af;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.log-amount {
|
||||
.amount-num {
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
color: #23272e;
|
||||
font-family: OPPOSANS, DIN, -apple-system, sans-serif;
|
||||
}
|
||||
|
||||
.amount-status {
|
||||
font-size: 20rpx;
|
||||
padding: 4rpx 12rpx;
|
||||
border-radius: 6rpx;
|
||||
|
||||
&.releasing {
|
||||
color: #b58028;
|
||||
background-color: #fef5e7;
|
||||
}
|
||||
|
||||
&.finished {
|
||||
color: #10b981;
|
||||
background-color: #e6f9f0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 进度条 */
|
||||
.plan-progress-box {
|
||||
.progress-info {
|
||||
.progress-txt {
|
||||
font-size: 22rpx;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.progress-percent {
|
||||
font-size: 22rpx;
|
||||
color: #b58028;
|
||||
font-weight: 600;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 12rpx;
|
||||
background: #f1f3f6;
|
||||
border-radius: 6rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.progress-inner {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #f7dfa6 0%, #e2be78 100%);
|
||||
border-radius: 6rpx;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.log-tags {
|
||||
flex-wrap: wrap;
|
||||
gap: 12rpx;
|
||||
|
||||
.tag-item {
|
||||
background-color: #f7f8fb;
|
||||
border-radius: 8rpx;
|
||||
padding: 6rpx 14rpx;
|
||||
|
||||
.tag-txt {
|
||||
font-size: 22rpx;
|
||||
color: #6b7280;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wallet-list {
|
||||
padding: 30rpx;
|
||||
/* 规则弹窗样式 */
|
||||
.rule-popup-body {
|
||||
padding: 36rpx 36rpx 48rpx;
|
||||
background-color: #ffffff;
|
||||
|
||||
.title {
|
||||
.rule-popup-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
color: #1e222a;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.rule-item {
|
||||
.rule-item-title {
|
||||
.rule-seq {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 50%;
|
||||
background: #f7dfa6;
|
||||
color: #3b2b10;
|
||||
font-size: 20rpx;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.rule-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #252932;
|
||||
}
|
||||
}
|
||||
|
||||
.rule-item-desc {
|
||||
font-size: 24rpx;
|
||||
color: #6a7180;
|
||||
line-height: 38rpx;
|
||||
padding-left: 44rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.rule-confirm-btn {
|
||||
width: 100%;
|
||||
height: 84rpx;
|
||||
line-height: 84rpx;
|
||||
text-align: center;
|
||||
background: linear-gradient(90deg, #2b2e38 0%, #17181d 100%);
|
||||
color: #f7d598;
|
||||
font-size: 28rpx;
|
||||
color: $dark-3;
|
||||
}
|
||||
|
||||
.money {
|
||||
font-size: 26rpx;
|
||||
color: $dark-3;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.desc {
|
||||
color: $gray-c;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
background: #f3e6d2;
|
||||
font-weight: 600;
|
||||
border-radius: 42rpx;
|
||||
box-shadow: 0 8rpx 20rpx rgba(25, 27, 33, 0.2);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
在新工单中引用
屏蔽一个用户