优化平台配置导航布局
This commit is contained in:
Vendored
+1
@@ -45,6 +45,7 @@ declare module 'vue' {
|
||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||
ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
|
||||
ElSpace: typeof import('element-plus/es')['ElSpace']
|
||||
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
|
||||
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
||||
ElTable: typeof import('element-plus/es')['ElTable']
|
||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import { computed, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import {
|
||||
Bell,
|
||||
Connection,
|
||||
Monitor,
|
||||
DataAnalysis,
|
||||
Document,
|
||||
@@ -27,6 +29,7 @@ import { formatAdminDateTime } from '@/utils/admin-time'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const sidebarStorageKey = 'admin-sidebar-collapsed'
|
||||
const isDevMode = import.meta.env.DEV
|
||||
const isSidebarCollapsed = ref(
|
||||
typeof window !== 'undefined' && window.localStorage.getItem(sidebarStorageKey) === '1',
|
||||
)
|
||||
@@ -40,8 +43,33 @@ const roleLabel = computed(() => {
|
||||
return '普通运营'
|
||||
})
|
||||
|
||||
type AdminNavItem = {
|
||||
to: string
|
||||
label: string
|
||||
icon: typeof DataAnalysis
|
||||
children?: AdminNavItem[]
|
||||
}
|
||||
|
||||
const platformConfigNavItems = computed<AdminNavItem[]>(() => {
|
||||
const items: AdminNavItem[] = [
|
||||
{ to: '/admin/platform-shops?tab=ninetyone', label: '91卡券', icon: Connection },
|
||||
{ to: '/admin/platform-shops?tab=notifications', label: '内部通知', icon: Bell },
|
||||
{ to: '/admin/platform-shops?tab=kuaishouEticket', label: '快手小店核销', icon: Tickets },
|
||||
]
|
||||
|
||||
if (isDevMode) {
|
||||
items.push({
|
||||
to: '/admin/platform-shops?tab=cloudtentacles',
|
||||
label: 'cloudtentacles',
|
||||
icon: Setting,
|
||||
})
|
||||
}
|
||||
|
||||
return items
|
||||
})
|
||||
|
||||
const navItems = computed(() => {
|
||||
const items: { to: string; label: string; icon: typeof DataAnalysis }[] = [
|
||||
const items: AdminNavItem[] = [
|
||||
{ to: '/admin/dashboard', label: '概览', icon: DataAnalysis },
|
||||
]
|
||||
|
||||
@@ -56,7 +84,12 @@ const navItems = computed(() => {
|
||||
|
||||
if (isAdmin.value) {
|
||||
items.push(
|
||||
{ to: '/admin/platform-shops', label: '平台配置', icon: Setting },
|
||||
{
|
||||
to: '/admin/platform-shops',
|
||||
label: '平台配置',
|
||||
icon: Setting,
|
||||
children: platformConfigNavItems.value,
|
||||
},
|
||||
{ to: '/admin/platform-fulfillment', label: '履约配置', icon: Tickets },
|
||||
{ to: '/admin/audit-logs', label: '审计', icon: Monitor },
|
||||
)
|
||||
@@ -65,6 +98,15 @@ const navItems = computed(() => {
|
||||
return items
|
||||
})
|
||||
|
||||
const activeNavIndex = computed(() => {
|
||||
if (route.path === '/admin/platform-shops') {
|
||||
const tab = typeof route.query.tab === 'string' ? route.query.tab : 'ninetyone'
|
||||
return `/admin/platform-shops?tab=${tab}`
|
||||
}
|
||||
|
||||
return route.path
|
||||
})
|
||||
|
||||
function toggleSidebarCollapse() {
|
||||
isSidebarCollapsed.value = !isSidebarCollapsed.value
|
||||
if (typeof window !== 'undefined') {
|
||||
@@ -112,17 +154,37 @@ async function submitLogout() {
|
||||
</div>
|
||||
|
||||
<el-menu
|
||||
:default-active="route.path"
|
||||
:default-active="activeNavIndex"
|
||||
:default-openeds="['/admin/platform-shops']"
|
||||
router
|
||||
class="sidebar-menu"
|
||||
:collapse="isSidebarCollapsed"
|
||||
:collapse-transition="false"
|
||||
:ellipsis="false"
|
||||
>
|
||||
<el-menu-item v-for="item in navItems" :key="item.to" :index="item.to" :title="item.label">
|
||||
<el-icon><component :is="item.icon" /></el-icon>
|
||||
<span>{{ item.label }}</span>
|
||||
</el-menu-item>
|
||||
<template v-for="item in navItems" :key="item.to">
|
||||
<el-sub-menu v-if="item.children?.length" :index="item.to">
|
||||
<template #title>
|
||||
<el-icon><component :is="item.icon" /></el-icon>
|
||||
<span>{{ item.label }}</span>
|
||||
</template>
|
||||
|
||||
<el-menu-item
|
||||
v-for="child in item.children"
|
||||
:key="child.to"
|
||||
:index="child.to"
|
||||
:title="child.label"
|
||||
>
|
||||
<el-icon><component :is="child.icon" /></el-icon>
|
||||
<span>{{ child.label }}</span>
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
|
||||
<el-menu-item v-else :index="item.to" :title="item.label">
|
||||
<el-icon><component :is="item.icon" /></el-icon>
|
||||
<span>{{ item.label }}</span>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-menu>
|
||||
|
||||
<el-tooltip :disabled="!isSidebarCollapsed" content="退出登录" placement="right">
|
||||
@@ -235,18 +297,33 @@ async function submitLogout() {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar-menu :deep(.el-menu-item) {
|
||||
.sidebar-menu :deep(.el-menu-item),
|
||||
.sidebar-menu :deep(.el-sub-menu__title) {
|
||||
margin: 2px var(--space-2);
|
||||
border-radius: var(--radius-md);
|
||||
min-height: 44px;
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
.sidebar-menu :deep(.el-menu-item.is-active) {
|
||||
.sidebar-menu :deep(.el-menu-item.is-active),
|
||||
.sidebar-menu :deep(.el-sub-menu.is-active > .el-sub-menu__title) {
|
||||
color: var(--color-primary);
|
||||
background: var(--color-primary-light);
|
||||
}
|
||||
|
||||
.sidebar-menu :deep(.el-sub-menu .el-menu-item) {
|
||||
margin-left: var(--space-4);
|
||||
min-height: 38px;
|
||||
line-height: 38px;
|
||||
color: var(--text-secondary);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
.sidebar-menu :deep(.el-sub-menu .el-menu-item.is-active) {
|
||||
color: var(--color-primary);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
margin: var(--space-3) var(--space-4) 0;
|
||||
flex-shrink: 0;
|
||||
@@ -263,13 +340,15 @@ async function submitLogout() {
|
||||
margin-bottom: var(--space-5);
|
||||
}
|
||||
|
||||
.is-sidebar-collapsed .sidebar-menu :deep(.el-menu-item) {
|
||||
.is-sidebar-collapsed .sidebar-menu :deep(.el-menu-item),
|
||||
.is-sidebar-collapsed .sidebar-menu :deep(.el-sub-menu__title) {
|
||||
justify-content: center;
|
||||
margin: 4px 10px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.is-sidebar-collapsed .sidebar-menu :deep(.el-menu-item .el-icon) {
|
||||
.is-sidebar-collapsed .sidebar-menu :deep(.el-menu-item .el-icon),
|
||||
.is-sidebar-collapsed .sidebar-menu :deep(.el-sub-menu__title .el-icon) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
@@ -313,7 +392,8 @@ async function submitLogout() {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.is-sidebar-collapsed .sidebar-menu :deep(.el-menu-item) {
|
||||
.is-sidebar-collapsed .sidebar-menu :deep(.el-menu-item),
|
||||
.is-sidebar-collapsed .sidebar-menu :deep(.el-sub-menu__title) {
|
||||
justify-content: flex-start;
|
||||
margin: 2px var(--space-2);
|
||||
padding: 0 var(--space-5);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { RefreshRight } from '@element-plus/icons-vue'
|
||||
|
||||
import AdminPageHeader from '@/components/admin/AdminPageHeader.vue'
|
||||
@@ -23,7 +24,21 @@ import type { PlatformTab } from './composables/types'
|
||||
const loading = ref(true)
|
||||
const isDevMode = import.meta.env.DEV
|
||||
const errorMessage = ref('')
|
||||
const activePlatform = ref<PlatformTab>('ninetyone')
|
||||
const route = useRoute()
|
||||
|
||||
const platformTabs: PlatformTab[] = ['ninetyone', 'notifications', 'kuaishouEticket']
|
||||
|
||||
if (isDevMode) {
|
||||
platformTabs.push('cloudtentacles')
|
||||
}
|
||||
|
||||
function normalizePlatformTab(value: unknown): PlatformTab {
|
||||
return typeof value === 'string' && platformTabs.includes(value as PlatformTab)
|
||||
? (value as PlatformTab)
|
||||
: 'ninetyone'
|
||||
}
|
||||
|
||||
const activePlatform = computed(() => normalizePlatformTab(route.query.tab))
|
||||
|
||||
const {
|
||||
ninetyoneLoading,
|
||||
@@ -147,42 +162,46 @@ const overviewCards = computed(() => {
|
||||
{
|
||||
key: 'notifications',
|
||||
label: '内部通知',
|
||||
tag: 'Bark / WPush',
|
||||
tag: '通知与监控',
|
||||
value:
|
||||
notificationStats.value.barkEnabledRecipientCount +
|
||||
notificationStats.value.wpushEnabledRecipientCount,
|
||||
unit: '启用接收人',
|
||||
meta: `Bark ${notificationStats.value.barkConfiguredRecipientCount} 人 · WPush ${notificationStats.value.wpushConfiguredRecipientCount} 人 · 最近成功 ${notificationStats.value.lastSuccessCount} 个`,
|
||||
status: notificationStats.value.ready ? '已就绪' : '待配置',
|
||||
},
|
||||
{
|
||||
key: 'ninetyone',
|
||||
label: '91卡券',
|
||||
tag: '接入 / 待补全',
|
||||
tag: '来源订单',
|
||||
value: ninetyoneStats.value.pendingCount,
|
||||
unit: '待补全订单',
|
||||
meta: `当前 ${ninetyoneStats.value.currentCount} 条 · 已生成任务 ${ninetyoneStats.value.taskReadyCount} 条`,
|
||||
status: ninetyoneStats.value.pendingCount > 0 ? '待处理' : '正常',
|
||||
},
|
||||
{
|
||||
key: 'kuaishouEticket',
|
||||
label: '快手小店核销',
|
||||
tag: 'Cookie / 券核销',
|
||||
tag: '店铺凭据',
|
||||
value: kuaishouEticketStats.value.configuredShopCount,
|
||||
unit: '已配置店铺',
|
||||
meta: `Cookie 就绪 ${kuaishouEticketStats.value.cookieReadyCount} 家 · 当前店铺 ${
|
||||
kuaishouEticketStats.value.selectedShopReady ? '可调试' : '待补全'
|
||||
}`,
|
||||
status: kuaishouEticketStats.value.cookieReadyCount > 0 ? '已就绪' : '待配置',
|
||||
},
|
||||
...(isDevMode
|
||||
? [
|
||||
{
|
||||
key: 'cloudtentacles',
|
||||
label: 'cloudtentacles',
|
||||
tag: '履约 / 登录',
|
||||
tag: '履约账号',
|
||||
value: cloudtentaclesStats.value.hasCredential ? '已配置' : '未配置',
|
||||
unit: '履约凭据',
|
||||
meta: `短信 ${cloudtentaclesStats.value.smsSent ? '已发送' : '未发送'} · 会话 ${
|
||||
cloudtentaclesStats.value.validated ? '已验证' : '未验证'
|
||||
}`,
|
||||
status: cloudtentaclesStats.value.validated ? '已验证' : '待验证',
|
||||
},
|
||||
]
|
||||
: []),
|
||||
@@ -191,6 +210,11 @@ const overviewCards = computed(() => {
|
||||
return cards
|
||||
})
|
||||
|
||||
const activeOverview = computed(
|
||||
() =>
|
||||
overviewCards.value.find((card) => card.key === activePlatform.value) || overviewCards.value[0],
|
||||
)
|
||||
|
||||
async function loadConfigs() {
|
||||
if (!hasAdminRole('admin')) {
|
||||
loading.value = false
|
||||
@@ -225,10 +249,6 @@ async function loadConfigs() {
|
||||
}
|
||||
}
|
||||
|
||||
function switchTab(tab: string) {
|
||||
activePlatform.value = tab as PlatformTab
|
||||
}
|
||||
|
||||
onMounted(loadConfigs)
|
||||
</script>
|
||||
|
||||
@@ -267,150 +287,139 @@ onMounted(loadConfigs)
|
||||
<el-skeleton v-if="loading" :rows="8" animated />
|
||||
|
||||
<template v-else>
|
||||
<!-- 概览卡片 -->
|
||||
<div class="overview-grid">
|
||||
<el-card
|
||||
v-for="card in overviewCards"
|
||||
:key="card.key"
|
||||
:class="['overview-card', { 'is-active': activePlatform === card.key }]"
|
||||
shadow="hover"
|
||||
@click="switchTab(card.key)"
|
||||
>
|
||||
<div class="card-head">
|
||||
<el-tag size="small" type="primary">{{ card.label }}</el-tag>
|
||||
<el-tag size="small">{{ card.tag }}</el-tag>
|
||||
<main class="platform-detail">
|
||||
<section v-if="activeOverview" class="active-summary">
|
||||
<div class="active-summary-copy">
|
||||
<div class="summary-kicker">{{ activeOverview.tag }}</div>
|
||||
<h2>{{ activeOverview.label }}</h2>
|
||||
<p>{{ activeOverview.meta }}</p>
|
||||
</div>
|
||||
<div class="card-value">{{ card.value }}</div>
|
||||
<div class="card-unit">{{ card.unit }}</div>
|
||||
<div class="card-meta">{{ card.meta }}</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<div class="summary-metrics">
|
||||
<div class="summary-metric">
|
||||
<span>{{ activeOverview.unit }}</span>
|
||||
<strong>{{ activeOverview.value }}</strong>
|
||||
</div>
|
||||
<el-tag size="large" effect="plain">{{ activeOverview.status }}</el-tag>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 平台切换 Tab -->
|
||||
<el-tabs v-model="activePlatform" type="card" class="platform-tabs">
|
||||
<el-tab-pane label="91卡券接入" name="ninetyone">
|
||||
<AdminPlatformNinetyoneSection
|
||||
:ninetyone-loading="ninetyoneLoading"
|
||||
:ninetyone-action-loading-id="ninetyoneActionLoadingId"
|
||||
:ninetyone-result-error="ninetyoneResultError"
|
||||
:ninetyone-status="ninetyoneStatus"
|
||||
:ninetyone-orders="ninetyoneOrders"
|
||||
:ninetyone-stats="ninetyoneStats"
|
||||
:load-ninetyone-orders="loadNinetyoneOrders"
|
||||
:handle-ninetyone-status-change="handleNinetyoneStatusChange"
|
||||
:handle-ninetyone-retry-order="handleNinetyoneRetryOrder"
|
||||
:handle-ninetyone-fail-order="handleNinetyoneFailOrder"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<AdminPlatformNinetyoneSection
|
||||
v-if="activePlatform === 'ninetyone'"
|
||||
:ninetyone-loading="ninetyoneLoading"
|
||||
:ninetyone-action-loading-id="ninetyoneActionLoadingId"
|
||||
:ninetyone-result-error="ninetyoneResultError"
|
||||
:ninetyone-status="ninetyoneStatus"
|
||||
:ninetyone-orders="ninetyoneOrders"
|
||||
:ninetyone-stats="ninetyoneStats"
|
||||
:load-ninetyone-orders="loadNinetyoneOrders"
|
||||
:handle-ninetyone-status-change="handleNinetyoneStatusChange"
|
||||
:handle-ninetyone-retry-order="handleNinetyoneRetryOrder"
|
||||
:handle-ninetyone-fail-order="handleNinetyoneFailOrder"
|
||||
/>
|
||||
|
||||
<el-tab-pane label="内部通知" name="notifications">
|
||||
<AdminPlatformNotificationSection
|
||||
:notification-file-path="notificationFilePath"
|
||||
:notification-form="notificationForm"
|
||||
:notification-recipients="notificationRecipients"
|
||||
:wpush-recipients="wpushRecipients"
|
||||
:notification-saving="notificationSaving"
|
||||
:notification-testing="notificationTesting"
|
||||
:notification-result-error="notificationResultError"
|
||||
:notification-test-result="notificationTestResult"
|
||||
:scheduled-jobs-file-path="scheduledJobsFilePath"
|
||||
:scheduled-jobs-form="scheduledJobsForm"
|
||||
:scheduled-jobs="scheduledJobs"
|
||||
:scheduled-job-runtime="scheduledJobRuntime"
|
||||
:cloudtentacles-monitor-accounts="cloudtentaclesMonitorAccounts"
|
||||
:scheduled-jobs-saving="scheduledJobsSaving"
|
||||
:scheduled-job-running-id="scheduledJobRunningId"
|
||||
:notification-stats="notificationStats"
|
||||
:add-notification-recipient="addNotificationRecipient"
|
||||
:remove-notification-recipient="removeNotificationRecipient"
|
||||
:handle-notification-save-config="handleNotificationSaveConfig"
|
||||
:handle-notification-test="handleNotificationTest"
|
||||
:handle-scheduled-jobs-save-config="handleScheduledJobsSaveConfig"
|
||||
:handle-scheduled-job-run-now="handleScheduledJobRunNow"
|
||||
:get-scheduled-job-runtime="getScheduledJobRuntime"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<AdminPlatformNotificationSection
|
||||
v-else-if="activePlatform === 'notifications'"
|
||||
:notification-file-path="notificationFilePath"
|
||||
:notification-form="notificationForm"
|
||||
:notification-recipients="notificationRecipients"
|
||||
:wpush-recipients="wpushRecipients"
|
||||
:notification-saving="notificationSaving"
|
||||
:notification-testing="notificationTesting"
|
||||
:notification-result-error="notificationResultError"
|
||||
:notification-test-result="notificationTestResult"
|
||||
:scheduled-jobs-file-path="scheduledJobsFilePath"
|
||||
:scheduled-jobs-form="scheduledJobsForm"
|
||||
:scheduled-jobs="scheduledJobs"
|
||||
:scheduled-job-runtime="scheduledJobRuntime"
|
||||
:cloudtentacles-monitor-accounts="cloudtentaclesMonitorAccounts"
|
||||
:scheduled-jobs-saving="scheduledJobsSaving"
|
||||
:scheduled-job-running-id="scheduledJobRunningId"
|
||||
:notification-stats="notificationStats"
|
||||
:add-notification-recipient="addNotificationRecipient"
|
||||
:remove-notification-recipient="removeNotificationRecipient"
|
||||
:handle-notification-save-config="handleNotificationSaveConfig"
|
||||
:handle-notification-test="handleNotificationTest"
|
||||
:handle-scheduled-jobs-save-config="handleScheduledJobsSaveConfig"
|
||||
:handle-scheduled-job-run-now="handleScheduledJobRunNow"
|
||||
:get-scheduled-job-runtime="getScheduledJobRuntime"
|
||||
/>
|
||||
|
||||
<el-tab-pane label="快手小店核销" name="kuaishouEticket">
|
||||
<AdminPlatformKuaishouEticketSection
|
||||
:kuaishou-eticket-file-path="kuaishouEticketFilePath"
|
||||
:kuaishou-eticket-shops="kuaishouEticketShops"
|
||||
:kuaishou-eticket-form="kuaishouEticketForm"
|
||||
:kuaishou-eticket-saving="kuaishouEticketSaving"
|
||||
:kuaishou-eticket-resolving-shop-id="kuaishouEticketResolvingShopId"
|
||||
:kuaishou-eticket-detailing="kuaishouEticketDetailing"
|
||||
:kuaishou-eticket-consuming="kuaishouEticketConsuming"
|
||||
:kuaishou-eticket-result-error="kuaishouEticketResultError"
|
||||
:kuaishou-eticket-shop-info-result="kuaishouEticketShopInfoResult"
|
||||
:kuaishou-eticket-detail-result="kuaishouEticketDetailResult"
|
||||
:kuaishou-eticket-consume-result="kuaishouEticketConsumeResult"
|
||||
:active-kuaishou-eticket-shop="activeKuaishouEticketShop"
|
||||
:kuaishou-eticket-stats="kuaishouEticketStats"
|
||||
:add-kuaishou-eticket-shop="addKuaishouEticketShop"
|
||||
:remove-kuaishou-eticket-shop="removeKuaishouEticketShop"
|
||||
:is-kuaishou-eticket-shop-expanded="isKuaishouEticketShopExpanded"
|
||||
:toggle-kuaishou-eticket-shop="toggleKuaishouEticketShop"
|
||||
:expand-all-kuaishou-eticket-shops="expandAllKuaishouEticketShops"
|
||||
:collapse-all-kuaishou-eticket-shops="collapseAllKuaishouEticketShops"
|
||||
:set-kuaishou-eticket-debug-shop="setKuaishouEticketDebugShop"
|
||||
:describe-kuaishou-eticket-shop="describeKuaishouEticketShop"
|
||||
:get-kuaishou-eticket-shop-initial="getKuaishouEticketShopInitial"
|
||||
:handle-kuaishou-eticket-resolve-shop-info="handleKuaishouEticketResolveShopInfo"
|
||||
:handle-kuaishou-eticket-save-source="handleKuaishouEticketSaveSource"
|
||||
:handle-kuaishou-eticket-query-detail="handleKuaishouEticketQueryDetail"
|
||||
:handle-kuaishou-eticket-consume="handleKuaishouEticketConsume"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<AdminPlatformKuaishouEticketSection
|
||||
v-else-if="activePlatform === 'kuaishouEticket'"
|
||||
:kuaishou-eticket-file-path="kuaishouEticketFilePath"
|
||||
:kuaishou-eticket-shops="kuaishouEticketShops"
|
||||
:kuaishou-eticket-form="kuaishouEticketForm"
|
||||
:kuaishou-eticket-saving="kuaishouEticketSaving"
|
||||
:kuaishou-eticket-resolving-shop-id="kuaishouEticketResolvingShopId"
|
||||
:kuaishou-eticket-detailing="kuaishouEticketDetailing"
|
||||
:kuaishou-eticket-consuming="kuaishouEticketConsuming"
|
||||
:kuaishou-eticket-result-error="kuaishouEticketResultError"
|
||||
:kuaishou-eticket-shop-info-result="kuaishouEticketShopInfoResult"
|
||||
:kuaishou-eticket-detail-result="kuaishouEticketDetailResult"
|
||||
:kuaishou-eticket-consume-result="kuaishouEticketConsumeResult"
|
||||
:active-kuaishou-eticket-shop="activeKuaishouEticketShop"
|
||||
:kuaishou-eticket-stats="kuaishouEticketStats"
|
||||
:add-kuaishou-eticket-shop="addKuaishouEticketShop"
|
||||
:remove-kuaishou-eticket-shop="removeKuaishouEticketShop"
|
||||
:is-kuaishou-eticket-shop-expanded="isKuaishouEticketShopExpanded"
|
||||
:toggle-kuaishou-eticket-shop="toggleKuaishouEticketShop"
|
||||
:expand-all-kuaishou-eticket-shops="expandAllKuaishouEticketShops"
|
||||
:collapse-all-kuaishou-eticket-shops="collapseAllKuaishouEticketShops"
|
||||
:set-kuaishou-eticket-debug-shop="setKuaishouEticketDebugShop"
|
||||
:describe-kuaishou-eticket-shop="describeKuaishouEticketShop"
|
||||
:get-kuaishou-eticket-shop-initial="getKuaishouEticketShopInitial"
|
||||
:handle-kuaishou-eticket-resolve-shop-info="handleKuaishouEticketResolveShopInfo"
|
||||
:handle-kuaishou-eticket-save-source="handleKuaishouEticketSaveSource"
|
||||
:handle-kuaishou-eticket-query-detail="handleKuaishouEticketQueryDetail"
|
||||
:handle-kuaishou-eticket-consume="handleKuaishouEticketConsume"
|
||||
/>
|
||||
|
||||
<el-tab-pane v-if="isDevMode" label="cloudtentacles 履约平台" name="cloudtentacles">
|
||||
<AdminPlatformCloudtentaclesSection
|
||||
:cloudtentacles-file-path="cloudtentaclesFilePath"
|
||||
:cloudtentacles-session-file-path="cloudtentaclesSessionFilePath"
|
||||
:cloudtentacles-form="cloudtentaclesForm"
|
||||
:cloudtentacles-saving="cloudtentaclesSaving"
|
||||
:cloudtentacles-sending-sms="cloudtentaclesSendingSms"
|
||||
:cloudtentacles-testing="cloudtentaclesTesting"
|
||||
:cloudtentacles-validating="cloudtentaclesValidating"
|
||||
:cloudtentacles-result-error="cloudtentaclesResultError"
|
||||
:cloudtentacles-sms-result="cloudtentaclesSmsResult"
|
||||
:cloudtentacles-login-result="cloudtentaclesLoginResult"
|
||||
:cloudtentacles-validate-result="cloudtentaclesValidateResult"
|
||||
:cloudtentacles-debug-loading="cloudtentaclesDebugLoading"
|
||||
:cloudtentacles-debug-result="cloudtentaclesDebugResult"
|
||||
:cloudtentacles-persisted-session="cloudtentaclesPersistedSession"
|
||||
:cloudtentacles-stats="cloudtentaclesStats"
|
||||
:sources="cloudtentaclesSources"
|
||||
:sessions="cloudtentaclesSessions"
|
||||
:selected-source-key="selectedCloudtentaclesSourceKey"
|
||||
:current-source-enabled="currentCloudtentaclesSourceEnabled"
|
||||
:current-source="currentCloudtentaclesSource"
|
||||
:current-session="currentCloudtentaclesSession"
|
||||
:switch-source="switchCloudtentaclesSource"
|
||||
:add-source="addCloudtentaclesSource"
|
||||
:remove-source="removeCloudtentaclesSource"
|
||||
:handle-cloudtentacles-save-source="handleCloudtentaclesSaveSource"
|
||||
:handle-cloudtentacles-send-sms-code="handleCloudtentaclesSendSmsCode"
|
||||
:handle-cloudtentacles-test-login="handleCloudtentaclesTestLogin"
|
||||
:handle-cloudtentacles-validate-session="handleCloudtentaclesValidateSession"
|
||||
:handle-cloudtentacles-fetch-asset="handleCloudtentaclesFetchAsset"
|
||||
:handle-cloudtentacles-fetch-categories="handleCloudtentaclesFetchCategories"
|
||||
:handle-cloudtentacles-fetch-sku-list="handleCloudtentaclesFetchSkuList"
|
||||
:handle-cloudtentacles-buy-sku="handleCloudtentaclesBuySku"
|
||||
:handle-cloudtentacles-use-sku="handleCloudtentaclesUseSku"
|
||||
:handle-cloudtentacles-fetch-knapsack="handleCloudtentaclesFetchKnapsack"
|
||||
:handle-cloudtentacles-fetch-vn-list="handleCloudtentaclesFetchVnList"
|
||||
:handle-cloudtentacles-appoint-vn="handleCloudtentaclesAppointVn"
|
||||
:handle-cloudtentacles-generate-vn-login-code="
|
||||
handleCloudtentaclesGenerateVnLoginCode
|
||||
"
|
||||
:handle-cloudtentacles-fetch-vn-code="handleCloudtentaclesFetchVnCode"
|
||||
:handle-cloudtentacles-verify-vn-code="handleCloudtentaclesVerifyVnCode"
|
||||
:handle-cloudtentacles-fetch-bind-url="handleCloudtentaclesFetchBindUrl"
|
||||
:handle-cloudtentacles-back-vn="handleCloudtentaclesBackVn"
|
||||
:handle-cloudtentacles-run-full-flow="handleCloudtentaclesRunFullFlow"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<AdminPlatformCloudtentaclesSection
|
||||
v-else-if="isDevMode && activePlatform === 'cloudtentacles'"
|
||||
:cloudtentacles-file-path="cloudtentaclesFilePath"
|
||||
:cloudtentacles-session-file-path="cloudtentaclesSessionFilePath"
|
||||
:cloudtentacles-form="cloudtentaclesForm"
|
||||
:cloudtentacles-saving="cloudtentaclesSaving"
|
||||
:cloudtentacles-sending-sms="cloudtentaclesSendingSms"
|
||||
:cloudtentacles-testing="cloudtentaclesTesting"
|
||||
:cloudtentacles-validating="cloudtentaclesValidating"
|
||||
:cloudtentacles-result-error="cloudtentaclesResultError"
|
||||
:cloudtentacles-sms-result="cloudtentaclesSmsResult"
|
||||
:cloudtentacles-login-result="cloudtentaclesLoginResult"
|
||||
:cloudtentacles-validate-result="cloudtentaclesValidateResult"
|
||||
:cloudtentacles-debug-loading="cloudtentaclesDebugLoading"
|
||||
:cloudtentacles-debug-result="cloudtentaclesDebugResult"
|
||||
:cloudtentacles-persisted-session="cloudtentaclesPersistedSession"
|
||||
:cloudtentacles-stats="cloudtentaclesStats"
|
||||
:sources="cloudtentaclesSources"
|
||||
:sessions="cloudtentaclesSessions"
|
||||
:selected-source-key="selectedCloudtentaclesSourceKey"
|
||||
:current-source-enabled="currentCloudtentaclesSourceEnabled"
|
||||
:current-source="currentCloudtentaclesSource"
|
||||
:current-session="currentCloudtentaclesSession"
|
||||
:switch-source="switchCloudtentaclesSource"
|
||||
:add-source="addCloudtentaclesSource"
|
||||
:remove-source="removeCloudtentaclesSource"
|
||||
:handle-cloudtentacles-save-source="handleCloudtentaclesSaveSource"
|
||||
:handle-cloudtentacles-send-sms-code="handleCloudtentaclesSendSmsCode"
|
||||
:handle-cloudtentacles-test-login="handleCloudtentaclesTestLogin"
|
||||
:handle-cloudtentacles-validate-session="handleCloudtentaclesValidateSession"
|
||||
:handle-cloudtentacles-fetch-asset="handleCloudtentaclesFetchAsset"
|
||||
:handle-cloudtentacles-fetch-categories="handleCloudtentaclesFetchCategories"
|
||||
:handle-cloudtentacles-fetch-sku-list="handleCloudtentaclesFetchSkuList"
|
||||
:handle-cloudtentacles-buy-sku="handleCloudtentaclesBuySku"
|
||||
:handle-cloudtentacles-use-sku="handleCloudtentaclesUseSku"
|
||||
:handle-cloudtentacles-fetch-knapsack="handleCloudtentaclesFetchKnapsack"
|
||||
:handle-cloudtentacles-fetch-vn-list="handleCloudtentaclesFetchVnList"
|
||||
:handle-cloudtentacles-appoint-vn="handleCloudtentaclesAppointVn"
|
||||
:handle-cloudtentacles-generate-vn-login-code="handleCloudtentaclesGenerateVnLoginCode"
|
||||
:handle-cloudtentacles-fetch-vn-code="handleCloudtentaclesFetchVnCode"
|
||||
:handle-cloudtentacles-verify-vn-code="handleCloudtentaclesVerifyVnCode"
|
||||
:handle-cloudtentacles-fetch-bind-url="handleCloudtentaclesFetchBindUrl"
|
||||
:handle-cloudtentacles-back-vn="handleCloudtentaclesBackVn"
|
||||
:handle-cloudtentacles-run-full-flow="handleCloudtentaclesRunFullFlow"
|
||||
/>
|
||||
</main>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
@@ -422,68 +431,85 @@ onMounted(loadConfigs)
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
/* 概览卡片网格 */
|
||||
.overview-grid {
|
||||
.platform-detail {
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.overview-card {
|
||||
cursor: pointer;
|
||||
transition:
|
||||
border-color 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.overview-card :deep(.el-card__body) {
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
.overview-card.is-active {
|
||||
border-color: var(--border-hover);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.card-head {
|
||||
.active-summary {
|
||||
display: flex;
|
||||
gap: var(--space-2);
|
||||
margin-bottom: var(--space-3);
|
||||
justify-content: space-between;
|
||||
gap: var(--space-4);
|
||||
align-items: center;
|
||||
padding: var(--space-4) var(--space-5);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-lg);
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.card-value {
|
||||
font-size: 26px;
|
||||
font-weight: 700;
|
||||
color: var(--text-primary);
|
||||
line-height: 1.1;
|
||||
.active-summary-copy {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.card-unit {
|
||||
color: var(--text-muted);
|
||||
font-size: var(--text-sm);
|
||||
margin-top: var(--space-1);
|
||||
}
|
||||
|
||||
.card-meta {
|
||||
color: var(--text-secondary);
|
||||
.summary-kicker {
|
||||
color: #2563eb;
|
||||
font-size: var(--text-xs);
|
||||
margin-top: var(--space-2);
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
/* Tab 切换 */
|
||||
.platform-tabs {
|
||||
margin-top: var(--space-2);
|
||||
.active-summary h2 {
|
||||
margin: 4px 0 0;
|
||||
color: var(--text-primary);
|
||||
font-size: var(--text-xl);
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.overview-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
.active-summary p {
|
||||
margin: var(--space-2) 0 0;
|
||||
color: var(--text-secondary);
|
||||
font-size: var(--text-sm);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.summary-metrics {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
gap: var(--space-3);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.summary-metric {
|
||||
min-width: 112px;
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid rgba(148, 163, 184, 0.18);
|
||||
border-radius: var(--radius-sm);
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.summary-metric span {
|
||||
color: var(--text-muted);
|
||||
font-size: var(--text-xs);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.summary-metric strong {
|
||||
color: var(--text-primary);
|
||||
font-size: var(--text-xl);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.active-summary {
|
||||
align-items: stretch;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.overview-grid {
|
||||
grid-template-columns: 1fr;
|
||||
.summary-metrics {
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
-15
@@ -28,21 +28,6 @@ defineProps<Props>()
|
||||
|
||||
<template>
|
||||
<div class="platform-section">
|
||||
<!-- 说明信息 -->
|
||||
<el-card class="section-card">
|
||||
<template #header>
|
||||
<span class="card-title">说明信息</span>
|
||||
</template>
|
||||
<el-descriptions :column="1" border size="small">
|
||||
<el-descriptions-item label="职责">
|
||||
接收 91卡券推送订单,未命中履约配置时先进入待补全队列,补完商品规则后可手动重试生成任务。
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="处理建议">
|
||||
先到"快手 Cloud 新履约"页为 91 的 productNo 配置规则,再回到这里点击重试。
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<!-- 订单队列 -->
|
||||
<el-card class="section-card">
|
||||
<template #header>
|
||||
|
||||
Reference in New Issue
Block a user