推送功能添加
deploy-userbase-front / build-and-deploy (push) Successful in 2m50s

This commit is contained in:
chenxing
2026-08-14 09:08:01 +08:00
parent 4077ef64d8
commit 85619785f6
92 changed files with 862 additions and 15442 deletions
+227
View File
@@ -0,0 +1,227 @@
<template>
<div class="main-wrapper">
<div class="main-container">
<div class="search-wrap fix">
<Select v-model="dataParams.appKey" class="ml-12" clearable filterable placeholder="应用" style="width: 180px"
@on-change="handleSearch">
<Option v-for="opt in appOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</Option>
</Select>
<Select v-model="dataParams.interfacePath" class="ml-12" clearable placeholder="接口" style="width: 160px"
@on-change="handleSearch">
<Option v-for="opt in interfaceOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</Option>
</Select>
<Select v-model="dataParams.success" class="ml-12" clearable placeholder="调用结果" style="width: 120px"
@on-change="handleSearch">
<Option :value="1">成功</Option>
<Option :value="0">失败</Option>
</Select>
<DatePicker v-model="startDate" type="date" placeholder="开始时间" format="yyyy-MM-dd" :editable="false"
:clearable="true" class="ml-12" style="width: 140px" @on-change="v => onStartChange(v)" />
<DatePicker v-model="endDate" type="date" placeholder="结束时间" format="yyyy-MM-dd" :editable="false"
:clearable="true" class="ml-12" style="width: 140px" @on-change="v => onEndChange(v)" />
<Button type="primary" class="ml-12" @click="handleSearch">查询</Button>
</div>
<TablePageAlovaNew ref="tableRef" :dataApi="tableApi" :columns="columns" :tableHeight="tableHeight" />
</div>
<PushLogDetailModal v-model="detailVisible" :row="currentRow" />
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { Message } from 'view-ui-plus';
import useCurrentInstance from '@/utils/hook/useCurrentInstance';
import TablePageAlovaNew from '@/components/TablePageAlovaNew.vue';
import Utils from '@/utils';
import PushLogDetailModal from './PushLogDetailModal.vue';
defineOptions({ name: 'PushLog' });
const { $utils } = useCurrentInstance();
const tableRef = ref<InstanceType<typeof TablePageAlovaNew> | null>(null);
const interfaceOptions = [
{ value: 'group/SyncGroup', label: '组全量同步' },
{ value: 'user/SyncUser', label: '用户全量同步' },
{ value: 'group/AddGroup', label: '添加组' },
{ value: 'group/UpdateGroup', label: '更新组' },
{ value: 'group/DeleteGroup', label: '删除组' },
{ value: 'user/AddUser', label: '添加用户' },
{ value: 'user/UpdateUser', label: '更新用户' },
{ value: 'user/DeleteUser', label: '删除用户' },
];
const appOptions = ref<{ value: number; label: string }[]>([]);
interface DataParams {
appKey?: number;
interfacePath?: string;
success?: number;
startTime?: string;
endTime?: string;
}
const dataParams = ref<DataParams>({
appKey: undefined,
interfacePath: undefined,
success: undefined,
startTime: undefined,
endTime: undefined,
});
const startDate = ref<Date | null>(null);
const endDate = ref<Date | null>(null);
function onStartChange(val: string) {
dataParams.value.startTime = val ? `${val} 00:00:00` : undefined;
handleSearch();
}
function onEndChange(val: string) {
dataParams.value.endTime = val ? `${val} 23:59:59` : undefined;
handleSearch();
}
function handleSearch() {
tableRef.value?.refreshData();
}
function clean(obj: Record<string, any>) {
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined && v !== null && v !== ''));
}
const tableApi = (params: { pageIndex: number; pageSize: number }) => {
return (Apis as any).Push.recordList({
params: clean({
appKey: dataParams.value.appKey,
interfacePath: dataParams.value.interfacePath,
success: dataParams.value.success,
startTime: dataParams.value.startTime,
endTime: dataParams.value.endTime,
pageIndex: params.pageIndex,
pageSize: params.pageSize,
}),
cacheFor: null,
});
};
const tableHeight = ref($utils.useTableHeight({ isOperat: false, isPage: true, isSearch: true }));
const columns = [
{ type: 'index', title: '序号', width: 70, align: 'center' },
{
title: '日志时间',
key: 'createdAt',
width: 170,
render: (h: any, { row }: any) =>
h('span', row.createdAt ? Utils.dateFormat(row.createdAt, 'yyyy-MM-dd HH:mm:ss') : '-'),
},
{ title: '应用', key: 'appName', width: 160, ellipsis: true, tooltip: true },
{
title: '接口',
key: 'interfaceLabel',
minWidth: 180,
render: (h: any, { row }: any) =>
h('span', { attrs: { title: row.interfacePath } }, row.interfaceLabel || row.interfacePath || '-'),
},
{
title: '调用结果',
key: 'success',
width: 90,
align: 'center',
render: (h: any, { row }: any) =>
h('span', { class: row.success === 1 ? 'text-success' : 'text-error' }, row.success === 1 ? '成功' : '失败'),
},
{
title: '重试',
key: 'attemptNo',
width: 80,
align: 'center',
render: (h: any, { row }: any) => h('span', `第${row.attemptNo || 1}次`),
},
{
title: '耗时(ms)',
key: 'costMs',
width: 100,
align: 'right',
render: (h: any, { row }: any) => h('span', row.costMs != null ? `${row.costMs}` : '-'),
},
{
title: '操作',
key: 'action',
width: 130,
align: 'center',
fixed: 'right' as const,
render: (h: any, { row }: any) => {
const actions = [
h('a', { style: { color: '#577afb', marginRight: '12px' }, on: { click: () => openDetail(row) } }, '详情'),
];
if (row.success !== 1) {
actions.push(
h('a', { style: { color: '#ed4014' }, on: { click: () => handleRetry(row) } }, '重试')
);
}
return h('span', actions);
},
},
];
const detailVisible = ref(false);
const currentRow = ref<Record<string, any> | null>(null);
function openDetail(row: any) {
currentRow.value = row;
detailVisible.value = true;
}
async function handleRetry(row: any) {
try {
await (Apis as any).Push.retry({ pathParams: { id: row.id }, cacheFor: null });
Message.success('已重新投递,稍后在列表中查看结果');
tableRef.value?.refreshData();
} catch (e: any) {
Message.error(e?.message || '重试失败');
}
}
async function loadApps() {
try {
const res = await (Apis as any).AppSettings.appList({
params: { pageIndex: 1, pageSize: 9999 },
cacheFor: null,
});
const list = (res && res.content) || [];
appOptions.value = list.map((a: any) => ({ value: a.appKey, label: `${a.name}(${a.appKey})` }));
} catch (e: any) {
appOptions.value = [];
}
}
loadApps();
</script>
<style lang="scss" scoped>
.search-wrap {
.ivu-select,
.ivu-input-wrapper,
.ivu-date-picker {
vertical-align: middle;
}
}
.text-success {
color: #19be6b;
}
.text-error {
color: #ed4014;
}
</style>