完善
This commit is contained in:
247
pages/mall/admin/finance/balance_record.uvue
Normal file
247
pages/mall/admin/finance/balance_record.uvue
Normal file
@@ -0,0 +1,247 @@
|
||||
<template>
|
||||
<view class="finance-balance-record">
|
||||
<!-- 筛选卡片 -->
|
||||
<view class="filter-card border-shadow">
|
||||
<view class="filter-row">
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">订单时间:</text>
|
||||
<view class="date-picker-wrap">
|
||||
<text class="calendar-icon">📅</text>
|
||||
<text class="date-placeholder">开始日期 - 结束日期</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">交易类型:</text>
|
||||
<view class="select-box">
|
||||
<text class="select-txt">请选择</text>
|
||||
<text class="arrow-down">▼</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 列表表格 -->
|
||||
<view class="table-container border-shadow">
|
||||
<view class="table-header">
|
||||
<view class="th col-id"><text class="th-txt">ID</text></view>
|
||||
<view class="th col-order"><text class="th-txt">关联订单</text></view>
|
||||
<view class="th col-time"><text class="th-txt">交易时间</text></view>
|
||||
<view class="th col-amount"><text class="th-txt">交易金额</text></view>
|
||||
<view class="th col-user"><text class="th-txt">用户</text></view>
|
||||
<view class="th col-type"><text class="th-txt">交易类型</text></view>
|
||||
<view class="th col-remark"><text class="th-txt">备注</text></view>
|
||||
<view class="th col-op"><text class="th-txt">操作</text></view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="table-body">
|
||||
<view class="table-row" v-for="item in tableData" :key="item.id">
|
||||
<view class="td col-id"><text class="td-txt">{{ item.id }}</text></view>
|
||||
<view class="td col-order text-left"><text class="td-txt">{{ item.order }}</text></view>
|
||||
<view class="td col-time"><text class="td-txt">{{ item.time }}</text></view>
|
||||
<view class="td col-amount">
|
||||
<text :class="['td-txt', item.amount.startsWith('+') ? 'red-txt' : 'green-txt']">{{ item.amount }}</text>
|
||||
</view>
|
||||
<view class="td col-user"><text class="td-txt">{{ item.user }}</text></view>
|
||||
<view class="td col-type"><text class="td-txt">{{ item.type }}</text></view>
|
||||
<view class="td col-remark text-left"><text class="td-txt">{{ item.remark }}</text></view>
|
||||
<view class="td col-op">
|
||||
<text class="btn-link">备注</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
interface BalanceRecord {
|
||||
id: string
|
||||
order: string
|
||||
time: string
|
||||
amount: string
|
||||
user: string
|
||||
type: string
|
||||
remark: string
|
||||
}
|
||||
|
||||
const tableData = ref<BalanceRecord[]>([
|
||||
{
|
||||
id: '31216',
|
||||
order: '新用户注册赠送余额',
|
||||
time: '2026-02-03 10:30:11',
|
||||
amount: '+ 88888.00',
|
||||
user: '1',
|
||||
type: '新用户注册赠送余额',
|
||||
remark: '新用户注册赠送88888余额'
|
||||
},
|
||||
{
|
||||
id: '31215',
|
||||
order: '新用户注册赠送余额',
|
||||
time: '2026-02-03 10:19:52',
|
||||
amount: '+ 88888.00',
|
||||
user: 'circus',
|
||||
type: '新用户注册赠送余额',
|
||||
remark: '新用户注册赠送88888余额'
|
||||
},
|
||||
{
|
||||
id: '31214',
|
||||
order: 'cp541560738494283776',
|
||||
time: '2026-02-03 10:09:07',
|
||||
amount: '- 999.00',
|
||||
user: '1岁上班22岁退休',
|
||||
type: '余额支付购买商品',
|
||||
remark: '余额支付999.00元购买商品'
|
||||
},
|
||||
{
|
||||
id: '31213',
|
||||
order: '新用户注册赠送余额',
|
||||
time: '2026-02-03 10:07:59',
|
||||
amount: '+ 88888.00',
|
||||
user: '1岁上班22岁退休',
|
||||
type: '新用户注册赠送余额',
|
||||
remark: '新用户注册赠送88888余额'
|
||||
},
|
||||
{
|
||||
id: '31212',
|
||||
order: '新用户注册赠送余额',
|
||||
time: '2026-02-03 02:17:24',
|
||||
amount: '+ 88888.00',
|
||||
user: '136****0434',
|
||||
type: '新用户注册赠送余额',
|
||||
remark: '新用户注册赠送88888余额'
|
||||
},
|
||||
{
|
||||
id: '31211',
|
||||
order: '新用户注册赠送余额',
|
||||
time: '2026-02-03 02:04:17',
|
||||
amount: '+ 88888.00',
|
||||
user: '灵境',
|
||||
type: '新用户注册赠送余额',
|
||||
remark: '新用户注册赠送88888余额'
|
||||
},
|
||||
{
|
||||
id: '31210',
|
||||
order: '新用户注册赠送余额',
|
||||
time: '2026-02-03 00:58:21',
|
||||
amount: '+ 88888.00',
|
||||
user: 'J.',
|
||||
type: '新用户注册赠送余额',
|
||||
remark: '新用户注册赠送88888余额'
|
||||
}
|
||||
])
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.finance-balance-record {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.border-shadow {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.filter-card { padding: 24px; margin-bottom: 20px; }
|
||||
.filter-row { display: flex; flex-direction: row; align-items: center; }
|
||||
.filter-item { display: flex; flex-direction: row; align-items: center; margin-right: 40px; }
|
||||
.filter-label { font-size: 14px; color: #333; margin-right: 15px; }
|
||||
|
||||
.date-picker-wrap {
|
||||
width: 260px;
|
||||
height: 36px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.select-box {
|
||||
width: 200px;
|
||||
height: 36px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.calendar-icon { font-size: 14px; margin-right: 10px; color: #c0c4cc; }
|
||||
.date-placeholder, .select-txt { font-size: 14px; color: #c0c4cc; }
|
||||
.arrow-down { margin-left: auto; font-size: 10px; color: #c0c4cc; }
|
||||
|
||||
/* 表格样式 */
|
||||
.table-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
background-color: #e6f0ff;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.th {
|
||||
padding: 12px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.th-txt {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.table-row:hover {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.td {
|
||||
padding: 16px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.td-txt {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 列宽分配 (参考截图比例) */
|
||||
.col-id { width: 70px; }
|
||||
.col-order { flex: 1.5; min-width: 180px; justify-content: flex-start; }
|
||||
.col-time { width: 160px; }
|
||||
.col-amount { width: 120px; }
|
||||
.col-user { width: 120px; }
|
||||
.col-type { width: 150px; }
|
||||
.col-remark { flex: 1.8; min-width: 200px; justify-content: flex-start; }
|
||||
.col-op { width: 80px; }
|
||||
|
||||
.text-left { justify-content: flex-start; text-align: left; }
|
||||
|
||||
/* 颜色 */
|
||||
.red-txt { color: #f56c6c; font-weight: 500; }
|
||||
.green-txt { color: #67c23a; font-weight: 500; }
|
||||
.btn-link { color: #1890ff; font-size: 13px; cursor: pointer; }
|
||||
</style>
|
||||
541
pages/mall/admin/finance/balance_stats.uvue
Normal file
541
pages/mall/admin/finance/balance_stats.uvue
Normal file
@@ -0,0 +1,541 @@
|
||||
<template>
|
||||
<view class="finance-balance-stats">
|
||||
<!-- 顶部数据统计卡片 (3列布局) -->
|
||||
<view class="stats-grid">
|
||||
<view class="stat-card border-shadow">
|
||||
<view class="stat-icon-circle bg-blue">
|
||||
<text class="icon-white">💰</text>
|
||||
</view>
|
||||
<view class="stat-content">
|
||||
<text class="stat-value">1447117274.55</text>
|
||||
<text class="stat-label">当前余额</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card border-shadow">
|
||||
<view class="stat-icon-circle bg-orange">
|
||||
<text class="icon-white">🏦</text>
|
||||
</view>
|
||||
<view class="stat-content">
|
||||
<text class="stat-value">1602611838.49</text>
|
||||
<text class="stat-label">累计余额</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stat-card border-shadow">
|
||||
<view class="stat-icon-circle bg-green">
|
||||
<text class="icon-white">💳</text>
|
||||
</view>
|
||||
<view class="stat-content">
|
||||
<text class="stat-value">155494563.94</text>
|
||||
<text class="stat-label">累计消耗余额</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 时间筛选区 -->
|
||||
<view class="filter-bar border-shadow">
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">时间选择:</text>
|
||||
<view class="date-picker-wrap">
|
||||
<text class="calendar-icon">📅</text>
|
||||
<text class="date-range">2026/01/05 - 2026/02/03</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 趋势图表区 (CRMEB 1:1) -->
|
||||
<view class="chart-box border-shadow">
|
||||
<view class="chart-header">
|
||||
<text class="chart-title">余额使用趋势</text>
|
||||
<view class="chart-legend">
|
||||
<view class="legend-item">
|
||||
<view class="dot blue-dot"></view>
|
||||
<text class="legend-txt">余额积累</text>
|
||||
</view>
|
||||
<view class="legend-item">
|
||||
<view class="dot green-dot"></view>
|
||||
<text class="legend-txt">余额消耗</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="chart-ops">
|
||||
<text class="op-icon">📥</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="main-chart-wrap">
|
||||
<EChartsView v-if="trendOption != null" :option="trendOption" class="main-trend-chart" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部双列分析 -->
|
||||
<view class="bottom-analysis">
|
||||
<view class="analysis-box border-shadow">
|
||||
<view class="box-header">
|
||||
<text class="box-title">余额来源分析</text>
|
||||
<view class="btn-toggle" @click="toggleSourceStyle">
|
||||
<text class="toggle-txt">切换样式</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="chart-container">
|
||||
<!-- 样式 0: 图表 -->
|
||||
<EChartsView v-if="sourceStyleMode == 0 && sourceOption != null" :option="sourceOption" class="pie-chart" />
|
||||
|
||||
<!-- 样式 1: 列表 -->
|
||||
<view v-if="sourceStyleMode == 1" class="stats-table">
|
||||
<view class="table-header">
|
||||
<text class="th col-idx">序号</text>
|
||||
<text class="th col-name">来源</text>
|
||||
<text class="th col-amount">金额</text>
|
||||
<text class="th col-percent">占比率</text>
|
||||
</view>
|
||||
<scroll-view class="table-body">
|
||||
<view class="table-row" v-for="(item, index) in sourceData" :key="index">
|
||||
<text class="td col-idx">{{ index + 1 }}</text>
|
||||
<text class="td col-name">{{ item.name }}</text>
|
||||
<text class="td col-amount">{{ item.value.toFixed(2) }}</text>
|
||||
<view class="td col-percent">
|
||||
<view class="progress-container">
|
||||
<view class="progress-bar" :style="{ width: item.percent + '%' }"></view>
|
||||
</view>
|
||||
<text class="percent-txt">{{ item.percent.toFixed(2) }}%</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="analysis-box border-shadow">
|
||||
<view class="box-header">
|
||||
<text class="box-title">余额消耗</text>
|
||||
<view class="btn-toggle" @click="toggleConsumptionStyle">
|
||||
<text class="toggle-txt">切换样式</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="chart-container">
|
||||
<!-- 样式 0: 图表 -->
|
||||
<EChartsView v-if="consumptionStyleMode == 0 && consumptionOption != null" :option="consumptionOption" class="pie-chart" />
|
||||
|
||||
<!-- 样式 1: 列表 -->
|
||||
<view v-if="consumptionStyleMode == 1" class="stats-table">
|
||||
<view class="table-header">
|
||||
<text class="th col-idx">序号</text>
|
||||
<text class="th col-name">来源</text>
|
||||
<text class="th col-amount">金额</text>
|
||||
<text class="th col-percent">占比率</text>
|
||||
</view>
|
||||
<scroll-view class="table-body">
|
||||
<view class="table-row" v-for="(item, index) in consumptionDataList" :key="index">
|
||||
<text class="td col-idx">{{ index + 1 }}</text>
|
||||
<text class="td col-name">{{ item.name }}</text>
|
||||
<text class="td col-amount">{{ item.value.toFixed(2) }}</text>
|
||||
<view class="td col-percent">
|
||||
<view class="progress-container">
|
||||
<view class="progress-bar" :style="{ width: item.percent + '%' }"></view>
|
||||
</view>
|
||||
<text class="percent-txt">{{ item.percent.toFixed(2) }}%</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-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 trendOption = ref<any>(null)
|
||||
const sourceOption = ref<any>(null)
|
||||
const consumptionOption = ref<any>(null)
|
||||
|
||||
// 样式切换状态: 0=图表, 1=列表
|
||||
const sourceStyleMode = ref(0)
|
||||
const consumptionStyleMode = ref(0)
|
||||
|
||||
// 统计数据 (使用 ref 保证响应式)
|
||||
const sourceData = ref([
|
||||
{ value: 125000.00, name: '系统增加', percent: 40.00 },
|
||||
{ value: 93750.00, name: '用户充值', percent: 30.00 },
|
||||
{ value: 78125.00, name: '佣金提现', percent: 25.00 },
|
||||
{ value: 62500.00, name: '抽奖赠送', percent: 20.00 },
|
||||
{ value: 46875.00, name: '商品退款', percent: 15.00 }
|
||||
])
|
||||
|
||||
const consumptionDataList = ref([
|
||||
{ value: 435692.51, name: '购买商品', percent: 50.00 },
|
||||
{ value: 8060.18, name: '购买会员', percent: 20.00 },
|
||||
{ value: 0.00, name: '充值退款', percent: 15.00 },
|
||||
{ value: 0.00, name: '系统减少', percent: 15.00 }
|
||||
])
|
||||
|
||||
/**
|
||||
* 转换 Plain Object 工具
|
||||
*/
|
||||
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(() => {
|
||||
initTrendChart()
|
||||
initSourceChart()
|
||||
initConsumptionChart()
|
||||
}, 300)
|
||||
})
|
||||
|
||||
function initTrendChart() {
|
||||
const dates = ['01-05', '01-06', '01-07', '01-08', '01-09', '01-10', '01-11', '01-12', '01-13', '01-14', '01-15', '01-16', '01-17', '01-18', '01-19', '01-20', '01-21', '01-22', '01-23', '01-24', '01-25', '01-26', '01-27', '01-28', '01-29', '01-30', '01-31', '02-01', '02-02', '02-03']
|
||||
const accumulationData = [2500000, 2900000, 1500000, 2400000, 1800000, 1300000, 500000, 2100000, 3000000, 2800000, 2300000, 2200000, 1500000, 1100000, 2300000, 2800000, 2600000, 2700000, 1800000, 1950000, 650000, 1600000, 1750000, 2400000, 2600000, 2000000, 1400000, 550000, 2100000, 550000]
|
||||
const consumptionData = [10000, 20000, 15000, 120000, 50000, 20000, 10000, 30000, 40000, 35000, 60000, 25000, 30000, 45000, 55000, 110000, 60000, 50000, 40000, 35000, 85000, 45000, 120000, 50000, 45000, 40000, 35000, 55000, 65000, 45000]
|
||||
|
||||
const option = {
|
||||
grid: { left: '3%', right: '4%', bottom: '5%', top: '5%', containLabel: true },
|
||||
tooltip: { trigger: 'axis' },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: dates,
|
||||
axisLine: { lineStyle: { color: '#f0f0f0' } },
|
||||
axisLabel: { color: '#999', interval: 4 }
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLine: { show: false },
|
||||
splitLine: { lineStyle: { color: '#f5f5f5' } },
|
||||
axisLabel: { color: '#999' }
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '余额积累',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: accumulationData,
|
||||
itemStyle: { color: '#1890ff' }
|
||||
},
|
||||
{
|
||||
name: '余额消耗',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: consumptionData,
|
||||
itemStyle: { color: '#52c41a' }
|
||||
}
|
||||
]
|
||||
}
|
||||
trendOption.value = toPlainObject(option)
|
||||
}
|
||||
|
||||
function initSourceChart() {
|
||||
const option = {
|
||||
tooltip: { trigger: 'item', formatter: '{b}: {c}%' },
|
||||
legend: { orient: 'vertical', right: '5%', top: 'center', itemWidth: 10, itemHeight: 10 },
|
||||
color: ['#5b8ff9', '#5ad8a6', '#5d7092', '#f6bd16', '#e8684a'],
|
||||
series: [
|
||||
{
|
||||
name: '余额来源',
|
||||
type: 'pie',
|
||||
radius: '70%',
|
||||
center: ['40%', '50%'],
|
||||
label: { show: true, fontSize: 11, formatter: '{b}\n{c}%' },
|
||||
// 关键点:将图表数据映射到 percent 字段
|
||||
data: sourceData.value.map(item => ({ value: item.percent, name: item.name }))
|
||||
}
|
||||
]
|
||||
}
|
||||
sourceOption.value = toPlainObject(option)
|
||||
}
|
||||
|
||||
function initConsumptionChart() {
|
||||
const option = {
|
||||
tooltip: { trigger: 'item', formatter: '{b}: {c}%' },
|
||||
legend: { orient: 'vertical', right: '5%', top: 'center', itemWidth: 10, itemHeight: 10 },
|
||||
color: ['#5b8ff9', '#5ad8a6', '#5d7092', '#f6bd16'],
|
||||
series: [
|
||||
{
|
||||
name: '余额消耗',
|
||||
type: 'pie',
|
||||
radius: '70%',
|
||||
center: ['40%', '50%'],
|
||||
label: { show: true, fontSize: 11, formatter: '{b}\n{c}%' },
|
||||
// 关键点:将图表数据映射到 percent 字段
|
||||
data: consumptionDataList.value.map(item => ({ value: item.percent, name: item.name }))
|
||||
}
|
||||
]
|
||||
}
|
||||
consumptionOption.value = toPlainObject(option)
|
||||
}
|
||||
|
||||
function toggleSourceStyle() {
|
||||
sourceStyleMode.value = sourceStyleMode.value === 0 ? 1 : 0
|
||||
if (sourceStyleMode.value === 0) {
|
||||
setTimeout(() => initSourceChart(), 50)
|
||||
}
|
||||
}
|
||||
|
||||
function toggleConsumptionStyle() {
|
||||
consumptionStyleMode.value = consumptionStyleMode.value === 0 ? 1 : 0
|
||||
if (consumptionStyleMode.value === 0) {
|
||||
setTimeout(() => initConsumptionChart(), 50)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.finance-balance-stats {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.border-shadow {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* 顶部卡片 */
|
||||
.stats-grid {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
padding: 24px 30px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stats-grid .stat-card:first-child { margin-left: 0; }
|
||||
.stats-grid .stat-card:last-child { margin-right: 0; }
|
||||
|
||||
.stat-icon-circle {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.bg-blue { background-color: #40a9ff; }
|
||||
.bg-orange { background-color: #ffa940; }
|
||||
.bg-green { background-color: #73d13d; }
|
||||
|
||||
.icon-white { color: #fff; font-size: 24px; }
|
||||
|
||||
.stat-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 28px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* 时间筛选区 */
|
||||
.filter-bar {
|
||||
padding: 16px 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.date-picker-wrap {
|
||||
width: 320px;
|
||||
height: 36px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.calendar-icon { font-size: 14px; color: #c0c4cc; margin-right: 10px; }
|
||||
.date-range { font-size: 14px; color: #606266; }
|
||||
|
||||
/* 趋势图表区 */
|
||||
.chart-box {
|
||||
padding: 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.chart-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.chart-title { font-size: 16px; font-weight: 600; color: #303133; margin-right: auto; }
|
||||
|
||||
.chart-legend {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.legend-item { display: flex; flex-direction: row; align-items: center; margin-left: 20px; }
|
||||
.legend-txt { font-size: 13px; color: #666; }
|
||||
.dot { width: 10px; height: 10px; border-radius: 5px; margin-right: 8px; }
|
||||
.blue-dot { background-color: #1890ff; }
|
||||
.green-dot { background-color: #52c41a; }
|
||||
|
||||
.chart-ops { margin-left: 20px; }
|
||||
.op-icon { font-size: 20px; color: #909399; }
|
||||
|
||||
.main-chart-wrap {
|
||||
height: 400px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.main-trend-chart {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 底部分析 */
|
||||
.bottom-analysis {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 0 -10px 40px -10px;
|
||||
}
|
||||
|
||||
.analysis-box {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.box-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.box-title { font-size: 15px; font-weight: 600; color: #303133; }
|
||||
|
||||
.btn-toggle {
|
||||
padding: 4px 12px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.toggle-txt { font-size: 12px; color: #606266; }
|
||||
|
||||
.chart-container {
|
||||
height: 300px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pie-chart {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 列表样式 */
|
||||
.stats-table {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background-color: #e6f0ff;
|
||||
padding: 12px 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.th {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 15px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.td {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.col-idx { width: 60px; }
|
||||
.col-name { flex: 1; }
|
||||
.col-amount { flex: 1.5; }
|
||||
.col-percent { flex: 2; display: flex; flex-direction: row; align-items: center; justify-content: center; padding: 0 20px; }
|
||||
|
||||
.progress-container {
|
||||
flex: 1;
|
||||
height: 8px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
margin-right: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 100%;
|
||||
background-color: #1890ff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.percent-txt {
|
||||
width: 60px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
422
pages/mall/admin/finance/bill.uvue
Normal file
422
pages/mall/admin/finance/bill.uvue
Normal file
@@ -0,0 +1,422 @@
|
||||
<template>
|
||||
<view class="finance-bill">
|
||||
<!-- 头部筛选 -->
|
||||
<view class="filter-card border-shadow">
|
||||
<view class="filter-row">
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">创建时间:</text>
|
||||
<view class="date-picker-wrap">
|
||||
<text class="calendar-icon">📅</text>
|
||||
<text class="date-placeholder">开始日期 - 结束日期</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<view class="content-card border-shadow">
|
||||
<!-- 汇总选项卡 -->
|
||||
<view class="tab-header">
|
||||
<view class="tab-item active"><text class="tab-txt active-txt">日账单</text></view>
|
||||
<view class="tab-item"><text class="tab-txt">周账单</text></view>
|
||||
<view class="tab-item"><text class="tab-txt">月账单</text></view>
|
||||
</view>
|
||||
|
||||
<!-- 表格区域 -->
|
||||
<view class="table-container">
|
||||
<view class="table-header">
|
||||
<view class="th col-id"><text class="th-txt">ID</text></view>
|
||||
<view class="th col-title"><text class="th-txt">标题</text></view>
|
||||
<view class="th col-date"><text class="th-txt">日期</text></view>
|
||||
<view class="th col-income"><text class="th-txt">收入金额</text></view>
|
||||
<view class="th col-expense"><text class="th-txt">支出金额</text></view>
|
||||
<view class="th col-entry"><text class="th-txt">入账金额</text></view>
|
||||
<view class="th col-ops"><text class="th-txt">操作</text></view>
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="item in tableData" :key="item.id">
|
||||
<view class="td col-id"><text class="td-txt">{{ item.id }}</text></view>
|
||||
<view class="td col-title text-left"><text class="td-txt">{{ item.title }}</text></view>
|
||||
<view class="td col-date"><text class="td-txt">{{ item.date }}</text></view>
|
||||
<view class="td col-income"><text class="td-txt red-txt">¥{{ item.income }}</text></view>
|
||||
<view class="td col-expense"><text class="td-txt green-txt">¥{{ item.expense }}</text></view>
|
||||
<view class="td col-entry"><text class="td-txt">¥{{ item.entry }}</text></view>
|
||||
<view class="td col-ops">
|
||||
<view class="ops-wrap">
|
||||
<text class="op-link">账单详情</text>
|
||||
<text class="op-divider">|</text>
|
||||
<text class="op-link">下载</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
interface BillSumRecord {
|
||||
id: number
|
||||
title: string
|
||||
date: string
|
||||
income: string
|
||||
expense: string
|
||||
entry: string
|
||||
}
|
||||
|
||||
const tableData = ref<BillSumRecord[]>([
|
||||
{ id: 1, title: '日账单', date: '2026-02-03', income: '0.00', expense: '0.00', entry: '0.00' },
|
||||
{ id: 2, title: '日账单', date: '2026-02-01', income: '0.00', expense: '0.00', entry: '0.00' },
|
||||
{ id: 3, title: '日账单', date: '2026-01-30', income: '0.00', expense: '0.00', entry: '0.00' },
|
||||
{ id: 4, title: '日账单', date: '2026-01-29', income: '0.00', expense: '0.00', entry: '0.00' },
|
||||
{ id: 5, title: '日账单', date: '2026-01-28', income: '0.00', expense: '0.00', entry: '0.00' },
|
||||
{ id: 6, title: '日账单', date: '2026-01-27', income: '0.00', expense: '0.00', entry: '0.00' },
|
||||
{ id: 7, title: '日账单', date: '2026-01-26', income: '0.00', expense: '0.00', entry: '0.00' },
|
||||
{ id: 8, title: '日账单', date: '2026-01-25', income: '0.00', expense: '0.00', entry: '0.00' },
|
||||
{ id: 9, title: '日账单', date: '2026-01-23', income: '0.00', expense: '0.00', entry: '0.00' },
|
||||
{ id: 10, title: '日账单', date: '2026-01-22', income: '0.00', expense: '0.00', entry: '0.00' }
|
||||
])
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.finance-bill {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.border-shadow {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* 筛选 */
|
||||
.filter-card {
|
||||
padding: 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.date-picker-wrap {
|
||||
width: 280px;
|
||||
height: 36px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.calendar-icon {
|
||||
font-size: 14px;
|
||||
margin-right: 8px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.date-placeholder {
|
||||
font-size: 14px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
/* 内容卡片 */
|
||||
.content-card {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tab-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0 20px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
padding: 16px 20px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-item.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 20%;
|
||||
right: 20%;
|
||||
height: 2px;
|
||||
background-color: #1890ff;
|
||||
}
|
||||
|
||||
.tab-txt {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.active-txt {
|
||||
color: #1890ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 表格样式 */
|
||||
.table-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
background-color: #e6f0ff; /* 对应截图的淡蓝色背景 */
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.th {
|
||||
padding: 14px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.th-txt {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.table-row:hover {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.td {
|
||||
padding: 16px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.td-txt {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 列宽分配 */
|
||||
.col-id { width: 80px; }
|
||||
.col-title { width: 150px; }
|
||||
.col-date { width: 220px; }
|
||||
.col-income { width: 180px; }
|
||||
.col-expense { width: 180px; }
|
||||
.col-entry { width: 180px; }
|
||||
.col-ops { flex: 1; min-width: 150px; }
|
||||
|
||||
.text-left {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
/* 颜色 */
|
||||
.red-txt {
|
||||
color: #f5222d; /* 收入红色 */
|
||||
}
|
||||
|
||||
.green-txt {
|
||||
color: #52c41a; /* 支出绿色 */
|
||||
}
|
||||
|
||||
/* 操作项 */
|
||||
.ops-wrap {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.op-link {
|
||||
font-size: 14px;
|
||||
color: #1890ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.op-divider {
|
||||
margin: 0 8px;
|
||||
color: #e8e8e8;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.finance-bill {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.border-shadow {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.filter-card {
|
||||
padding: 20px 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-right: 28px;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.date-picker-wrap, .select-box {
|
||||
width: 200px;
|
||||
height: 32px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.calendar-icon {
|
||||
font-size: 12px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.date-placeholder, .select-txt {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.arrow-down {
|
||||
margin-left: auto;
|
||||
font-size: 8px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.btn-query, .btn-export {
|
||||
height: 32px;
|
||||
padding: 0 20px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.btn-query {
|
||||
background-color: #1890ff;
|
||||
}
|
||||
|
||||
.btn-export {
|
||||
background-color: #fff;
|
||||
border: 1px solid #dcdfe6;
|
||||
}
|
||||
|
||||
.btn-txt { color: #fff; font-size: 14px; }
|
||||
.export-txt { color: #606266; font-size: 14px; }
|
||||
|
||||
/* 表格样式 */
|
||||
.table-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
background-color: #f8f9fb;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.th {
|
||||
padding: 15px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.th-txt {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.td {
|
||||
padding: 15px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.td-txt {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.col-id { width: 100px; }
|
||||
.col-title { width: 150px; }
|
||||
.col-type { width: 120px; }
|
||||
.col-amount { width: 120px; }
|
||||
.col-time { width: 180px; }
|
||||
.col-remark { flex: 1; min-width: 200px; }
|
||||
|
||||
.text-left { justify-content: flex-start; }
|
||||
|
||||
.type-tag {
|
||||
font-size: 12px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.tag-green { background-color: #f0f9eb; color: #67c23a; border: 1px solid #e1f3d8; }
|
||||
.tag-orange { background-color: #fdf6ec; color: #e6a23c; border: 1px solid #faecd8; }
|
||||
|
||||
.green-txt { color: #67c23a; }
|
||||
.red-txt { color: #f56c6c; }
|
||||
</style>
|
||||
317
pages/mall/admin/finance/capital_flow.uvue
Normal file
317
pages/mall/admin/finance/capital_flow.uvue
Normal file
@@ -0,0 +1,317 @@
|
||||
<template>
|
||||
<view class="finance-capital-flow">
|
||||
<!-- 头部筛选区 -->
|
||||
<view class="filter-card border-shadow">
|
||||
<view class="filter-row">
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">订单时间:</text>
|
||||
<view class="date-picker-wrap">
|
||||
<text class="calendar-icon">📅</text>
|
||||
<text class="date-placeholder">开始日期 - 结束日期</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">交易类型:</text>
|
||||
<view class="select-box">
|
||||
<text class="select-txt">请选择</text>
|
||||
<text class="arrow-down">▼</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item search-wrap">
|
||||
<text class="filter-label">流水搜索:</text>
|
||||
<input class="search-input" placeholder="订单号/昵称/电话/用户ID" />
|
||||
</view>
|
||||
<view class="btn-query">
|
||||
<text class="btn-txt">查询</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据表格 (Flex 模拟) -->
|
||||
<view class="table-container border-shadow">
|
||||
<view class="table-header">
|
||||
<view class="th col-flow"><text class="th-txt">交易单号</text></view>
|
||||
<view class="th col-order"><text class="th-txt">关联订单</text></view>
|
||||
<view class="th col-time"><text class="th-txt">交易时间</text></view>
|
||||
<view class="th col-amount"><text class="th-txt">交易金额</text></view>
|
||||
<view class="th col-user"><text class="th-txt">交易用户</text></view>
|
||||
<view class="th col-method"><text class="th-txt">支付方式</text></view>
|
||||
<view class="th col-remark"><text class="th-txt">备注</text></view>
|
||||
<view class="th col-ops"><text class="th-txt">操作</text></view>
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="item in tableData" :key="item.flowNo">
|
||||
<view class="td col-flow"><text class="td-txt">{{ item.flowNo }}</text></view>
|
||||
<view class="td col-order text-left"><text class="td-txt">{{ item.orderNo }}</text></view>
|
||||
<view class="td col-time"><text class="td-txt">{{ item.time }}</text></view>
|
||||
<view class="td col-amount"><text class="td-txt red-txt">{{ item.amount }}</text></view>
|
||||
<view class="td col-user"><text class="td-txt">{{ item.user }}</text></view>
|
||||
<view class="td col-method"><text class="td-txt">{{ item.method }}</text></view>
|
||||
<view class="td col-remark"><text class="td-txt">{{ item.remark }}</text></view>
|
||||
<view class="td col-ops">
|
||||
<text class="op-link">备注</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
interface FlowRecord {
|
||||
flowNo: string
|
||||
orderNo: string
|
||||
time: string
|
||||
amount: string
|
||||
user: string
|
||||
method: string
|
||||
remark: string
|
||||
}
|
||||
|
||||
const tableData = ref<FlowRecord[]>([
|
||||
{
|
||||
flowNo: 'ZJ202602031258428744',
|
||||
orderNo: 'hy541422245264752640',
|
||||
time: '2026-02-03 00:58:42',
|
||||
amount: '+0.00',
|
||||
user: 'J.',
|
||||
method: '微信',
|
||||
remark: ''
|
||||
},
|
||||
{
|
||||
flowNo: 'ZJ202602011056592117',
|
||||
orderNo: 'hy541029224517992448',
|
||||
time: '2026-02-01 22:56:59',
|
||||
amount: '+0.00',
|
||||
user: 'dev 王鑫',
|
||||
method: '微信',
|
||||
remark: ''
|
||||
},
|
||||
{
|
||||
flowNo: 'ZJ202602010513443817',
|
||||
orderNo: 'hy540942844546777088',
|
||||
time: '2026-02-01 17:13:44',
|
||||
amount: '+0.00',
|
||||
user: 'Sunshine',
|
||||
method: '微信',
|
||||
remark: ''
|
||||
},
|
||||
{
|
||||
flowNo: 'ZJ202602010127248683',
|
||||
orderNo: 'hy540885887420989440',
|
||||
time: '2026-02-01 13:27:24',
|
||||
amount: '+0.00',
|
||||
user: '132****8769',
|
||||
method: '微信',
|
||||
remark: ''
|
||||
},
|
||||
{
|
||||
flowNo: 'ZJ202602011215407366',
|
||||
orderNo: 'hy540686639874179072',
|
||||
time: '2026-02-01 00:15:40',
|
||||
amount: '+0.00',
|
||||
user: '177****9187',
|
||||
method: '微信',
|
||||
remark: ''
|
||||
},
|
||||
{
|
||||
flowNo: 'ZJ202601301026512881',
|
||||
orderNo: 'hy540296867267739648',
|
||||
time: '2026-01-30 22:26:51',
|
||||
amount: '+0.00',
|
||||
user: '暂未成功人士',
|
||||
method: '微信',
|
||||
remark: ''
|
||||
},
|
||||
{
|
||||
flowNo: 'ZJ202601300534267557',
|
||||
orderNo: 'hy540223279126806528',
|
||||
time: '2026-01-30 17:34:26',
|
||||
amount: '+0.00',
|
||||
user: 'b342865d2077',
|
||||
method: '微信',
|
||||
remark: ''
|
||||
}
|
||||
])
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.finance-capital-flow {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.border-shadow {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* 筛选卡片 */
|
||||
.filter-card {
|
||||
padding: 20px 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-right: 28px;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin-right: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.date-picker-wrap {
|
||||
width: 220px;
|
||||
height: 32px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.calendar-icon {
|
||||
font-size: 12px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.date-placeholder {
|
||||
font-size: 13px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.select-box {
|
||||
width: 200px;
|
||||
height: 32px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.select-txt {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.arrow-down {
|
||||
font-size: 8px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.search-wrap {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
height: 32px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
padding: 0 12px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.btn-query {
|
||||
background-color: #1890ff;
|
||||
border-radius: 4px;
|
||||
height: 32px;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.btn-txt {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 表格 */
|
||||
.table-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
background-color: #f8f9fb;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.th {
|
||||
padding: 15px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.th-txt {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.td {
|
||||
padding: 15px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.td-txt {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.col-flow { width: 200px; }
|
||||
.col-order { width: 220px; }
|
||||
.col-time { width: 180px; }
|
||||
.col-amount { width: 120px; }
|
||||
.col-user { width: 150px; }
|
||||
.col-method { width: 120px; }
|
||||
.col-remark { flex: 1; min-width: 100px; }
|
||||
.col-ops { width: 100px; }
|
||||
|
||||
.text-left {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.red-txt {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.op-link {
|
||||
font-size: 13px;
|
||||
color: #1890ff;
|
||||
}
|
||||
</style>
|
||||
358
pages/mall/admin/finance/commission.uvue
Normal file
358
pages/mall/admin/finance/commission.uvue
Normal file
@@ -0,0 +1,358 @@
|
||||
<template>
|
||||
<view class="finance-commission">
|
||||
<!-- 筛选卡片 -->
|
||||
<view class="filter-card border-shadow">
|
||||
<view class="filter-row">
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">昵称/手机号/分销商ID:</text>
|
||||
<input class="search-input" placeholder="请输入昵称搜索" />
|
||||
</view>
|
||||
<view class="btn-query">
|
||||
<text class="btn-txt">查询</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 列表表格 -->
|
||||
<view class="table-card border-shadow">
|
||||
<view class="action-bar">
|
||||
<view class="btn-export">
|
||||
<text class="export-txt">导出</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="table-container">
|
||||
<view class="table-header">
|
||||
<view class="th col-user"><text class="th-txt">用户信息</text></view>
|
||||
<view class="th col-total"><text class="th-txt">总佣金金额</text></view>
|
||||
<view class="th col-account"><text class="th-txt">账户佣金</text></view>
|
||||
<view class="th col-withdraw"><text class="th-txt">提现佣金</text></view>
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="item in tableData" :key="item.uid">
|
||||
<view class="td col-user">
|
||||
<text class="td-txt">{{ item.userInfo }}</text>
|
||||
</view>
|
||||
<view class="td col-total">
|
||||
<text class="td-txt">{{ item.totalAmount }}</text>
|
||||
</view>
|
||||
<view class="td col-account">
|
||||
<text class="td-txt">{{ item.accountAmount }}</text>
|
||||
</view>
|
||||
<view class="td col-withdraw">
|
||||
<text class="td-txt">{{ item.withdrawAmount }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
interface CommissionSummary {
|
||||
uid: string
|
||||
userInfo: string
|
||||
totalAmount: string
|
||||
accountAmount: string
|
||||
withdrawAmount: string
|
||||
}
|
||||
|
||||
const tableData = ref<CommissionSummary[]>([
|
||||
{
|
||||
uid: '77418',
|
||||
userInfo: '张迪 | 155****5525 | 77418',
|
||||
totalAmount: '11.00',
|
||||
accountAmount: '11.00',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '69696',
|
||||
userInfo: "I'm yours - | 69696",
|
||||
totalAmount: '0.40',
|
||||
accountAmount: '0.40',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '68582',
|
||||
userInfo: 'guan | 68582',
|
||||
totalAmount: '140.80',
|
||||
accountAmount: '140.80',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '65258',
|
||||
userInfo: '纯爱战神别名王富贵儿 | 158****4881 | 65258',
|
||||
totalAmount: '11.00',
|
||||
accountAmount: '11.00',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '66265',
|
||||
userInfo: '王伟兴 | 66265',
|
||||
totalAmount: '11.99',
|
||||
accountAmount: '11.99',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '65270',
|
||||
userInfo: '199****1781 | 199****1781 | 65270',
|
||||
totalAmount: '31.60',
|
||||
accountAmount: '31.60',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '64572',
|
||||
userInfo: '洒笾菂艸 | 188****2434 | 64572',
|
||||
totalAmount: '0.20',
|
||||
accountAmount: '0.20',
|
||||
withdrawAmount: '0'
|
||||
},
|
||||
{
|
||||
uid: '47952',
|
||||
userInfo: '那小子 | 134****3573 | 47952',
|
||||
totalAmount: '19.80',
|
||||
accountAmount: '19.80',
|
||||
withdrawAmount: '0'
|
||||
}
|
||||
])
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.finance-commission {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.border-shadow {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* 筛选 */
|
||||
.filter-card {
|
||||
padding: 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 240px;
|
||||
height: 36px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
padding: 0 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.btn-query {
|
||||
margin-left: 12px;
|
||||
background-color: #1890ff;
|
||||
border-radius: 4px;
|
||||
height: 36px;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-txt {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 表格区域 */
|
||||
.table-card {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.action-bar {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.btn-export {
|
||||
width: 60px;
|
||||
height: 32px;
|
||||
background-color: #e6f7ff;
|
||||
border: 1px solid #91d5ff;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.export-txt {
|
||||
color: #1890ff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.table-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
background-color: #e6f0ff; /* 淡蓝色表头 */
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.th {
|
||||
padding: 14px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.th-txt {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.table-row:hover {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.td {
|
||||
padding: 16px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.td-txt {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 列宽分配 */
|
||||
.col-user { flex: 2; min-width: 300px; justify-content: flex-start; }
|
||||
.col-total { flex: 1; justify-content: flex-start; }
|
||||
.col-account { flex: 1; justify-content: flex-start; }
|
||||
.col-withdraw { flex: 1; justify-content: flex-start; }
|
||||
</style>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.finance-commission {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.border-shadow {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.filter-card {
|
||||
padding: 20px 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-right: 28px;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.date-picker-wrap {
|
||||
width: 220px;
|
||||
height: 32px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.calendar-icon { font-size: 12px; margin-right: 8px; }
|
||||
.date-placeholder { font-size: 13px; color: #c0c4cc; }
|
||||
|
||||
.search-wrap { flex: 1; }
|
||||
.search-input {
|
||||
width: 200px;
|
||||
height: 32px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
padding: 0 12px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.btn-query {
|
||||
height: 32px;
|
||||
padding: 0 20px;
|
||||
background-color: #1890ff;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-txt { color: #fff; font-size: 14px; }
|
||||
|
||||
/* 表格 */
|
||||
.table-container { display: flex; flex-direction: column; }
|
||||
.table-header { background-color: #f8f9fb; display: flex; flex-direction: row; border-bottom: 1px solid #ebeef5; }
|
||||
.th { padding: 15px 10px; display: flex; align-items: center; justify-content: center; }
|
||||
.th-txt { font-size: 14px; font-weight: 600; color: #909399; }
|
||||
|
||||
.table-row { display: flex; flex-direction: row; border-bottom: 1px solid #ebeef5; }
|
||||
.td { padding: 15px 10px; display: flex; align-items: center; justify-content: center; }
|
||||
.td-txt { font-size: 13px; color: #606266; }
|
||||
|
||||
.col-id { width: 80px; }
|
||||
.col-user { width: 180px; justify-content: flex-start; }
|
||||
.col-order { width: 180px; }
|
||||
.col-amount { width: 120px; }
|
||||
.col-type { width: 120px; }
|
||||
.col-time { width: 180px; }
|
||||
.col-status { width: 100px; }
|
||||
|
||||
.avatar { width: 32px; height: 32px; border-radius: 16px; margin-right: 10px; }
|
||||
.user-name { font-size: 13px; color: #606266; }
|
||||
.green-txt { color: #67c23a; font-weight: bold; }
|
||||
|
||||
.status-dot-active {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
background-color: #67c23a;
|
||||
margin-right: 6px;
|
||||
}
|
||||
</style>
|
||||
55
pages/mall/admin/finance/finance-placeholder.scss
Normal file
55
pages/mall/admin/finance/finance-placeholder.scss
Normal file
@@ -0,0 +1,55 @@
|
||||
.page-container {
|
||||
padding: 20px;
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
display: block;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.page-content {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.placeholder-card {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
}
|
||||
|
||||
.placeholder-title {
|
||||
display: block;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #666;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.placeholder-desc {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.placeholder-info {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
color: #1890ff;
|
||||
}
|
||||
394
pages/mall/admin/finance/invoice.uvue
Normal file
394
pages/mall/admin/finance/invoice.uvue
Normal file
@@ -0,0 +1,394 @@
|
||||
<template>
|
||||
<view class="finance-invoice">
|
||||
<!-- 头部筛选区 -->
|
||||
<view class="filter-card border-shadow">
|
||||
<view class="filter-row">
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">创建时间:</text>
|
||||
<view class="date-picker-wrap">
|
||||
<text class="calendar-icon">📅</text>
|
||||
<text class="date-placeholder">开始日期 - 结束日期</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">搜索:</text>
|
||||
<view class="search-group">
|
||||
<view class="select-trigger">
|
||||
<text class="select-txt">请选择</text>
|
||||
<text class="arrow-down">▼</text>
|
||||
</view>
|
||||
<input class="search-input" placeholder="请输入" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn-query">
|
||||
<text class="btn-txt">查询</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 状态切换选项卡 -->
|
||||
<view class="tab-section">
|
||||
<view
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
class="tab-item"
|
||||
:class="{ active: activeTab === index }"
|
||||
@click="activeTab = index"
|
||||
>
|
||||
<text class="tab-title">{{ tab.name }} ({{ tab.count }})</text>
|
||||
<view class="active-line" v-if="activeTab === index"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据表格 (Flex 模拟) -->
|
||||
<view class="table-container border-shadow">
|
||||
<view class="table-header">
|
||||
<view class="th col-order"><text class="th-txt">订单号</text></view>
|
||||
<view class="th col-amount"><text class="th-txt">订单金额</text></view>
|
||||
<view class="th col-type"><text class="th-txt">发票类型</text></view>
|
||||
<view class="th col-header"><text class="th-txt">发票抬头类型</text></view>
|
||||
<view class="th col-time"><text class="th-txt">下单时间</text></view>
|
||||
<view class="th col-status-inv"><text class="th-txt">开票状态</text></view>
|
||||
<view class="th col-status-order"><text class="th-txt">订单状态</text></view>
|
||||
<view class="th col-ops"><text class="th-txt">操作</text></view>
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="item in tableData" :key="item.orderNo">
|
||||
<view class="td col-order text-left"><text class="td-txt">{{ item.orderNo }}</text></view>
|
||||
<view class="td col-amount"><text class="td-txt">¥ {{ item.amount }}</text></view>
|
||||
<view class="td col-type"><text class="td-txt">{{ item.invoiceType }}</text></view>
|
||||
<view class="td col-header"><text class="td-txt">{{ item.headerType }}</text></view>
|
||||
<view class="td col-time"><text class="td-txt">{{ item.time }}</text></view>
|
||||
<view class="td col-status-inv"><text class="td-txt red-cell">{{ item.invStatus }}</text></view>
|
||||
<view class="td col-status-order"><text class="td-txt">{{ item.orderStatus }}</text></view>
|
||||
<view class="td col-ops">
|
||||
<view class="ops-box">
|
||||
<text class="op-link">操作</text>
|
||||
<text class="sep">|</text>
|
||||
<text class="op-link">订单信息</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
const activeTab = ref(0)
|
||||
|
||||
const tabs = ref([
|
||||
{ name: '全部发票', count: 163 },
|
||||
{ name: '待开发票', count: 105 },
|
||||
{ name: '已开发票', count: 34 },
|
||||
{ name: '退款发票', count: 33 }
|
||||
])
|
||||
|
||||
const tableData = ref([
|
||||
{
|
||||
orderNo: 'cp538981381384962048',
|
||||
amount: '999.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2026-01-27 07:19:35',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp523490058603331584',
|
||||
amount: '9.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2025-12-15 13:22:35',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp524967077409193984',
|
||||
amount: '9.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2025-12-19 15:11:44',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp521126678106210304',
|
||||
amount: '11890.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2025-12-09 00:51:22',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp521126166883467264',
|
||||
amount: '11800.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2025-12-09 00:49:20',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp517015093888679936',
|
||||
amount: '142.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2025-11-27 16:33:24',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp313601579989073920',
|
||||
amount: '0.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2024-05-15 08:59:56',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '待评价'
|
||||
},
|
||||
{
|
||||
orderNo: 'cp503871643047690240',
|
||||
amount: '999.00',
|
||||
invoiceType: '电子普通发票',
|
||||
headerType: '个人',
|
||||
time: '2025-10-22 10:06:01',
|
||||
invStatus: '未开票',
|
||||
orderStatus: '未发货'
|
||||
}
|
||||
])
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.finance-invoice {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.border-shadow {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* 筛选栏 */
|
||||
.filter-card {
|
||||
padding: 20px 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.date-picker-wrap {
|
||||
width: 240px;
|
||||
height: 32px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.calendar-icon {
|
||||
margin-right: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.date-placeholder {
|
||||
font-size: 13px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.search-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
height: 32px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.select-trigger {
|
||||
width: 90px;
|
||||
height: 100%;
|
||||
border-right: 1px solid #dcdfe6;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.select-txt {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.arrow-down {
|
||||
font-size: 8px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 160px;
|
||||
height: 100%;
|
||||
padding: 0 12px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.btn-query {
|
||||
background-color: #1890ff;
|
||||
border-radius: 4px;
|
||||
padding: 0 20px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-txt {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 选项卡 */
|
||||
.tab-section {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
padding: 12px 20px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tab-title {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-title {
|
||||
color: #1890ff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.active-line {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
height: 2px;
|
||||
background-color: #1890ff;
|
||||
}
|
||||
|
||||
/* 表格 */
|
||||
.table-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
background-color: #f8f9fb;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.th {
|
||||
padding: 15px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.th-txt {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.td {
|
||||
padding: 15px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.td-txt {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 列宽分配 */
|
||||
.col-order { width: 220px; justify-content: flex-start; padding-left: 20px; }
|
||||
.col-amount { width: 120px; }
|
||||
.col-type { width: 150px; }
|
||||
.col-header { width: 120px; }
|
||||
.col-time { width: 180px; }
|
||||
.col-status-inv { width: 120px; }
|
||||
.col-status-order { width: 120px; }
|
||||
.col-ops { flex: 1; min-width: 140px; }
|
||||
|
||||
.text-left {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.red-cell {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.ops-box {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.op-link {
|
||||
font-size: 13px;
|
||||
color: #1890ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sep {
|
||||
font-size: 12px;
|
||||
color: #ebeef5;
|
||||
margin: 0 8px;
|
||||
}
|
||||
</style>
|
||||
425
pages/mall/admin/finance/recharge.uvue
Normal file
425
pages/mall/admin/finance/recharge.uvue
Normal file
@@ -0,0 +1,425 @@
|
||||
<template>
|
||||
<view class="finance-recharge">
|
||||
<!-- 头部筛选区 -->
|
||||
<view class="filter-card border-shadow">
|
||||
<view class="filter-row">
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">时间选择:</text>
|
||||
<view class="date-picker-wrap">
|
||||
<text class="calendar-icon">📅</text>
|
||||
<text class="date-placeholder">开始日期 - 结束日期</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">支付类型:</text>
|
||||
<view class="select-box">
|
||||
<text class="select-txt">全部</text>
|
||||
<text class="arrow-down">▼</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item search-wrap">
|
||||
<text class="filter-label">搜索:</text>
|
||||
<input class="search-input" placeholder="请输入用户昵称、订单号" />
|
||||
</view>
|
||||
<view class="btn-query">
|
||||
<text class="btn-txt">查询</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 统计网格 -->
|
||||
<view class="stats-grid">
|
||||
<view class="stat-card border-shadow" v-for="(item, index) in stats" :key="index">
|
||||
<view class="icon-circle" :class="item.colorClass">
|
||||
<text class="stat-icon">{{ item.icon }}</text>
|
||||
</view>
|
||||
<view class="stat-info">
|
||||
<text class="stat-value">{{ item.value }}</text>
|
||||
<text class="stat-label">{{ item.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作区域 -->
|
||||
<view class="action-section">
|
||||
<view class="btn-export">
|
||||
<text class="btn-export-txt">导出</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据表格 (Flex 模拟) -->
|
||||
<view class="table-container border-shadow">
|
||||
<view class="table-header">
|
||||
<view class="th col-id"><text class="th-txt">ID</text></view>
|
||||
<view class="th col-avatar"><text class="th-txt">头像</text></view>
|
||||
<view class="th col-nickname"><text class="th-txt">用户昵称</text></view>
|
||||
<view class="th col-orderno"><text class="th-txt">订单号</text></view>
|
||||
<view class="th col-amount"><text class="th-txt">支付金额</text></view>
|
||||
<view class="th col-paid"><text class="th-txt">是否支付</text></view>
|
||||
<view class="th col-type"><text class="th-txt">充值类型</text></view>
|
||||
<view class="th col-time"><text class="th-txt">支付时间</text></view>
|
||||
<view class="th col-ops"><text class="th-txt">操作</text></view>
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="item in tableData" :key="item.id">
|
||||
<view class="td col-id"><text class="td-txt">{{ item.id }}</text></view>
|
||||
<view class="td col-avatar">
|
||||
<view class="avatar-box">
|
||||
<text class="avatar-placeholder" v-if="!item.hasAvatar">🖼️</text>
|
||||
<view class="avatar-img-mock" v-else></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="td col-nickname"><text class="td-txt">{{ item.nickname }}</text></view>
|
||||
<view class="td col-orderno"><text class="td-txt">{{ item.orderNo }}</text></view>
|
||||
<view class="td col-amount"><text class="td-txt">{{ item.amount }}</text></view>
|
||||
<view class="td col-paid"><text class="td-txt">{{ item.isPaid }}</text></view>
|
||||
<view class="td col-type"><text class="td-txt">{{ item.type }}</text></view>
|
||||
<view class="td col-time"><text class="td-txt">{{ item.time }}</text></view>
|
||||
<view class="td col-ops">
|
||||
<text class="op-link">删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
const stats = ref([
|
||||
{ label: '充值总金额', value: '446747490.72', icon: '¥', colorClass: 'blue' },
|
||||
{ label: '充值退款金额', value: '1.19', icon: '¥', colorClass: 'orange' },
|
||||
{ label: '支付宝充值金额', value: '78812.24', icon: '支', colorClass: 'green' },
|
||||
{ label: '微信充值金额', value: '8518075.11', icon: '✔', colorClass: 'pink' }
|
||||
])
|
||||
|
||||
interface RechargeRecord {
|
||||
id: number
|
||||
hasAvatar: boolean
|
||||
nickname: string
|
||||
orderNo: string
|
||||
amount: string
|
||||
isPaid: string
|
||||
type: string
|
||||
time: string
|
||||
}
|
||||
|
||||
const tableData = ref<RechargeRecord[]>([
|
||||
{
|
||||
id: 4522,
|
||||
hasAvatar: true,
|
||||
nickname: 'TTA NW',
|
||||
orderNo: 'cz540603403592531968',
|
||||
amount: '10.00',
|
||||
isPaid: '未支付',
|
||||
type: '微信充值',
|
||||
time: '暂无'
|
||||
},
|
||||
{
|
||||
id: 4521,
|
||||
hasAvatar: true,
|
||||
nickname: 'TTA NW',
|
||||
orderNo: 'cz540592008763277312',
|
||||
amount: '3343.00',
|
||||
isPaid: '未支付',
|
||||
type: '微信充值',
|
||||
time: '暂无'
|
||||
},
|
||||
{
|
||||
id: 4520,
|
||||
hasAvatar: true,
|
||||
nickname: '绯',
|
||||
orderNo: 'cz538561368400330752',
|
||||
amount: '500.00',
|
||||
isPaid: '未支付',
|
||||
type: '支付宝充值',
|
||||
time: '暂无'
|
||||
},
|
||||
{
|
||||
id: 4519,
|
||||
hasAvatar: false,
|
||||
nickname: '六六狗',
|
||||
orderNo: 'cz538368229429477376',
|
||||
amount: '50.00',
|
||||
isPaid: '未支付',
|
||||
type: '微信充值',
|
||||
time: '暂无'
|
||||
},
|
||||
{
|
||||
id: 4518,
|
||||
hasAvatar: false,
|
||||
nickname: 'aabbc',
|
||||
orderNo: 'cz538165303901683712',
|
||||
amount: '10.00',
|
||||
isPaid: '未支付',
|
||||
type: '其他充值',
|
||||
time: '暂无'
|
||||
}
|
||||
])
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.finance-recharge {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.border-shadow {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* 筛选卡片 */
|
||||
.filter-card {
|
||||
padding: 20px 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-right: 28px;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin-right: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.date-picker-wrap {
|
||||
width: 220px;
|
||||
height: 32px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.calendar-icon {
|
||||
font-size: 12px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.date-placeholder {
|
||||
font-size: 13px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.select-box {
|
||||
width: 160px;
|
||||
height: 32px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.select-txt {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.arrow-down {
|
||||
font-size: 8px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.search-wrap {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
height: 32px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
padding: 0 12px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.btn-query {
|
||||
background-color: #1890ff;
|
||||
border-radius: 4px;
|
||||
height: 32px;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.btn-txt {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 统计网格 */
|
||||
.stats-grid {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
width: 24%;
|
||||
padding: 24px 20px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.icon-circle {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 26px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.blue { background-color: #e6f7ff; color: #1890ff; }
|
||||
.orange { background-color: #fff7e1; color: #fa8c16; }
|
||||
.green { background-color: #f6ffed; color: #52c41a; }
|
||||
.pink { background-color: #fff0f6; color: #eb2f96; }
|
||||
|
||||
.stat-icon { font-size: 22px; font-weight: bold; }
|
||||
|
||||
.stat-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
color: #303133;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
/* 操作区 */
|
||||
.action-section {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.btn-export {
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-export-txt {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 表格 */
|
||||
.table-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
background-color: #f8f9fb;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.th {
|
||||
padding: 12px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.th-txt {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.td {
|
||||
padding: 12px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.td-txt {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.col-id { width: 80px; }
|
||||
.col-avatar { width: 80px; }
|
||||
.col-nickname { width: 150px; }
|
||||
.col-orderno { width: 220px; }
|
||||
.col-amount { width: 120px; }
|
||||
.col-paid { width: 120px; }
|
||||
.col-type { width: 150px; }
|
||||
.col-time { width: 150px; }
|
||||
.col-ops { flex: 1; min-width: 100px; }
|
||||
|
||||
.avatar-box {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: #f0f2f5;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.avatar-img-mock {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.avatar-placeholder {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.op-link {
|
||||
font-size: 13px;
|
||||
color: #1890ff;
|
||||
}
|
||||
</style>
|
||||
836
pages/mall/admin/finance/transaction_stats.uvue
Normal file
836
pages/mall/admin/finance/transaction_stats.uvue
Normal 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: 16px;
|
||||
background-color: #f0f2f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 头部筛选 */
|
||||
.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>
|
||||
469
pages/mall/admin/finance/withdrawal.uvue
Normal file
469
pages/mall/admin/finance/withdrawal.uvue
Normal file
@@ -0,0 +1,469 @@
|
||||
<template>
|
||||
<view class="finance-withdrawal">
|
||||
<!-- 头部筛选区 -->
|
||||
<view class="filter-card">
|
||||
<view class="filter-row">
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">时间选择:</text>
|
||||
<uni-datetime-picker v-model="timeRange" type="daterange" class="dt-picker" />
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">提现状态:</text>
|
||||
<uni-data-select v-model="statusValue" :localdata="statusOptions" class="data-select" />
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<text class="filter-label">提现方式:</text>
|
||||
<uni-data-select v-model="methodValue" :localdata="methodOptions" class="data-select" />
|
||||
</view>
|
||||
<view class="filter-item search-wrap">
|
||||
<text class="filter-label">搜索:</text>
|
||||
<uni-easyinput v-model="searchKeyword" placeholder="微信昵称/姓名/支付宝账号/银行卡号" class="search-input" />
|
||||
</view>
|
||||
<button class="btn-query" @click="handleQuery">查询</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 统计指标网格 -->
|
||||
<view class="stats-grid">
|
||||
<view class="stat-card" v-for="(item, index) in stats" :key="index">
|
||||
<view class="icon-circle" :class="item.colorClass">
|
||||
<text class="stat-icon">{{ item.icon }}</text>
|
||||
</view>
|
||||
<view class="stat-info">
|
||||
<text class="stat-value">{{ item.value }}</text>
|
||||
<text class="stat-label">{{ item.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮区 -->
|
||||
<view class="action-section">
|
||||
<view class="btn-record">
|
||||
<text class="btn-record-txt">佣金记录</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据表格 (使用 Flex 模拟以确保兼容性和精度) -->
|
||||
<view class="table-container">
|
||||
<view class="table-header">
|
||||
<view class="th col-id"><text class="th-txt">ID</text></view>
|
||||
<view class="th col-user"><text class="th-txt">用户信息</text></view>
|
||||
<view class="th col-amount"><text class="th-txt">提现金额</text></view>
|
||||
<view class="th col-fee"><text class="th-txt">提现手续费</text></view>
|
||||
<view class="th col-net"><text class="th-txt">到账金额</text></view>
|
||||
<view class="th col-method"><text class="th-txt">提现方式</text></view>
|
||||
<view class="th col-qr"><text class="th-txt">收款码</text></view>
|
||||
<view class="th col-time"><text class="th-txt">申请时间</text></view>
|
||||
<view class="th col-remark"><text class="th-txt">备注</text></view>
|
||||
<view class="th col-status"><text class="th-txt">审核状态</text></view>
|
||||
<view class="th col-ops"><text class="th-txt">操作</text></view>
|
||||
</view>
|
||||
|
||||
<view class="table-body">
|
||||
<view class="table-row" v-for="(item, index) in tableData" :key="item.id">
|
||||
<view class="td col-id"><text class="td-txt">{{ item.id }}</text></view>
|
||||
<view class="td col-user">
|
||||
<view class="user-info-box">
|
||||
<view class="avatar-box">
|
||||
<text class="avatar-placeholder">U</text>
|
||||
</view>
|
||||
<view class="user-detail">
|
||||
<text class="user-nickname">{{ item.nickname }}</text>
|
||||
<text class="user-id">用户id:{{ item.userId }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="td col-amount"><text class="td-txt">{{ item.amount }}</text></view>
|
||||
<view class="td col-fee"><text class="td-txt">{{ item.fee }}</text></view>
|
||||
<view class="td col-net"><text class="td-txt green-txt">{{ item.netAmount }}</text></view>
|
||||
<view class="td col-method">
|
||||
<view class="method-box">
|
||||
<text class="m-line">姓名:{{ item.name }}</text>
|
||||
<text class="m-line">{{ item.type }}:{{ item.account }}</text>
|
||||
<text v-if="item.bank" class="m-line">银行开户地址:{{ item.bank }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="td col-qr">
|
||||
<view class="qr-box" v-if="item.id === 57">
|
||||
<text class="qr-icon-txt">■</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="td col-time"><text class="td-txt">{{ item.time }}</text></view>
|
||||
<view class="td col-remark"><text class="td-txt">{{ item.remark || '' }}</text></view>
|
||||
<view class="td col-status"><text class="td-txt">申请中</text></view>
|
||||
<view class="td col-ops">
|
||||
<view class="ops-box">
|
||||
<text class="op-btn blue">编辑</text>
|
||||
<text class="op-sep">|</text>
|
||||
<text class="op-btn blue">通过</text>
|
||||
<text class="op-sep">|</text>
|
||||
<text class="op-btn blue">驳回</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
const timeRange = ref([])
|
||||
const statusValue = ref('all')
|
||||
const methodValue = ref('all')
|
||||
const searchKeyword = ref('')
|
||||
|
||||
const statusOptions = ref([
|
||||
{ value: 'all', text: '全部' },
|
||||
{ value: '0', text: '待审核' },
|
||||
{ value: '1', text: '已通过' },
|
||||
{ value: '-1', text: '已驳回' }
|
||||
])
|
||||
|
||||
const methodOptions = ref([
|
||||
{ value: 'all', text: '全部' },
|
||||
{ value: 'alipay', text: '支付宝' },
|
||||
{ value: 'bank', text: '银行卡' },
|
||||
{ value: 'weixin', text: '微信' }
|
||||
])
|
||||
|
||||
const stats = ref([
|
||||
{ label: '佣金总金额', value: '676809.25', icon: '$', colorClass: 'blue' },
|
||||
{ label: '待提现金额', value: '71', icon: '¥', colorClass: 'orange' },
|
||||
{ label: '已提现金额', value: '68879.25', icon: '$', colorClass: 'green' },
|
||||
{ label: '未提现金额', value: '607930.00', icon: '¥', colorClass: 'pink' }
|
||||
])
|
||||
|
||||
const tableData = ref([
|
||||
{
|
||||
id: 57,
|
||||
nickname: '用户昵称: 177****766',
|
||||
userId: '58837',
|
||||
amount: '20.00',
|
||||
fee: '0.00',
|
||||
netAmount: '20.00',
|
||||
name: '接口',
|
||||
type: '支付宝',
|
||||
account: '1195953899',
|
||||
time: '2025-10-24 16:04',
|
||||
remark: ''
|
||||
},
|
||||
{
|
||||
id: 56,
|
||||
nickname: '用户昵称: 测试员的',
|
||||
userId: '20695',
|
||||
amount: '1.00',
|
||||
fee: '0.00',
|
||||
netAmount: '1.00',
|
||||
name: '123',
|
||||
type: '银行卡',
|
||||
account: '4001231221',
|
||||
bank: '中国银行',
|
||||
time: '2025-07-04 15:11',
|
||||
remark: ''
|
||||
}
|
||||
])
|
||||
|
||||
const handleQuery = () => {
|
||||
console.log('Query with:', statusValue.value, methodValue.value, searchKeyword.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.finance-withdrawal {
|
||||
padding: 20px;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 筛选样式更新 */
|
||||
.filter-card {
|
||||
background-color: #fff;
|
||||
padding: 24px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-right: 24px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
margin-right: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dt-picker {
|
||||
width: 260px;
|
||||
}
|
||||
|
||||
.data-select {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.search-wrap {
|
||||
flex: 1;
|
||||
min-width: 320px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.btn-query {
|
||||
background-color: #1890ff;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
padding: 0 24px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* 统计卡片样式 */
|
||||
.stats-grid {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
width: 24%;
|
||||
background-color: #fff;
|
||||
padding: 24px 20px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.icon-circle {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 26px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.blue { background-color: #e6f7ff; color: #1890ff; }
|
||||
.orange { background-color: #fff7e1; color: #fa8c16; }
|
||||
.green { background-color: #f6ffed; color: #52c41a; }
|
||||
.pink { background-color: #fff0f6; color: #eb2f96; }
|
||||
|
||||
.stat-icon { font-size: 24px; font-weight: bold; }
|
||||
|
||||
.stat-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
color: #303133;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
/* 操作区域 */
|
||||
.action-section {
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.btn-record {
|
||||
background-color: #1890ff;
|
||||
border-radius: 4px;
|
||||
padding: 6px 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-record-txt {
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* 表格容器样式 (Flex 模拟) */
|
||||
.table-container {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
background-color: #f8f9fb;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.th {
|
||||
padding: 12px 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.th-txt {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.table-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.td {
|
||||
padding: 12px 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.td-txt {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 列宽定义 (与截图匹配) */
|
||||
.col-id { width: 60px; }
|
||||
.col-user { width: 180px; justify-content: flex-start; }
|
||||
.col-amount { width: 100px; }
|
||||
.col-fee { width: 100px; }
|
||||
.col-net { width: 100px; }
|
||||
.col-method { flex: 1; min-width: 220px; justify-content: flex-start; }
|
||||
.col-qr { width: 80px; }
|
||||
.col-time { width: 150px; }
|
||||
.col-remark { width: 80px; }
|
||||
.col-status { width: 100px; }
|
||||
.col-ops { width: 160px; }
|
||||
|
||||
/* 用户信息单元格 */
|
||||
.user-info-box {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar-box {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 16px;
|
||||
background-color: #f0f2f5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.avatar-placeholder {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.user-detail {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.user-nickname {
|
||||
font-size: 13px;
|
||||
color: #303133;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.user-id {
|
||||
font-size: 11px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 提现方式单元格 */
|
||||
.method-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.m-line {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.green-txt {
|
||||
color: #52c41a;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 收款码 */
|
||||
.qr-box {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.qr-icon-txt {
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* 操作项 */
|
||||
.ops-box {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.op-btn {
|
||||
font-size: 13px;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.blue { color: #1890ff; }
|
||||
|
||||
.op-sep {
|
||||
color: #ebeef5;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user