feat(iframe): add AdminJdAccount and AdminJdOrder routes
Add new routes for managing JD accounts and orders in the admin interface. This includes the addition of new components for handling account details, order history, and summary views. The changes enable administrators to view and manage JD account and order data more effectively.
This commit is contained in:
@@ -205,6 +205,26 @@ const IFRAME: AppRouteRecordRaw = {
|
||||
requiresAuth: false,
|
||||
roles: ['*']
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'AdminJdAccount',
|
||||
name: 'iframeAdminJdAccount',
|
||||
component: () => import('@/views/card-jd-ck/account/index.vue'),
|
||||
meta: {
|
||||
locale: '京东ck账户(管理端)',
|
||||
requiresAuth: false,
|
||||
roles: ['*']
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'AdminJdOrder',
|
||||
name: 'iframeAdminJdOrder',
|
||||
component: () => import('@/views/card-jd-ck/order/index.vue'),
|
||||
meta: {
|
||||
locale: '京东ck订单(管理端)',
|
||||
requiresAuth: false,
|
||||
roles: ['*']
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
237
src/views/card-jd-ck/account/components/add-modal.vue
Normal file
237
src/views/card-jd-ck/account/components/add-modal.vue
Normal file
@@ -0,0 +1,237 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:visible="props.visible"
|
||||
:ok-loading="loading"
|
||||
draggable
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<template #title>{{ props.id === '' ? '新增' : '编辑' }}Cookie</template>
|
||||
<a-form ref="formDataRef" :model="formData">
|
||||
<a-form-item field="name" label="名称" required>
|
||||
<a-input v-model="formData.name" />
|
||||
</a-form-item>
|
||||
<a-form-item field="cookie" label="cookie" required>
|
||||
<a-space
|
||||
direction="vertical"
|
||||
fill
|
||||
style="width: -webkit-fill-available"
|
||||
>
|
||||
<a-textarea
|
||||
v-model="formData.cookie"
|
||||
:autoSize="{ minRows: 3, maxRows: 10 }"
|
||||
/>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="maxAmountLimit"
|
||||
label="充值限制(金额)"
|
||||
tooltip="0表示没有限制"
|
||||
required
|
||||
>
|
||||
<a-input-number v-model="formData.maxAmountLimit" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="maxCountLimit"
|
||||
label="充值限制(次数)"
|
||||
tooltip="0表示没有限制"
|
||||
required
|
||||
>
|
||||
<a-input-number v-model="formData.maxCountLimit" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="status"
|
||||
label="状态"
|
||||
:disabled="![0, 1].includes(formData.status)"
|
||||
>
|
||||
<a-switch
|
||||
v-model="formData.status"
|
||||
:checked-value="1"
|
||||
:unchecked-value="0"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item field="groupId" label="分组">
|
||||
<a-select
|
||||
v-model="formData.groupId"
|
||||
placeholder="请选择分组"
|
||||
:showSearch="true"
|
||||
:filter-option="false"
|
||||
:allowClear="true"
|
||||
>
|
||||
<a-option
|
||||
v-for="(item, index) in groupList"
|
||||
:key="index"
|
||||
:value="item.id"
|
||||
:label="item.name"
|
||||
/>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item field="remark" label="备注">
|
||||
<a-textarea v-model="formData.remark" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<!-- <a-button
|
||||
v-if="props.id === ''"
|
||||
type="secondary"
|
||||
status="warning"
|
||||
:loading="renderData.loading"
|
||||
@click="checkCookie"
|
||||
>
|
||||
检测Cookie
|
||||
</a-button> -->
|
||||
<a-space>
|
||||
<a-button @click="handleCancel">取消</a-button>
|
||||
<a-button type="primary" :loading="loading" @click="handleOk">
|
||||
确定
|
||||
</a-button>
|
||||
<!-- <a-button
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
:disabled="!renderData.cookieStatus && props.id === ''"
|
||||
@click="handleOk"
|
||||
>
|
||||
确定
|
||||
</a-button> -->
|
||||
</a-space>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { FormInstance } from '@arco-design/web-vue';
|
||||
import { ref, PropType, watch, reactive } from 'vue';
|
||||
import { isNull } from '@/utils/is.ts';
|
||||
import { apiClient } from '@/api/index.ts';
|
||||
import {
|
||||
addWalmartCard,
|
||||
detectCookie,
|
||||
updateWalmartCard
|
||||
} from '@/api/card-walmart-account';
|
||||
import { notification } from './component.tsx';
|
||||
import {
|
||||
KamiApiCardInfoWalmartV1AccountCreateReq,
|
||||
KamiApiCardInfoWalmartV1AccountListRecord
|
||||
} from '@/api/generated/index.ts';
|
||||
import type { KamiInternalModelEntityV1CardRedeemAccountGroup } from '@/api/generated/index.ts';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
account: {
|
||||
type: Object as PropType<
|
||||
Required<KamiApiCardInfoWalmartV1AccountListRecord>
|
||||
>,
|
||||
default: null
|
||||
}
|
||||
});
|
||||
|
||||
const generateFormData = () => {
|
||||
return {
|
||||
status: 1,
|
||||
maxAmountLimit: 0,
|
||||
maxCountLimit: 0,
|
||||
cookie: '',
|
||||
remark: '',
|
||||
name: ''
|
||||
};
|
||||
};
|
||||
const formData =
|
||||
ref<KamiApiCardInfoWalmartV1AccountCreateReq>(generateFormData());
|
||||
const formDataRef = ref<FormInstance>();
|
||||
|
||||
const { loading, setLoading } = useLoading(false);
|
||||
const renderData = reactive<{ cookieStatus: boolean; loading: boolean }>({
|
||||
cookieStatus: false,
|
||||
loading: false
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible']);
|
||||
const groupList = ref<KamiInternalModelEntityV1CardRedeemAccountGroup[]>([]);
|
||||
|
||||
const handleOk = () => {
|
||||
if (formData.value) {
|
||||
formDataRef.value.validate().then(async res => {
|
||||
if (res) return;
|
||||
setLoading(true);
|
||||
try {
|
||||
if (props.id === '') {
|
||||
await addWalmartCard(formData.value);
|
||||
} else {
|
||||
await updateWalmartCard({ id: props.id, ...formData.value });
|
||||
}
|
||||
emit('update:visible', false);
|
||||
formData.value = generateFormData();
|
||||
} catch (error) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
watch(
|
||||
() => props.account,
|
||||
val => {
|
||||
if (!isNull(val)) {
|
||||
formData.value = { ...val };
|
||||
}
|
||||
}
|
||||
);
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false);
|
||||
formData.value = generateFormData();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => formData.value.cookie,
|
||||
val => {
|
||||
renderData.cookieStatus = false;
|
||||
}
|
||||
);
|
||||
|
||||
const checkCookie = async () => {
|
||||
renderData.loading = false;
|
||||
try {
|
||||
const cookieResp = await detectCookie({
|
||||
cookie: formData.value.cookie.trim()
|
||||
});
|
||||
if (cookieResp.data.isAvailable) {
|
||||
notification(
|
||||
true,
|
||||
cookieResp.data.nickname,
|
||||
cookieResp.data.balance,
|
||||
cookieResp.data.isExist
|
||||
);
|
||||
renderData.cookieStatus = true;
|
||||
if (props.id === '') {
|
||||
renderData.cookieStatus = !cookieResp.data.isExist;
|
||||
}
|
||||
} else {
|
||||
notification(false);
|
||||
}
|
||||
} finally {
|
||||
renderData.loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
const getAllGroupList = () => {
|
||||
apiClient.apiCardInfoWalmartGroupAllListGet().then(res => {
|
||||
groupList.value = res.data.list;
|
||||
});
|
||||
};
|
||||
getAllGroupList();
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
249
src/views/card-jd-ck/account/components/component.tsx
Normal file
249
src/views/card-jd-ck/account/components/component.tsx
Normal file
@@ -0,0 +1,249 @@
|
||||
import { batchAdd, downloadWalmartCardData } from '@/api/card-walmart-account';
|
||||
import type { KamiApiCardInfoWalmartV1AccountCookieCheckRes } from '@/api/generated';
|
||||
import { getAPIBaseUrl } from '@/api/utils';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { getToken, getTokenFrom } from '@/utils/auth';
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
type FileItem,
|
||||
Message,
|
||||
Modal,
|
||||
Notification,
|
||||
Row,
|
||||
Space,
|
||||
Table,
|
||||
type TableColumnData,
|
||||
type TableData,
|
||||
Tag,
|
||||
Upload
|
||||
} from '@arco-design/web-vue';
|
||||
import { isArray } from 'lodash';
|
||||
import { defineComponent, reactive, ref } from 'vue';
|
||||
|
||||
const tableColumns: TableColumnData[] = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'index',
|
||||
render: (data: { rowIndex: number }) => {
|
||||
return data.rowIndex + 1;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name'
|
||||
},
|
||||
{
|
||||
title: '昵称',
|
||||
dataIndex: 'nickname'
|
||||
},
|
||||
{
|
||||
title: '限额(金额)',
|
||||
dataIndex: 'maxAmountLimit'
|
||||
},
|
||||
{
|
||||
title: '限额(次数)',
|
||||
dataIndex: 'maxCountLimit'
|
||||
},
|
||||
{
|
||||
title: 'cookie',
|
||||
dataIndex: 'cookie',
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '是否存在系统内',
|
||||
dataIndex: 'isExist',
|
||||
render: (data: { record: TableData }) => {
|
||||
let color = 'red';
|
||||
let text = '不存在';
|
||||
if (data.record.isExist) {
|
||||
color = 'green';
|
||||
text = '存在';
|
||||
}
|
||||
return (
|
||||
<Tag size='small' color={color}>
|
||||
{text}
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '是否可用',
|
||||
dataIndex: 'isAvailable',
|
||||
render: (data: { record: TableData }) => {
|
||||
let color = 'red';
|
||||
let text = '不可用';
|
||||
if (data.record.isAvailable) {
|
||||
color = 'green';
|
||||
text = '可用';
|
||||
}
|
||||
return (
|
||||
<Tag size='small' color={color}>
|
||||
{text}
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
export const notification = (
|
||||
isSucceed: boolean = true,
|
||||
nickname: string = '',
|
||||
balance: number = 0,
|
||||
isExist: boolean = false
|
||||
) => {
|
||||
if (isSucceed) {
|
||||
const id = `${Date.now()}`;
|
||||
Notification.success({
|
||||
id,
|
||||
title: '用户信息',
|
||||
content: () => (
|
||||
<div>
|
||||
<div>用户昵称:{nickname}</div>
|
||||
<div>用户余额:{balance}</div>
|
||||
<div>是否存在于系统:{isExist ? '存在' : '不存在'}</div>
|
||||
</div>
|
||||
),
|
||||
closable: true,
|
||||
footer: () => (
|
||||
<Space>
|
||||
<Button
|
||||
status='normal'
|
||||
type='primary'
|
||||
onClick={() => Notification.remove(id)}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
</Space>
|
||||
),
|
||||
duration: 0
|
||||
});
|
||||
} else {
|
||||
const id = `${Date.now()}`;
|
||||
Notification.error({
|
||||
id,
|
||||
title: '用户信息',
|
||||
content: 'cookie无效',
|
||||
footer: () => (
|
||||
<Space>
|
||||
<Button
|
||||
status='danger'
|
||||
type='primary'
|
||||
onClick={() => Notification.remove(id)}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
</Space>
|
||||
),
|
||||
duration: 0
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const batchImportModel = defineComponent({
|
||||
name: 'batchImportWalmartAccountModel',
|
||||
emits: {
|
||||
close: () => {}
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const state = reactive<{
|
||||
visible: boolean;
|
||||
}>({
|
||||
visible: false
|
||||
});
|
||||
const { loading, setLoading } = useLoading(false);
|
||||
const tableData = ref<KamiApiCardInfoWalmartV1AccountCookieCheckRes[]>([]);
|
||||
|
||||
return () => (
|
||||
<>
|
||||
<Button
|
||||
type='primary'
|
||||
size='small'
|
||||
onClick={() => (state.visible = !state.visible)}
|
||||
>
|
||||
导入
|
||||
</Button>
|
||||
<Modal
|
||||
title='批量导入'
|
||||
width='80%'
|
||||
v-model:visible={state.visible}
|
||||
onBeforeOk={async (done: (closed: boolean) => void) => {
|
||||
try {
|
||||
await batchAdd({ list: tableData.value });
|
||||
emit('close');
|
||||
Message.success('上传成功');
|
||||
done(true);
|
||||
} catch {
|
||||
Message.error('上传失败');
|
||||
done(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Row gutter={20}>
|
||||
<Col span={4}>
|
||||
<Space direction='vertical' fill>
|
||||
<Button
|
||||
long
|
||||
status='warning'
|
||||
onClick={() => downloadWalmartCardData()}
|
||||
>
|
||||
下载模板
|
||||
</Button>
|
||||
<Upload
|
||||
disabled={loading.value}
|
||||
onBeforeUpload={async (
|
||||
file: File
|
||||
): Promise<boolean | File> => {
|
||||
setLoading(true);
|
||||
tableData.value = [];
|
||||
return file;
|
||||
}}
|
||||
draggable
|
||||
limit={1}
|
||||
accept='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
onSuccess={(fileItem: FileItem) => {
|
||||
setLoading(false);
|
||||
if (fileItem.response.code === 0) {
|
||||
if (
|
||||
isArray(fileItem.response.data.list) &&
|
||||
fileItem.response.data.list.length > 0
|
||||
) {
|
||||
tableData.value = fileItem.response.data.list;
|
||||
}
|
||||
Message.success(
|
||||
`上传成功${fileItem.response.data?.msg ? ':' + fileItem.response.data?.msg : ''}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
Message.error(`上传失败:${fileItem.response.message}`);
|
||||
}}
|
||||
onError={() => {
|
||||
Message.error('上传失败');
|
||||
setLoading(false);
|
||||
}}
|
||||
action={`${getAPIBaseUrl()}/api/cardInfo/walmart/account/check`}
|
||||
headers={{
|
||||
Authorization: `Bearer ${getToken()}`,
|
||||
tokenFrom: getTokenFrom()
|
||||
}}
|
||||
tip='点击批量上传ck'
|
||||
/>
|
||||
</Space>
|
||||
</Col>
|
||||
<Col span={20}>
|
||||
<Table
|
||||
pagination={false}
|
||||
loading={loading.value}
|
||||
data={tableData.value}
|
||||
columns={tableColumns}
|
||||
></Table>
|
||||
</Col>
|
||||
</Row>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default null;
|
||||
159
src/views/card-jd-ck/account/components/detail.vue
Normal file
159
src/views/card-jd-ck/account/components/detail.vue
Normal file
@@ -0,0 +1,159 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
:visible="drawVisible"
|
||||
width="70%"
|
||||
:footer="false"
|
||||
unmountOnClose
|
||||
@open="openDrawer"
|
||||
@cancel="closeDrawer"
|
||||
>
|
||||
<template #title>账户流水</template>
|
||||
<a-table
|
||||
row-key="id"
|
||||
:loading="loading"
|
||||
:pagination="{
|
||||
current: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
total: pagination.total,
|
||||
pageSizeOptions: [10, 20, 50, 100],
|
||||
showPageSize: true
|
||||
}"
|
||||
:columns="columns"
|
||||
:data="renderData"
|
||||
:bordered="false"
|
||||
size="small"
|
||||
column-resizable:bordered="{cell:true}"
|
||||
@page-change="onPageChange"
|
||||
@page-size-change="onPageSizeChange"
|
||||
/>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { Pagination } from '@/types/global';
|
||||
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { TableColumnData } from '@arco-design/web-vue';
|
||||
import {
|
||||
queryWalmartAccountWalletList,
|
||||
WalmartAccountWalletParams
|
||||
} from '@/api/card-walmart-account';
|
||||
import { KamiInternalModelEntityV1CardRedeemAccountHistory } from '@/api/generated';
|
||||
|
||||
const basePagination: Pagination = {
|
||||
current: 1,
|
||||
pageSize: 50
|
||||
};
|
||||
const pagination = reactive({
|
||||
...basePagination
|
||||
});
|
||||
const columns: TableColumnData[] = [
|
||||
{
|
||||
title: '序号',
|
||||
slotName: 'index',
|
||||
render: ({ rowIndex }) => {
|
||||
return rowIndex + 1 + (pagination.current - 1) * pagination.pageSize;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '订单号',
|
||||
dataIndex: 'orderNo'
|
||||
},
|
||||
{
|
||||
title: '金额',
|
||||
dataIndex: 'amount',
|
||||
render: ({ record }) => {
|
||||
switch (record.operationStatus) {
|
||||
case 'return':
|
||||
return `-${record.amount}`;
|
||||
case 'deduct':
|
||||
return `+${record.amount}`;
|
||||
case 'initialize':
|
||||
return `+${record.amount}`;
|
||||
default:
|
||||
return '未知';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作状态',
|
||||
dataIndex: 'operationStatus',
|
||||
render: ({ record }) => {
|
||||
switch (record.operationStatus) {
|
||||
case 'return':
|
||||
return '退款';
|
||||
case 'deduct':
|
||||
return '加款';
|
||||
case 'initialize':
|
||||
return '初始化';
|
||||
default:
|
||||
return '未知';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '备注',
|
||||
dataIndex: 'remark'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createdAt',
|
||||
slotName: 'createdAt'
|
||||
}
|
||||
];
|
||||
const { loading, setLoading } = useLoading(true);
|
||||
const renderData = ref<KamiInternalModelEntityV1CardRedeemAccountHistory[]>([]);
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
accountId: string;
|
||||
}>();
|
||||
const state = reactive({
|
||||
visible: false
|
||||
});
|
||||
const emits = defineEmits<{
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
onMounted(() => {
|
||||
state.visible = props.visible;
|
||||
});
|
||||
|
||||
const drawVisible = computed(() => props.visible);
|
||||
|
||||
const fetchData = async (
|
||||
params: WalmartAccountWalletParams = {
|
||||
current: 1,
|
||||
pageSize: 50
|
||||
}
|
||||
) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
params.accountId = props.accountId;
|
||||
const {
|
||||
data: { list, total }
|
||||
} = await queryWalmartAccountWalletList(params);
|
||||
renderData.value = list;
|
||||
pagination.current = params.current;
|
||||
pagination.pageSize = params.pageSize;
|
||||
pagination.total = total;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
const onPageChange = (current: number) => {
|
||||
fetchData({ ...pagination, current });
|
||||
};
|
||||
const onPageSizeChange = (pageSize: number) => {
|
||||
fetchData({ ...pagination, pageSize });
|
||||
};
|
||||
const closeDrawer = () => {
|
||||
emits('update:visible', false);
|
||||
};
|
||||
const openDrawer = () => {
|
||||
fetchData();
|
||||
};
|
||||
</script>
|
||||
490
src/views/card-jd-ck/account/index.vue
Normal file
490
src/views/card-jd-ck/account/index.vue
Normal file
@@ -0,0 +1,490 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<Breadcrumb :items="['充值账户管理', '京东Cookie']" />
|
||||
<a-space direction="vertical" fill>
|
||||
<a-card class="general-card" title="京东Cookie管理">
|
||||
<a-row>
|
||||
<a-col :flex="1">
|
||||
<a-form
|
||||
:model="formModel"
|
||||
:label-col-props="{ span: 6 }"
|
||||
:wrapper-col-props="{ span: 18 }"
|
||||
label-align="left"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="8">
|
||||
<a-form-item field="cookie" label="cookie">
|
||||
<a-input
|
||||
v-model="formModel.cookie"
|
||||
placeholder="请输入Cookie"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item field="name" label="名称">
|
||||
<a-input
|
||||
v-model="formModel.name"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item field="nickname" label="沃尔玛昵称">
|
||||
<a-input
|
||||
v-model="formModel.nickname"
|
||||
placeholder="请输入账户昵称"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-col>
|
||||
<a-divider style="height: 42px" direction="vertical" />
|
||||
<a-col flex="172px" style="text-align: right">
|
||||
<a-space direction="horizontal" :size="18">
|
||||
<a-button type="primary" @click="search">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
搜索
|
||||
</a-button>
|
||||
<a-button @click="reset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
重置
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-divider style="margin-top: 0" />
|
||||
<a-row style="justify-content: space-between; margin-bottom: 16px">
|
||||
<a-space>
|
||||
<a-button
|
||||
v-if="checkTokenFromLogin()"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="showAddModel({ id: '', ...generateFormModel() })"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-plus />
|
||||
</template>
|
||||
添加
|
||||
</a-button>
|
||||
<a-button @click="download">
|
||||
<template #icon>
|
||||
<icon-download />
|
||||
</template>
|
||||
导出
|
||||
</a-button>
|
||||
<batchImportModel @close="() => search()" />
|
||||
</a-space>
|
||||
<a-tabs
|
||||
default-active-key=""
|
||||
type="capsule"
|
||||
:onChange="onChangeRadio"
|
||||
animation
|
||||
>
|
||||
<a-tab-pane key="" title="全部" />
|
||||
<a-tab-pane
|
||||
v-for="item in groupList"
|
||||
:key="item.id"
|
||||
:title="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</a-tabs>
|
||||
</a-row>
|
||||
<a-table
|
||||
:loading="loading"
|
||||
:pagination="{
|
||||
current: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
total: pagination.total,
|
||||
pageSizeOptions: [10, 20, 50, 100],
|
||||
showPageSize: true
|
||||
}"
|
||||
:columns="columns"
|
||||
:data="renderData"
|
||||
:scroll="{ x: 1080 }"
|
||||
@page-change="onPageChange"
|
||||
@page-size-change="onPageSizeChange"
|
||||
>
|
||||
<template #status="{ record }">
|
||||
<a-space size="small">
|
||||
<a-switch
|
||||
v-if="[0, 1].includes(record.status)"
|
||||
v-model="record.status"
|
||||
size="small"
|
||||
:checked-value="1"
|
||||
:unchecked-value="0"
|
||||
:beforeChange="
|
||||
newValue => updateCurrentStatus(record, newValue)
|
||||
"
|
||||
/>
|
||||
<a-tag
|
||||
v-else
|
||||
size="small"
|
||||
:color="statusMapper(record.status).color"
|
||||
>
|
||||
{{ statusMapper(record.status).text }}
|
||||
</a-tag>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #operations="{ record }">
|
||||
<a-space size="small">
|
||||
<a-tooltip content="修改">
|
||||
<a-button
|
||||
size="small"
|
||||
status="warning"
|
||||
@click="showAddModel(record)"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-pen />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip content="详情">
|
||||
<a-button size="small" @click="showDetailModel(record)">
|
||||
<template #icon>
|
||||
<icon-list />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-popconfirm
|
||||
type="warning"
|
||||
content="确认刷新账号状态嘛?"
|
||||
@ok="refreshButton(record)"
|
||||
>
|
||||
<a-tooltip content="刷新">
|
||||
<a-button
|
||||
v-if="record.status === 3"
|
||||
size="small"
|
||||
status="success"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-popconfirm>
|
||||
<a-tooltip content="检查账号状态">
|
||||
<a-button
|
||||
size="small"
|
||||
status="warning"
|
||||
@click="checkOne(record.id)"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-check-circle />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip content="删除">
|
||||
<a-button
|
||||
size="small"
|
||||
status="danger"
|
||||
@click="deleteOne(record.id)"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-delete />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
<summary-card />
|
||||
</a-space>
|
||||
<add-modal
|
||||
:id="state.accountId"
|
||||
v-model:visible="state.addModalVisible"
|
||||
:account="state.account"
|
||||
/>
|
||||
<account-detail
|
||||
v-model:visible="state.accountDetailVisible"
|
||||
:accountId="state.accountId"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { Pagination } from '@/types/global';
|
||||
import { checkTokenFromLogin } from '@/utils/auth';
|
||||
import { onMounted, reactive, ref, watchEffect } from 'vue';
|
||||
import { Notification, TableColumnData } from '@arco-design/web-vue';
|
||||
import AddModal from './components/add-modal.vue';
|
||||
import summaryCard from './summary.tsx';
|
||||
import AccountDetail from './components/detail.vue';
|
||||
import {
|
||||
deleteWalmartCard,
|
||||
downloadDataList,
|
||||
refreshWalmartCardStatus,
|
||||
updateWalmartCardStatus,
|
||||
WalmartCardParams,
|
||||
walmartCardUpdateRecord
|
||||
} from '@/api/card-walmart-account';
|
||||
import { batchImportModel } from './components/component.tsx';
|
||||
import {
|
||||
ApiCardInfoWalmartAccountGetListGetPageSizeEnum,
|
||||
KamiApiCardInfoWalmartV1AccountListRecord,
|
||||
KamiInternalModelEntityV1CardRedeemAccountGroup
|
||||
} from '@/api/generated/index.ts';
|
||||
import { apiClient } from '@/api/index.ts';
|
||||
|
||||
const basePagination: Pagination = {
|
||||
current: 1,
|
||||
pageSize: 50
|
||||
};
|
||||
const pagination = reactive({
|
||||
...basePagination
|
||||
});
|
||||
const columns: TableColumnData[] = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'index',
|
||||
render: ({ rowIndex }) => {
|
||||
return rowIndex + 1 + (pagination.current - 1) * pagination.pageSize;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name'
|
||||
},
|
||||
{
|
||||
title: '昵称',
|
||||
dataIndex: 'nickname'
|
||||
},
|
||||
{
|
||||
title: '余额',
|
||||
dataIndex: 'balance'
|
||||
},
|
||||
{
|
||||
title: '今日充值金额',
|
||||
dataIndex: 'amountTodaySum'
|
||||
},
|
||||
{
|
||||
title: '今日充值次数',
|
||||
dataIndex: 'amountTodayCount'
|
||||
},
|
||||
{
|
||||
title: '充值限制(金额)',
|
||||
dataIndex: 'maxAmountLimit'
|
||||
},
|
||||
{
|
||||
title: '充值限制(次数)',
|
||||
dataIndex: 'maxCountLimit'
|
||||
},
|
||||
{
|
||||
title: '累计充值金额',
|
||||
dataIndex: 'amountTotalSum'
|
||||
},
|
||||
{
|
||||
title: '累计充值次数',
|
||||
dataIndex: 'amountTotalCount'
|
||||
},
|
||||
{
|
||||
title: 'ck',
|
||||
dataIndex: 'cookie',
|
||||
ellipsis: true,
|
||||
tooltip: true
|
||||
},
|
||||
{
|
||||
title: '创建人',
|
||||
dataIndex: 'uploadUser.username'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
slotName: 'status'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createdAt',
|
||||
slotName: 'createdAt'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operations',
|
||||
slotName: 'operations',
|
||||
fixed: 'right',
|
||||
width: 220
|
||||
}
|
||||
];
|
||||
const generateFormModel = () => {
|
||||
return {
|
||||
remark: '',
|
||||
name: '',
|
||||
cookie: '',
|
||||
nickname: '',
|
||||
maxAmountLimit: 0,
|
||||
status: 1,
|
||||
createdUserName: '',
|
||||
groupId: null
|
||||
};
|
||||
};
|
||||
const { loading, setLoading } = useLoading(true);
|
||||
const renderData = ref<KamiApiCardInfoWalmartV1AccountListRecord[]>([]);
|
||||
const formModel = ref(generateFormModel());
|
||||
const state = reactive({
|
||||
addModalVisible: false,
|
||||
deployModalVisible: false,
|
||||
accountDetailVisible: false,
|
||||
accountId: '',
|
||||
account: null
|
||||
});
|
||||
|
||||
const groupList = ref<KamiInternalModelEntityV1CardRedeemAccountGroup[]>([]);
|
||||
|
||||
const fetchData = async (
|
||||
params: WalmartCardParams = { current: 1, pageSize: 50 }
|
||||
) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await apiClient.apiCardInfoWalmartAccountGetListGet(
|
||||
params.current,
|
||||
params.pageSize as ApiCardInfoWalmartAccountGetListGetPageSizeEnum,
|
||||
formModel.value.name,
|
||||
formModel.value.nickname,
|
||||
formModel.value.cookie,
|
||||
formModel.value.createdUserName,
|
||||
formModel.value.groupId
|
||||
);
|
||||
renderData.value = res.data.list;
|
||||
pagination.current = params.current;
|
||||
pagination.pageSize = params.pageSize;
|
||||
pagination.total = res.data.total;
|
||||
} catch (err) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
const onPageChange = (current: number) => {
|
||||
fetchData({ ...pagination, current });
|
||||
};
|
||||
const onPageSizeChange = (pageSize: number) => {
|
||||
fetchData({ ...pagination, pageSize });
|
||||
};
|
||||
const search = () => {
|
||||
fetchData({
|
||||
...basePagination,
|
||||
...formModel.value
|
||||
} as unknown as WalmartCardParams);
|
||||
};
|
||||
const reset = () => {
|
||||
formModel.value = generateFormModel();
|
||||
};
|
||||
|
||||
const getAllGroupList = () => {
|
||||
apiClient.apiCardInfoWalmartGroupAllListGet().then(res => {
|
||||
groupList.value = res.data.list;
|
||||
});
|
||||
};
|
||||
|
||||
const deleteOne = async (id: string) => {
|
||||
try {
|
||||
await deleteWalmartCard({ id });
|
||||
} catch {
|
||||
Notification.error({
|
||||
id: 'walmartAccountNotice',
|
||||
content: '删除沃尔玛卡失败',
|
||||
closable: true
|
||||
});
|
||||
} finally {
|
||||
fetchData({ ...pagination });
|
||||
}
|
||||
};
|
||||
|
||||
const checkOne = async (id: string) => {
|
||||
try {
|
||||
const result = await apiClient.apiCardInfoWalmartAccountStatusDetectGet(id);
|
||||
if (result.data.status) {
|
||||
Notification.info({
|
||||
id: 'walmartAccountNotice',
|
||||
content: 'ck有效',
|
||||
closable: true
|
||||
});
|
||||
} else {
|
||||
Notification.error({
|
||||
id: 'walmartAccountNotice',
|
||||
content: 'ck无效',
|
||||
closable: true
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
Notification.error({
|
||||
id: 'walmartAccountNotice',
|
||||
content: '检测沃尔玛卡失败',
|
||||
closable: true
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const showAddModel = (record: walmartCardUpdateRecord) => {
|
||||
state.addModalVisible = true;
|
||||
state.accountId = record.id;
|
||||
state.account = record;
|
||||
if (state.account.groupId === 0) {
|
||||
state.account.groupId = null;
|
||||
}
|
||||
};
|
||||
const showDetailModel = (record: walmartCardUpdateRecord) => {
|
||||
state.accountDetailVisible = true;
|
||||
state.accountId = record.id;
|
||||
};
|
||||
watchEffect(() => {
|
||||
// 目标账户和存储用户不能相同
|
||||
if (!state.addModalVisible) {
|
||||
search();
|
||||
}
|
||||
});
|
||||
const updateCurrentStatus = async (
|
||||
record: walmartCardUpdateRecord,
|
||||
newValue: string | number | boolean
|
||||
) => {
|
||||
await updateWalmartCardStatus({ id: record.id, status: newValue as number });
|
||||
record.status = newValue as number;
|
||||
};
|
||||
|
||||
const statusMapper = (status: number): { text: string; color: string } => {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return { text: '失效', color: 'red' };
|
||||
case 1:
|
||||
return { text: '正常', color: 'green' };
|
||||
case 2:
|
||||
return { text: '充值过快', color: 'orange' };
|
||||
case 3:
|
||||
return { text: '充值限制(用户设置)', color: 'red' };
|
||||
case 4:
|
||||
return { text: '充值限制(其他)', color: 'red' };
|
||||
case 5:
|
||||
return { text: '充值限制(低额)', color: 'red' };
|
||||
case 6:
|
||||
return { text: '充值限制(安全原因)', color: 'red' };
|
||||
case 7:
|
||||
return { text: '充值限制(暂时限制)', color: 'red' };
|
||||
case 8:
|
||||
return { text: '充值限制(平台原因)', color: 'red' };
|
||||
default:
|
||||
return { text: '未知', color: 'gray' };
|
||||
}
|
||||
};
|
||||
const refreshButton = (record: walmartCardUpdateRecord) => {
|
||||
refreshWalmartCardStatus({ id: record.id }).then(() => {
|
||||
fetchData();
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
fetchData();
|
||||
getAllGroupList();
|
||||
});
|
||||
|
||||
const onChangeRadio = (value: string | number | boolean) => {
|
||||
formModel.value.groupId = value as number;
|
||||
// fetchData();
|
||||
};
|
||||
const download = () => {
|
||||
downloadDataList();
|
||||
};
|
||||
</script>
|
||||
213
src/views/card-jd-ck/account/summary.tsx
Normal file
213
src/views/card-jd-ck/account/summary.tsx
Normal file
@@ -0,0 +1,213 @@
|
||||
import { apiClient } from '@/api';
|
||||
import type {
|
||||
KamiApiCardInfoWalmartV1CardRedeemAccountSummary,
|
||||
ApiCardInfoWalmartAccountDailySummaryGetPageSizeEnum
|
||||
} from '@/api/generated';
|
||||
import { handleDownLoadFile } from '@/api/utils';
|
||||
import type { Pagination } from '@/types/global';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Col,
|
||||
DatePicker,
|
||||
Divider,
|
||||
Form,
|
||||
FormItem,
|
||||
Input,
|
||||
Message,
|
||||
Row,
|
||||
Space,
|
||||
Table,
|
||||
type TableColumnData
|
||||
} from '@arco-design/web-vue';
|
||||
import { defineComponent, onMounted, reactive, ref } from 'vue';
|
||||
|
||||
interface IformData {
|
||||
accountId: string;
|
||||
username: string;
|
||||
date: string;
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'walmartSummary',
|
||||
setup() {
|
||||
const generateFormModel = (): IformData => {
|
||||
return {
|
||||
username: '',
|
||||
accountId: '',
|
||||
date: null
|
||||
};
|
||||
};
|
||||
|
||||
const formModel = ref(generateFormModel());
|
||||
const basePagination: Pagination = {
|
||||
current: 1,
|
||||
pageSize: 50
|
||||
};
|
||||
const pagination = reactive({
|
||||
...basePagination
|
||||
});
|
||||
const columns: TableColumnData[] = [
|
||||
{
|
||||
title: '序号',
|
||||
render(data) {
|
||||
return data.rowIndex + 1;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '用户名',
|
||||
dataIndex: 'accountInfo.name'
|
||||
},
|
||||
{
|
||||
title: '余额',
|
||||
dataIndex: 'accountInfo.balance'
|
||||
},
|
||||
{
|
||||
title: '今日充值金额',
|
||||
dataIndex: 'amountTodaySum'
|
||||
},
|
||||
{
|
||||
title: '今日充值次数',
|
||||
dataIndex: 'amountTodayCount'
|
||||
},
|
||||
{
|
||||
title: '累计充值金额',
|
||||
dataIndex: 'amountTotalSum'
|
||||
},
|
||||
{
|
||||
title: '累计充值次数',
|
||||
dataIndex: 'amountTotalCount'
|
||||
},
|
||||
{
|
||||
title: '上传人',
|
||||
dataIndex: 'accountInfo.uploadUser.username'
|
||||
},
|
||||
{
|
||||
title: '日期',
|
||||
dataIndex: 'date'
|
||||
}
|
||||
];
|
||||
const tableData = ref<KamiApiCardInfoWalmartV1CardRedeemAccountSummary[]>(
|
||||
[]
|
||||
);
|
||||
|
||||
const downloadExcel = () => {
|
||||
apiClient
|
||||
.apiCardInfoWalmartAccountSummaryDownloadGet(
|
||||
pagination.current,
|
||||
pagination.pageSize as ApiCardInfoWalmartAccountDailySummaryGetPageSizeEnum,
|
||||
formModel.value.username,
|
||||
formModel.value.date,
|
||||
{
|
||||
responseType: 'blob'
|
||||
}
|
||||
)
|
||||
.then(res => {
|
||||
// 判断是不是blob类型
|
||||
if (!res.data) {
|
||||
Message.error('下载账户统计明细失败');
|
||||
return;
|
||||
}
|
||||
handleDownLoadFile(res.data as any, '沃尔玛账户统计明细.xlsx');
|
||||
});
|
||||
};
|
||||
const fetchData = (
|
||||
page: Pagination = pagination,
|
||||
params: IformData = formModel.value
|
||||
) => {
|
||||
apiClient
|
||||
.apiCardInfoWalmartAccountDailySummaryGet(
|
||||
page.current,
|
||||
page.pageSize as ApiCardInfoWalmartAccountDailySummaryGetPageSizeEnum,
|
||||
params.username,
|
||||
params.date
|
||||
)
|
||||
.then(res => {
|
||||
tableData.value = res.data.list;
|
||||
pagination.total = res.data.total;
|
||||
});
|
||||
};
|
||||
const reset = () => {
|
||||
formModel.value = generateFormModel();
|
||||
};
|
||||
onMounted(() => {
|
||||
fetchData();
|
||||
});
|
||||
return () => (
|
||||
<Card class='general-card' title='核销统计'>
|
||||
<Space direction='vertical' fill>
|
||||
<Row>
|
||||
<Col flex={1}>
|
||||
<Form model={formModel}>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<FormItem field='username' label='用户名'>
|
||||
<Input
|
||||
v-model={formModel.value.username}
|
||||
placeholder='请输入用户名'
|
||||
/>
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col span={16}>
|
||||
<FormItem field='date' label='查询日期'>
|
||||
<DatePicker v-model={formModel.value.date} />
|
||||
</FormItem>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</Col>
|
||||
<Divider style='height: 42px' direction='vertical' />
|
||||
<Space direction='vertical' fill>
|
||||
<Row>
|
||||
<Col flex='172px' style='text-align: right'>
|
||||
<Space direction='horizontal' size={18}>
|
||||
<Button
|
||||
type='primary'
|
||||
onClick={() => fetchData()}
|
||||
v-slots={{
|
||||
icon: () => <icon-search />
|
||||
}}
|
||||
>
|
||||
搜索
|
||||
</Button>
|
||||
<Button
|
||||
onClick={reset}
|
||||
v-slots={{
|
||||
icon: () => <icon-refresh />
|
||||
}}
|
||||
>
|
||||
重置
|
||||
</Button>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col>
|
||||
<Button
|
||||
type='secondary'
|
||||
status='warning'
|
||||
onClick={() => downloadExcel()}
|
||||
v-slots={{
|
||||
icon: () => <icon-download />
|
||||
}}
|
||||
>
|
||||
下载
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Space>
|
||||
</Row>
|
||||
<Table
|
||||
columns={columns}
|
||||
data={tableData.value}
|
||||
pagination={pagination}
|
||||
onPageChange={(current: number) => {
|
||||
pagination.current = current;
|
||||
fetchData();
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
});
|
||||
143
src/views/card-jd-ck/order/components/history.vue
Normal file
143
src/views/card-jd-ck/order/components/history.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
v-model:visible="state.visible"
|
||||
width="40%"
|
||||
title="充值操作日志"
|
||||
:footer="false"
|
||||
unmount-on-close
|
||||
@close="closeDrawer"
|
||||
>
|
||||
<div v-if="props.orderNo !== ''">
|
||||
<a-radio-group
|
||||
v-model="state.isReverse"
|
||||
type="button"
|
||||
size="small"
|
||||
class="sort-btn"
|
||||
>
|
||||
<a-radio :value="true">正序</a-radio>
|
||||
<a-radio :value="false">逆序</a-radio>
|
||||
</a-radio-group>
|
||||
<a-timeline :reverse="state.isReverse">
|
||||
<a-timeline-item
|
||||
v-for="(item, index) in renderData"
|
||||
:key="index"
|
||||
:label="item.createdAt"
|
||||
>
|
||||
<a-space>
|
||||
<span>
|
||||
{{ mapStatus(item.operationStatus) }}
|
||||
</span>
|
||||
<span class="remark">
|
||||
{{ item.remark }}
|
||||
</span>
|
||||
</a-space>
|
||||
</a-timeline-item>
|
||||
</a-timeline>
|
||||
</div>
|
||||
<div v-else>404</div>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { queryWalmartOrderHistoryList } from '@/api/card-walmart-order';
|
||||
import { KamiInternalModelEntityV1CardRedeemOrderHistory } from '@/api/generated';
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
orderNo: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
|
||||
const visible = defineModel<boolean>('visible');
|
||||
|
||||
const state = reactive<{ isReverse: boolean; visible: boolean }>({
|
||||
isReverse: true,
|
||||
visible: false
|
||||
});
|
||||
|
||||
const renderData = ref<KamiInternalModelEntityV1CardRedeemOrderHistory[]>([]);
|
||||
|
||||
const getJDOrderHistoryList = async () => {
|
||||
const res = await queryWalmartOrderHistoryList({
|
||||
orderNo: props.orderNo
|
||||
});
|
||||
renderData.value = res.data.list;
|
||||
};
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
newValue => {
|
||||
state.visible = newValue;
|
||||
if (newValue) {
|
||||
getJDOrderHistoryList();
|
||||
} else {
|
||||
renderData.value = [];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const closeDrawer = () => {
|
||||
visible.value = false;
|
||||
// emit('update:visible', false);
|
||||
};
|
||||
|
||||
const mapStatus = (opeationStatus: number) => {
|
||||
switch (opeationStatus) {
|
||||
case 100:
|
||||
return '充值失败';
|
||||
case 1:
|
||||
return '添加订单';
|
||||
case 2:
|
||||
return '分配账号';
|
||||
case 3:
|
||||
return '充值成功';
|
||||
case 4:
|
||||
return '开始回调';
|
||||
case 5:
|
||||
return '订单退回';
|
||||
case 6:
|
||||
return '订单失败(账户问题)';
|
||||
case 7:
|
||||
return '分配账号失败';
|
||||
case 8:
|
||||
return '订单验证失败';
|
||||
case 9:
|
||||
return '开始回调';
|
||||
case 10:
|
||||
return '回调成功';
|
||||
case 11:
|
||||
return '回调失败 ';
|
||||
case 12:
|
||||
return '订单未处于充值结束状态';
|
||||
case 13:
|
||||
return '用户设置不触发回调';
|
||||
case 14:
|
||||
return '未知状态';
|
||||
case 15:
|
||||
return '服务器错误';
|
||||
case 16:
|
||||
return '开始处理';
|
||||
case 17:
|
||||
return ' 查询卡密余额';
|
||||
case 18:
|
||||
return ' 开始绑卡';
|
||||
case 19:
|
||||
return ' 绑卡结束';
|
||||
default:
|
||||
return '未知状态';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.sort-btn {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.remark {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
</style>
|
||||
457
src/views/card-jd-ck/order/index.vue
Normal file
457
src/views/card-jd-ck/order/index.vue
Normal file
@@ -0,0 +1,457 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<Breadcrumb :items="['充值账户管理', '充值流水']" />
|
||||
<a-card class="general-card" title="流水记录">
|
||||
<a-row>
|
||||
<a-col :flex="1">
|
||||
<a-form
|
||||
:model="formModel"
|
||||
:label-col-props="{ span: 6 }"
|
||||
:wrapper-col-props="{ span: 18 }"
|
||||
label-align="left"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="8">
|
||||
<a-form-item field="giftCardPwd" label="卡密">
|
||||
<a-input
|
||||
v-model="formModel.giftCardPwd"
|
||||
placeholder="请输入卡密"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item field="attach" label="商户订单号">
|
||||
<a-input
|
||||
v-model="formModel.attach"
|
||||
placeholder="请输入商户订单号"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item field="merchantId" label="系统订单号">
|
||||
<a-input
|
||||
v-model="formModel.merchantId"
|
||||
placeholder="请输入系统订单号"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item field="dateRange" label="创建时间">
|
||||
<a-range-picker v-model="formModel.dateRange" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item field="accountNickName" label="账户昵称">
|
||||
<a-input
|
||||
v-model="formModel.accountNickName"
|
||||
placeholder="请输入账户昵称"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item field="accountCk" label="账户Ck">
|
||||
<a-input
|
||||
v-model="formModel.accountCk"
|
||||
placeholder="请输入账户Ck"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-col>
|
||||
<a-divider style="height: 42px" direction="vertical" />
|
||||
<a-col flex="172px" style="text-align: right">
|
||||
<a-space direction="vertical" :size="18">
|
||||
<a-space direction="horizontal" :size="18">
|
||||
<a-button type="primary" @click="search">
|
||||
<template #icon>
|
||||
<icon-search />
|
||||
</template>
|
||||
搜索
|
||||
</a-button>
|
||||
<a-button @click="reset">
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
重置
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-space>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-divider style="margin-top: 0" />
|
||||
<a-space direction="vertical" fill>
|
||||
<a-row style="justify-content: space-between; margin-bottom: 16px">
|
||||
<config v-if="state.showConfig" />
|
||||
<a-tabs
|
||||
default-active-key=""
|
||||
type="capsule"
|
||||
:onChange="onChangeRadio"
|
||||
animation
|
||||
>
|
||||
<a-tab-pane key="" title="全部" />
|
||||
<a-tab-pane
|
||||
v-for="item in groupList"
|
||||
:key="item.id"
|
||||
:title="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</a-tabs>
|
||||
</a-row>
|
||||
<a-table
|
||||
:loading="loading"
|
||||
:pagination="{
|
||||
current: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
total: pagination.total,
|
||||
pageSizeOptions: [10, 20, 50, 100],
|
||||
showPageSize: true,
|
||||
showTotal: true
|
||||
}"
|
||||
table-layout-fixed
|
||||
column-resizable
|
||||
:columns="columns"
|
||||
:data="renderData"
|
||||
:bordered="false"
|
||||
column-resizable:bordered="{cell:true}"
|
||||
@page-change="onPageChange"
|
||||
@page-size-change="onPageSizeChange"
|
||||
>
|
||||
<template #status="{ record }">
|
||||
<a-tag size="small" :color="statusMapper(record.status).color">
|
||||
{{ statusMapper(record.status).text }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template #orderStatus="{ record }">
|
||||
<a-tag
|
||||
v-if="record.orderStatus !== 0"
|
||||
size="small"
|
||||
:color="statusMapper(record.orderStatus).color"
|
||||
>
|
||||
{{ statusMapper(record.orderStatus).text }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template #notifyStatus="{ record }">
|
||||
<a-tag
|
||||
v-if="[1, 2].includes(record.notifyStatus)"
|
||||
size="small"
|
||||
:color="record.notifyStatus === 1 ? 'green' : 'red'"
|
||||
>
|
||||
回调{{ record.notifyStatus === 1 ? '成功' : '失败' }}
|
||||
</a-tag>
|
||||
<a-tag v-else size="small" color="gray">未回调</a-tag>
|
||||
</template>
|
||||
<template #operation="{ record }">
|
||||
<a-space size="small">
|
||||
<a-tooltip v-if="record.status === 7" content="刷新调度">
|
||||
<a-button
|
||||
size="small"
|
||||
status="warning"
|
||||
@click="resetStatus(record.orderNo)"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-refresh />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip content="详情">
|
||||
<a-button
|
||||
size="small"
|
||||
@click="showOrderHistory(record.orderNo)"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-list />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<!-- 回调 -->
|
||||
<a-tooltip content="回调">
|
||||
<a-button
|
||||
v-if="
|
||||
record.notifyStatus !== 1 &&
|
||||
[1, 100, 17].includes(record.orderStatus)
|
||||
"
|
||||
size="small"
|
||||
status="warning"
|
||||
@click="callback(record.orderNo)"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-send />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-space>
|
||||
</a-card>
|
||||
<order-history
|
||||
v-model:visible="state.orderHistoryModalVisible"
|
||||
:order-no="state.selectedOrderNo"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { TableColumnData, Notification, Message } from '@arco-design/web-vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { Pagination } from '@/types/global';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import OrderHistory from './components/history.vue';
|
||||
import { checkTokenFromIframe } from '@/utils/auth';
|
||||
import { walmartCardOrderParams } from '@/api/card-walmart-order.ts';
|
||||
import {
|
||||
ApiCardInfoWalmartOrderListGetPageSizeEnum,
|
||||
KamiInternalModelEntityV1CardRedeemAccountGroup,
|
||||
KamiInternalModelEntityV1CardRedeemOrderInfo
|
||||
} from '@/api/generated/index.ts';
|
||||
import { apiClient } from '@/api/index.ts';
|
||||
|
||||
const basePagination: Pagination = {
|
||||
current: 1,
|
||||
pageSize: 50
|
||||
};
|
||||
const state = reactive({
|
||||
orderHistoryModalVisible: false,
|
||||
selectedOrderNo: '',
|
||||
showConfig: false,
|
||||
activeTableKey: 0
|
||||
});
|
||||
const pagination = reactive({
|
||||
...basePagination
|
||||
});
|
||||
|
||||
const groupList = ref<KamiInternalModelEntityV1CardRedeemAccountGroup[]>([]);
|
||||
const columns: TableColumnData[] = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'index',
|
||||
render: ({ rowIndex }) => {
|
||||
return rowIndex + 1 + (pagination.current - 1) * pagination.pageSize;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '系统订单号',
|
||||
dataIndex: 'merchantId'
|
||||
},
|
||||
{
|
||||
title: '商户订单号',
|
||||
dataIndex: 'attach'
|
||||
},
|
||||
{
|
||||
title: '分配账号',
|
||||
dataIndex: 'accountName'
|
||||
},
|
||||
{
|
||||
title: '卡种',
|
||||
dataIndex: 'cardTypeName'
|
||||
},
|
||||
{
|
||||
title: '卡号',
|
||||
dataIndex: 'cardNo',
|
||||
tooltip: true,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '礼品卡密码',
|
||||
dataIndex: 'giftCardPwd'
|
||||
},
|
||||
{
|
||||
title: '卡面金额',
|
||||
dataIndex: 'orderAmount'
|
||||
},
|
||||
{
|
||||
title: '实际金额',
|
||||
dataIndex: 'actualAmount'
|
||||
},
|
||||
{
|
||||
title: '充值状态',
|
||||
dataIndex: 'status',
|
||||
slotName: 'status'
|
||||
},
|
||||
{
|
||||
title: '状态明细',
|
||||
dataIndex: 'orderStatus',
|
||||
slotName: 'orderStatus'
|
||||
},
|
||||
{
|
||||
title: '回调状态',
|
||||
dataIndex: 'notifyStatus',
|
||||
slotName: 'notifyStatus'
|
||||
},
|
||||
// {
|
||||
// title: '备注',
|
||||
// dataIndex: 'remark'
|
||||
// },
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createdAt'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
slotName: 'operation'
|
||||
}
|
||||
];
|
||||
const generateFormModel = () => {
|
||||
return {
|
||||
merchantId: '',
|
||||
attach: '',
|
||||
giftCardPwd: '',
|
||||
accountNickName: '',
|
||||
accountCk: '',
|
||||
status: null,
|
||||
dateRange: [],
|
||||
groupId: null
|
||||
};
|
||||
};
|
||||
|
||||
const resetStatus = (orderNo: string) => {
|
||||
apiClient.apiCardInfoWalmartOrderStatusResetPut({ id: orderNo }).then(() => {
|
||||
Message.success('重置成功');
|
||||
search();
|
||||
});
|
||||
};
|
||||
|
||||
const { loading, setLoading } = useLoading(true);
|
||||
const renderData = ref<KamiInternalModelEntityV1CardRedeemOrderInfo[]>([]);
|
||||
const formModel = ref<{
|
||||
merchantId: string;
|
||||
accountNickName: string;
|
||||
accountCk: string;
|
||||
attach: string;
|
||||
giftCardPwd: string;
|
||||
status: number;
|
||||
dateRange: string[];
|
||||
groupId: number | null;
|
||||
}>(generateFormModel());
|
||||
|
||||
const fetchData = async (
|
||||
params: walmartCardOrderParams = {
|
||||
current: 1,
|
||||
pageSize: 50
|
||||
}
|
||||
) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await apiClient.apiCardInfoWalmartOrderListGet(
|
||||
pagination.current,
|
||||
pagination.pageSize as ApiCardInfoWalmartOrderListGetPageSizeEnum,
|
||||
formModel.value.giftCardPwd,
|
||||
formModel.value.merchantId,
|
||||
formModel.value.attach,
|
||||
formModel.value.accountNickName,
|
||||
formModel.value.groupId,
|
||||
formModel.value.accountCk,
|
||||
formModel.value.dateRange
|
||||
);
|
||||
renderData.value = res.data.list;
|
||||
pagination.current = params.current;
|
||||
pagination.pageSize = params.pageSize;
|
||||
pagination.total = res.data.total;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onPageChange = (current: number) => {
|
||||
fetchData({ ...pagination, current });
|
||||
};
|
||||
const onPageSizeChange = (pageSize: number) => {
|
||||
fetchData({ ...pagination, pageSize, current: 1 });
|
||||
};
|
||||
const search = () => {
|
||||
fetchData({
|
||||
current: 1,
|
||||
...basePagination,
|
||||
...formModel.value
|
||||
});
|
||||
};
|
||||
const showOrderHistory = (orderNo: string) => {
|
||||
state.orderHistoryModalVisible = true;
|
||||
state.selectedOrderNo = orderNo;
|
||||
};
|
||||
const statusMapper = (status: number): { text: string; color: string } => {
|
||||
switch (status) {
|
||||
case 100:
|
||||
return { text: '失败', color: 'red' };
|
||||
case 1:
|
||||
return { text: '成功', color: 'green' };
|
||||
case 2:
|
||||
return { text: '待处理', color: 'orange' };
|
||||
case 3:
|
||||
return { text: '验证失败', color: 'red' };
|
||||
case 4:
|
||||
return { text: '账号失效', color: 'red' };
|
||||
case 5:
|
||||
return { text: '账号充值频繁', color: 'red' };
|
||||
case 6:
|
||||
return { text: '未知', color: 'gray' };
|
||||
case 7:
|
||||
return { text: '禁用(充值次数超限)', color: 'red' };
|
||||
case 8:
|
||||
return { text: '金额异议(充值成功)', color: 'pinkpurple' };
|
||||
case 9:
|
||||
return { text: '卡密类型错误', color: 'red' };
|
||||
case 10:
|
||||
return { text: '金额异议(充值失败)', color: 'red' };
|
||||
case 11:
|
||||
return { text: '卡密被绑定', color: 'red' };
|
||||
case 12:
|
||||
return { text: '重复绑卡', color: 'red' };
|
||||
case 13:
|
||||
return { text: '账号受限', color: 'red' };
|
||||
case 14:
|
||||
return { text: '匹配账号', color: 'orange' };
|
||||
case 15:
|
||||
return { text: '卡片无效/不存在', color: 'red' };
|
||||
case 16:
|
||||
return { text: '卡片过期', color: 'red' };
|
||||
case 17:
|
||||
return { text: '补卡成功', color: 'green' };
|
||||
case 18:
|
||||
return { text: '开始处理', color: 'green' };
|
||||
case 19:
|
||||
return { text: '订单重复上传', color: 'red' };
|
||||
case 20:
|
||||
return { text: '卡号不符合规则', color: 'red' };
|
||||
default:
|
||||
return { text: '未知', color: 'gray' };
|
||||
}
|
||||
};
|
||||
const reset = () => {
|
||||
formModel.value = generateFormModel();
|
||||
};
|
||||
onMounted(() => {
|
||||
if (checkTokenFromIframe()) {
|
||||
state.showConfig = true;
|
||||
}
|
||||
fetchData({ ...pagination });
|
||||
});
|
||||
const callback = async (orderNo: string) => {
|
||||
try {
|
||||
await apiClient.apiCardInfoWalmartOrderCallbackGet(orderNo);
|
||||
Notification.success({
|
||||
title: '成功',
|
||||
content: '等待回调'
|
||||
});
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const getAllGroupList = () => {
|
||||
apiClient.apiCardInfoWalmartGroupAllListGet().then(res => {
|
||||
groupList.value = res.data.list;
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeRadio = (value: string | number | boolean) => {
|
||||
formModel.value.groupId = value as number;
|
||||
fetchData();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getAllGroupList();
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user