472 lines
12 KiB
Vue
472 lines
12 KiB
Vue
<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="keyword" label="关键字">
|
||
<a-input
|
||
v-model="formModel.keyword"
|
||
placeholder="Cookie ID/账户名称"
|
||
/>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="8">
|
||
<a-form-item field="status" label="状态">
|
||
<a-select
|
||
v-model="formModel.status"
|
||
placeholder="请选择状态"
|
||
allow-clear
|
||
>
|
||
<a-option :value="0">未知</a-option>
|
||
<a-option :value="1">正常</a-option>
|
||
<a-option :value="2">暂停</a-option>
|
||
<a-option :value="3">失效</a-option>
|
||
</a-select>
|
||
</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 type="primary" size="small" @click="showAddModal()">
|
||
<template #icon>
|
||
<icon-plus />
|
||
</template>
|
||
添加Cookie
|
||
</a-button>
|
||
<a-button type="secondary" size="small" @click="showBatchAddModal">
|
||
<template #icon>
|
||
<icon-plus-circle />
|
||
</template>
|
||
批量添加Cookie
|
||
</a-button>
|
||
<a-button
|
||
type="outline"
|
||
status="danger"
|
||
size="small"
|
||
:loading="deleteInvalidLoading"
|
||
@click="handleDeleteInvalidCookies"
|
||
>
|
||
<template #icon>
|
||
<icon-delete />
|
||
</template>
|
||
删除所有失效Cookie
|
||
</a-button>
|
||
</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: 1400 }"
|
||
@page-change="onPageChange"
|
||
@page-size-change="onPageSizeChange"
|
||
>
|
||
<template #status="{ record }">
|
||
<a-tag v-if="record.status === 0" color="gray">未知</a-tag>
|
||
<a-tag v-else-if="record.status === 1" color="green">正常</a-tag>
|
||
<a-tag v-else-if="record.status === 2" color="orange">暂停</a-tag>
|
||
<a-tag v-else-if="record.status === 3" color="red">失效</a-tag>
|
||
<a-tag v-else color="gray">未知</a-tag>
|
||
</template>
|
||
<template #operations="{ record }">
|
||
<a-space size="small">
|
||
<a-tooltip content="查看详情">
|
||
<a-button size="small" @click="showDetail(record)">
|
||
<template #icon>
|
||
<icon-eye />
|
||
</template>
|
||
</a-button>
|
||
</a-tooltip>
|
||
<a-tooltip content="变更记录">
|
||
<a-button size="small" @click="showHistory(record)">
|
||
<template #icon>
|
||
<icon-history />
|
||
</template>
|
||
</a-button>
|
||
</a-tooltip>
|
||
<a-tooltip content="编辑">
|
||
<a-button
|
||
size="small"
|
||
status="warning"
|
||
@click="showEditModal(record)"
|
||
>
|
||
<template #icon>
|
||
<icon-edit />
|
||
</template>
|
||
</a-button>
|
||
</a-tooltip>
|
||
<a-popconfirm
|
||
content="确认删除此Cookie吗?"
|
||
@ok="deleteCookie(record.cookieId)"
|
||
>
|
||
<a-tooltip content="删除">
|
||
<a-button size="small" status="danger">
|
||
<template #icon>
|
||
<icon-delete />
|
||
</template>
|
||
</a-button>
|
||
</a-tooltip>
|
||
</a-popconfirm>
|
||
</a-space>
|
||
</template>
|
||
</a-table>
|
||
</a-card>
|
||
|
||
<!-- 添加/编辑Cookie弹窗 -->
|
||
<cookie-modal
|
||
v-model:visible="modalVisible"
|
||
:cookie-id="currentCookieId"
|
||
:cookie-data="currentCookie"
|
||
@success="handleModalSuccess"
|
||
/>
|
||
|
||
<!-- Cookie详情弹窗 -->
|
||
<cookie-detail
|
||
v-model:visible="detailVisible"
|
||
:cookie-id="currentCookieId"
|
||
/>
|
||
|
||
<!-- Cookie变更记录侧边栏 -->
|
||
<cookie-history-drawer
|
||
v-model:visible="historyVisible"
|
||
:cookie-id="currentCookieId"
|
||
/>
|
||
|
||
<!-- 批量添加Cookie弹窗 -->
|
||
<batch-import-modal
|
||
v-model:visible="batchAddVisible"
|
||
@success="handleBatchAddSuccess"
|
||
/>
|
||
</div>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
import { ref, reactive, onMounted } from 'vue';
|
||
import { Message, Modal } from '@arco-design/web-vue';
|
||
import type { TableColumnData } from '@arco-design/web-vue';
|
||
import useLoading from '@/hooks/loading';
|
||
import { Pagination } from '@/types/global';
|
||
import { jdCookieClient } from '@/api';
|
||
import type {
|
||
KamiApiJdCookieV1CookieAccountInfo,
|
||
KamiApiJdCookieV1DeleteInvalidRes
|
||
} from '@/api/generated';
|
||
import CookieModal from './components/cookie-modal.vue';
|
||
import CookieDetail from './components/cookie-detail.vue';
|
||
import CookieHistoryDrawer from './components/cookie-history-drawer.vue';
|
||
import BatchImportModal from './components/batch-import-modal.vue';
|
||
|
||
const { loading, setLoading } = useLoading(true);
|
||
const deleteInvalidLoading = ref(false);
|
||
|
||
// 分页配置
|
||
const basePagination: Pagination = {
|
||
current: 1,
|
||
pageSize: 20
|
||
};
|
||
const pagination = reactive({ ...basePagination });
|
||
|
||
// 表格列配置
|
||
const columns: TableColumnData[] = [
|
||
{
|
||
title: '序号',
|
||
dataIndex: 'index',
|
||
width: 80,
|
||
render: ({ rowIndex }) => {
|
||
return rowIndex + 1 + (pagination.current - 1) * pagination.pageSize;
|
||
}
|
||
},
|
||
{
|
||
title: 'Cookie ID',
|
||
dataIndex: 'cookieId',
|
||
width: 200,
|
||
ellipsis: true,
|
||
tooltip: true
|
||
},
|
||
{
|
||
title: '账户名称',
|
||
dataIndex: 'accountName',
|
||
width: 150,
|
||
ellipsis: true,
|
||
tooltip: true
|
||
},
|
||
{
|
||
title: '连续失败次数',
|
||
dataIndex: 'failureCount',
|
||
width: 120
|
||
},
|
||
{
|
||
title: '最后使用时间',
|
||
dataIndex: 'lastUsedAt',
|
||
width: 180
|
||
},
|
||
{
|
||
title: '暂停解除时间',
|
||
dataIndex: 'suspendUntil',
|
||
width: 180
|
||
},
|
||
{
|
||
title: '状态',
|
||
dataIndex: 'status',
|
||
slotName: 'status',
|
||
width: 100
|
||
},
|
||
{
|
||
title: '创建时间',
|
||
dataIndex: 'createdAt',
|
||
width: 180
|
||
},
|
||
{
|
||
title: '更新时间',
|
||
dataIndex: 'updatedAt',
|
||
width: 180
|
||
},
|
||
{
|
||
title: '备注',
|
||
dataIndex: 'remark',
|
||
width: 200,
|
||
ellipsis: true,
|
||
tooltip: true
|
||
},
|
||
{
|
||
title: '操作',
|
||
dataIndex: 'operations',
|
||
slotName: 'operations',
|
||
width: 200,
|
||
fixed: 'right'
|
||
}
|
||
];
|
||
|
||
// 类型定义
|
||
interface FormModel {
|
||
keyword: string;
|
||
status: number | undefined;
|
||
}
|
||
|
||
interface QueryParams {
|
||
current?: number;
|
||
pageSize?: number;
|
||
keyword?: string;
|
||
status?: number;
|
||
}
|
||
|
||
// 数据状态
|
||
const renderData = ref<KamiApiJdCookieV1CookieAccountInfo[]>([]);
|
||
const formModel = reactive<FormModel>({
|
||
keyword: '',
|
||
status: undefined
|
||
});
|
||
|
||
// 弹窗状态
|
||
const modalVisible = ref(false);
|
||
const detailVisible = ref(false);
|
||
const historyVisible = ref(false);
|
||
const batchAddVisible = ref(false);
|
||
const currentCookieId = ref('');
|
||
const currentCookie = ref<KamiApiJdCookieV1CookieAccountInfo | null>(null);
|
||
|
||
// 获取Cookie列表
|
||
const fetchData = async (params: QueryParams = {}) => {
|
||
setLoading(true);
|
||
try {
|
||
const response = await jdCookieClient.apiJdCookieAccountListGet({
|
||
page: params.current || pagination.current,
|
||
size: params.pageSize || pagination.pageSize,
|
||
keyword: params.keyword,
|
||
status: params.status
|
||
});
|
||
|
||
renderData.value = response.data.list || [];
|
||
pagination.total = response.data.total || 0;
|
||
} catch (error) {
|
||
Message.error('获取Cookie列表失败');
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
// 搜索
|
||
const search = (): void => {
|
||
fetchData({
|
||
current: 1,
|
||
...formModel
|
||
});
|
||
};
|
||
|
||
// 重置
|
||
const reset = (): void => {
|
||
formModel.keyword = '';
|
||
formModel.status = undefined;
|
||
search();
|
||
};
|
||
|
||
// 分页变化
|
||
const onPageChange = (current: number): void => {
|
||
pagination.current = current;
|
||
fetchData(formModel);
|
||
};
|
||
|
||
const onPageSizeChange = (pageSize: number): void => {
|
||
pagination.pageSize = pageSize;
|
||
pagination.current = 1;
|
||
fetchData(formModel);
|
||
};
|
||
|
||
// 显示添加弹窗
|
||
const showAddModal = (): void => {
|
||
currentCookieId.value = '';
|
||
currentCookie.value = null;
|
||
modalVisible.value = true;
|
||
};
|
||
|
||
// 显示编辑弹窗
|
||
const showEditModal = (record: KamiApiJdCookieV1CookieAccountInfo): void => {
|
||
currentCookieId.value = record.cookieId;
|
||
currentCookie.value = record;
|
||
modalVisible.value = true;
|
||
};
|
||
|
||
// 显示详情
|
||
const showDetail = (record: KamiApiJdCookieV1CookieAccountInfo): void => {
|
||
currentCookieId.value = record.cookieId;
|
||
detailVisible.value = true;
|
||
};
|
||
|
||
// 显示变更记录
|
||
const showHistory = (record: KamiApiJdCookieV1CookieAccountInfo): void => {
|
||
currentCookieId.value = record.cookieId;
|
||
historyVisible.value = true;
|
||
};
|
||
|
||
// 删除Cookie
|
||
const deleteCookie = async (cookieId: string): Promise<void> => {
|
||
try {
|
||
await jdCookieClient.apiJdCookieAccountDeleteDelete({ cookieId });
|
||
Message.success('删除成功');
|
||
search();
|
||
} catch (error) {
|
||
Message.error('删除失败');
|
||
}
|
||
};
|
||
|
||
// 显示批量添加弹窗
|
||
const showBatchAddModal = (): void => {
|
||
batchAddVisible.value = true;
|
||
};
|
||
|
||
// 弹窗成功回调
|
||
const handleModalSuccess = (): void => {
|
||
search();
|
||
};
|
||
|
||
// 批量添加成功回调
|
||
const handleBatchAddSuccess = (): void => {
|
||
search();
|
||
};
|
||
|
||
// 删除所有失效Cookie
|
||
const handleDeleteInvalidCookies = async (): Promise<void> => {
|
||
// 显示确认对话框
|
||
const confirmed = await new Promise<boolean>(resolve => {
|
||
const modal = Modal.confirm({
|
||
title: '确认删除',
|
||
content: '确认要删除所有失效的Cookie吗?此操作不可恢复。',
|
||
okText: '确认删除',
|
||
cancelText: '取消',
|
||
okButtonProps: {
|
||
status: 'danger'
|
||
},
|
||
onOk: () => {
|
||
resolve(true);
|
||
return new Promise(okResolve => {
|
||
setTimeout(() => okResolve(true), 0);
|
||
});
|
||
},
|
||
onCancel: () => {
|
||
resolve(false);
|
||
}
|
||
});
|
||
});
|
||
|
||
if (!confirmed) {
|
||
return;
|
||
}
|
||
|
||
deleteInvalidLoading.value = true;
|
||
try {
|
||
const response =
|
||
await jdCookieClient.apiJdCookieAccountDeleteInvalidDelete();
|
||
const result = response.data;
|
||
|
||
// 显示详细的成功信息
|
||
if (result.deletedCount && result.deletedCount > 0) {
|
||
Message.success(
|
||
`成功删除 ${result.deletedCount} 个失效Cookie${result.failedCount ? `,${result.failedCount} 个删除失败` : ''}`
|
||
);
|
||
|
||
// 如果有删除失败的详情,可以在控制台查看
|
||
if (result.failedCount && result.results) {
|
||
console.group('删除失效Cookie详情:');
|
||
result.results.forEach((item, index) => {
|
||
if (!item.success) {
|
||
console.warn(`${index + 1}. ${item.cookieId}: ${item.message}`);
|
||
}
|
||
});
|
||
console.groupEnd();
|
||
}
|
||
} else {
|
||
Message.info('没有找到失效的Cookie');
|
||
}
|
||
|
||
// 刷新列表
|
||
search();
|
||
} catch (error) {
|
||
console.error('删除失效Cookie失败:', error);
|
||
Message.error('删除失效Cookie失败,请稍后重试');
|
||
} finally {
|
||
deleteInvalidLoading.value = false;
|
||
}
|
||
};
|
||
|
||
onMounted(() => {
|
||
search();
|
||
});
|
||
</script>
|