完成代码路径重构

This commit is contained in:
2026-03-18 08:36:49 +08:00
parent 4041933e42
commit c2cd6dcd95
290 changed files with 866 additions and 38459 deletions

View File

@@ -0,0 +1,836 @@
<template>
<view class="finance-transaction-stats">
<!-- 头部筛选 -->
<view class="header-filters">
<view class="date-tabs">
<text
v-for="(item, index) in dateOptions"
:key="index"
class="date-tab-item"
:class="{ active: activeDateTab === index }"
@click="activeDateTab = index"
>{{ item }}</text>
</view>
<view class="date-picker-wrap">
<text class="calendar-icon">D</text>
<text class="date-range-text">2026-02-03 - 2026-02-03</text>
</view>
</view>
<!-- 交易概况区块 (CRMEB 1:1 复刻) -->
<view class="overview-card">
<view class="overview-header">
<view class="header-left">
<text class="section-title">交易概况</text>
<text class="info-tag">?</text>
</view>
<view class="header-right">
<view class="date-picker-inline">
<text class="date-text">2026/01/05 - 2026/02/03</text>
</view>
<button class="btn-query">查询</button>
<button class="btn-export">导出</button>
</view>
</view>
<!-- 指标网格 -->
<view class="overview-grid">
<!-- 第一行 -->
<view class="grid-row">
<view class="overview-item">
<view class="icon-box blue"><text class="icon">🕒</text></view>
<view class="item-info">
<text class="item-label">营业额</text>
<text class="item-value">442753.70</text>
<view class="trend-row">
<text class="trend-label">环比增长:</text>
<text class="trend-value up">44275370% ▲</text>
</view>
</view>
</view>
<view class="overview-item">
<view class="icon-box green"><text class="icon">¥</text></view>
<view class="item-info">
<text class="item-label">商品支付金额</text>
<text class="item-value">434693.52</text>
<view class="trend-row">
<text class="trend-label">环比增长:</text>
<text class="trend-value up">43469352% ▲</text>
</view>
</view>
</view>
<view class="overview-item">
<view class="icon-box orange"><text class="icon">🔒</text></view>
<view class="item-info">
<text class="item-label">购买会员金额</text>
<text class="item-value">8059.18</text>
<view class="trend-row">
<text class="trend-label">环比增长:</text>
<text class="trend-value up">805918% ▲</text>
</view>
</view>
</view>
<view class="overview-item">
<view class="icon-box purple"><text class="icon">💰</text></view>
<view class="item-info">
<text class="item-label">充值金额</text>
<text class="item-value">0.00</text>
<view class="trend-row">
<text class="trend-label">环比增长:</text>
<text class="trend-value">0% -</text>
</view>
</view>
</view>
<view class="overview-item">
<view class="icon-box cyan"><text class="icon">🛒</text></view>
<view class="item-info">
<text class="item-label">线下收银金额</text>
<text class="item-value">1</text>
<view class="trend-row">
<text class="trend-label">环比增长:</text>
<text class="trend-value up">100% ▲</text>
</view>
</view>
</view>
</view>
<!-- 第二行 -->
<view class="grid-row second">
<view class="overview-item">
<view class="icon-box light-green"><text class="icon">↘</text></view>
<view class="item-info">
<text class="item-label">支出金额</text>
<text class="item-value">442752.69</text>
<view class="trend-row">
<text class="trend-label">环比增长:</text>
<text class="trend-value up">44275269% ▲</text>
</view>
</view>
</view>
<view class="overview-item">
<view class="icon-box gold"><text class="icon">💳</text></view>
<view class="item-info">
<text class="item-label">余额支付金额</text>
<text class="item-value">442752.69</text>
<view class="trend-row">
<text class="trend-label">环比增长:</text>
<text class="trend-value up">5293.00% ▲</text>
</view>
</view>
</view>
<view class="overview-item">
<view class="icon-box red-purple"><text class="icon"></text></view>
<view class="item-info">
<text class="item-label">支付佣金金额</text>
<text class="item-value">0.00</text>
<view class="trend-row">
<text class="trend-label">环比增长:</text>
<text class="trend-value">0% -</text>
</view>
</view>
</view>
<view class="overview-item">
<view class="icon-box blue-gray"><text class="icon">📦</text></view>
<view class="item-info">
<text class="item-label">商品退款金额</text>
<text class="item-value">0.00</text>
<view class="trend-row">
<text class="trend-label">环比增长:</text>
<text class="trend-value">0% -</text>
</view>
</view>
</view>
<!-- 占位使其对齐 -->
<view class="overview-item transparent"></view>
</view>
</view>
<!-- 概况图表区 -->
<view class="overview-chart-section">
<view class="overview-chart-legend">
<view class="legend-dot blue"><text class="legend-text">营业额</text></view>
<view class="legend-dot green"><text class="legend-text">商品支付金额</text></view>
<view class="legend-dot gray-blue"><text class="legend-text">购买会员金额</text></view>
<view class="legend-dot red"><text class="legend-text">充值金额</text></view>
<view class="legend-dot orange"><text class="legend-text">支出金额</text></view>
</view>
<view class="overview-chart-box">
<EChartsView v-if="overviewTrendOption != null" :option="overviewTrendOption" class="main-trend-chart" />
</view>
</view>
</view>
<!-- 之前的统计卡片区域 -->
<view class="stats-section">
<!-- 左侧:今日订单金额 -->
<view class="stats-card-main">
<view class="card-header">
<text class="card-title">今日订单金额</text>
</view>
<view class="card-content">
<view class="amount-wrap">
<text class="currency">¥</text>
<text class="amount-value">0</text>
</view>
<view class="chart-legend">
<view class="legend-item">
<view class="dot blue"></view>
<text>今天</text>
</view>
<view class="legend-item">
<view class="dot gray"></view>
<text>昨天</text>
</view>
</view>
<view class="chart-box">
<EChartsView v-if="orderAmountOption != null" :option="orderAmountOption" class="stats-chart" />
</view>
</view>
</view>
<!-- 侧边统计网格 -->
<view class="stats-side-grid">
<view class="side-column">
<!-- 今日订单数 -->
<view class="side-stat-card">
<view class="card-header">
<text class="card-title">今日订单数</text>
</view>
<view class="card-body">
<text class="main-val">0</text>
<view class="compare-row">
<text class="label">昨日:</text>
<text class="val">4</text>
</view>
<view class="compare-row">
<text class="label">日环比:</text>
<text class="val down">-100% ▼</text>
</view>
<view class="mini-chart-placeholder">
<view class="blue-line"></view>
</view>
</view>
</view>
<!-- 本月订单数 -->
<view class="side-stat-card">
<view class="card-header">
<text class="card-title">本月订单数</text>
</view>
<view class="card-body">
<text class="main-val">12</text>
<view class="compare-row">
<text class="label">上月:</text>
<text class="val">206</text>
</view>
<view class="compare-row">
<text class="label">月环比:</text>
<text class="val down">-94% ▼</text>
</view>
<view class="mini-chart-placeholder">
<view class="blue-line"></view>
</view>
</view>
</view>
</view>
<view class="side-column">
<!-- 今日支付人数 -->
<view class="side-stat-card">
<view class="card-header">
<text class="card-title">今日支付人数</text>
</view>
<view class="card-body">
<text class="main-val">0</text>
<view class="compare-row">
<text class="label">昨日:</text>
<text class="val">4</text>
</view>
<view class="compare-row">
<text class="label">日环比:</text>
<text class="val down">-100% ▼</text>
</view>
<view class="mini-chart-placeholder">
<view class="blue-line"></view>
</view>
</view>
</view>
<!-- 本月支付人数 -->
<view class="side-stat-card">
<view class="card-header">
<text class="card-title">本月支付人数</text>
</view>
<view class="card-body">
<text class="main-val">7</text>
<view class="compare-row">
<text class="label">上月:</text>
<text class="val">134</text>
</view>
<view class="compare-row">
<text class="label">月环比:</text>
<text class="val down">-94% ▼</text>
</view>
<view class="mini-chart-placeholder">
<view class="blue-line"></view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import { ref, onMounted } from 'vue'
import EChartsView from '@/uni_modules/charts/EChartsView.vue'
const dateOptions = ['今天', '昨天', '最近7天', '最近30天', '本月', '本年']
const activeDateTab = ref(0)
const orderAmountOption = ref<any>(null)
const overviewTrendOption = ref<any>(null)
/**
* 工具函数:将 UTS 对象转换为纯 JavaScript 对象
* 确保 ECharts 在 renderjs 中能正确接收数据
*/
function toPlainObject(obj : any) : any {
if (obj == null) return null
if (typeof obj !== 'object') return obj
if (Array.isArray(obj)) {
return (obj as Array<any>).map((item : any) : any => toPlainObject(item))
}
const plain : Record<string, any> = {}
const keys = Object.keys(obj as Record<string, any>)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
if (key.startsWith('_') || key == 'toJSON') continue
const value = (obj as Record<string, any>)[key]
if (typeof value == 'function') continue
if (value != null && typeof value == 'object' && !Array.isArray(value)) {
plain[key] = toPlainObject(value)
} else {
plain[key] = value
}
}
return plain
}
onMounted(() => {
// 延迟初始化图表确保容器就位
setTimeout(() => {
initCharts()
}, 300)
})
function initCharts() {
// 模拟趋势数据
const todayData = [120, 132, 101, 134, 90, 230, 210]
const yesterdayData = [220, 182, 191, 234, 290, 330, 310]
const option = {
grid: { left: '3%', right: '4%', bottom: '3%', top: '5%', containLabel: true },
tooltip: {
trigger: 'axis',
axisPointer: {
lineStyle: { color: '#1890ff', type: 'dashed' }
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00', '23:59'],
axisLine: { lineStyle: { color: '#f0f0f0' } },
axisLabel: { color: '#999' }
},
yAxis: {
type: 'value',
splitLine: { show: false },
axisLine: { show: false },
axisLabel: { color: '#999' }
},
series: [
{
name: '今天',
type: 'line',
smooth: true,
data: todayData,
lineStyle: { color: '#1890ff', width: 2 },
areaStyle: {
color: {
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(24, 144, 255, 0.2)' },
{ offset: 1, color: 'rgba(24, 144, 255, 0)' }
]
}
},
itemStyle: { color: '#1890ff' }
},
{
name: '昨天',
type: 'line',
smooth: true,
data: yesterdayData,
lineStyle: { color: '#d9d9d9', width: 2, type: 'dashed' },
itemStyle: { color: '#d9d9d9' }
}
]
}
// 核心修复:传递给 ECharts 的 Option 必须是 Plain Object
orderAmountOption.value = toPlainObject(option)
// 初始化交易概况趋势图 (多曲线)
const overviewOption = {
grid: { left: '3%', right: '4%', bottom: '10%', top: '5%', containLabel: true },
tooltip: { trigger: 'axis' },
xAxis: {
type: 'category',
boundaryGap: false,
data: ['2026-01-05', '01-10', '01-15', '01-20', '01-25', '01-31', '02-03'],
axisLine: { lineStyle: { color: '#f0f0f0' } },
axisLabel: { color: '#999', fontSize: 10 }
},
yAxis: {
type: 'value',
axisLine: { show: false },
splitLine: { lineStyle: { color: '#f5f5f5' } },
axisLabel: { color: '#999' }
},
series: [
{
name: '营业额',
type: 'line',
smooth: true,
data: [1000, 5000, 20000, 15000, 80000, 20000, 5000],
itemStyle: { color: '#1890ff' }
},
{
name: '商品支付金额',
type: 'line',
smooth: true,
data: [800, 4000, 18000, 12000, 75000, 18000, 4000],
itemStyle: { color: '#52c41a' }
},
{
name: '支出金额',
type: 'line',
smooth: true,
data: [500, 3000, 15000, 10000, 90000, 15000, 3000],
itemStyle: { color: '#fa8c16' }
}
]
}
overviewTrendOption.value = toPlainObject(overviewOption)
}
</script>
<style scoped lang="scss">
.finance-transaction-stats {
padding: 0;
background-color: transparent;
min-height: auto;
}
/* 头部筛选 */
.header-filters {
background: #fff;
padding: 12px 20px;
border-radius: 4px;
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 20px;
}
.date-tabs {
display: flex;
flex-direction: row;
border: 1px solid #d9d9d9;
border-radius: 2px;
margin-right: 20px;
}
.date-tab-item {
padding: 4px 15px;
font-size: 14px;
color: #666;
border-right: 1px solid #d9d9d9;
cursor: pointer;
&:last-child {
border-right: none;
}
&.active {
background-color: #1890ff;
color: #fff;
border-color: #1890ff;
}
}
.date-picker-wrap {
display: flex;
flex-direction: row;
align-items: center;
padding: 4px 12px;
border: 1px solid #d9d9d9;
border-radius: 2px;
}
.calendar-icon {
margin-right: 8px;
font-size: 14px;
}
.date-range-text {
font-size: 14px;
color: #333;
}
/* 统计区域布局 */
.stats-section {
display: flex;
flex-direction: row;
gap: 16px;
}
.stats-card-main {
flex: 3;
background: #fff;
border-radius: 4px;
padding: 24px;
min-height: 380px;
}
.card-title {
font-size: 16px;
color: #333;
font-weight: 500;
margin-bottom: 20px;
display: block;
}
.amount-wrap {
margin-top: 10px;
}
.currency {
font-size: 24px;
color: #333;
margin-right: 8px;
}
.amount-value {
font-size: 40px;
color: #333;
font-weight: bold;
}
.chart-legend {
display: flex;
flex-direction: row;
margin-top: 16px;
}
.legend-item {
display: flex;
flex-direction: row;
align-items: center;
margin-right: 20px;
font-size: 14px;
color: #666;
}
.dot {
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 8px;
&.blue { background-color: #1890ff; }
&.gray { background-color: #d9d9d9; }
}
.chart-box {
width: 100%;
height: 220px;
margin-top: 20px;
}
.stats-chart {
width: 100%;
height: 100%;
}
/* 侧边网格 */
.stats-side-grid {
flex: 2;
display: flex;
flex-direction: row;
gap: 16px;
}
.side-column {
flex: 1;
display: flex;
flex-direction: column;
gap: 16px;
}
.side-stat-card {
background: #fff;
border-radius: 4px;
padding: 24px;
display: flex;
flex-direction: column;
}
.main-val {
font-size: 32px;
font-weight: bold;
color: #333;
margin-bottom: 20px;
display: block;
}
.compare-row {
display: flex;
flex-direction: row;
margin-bottom: 8px;
font-size: 14px;
}
.compare-row .label {
color: #999;
margin-right: 8px;
}
.compare-row .val {
color: #333;
&.down { color: #52c41a; }
&.up { color: #f5222d; }
}
.mini-chart-placeholder {
margin-top: 20px;
height: 2px;
background-color: #f0f0f0;
position: relative;
}
.blue-line {
position: absolute;
left: 0;
top: 0;
width: 60%;
height: 100%;
background-color: #1890ff;
}
/* 交易概况复刻样式 */
.overview-card {
background: #fff;
border-radius: 4px;
padding: 20px;
margin-bottom: 20px;
}
.overview-header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.overview-header .header-left {
display: flex;
flex-direction: row;
align-items: center;
}
.section-title {
font-size: 16px;
font-weight: bold;
color: #333;
}
.info-tag {
width: 16px;
height: 16px;
border-radius: 50%;
background: #eee;
color: #999;
font-size: 11px;
display: flex;
align-items: center;
justify-content: center;
margin-left: 8px;
}
.overview-header .header-right {
display: flex;
flex-direction: row;
gap: 12px;
}
.date-picker-inline {
border: 1px solid #dcdfe6;
padding: 5px 15px;
border-radius: 4px;
display: flex;
align-items: center;
}
.date-text {
font-size: 13px;
color: #606266;
}
.btn-query, .btn-export {
padding: 0 16px;
height: 32px;
line-height: 32px;
font-size: 13px;
border-radius: 4px;
cursor: pointer;
}
.btn-query {
background-color: #1890ff;
color: #fff;
border: none;
}
.btn-export {
background: #fff;
color: #1890ff;
border: 1px solid #1890ff;
}
/* 指标网格 */
.overview-grid {
display: flex;
flex-direction: column;
gap: 30px;
padding-bottom: 30px;
border-bottom: 1px dashed #f0f0f0;
}
.grid-row {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.overview-item {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
}
.overview-item.transparent {
visibility: hidden;
}
.icon-box {
width: 44px;
height: 44px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12px;
}
.icon-box .icon {
font-size: 20px;
color: #fff;
}
.icon-box.blue { background-color: #2f54eb; }
.icon-box.green { background-color: #52c41a; }
.icon-box.orange { background-color: #fa8c16; }
.icon-box.purple { background-color: #722ed1; }
.icon-box.cyan { background-color: #13c2c2; }
.icon-box.light-green { background-color: #a0d911; }
.icon-box.gold { background-color: #faad14; }
.icon-box.red-purple { background-color: #eb2f96; }
.icon-box.blue-gray { background-color: #4096ff; }
.item-info {
display: flex;
flex-direction: column;
}
.item-label {
font-size: 13px;
color: #999;
margin-bottom: 4px;
}
.item-value {
font-size: 24px;
font-weight: bold;
color: #333;
margin-bottom: 4px;
}
.trend-row {
display: flex;
flex-direction: row;
font-size: 12px;
color: #999;
}
.trend-value.up {
color: #f5222d;
margin-left: 4px;
}
/* 图表区 */
.overview-chart-section {
padding-top: 24px;
}
.overview-chart-legend {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 16px;
margin-bottom: 20px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.legend-dot.blue { background: #1890ff; }
.legend-dot.green { background: #52c41a; }
.legend-dot.gray-blue { background: #607d8b; }
.legend-dot.red { background: #f44336; }
.legend-dot.orange { background: #fa8c16; }
.legend-text {
font-size: 12px;
color: #666;
}
.overview-chart-box {
width: 100%;
height: 400px;
}
.main-trend-chart {
width: 100%;
height: 100%;
}
</style>