feat: 添加获取所有商户信息的API接口及相关模型,更新订单每日汇总请求参数以支持多选功能

This commit is contained in:
danial
2025-05-08 23:28:09 +08:00
parent 954b8780b3
commit 1b1a885f0d
9 changed files with 629 additions and 177 deletions

View File

@@ -248,10 +248,12 @@ models/kami-api-merchant-v1-merchant-deploy-record.ts
models/kami-api-merchant-v1-merchant-deploy-update-req.ts
models/kami-api-merchant-v1-merchant-hidden-config-entity.ts
models/kami-api-merchant-v1-merchant-info-record.ts
models/kami-api-merchant-v1-merchant-sample-all-list-res.ts
models/kami-api-merchant-v1-order-query-record.ts
models/kami-api-merchant-v1-order-query-req.ts
models/kami-api-merchant-v1-order-query-res.ts
models/kami-api-merchant-v1-platform-rate-record.ts
models/kami-api-merchant-v1-sample-all-list-res.ts
models/kami-api-merchant-v1-steal-create-req.ts
models/kami-api-merchant-v1-steal-delete-req.ts
models/kami-api-merchant-v1-steal-list-req.ts

View File

@@ -307,6 +307,8 @@ import type { KamiApiMerchantV1MerchantDeployListRes } from '../models';
// @ts-ignore
import type { KamiApiMerchantV1MerchantDeployUpdateReq } from '../models';
// @ts-ignore
import type { KamiApiMerchantV1MerchantSampleAllListRes } from '../models';
// @ts-ignore
import type { KamiApiMerchantV1OrderQueryRes } from '../models';
// @ts-ignore
import type { KamiApiMerchantV1StealCreateReq } from '../models';
@@ -7642,6 +7644,45 @@ export const DefaultApiAxiosParamCreator = function (
options: localVarRequestOptions
};
},
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiMerchantListSampleAllGet: async (
options: RawAxiosRequestConfig = {}
): Promise<RequestArgs> => {
const localVarPath = `/api/merchant/list/sampleAll`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = {
method: 'GET',
...baseOptions,
...options
};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions =
baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {
...localVarHeaderParameter,
...headersFromBaseOptions,
...options.headers
};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions
};
},
/**
*
* @summary
@@ -7729,26 +7770,18 @@ export const DefaultApiAxiosParamCreator = function (
/**
*
* @summary
* @param {number} current
* @param {ApiOrderInfoSummaryDailyStatsGetPageSizeEnum} pageSize
* @param {string} [roadUid]
* @param {Array<string>} [roadUid]
* @param {Array<string>} [dateRange]
* @param {Array<string>} [merchantUid]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiOrderInfoSummaryDailyStatsGet: async (
current: number,
pageSize: ApiOrderInfoSummaryDailyStatsGetPageSizeEnum,
roadUid?: string,
roadUid?: Array<string>,
dateRange?: Array<string>,
merchantUid?: Array<string>,
options: RawAxiosRequestConfig = {}
): Promise<RequestArgs> => {
// verify required parameter 'current' is not null or undefined
assertParamExists('apiOrderInfoSummaryDailyStatsGet', 'current', current);
// verify required parameter 'pageSize' is not null or undefined
assertParamExists(
'apiOrderInfoSummaryDailyStatsGet',
'pageSize',
pageSize
);
const localVarPath = `/api/orderInfo/summary/dailyStats`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@@ -7765,16 +7798,16 @@ export const DefaultApiAxiosParamCreator = function (
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
if (roadUid !== undefined) {
localVarQueryParameter['roadUid'] = roadUid;
if (roadUid) {
localVarQueryParameter['roadUid[]'] = roadUid;
}
if (current !== undefined) {
localVarQueryParameter['current'] = current;
if (dateRange) {
localVarQueryParameter['dateRange[]'] = dateRange;
}
if (pageSize !== undefined) {
localVarQueryParameter['pageSize'] = pageSize;
if (merchantUid) {
localVarQueryParameter['merchantUid[]'] = merchantUid;
}
setSearchParams(localVarUrlObj, localVarQueryParameter);
@@ -15371,6 +15404,35 @@ export const DefaultApiFp = function (configuration?: Configuration) {
configuration
)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiMerchantListSampleAllGet(
options?: RawAxiosRequestConfig
): Promise<
(
axios?: AxiosInstance,
basePath?: string
) => AxiosPromise<KamiApiMerchantV1MerchantSampleAllListRes>
> {
const localVarAxiosArgs =
await localVarAxiosParamCreator.apiMerchantListSampleAllGet(options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath =
operationServerMap['DefaultApi.apiMerchantListSampleAllGet']?.[
localVarOperationServerIndex
]?.url;
return (axios, basePath) =>
createRequestFunction(
localVarAxiosArgs,
globalAxios,
BASE_PATH,
configuration
)(axios, localVarOperationServerBasePath || basePath);
},
/**
*
* @summary
@@ -15437,16 +15499,16 @@ export const DefaultApiFp = function (configuration?: Configuration) {
/**
*
* @summary
* @param {number} current
* @param {ApiOrderInfoSummaryDailyStatsGetPageSizeEnum} pageSize
* @param {string} [roadUid]
* @param {Array<string>} [roadUid]
* @param {Array<string>} [dateRange]
* @param {Array<string>} [merchantUid]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiOrderInfoSummaryDailyStatsGet(
current: number,
pageSize: ApiOrderInfoSummaryDailyStatsGetPageSizeEnum,
roadUid?: string,
roadUid?: Array<string>,
dateRange?: Array<string>,
merchantUid?: Array<string>,
options?: RawAxiosRequestConfig
): Promise<
(
@@ -15456,9 +15518,9 @@ export const DefaultApiFp = function (configuration?: Configuration) {
> {
const localVarAxiosArgs =
await localVarAxiosParamCreator.apiOrderInfoSummaryDailyStatsGet(
current,
pageSize,
roadUid,
dateRange,
merchantUid,
options
);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
@@ -19820,6 +19882,19 @@ export const DefaultApiFactory = function (
.apiMerchantListAllGet(options)
.then(request => request(axios, basePath));
},
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiMerchantListSampleAllGet(
options?: RawAxiosRequestConfig
): AxiosPromise<KamiApiMerchantV1MerchantSampleAllListRes> {
return localVarFp
.apiMerchantListSampleAllGet(options)
.then(request => request(axios, basePath));
},
/**
*
* @summary
@@ -19856,14 +19931,14 @@ export const DefaultApiFactory = function (
* @throws {RequiredError}
*/
apiOrderInfoSummaryDailyStatsGet(
requestParameters: DefaultApiApiOrderInfoSummaryDailyStatsGetRequest,
requestParameters: DefaultApiApiOrderInfoSummaryDailyStatsGetRequest = {},
options?: RawAxiosRequestConfig
): AxiosPromise<KamiApiOrderV1OrderSummaryDailyGetListRes> {
return localVarFp
.apiOrderInfoSummaryDailyStatsGet(
requestParameters.current,
requestParameters.pageSize,
requestParameters.roadUid,
requestParameters.dateRange,
requestParameters.merchantUid,
options
)
.then(request => request(axios, basePath));
@@ -22577,6 +22652,17 @@ export interface DefaultApiInterface {
options?: RawAxiosRequestConfig
): AxiosPromise<KamiApiMerchantV1MerchantAllListRes>;
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof DefaultApiInterface
*/
apiMerchantListSampleAllGet(
options?: RawAxiosRequestConfig
): AxiosPromise<KamiApiMerchantV1MerchantSampleAllListRes>;
/**
*
* @summary
@@ -22610,7 +22696,7 @@ export interface DefaultApiInterface {
* @memberof DefaultApiInterface
*/
apiOrderInfoSummaryDailyStatsGet(
requestParameters: DefaultApiApiOrderInfoSummaryDailyStatsGetRequest,
requestParameters?: DefaultApiApiOrderInfoSummaryDailyStatsGetRequest,
options?: RawAxiosRequestConfig
): AxiosPromise<KamiApiOrderV1OrderSummaryDailyGetListRes>;
@@ -25854,25 +25940,25 @@ export interface DefaultApiApiMerchantOrderQueryGetRequest {
*/
export interface DefaultApiApiOrderInfoSummaryDailyStatsGetRequest {
/**
*
* @type {number}
*
* @type {Array<string>}
* @memberof DefaultApiApiOrderInfoSummaryDailyStatsGet
*/
readonly current: number;
/**
*
* @type {5 | 10 | 15 | 20 | 50 | 100}
* @memberof DefaultApiApiOrderInfoSummaryDailyStatsGet
*/
readonly pageSize: ApiOrderInfoSummaryDailyStatsGetPageSizeEnum;
readonly roadUid?: Array<string>;
/**
*
* @type {string}
* @type {Array<string>}
* @memberof DefaultApiApiOrderInfoSummaryDailyStatsGet
*/
readonly roadUid?: string;
readonly dateRange?: Array<string>;
/**
*
* @type {Array<string>}
* @memberof DefaultApiApiOrderInfoSummaryDailyStatsGet
*/
readonly merchantUid?: Array<string>;
}
/**
@@ -29522,6 +29608,19 @@ export class DefaultApi extends BaseAPI implements DefaultApiInterface {
.then(request => request(this.axios, this.basePath));
}
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof DefaultApi
*/
public apiMerchantListSampleAllGet(options?: RawAxiosRequestConfig) {
return DefaultApiFp(this.configuration)
.apiMerchantListSampleAllGet(options)
.then(request => request(this.axios, this.basePath));
}
/**
*
* @summary
@@ -29561,14 +29660,14 @@ export class DefaultApi extends BaseAPI implements DefaultApiInterface {
* @memberof DefaultApi
*/
public apiOrderInfoSummaryDailyStatsGet(
requestParameters: DefaultApiApiOrderInfoSummaryDailyStatsGetRequest,
requestParameters: DefaultApiApiOrderInfoSummaryDailyStatsGetRequest = {},
options?: RawAxiosRequestConfig
) {
return DefaultApiFp(this.configuration)
.apiOrderInfoSummaryDailyStatsGet(
requestParameters.current,
requestParameters.pageSize,
requestParameters.roadUid,
requestParameters.dateRange,
requestParameters.merchantUid,
options
)
.then(request => request(this.axios, this.basePath));
@@ -30979,18 +31078,6 @@ export enum ApiMerchantConfigStealRuleRecordGetPageSizeEnum {
NUMBER_50 = 50,
NUMBER_100 = 100
}
/**
* @export
* @enum {string}
*/
export enum ApiOrderInfoSummaryDailyStatsGetPageSizeEnum {
NUMBER_5 = 5,
NUMBER_10 = 10,
NUMBER_15 = 15,
NUMBER_20 = 20,
NUMBER_50 = 50,
NUMBER_100 = 100
}
/**
* @export
* @enum {string}

View File

@@ -236,10 +236,12 @@ export * from './kami-api-merchant-v1-merchant-deploy-record';
export * from './kami-api-merchant-v1-merchant-deploy-update-req';
export * from './kami-api-merchant-v1-merchant-hidden-config-entity';
export * from './kami-api-merchant-v1-merchant-info-record';
export * from './kami-api-merchant-v1-merchant-sample-all-list-res';
export * from './kami-api-merchant-v1-order-query-record';
export * from './kami-api-merchant-v1-order-query-req';
export * from './kami-api-merchant-v1-order-query-res';
export * from './kami-api-merchant-v1-platform-rate-record';
export * from './kami-api-merchant-v1-sample-all-list-res';
export * from './kami-api-merchant-v1-steal-create-req';
export * from './kami-api-merchant-v1-steal-delete-req';
export * from './kami-api-merchant-v1-steal-list-req';

View File

@@ -0,0 +1,37 @@
/* tslint:disable */
/**
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document:
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
// May contain unused imports in some cases
// @ts-ignore
import type { KamiApiMerchantV1SampleAllListRes } from './kami-api-merchant-v1-sample-all-list-res';
/**
*
* @export
* @interface KamiApiMerchantV1MerchantSampleAllListRes
*/
export interface KamiApiMerchantV1MerchantSampleAllListRes {
/**
*
* @type {number}
* @memberof KamiApiMerchantV1MerchantSampleAllListRes
*/
total?: number;
/**
*
* @type {Array<KamiApiMerchantV1SampleAllListRes>}
* @memberof KamiApiMerchantV1MerchantSampleAllListRes
*/
list?: Array<KamiApiMerchantV1SampleAllListRes>;
}

View File

@@ -0,0 +1,33 @@
/* tslint:disable */
/**
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document:
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
/**
*
* @export
* @interface KamiApiMerchantV1SampleAllListRes
*/
export interface KamiApiMerchantV1SampleAllListRes {
/**
* 主键,自增
* @type {number}
* @memberof KamiApiMerchantV1SampleAllListRes
*/
id?: number;
/**
* 商户名称
* @type {string}
* @memberof KamiApiMerchantV1SampleAllListRes
*/
merchantName?: string;
}

View File

@@ -20,33 +20,20 @@
export interface KamiApiOrderV1OrderSummaryDailyGetListReq {
/**
*
* @type {string}
* @type {Array<string>}
* @memberof KamiApiOrderV1OrderSummaryDailyGetListReq
*/
roadUid?: string;
'roadUid[]'?: Array<string>;
/**
* 页数
* @type {number}
*
* @type {Array<string>}
* @memberof KamiApiOrderV1OrderSummaryDailyGetListReq
*/
current: number;
'dateRange[]'?: Array<string>;
/**
* 页码
* @type {number}
*
* @type {Array<string>}
* @memberof KamiApiOrderV1OrderSummaryDailyGetListReq
*/
pageSize: KamiApiOrderV1OrderSummaryDailyGetListReqPageSizeEnum;
}
/**
* @export
* @enum {string}
*/
export enum KamiApiOrderV1OrderSummaryDailyGetListReqPageSizeEnum {
NUMBER_5 = 5,
NUMBER_10 = 10,
NUMBER_15 = 15,
NUMBER_20 = 20,
NUMBER_50 = 50,
NUMBER_100 = 100
'merchantUid[]'?: Array<string>;
}

View File

@@ -4,13 +4,14 @@
:option="options"
:autoresize="autoResize"
:style="{ width, height }"
:theme="theme"
/>
</template>
<script lang="ts" setup>
import { ref, nextTick } from 'vue';
import { ref, nextTick, computed } from 'vue';
import VCharts from 'vue-echarts';
// import { useAppStore } from '@/store';
import { useAppStore } from '@/store';
defineProps({
options: {
@@ -32,13 +33,14 @@ defineProps({
default: '100%'
}
});
// const appStore = useAppStore();
// const theme = computed(() => {
// if (appStore.theme === 'dark') return 'dark';
// return '';
// });
const appStore = useAppStore();
const theme = computed(() => {
if (appStore.theme === 'dark') return 'dark';
return '';
});
const renderChart = ref(false);
// wait container expand
nextTick(() => {
renderChart.value = true;
});

View File

@@ -9,15 +9,76 @@
title="订单量"
>
<template #extra>
<a-link>明细</a-link>
<a-space>
<a-range-picker
v-model="dateRange"
style="width: 240px"
@change="handleDateChange"
/>
<a-select
v-model="selectedMerchants"
:options="merchantOptions"
placeholder="选择商户"
multiple
allow-clear
style="width: 200px"
@change="handleMerchantChange"
/>
<a-select
v-model="selectedRoads"
:options="roadOptions"
placeholder="选择通道"
multiple
allow-clear
style="width: 200px"
@change="handleRoadChange"
/>
<a-button type="primary" @click="handleDetailClick">明细</a-button>
</a-space>
</template>
<Chart height="289px" :option="chartOption" />
</a-card>
<!-- 明细模态框 -->
<a-modal
v-model:visible="detailVisible"
title="订单明细"
:width="1000"
:footer="false"
>
<a-table
:data="detailData"
:pagination="{
total: detailData.length,
pageSize: 10,
showTotal: true
}"
:bordered="false"
:stripe="true"
>
<template #columns>
<a-table-column title="日期" data-index="date" />
<a-table-column title="商户" data-index="merchantName" />
<a-table-column title="通道" data-index="roadName" />
<a-table-column title="成功订单数" data-index="succeedCount" />
<a-table-column title="总订单数" data-index="totalCount" />
<a-table-column title="失败订单数" data-index="failedCount" />
<a-table-column title="等待订单数" data-index="waitedCount" />
<a-table-column title="成功展示金额" data-index="succeedShowAmount" />
<a-table-column title="成功实际金额" data-index="succeedFactAmount" />
<a-table-column title="总展示金额" data-index="totalShowAmount" />
<a-table-column title="总实际金额" data-index="totalFactAmount" />
<a-table-column title="成功率" data-index="rate">
<template #cell="{ record }">{{ record.rate }}%</template>
</a-table-column>
</template>
</a-table>
</a-modal>
</a-spin>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { ref, onMounted } from 'vue';
import { graphic } from 'echarts';
import useLoading from '@/hooks/loading';
import useChartOption from '@/hooks/chart-option';
@@ -25,9 +86,214 @@ import { ToolTipFormatterParams } from '@/types/echarts';
import { AnyObject } from '@/types/global';
import { apiClient } from '@/api';
import {
ApiOrderInfoSummaryDailyStatsGetPageSizeEnum,
ApiOrderInfoSummaryGetListGetPageSizeEnum,
KamiApiOrderV1OrderSummaryDailyRecord
} from '@/api/generated';
import dayjs from 'dayjs';
// 状态变量
const dateRange = ref<[dayjs.Dayjs, dayjs.Dayjs] | null>(null);
const selectedMerchants = ref<string[]>([]);
const selectedRoads = ref<string[]>([]);
const detailVisible = ref(false);
const detailData = ref<KamiApiOrderV1OrderSummaryDailyRecord[]>([]);
const rawData = ref<KamiApiOrderV1OrderSummaryDailyRecord[]>([]);
// 筛选选项数据
const merchantOptions = ref<{ label: string; value: number }[]>([]);
const roadOptions = ref<{ label: string; value: string }[]>([]);
const dateOptions = ref<{ startDate: string; endDate: string }>({
startDate: '',
endDate: ''
});
// 获取商户列表
const fetchMerchantList = async () => {
try {
const { data } = await apiClient.apiMerchantListSampleAllGet();
merchantOptions.value = data.list.map(item => ({
label: item.merchantName || '',
value: item.id || null
}));
} catch (err) {
console.error('获取商户列表失败:', err);
}
};
// 获取通道列表
const fetchRoadList = async () => {
try {
const { data } = await apiClient.apiRoadSimpleGetAllGet();
roadOptions.value = data.list.map(item => ({
label: item.roadName || '',
value: item.roadUid || ''
}));
} catch (err) {
console.error('获取通道列表失败:', err);
}
};
// 获取日期范围
const fetchDateRange = async () => {
// 初始时间是当前时间-15 天
dateRange.value = [dayjs().subtract(15, 'day'), dayjs()];
dateOptions.value.startDate = dateRange.value[0].format('YYYY-MM-DD');
dateOptions.value.endDate = dateRange.value[1].format('YYYY-MM-DD');
};
// 初始化数据
const initData = async () => {
await Promise.all([fetchMerchantList(), fetchRoadList(), fetchDateRange()]);
await fetchData();
};
// 处理日期变化
const handleDateChange = () => {
fetchData();
};
// 处理商户变化
const handleMerchantChange = () => {
fetchData();
};
// 处理通道变化
const handleRoadChange = () => {
fetchData();
};
// 处理明细点击
const handleDetailClick = () => {
detailData.value = rawData.value;
detailVisible.value = true;
};
// 获取筛选后的数据
const getFilteredData = () => {
let filtered = [...rawData.value];
if (dateRange.value) {
const [start, end] = dateRange.value;
filtered = filtered.filter(item => {
const date = dayjs(item.date);
return date.isAfter(start) && date.isBefore(end);
});
}
if (selectedMerchants.value.length > 0) {
filtered = filtered.filter(item =>
selectedMerchants.value.includes(item.merchantUid)
);
}
if (selectedRoads.value.length > 0) {
filtered = filtered.filter(item =>
selectedRoads.value.includes(item.roadUid)
);
}
return filtered;
};
// 更新图表数据
const updateChartData = () => {
const filtered = getFilteredData();
// 获取日期范围
const dates = filtered.map(item => item.date);
const minDate = dayjs(Math.min(...dates.map(d => new Date(d).getTime())));
const maxDate = dayjs(Math.max(...dates.map(d => new Date(d).getTime())));
// 生成完整的日期序列
const allDates: string[] = [];
let currentDate = minDate;
while (currentDate.isBefore(maxDate) || currentDate.isSame(maxDate, 'day')) {
allDates.push(currentDate.format('YYYY-MM-DD'));
currentDate = currentDate.add(1, 'day');
}
// 重置数据
xAxis.value = allDates;
seriesData.value = [
{ name: '成功订单量', data: [] },
{ name: '总订单量', data: [] },
{ name: '成功率', data: [] }
];
// 填充数据
allDates.forEach(date => {
const dayData = filtered.filter(item => item.date === date);
const succeedAmount = dayData.reduce(
(sum, item) => sum + item.succeedFactAmount,
0
);
const totalAmount = dayData.reduce(
(sum, item) => sum + item.totalFactAmount,
0
);
// 计算成功率
const rate = totalAmount > 0 ? (succeedAmount / totalAmount) * 100 : 0;
seriesData.value[0].data.push(succeedAmount);
seriesData.value[1].data.push(totalAmount);
seriesData.value[2].data.push(rate);
});
// 更新图表边界文本
if (allDates.length > 0) {
graphicElements.value[0].style.text = allDates[0];
graphicElements.value[1].style.text = allDates[allDates.length - 1];
}
};
// 定义线条颜色配置
const lineColors = [
{
line: [
{ offset: 0, color: 'rgba(30, 231, 255, 1)' },
{ offset: 0.5, color: 'rgba(36, 154, 255, 1)' },
{ offset: 1, color: 'rgba(111, 66, 251, 1)' }
],
area: [
{ offset: 0, color: 'rgba(17, 126, 255, 0.16)' },
{ offset: 1, color: 'rgba(17, 128, 255, 0)' }
]
},
{
line: [
{ offset: 0, color: 'rgba(255, 99, 132, 1)' },
{ offset: 0.5, color: 'rgba(255, 159, 64, 1)' },
{ offset: 1, color: 'rgba(255, 205, 86, 1)' }
],
area: [
{ offset: 0, color: 'rgba(255, 99, 132, 0.16)' },
{ offset: 1, color: 'rgba(255, 99, 132, 0)' }
]
},
{
line: [
{ offset: 0, color: 'rgba(75, 192, 192, 1)' },
{ offset: 0.5, color: 'rgba(54, 162, 235, 1)' },
{ offset: 1, color: 'rgba(153, 102, 255, 1)' }
],
area: [
{ offset: 0, color: 'rgba(75, 192, 192, 0.16)' },
{ offset: 1, color: 'rgba(75, 192, 192, 0)' }
]
},
{
line: [
{ offset: 0, color: 'rgba(255, 159, 64, 1)' },
{ offset: 0.5, color: 'rgba(255, 99, 132, 1)' },
{ offset: 1, color: 'rgba(153, 102, 255, 1)' }
],
area: [
{ offset: 0, color: 'rgba(255, 159, 64, 0.16)' },
{ offset: 1, color: 'rgba(255, 159, 64, 0)' }
]
}
];
function graphicFactory(side: AnyObject) {
return {
@@ -42,13 +308,15 @@ function graphicFactory(side: AnyObject) {
}
};
}
const { loading, setLoading } = useLoading(true);
const xAxis = ref<string[]>([]);
const chartsData = ref<number[]>([]);
const seriesData = ref<{ name: string; data: number[] }[]>([]);
const graphicElements = ref([
graphicFactory({ left: '2.6%' }),
graphicFactory({ right: 0 })
]);
const { chartOption } = useChartOption(() => {
return {
grid: {
@@ -57,6 +325,14 @@ const { chartOption } = useChartOption(() => {
top: '10',
bottom: '30'
},
legend: {
show: true,
top: 0,
right: 0,
textStyle: {
color: '#4E5969'
}
},
xAxis: {
type: 'category',
offset: 2,
@@ -95,116 +371,144 @@ const { chartOption } = useChartOption(() => {
}
}
},
yAxis: {
type: 'value',
axisLine: {
show: false
},
axisLabel: {
formatter(value: any, idx: number) {
if (idx === 0) return value;
return `${value}k`;
yAxis: [
{
type: 'value',
name: '订单量',
nameTextStyle: {
color: '#4E5969'
},
axisLine: {
show: false
},
axisLabel: {
formatter(value: any, idx: number) {
if (idx === 0) return value;
return `${value}k`;
}
},
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
color: '#E5E8EF'
}
}
},
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
color: '#E5E8EF'
{
type: 'value',
name: '成功率',
nameTextStyle: {
color: '#4E5969'
},
min: 0,
max: 100,
axisLine: {
show: false
},
axisLabel: {
formatter: '{value}%'
},
splitLine: {
show: false
}
}
},
],
tooltip: {
trigger: 'axis',
formatter(params) {
const [firstElement] = params as ToolTipFormatterParams[];
return `<div>
<p class="tooltip-title">${firstElement.axisValueLabel}</p>
<div class="content-panel"><span>总内容量</span><span class="tooltip-value">${(
Number(firstElement.value) * 10000
).toLocaleString()}</span></div>
</div>`;
const paramsList = params as ToolTipFormatterParams[];
let result = `<div><p class="tooltip-title">${paramsList[0].axisValueLabel}</p>`;
paramsList.forEach(item => {
result += `<div class="content-panel"><span>${item.seriesName}</span><span class="tooltip-value">${
item.seriesName === '成功率'
? `${Number(item.value).toFixed(2)}%`
: Number(item.value).toLocaleString()
}</span></div>`;
});
result += '</div>';
return result;
},
className: 'echarts-tooltip-diy'
},
graphic: {
elements: graphicElements.value
},
series: [
{
data: chartsData.value,
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 12,
emphasis: {
focus: 'series',
itemStyle: {
borderWidth: 2
}
},
lineStyle: {
width: 3,
color: new graphic.LinearGradient(0, 0, 1, 0, [
{
offset: 0,
color: 'rgba(30, 231, 255, 1)'
},
{
offset: 0.5,
color: 'rgba(36, 154, 255, 1)'
},
{
offset: 1,
color: 'rgba(111, 66, 251, 1)'
}
])
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
color: new graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(17, 126, 255, 0.16)'
},
{
offset: 1,
color: 'rgba(17, 128, 255, 0)'
}
])
series: seriesData.value.map((series, index) => ({
name: series.name,
data: series.data,
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 12,
yAxisIndex: series.name === '成功率' ? 1 : 0,
emphasis: {
focus: 'series',
itemStyle: {
borderWidth: 2
}
},
lineStyle: {
width: 3,
color: new graphic.LinearGradient(
0,
0,
1,
0,
lineColors[index % lineColors.length].line
)
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
color: new graphic.LinearGradient(
0,
0,
0,
1,
lineColors[index % lineColors.length].area
)
}
]
}))
};
});
const fetchData = async () => {
setLoading(true);
try {
const { data: chartData } =
await apiClient.apiOrderInfoSummaryDailyStatsGet({
current: 1,
pageSize: 100 as ApiOrderInfoSummaryDailyStatsGetPageSizeEnum
roadUid:
selectedRoads.value.length > 0 ? selectedRoads.value : undefined,
merchantUid:
selectedMerchants.value.length > 0
? selectedMerchants.value
: undefined,
dateRange: dateRange.value
? [
dayjs(dateRange.value[0]).format('YYYY-MM-DD'),
dayjs(dateRange.value[1]).format('YYYY-MM-DD')
]
: undefined
});
console.log(chartData);
chartData.list.forEach(
(el: KamiApiOrderV1OrderSummaryDailyRecord, idx: number) => {
xAxis.value.push(el.date);
chartsData.value.push(el.succeedFactAmount);
if (idx === 0) {
graphicElements.value[0].style.text = el.date;
}
if (idx === chartData.list.length - 1) {
graphicElements.value[1].style.text = el.date;
}
}
);
rawData.value = chartData.list;
updateChartData();
} catch (err) {
console.error('获取订单数据失败:', err);
} finally {
setLoading(false);
}
};
fetchData();
// 使用 onMounted 替代直接调用
onMounted(() => {
initData();
});
</script>
<style scoped lang="less"></style>
<style scoped lang="less">
:deep(.arco-table-th) {
background-color: var(--color-fill-2);
}
</style>

View File

@@ -63,10 +63,8 @@ export default {
<style lang="less" scoped>
.container {
display: flex;
padding: 16px 20px;
padding-bottom: 0;
background-color: var(--color-fill-2);
}
.left-side {