卡券订单

This commit is contained in:
邱贞招 2025-03-27 14:26:06 +08:00
parent 7ff0f81a62
commit ccd3551f43
9 changed files with 747 additions and 156 deletions

View File

@ -6,7 +6,8 @@ export function login(username, password, code, uuid) {
username, username,
password, password,
code, code,
uuid uuid,
platform: '2'
} }
return request({ return request({
url: '/login', url: '/login',

64
src/api/system/app.js Normal file
View File

@ -0,0 +1,64 @@
import request from '@/utils/request'
// 查询APP信息列表
export function listApp(query) {
return request({
url: '/ss/app/list',
method: 'get',
params: query
})
}
// 所有APP列表
export function listAllApp() {
return request({
url: '/ss/app/all',
method: 'get'
})
}
// 查询APP信息列表
export function listAppByIds(ids) {
return request({
url: '/ss/app/listByIds',
method: 'post',
headers: {
repeatSubmit: true,
},
data: ids
})
}
// 查询APP信息详细
export function getApp(id) {
return request({
url: '/ss/app/' + id,
method: 'get'
})
}
// 新增APP信息
export function addApp(data) {
return request({
url: '/ss/app',
method: 'post',
data: data
})
}
// 修改APP信息
export function updateApp(data) {
return request({
url: '/ss/app',
method: 'put',
data: data
})
}
// 删除APP信息
export function delApp(id) {
return request({
url: '/ss/app/' + id,
method: 'delete'
})
}

View File

@ -34,7 +34,10 @@ export function addChannel(data) {
return request({ return request({
url: '/system/channel', url: '/system/channel',
method: 'post', method: 'post',
data: data data: {
...data,
appIds: Array.isArray(data.appIds) ? data.appIds : []
}
}) })
} }
@ -43,7 +46,10 @@ export function updateChannel(data) {
return request({ return request({
url: '/system/channel', url: '/system/channel',
method: 'put', method: 'put',
data: data data: {
...data,
appIds: Array.isArray(data.appIds) ? data.appIds : []
}
}) })
} }
@ -54,3 +60,12 @@ export function delChannel(channelId) {
method: 'delete' method: 'delete'
}) })
} }
// 导出充值渠道
export function exportChannel(query) {
return request({
url: '/system/channel/export',
method: 'get',
params: query
})
}

View File

@ -9,6 +9,11 @@ export const views = {
withdraw: 'withdraw', // 提现 withdraw: 'withdraw', // 提现
recharge: 'recharge', // 充值订单 recharge: 'recharge', // 充值订单
} }
// 应用类型
export const AppType = {
WECHAT: "1", // 微信
ALI_PAY: "2", // 支付宝
}
// 收款账户类型 // 收款账户类型
export const AccountType = { export const AccountType = {

View File

@ -0,0 +1,369 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="应用名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入应用名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="应用类型" prop="type">
<el-select v-model="queryParams.type" placeholder="请选择应用类型" style="width: 100%">
<el-option v-for="item of dict.type.app_type" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['ss:app:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['ss:app:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['ss:app:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['ss:app:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="appList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="onSortChange">
<el-table-column type="selection" width="55" align="center" />
<template v-for="column of showColumns">
<el-table-column
:key="column.key"
:label="column.label"
:prop="column.key"
:align="column.align"
:min-width="column.minWidth"
:sort-orders="orderSorts"
:sortable="column.sortable"
:show-overflow-tooltip="column.overflow"
:width="column.width"
>
<template slot-scope="d">
<template v-if="column.key === 'id'">
{{d.row[column.key]}}
</template>
<template v-else-if="column.key === 'type'">
<dict-tag :options="dict.type.app_type" :value="d.row[column.key]"/>
</template>
<template v-else>
{{d.row[column.key]}}
</template>
</template>
</el-table-column>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['ss:app:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['ss:app:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改APP信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="6em">
<el-row>
<form-col :span="span" label="应用名称" prop="name">
<el-input v-model="form.name" placeholder="请输入应用名称" />
</form-col>
<form-col :span="span" label="应用类型" prop="type">
<el-select v-model="form.type" placeholder="请选择应用类型" style="width: 100%">
<el-option v-for="item of dict.type.app_type" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
</form-col>
<!-- 微信配置 -->
<template v-if="form.type === AppType.WECHAT">
<form-col :span="span" label="应用ID" prop="config.appId">
<el-input v-model="form.config.appId" placeholder="请输入应用ID" />
</form-col>
<form-col :span="span" label="应用秘钥" prop="config.appSecret">
<el-input v-model="form.config.appSecret" placeholder="请输入应用秘钥" />
</form-col>
</template>
<!-- 支付宝配置 -->
<template v-else-if="form.type === AppType.ALI_PAY">
<form-col :span="span" label="应用ID" prop="config.appId">
<el-input v-model="form.config.appId" placeholder="请输入应用ID" />
</form-col>
<form-col :span="span" label="应用私钥" prop="config.privateKey">
<el-input v-model="form.config.privateKey" placeholder="请输入应用私钥" type="textarea" />
</form-col>
<form-col :span="span" label="应用公钥证书地址" prop="config.appCertPath" label-width="9em">
<el-input v-model="form.config.appCertPath" placeholder="请输入应用公钥证书地址" />
</form-col>
<form-col :span="span" label="支付宝公钥证书地址" prop="config.alipayCertPath" label-width="10em">
<el-input v-model="form.config.alipayCertPath" placeholder="请输入支付宝公钥证书地址" />
</form-col>
<form-col :span="span" label="支付宝根证书地址" prop="config.alipayRootCertPath" label-width="9em">
<el-input v-model="form.config.alipayRootCertPath" placeholder="请输入支付宝根证书地址" />
</form-col>
<form-col :span="span" label="AES秘钥" prop="config.aesPrivateKey">
<el-input v-model="form.config.aesPrivateKey" placeholder="请输入AES秘钥" />
</form-col>
</template>
<form-col :span="span" label="SN前缀" prop="snPrefix">
<el-input v-model="form.snPrefix" placeholder="请输入SN前缀" />
</form-col>
<form-col :span="span" label="合伙人前缀" prop="staffPrefix">
<el-input v-model="form.staffPrefix" placeholder="请输入合伙人前缀" />
</form-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listApp, getApp, delApp, addApp, updateApp } from "@/api/system/app";
import { $showColumns } from '@/utils/mixins';
import { AppType } from '@/utils/constants';
//
const defaultSort = {
prop: "createTime",
order: "descending"
}
export default {
name: "App",
mixins: [$showColumns],
dicts: ['app_type'],
data() {
return {
span: 24,
AppType,
//
columns: [
{key: 'id', visible: true, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'name', visible: true, label: '应用名称', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'type', visible: true, label: '应用类型', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
// {key: 'snPrefix', visible: true, label: 'SN', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
// {key: 'staffPrefix', visible: true, label: '', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'createTime', visible: true, label: '创建时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
],
//
orderSorts: ['ascending', 'descending', null],
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
// APP
appList: [],
//
title: "",
//
open: false,
defaultSort,
//
queryParams: {
pageNum: 1,
pageSize: 20,
orderByColumn: defaultSort.prop,
isAsc: defaultSort.order,
id: null,
name: null,
type: null,
appId: null,
},
//
form: {},
//
rules: {
name: [
{ required: true, message: "应用名称不能为空", trigger: "blur" }
],
type: [
{ required: true, message: "应用类型不能为空", trigger: "blur" }
]
}
};
},
created() {
this.getList();
},
methods: {
/** 当排序按钮被点击时触发 **/
onSortChange(column) {
if (column.order == null) {
this.queryParams.orderByColumn = defaultSort.prop;
this.queryParams.isAsc = defaultSort.order;
} else {
this.queryParams.orderByColumn = column.prop;
this.queryParams.isAsc = column.order;
}
this.getList();
},
/** 查询APP信息列表 */
getList() {
this.loading = true;
listApp(this.queryParams).then(response => {
this.appList = response.rows;
this.total = response.total;
this.loading = false;
});
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
id: null,
name: null,
type: null,
config: {},
createTime: null
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加APP信息";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.id || this.ids
getApp(id).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改APP信息";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateApp(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addApp(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除APP信息编号为"' + ids + '"的数据项?').then(function() {
return delApp(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download('ss/app/export', {
...this.queryParams
}, `app_${new Date().getTime()}.xlsx`)
}
}
};
</script>

View File

@ -110,6 +110,9 @@
<template #suffix>%</template> <template #suffix>%</template>
</el-input> </el-input>
</form-col> </form-col>
<form-col :span="24" label="绑定APP" prop="appIds">
<app-input v-model="form.appIds" :multiple="true"/>
</form-col>
<h2 style="font-weight: 700;font-size: 18px">相关配置</h2> <h2 style="font-weight: 700;font-size: 18px">相关配置</h2>
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
@ -159,6 +162,7 @@
<script> <script>
import { listChannel, getChannel, delChannel, addChannel, updateChannel } from "@/api/system/channel"; import { listChannel, getChannel, delChannel, addChannel, updateChannel } from "@/api/system/channel";
import { $showColumns,$serviceType, $withdrawServiceType } from '@/utils/mixins' import { $showColumns,$serviceType, $withdrawServiceType } from '@/utils/mixins'
import AppInput from '@/components/Business/App/AppInput'
// //
const defaultSort = { const defaultSort = {
@ -167,6 +171,9 @@ const defaultSort = {
} }
export default { export default {
name: "Channel", name: "Channel",
components: {
AppInput
},
mixins: [$showColumns, $serviceType, $withdrawServiceType], mixins: [$showColumns, $serviceType, $withdrawServiceType],
dicts: ['withdraw_service_type', 'service_type','ss_channel_type'], dicts: ['withdraw_service_type', 'service_type','ss_channel_type'],
data() { data() {
@ -213,7 +220,20 @@ export default {
costRate: null costRate: null
}, },
// //
form: {}, form: {
channelId: null,
name: null,
enabled: null,
serviceRate: null,
costRate: null,
appIds: [],
merchantId: null,
apiV3Key: null,
notifyUrl: null,
privateKeyPath: null,
merchantSerialNumber: null,
refundNotifyUrl: null
},
// //
rules: { rules: {
name: [ name: [
@ -225,6 +245,9 @@ export default {
costRate: [ costRate: [
{required: true, type: 'number', message: '成本不能为空', target: 'blur'} {required: true, type: 'number', message: '成本不能为空', target: 'blur'}
], ],
appIds: [
{required: true, type: 'array', message: '请选择绑定的APP', trigger: 'change'}
]
} }
}; };
}, },
@ -292,7 +315,14 @@ export default {
name: null, name: null,
enabled: null, enabled: null,
serviceRate: null, serviceRate: null,
costRate: null costRate: null,
appIds: [],
merchantId: null,
apiV3Key: null,
notifyUrl: null,
privateKeyPath: null,
merchantSerialNumber: null,
refundNotifyUrl: null
}; };
this.resetForm("form"); this.resetForm("form");
}, },

View File

@ -176,6 +176,7 @@
>详情</el-button> >详情</el-button>
<el-button <el-button
size="mini" size="mini"
v-if="scope.row.status === '4' || scope.row.status === '8'"
type="text" type="text"
icon="el-icon-card" icon="el-icon-card"
@click="handleRefund(scope.row)" @click="handleRefund(scope.row)"

View File

@ -10,6 +10,7 @@
</div> </div>
<div class="operation-buttons"> <div class="operation-buttons">
<el-button <el-button
v-if="order.status === '4' || order.status === '8'"
type="primary" type="primary"
icon="el-icon-card" icon="el-icon-card"
size="small" size="small"

View File

@ -32,10 +32,10 @@
<div>用户详情</div> <div>用户详情</div>
</el-row> </el-row>
<el-row type="flex" justify="end" > <el-row type="flex" justify="end" >
<!-- <el-button v-if="detail.userType === '01'" type="text" icon="el-icon-plus" size="mini" @click="handleAddAccount"--> <!-- <el-button v-if="detail.userType === '01'" type="text" icon="el-icon-plus" size="mini" @click="handleAddAccount"
<!-- v-hasPermi="['system:smUser:edit']">加账</el-button>--> v-hasPermi="['system:smUser:edit']">加账</el-button>-->
<!-- <el-button v-if="detail.userType === '01' || detail.userType === '05'" type="text" icon="el-icon-minus" size="mini" @click="handleReduceAccount"--> <!-- <el-button v-if="detail.userType === '01' || detail.userType === '05'" type="text" icon="el-icon-minus" size="mini" @click="handleReduceAccount"
<!-- v-hasPermi="['system:smUser:edit']">减账</el-button>--> v-hasPermi="['system:smUser:edit']">减账</el-button>-->
<el-button v-if="detail.userType !== '00'" type="text" icon="el-icon-setting" size="mini" @click="handleUpdateRisk" <el-button v-if="detail.userType !== '00'" type="text" icon="el-icon-setting" size="mini" @click="handleUpdateRisk"
v-hasPermi="['system:smUser:edit']">配置</el-button> v-hasPermi="['system:smUser:edit']">配置</el-button>
</el-row> </el-row>
@ -96,8 +96,11 @@
@change="handleDateRangeChange" /> @change="handleDateRangeChange" />
</div> </div>
<div class="chart-container"> <div class="chart-container">
<div v-if="dailyReportData && dailyReportData.length > 0" ref="dailyChart" style="width: 100%; height: 300px"></div> <div v-if="detail.inComeList && detail.inComeList.length > 0"
<el-empty v-else description="暂无数据" image-size="100"> ref="dailyChart"
style="width: 100%; height: 300px">
</div>
<el-empty v-else :image-size="100" description="暂无数据">
<template #image> <template #image>
<el-icon :size="50"><i class="el-icon-data-line"></i></el-icon> <el-icon :size="50"><i class="el-icon-data-line"></i></el-icon>
</template> </template>
@ -110,12 +113,12 @@
<el-tab-pane label="月报表" name="monthly"> <el-tab-pane label="月报表" name="monthly">
<div class="report-container"> <div class="report-container">
<div class="filter-section"> <div class="filter-section">
<el-date-picker v-model="selectedMonth" type="month" placeholder="选择月份" value-format="yyyy-MM" <el-date-picker v-model="selectedYear" type="year" placeholder="选择年份" value-format="yyyy"
@change="loadMonthlyReport" /> @change="loadMonthlyReport" />
</div> </div>
<div class="chart-container"> <div class="chart-container">
<div v-if="monthlyReportData && monthlyReportData.length > 0" ref="monthlyChart" style="width: 100%; height: 300px"></div> <div v-if="monthlyReportData && monthlyReportData.length > 0" ref="monthlyChart" style="width: 100%; height: 300px"></div>
<el-empty v-else description="暂无数据" image-size="100"> <el-empty v-else :image-size="100" description="暂无数据">
<template #image> <template #image>
<el-icon :size="50"><i class="el-icon-data-line"></i></el-icon> <el-icon :size="50"><i class="el-icon-data-line"></i></el-icon>
</template> </template>
@ -352,7 +355,7 @@ export default {
showConfigDialog: false, showConfigDialog: false,
dateRange: [], dateRange: [],
selectedMonth: '', selectedYear: '',
dailyReportData: [], dailyReportData: [],
monthlyReportData: [], monthlyReportData: [],
dailyChart: null, dailyChart: null,
@ -453,42 +456,61 @@ export default {
} }
}, },
created() { created() {
this.getDetail();
const end = new Date(); const end = new Date();
const start = new Date(); const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7); start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
this.dateRange = [this.formatDate(start), this.formatDate(end)]; this.dateRange = [this.formatDate(start), this.formatDate(end)];
this.selectedMonth = this.formatDate(new Date()).substring(0, 7); this.selectedYear = this.formatDate(new Date()).substring(0, 4);
this.getDetail();
}, },
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
this.initCharts(); this.initCharts();
// tab
if (this.reportActiveTab === 'monthly') {
this.loadMonthlyReport();
}
}); });
}, },
beforeDestroy() { beforeDestroy() {
window.removeEventListener('resize', this.handleResize);
if (this.dailyChart) { if (this.dailyChart) {
this.dailyChart.dispose(); this.dailyChart.dispose();
this.dailyChart = null;
} }
if (this.monthlyChart) { if (this.monthlyChart) {
this.monthlyChart.dispose(); this.monthlyChart.dispose();
this.monthlyChart = null;
} }
window.removeEventListener('resize', this.handleResize);
}, },
methods: { methods: {
initCharts() { initCharts() {
this.$nextTick(() => { console.log('开始初始化图表');
console.log('当前激活的tab:', this.reportActiveTab);
// tab // tab
if (this.reportActiveTab === 'daily' && this.$refs.dailyChart) { if (this.reportActiveTab === 'daily' && this.$refs.dailyChart) {
console.log('初始化日报表图表');
if (this.dailyChart) {
this.dailyChart.dispose();
this.dailyChart = null;
}
this.dailyChart = echarts.init(this.$refs.dailyChart); this.dailyChart = echarts.init(this.$refs.dailyChart);
this.loadDailyReport(); this.loadDailyReport();
} else if (this.reportActiveTab === 'monthly' && this.$refs.monthlyChart) { } else if (this.reportActiveTab === 'monthly' && this.$refs.monthlyChart) {
console.log('初始化月报表图表');
if (this.monthlyChart) {
this.monthlyChart.dispose();
this.monthlyChart = null;
}
this.monthlyChart = echarts.init(this.$refs.monthlyChart); this.monthlyChart = echarts.init(this.$refs.monthlyChart);
this.loadMonthlyReport(); this.loadMonthlyReport();
} else {
console.log('图表容器不存在或tab未激活');
} }
// //
window.addEventListener('resize', this.handleResize); window.addEventListener('resize', this.handleResize);
});
}, },
handleResize() { handleResize() {
@ -501,25 +523,32 @@ export default {
}, },
handleReportTabClick(tab) { handleReportTabClick(tab) {
console.log('切换报表tab:', tab.name);
// //
this.$nextTick(() => { this.$nextTick(() => {
if (tab.name === 'daily') { if (tab.name === 'daily') {
// //
if (this.dailyChart) { if (this.dailyChart) {
this.dailyChart.dispose(); this.dailyChart.dispose();
this.dailyChart = null;
} }
// // DOM
if (this.$refs.dailyChart) {
this.dailyChart = echarts.init(this.$refs.dailyChart); this.dailyChart = echarts.init(this.$refs.dailyChart);
this.loadDailyReport(); this.loadDailyReport();
}
} else if (tab.name === 'monthly') { } else if (tab.name === 'monthly') {
// //
if (this.monthlyChart) { if (this.monthlyChart) {
this.monthlyChart.dispose(); this.monthlyChart.dispose();
this.monthlyChart = null;
} }
// // DOM
if (this.$refs.monthlyChart) {
this.monthlyChart = echarts.init(this.$refs.monthlyChart); this.monthlyChart = echarts.init(this.$refs.monthlyChart);
this.loadMonthlyReport(); this.loadMonthlyReport();
} }
}
}); });
}, },
@ -550,9 +579,16 @@ export default {
getUser(this.$route.params.userId, params).then(response => { getUser(this.$route.params.userId, params).then(response => {
this.detail = response.data; this.detail = response.data;
this.detail.serviceFeeProportion = this.detail.serviceFeeProportion * 100; this.detail.serviceFeeProportion = this.detail.serviceFeeProportion * 100;
console.log('获取到的用户详情数据:', this.detail);
console.log('月报表数据:', this.detail.monthlyList);
// //
this.$nextTick(() => { this.$nextTick(() => {
this.initDailyChart(); this.initDailyChart();
// tab,
if (this.reportActiveTab === 'monthly') {
this.loadMonthlyReport();
}
}); });
}).finally(() => { }).finally(() => {
this.loading = false; this.loading = false;
@ -668,28 +704,51 @@ export default {
loadDailyReport() { loadDailyReport() {
if (!this.dateRange) return; if (!this.dateRange) return;
//
const [startDate, endDate] = this.dateRange; const [startDate, endDate] = this.dateRange;
// this.loading = true;
getUser(this.$route.params.userId, { getUser(this.$route.params.userId, {
startDate, startDate,
endDate endDate
}).then(response => { }).then(response => {
this.detail = response.data; this.detail = response.data;
// DOM
this.$nextTick(() => { this.$nextTick(() => {
if (this.$refs.dailyChart) {
this.initDailyChart(); this.initDailyChart();
}
}); });
}).catch(error => {
console.error('加载数据失败:', error);
}).finally(() => {
this.loading = false;
}); });
}, },
initDailyChart() { initDailyChart() {
if (!this.dailyChart) { // 1. DOM
this.dailyChart = echarts.init(this.$refs.dailyChart); if (!this.$refs.dailyChart) {
console.warn('图表容器不存在');
return;
} }
// 使 API // 2.
const days = this.detail.inComeList.map(item => item.day.substring(5)); // MM-dd if (!this.detail.inComeList || !Array.isArray(this.detail.inComeList)) {
console.warn('收入数据不存在或格式不正确');
return;
}
try {
// 3.
if (this.dailyChart) {
this.dailyChart.dispose();
}
// 4.
this.dailyChart = echarts.init(this.$refs.dailyChart);
//
const days = this.detail.inComeList.map(item => item.day.substring(5));
const incomes = this.detail.inComeList.map(item => item.orderIncome); const incomes = this.detail.inComeList.map(item => item.orderIncome);
const orderNums = this.detail.inComeList.map(item => item.orderNum); const orderNums = this.detail.inComeList.map(item => item.orderNum);
@ -753,34 +812,59 @@ export default {
}; };
this.dailyChart.setOption(option); this.dailyChart.setOption(option);
} catch (error) {
console.error('初始化图表失败:', error);
}
}, },
loadMonthlyReport() { loadMonthlyReport() {
const [year, month] = this.selectedMonth.split('-'); if (!this.selectedYear) {
const daysInMonth = new Date(year, month, 0).getDate(); console.log('未选择年份,无法加载月报表');
return;
}
// console.log('开始加载月报表,年份:', this.selectedYear);
this.monthlyReportData = Array.from({ length: daysInMonth }, (_, i) => { console.log('当前月报表数据:', this.detail.monthlyList);
return {
date: `${this.selectedMonth}-${String(i + 1).padStart(2, '0')}`, // 使monthlyList
rechargeAmount: Math.floor(Math.random() * 10000), this.monthlyReportData = this.detail.monthlyList || [];
consumeAmount: Math.floor(Math.random() * 8000)
}; if (!this.monthlyReportData || this.monthlyReportData.length === 0) {
}); console.log('没有月报表数据');
return;
}
// DOM
if (!this.$refs.monthlyChart) {
console.log('月报表图表容器不存在');
return;
}
//
if (!this.monthlyChart) {
this.monthlyChart = echarts.init(this.$refs.monthlyChart);
}
// //
const option = { const option = {
title: { title: {
text: '月度统计' text: `${this.selectedYear}年度统计`
}, },
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: { axisPointer: {
type: 'line' type: 'line'
},
formatter: function(params) {
let result = params[0].axisValue + '<br/>';
params.forEach(param => {
result += param.seriesName + ': ' + param.value + (param.seriesName === '订单数量' ? '单' : '元') + '<br/>';
});
return result;
} }
}, },
legend: { legend: {
data: ['充值金额', '消费金额'] data: ['收入金额', '订单数量']
}, },
grid: { grid: {
left: '3%', left: '3%',
@ -790,14 +874,16 @@ export default {
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
boundaryGap: false, // false线 boundaryGap: false,
data: this.monthlyReportData.map((_, index) => index + 1), data: this.monthlyReportData.map(item => item.month.substring(5)), //
axisLabel: { axisLabel: {
formatter: '{value}日' rotate: 45
} }
}, },
yAxis: { yAxis: [
{
type: 'value', type: 'value',
name: '收入金额',
axisLabel: { axisLabel: {
formatter: '{value}元' formatter: '{value}元'
}, },
@ -808,27 +894,22 @@ export default {
} }
} }
}, },
{
type: 'value',
name: '订单数量',
axisLabel: {
formatter: '{value}单'
},
splitLine: {
show: false
}
}
],
series: [ series: [
{ {
name: '充值金额', name: '收入金额',
type: 'line',
symbol: 'circle', //
symbolSize: 6, //
itemStyle: {
normal: {
lineStyle: {
width: 2
}
}
},
areaStyle: {
opacity: 0.1
},
data: this.monthlyReportData.map(item => item.rechargeAmount)
},
{
name: '消费金额',
type: 'line', type: 'line',
smooth: true,
symbol: 'circle', symbol: 'circle',
symbolSize: 6, symbolSize: 6,
itemStyle: { itemStyle: {
@ -841,13 +922,37 @@ export default {
areaStyle: { areaStyle: {
opacity: 0.1 opacity: 0.1
}, },
data: this.monthlyReportData.map(item => item.consumeAmount) data: this.monthlyReportData.map(item => item.orderIncome)
},
{
name: '订单数量',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 6,
yAxisIndex: 1,
itemStyle: {
normal: {
lineStyle: {
width: 2
}
}
},
areaStyle: {
opacity: 0.1
},
data: this.monthlyReportData.map(item => item.orderNum)
} }
] ]
}; };
if (this.monthlyChart) { console.log('图表配置:', option);
try {
this.monthlyChart.setOption(option); this.monthlyChart.setOption(option);
console.log('图表更新完成');
} catch (error) {
console.error('设置图表配置失败:', error);
} }
}, },
} }