ylj20011123 2900c384eb update
2025-10-29 10:02:45 +08:00

763 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="order-settlement-analysis">
<!-- 报表标题 -->
<view class="report-header">
<text class="report-title">订单和结算数据交叉分析</text>
<view class="report-period">
<text class="period-label">分析周期</text>
<text class="period-value">{{ analysisPeriod }}</text>
</view>
</view>
<!-- 关键指标卡片 -->
<view class="metrics-row">
<view class="metric-card">
<view class="metric-icon platform-total"></view>
<text class="metric-title">平台结算总额</text>
<view class="metric-value-container">
<text class="metric-value">¥{{ formatMoney(platformSettlementTotal) }}</text>
<text class="metric-unit"></text>
</view>
</view>
<view class="metric-card">
<view class="metric-icon shop-total"></view>
<text class="metric-title">店铺结算总额</text>
<view class="metric-value-container">
<text class="metric-value">¥{{ formatMoney(shopSettlementTotal) }}</text>
<text class="metric-unit"></text>
</view>
</view>
<view class="metric-card">
<view class="metric-icon provider-total"></view>
<text class="metric-title">服务商结算总额</text>
<view class="metric-value-container">
<text class="metric-value">¥{{ formatMoney(providerSettlementTotal) }}</text>
<text class="metric-unit"></text>
</view>
</view>
</view>
<view class="metrics-row">
<view class="metric-card">
<view class="metric-icon commission-total"></view>
<text class="metric-title">平台佣金总额</text>
<view class="metric-value-container">
<text class="metric-value">¥{{ formatMoney(platformCommissionTotal) }}</text>
<text class="metric-unit"></text>
</view>
</view>
<view class="metric-card">
<view class="metric-icon settlement-count"></view>
<text class="metric-title">结算笔数</text>
<view class="metric-value-container">
<text class="metric-value">{{ formatNumber(settlementCount) }}</text>
<text class="metric-unit"></text>
</view>
</view>
<view class="metric-card">
<view class="metric-icon avg-cycle"></view>
<text class="metric-title">平均结算周期</text>
<view class="metric-value-container">
<text class="metric-value">{{ avgSettlementCycle }}</text>
<text class="metric-unit"></text>
</view>
</view>
</view>
<!-- 结算金额对比 -->
<view class="chart-card">
<view class="chart-header">
<text class="chart-title">结算金额对比分析</text>
<text class="chart-subtitle">平台店铺服务商结算金额分布</text>
</view>
<view class="chart-content">
<view class="column-chart-container">
<QiunDataCharts
type="column"
:opts="settlementCompareOpts"
:chartData="settlementCompareChartData"
:canvas2d="true"
:inScrollView="true"
canvasId="settlementCompareChart"
/>
</view>
</view>
</view>
<!-- 结算金额占比 -->
<view class="chart-card">
<view class="chart-header">
<text class="chart-title">结算金额占比分析</text>
<text class="chart-subtitle">各结算方金额占比情况</text>
</view>
<view class="chart-content">
<view class="pie-chart-container">
<QiunDataCharts
type="pie"
:opts="settlementRatioOpts"
:chartData="settlementRatioChartData"
:canvas2d="true"
:inScrollView="true"
canvasId="settlementRatioChart"
/>
<view class="pie-legend">
<view class="legend-item" v-for="(item, index) in settlementRatioList" :key="index">
<view class="legend-color" :style="{ backgroundColor: item.color }"></view>
<text class="legend-name">{{ item.name }}</text>
<text class="legend-value">{{ item.percentage }}%</text>
</view>
</view>
</view>
</view>
</view>
<!-- 佣金收入趋势 -->
<view class="chart-card">
<view class="chart-header">
<text class="chart-title">平台佣金收入趋势</text>
<text class="chart-subtitle">最近30天佣金收入变化趋势</text>
</view>
<view class="chart-content">
<view class="line-chart-container">
<QiunDataCharts
type="line"
:opts="commissionTrendOpts"
:chartData="commissionTrendChartData"
:canvas2d="true"
:inScrollView="true"
canvasId="commissionTrendChart"
/>
</view>
</view>
</view>
<!-- 结算周期分析 -->
<view class="chart-card">
<view class="chart-header">
<text class="chart-title">结算周期分析</text>
<text class="chart-subtitle">不同结算周期的分布情况</text>
</view>
<view class="chart-content">
<view class="bar-chart-container">
<QiunDataCharts
type="column"
:opts="settlementCycleOpts"
:chartData="settlementCycleChartData"
:canvas2d="true"
:inScrollView="true"
canvasId="settlementCycleChart"
/>
</view>
</view>
</view>
<!-- 详细结算数据 -->
<view class="chart-card">
<view class="chart-header">
<text class="chart-title">详细结算数据</text>
<view class="table-actions">
<text class="action-btn" @click="toggleFilter">筛选</text>
<text class="action-btn" @click="exportData">导出</text>
</view>
</view>
<view class="settlement-cards">
<view class="settlement-card" v-for="(item, index) in settlementList" :key="index">
<view class="settlement-header">
<view class="settlement-type-tag" :style="{
backgroundColor: item.type === '平台结算' ? '#576EFF' :
item.type === '店铺结算' ? '#52C41A' :
item.type === '服务商结算' ? '#FAAD14' : '#666666'
}">
{{ item.type }}
</view>
<text class="settlement-date">{{ item.date }}</text>
</view>
<view class="settlement-body">
<text class="settlement-merchant">{{ item.merchant }}</text>
<view class="settlement-metrics">
<view class="metric-item">
<text class="metric-label">结算金额</text>
<text class="metric-value">¥{{ formatMoney(item.amount) }}</text>
</view>
<view class="metric-divider"></view>
<view class="metric-item">
<text class="metric-label">结算周期</text>
<text class="metric-value">{{ item.cycle }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
export default {
components: {
QiunDataCharts
},
data() {
return {
analysisPeriod: '2024年10月',
platformSettlementTotal: 5678901,
shopSettlementTotal: 34567890,
providerSettlementTotal: 12345678,
platformCommissionTotal: 2345678,
settlementCount: 12345,
avgSettlementCycle: 7.5,
// 结算金额对比数据
settlementCompareData: {
categories: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
platformData: [123456, 156789, 187654, 234567, 198765, 156789, 123456],
shopData: [567890, 678901, 789012, 890123, 789012, 678901, 567890],
providerData: [234567, 256789, 278901, 290123, 278901, 256789, 234567]
},
// 结算金额占比数据
settlementRatioList: [
{ name: '店铺结算', amount: 34567890, percentage: 72.8, color: '#52C41A' },
{ name: '服务商结算', amount: 12345678, percentage: 26.0, color: '#FAAD14' },
{ name: '平台结算', amount: 5678901, percentage: 12.0, color: '#576EFF' }
],
// 佣金收入趋势数据
commissionTrendData: {
categories: ['1日', '5日', '10日', '15日', '20日', '25日', '30日'],
commissionData: [23456, 34567, 45678, 56789, 67890, 78901, 89012],
settlementData: [123456, 156789, 187654, 234567, 198765, 156789, 123456]
},
// 结算周期分析数据
settlementCycleData: [
{ name: 'T+1结算', count: 5678 },
{ name: 'T+3结算', count: 3456 },
{ name: 'T+7结算', count: 2345 },
{ name: 'T+15结算', count: 789 },
{ name: 'T+30结算', count: 234 },
{ name: '其他周期', count: 123 }
],
// 详细结算数据
settlementList: [
{ type: '平台结算', date: '2024-10-28', merchant: '平台总部', amount: 567891, cycle: 7 },
{ type: '店铺结算', date: '2024-10-28', merchant: '云南特产店', amount: 234567, cycle: 7 },
{ type: '服务商结算', date: '2024-10-28', merchant: '顺丰物流', amount: 123456, cycle: 7 },
{ type: '店铺结算', date: '2024-10-27', merchant: '茶叶专营店', amount: 198765, cycle: 3 },
{ type: '服务商结算', date: '2024-10-27', merchant: '支付宝', amount: 156789, cycle: 1 },
{ type: '店铺结算', date: '2024-10-26', merchant: '手工艺品店', amount: 145678, cycle: 7 }
]
}
},
computed: {
// 结算金额对比图表数据
settlementCompareChartData() {
return {
categories: this.settlementCompareData.categories,
series: [
{
name: '平台结算',
data: this.settlementCompareData.platformData
},
{
name: '店铺结算',
data: this.settlementCompareData.shopData
},
{
name: '服务商结算',
data: this.settlementCompareData.providerData
}
]
}
},
// 结算金额对比图表配置
settlementCompareOpts() {
return {
color: ['#576EFF', '#52C41A', '#FAAD14'],
padding: [15, 15, 15, 15],
dataLabel: false,
legend: {
show: false
},
xAxis: {
disableGrid: true
},
yAxis: {
gridType: 'dash',
dashLength: 2,
data: [{
min: 0
}]
},
extra: {
column: {
type: 'group',
width: 20,
activeBgColor: '#000000',
activeBgOpacity: 0.08,
linearType: 'custom',
barBorderCircle: true
}
}
}
},
// 结算金额占比图表数据
settlementRatioChartData() {
return {
series: [{
data: this.settlementRatioList.map(item => ({
name: item.name,
value: item.amount
}))
}]
}
},
// 结算金额占比图表配置
settlementRatioOpts() {
return {
color: this.settlementRatioList.map(item => item.color),
padding: [5, 5, 5, 5],
dataLabel: true,
legend: {
show: false
},
extra: {
pie: {
activeOpacity: 0.5,
activeRadius: 10,
offsetAngle: 0,
labelWidth: 15,
border: false,
borderWidth: 3,
borderColor: '#FFFFFF'
}
}
}
},
// 佣金收入趋势图表数据
commissionTrendChartData() {
return {
categories: this.commissionTrendData.categories,
series: [
{
name: '佣金收入',
data: this.commissionTrendData.commissionData
},
{
name: '结算总额(÷10)',
data: this.commissionTrendData.settlementData.map(v => v / 10)
}
]
}
},
// 佣金收入趋势图表配置
commissionTrendOpts() {
return {
color: ['#576EFF', '#52C41A'],
padding: [15, 15, 15, 15],
dataLabel: false,
legend: {
show: false
},
xAxis: {
disableGrid: true
},
yAxis: {
gridType: 'dash',
dashLength: 2,
data: [
{
min: 0
},
{
min: 0,
position: 'right'
}
]
},
extra: {
line: {
type: 'curve',
width: 2,
activeType: 'hollow'
}
}
}
},
// 结算周期分析图表数据
settlementCycleChartData() {
return {
categories: this.settlementCycleData.map(item => item.name),
series: [{
name: '结算笔数',
data: this.settlementCycleData.map(item => item.count)
}]
}
},
// 结算周期分析图表配置
settlementCycleOpts() {
return {
color: ['#FAAD14'],
padding: [15, 15, 15, 15],
dataLabel: false,
enableScroll: true,
xAxis: {
itemCount: 4,
scrollShow: true,
scrollAlign: 'right',
scrollColor: '#FAAD14',
scrollBackgroundColor: 'rgba(250, 173, 20, 0.1)',
scrollWidth: 4,
scrollHeight: 8
},
yAxis: {
gridType: 'dash',
dashLength: 2,
data: [{
min: 0
}]
},
extra: {
column: {
type: 'group',
width: 30,
activeBgColor: '#000000',
activeBgOpacity: 0.08,
linearType: 'custom',
barBorderCircle: true
}
}
}
}
},
methods: {
formatNumber(num) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
},
formatMoney(amount) {
return amount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
},
toggleFilter() {
console.log('打开筛选器')
},
exportData() {
console.log('导出数据')
}
}
}
</script>
<style scoped lang="less">
@primary-color: #667eea;
@secondary-color: #764ba2;
@success-color: #52c41a;
@warning-color: #faad14;
@error-color: #ff4d4f;
@text-primary: #333;
@text-secondary: #666;
@text-light: #999;
@bg-white: #ffffff;
@border-radius: 16rpx;
@shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
.order-settlement-analysis {
.report-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32rpx;
padding: 0 8rpx;
.report-title {
font-size: 36rpx;
font-weight: 600;
color: @text-primary;
}
.report-period {
display: flex;
align-items: center;
.period-label {
font-size: 24rpx;
color: @text-secondary;
margin-right: 8rpx;
}
.period-value {
font-size: 24rpx;
color: @primary-color;
font-weight: 500;
}
}
}
.metrics-row {
display: flex;
gap: 24rpx;
margin-bottom: 24rpx;
.metric-card {
flex: 1;
background: @bg-white;
border-radius: @border-radius;
padding: 32rpx 24rpx;
box-shadow: @shadow;
text-align: center;
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4rpx;
background: linear-gradient(90deg, @primary-color, @secondary-color);
}
.metric-icon {
width: 48rpx;
height: 48rpx;
margin: 0 auto 16rpx;
border-radius: 50%;
position: relative;
&.platform-total {
background: linear-gradient(135deg, #1890ff, #40a9ff);
&::after { content: '🏢'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
}
&.shop-total {
background: linear-gradient(135deg, #52c41a, #73d13d);
&::after { content: '🏪'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
}
&.provider-total {
background: linear-gradient(135deg, #faad14, #ffc53d);
&::after { content: '🤝'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
}
&.commission-total {
background: linear-gradient(135deg, #722ed1, #9254de);
&::after { content: '💵'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
}
&.settlement-count {
background: linear-gradient(135deg, #eb2f96, #f759ab);
&::after { content: '📝'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
}
&.avg-cycle {
background: linear-gradient(135deg, #13c2c2, #36cfc9);
&::after { content: '⏰'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
}
}
.metric-title {
font-size: 24rpx;
color: @text-secondary;
margin-bottom: 12rpx;
}
.metric-value-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 4rpx;
}
.metric-value {
font-size: 32rpx;
font-weight: 600;
color: @text-primary;
font-family: 'DINAlternate-Bold', sans-serif;
line-height: 1;
}
.metric-unit {
font-size: 20rpx;
color: @text-light;
line-height: 1;
}
}
}
.chart-card {
background: @bg-white;
border-radius: @border-radius;
padding: 24rpx;
box-shadow: @shadow;
margin-bottom: 24rpx;
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
.chart-title {
font-size: 28rpx;
font-weight: 600;
color: @text-primary;
}
.chart-subtitle {
font-size: 22rpx;
color: @text-light;
margin-top: 4rpx;
}
.table-actions {
display: flex;
gap: 16rpx;
.action-btn {
font-size: 24rpx;
color: @primary-color;
padding: 8rpx 16rpx;
border: 1rpx solid @primary-color;
border-radius: 8rpx;
}
}
}
.chart-content {
.column-chart-container,
.line-chart-container,
.bar-chart-container {
width: 100%;
}
.pie-chart-container {
display: flex;
flex-direction: column;
align-items: center;
.pie-legend {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 16rpx;
margin-top: 16rpx;
.legend-item {
display: flex;
align-items: center;
gap: 8rpx;
.legend-color {
width: 12rpx;
height: 12rpx;
border-radius: 2rpx;
}
.legend-name {
font-size: 22rpx;
color: @text-secondary;
}
.legend-value {
font-size: 22rpx;
color: @text-primary;
font-weight: 600;
}
}
}
}
}
.settlement-cards {
display: flex;
flex-direction: column;
gap: 16rpx;
.settlement-card {
background: #fafafa;
border-radius: 12rpx;
padding: 20rpx;
border: 1rpx solid #f0f0f0;
.settlement-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16rpx;
.settlement-type-tag {
padding: 4rpx 12rpx;
border-radius: 12rpx;
font-size: 20rpx;
color: white;
font-weight: 500;
}
.settlement-date {
font-size: 20rpx;
color: @text-light;
font-family: monospace;
}
}
.settlement-body {
.settlement-merchant {
font-size: 28rpx;
color: @text-primary;
font-weight: 600;
margin-bottom: 12rpx;
display: block;
}
.settlement-metrics {
display: flex;
align-items: center;
.metric-item {
flex: 1;
text-align: center;
.metric-label {
font-size: 20rpx;
color: @text-secondary;
display: block;
margin-bottom: 4rpx;
}
.metric-value {
font-size: 24rpx;
color: @text-primary;
font-weight: 600;
display: block;
}
}
.metric-divider {
width: 1rpx;
height: 40rpx;
background: #e0e0e0;
margin: 0 16rpx;
}
}
}
}
}
}
}
</style>