feat(card-walmart-c-trip): 实现沃尔玛 Cookie 管理功能
- 新增沃尔玛 Cookie管理页面,包括搜索、添加、编辑、删除等功能 - 实现批量导入和导出功能 - 添加账户详情和操作日志组件 - 集成通知和表单验证功能
This commit is contained in:
219
src/views/card-walmart-c-trip/account/components/add-modal.vue
Normal file
219
src/views/card-walmart-c-trip/account/components/add-modal.vue
Normal file
@@ -0,0 +1,219 @@
|
||||
<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"
|
||||
:disabled="props.id !== ''"
|
||||
required
|
||||
>
|
||||
<a-space
|
||||
direction="vertical"
|
||||
fill
|
||||
style="
|
||||
width: 100%;
|
||||
width: -moz-available;
|
||||
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="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 { notification } from './component.tsx';
|
||||
import {
|
||||
type KamiApiCardInfoCTripV1AccountCreateReq,
|
||||
KamiApiCardInfoWalmartV1AccountListRecord
|
||||
} from '@/api/generated/index.ts';
|
||||
import { apiClient } from '@/api';
|
||||
|
||||
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<KamiApiCardInfoCTripV1AccountCreateReq>(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 handleOk = () => {
|
||||
if (formData.value) {
|
||||
formDataRef.value.validate().then(async res => {
|
||||
if (res) return;
|
||||
setLoading(true);
|
||||
try {
|
||||
if (props.id === '') {
|
||||
await apiClient.apiCardInfoCTripAccountCreatePost(formData.value);
|
||||
} else {
|
||||
await apiClient.apiCardInfoCTripAccountUpdatePut({
|
||||
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 apiClient.apiCardInfoCTripAccountCheckCookiePost({
|
||||
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;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
257
src/views/card-walmart-c-trip/account/components/component.tsx
Normal file
257
src/views/card-walmart-c-trip/account/components/component.tsx
Normal file
@@ -0,0 +1,257 @@
|
||||
import { getAPIBaseUrl, handleDownLoadFile } 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';
|
||||
import type { KamiApiCardInfoCTripV1AccountCookieCheckRes } from '@/api/generated';
|
||||
import { apiClient } from '@/api';
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 新增下载模板文件的函数
|
||||
const downloadDataList = async () => {
|
||||
const response = await apiClient.apiCardInfoCTripAccountDownloadGet({
|
||||
responseType: 'blob'
|
||||
});
|
||||
handleDownLoadFile(response.data as any, '沃尔玛账号下载数据.xlsx');
|
||||
};
|
||||
|
||||
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<KamiApiCardInfoCTripV1AccountCookieCheckRes[]>([]);
|
||||
|
||||
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 apiClient.apiCardInfoCTripAccountBatchAddPost({
|
||||
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={() => downloadDataList()}
|
||||
>
|
||||
下载模板
|
||||
</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/cTrip/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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
});
|
||||
162
src/views/card-walmart-c-trip/account/components/detail.vue
Normal file
162
src/views/card-walmart-c-trip/account/components/detail.vue
Normal file
@@ -0,0 +1,162 @@
|
||||
<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 {
|
||||
ApiCardInfoCTripAccountGetWalletListGetPageSizeEnum,
|
||||
KamiInternalModelEntityV1CardRedeemAccountHistory
|
||||
} from '@/api/generated';
|
||||
import { apiClient } from '@/api';
|
||||
|
||||
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: Pagination = {
|
||||
current: 1,
|
||||
pageSize: 50
|
||||
}
|
||||
) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const {
|
||||
data: { list, total }
|
||||
} = await apiClient.apiCardInfoCTripAccountGetWalletListGet(
|
||||
params.current,
|
||||
params.pageSize as ApiCardInfoCTripAccountGetWalletListGetPageSizeEnum,
|
||||
props.accountId
|
||||
);
|
||||
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>
|
||||
416
src/views/card-walmart-c-trip/account/index.vue
Normal file
416
src/views/card-walmart-c-trip/account/index.vue
Normal file
@@ -0,0 +1,416 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<Breadcrumb :items="['充值账户管理', '沃尔玛Cookie']" />
|
||||
<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="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-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
|
||||
v-if="checkTokenFromIframe()"
|
||||
size="small"
|
||||
status="danger"
|
||||
@click="deleteOne(record.id)"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-delete />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
<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 { checkTokenFromIframe, 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 AccountDetail from './components/detail.vue';
|
||||
import { batchImportModel } from './components/component.tsx';
|
||||
import { apiClient } from '@/api';
|
||||
import {
|
||||
ApiCardInfoCTripOrderListGetPageSizeEnum,
|
||||
KamiApiCardInfoCTripV1AccountListRecord
|
||||
} from '@/api/generated';
|
||||
import { handleDownLoadFile } from '@/api/utils.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
|
||||
};
|
||||
};
|
||||
|
||||
interface formDataType {
|
||||
remark: string;
|
||||
name: string;
|
||||
cookie: string;
|
||||
nickname: string;
|
||||
maxAmountLimit: number;
|
||||
status: number;
|
||||
}
|
||||
|
||||
const { loading, setLoading } = useLoading(true);
|
||||
const renderData = ref<KamiApiCardInfoCTripV1AccountListRecord[]>([]);
|
||||
const formModel = ref<formDataType>(generateFormModel());
|
||||
const state = reactive({
|
||||
addModalVisible: false,
|
||||
deployModalVisible: false,
|
||||
accountDetailVisible: false,
|
||||
accountId: '',
|
||||
account: null
|
||||
});
|
||||
const fetchData = async (
|
||||
page: Pagination = { current: 1, pageSize: 50 },
|
||||
formData: Partial<formDataType> = {}
|
||||
) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const {
|
||||
data: { list, total }
|
||||
} = await apiClient.apiCardInfoCTripOrderListGet(
|
||||
page.current,
|
||||
page.pageSize as ApiCardInfoCTripOrderListGetPageSizeEnum
|
||||
);
|
||||
renderData.value = list;
|
||||
pagination.current = page.current;
|
||||
pagination.pageSize = page.pageSize;
|
||||
pagination.total = 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);
|
||||
};
|
||||
const reset = () => {
|
||||
formModel.value = generateFormModel();
|
||||
};
|
||||
|
||||
const deleteOne = async (id: string) => {
|
||||
try {
|
||||
await apiClient.apiCardInfoCTripAccountDeleteDelete(id);
|
||||
} catch {
|
||||
Notification.error({
|
||||
id: 'walmartAccountNotice',
|
||||
content: '删除沃尔玛卡失败',
|
||||
closable: true
|
||||
});
|
||||
} finally {
|
||||
await fetchData({ ...pagination });
|
||||
}
|
||||
};
|
||||
|
||||
const showAddModel = (record: KamiApiCardInfoCTripV1AccountListRecord) => {
|
||||
state.addModalVisible = true;
|
||||
state.accountId = record.id;
|
||||
state.account = record;
|
||||
};
|
||||
const showDetailModel = (record: KamiApiCardInfoCTripV1AccountListRecord) => {
|
||||
state.accountDetailVisible = true;
|
||||
state.accountId = record.id;
|
||||
};
|
||||
watchEffect(() => {
|
||||
// 目标账户和存储用户不能相同
|
||||
if (!state.addModalVisible) {
|
||||
search();
|
||||
}
|
||||
});
|
||||
const updateCurrentStatus = async (
|
||||
record: KamiApiCardInfoCTripV1AccountListRecord,
|
||||
newValue: string | number | boolean
|
||||
) => {
|
||||
await apiClient.apiCardInfoCTripAccountUpdateStatusPut({
|
||||
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: KamiApiCardInfoCTripV1AccountListRecord) => {
|
||||
apiClient
|
||||
.apiCardInfoCTripAccountRefreshStatusPut({ id: record.id })
|
||||
.then(() => {
|
||||
fetchData();
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
fetchData();
|
||||
});
|
||||
const download = () => {
|
||||
apiClient.apiCardInfoCTripAccountDownloadGet().then(res => {
|
||||
handleDownLoadFile(res.data as any, '沃尔玛卡列表.xlsx');
|
||||
});
|
||||
};
|
||||
</script>
|
||||
129
src/views/card-walmart-c-trip/order-summary/index.vue
Normal file
129
src/views/card-walmart-c-trip/order-summary/index.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<Breadcrumb :items="['订单', '订单汇总']" />
|
||||
<a-card class="general-card" title="订单汇总">
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:loading="loading"
|
||||
:data="renderData"
|
||||
:pagination="{
|
||||
current: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
total: pagination.total,
|
||||
pageSizeOptions: [10, 20, 50, 100],
|
||||
showPageSize: true
|
||||
}"
|
||||
:bordered="false"
|
||||
column-resizable:bordered="{cell:true}"
|
||||
@page-change="onPageChange"
|
||||
@page-size-change="onPageSizeChange"
|
||||
>
|
||||
<template #index="{ rowIndex }">
|
||||
{{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Pagination } from '@/types/global';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { OrderSummaryRecord, queryOrderSummaryList } from '@/api/order-summary';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { TableColumnData } from '@arco-design/web-vue/es/table';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
const route = useRoute();
|
||||
const basePagination: Pagination = {
|
||||
current: 1,
|
||||
pageSize: 50
|
||||
};
|
||||
const columns: TableColumnData[] = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'index',
|
||||
slotName: 'index'
|
||||
},
|
||||
{
|
||||
title: '商户ID',
|
||||
dataIndex: 'merchantUid'
|
||||
},
|
||||
{
|
||||
title: '商户名称',
|
||||
dataIndex: 'merchantName'
|
||||
},
|
||||
{
|
||||
title: '成交金额(面额)',
|
||||
dataIndex: 'succeedShowAmount'
|
||||
},
|
||||
{
|
||||
title: '成交金额(实际)',
|
||||
dataIndex: 'succeedFactAmount'
|
||||
},
|
||||
{
|
||||
title: '成交数量',
|
||||
dataIndex: 'succeedCount'
|
||||
},
|
||||
{
|
||||
title: '总额(面额)',
|
||||
dataIndex: 'totalShowAmount'
|
||||
},
|
||||
{
|
||||
title: '总额(实际)',
|
||||
dataIndex: 'totalFactAmount'
|
||||
},
|
||||
{
|
||||
title: '订单总数',
|
||||
dataIndex: 'totalCount'
|
||||
},
|
||||
{
|
||||
title: '失败数量',
|
||||
dataIndex: 'failedCount'
|
||||
},
|
||||
{
|
||||
title: '失败(未填写)订单数量',
|
||||
dataIndex: 'waitedCount'
|
||||
},
|
||||
{
|
||||
title: '成功率',
|
||||
dataIndex: 'rate'
|
||||
},
|
||||
{
|
||||
title: '日期',
|
||||
dataIndex: 'date'
|
||||
}
|
||||
];
|
||||
const { loading, setLoading } = useLoading(true);
|
||||
const pagination = reactive({
|
||||
...basePagination
|
||||
});
|
||||
const renderData = ref<OrderSummaryRecord[]>([]);
|
||||
|
||||
const fetchData = async (
|
||||
params: { current: number; pageSize: number } = basePagination
|
||||
) => {
|
||||
setLoading(true);
|
||||
const {
|
||||
data: { list, total }
|
||||
} = await queryOrderSummaryList({
|
||||
...params,
|
||||
roadUid: route.params.roadUid as string
|
||||
});
|
||||
console.log(params);
|
||||
renderData.value = list;
|
||||
pagination.current = params.current;
|
||||
pagination.pageSize = params.pageSize;
|
||||
pagination.total = total;
|
||||
setLoading(false);
|
||||
};
|
||||
const onPageChange = (current: number) => {
|
||||
fetchData({ ...pagination, current });
|
||||
};
|
||||
const onPageSizeChange = (pageSize: number) => {
|
||||
fetchData({ ...pagination, pageSize });
|
||||
};
|
||||
onMounted(() => {
|
||||
fetchData();
|
||||
});
|
||||
</script>
|
||||
113
src/views/card-walmart-c-trip/order/components/config.tsx
Normal file
113
src/views/card-walmart-c-trip/order/components/config.tsx
Normal file
@@ -0,0 +1,113 @@
|
||||
import { apiClient } from '@/api';
|
||||
import { getWalmartConfig } from '@/api/card-walmart-order';
|
||||
import type { KamiApiCardInfoWalmartV1RedeemConfigGetRes } from '@/api/generated';
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
Form,
|
||||
FormItem,
|
||||
Switch,
|
||||
type FormInstance,
|
||||
InputNumber
|
||||
} from '@arco-design/web-vue';
|
||||
import { defineComponent, onMounted, reactive, ref } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'cardJdConfig',
|
||||
setup() {
|
||||
const state = reactive<{
|
||||
visible: boolean;
|
||||
}>({
|
||||
visible: false
|
||||
});
|
||||
const formData = ref<Required<KamiApiCardInfoWalmartV1RedeemConfigGetRes>>({
|
||||
isAllowDifferentAmount: true,
|
||||
isAllowDifferentSucceedCallback: true,
|
||||
isAllowDifferentFailCallback: true,
|
||||
redeemCardMinAmount: 0,
|
||||
isAllowCompensatedCallback: true,
|
||||
redeemCardRate: 100
|
||||
});
|
||||
const formRef = ref<FormInstance>();
|
||||
onMounted(() => {
|
||||
getWalmartConfig().then(res => {
|
||||
formData.value = res.data;
|
||||
});
|
||||
});
|
||||
return () => (
|
||||
<>
|
||||
<Button
|
||||
type='primary'
|
||||
status='normal'
|
||||
onClick={() => {
|
||||
state.visible = !state.visible;
|
||||
getWalmartConfig().then(res => {
|
||||
formData.value = res.data;
|
||||
});
|
||||
}}
|
||||
>
|
||||
设置
|
||||
</Button>
|
||||
<Modal
|
||||
title='充值设置'
|
||||
v-model:visible={state.visible}
|
||||
onBeforeOk={async (done: (closed: boolean) => void) => {
|
||||
if (await formRef.value.validate()) {
|
||||
done(false);
|
||||
}
|
||||
try {
|
||||
await apiClient.apiCardInfoWalmartConfigSetPost(formData.value);
|
||||
done(true);
|
||||
} catch {
|
||||
done(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Form
|
||||
ref={formRef}
|
||||
model={formData}
|
||||
labelColProps={{ span: 12 }}
|
||||
wrapperColProps={{ span: 12 }}
|
||||
>
|
||||
<FormItem field='redeemCardMinAmount' label='最小充值金额' required>
|
||||
<InputNumber v-model={formData.value.redeemCardMinAmount} />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
field='isAllowDifferentAmount'
|
||||
label='是否兑换(金额异议)'
|
||||
required
|
||||
>
|
||||
<Switch v-model={formData.value.isAllowDifferentAmount} />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
field='isAllowDifferentSucceedCallback'
|
||||
label='成功是否回调(金额异议)'
|
||||
required
|
||||
>
|
||||
<Switch
|
||||
v-model={formData.value.isAllowDifferentSucceedCallback}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
field='isAllowDifferentFailCallback'
|
||||
label='失败是否回调(金额异议)'
|
||||
required
|
||||
>
|
||||
<Switch v-model={formData.value.isAllowDifferentFailCallback} />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
field='isAllowCompensatedCallback'
|
||||
label='补卡自动回调'
|
||||
required
|
||||
>
|
||||
<Switch v-model={formData.value.isAllowCompensatedCallback} />
|
||||
</FormItem>
|
||||
<FormItem field='redeemCardRate' label='充值速率(单/分钟)' required>
|
||||
<InputNumber v-model={formData.value.redeemCardRate} />
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
});
|
||||
137
src/views/card-walmart-c-trip/order/components/history.vue
Normal file
137
src/views/card-walmart-c-trip/order/components/history.vue
Normal file
@@ -0,0 +1,137 @@
|
||||
<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 '开始处理';
|
||||
default:
|
||||
return '未知状态';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.sort-btn {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.remark {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
</style>
|
||||
394
src/views/card-walmart-c-trip/order/index.vue
Normal file
394
src/views/card-walmart-c-trip/order/index.vue
Normal file
@@ -0,0 +1,394 @@
|
||||
<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>
|
||||
<config v-if="state.showConfig" />
|
||||
<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 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 } from '@arco-design/web-vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { Pagination } from '@/types/global';
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import config from './components/config.tsx';
|
||||
import OrderHistory from './components/history.vue';
|
||||
import { checkTokenFromIframe } from '@/utils/auth';
|
||||
import {
|
||||
queryWalmartCardOrderList,
|
||||
walmartCardOrderParams
|
||||
} from '@/api/card-walmart-order.ts';
|
||||
import { 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
|
||||
});
|
||||
const pagination = reactive({
|
||||
...basePagination
|
||||
});
|
||||
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: []
|
||||
};
|
||||
};
|
||||
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: Date[];
|
||||
}>(generateFormModel());
|
||||
|
||||
const fetchData = async (
|
||||
params: walmartCardOrderParams = {
|
||||
current: 1,
|
||||
pageSize: 50
|
||||
}
|
||||
) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const {
|
||||
data: { list, total }
|
||||
} = await queryWalmartCardOrderList(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, current: 1 });
|
||||
};
|
||||
const search = () => {
|
||||
fetchData({
|
||||
...basePagination,
|
||||
...formModel.value,
|
||||
current: 1
|
||||
});
|
||||
};
|
||||
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) {}
|
||||
};
|
||||
</script>
|
||||
@@ -1,4 +1,3 @@
|
||||
// import { batchAdd, downloadJDCardData } from '@/api/card-jd-account';
|
||||
import { batchAdd, downloadDataList } from '@/api/card-walmart-account';
|
||||
import type { KamiApiCardInfoWalmartV1AccountCookieCheckRes } from '@/api/generated';
|
||||
import { getAPIBaseUrl } from '@/api/utils';
|
||||
|
||||
Reference in New Issue
Block a user