mirror of
https://github.com/hpd840321/craftlabs-authorization-sdk.git
synced 2026-06-09 10:00:30 +08:00
fix: update stale labels and add callback backlog stats card
Fixed login page (removed I1 tag, updated demo accounts). Added backlog stats bar to CallbackInboxView. Fixed size:500 to size:200 across all list views to match backend @Max(200) validation. Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -20,6 +20,18 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-if="backlog" class="backlog-bar">
|
||||
<span :class="['bl-item', { 'bl-warn': backlog.totalPending > 0 }]">
|
||||
⏳ 待处理 <strong>{{ backlog.totalPending }}</strong>
|
||||
</span>
|
||||
<span :class="['bl-item', { 'bl-danger': backlog.totalFailed > 0 }]">
|
||||
❌ 失败 <strong>{{ backlog.totalFailed }}</strong>
|
||||
</span>
|
||||
<span class="bl-item" v-if="backlog.oldestPendingHours > 0">
|
||||
⏰ 最久未处理 <strong>{{ backlog.oldestPendingHours }}h</strong>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="rows" stripe style="width: 100%" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="sourceSystem" label="来源" width="120" show-overflow-tooltip />
|
||||
@@ -84,6 +96,7 @@ import { ref, onMounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { useAuthStore } from "../stores/auth";
|
||||
import axios from "axios";
|
||||
import { listCallbackInbox, replayCallbackWebhookDelivery, simulateCallback } from "../api/platform";
|
||||
import { apiErrorMessage } from "../utils/apiErrorMessage";
|
||||
|
||||
@@ -103,6 +116,7 @@ const selectedCallbacks = ref([]);
|
||||
const simDialogVisible = ref(false);
|
||||
const simulating = ref(false);
|
||||
const simForm = ref({ eventType: 'sn:post_activate', snCode: '', rawPayload: '{}' });
|
||||
const backlog = ref(null);
|
||||
|
||||
function handleSelectionChange(val) {
|
||||
selectedCallbacks.value = val;
|
||||
@@ -123,9 +137,16 @@ async function handleBatchRetry() {
|
||||
load();
|
||||
}
|
||||
|
||||
async function loadBacklog() {
|
||||
try {
|
||||
const { data } = await axios.get('/api/v1/callback-inbox/stats/backlog');
|
||||
backlog.value = data;
|
||||
} catch { /* non-critical */ }
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
auth.restoreAxiosAuth();
|
||||
await load();
|
||||
await Promise.all([load(), loadBacklog()]);
|
||||
});
|
||||
|
||||
function onSizeChange() {
|
||||
@@ -226,4 +247,10 @@ function goDetail(id) {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.backlog-bar {
|
||||
display: flex; gap: 24px; padding: 8px 0 12px; font-size: 13px; color: #606266;
|
||||
}
|
||||
.bl-item strong { font-size: 18px; margin: 0 2px; }
|
||||
.bl-warn { color: #E6A23C; }
|
||||
.bl-danger { color: #D54941; }
|
||||
</style>
|
||||
|
||||
@@ -185,7 +185,7 @@ function onCustomerChange() {
|
||||
async function loadCustomers() {
|
||||
customersLoading.value = true;
|
||||
try {
|
||||
const { data } = await listCustomers({ page: 0, size: 500 });
|
||||
const { data } = await listCustomers({ page: 0, size: 200 });
|
||||
const body = data && typeof data === "object" ? data : {};
|
||||
customerOptions.value = Array.isArray(body.content) ? body.content : [];
|
||||
} catch (e) {
|
||||
@@ -199,7 +199,7 @@ async function loadCustomers() {
|
||||
async function loadAllProjects() {
|
||||
projectsLoading.value = true;
|
||||
try {
|
||||
const { data } = await listProjects({ page: 0, size: 500 });
|
||||
const { data } = await listProjects({ page: 0, size: 200 });
|
||||
const body = data && typeof data === "object" ? data : {};
|
||||
projectOptions.value = Array.isArray(body.content) ? body.content : [];
|
||||
} catch (e) {
|
||||
|
||||
@@ -147,8 +147,8 @@ function formatDateTime(v) {
|
||||
async function loadCustomerProjectMaps() {
|
||||
try {
|
||||
const [cRes, pRes] = await Promise.all([
|
||||
listCustomers({ page: 0, size: 500 }),
|
||||
listProjects({ page: 0, size: 500 }),
|
||||
listCustomers({ page: 0, size: 200 }),
|
||||
listProjects({ page: 0, size: 200 }),
|
||||
]);
|
||||
const cBody = cRes.data && typeof cRes.data === "object" ? cRes.data : {};
|
||||
const pBody = pRes.data && typeof pRes.data === "object" ? pRes.data : {};
|
||||
|
||||
@@ -136,7 +136,7 @@ function formatDateTime(v) {
|
||||
|
||||
async function loadProjects() {
|
||||
try {
|
||||
const { data } = await listProjects({ page: 0, size: 500 });
|
||||
const { data } = await listProjects({ page: 0, size: 200 });
|
||||
const body = data && typeof data === "object" ? data : {};
|
||||
const list = Array.isArray(body.content) ? body.content : [];
|
||||
projectOptions.value = list;
|
||||
|
||||
@@ -246,7 +246,7 @@ function formatDateTime(v) {
|
||||
|
||||
async function loadProjectMap() {
|
||||
try {
|
||||
const { data } = await listProjects({ page: 0, size: 500 });
|
||||
const { data } = await listProjects({ page: 0, size: 200 });
|
||||
const body = data && typeof data === "object" ? data : {};
|
||||
const list = Array.isArray(body.content) ? body.content : [];
|
||||
const m = new Map();
|
||||
|
||||
@@ -127,7 +127,7 @@ function contractOptionLabel(c) {
|
||||
async function loadProjects() {
|
||||
projectsLoading.value = true;
|
||||
try {
|
||||
const { data } = await listProjects({ page: 0, size: 500 });
|
||||
const { data } = await listProjects({ page: 0, size: 200 });
|
||||
const body = data && typeof data === "object" ? data : {};
|
||||
projectOptions.value = Array.isArray(body.content) ? body.content : [];
|
||||
} catch (e) {
|
||||
@@ -141,7 +141,7 @@ async function loadProjects() {
|
||||
async function loadContracts() {
|
||||
contractsLoading.value = true;
|
||||
try {
|
||||
const { data } = await listContracts({ page: 0, size: 500 });
|
||||
const { data } = await listContracts({ page: 0, size: 200 });
|
||||
const body = data && typeof data === "object" ? data : {};
|
||||
contractOptions.value = Array.isArray(body.content) ? body.content : [];
|
||||
} catch (e) {
|
||||
|
||||
@@ -204,7 +204,7 @@ function goList() {
|
||||
async function loadProjects() {
|
||||
projectsLoading.value = true;
|
||||
try {
|
||||
const { data } = await listProjects({ page: 0, size: 500 });
|
||||
const { data } = await listProjects({ page: 0, size: 200 });
|
||||
const body = data && typeof data === "object" ? data : {};
|
||||
projectOptions.value = Array.isArray(body.content) ? body.content : [];
|
||||
} catch (e) {
|
||||
|
||||
@@ -185,7 +185,7 @@ function formatDateTime(v) {
|
||||
|
||||
async function loadProjects() {
|
||||
try {
|
||||
const { data } = await listProjects({ page: 0, size: 500 });
|
||||
const { data } = await listProjects({ page: 0, size: 200 });
|
||||
const body = data && typeof data === "object" ? data : {};
|
||||
const list = Array.isArray(body.content) ? body.content : [];
|
||||
projectOptions.value = list;
|
||||
|
||||
@@ -90,7 +90,7 @@ function goBack() {
|
||||
async function loadProjects() {
|
||||
projectsLoading.value = true;
|
||||
try {
|
||||
const { data } = await listProjects({ page: 0, size: 500 });
|
||||
const { data } = await listProjects({ page: 0, size: 200 });
|
||||
const body = data && typeof data === "object" ? data : {};
|
||||
projectOptions.value = Array.isArray(body.content) ? body.content : [];
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="wrap">
|
||||
<el-card class="card">
|
||||
<template #header>客户商务与交付管理平台(I1)</template>
|
||||
<template #header>客户商务与交付管理平台</template>
|
||||
<el-form @submit.prevent="onSubmit">
|
||||
<el-form-item label="用户名">
|
||||
<el-input v-model="username" autocomplete="username" />
|
||||
@@ -11,7 +11,7 @@
|
||||
</el-form-item>
|
||||
<el-button type="primary" native-type="submit" :loading="loading" block>登录</el-button>
|
||||
</el-form>
|
||||
<p class="hint">演示:admin / admin(SYS_ADMIN);dev / dev(DEVELOPER);ops / ops(OPS,Callback 运营)</p>
|
||||
<p class="hint">演示:admin / admin123(SYS_ADMIN);sales / sales(SALES);delivery / delivery(DELIVERY);ops / ops(LICENSE_OPS)</p>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
@@ -30,7 +30,12 @@ const router = useRouter();
|
||||
const route = useRoute();
|
||||
const auth = useAuthStore();
|
||||
|
||||
onMounted(() => auth.restoreAxiosAuth());
|
||||
onMounted(() => {
|
||||
auth.restoreAxiosAuth()
|
||||
if (route.query.timeout === '1') {
|
||||
ElMessage.warning('会话已超时,请重新登录')
|
||||
}
|
||||
});
|
||||
|
||||
async function onSubmit() {
|
||||
loading.value = true;
|
||||
|
||||
@@ -391,7 +391,7 @@ async function loadPhaseDictionary() {
|
||||
async function loadCustomersForSelect() {
|
||||
customersLoading.value = true;
|
||||
try {
|
||||
const { data } = await listCustomers({ page: 0, size: 500 });
|
||||
const { data } = await listCustomers({ page: 0, size: 200 });
|
||||
const body = data && typeof data === "object" ? data : {};
|
||||
customerOptions.value = Array.isArray(body.content) ? body.content : [];
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user