feat(camel-oil): 更新账号相关API模型和界面组件
- 从账号历史记录模型中移除historyUuid字段 - 在创建令牌请求模型中新增phone字段用于绑定手机号 - 在令牌信息模型中新增phone字段 - 移除账号详情页面中的账号ID显示和统计信息卡片 - 更新账号历史记录组件的筛选条件和展示字段 - 修改账号列表中的状态选项和显示逻辑 - 移除账号关联订单统计弹窗及相关功能 - 更新订单历史记录模型枚举值,新增FillCard类型 - 调整.clau ```
This commit is contained in:
@@ -9,7 +9,9 @@
|
||||
"Bash(pnpm lint:*)",
|
||||
"Bash(pnpm prettier:fix)",
|
||||
"Bash(pnpm eslint:*)",
|
||||
"Bash(mkdir:*)"
|
||||
"Bash(mkdir:*)",
|
||||
"Bash(pnpm build)",
|
||||
"Bash(pnpm eslint:fix)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
| Name | Type | Description | Notes |
|
||||
| ---------------- | ---------- | ------------ | --------------------------------- |
|
||||
| **historyUuid** | **string** | 历史记录UUID | [optional] [default to undefined] |
|
||||
| **accountId** | **number** | 账号ID | [optional] [default to undefined] |
|
||||
| **changeType** | **string** | 变更类型 | [optional] [default to undefined] |
|
||||
| **changeText** | **string** | 变更类型文本 | [optional] [default to undefined] |
|
||||
@@ -20,7 +19,6 @@
|
||||
import { KamiApiCamelOilV1AccountHistoryItem } from './api';
|
||||
|
||||
const instance: KamiApiCamelOilV1AccountHistoryItem = {
|
||||
historyUuid,
|
||||
accountId,
|
||||
changeType,
|
||||
changeText,
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
## Properties
|
||||
|
||||
| Name | Type | Description | Notes |
|
||||
| -------------- | ---------- | ----------- | --------------------------------- |
|
||||
| -------------- | ---------- | ------------ | --------------------------------- |
|
||||
| **tokenName** | **string** | Token名称 | [default to undefined] |
|
||||
| **tokenValue** | **string** | Token值 | [default to undefined] |
|
||||
| **phone** | **string** | 绑定的手机号 | [optional] [default to undefined] |
|
||||
| **remark** | **string** | 备注 | [optional] [default to undefined] |
|
||||
|
||||
## Example
|
||||
@@ -16,6 +17,7 @@ import { KamiApiCamelOilV1CreateTokenReq } from './api';
|
||||
const instance: KamiApiCamelOilV1CreateTokenReq = {
|
||||
tokenName,
|
||||
tokenValue,
|
||||
phone,
|
||||
remark
|
||||
};
|
||||
```
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
| Name | Type | Description | Notes |
|
||||
| --------------- | ---------- | ------------ | --------------------------------- |
|
||||
| **historyUuid** | **string** | 历史记录UUID | [optional] [default to undefined] |
|
||||
| **orderNo** | **string** | 订单号 | [optional] [default to undefined] |
|
||||
| **changeType** | **string** | 变更类型 | [optional] [default to undefined] |
|
||||
| **changeText** | **string** | 变更类型文本 | [optional] [default to undefined] |
|
||||
@@ -20,7 +19,6 @@
|
||||
import { KamiApiCamelOilV1OrderHistoryItem } from './api';
|
||||
|
||||
const instance: KamiApiCamelOilV1OrderHistoryItem = {
|
||||
historyUuid,
|
||||
orderNo,
|
||||
changeType,
|
||||
changeText,
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
| **id** | **number** | Token ID | [optional] [default to undefined] |
|
||||
| **tokenName** | **string** | Token名称 | [optional] [default to undefined] |
|
||||
| **tokenValue** | **string** | Token值 | [optional] [default to undefined] |
|
||||
| **phone** | **string** | 绑定的手机号 | [optional] [default to undefined] |
|
||||
| **status** | **number** | 状态 | [optional] [default to undefined] |
|
||||
| **bindCount** | **number** | 已绑定卡密数量 | [optional] [default to undefined] |
|
||||
| **totalBindAmount** | **object** | | [optional] [default to undefined] |
|
||||
@@ -25,6 +26,7 @@ const instance: KamiApiCamelOilV1TokenInfo = {
|
||||
id,
|
||||
tokenName,
|
||||
tokenValue,
|
||||
phone,
|
||||
status,
|
||||
bindCount,
|
||||
totalBindAmount,
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
*/
|
||||
|
||||
export interface KamiApiCamelOilV1AccountHistoryItem {
|
||||
/**
|
||||
* 历史记录UUID
|
||||
*/
|
||||
historyUuid?: string;
|
||||
/**
|
||||
* 账号ID
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,10 @@ export interface KamiApiCamelOilV1CreateTokenReq {
|
||||
* Token值
|
||||
*/
|
||||
tokenValue: string;
|
||||
/**
|
||||
* 绑定的手机号
|
||||
*/
|
||||
phone?: string;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
*/
|
||||
|
||||
export interface KamiApiCamelOilV1OrderHistoryItem {
|
||||
/**
|
||||
* 历史记录UUID
|
||||
*/
|
||||
historyUuid?: string;
|
||||
/**
|
||||
* 订单号
|
||||
*/
|
||||
@@ -57,6 +53,7 @@ export enum KamiApiCamelOilV1OrderHistoryItemChangeTypeEnum {
|
||||
CheckPay = 'check_pay',
|
||||
Create = 'create',
|
||||
Fail = 'fail',
|
||||
FillCard = 'fill_card',
|
||||
GetPayUrl = 'get_pay_url',
|
||||
Paid = 'paid',
|
||||
Submit = 'submit',
|
||||
|
||||
@@ -25,6 +25,10 @@ export interface KamiApiCamelOilV1TokenInfo {
|
||||
* Token值
|
||||
*/
|
||||
tokenValue?: string;
|
||||
/**
|
||||
* 绑定的手机号
|
||||
*/
|
||||
phone?: string;
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
|
||||
@@ -1,257 +0,0 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="modalVisible"
|
||||
title="账号关联订单统计"
|
||||
width="600px"
|
||||
:footer="false"
|
||||
>
|
||||
<a-spin :loading="loading" style="width: 100%">
|
||||
<div v-if="accountOrderStats" class="orders-stats">
|
||||
<!-- 订单统计卡片 -->
|
||||
<a-row :gutter="16" style="margin-bottom: 24px">
|
||||
<a-col :span="6">
|
||||
<a-statistic
|
||||
title="总订单数"
|
||||
:value="statistics.totalOrders"
|
||||
suffix="单"
|
||||
:value-style="{ color: '#165dff', fontSize: '24px' }"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-statistic
|
||||
title="已支付订单"
|
||||
:value="statistics.paidOrders"
|
||||
suffix="单"
|
||||
:value-style="{ color: '#00b42a', fontSize: '24px' }"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-statistic
|
||||
title="待支付订单"
|
||||
:value="statistics.pendingOrders"
|
||||
suffix="单"
|
||||
:value-style="{ color: '#ff7d00', fontSize: '24px' }"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-statistic
|
||||
title="超时订单"
|
||||
:value="statistics.timeoutOrders"
|
||||
suffix="单"
|
||||
:value-style="{ color: '#f53f3f', fontSize: '24px' }"
|
||||
/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<!-- 详细统计信息 -->
|
||||
<a-card title="详细统计" class="detail-stats-card">
|
||||
<a-descriptions :column="2" bordered>
|
||||
<a-descriptions-item label="总订单数">
|
||||
<a-tag color="blue">{{ statistics.totalOrders }} 单</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="已支付订单">
|
||||
<a-tag color="green">{{ statistics.paidOrders }} 单</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="待支付订单">
|
||||
<a-tag color="orange">{{ statistics.pendingOrders }} 单</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="超时订单">
|
||||
<a-tag color="red">{{ statistics.timeoutOrders }} 单</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="支付成功率">
|
||||
<span :class="paymentRateClass">{{ paymentRate }}%</span>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="待支付率">
|
||||
<span :class="pendingRateClass">{{ pendingRate }}%</span>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-card>
|
||||
</div>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<a-empty v-else description="暂无订单统计数据" />
|
||||
</a-spin>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue';
|
||||
import { jdV2OrderClient } from '@/api/index.ts';
|
||||
import type { KamiApiCamelOilV1AccountOrderListResOrderStats } from '@/api/generated/models/index.ts';
|
||||
|
||||
// Props 定义
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
accountId: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
accountId: ''
|
||||
});
|
||||
|
||||
// Emits 定义
|
||||
interface Emits {
|
||||
(e: 'update:visible', value: boolean): void;
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
// 响应式数据
|
||||
const loading = ref(false);
|
||||
const accountOrderStats =
|
||||
ref<KamiApiCamelOilV1AccountOrderListResOrderStats | null>(null);
|
||||
|
||||
// 统计数据
|
||||
const statistics = reactive({
|
||||
totalOrders: 0,
|
||||
paidOrders: 0,
|
||||
pendingOrders: 0,
|
||||
timeoutOrders: 0
|
||||
});
|
||||
|
||||
// 计算属性
|
||||
const modalVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: value => emit('update:visible', value)
|
||||
});
|
||||
|
||||
const paymentRate = computed(() => {
|
||||
if (statistics.totalOrders === 0) return 0;
|
||||
return ((statistics.paidOrders / statistics.totalOrders) * 100).toFixed(2);
|
||||
});
|
||||
|
||||
const pendingRate = computed(() => {
|
||||
if (statistics.totalOrders === 0) return 0;
|
||||
return ((statistics.pendingOrders / statistics.totalOrders) * 100).toFixed(2);
|
||||
});
|
||||
|
||||
const paymentRateClass = computed(() => {
|
||||
const rate = parseFloat(paymentRate.value.toString());
|
||||
if (rate >= 90) return 'rate-excellent';
|
||||
if (rate >= 70) return 'rate-good';
|
||||
return 'rate-poor';
|
||||
});
|
||||
|
||||
const pendingRateClass = computed(() => {
|
||||
const rate = parseFloat(pendingRate.value.toString());
|
||||
if (rate <= 10) return 'rate-excellent';
|
||||
if (rate <= 30) return 'rate-good';
|
||||
return 'rate-poor';
|
||||
});
|
||||
|
||||
/**
|
||||
* 获取账号订单统计数据
|
||||
*/
|
||||
const fetchAccountOrderStats = async () => {
|
||||
if (!props.accountId) return;
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
// 由于API结构问题,这里暂时使用模拟数据
|
||||
// 实际应该调用: camelOilOrderClient.apiCamelOilOrderAccountOrdersGet()
|
||||
// 但是这个API返回的是单个账号的订单统计,不是列表
|
||||
|
||||
// 模拟数据,等待API完善
|
||||
accountOrderStats.value = {
|
||||
totalOrders: 150,
|
||||
paidOrders: 120,
|
||||
pendingOrders: 25,
|
||||
timeoutOrders: 5
|
||||
};
|
||||
|
||||
// 更新统计数据
|
||||
if (accountOrderStats.value) {
|
||||
Object.assign(statistics, {
|
||||
totalOrders: accountOrderStats.value.totalOrders || 0,
|
||||
paidOrders: accountOrderStats.value.paidOrders || 0,
|
||||
pendingOrders: accountOrderStats.value.pendingOrders || 0,
|
||||
timeoutOrders: accountOrderStats.value.timeoutOrders || 0
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取账号订单统计失败:', error);
|
||||
accountOrderStats.value = null;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 监听弹窗显示状态
|
||||
watch(
|
||||
() => props.visible,
|
||||
visible => {
|
||||
if (visible && props.accountId) {
|
||||
fetchAccountOrderStats();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 监听账号ID变化
|
||||
watch(
|
||||
() => props.accountId,
|
||||
accountId => {
|
||||
if (accountId && props.visible) {
|
||||
fetchAccountOrderStats();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.orders-stats {
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.detail-stats-card {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.rate-excellent {
|
||||
color: #00b42a;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.rate-good {
|
||||
color: #ff7d00;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.rate-poor {
|
||||
color: #f53f3f;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
:deep(.arco-statistic) {
|
||||
text-align: center;
|
||||
padding: 16px;
|
||||
border-radius: 6px;
|
||||
background-color: #f7f8fa;
|
||||
}
|
||||
|
||||
:deep(.arco-statistic-title) {
|
||||
color: #86909c;
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
:deep(.arco-statistic-value) {
|
||||
color: #1d2129;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:deep(.arco-descriptions-item-label) {
|
||||
font-weight: 600;
|
||||
background-color: #f7f8fa;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body) {
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
@@ -10,9 +10,6 @@
|
||||
<!-- 基本信息 -->
|
||||
<a-card title="基本信息" class="detail-card">
|
||||
<a-descriptions :column="2" bordered>
|
||||
<a-descriptions-item label="账号ID">
|
||||
{{ accountDetail.accountId }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="账号名称">
|
||||
{{ accountDetail.accountName }}
|
||||
</a-descriptions-item>
|
||||
@@ -35,33 +32,6 @@
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-card>
|
||||
|
||||
<!-- 统计信息 -->
|
||||
<a-card title="统计信息" class="detail-card">
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="8">
|
||||
<a-statistic
|
||||
title="今日充值金额"
|
||||
:value="parseFloat(statistics.todayAmount)"
|
||||
prefix="¥"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-statistic
|
||||
title="今日充值次数"
|
||||
:value="parseFloat(statistics.todayCount)"
|
||||
suffix="次"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-statistic
|
||||
title="本月充值金额"
|
||||
:value="parseFloat(statistics.monthAmount)"
|
||||
prefix="¥"
|
||||
/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</div>
|
||||
|
||||
<!-- 空状态 -->
|
||||
@@ -98,13 +68,6 @@ const loading = ref(false);
|
||||
const accountDetail =
|
||||
ref<KamiApiCamelOilV1AccountStatisticsResAccountInfo | null>(null);
|
||||
|
||||
// 统计数据
|
||||
const statistics = ref({
|
||||
todayAmount: '0',
|
||||
todayCount: '0',
|
||||
monthAmount: '0'
|
||||
});
|
||||
|
||||
// 计算属性
|
||||
const modalVisible = computed({
|
||||
get: () => props.visible,
|
||||
@@ -112,26 +75,19 @@ const modalVisible = computed({
|
||||
});
|
||||
|
||||
/**
|
||||
* 获取账号详情和统计信息
|
||||
* 获取账号详情
|
||||
*/
|
||||
const fetchAccountDetail = async () => {
|
||||
if (!props.accountId) return;
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
// 获取账号统计信息
|
||||
// 获取账号详情信息
|
||||
const { data } = await jdV2AccountClient.apiJdV2AccountStatisticsGet({
|
||||
accountId: parseInt(props.accountId)
|
||||
});
|
||||
|
||||
accountDetail.value = data.accountInfo;
|
||||
|
||||
// 暂时使用默认统计信息,等待API完善
|
||||
statistics.value = {
|
||||
todayAmount: '0',
|
||||
todayCount: '0',
|
||||
monthAmount: '0'
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取账号详情失败:', error);
|
||||
accountDetail.value = null;
|
||||
@@ -148,20 +104,20 @@ const fetchAccountDetail = async () => {
|
||||
const statusMapper = (
|
||||
status: number | undefined
|
||||
): { text: string; color: string } => {
|
||||
if (!status) return { text: '未知', color: 'gray' };
|
||||
if (!status) return { text: '未知状态', color: 'gray' };
|
||||
switch (status) {
|
||||
case 0:
|
||||
return { text: '失效', color: 'red' };
|
||||
return { text: '待登录', color: 'orange' }; // 需要登录验证
|
||||
case 1:
|
||||
return { text: '正常', color: 'green' };
|
||||
return { text: '发送验证码', color: 'blue' }; // 正在发送验证码
|
||||
case 2:
|
||||
return { text: '充值过快', color: 'orange' };
|
||||
return { text: '在线', color: 'green' }; // 账户在线,可用
|
||||
case 3:
|
||||
return { text: '账号受限', color: 'red' };
|
||||
return { text: '已暂停', color: 'orange' }; // 账户被暂停使用
|
||||
case 4:
|
||||
return { text: '异常', color: 'gray' };
|
||||
return { text: '已失效', color: 'red' }; // 账户已失效
|
||||
default:
|
||||
return { text: '未知', color: 'gray' };
|
||||
return { text: '未知状态', color: 'gray' };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -200,39 +156,8 @@ watch(
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.balance-text {
|
||||
color: #00b42a;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.recharge-text {
|
||||
color: #165dff;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
:deep(.arco-descriptions-item-label) {
|
||||
font-weight: 600;
|
||||
background-color: #f7f8fa;
|
||||
}
|
||||
|
||||
:deep(.arco-statistic) {
|
||||
text-align: center;
|
||||
padding: 16px;
|
||||
border-radius: 6px;
|
||||
background-color: #f7f8fa;
|
||||
}
|
||||
|
||||
:deep(.arco-statistic-title) {
|
||||
color: #86909c;
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
:deep(.arco-statistic-value) {
|
||||
color: #1d2129;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
background-color: var(--color-fill-2);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -27,18 +27,26 @@
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item field="action" label="操作类型">
|
||||
<a-form-item field="changeType" label="变更类型">
|
||||
<a-select
|
||||
v-model="filterForm.action"
|
||||
placeholder="请选择操作类型"
|
||||
v-model="filterForm.changeType"
|
||||
placeholder="请选择变更类型"
|
||||
allow-clear
|
||||
style="width: 100%"
|
||||
>
|
||||
<a-option value="create">创建</a-option>
|
||||
<a-option value="update">更新</a-option>
|
||||
<a-option value="delete">删除</a-option>
|
||||
<a-option value="recharge">充值</a-option>
|
||||
<a-option value="consume">消费</a-option>
|
||||
<a-option value="create">创建账号</a-option>
|
||||
<a-option value="login">登录成功</a-option>
|
||||
<a-option value="offline">检测到掉线</a-option>
|
||||
<a-option value="login_fail">登录失败</a-option>
|
||||
<a-option value="pause">订单数达到10,暂停使用</a-option>
|
||||
<a-option value="resume">次日重置,恢复使用</a-option>
|
||||
<a-option value="invalidate">
|
||||
单日下单不足10个,账号失效
|
||||
</a-option>
|
||||
<a-option value="order_bind">绑定订单</a-option>
|
||||
<a-option value="order_complete">订单完成</a-option>
|
||||
<a-option value="update">更新账号信息</a-option>
|
||||
<a-option value="delete">删除账号</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -79,31 +87,39 @@
|
||||
@page-change="onPageChange"
|
||||
@page-size-change="onPageSizeChange"
|
||||
>
|
||||
<template #action="{ record }">
|
||||
<a-tag :color="actionMapper(record.action).color">
|
||||
{{ actionMapper(record.action).text }}
|
||||
<template #changeType="{ record }">
|
||||
<a-tag :color="changeTypeMapper(record.changeType).color">
|
||||
{{ changeTypeMapper(record.changeType).text }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<template #amount="{ record }">
|
||||
<span
|
||||
v-if="record.amount"
|
||||
:class="{
|
||||
'amount-positive': record.amount > 0,
|
||||
'amount-negative': record.amount < 0
|
||||
}"
|
||||
<template #beforeStatus="{ record }">
|
||||
<a-tag
|
||||
v-if="
|
||||
record.statusBefore !== undefined &&
|
||||
record.statusBefore !== null
|
||||
"
|
||||
:color="statusColorMapper(record.statusBefore)"
|
||||
>
|
||||
{{ record.amount > 0 ? '+' : '' }}¥{{ record.amount }}
|
||||
</span>
|
||||
{{ statusMapper(record.statusBefore).text }}
|
||||
</a-tag>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
|
||||
<template #balance="{ record }">
|
||||
<span class="balance-text">¥{{ record.balance || 0 }}</span>
|
||||
<template #afterStatus="{ record }">
|
||||
<a-tag
|
||||
v-if="
|
||||
record.statusAfter !== undefined && record.statusAfter !== null
|
||||
"
|
||||
:color="statusColorMapper(record.statusAfter)"
|
||||
>
|
||||
{{ statusMapper(record.statusAfter).text }}
|
||||
</a-tag>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
|
||||
<template #details="{ record }">
|
||||
<a-tooltip v-if="record.details" :content="record.details">
|
||||
<template #remark="{ record }">
|
||||
<a-tooltip v-if="record.remark" :content="record.remark">
|
||||
<a-button size="small" type="text">
|
||||
<template #icon>
|
||||
<icon-eye />
|
||||
@@ -120,10 +136,9 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue';
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { TableColumnData } from '@arco-design/web-vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { Pagination } from '@/types/global';
|
||||
import { jdV2AccountClient } from '@/api/index.ts';
|
||||
import type { KamiApiCamelOilV1AccountHistoryItem } from '@/api/generated/models/index.ts';
|
||||
@@ -148,7 +163,7 @@ interface Emits {
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
// 响应式数据
|
||||
const { loading, setLoading } = useLoading(false);
|
||||
const loading = ref(false);
|
||||
const tableLoading = ref(false);
|
||||
const historyData = ref<KamiApiCamelOilV1AccountHistoryItem[]>([]);
|
||||
|
||||
@@ -163,7 +178,7 @@ const pagination = reactive({ ...basePagination });
|
||||
// 筛选表单
|
||||
const filterForm = reactive({
|
||||
dateRange: [] as Date[],
|
||||
action: undefined as string | undefined
|
||||
changeType: undefined as string | undefined
|
||||
});
|
||||
|
||||
// 时间快捷选项
|
||||
@@ -220,43 +235,37 @@ const columns: TableColumnData[] = [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作类型',
|
||||
dataIndex: 'action',
|
||||
slotName: 'action',
|
||||
title: '变更类型',
|
||||
dataIndex: 'changeType',
|
||||
slotName: 'changeType',
|
||||
width: 180
|
||||
},
|
||||
{
|
||||
title: '变更前状态',
|
||||
dataIndex: 'statusBefore',
|
||||
slotName: 'beforeStatus',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '操作人',
|
||||
dataIndex: 'operator',
|
||||
width: 120
|
||||
title: '变更后状态',
|
||||
dataIndex: 'statusAfter',
|
||||
slotName: 'afterStatus',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '金额变化',
|
||||
dataIndex: 'amount',
|
||||
slotName: 'amount',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '操作后余额',
|
||||
dataIndex: 'balance',
|
||||
slotName: 'balance',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '操作说明',
|
||||
dataIndex: 'description',
|
||||
title: '备注说明',
|
||||
dataIndex: 'remark',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '详细信息',
|
||||
dataIndex: 'details',
|
||||
slotName: 'details',
|
||||
title: '失败次数',
|
||||
dataIndex: 'failureCount',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '操作时间',
|
||||
title: '创建时间',
|
||||
dataIndex: 'createdAt',
|
||||
width: 180
|
||||
}
|
||||
@@ -338,31 +347,90 @@ const searchHistory = () => {
|
||||
*/
|
||||
const resetFilter = () => {
|
||||
filterForm.dateRange = [];
|
||||
filterForm.action = undefined;
|
||||
filterForm.changeType = undefined;
|
||||
searchHistory();
|
||||
};
|
||||
|
||||
/**
|
||||
* 操作类型映射器
|
||||
* @param action 操作类型
|
||||
* @returns 操作类型文本和颜色
|
||||
* 变更类型映射器
|
||||
* 基于后端Go定义的CamelOilAccountChangeType
|
||||
* @param changeType 变更类型
|
||||
* @returns 变更类型文本和颜色
|
||||
*/
|
||||
const actionMapper = (action: string): { text: string; color: string } => {
|
||||
switch (action) {
|
||||
const changeTypeMapper = (
|
||||
changeType: string
|
||||
): { text: string; color: string } => {
|
||||
switch (changeType) {
|
||||
case 'create':
|
||||
return { text: '创建', color: 'green' };
|
||||
return { text: '创建账号', color: 'green' };
|
||||
case 'login':
|
||||
return { text: '登录成功', color: 'blue' };
|
||||
case 'offline':
|
||||
return { text: '检测到掉线', color: 'orange' };
|
||||
case 'login_fail':
|
||||
return { text: '登录失败', color: 'red' };
|
||||
case 'pause':
|
||||
return { text: '订单数达到10,暂停使用', color: 'orange' };
|
||||
case 'resume':
|
||||
return { text: '次日重置,恢复使用', color: 'green' };
|
||||
case 'invalidate':
|
||||
return { text: '单日下单不足10个,账号失效', color: 'red' };
|
||||
case 'order_bind':
|
||||
return { text: '绑定订单', color: 'blue' };
|
||||
case 'order_complete':
|
||||
return { text: '订单完成', color: 'green' };
|
||||
case 'update':
|
||||
return { text: '更新', color: 'blue' };
|
||||
return { text: '更新账号信息', color: 'blue' };
|
||||
case 'delete':
|
||||
return { text: '删除', color: 'red' };
|
||||
case 'recharge':
|
||||
return { text: '充值', color: 'green' };
|
||||
case 'consume':
|
||||
return { text: '消费', color: 'orange' };
|
||||
case 'status_change':
|
||||
return { text: '状态变更', color: 'purple' };
|
||||
return { text: '删除账号', color: 'red' };
|
||||
default:
|
||||
return { text: '未知', color: 'gray' };
|
||||
return { text: '未知变更', color: 'gray' };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 状态颜色映射器
|
||||
* 基于后端Go定义的CamelOilAccountStatus
|
||||
* @param status 状态值
|
||||
* @returns 状态颜色
|
||||
*/
|
||||
const statusColorMapper = (status: number): string => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return 'orange'; // 待登录
|
||||
case 1:
|
||||
return 'blue'; // 发送验证码
|
||||
case 2:
|
||||
return 'green'; // 在线
|
||||
case 3:
|
||||
return 'orange'; // 已暂停
|
||||
case 4:
|
||||
return 'red'; // 已失效
|
||||
default:
|
||||
return 'gray'; // 未知状态
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 状态文本映射器
|
||||
* 基于后端Go定义的CamelOilAccountStatus
|
||||
* @param status 状态值
|
||||
* @returns 状态文本
|
||||
*/
|
||||
const statusMapper = (status: number): { text: string } => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return { text: '待登录' };
|
||||
case 1:
|
||||
return { text: '发送验证码' };
|
||||
case 2:
|
||||
return { text: '在线' };
|
||||
case 3:
|
||||
return { text: '已暂停' };
|
||||
case 4:
|
||||
return { text: '已失效' };
|
||||
default:
|
||||
return { text: '未知状态' };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -393,23 +461,25 @@ watch(
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.amount-positive {
|
||||
color: #00b42a;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.amount-negative {
|
||||
color: #f53f3f;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.balance-text {
|
||||
color: #165dff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body) {
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
|
||||
/* 确保滚动条样式跟随主题 */
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--color-border-3) transparent;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body::-webkit-scrollbar) {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body::-webkit-scrollbar-thumb) {
|
||||
background-color: var(--color-border-3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body::-webkit-scrollbar-track) {
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="modalVisible"
|
||||
title="订单详情"
|
||||
width="700px"
|
||||
:footer="false"
|
||||
>
|
||||
<div v-if="order" class="order-detail">
|
||||
<a-descriptions :column="2" bordered>
|
||||
<a-descriptions-item label="订单号">
|
||||
{{ order.orderNo }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="商户订单号">
|
||||
{{ order.merchantOrderNo || '-' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="订单金额">
|
||||
<span class="amount-text">¥{{ order.amount }}</span>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="订单状态">
|
||||
<a-tag :color="statusMapper(order.status).color">
|
||||
{{ statusMapper(order.status).text }}
|
||||
</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="支付状态">
|
||||
<a-tag :color="payStatusMapper(order.payStatus).color">
|
||||
{{ payStatusMapper(order.payStatus).text }}
|
||||
</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="充值账号">
|
||||
{{ order.accountName }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="充值手机">
|
||||
{{ order.accountPhone }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="回调状态">
|
||||
<a-tag :color="order.callbackStatus === 1 ? 'green' : 'red'">
|
||||
{{ order.callbackStatus === 1 ? '成功' : '失败' }}
|
||||
</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="创建时间" :span="2">
|
||||
{{ order.createdAt }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="更新时间" :span="2">
|
||||
{{ order.updatedAt }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="备注" :span="2">
|
||||
{{ order.remark || '-' }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
// Props 定义
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
order: any;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
order: null
|
||||
});
|
||||
|
||||
// Emits 定义
|
||||
interface Emits {
|
||||
(e: 'update:visible', value: boolean): void;
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
// 计算属性
|
||||
const modalVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: value => emit('update:visible', value)
|
||||
});
|
||||
|
||||
/**
|
||||
* 订单状态映射器
|
||||
* @param status 状态值
|
||||
* @returns 状态文本和颜色
|
||||
*/
|
||||
const statusMapper = (status: number): { text: string; color: string } => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return { text: '待处理', color: 'orange' };
|
||||
case 1:
|
||||
return { text: '成功', color: 'green' };
|
||||
case 2:
|
||||
return { text: '失败', color: 'red' };
|
||||
case 3:
|
||||
return { text: '已取消', color: 'gray' };
|
||||
default:
|
||||
return { text: '未知', color: 'gray' };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 支付状态映射器
|
||||
* @param status 支付状态
|
||||
* @returns 支付状态文本和颜色
|
||||
*/
|
||||
const payStatusMapper = (status: number): { text: string; color: string } => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return { text: '未支付', color: 'orange' };
|
||||
case 1:
|
||||
return { text: '已支付', color: 'green' };
|
||||
case 2:
|
||||
return { text: '支付失败', color: 'red' };
|
||||
default:
|
||||
return { text: '未知', color: 'gray' };
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.order-detail {
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.amount-text {
|
||||
color: #165dff;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
:deep(.arco-descriptions-item-label) {
|
||||
font-weight: 600;
|
||||
background-color: #f7f8fa;
|
||||
}
|
||||
</style>
|
||||
@@ -27,11 +27,11 @@
|
||||
placeholder="请选择状态"
|
||||
allow-clear
|
||||
>
|
||||
<a-option :value="0">失效</a-option>
|
||||
<a-option :value="1">正常</a-option>
|
||||
<a-option :value="2">充值过快</a-option>
|
||||
<a-option :value="3">账号受限</a-option>
|
||||
<a-option :value="4">异常</a-option>
|
||||
<a-option :value="0">待登录</a-option>
|
||||
<a-option :value="1">发送验证码</a-option>
|
||||
<a-option :value="2">在线</a-option>
|
||||
<a-option :value="3">已暂停</a-option>
|
||||
<a-option :value="4">已失效</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -88,8 +88,8 @@
|
||||
>
|
||||
<!-- 状态列模板 -->
|
||||
<template #status="{ record }">
|
||||
<a-tag size="small" :color="statusMapper(record.status).color">
|
||||
{{ statusMapper(record.status).text }}
|
||||
<a-tag size="small" :color="statusColorMapper(record.status)">
|
||||
{{ record.statusText || statusMapper(record.status).text }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
@@ -110,13 +110,6 @@
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip content="关联订单">
|
||||
<a-button size="small" @click="showAccountOrders(record)">
|
||||
<template #icon>
|
||||
<icon-order />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table>
|
||||
@@ -133,33 +126,22 @@
|
||||
v-model:visible="state.historyModalVisible"
|
||||
:account-id="state.accountId"
|
||||
/>
|
||||
|
||||
<!-- 账号关联订单弹窗 -->
|
||||
<account-orders
|
||||
v-model:visible="state.ordersModalVisible"
|
||||
:account-id="state.accountId"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, reactive, ref, watchEffect } from 'vue';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { Notification, TableColumnData } from '@arco-design/web-vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { Pagination } from '@/types/global';
|
||||
import { checkTokenFromIframe, checkTokenFromLogin } from '@/utils/auth';
|
||||
import { jdV2AccountClient } from '@/api/index.ts';
|
||||
import type {
|
||||
KamiApiCamelOilV1AccountListItem,
|
||||
KamiApiCamelOilV1AccountListItemStatusEnum
|
||||
} from '@/api/generated/models/index.ts';
|
||||
import type { KamiApiCamelOilV1AccountListItem } from '@/api/generated/models/index.ts';
|
||||
import type {
|
||||
ApiJdV2AccountListGetPageSizeEnum,
|
||||
ApiJdV2AccountListGetStatusEnum
|
||||
} from '@/api/generated/apis/jdv2-account-api';
|
||||
import AccountDetail from './components/detail.vue';
|
||||
import AccountHistory from './components/history.vue';
|
||||
import AccountOrders from './components/account-orders.vue';
|
||||
|
||||
// 基础分页配置
|
||||
const basePagination: Pagination = {
|
||||
@@ -182,13 +164,6 @@ const columns: TableColumnData[] = [
|
||||
return rowIndex + 1 + (pagination.current - 1) * pagination.pageSize;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '账号ID',
|
||||
dataIndex: 'accountId',
|
||||
width: 120,
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '账号名称',
|
||||
dataIndex: 'accountName',
|
||||
@@ -201,21 +176,6 @@ const columns: TableColumnData[] = [
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '当日订单数',
|
||||
dataIndex: 'dailyOrderCount',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '累计订单数',
|
||||
dataIndex: 'totalOrderCount',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '剩余可下单',
|
||||
dataIndex: 'remainingOrders',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '最后使用时间',
|
||||
dataIndex: 'lastUsedAt',
|
||||
@@ -229,6 +189,20 @@ const columns: TableColumnData[] = [
|
||||
slotName: 'status',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '失败原因',
|
||||
dataIndex: 'failureReason',
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'remark',
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createdAt',
|
||||
@@ -254,32 +228,12 @@ const generateSearchFormModel = () => ({
|
||||
status: undefined as ApiJdV2AccountListGetStatusEnum | undefined
|
||||
});
|
||||
|
||||
// 账号数据模型
|
||||
const generateAccountModel = () => ({
|
||||
accountId: '',
|
||||
accountName: '',
|
||||
phone: '',
|
||||
status: undefined as KamiApiCamelOilV1AccountListItemStatusEnum | undefined,
|
||||
statusText: '',
|
||||
dailyOrderCount: 0,
|
||||
totalOrderCount: 0,
|
||||
remainingOrders: 0,
|
||||
lastUsedAt: '',
|
||||
lastLoginAt: '',
|
||||
tokenExpireAt: '',
|
||||
failureReason: '',
|
||||
remark: '',
|
||||
createdAt: '',
|
||||
updatedAt: ''
|
||||
});
|
||||
|
||||
const formModel = ref(generateSearchFormModel());
|
||||
|
||||
// 弹窗状态管理
|
||||
const state = reactive({
|
||||
detailModalVisible: false,
|
||||
historyModalVisible: false,
|
||||
ordersModalVisible: false,
|
||||
accountId: '',
|
||||
account: null as KamiApiCamelOilV1AccountListItem | null
|
||||
});
|
||||
@@ -385,33 +339,54 @@ const showHistoryModal = (record: KamiApiCamelOilV1AccountListItem) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 显示账号关联订单弹窗
|
||||
* @param record 账号记录
|
||||
* 状态颜色映射器
|
||||
* 基于后端Go定义的状态:
|
||||
* - 0: 待登录
|
||||
* - 1: 发送验证码
|
||||
* - 2: 在线
|
||||
* - 3: 已暂停
|
||||
* - 4: 已失效
|
||||
* 使用 Arco Design 标准颜色以兼容主题切换
|
||||
* @param status 状态值
|
||||
* @returns 状态颜色
|
||||
*/
|
||||
const showAccountOrders = (record: KamiApiCamelOilV1AccountListItem) => {
|
||||
state.accountId = record.accountId?.toString() || '';
|
||||
state.ordersModalVisible = true;
|
||||
const statusColorMapper = (status: number): string => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return 'orange'; // 待登录 - 橙色(等待状态)
|
||||
case 1:
|
||||
return 'blue'; // 发送验证码 - 蓝色(进行中状态)
|
||||
case 2:
|
||||
return 'green'; // 在线 - 绿色(正常状态)
|
||||
case 3:
|
||||
return 'orange'; // 已暂停 - 橙色(警告状态)
|
||||
case 4:
|
||||
return 'red'; // 已失效 - 红色(危险状态)
|
||||
default:
|
||||
return 'gray'; // 未知状态 - 灰色(中性状态)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 状态映射器
|
||||
* 状态文本映射器(作为备用)
|
||||
* 基于后端Go定义的状态
|
||||
* @param status 状态值
|
||||
* @returns 状态文本和颜色
|
||||
* @returns 状态文本
|
||||
*/
|
||||
const statusMapper = (status: number): { text: string; color: string } => {
|
||||
const statusMapper = (status: number): { text: string } => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return { text: '失效', color: 'red' };
|
||||
return { text: '待登录' }; // 需要登录验证
|
||||
case 1:
|
||||
return { text: '正常', color: 'green' };
|
||||
return { text: '发送验证码' }; // 正在发送验证码
|
||||
case 2:
|
||||
return { text: '充值过快', color: 'orange' };
|
||||
return { text: '在线' }; // 账户在线,可用
|
||||
case 3:
|
||||
return { text: '账号受限', color: 'red' };
|
||||
return { text: '已暂停' }; // 账户被暂停使用
|
||||
case 4:
|
||||
return { text: '异常', color: 'gray' };
|
||||
return { text: '已失效' }; // 账户已失效
|
||||
default:
|
||||
return { text: '未知', color: 'gray' };
|
||||
return { text: '未知状态' };
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -51,14 +51,6 @@
|
||||
{{ payStatusMapper(order.payStatus).text }}
|
||||
</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="回调状态">
|
||||
<a-tag :color="order.callbackStatus === 1 ? 'green' : 'red'">
|
||||
{{ order.callbackStatus === 1 ? '成功' : '失败' }}
|
||||
</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="回调次数">
|
||||
{{ order.callbackCount || 0 }} 次
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-card>
|
||||
|
||||
@@ -68,42 +60,14 @@
|
||||
<a-descriptions-item label="创建时间">
|
||||
{{ order.createdAt }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="支付时间">
|
||||
{{ order.payTime || '-' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="完成时间">
|
||||
{{ order.completeTime || '-' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="最后回调时间">
|
||||
{{ order.lastCallbackTime || '-' }}
|
||||
<a-descriptions-item label="支付完成时间">
|
||||
{{ order.paidAt || '-' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="更新时间" :span="2">
|
||||
{{ order.updatedAt }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-card>
|
||||
|
||||
<!-- 其他信息 -->
|
||||
<a-card title="其他信息" class="detail-card">
|
||||
<a-descriptions :column="1" bordered>
|
||||
<a-descriptions-item label="回调地址">
|
||||
<code class="callback-url">{{ order.callbackUrl || '-' }}</code>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="请求参数">
|
||||
<pre class="request-params">{{
|
||||
formatJson(order.requestParams) || '-'
|
||||
}}</pre>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="响应参数">
|
||||
<pre class="response-params">{{
|
||||
formatJson(order.responseParams) || '-'
|
||||
}}</pre>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="备注">
|
||||
{{ order.remark || '-' }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-card>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
@@ -137,56 +101,43 @@ const modalVisible = computed({
|
||||
|
||||
/**
|
||||
* 订单状态映射器
|
||||
* 基于后端Go定义的CamelOilOrderStatus
|
||||
* @param status 状态值
|
||||
* @returns 状态文本和颜色
|
||||
*/
|
||||
const statusMapper = (status: number): { text: string; color: string } => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return { text: '待处理', color: 'orange' };
|
||||
return { text: '待处理', color: 'orange' }; // CamelOilOrderStatusPending
|
||||
case 1:
|
||||
return { text: '成功', color: 'green' };
|
||||
return { text: '处理中', color: 'blue' }; // CamelOilOrderStatusProcessing
|
||||
case 2:
|
||||
return { text: '失败', color: 'red' };
|
||||
return { text: '已完成', color: 'green' }; // CamelOilOrderStatusCompleted
|
||||
case 3:
|
||||
return { text: '已取消', color: 'gray' };
|
||||
return { text: '已失败', color: 'red' }; // CamelOilOrderStatusFailed
|
||||
default:
|
||||
return { text: '未知', color: 'gray' };
|
||||
return { text: '未知状态', color: 'gray' };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 支付状态映射器
|
||||
* 基于后端Go定义的CamelOilPayStatus
|
||||
* @param status 支付状态
|
||||
* @returns 支付状态文本和颜色
|
||||
*/
|
||||
const payStatusMapper = (status: number): { text: string; color: string } => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return { text: '未支付', color: 'orange' };
|
||||
return { text: '未支付', color: 'orange' }; // CamelOilPaymentStatusUnpaid
|
||||
case 1:
|
||||
return { text: '已支付', color: 'green' };
|
||||
return { text: '已支付', color: 'green' }; // CamelOilPaymentStatusPaid
|
||||
case 2:
|
||||
return { text: '支付失败', color: 'red' };
|
||||
return { text: '已退款', color: 'blue' }; // CamelOilPaymentStatusRefunded
|
||||
case 3:
|
||||
return { text: '已超时', color: 'red' }; // CamelOilPaymentStatusTimeout
|
||||
default:
|
||||
return { text: '未知', color: 'gray' };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 格式化JSON字符串
|
||||
* @param json JSON对象或字符串
|
||||
* @returns 格式化后的字符串
|
||||
*/
|
||||
const formatJson = (json: any): string => {
|
||||
if (!json) return '';
|
||||
try {
|
||||
if (typeof json === 'string') {
|
||||
return JSON.stringify(JSON.parse(json), null, 2);
|
||||
}
|
||||
return JSON.stringify(json, null, 2);
|
||||
} catch {
|
||||
return String(json);
|
||||
return { text: '未知状态', color: 'gray' };
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -205,48 +156,41 @@ const formatJson = (json: any): string => {
|
||||
}
|
||||
|
||||
.amount-text {
|
||||
color: #165dff;
|
||||
color: rgb(var(--primary-6));
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.actual-amount-text {
|
||||
color: #00b42a;
|
||||
color: rgb(var(--success-6));
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.callback-url {
|
||||
background-color: #f7f8fa;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-family: Monaco, Menlo, 'Ubuntu Mono', monospace;
|
||||
font-size: 12px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.request-params,
|
||||
.response-params {
|
||||
background-color: #f7f8fa;
|
||||
padding: 12px;
|
||||
border-radius: 6px;
|
||||
font-family: Monaco, Menlo, 'Ubuntu Mono', monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:deep(.arco-descriptions-item-label) {
|
||||
font-weight: 600;
|
||||
background-color: #f7f8fa;
|
||||
background-color: var(--color-fill-2);
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body) {
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
|
||||
/* 确保滚动条样式跟随主题 */
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--color-border-3) transparent;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body::-webkit-scrollbar) {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body::-webkit-scrollbar-thumb) {
|
||||
background-color: var(--color-border-3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body::-webkit-scrollbar-track) {
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -21,21 +21,13 @@
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item field="merchantOrderNo" label="商户订单号">
|
||||
<a-form-item field="merchantOrderId" label="商户订单号">
|
||||
<a-input
|
||||
v-model="formModel.merchantOrderNo"
|
||||
v-model="formModel.merchantOrderId"
|
||||
placeholder="请输入商户订单号"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item field="accountPhone" label="充值手机">
|
||||
<a-input
|
||||
v-model="formModel.accountPhone"
|
||||
placeholder="请输入充值手机号"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item field="status" label="订单状态">
|
||||
<a-select
|
||||
@@ -44,9 +36,9 @@
|
||||
allow-clear
|
||||
>
|
||||
<a-option :value="0">待处理</a-option>
|
||||
<a-option :value="1">成功</a-option>
|
||||
<a-option :value="2">失败</a-option>
|
||||
<a-option :value="3">已取消</a-option>
|
||||
<a-option :value="1">处理中</a-option>
|
||||
<a-option :value="2">已完成</a-option>
|
||||
<a-option :value="3">已失败</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
@@ -140,8 +132,8 @@
|
||||
|
||||
<!-- 回调状态模板 -->
|
||||
<template #callbackStatus="{ record }">
|
||||
<a-tag :color="record.callbackStatus === 1 ? 'green' : 'red'">
|
||||
{{ record.callbackStatus === 1 ? '成功' : '失败' }}
|
||||
<a-tag :color="callbackStatusMapper(record.notifyStatus).color">
|
||||
{{ callbackStatusMapper(record.notifyStatus).text }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
@@ -198,6 +190,11 @@ import type {
|
||||
ApiJdV2OrderListGetStatusEnum,
|
||||
ApiJdV2OrderListGetPayStatusEnum
|
||||
} from '@/api/generated/apis/jdv2-order-api';
|
||||
import type {
|
||||
KamiApiCamelOilV1OrderListItemStatusEnum,
|
||||
KamiApiCamelOilV1OrderListItemPayStatusEnum,
|
||||
KamiApiCamelOilV1OrderListItemNotifyStatusEnum
|
||||
} from '@/api/generated/models/index.ts';
|
||||
import OrderDetailModal from './components/order-detail-modal.vue';
|
||||
import OrderHistoryModal from './components/order-history-modal.vue';
|
||||
|
||||
@@ -280,14 +277,9 @@ const columns: TableColumnData[] = [
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '账号ID',
|
||||
dataIndex: 'accountId',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '充值手机',
|
||||
dataIndex: 'accountPhone',
|
||||
width: 130
|
||||
title: '账号名称',
|
||||
dataIndex: 'accountName',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: '订单金额',
|
||||
@@ -309,18 +301,27 @@ const columns: TableColumnData[] = [
|
||||
},
|
||||
{
|
||||
title: '回调状态',
|
||||
dataIndex: 'callbackStatus',
|
||||
dataIndex: 'notifyStatus',
|
||||
slotName: 'callbackStatus',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createdAt',
|
||||
width: 180
|
||||
title: '支付完成时间',
|
||||
dataIndex: 'paidAt',
|
||||
width: 180,
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
dataIndex: 'updatedAt',
|
||||
title: '失败原因',
|
||||
dataIndex: 'failureReason',
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createdAt',
|
||||
width: 180
|
||||
},
|
||||
{
|
||||
@@ -335,8 +336,7 @@ const columns: TableColumnData[] = [
|
||||
// 表单模型
|
||||
const generateFormModel = () => ({
|
||||
orderNo: '',
|
||||
merchantOrderNo: '',
|
||||
accountPhone: '',
|
||||
merchantOrderId: '',
|
||||
status: undefined as ApiJdV2OrderListGetStatusEnum | undefined,
|
||||
payStatus: undefined as ApiJdV2OrderListGetPayStatusEnum | undefined,
|
||||
dateRange: [] as Date[]
|
||||
@@ -456,39 +456,64 @@ const showOrderHistory = (record: KamiApiCamelOilV1OrderListItem) => {
|
||||
|
||||
/**
|
||||
* 订单状态映射器
|
||||
* 基于后端Go定义的CamelOilOrderStatus
|
||||
* @param status 状态值
|
||||
* @returns 状态文本和颜色
|
||||
*/
|
||||
const statusMapper = (status: number): { text: string; color: string } => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return { text: '待处理', color: 'orange' };
|
||||
return { text: '待处理', color: 'orange' }; // CamelOilOrderStatusPending
|
||||
case 1:
|
||||
return { text: '成功', color: 'green' };
|
||||
return { text: '处理中', color: 'blue' }; // CamelOilOrderStatusProcessing
|
||||
case 2:
|
||||
return { text: '失败', color: 'red' };
|
||||
return { text: '已完成', color: 'green' }; // CamelOilOrderStatusCompleted
|
||||
case 3:
|
||||
return { text: '已取消', color: 'gray' };
|
||||
return { text: '已失败', color: 'red' }; // CamelOilOrderStatusFailed
|
||||
default:
|
||||
return { text: '未知', color: 'gray' };
|
||||
return { text: '未知状态', color: 'gray' };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 支付状态映射器
|
||||
* 基于后端Go定义的CamelOilPayStatus
|
||||
* @param status 支付状态
|
||||
* @returns 支付状态文本和颜色
|
||||
*/
|
||||
const payStatusMapper = (status: number): { text: string; color: string } => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return { text: '未支付', color: 'orange' };
|
||||
return { text: '未支付', color: 'orange' }; // CamelOilPaymentStatusUnpaid
|
||||
case 1:
|
||||
return { text: '已支付', color: 'green' };
|
||||
return { text: '已支付', color: 'green' }; // CamelOilPaymentStatusPaid
|
||||
case 2:
|
||||
return { text: '支付失败', color: 'red' };
|
||||
return { text: '已退款', color: 'blue' }; // CamelOilPaymentStatusRefunded
|
||||
case 3:
|
||||
return { text: '已超时', color: 'red' }; // CamelOilPaymentStatusTimeout
|
||||
default:
|
||||
return { text: '未知', color: 'gray' };
|
||||
return { text: '未知状态', color: 'gray' };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 回调状态映射器
|
||||
* 基于后端Go定义的CamelOilNotifyStatus
|
||||
* @param status 回调状态
|
||||
* @returns 回调状态文本和颜色
|
||||
*/
|
||||
const callbackStatusMapper = (
|
||||
status: number
|
||||
): { text: string; color: string } => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return { text: '未回调', color: 'orange' }; // CamelOilCallbackStatusPending
|
||||
case 1:
|
||||
return { text: '回调成功', color: 'green' }; // CamelOilCallbackStatusSuccess
|
||||
case 2:
|
||||
return { text: '回调失败', color: 'red' }; // CamelOilCallbackStatusFailed
|
||||
default:
|
||||
return { text: '未知状态', color: 'gray' };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -516,7 +541,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.amount-text {
|
||||
color: #165dff;
|
||||
color: rgb(var(--primary-6));
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -31,6 +31,13 @@
|
||||
show-word-limit
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item field="phone" label="绑定手机号" required>
|
||||
<a-input
|
||||
v-model="formModel.phone"
|
||||
placeholder="请输入绑定的手机号"
|
||||
:max-length="11"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item field="remark" label="备注">
|
||||
<a-textarea
|
||||
v-model="formModel.remark"
|
||||
@@ -74,6 +81,7 @@ const generateFormModel = () => {
|
||||
return {
|
||||
tokenName: '',
|
||||
tokenValue: '',
|
||||
phone: '',
|
||||
remark: ''
|
||||
};
|
||||
};
|
||||
@@ -89,6 +97,10 @@ const rules = {
|
||||
{ required: true, message: '请输入Token值' },
|
||||
{ min: 1, max: 1000, message: 'Token值长度为1-1000个字符' }
|
||||
],
|
||||
phone: [
|
||||
{ required: true, message: '请输入绑定手机号' },
|
||||
{ match: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码' }
|
||||
],
|
||||
remark: [{ max: 500, message: '备注长度不能超过500个字符' }]
|
||||
};
|
||||
|
||||
@@ -144,8 +156,26 @@ const handleBeforeOk = async () => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 使用 Arco Design 的原生样式,确保主题兼容性 */
|
||||
:deep(.arco-modal-body) {
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
|
||||
/* 确保滚动条样式跟随主题 */
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--color-border-3) transparent;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body::-webkit-scrollbar) {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body::-webkit-scrollbar-thumb) {
|
||||
background-color: var(--color-border-3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body::-webkit-scrollbar-track) {
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -211,8 +211,26 @@ watch(
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 使用 Arco Design 的原生样式,确保主题兼容性 */
|
||||
:deep(.arco-modal-body) {
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
|
||||
/* 确保滚动条样式跟随主题 */
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--color-border-3) transparent;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body::-webkit-scrollbar) {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body::-webkit-scrollbar-thumb) {
|
||||
background-color: var(--color-border-3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
:deep(.arco-modal-body::-webkit-scrollbar-track) {
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -178,12 +178,31 @@ const columns: TableColumnData[] = [
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: 'Token',
|
||||
dataIndex: 'token',
|
||||
title: 'Token值',
|
||||
dataIndex: 'tokenValue',
|
||||
width: 300,
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '绑定手机号',
|
||||
dataIndex: 'phone',
|
||||
width: 130,
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '绑定数量',
|
||||
dataIndex: 'bindCount',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '最后使用时间',
|
||||
dataIndex: 'lastUsedAt',
|
||||
width: 180,
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
@@ -191,20 +210,17 @@ const columns: TableColumnData[] = [
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '创建人',
|
||||
dataIndex: 'createdBy',
|
||||
width: 120
|
||||
title: '备注',
|
||||
dataIndex: 'remark',
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createdAt',
|
||||
width: 180
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
dataIndex: 'updatedAt',
|
||||
width: 180
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operations',
|
||||
@@ -342,4 +358,8 @@ onMounted(() => {
|
||||
.container {
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
|
||||
.general-card {
|
||||
min-height: calc(100vh - 170px);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user