清理旧消息和历史命名
This commit is contained in:
@@ -62,11 +62,6 @@ const router = createRouter({
|
||||
meta: { allowedRoles: ['admin', 'operator'] },
|
||||
component: () => import('@/views/admin/inventory/AdminInventoryView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'message-deliveries',
|
||||
component: () =>
|
||||
import('@/views/admin/message-deliveries/AdminMessageDeliveriesView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'webhook-events',
|
||||
meta: { allowedRoles: ['admin', 'operator'] },
|
||||
|
||||
@@ -6,5 +6,4 @@ export * from './platform-config'
|
||||
export * from './orders'
|
||||
export * from './tasks'
|
||||
export * from './inventory'
|
||||
export * from './message-deliveries'
|
||||
export * from './webhook-events'
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import { apiGet } from '@/lib/http'
|
||||
import type { AdminMessageDeliveryListItem, AdminPagination } from '@/types/admin'
|
||||
|
||||
export function fetchAdminMessageDeliveries(params?: Record<string, unknown>) {
|
||||
return apiGet<{ items: AdminMessageDeliveryListItem[]; pagination: AdminPagination }>(
|
||||
'/api/v1/admin/message-deliveries',
|
||||
params,
|
||||
)
|
||||
}
|
||||
@@ -43,14 +43,6 @@ export function regenerateAdminTaskClaimLink(taskId: number | string) {
|
||||
return apiPost<AdminTaskActionResponse>(`/api/v1/admin/tasks/${taskId}/regenerate-claim-link`, {})
|
||||
}
|
||||
|
||||
export function confirmAdminTaskAssistedRole(taskId: number | string) {
|
||||
return apiPost<AdminTaskActionResponse>(`/api/v1/admin/tasks/${taskId}/support-confirm-role`, {})
|
||||
}
|
||||
|
||||
export function redeemAdminTaskAssisted(taskId: number | string) {
|
||||
return apiPost<AdminTaskActionResponse>(`/api/v1/admin/tasks/${taskId}/support-redeem`, {})
|
||||
}
|
||||
|
||||
export function closeAdminTask(taskId: number | string) {
|
||||
return apiPost<AdminTaskActionResponse>(`/api/v1/admin/tasks/${taskId}/close`, {})
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* ============================================================
|
||||
管理员列表页共享样式
|
||||
引入: AdminOrdersView, AdminTasksView, AdminMessageDeliveriesView,
|
||||
AdminWebhookEventsView, AdminUsersView, AdminInventoryView
|
||||
引入: AdminOrdersView, AdminTasksView, AdminWebhookEventsView,
|
||||
AdminUsersView, AdminInventoryView
|
||||
各页面自行覆盖 grid-template-columns 等布局差异
|
||||
============================================================ */
|
||||
|
||||
|
||||
@@ -39,9 +39,6 @@ export type {
|
||||
AdminWebhookReplayResponse,
|
||||
} from './webhook-events'
|
||||
|
||||
// Message deliveries types
|
||||
export type { AdminMessageDeliveryListItem } from './message-deliveries'
|
||||
|
||||
// Platform config types
|
||||
export type {
|
||||
AdminNotificationBarkRecipient,
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
export interface AdminMessageDeliveryListItem {
|
||||
deliveryId: number
|
||||
provider: string
|
||||
platform: string
|
||||
shopId: string
|
||||
shopName: string
|
||||
channel: string
|
||||
orderId: number | null
|
||||
taskId: number | null
|
||||
taskNo: string
|
||||
taskStatus: string
|
||||
platformOrderId: string
|
||||
recipientKey: string
|
||||
messageContent: string
|
||||
claimUrl: string
|
||||
status: string
|
||||
requestUrl: string
|
||||
responseStatus: number
|
||||
response: Record<string, unknown>
|
||||
errorMessage: string
|
||||
sentAt: string | null
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
@@ -48,8 +48,6 @@ export interface AdminTaskOperations {
|
||||
canRefreshKuaishouCloudRoleInfo: boolean
|
||||
canDispatchKuaishouCloudFulfillment: boolean
|
||||
canReturnKuaishouCloudFulfillment: boolean
|
||||
canSupportConfirmRole: boolean
|
||||
canSupportRedeem: boolean
|
||||
canViewSensitiveTaskData: boolean
|
||||
}
|
||||
|
||||
|
||||
@@ -41,13 +41,6 @@ export const adminInventoryCredentialTypeOptions = [
|
||||
{ label: '纯文本凭据', value: 'text_credential' },
|
||||
]
|
||||
|
||||
export const adminMessageDeliveryStatusOptions = [
|
||||
{ label: '全部状态', value: '' },
|
||||
{ label: '发送成功', value: 'success' },
|
||||
{ label: '发送失败', value: 'failed' },
|
||||
{ label: '等待发送', value: 'pending' },
|
||||
]
|
||||
|
||||
export const adminWebhookProcessedOptions = [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '处理成功', value: '1' },
|
||||
|
||||
@@ -148,7 +148,7 @@ export function useAdminInventory() {
|
||||
function getCredentialTypeHint(value: string) {
|
||||
const normalized = String(value || '').trim()
|
||||
if (normalized === 'tencent_code')
|
||||
return '当前腾讯自动领取链路会优先预占这一类兑换码,三角洲行动这类场景就使用这个类型。内部 SKU 支持中文、英文和数字混用。'
|
||||
return '当前领取链路会优先预占这一类兑换码,快手云履约等场景可按内部 SKU 统一匹配。'
|
||||
if (normalized === 'card_password') return '适合卡号 / 卡密一体的库存项。'
|
||||
if (normalized === 'account_password') return '适合账号密码、账号令牌等组合凭据。'
|
||||
if (normalized === 'activation_link') return '适合直接发链接的激活类库存。'
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
Expand,
|
||||
Fold,
|
||||
List,
|
||||
Message,
|
||||
Setting,
|
||||
SwitchButton,
|
||||
Tickets,
|
||||
@@ -62,8 +61,6 @@ const navItems = computed(() => {
|
||||
items.push({ to: '/admin/inventory', label: '库存', icon: Box })
|
||||
}
|
||||
|
||||
items.push({ to: '/admin/message-deliveries', label: '消息发送', icon: Message })
|
||||
|
||||
if (isAdmin.value || isOperator.value) {
|
||||
items.push({ to: '/admin/webhook-events', label: 'Webhook', icon: Connection })
|
||||
}
|
||||
|
||||
@@ -1,281 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
|
||||
import { useAdminListPage } from '@/composables/useAdminListPage'
|
||||
import AdminPageHeader from '@/components/admin/AdminPageHeader.vue'
|
||||
import AdminStatusTag from '@/components/admin/AdminStatusTag.vue'
|
||||
import { fetchAdminMessageDeliveries } from '@/services/admin'
|
||||
import type { AdminMessageDeliveryListItem } from '@/types/admin'
|
||||
import { formatAdminDateTime } from '@/utils/admin-time'
|
||||
import { adminMessageDeliveryStatusOptions } from '@/utils/admin-options'
|
||||
|
||||
const provider = ref('agiso')
|
||||
const platform = ref('xianyu')
|
||||
const status = ref('')
|
||||
const shopId = ref('')
|
||||
const platformOrderId = ref('')
|
||||
const taskNo = ref('')
|
||||
const dateFrom = ref('')
|
||||
const dateTo = ref('')
|
||||
|
||||
const {
|
||||
loading,
|
||||
errorMessage,
|
||||
items,
|
||||
pagination,
|
||||
loadPage: loadMessageDeliveries,
|
||||
} = useAdminListPage<AdminMessageDeliveryListItem>({
|
||||
defaultErrorMessage: '读取消息发送记录失败',
|
||||
fetchPage: (page, pageSize) =>
|
||||
fetchAdminMessageDeliveries({
|
||||
page,
|
||||
pageSize,
|
||||
provider: provider.value.trim(),
|
||||
platform: platform.value.trim(),
|
||||
status: status.value.trim(),
|
||||
shopId: shopId.value.trim(),
|
||||
platformOrderId: platformOrderId.value.trim(),
|
||||
taskNo: taskNo.value.trim(),
|
||||
dateFrom: dateFrom.value.trim(),
|
||||
dateTo: dateTo.value.trim(),
|
||||
}),
|
||||
})
|
||||
|
||||
const summary = computed(() => ({
|
||||
successCount: items.value.filter((item) => item.status === 'success').length,
|
||||
failedCount: items.value.filter((item) => item.status === 'failed').length,
|
||||
pendingCount: items.value.filter((item) => item.status === 'pending').length,
|
||||
}))
|
||||
|
||||
function resetFilters() {
|
||||
provider.value = 'agiso'
|
||||
platform.value = 'xianyu'
|
||||
status.value = ''
|
||||
shopId.value = ''
|
||||
platformOrderId.value = ''
|
||||
taskNo.value = ''
|
||||
dateFrom.value = ''
|
||||
dateTo.value = ''
|
||||
void loadMessageDeliveries(1)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void loadMessageDeliveries(1)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="deliveries-page list-page">
|
||||
<AdminPageHeader
|
||||
title="消息发送记录"
|
||||
description="查看领取链接消息是否真正发出、平台返回了什么、失败原因是什么。"
|
||||
>
|
||||
<template #extra>
|
||||
<span class="total-badge">共 {{ pagination.total }} 条记录</span>
|
||||
</template>
|
||||
</AdminPageHeader>
|
||||
|
||||
<!-- 筛选 -->
|
||||
<el-card shadow="never" class="section-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">筛选消息</span>
|
||||
<span class="card-desc">按服务商、平台、发送状态、店铺等条件筛选。</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="filter-grid">
|
||||
<el-input
|
||||
v-model="provider"
|
||||
class="filter-control"
|
||||
placeholder="服务商,如 agiso"
|
||||
clearable
|
||||
@keyup.enter="loadMessageDeliveries(1)"
|
||||
/>
|
||||
<el-input
|
||||
v-model="platform"
|
||||
class="filter-control"
|
||||
placeholder="业务平台,如 xianyu"
|
||||
clearable
|
||||
@keyup.enter="loadMessageDeliveries(1)"
|
||||
/>
|
||||
<el-select v-model="status" class="filter-control" placeholder="发送状态" clearable>
|
||||
<el-option
|
||||
v-for="opt in adminMessageDeliveryStatusOptions"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input
|
||||
v-model="shopId"
|
||||
class="filter-control"
|
||||
placeholder="店铺 ID(精确匹配)"
|
||||
clearable
|
||||
@keyup.enter="loadMessageDeliveries(1)"
|
||||
/>
|
||||
<el-input
|
||||
v-model="platformOrderId"
|
||||
class="filter-control"
|
||||
placeholder="平台订单号"
|
||||
clearable
|
||||
@keyup.enter="loadMessageDeliveries(1)"
|
||||
/>
|
||||
<el-input
|
||||
v-model="taskNo"
|
||||
class="filter-control"
|
||||
placeholder="任务编号"
|
||||
clearable
|
||||
@keyup.enter="loadMessageDeliveries(1)"
|
||||
/>
|
||||
<el-date-picker
|
||||
v-model="dateFrom"
|
||||
class="filter-control"
|
||||
type="date"
|
||||
placeholder="开始日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<el-date-picker
|
||||
v-model="dateTo"
|
||||
class="filter-control"
|
||||
type="date"
|
||||
placeholder="结束日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<div class="filter-buttons">
|
||||
<el-button round @click="resetFilters">重置</el-button>
|
||||
<el-button round type="primary" @click="loadMessageDeliveries(1)">查询</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 摘要 -->
|
||||
<div v-if="!loading && items.length > 0" class="summary-strip">
|
||||
<span class="summary-title">当前页</span>
|
||||
<span class="summary-metric" data-tone="success"
|
||||
>发送成功 <strong>{{ summary.successCount }}</strong></span
|
||||
>
|
||||
<span class="summary-metric" data-tone="danger"
|
||||
>发送失败 <strong>{{ summary.failedCount }}</strong></span
|
||||
>
|
||||
<span class="summary-metric" data-tone="warning"
|
||||
>等待中 <strong>{{ summary.pendingCount }}</strong></span
|
||||
>
|
||||
</div>
|
||||
|
||||
<el-alert
|
||||
v-if="errorMessage"
|
||||
:title="errorMessage"
|
||||
type="error"
|
||||
show-icon
|
||||
:closable="false"
|
||||
class="mt-4"
|
||||
/>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-card
|
||||
shadow="never"
|
||||
class="section-card"
|
||||
v-loading="loading"
|
||||
element-loading-text="消息发送记录加载中"
|
||||
>
|
||||
<template v-if="items.length === 0 && !loading">
|
||||
<el-empty description="当前筛选下还没有消息发送记录。" :image-size="60" />
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<div class="orders-toolbar table-toolbar">
|
||||
<strong>发送明细</strong>
|
||||
<span>第 {{ pagination.page }} 页,当前展示 {{ items.length }} 条</span>
|
||||
</div>
|
||||
|
||||
<el-table :data="items" stripe size="small" class="orders-table data-table">
|
||||
<el-table-column label="消息ID" width="100">
|
||||
<template #default="{ row }">
|
||||
<span class="order-no id-link">#{{ row.deliveryId }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="接收者" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<div class="cell-stack">
|
||||
<span class="cell-title">{{
|
||||
row.recipientKey || row.shopName || row.shopId || '-'
|
||||
}}</span>
|
||||
<span class="cell-subline">{{ row.shopName || row.shopId || '-' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="消息类型" min-width="140">
|
||||
<template #default="{ row }">
|
||||
<div class="cell-stack">
|
||||
<span class="cell-title">{{ row.channel || '-' }}</span>
|
||||
<div class="cell-meta-row">
|
||||
<span class="compact-chip">{{ row.provider || '-' }}</span>
|
||||
<span class="compact-chip">{{ row.platform || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<AdminStatusTag :status="row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<div class="cell-stack">
|
||||
<span class="cell-title">{{ formatAdminDateTime(row.createdAt) }}</span>
|
||||
<span v-if="row.sentAt" class="cell-subline"
|
||||
>发送 {{ formatAdminDateTime(row.sentAt) }}</span
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="140">
|
||||
<template #default="{ row }">
|
||||
<div class="action-stack">
|
||||
<a
|
||||
v-if="row.claimUrl"
|
||||
class="detail-link"
|
||||
:href="row.claimUrl"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>Claim 链接</a
|
||||
>
|
||||
<RouterLink
|
||||
v-if="row.orderId"
|
||||
class="detail-link"
|
||||
:to="`/admin/orders/${row.orderId}`"
|
||||
>订单 #{{ row.orderId }}</RouterLink
|
||||
>
|
||||
<RouterLink v-if="row.taskId" class="detail-link" :to="`/admin/tasks/${row.taskId}`"
|
||||
>任务 {{ row.taskNo || row.taskId }}</RouterLink
|
||||
>
|
||||
<span v-if="!row.claimUrl && !row.orderId && !row.taskId" class="cell-subline"
|
||||
>-</span
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
v-if="pagination.total > 0"
|
||||
v-model:current-page="pagination.page"
|
||||
:page-size="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
layout="total, prev, pager, next"
|
||||
class="pagination-center"
|
||||
@current-change="loadMessageDeliveries"
|
||||
/>
|
||||
</template>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@import '../../../styles/admin-list-pages.css';
|
||||
|
||||
.filter-grid {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
</style>
|
||||
@@ -3,9 +3,7 @@ import { onMounted } from 'vue'
|
||||
|
||||
import {
|
||||
closeAdminTask,
|
||||
confirmAdminTaskAssistedRole,
|
||||
markAdminTaskManualReview,
|
||||
redeemAdminTaskAssisted,
|
||||
regenerateAdminTaskClaimLink,
|
||||
releaseAdminTaskInventoryBinding,
|
||||
retryAdminTask,
|
||||
@@ -94,20 +92,6 @@ onMounted(loadDetail)
|
||||
`确认重新生成任务 ${detail!.task.taskNo} 的领取链接吗?旧链接会失效。`,
|
||||
)
|
||||
"
|
||||
@confirm-role="
|
||||
runAction(
|
||||
() => confirmAdminTaskAssistedRole(detail!.task.taskId),
|
||||
'角色已确认',
|
||||
`确认以客服身份锁定任务 ${detail!.task.taskNo} 当前识别到的角色信息吗?`,
|
||||
)
|
||||
"
|
||||
@support-redeem="
|
||||
runAction(
|
||||
() => redeemAdminTaskAssisted(detail!.task.taskId),
|
||||
'兑换任务已启动',
|
||||
`确认开始执行任务 ${detail!.task.taskNo} 的自动兑换吗?`,
|
||||
)
|
||||
"
|
||||
@prepare-kuaishou-cloud="submitKuaishouCloudPrepare"
|
||||
@dispatch-kuaishou-cloud="submitKuaishouCloudDispatch"
|
||||
@return-kuaishou-cloud="submitKuaishouCloudReturnNumber"
|
||||
|
||||
@@ -13,8 +13,6 @@ defineProps<Props>()
|
||||
const emit = defineEmits<{
|
||||
retry: []
|
||||
regenerateClaimLink: []
|
||||
confirmRole: []
|
||||
supportRedeem: []
|
||||
prepareKuaishouCloud: []
|
||||
dispatchKuaishouCloud: []
|
||||
returnKuaishouCloud: []
|
||||
@@ -45,24 +43,6 @@ const emit = defineEmits<{
|
||||
>
|
||||
重发链接
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="detail.operations.canSupportConfirmRole"
|
||||
:loading="actionLoading"
|
||||
round
|
||||
type="warning"
|
||||
@click="emit('confirmRole')"
|
||||
>
|
||||
客服确认角色
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="detail.operations.canSupportRedeem"
|
||||
:loading="actionLoading"
|
||||
round
|
||||
type="success"
|
||||
@click="emit('supportRedeem')"
|
||||
>
|
||||
客服开始兑换
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="canManageTaskLifecycle && detail.operations.canPrepareKuaishouCloudFulfillment"
|
||||
:loading="actionLoading"
|
||||
|
||||
@@ -152,14 +152,14 @@ onMounted(() => {
|
||||
<el-input
|
||||
v-model="provider"
|
||||
class="filter-control"
|
||||
placeholder="服务商,如 agiso"
|
||||
placeholder="服务商,如 91kaquan"
|
||||
clearable
|
||||
@keyup.enter="applyFilters(1)"
|
||||
/>
|
||||
<el-input
|
||||
v-model="platform"
|
||||
class="filter-control"
|
||||
placeholder="业务平台,如 xianyu / taobao"
|
||||
placeholder="业务平台,如 kuaishou"
|
||||
clearable
|
||||
@keyup.enter="applyFilters(1)"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user