优化履约配置ui

This commit is contained in:
yml
2026-05-22 09:41:48 +08:00
parent ecab6ae9b7
commit f15b772333
11 changed files with 326 additions and 133 deletions
+11 -7
View File
@@ -1,9 +1,13 @@
{
"token": "P1ifGvDcxYchECzx51cqL2TzBkntjQtRwxpetU7RDMMjsSCmC8kHU751bJ4rJMSSjQN73QveARqGLIWe078nKvnA",
"baseUrl": "https://123.207.217.176",
"username": "17665234375",
"phone": "17665234375",
"loggedInAt": "2026-05-19T13:48:31.443Z",
"deviceId": "-",
"deviceType": 0
"sessions": {
"default": {
"token": "P1ifGvDcxYchECzx51cqL2TzBkntjQtRwxpetU7RDMMjsSCmC8kHU751bJ4rJMSSjQN73QveARqGLIWe078nKvnA",
"baseUrl": "https://123.207.217.176",
"username": "17665234375",
"phone": "17665234375",
"loggedInAt": "2026-05-22T01:39:20.128Z",
"deviceId": "-",
"deviceType": 0
}
}
}
@@ -56,4 +56,13 @@ const activeTab = computed<FulfillmentTabKey>({
:deep(.hub-tabs .el-tabs__content) {
padding-top: var(--space-4);
}
:deep(.hub-tabs .el-tabs__item) {
font-weight: 500;
font-size: var(--text-base);
}
:deep(.hub-tabs .el-tabs__item.is-active) {
font-weight: 600;
}
</style>
@@ -5,41 +5,83 @@
.section-card {
border-radius: var(--radius-lg);
border: 1px solid var(--border-default);
background: var(--bg-surface);
}
.section-card :deep(.el-card__header) {
background: var(--bg-surface);
border-bottom: 1px solid var(--border-default);
padding: var(--space-4) var(--space-5);
}
.section-card :deep(.el-card__body) {
padding: var(--space-5);
}
.card-header {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.card-header--split {
align-items: center;
flex-direction: row;
justify-content: space-between;
align-items: flex-start;
}
.card-title {
display: block;
font-size: var(--text-lg);
font-weight: 600;
color: var(--text-primary);
margin-bottom: var(--space-1);
}
.card-desc {
display: block;
font-size: var(--text-sm);
color: var(--text-secondary);
line-height: 1.5;
}
.overview-card {
display: grid;
gap: var(--space-4);
gap: var(--space-5);
}
.overview-file {
margin-top: var(--space-1);
}
.overview-file code {
color: var(--text-primary);
word-break: break-all;
font-size: var(--text-sm);
}
.overview-stats {
display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: var(--space-3);
gap: var(--space-4);
}
.overview-stat {
min-width: 0;
padding: var(--space-3);
padding: var(--space-4);
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
background: var(--bg-subtle);
background: var(--bg-surface);
}
.overview-stat :deep(.el-statistic__head) {
margin-bottom: 6px;
margin-bottom: var(--space-2);
color: var(--text-secondary);
font-size: var(--text-xs);
font-weight: 700;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.overview-stat :deep(.el-statistic__content) {
@@ -58,7 +100,7 @@
.lookup-toolbar,
.lookup-summary {
display: grid;
gap: var(--space-3);
gap: var(--space-4);
}
.lookup-toolbar {
@@ -67,15 +109,15 @@
}
.lookup-summary {
margin-top: var(--space-4);
margin-top: var(--space-1);
}
.field-help {
display: block;
margin-top: 6px;
margin-top: var(--space-2);
color: var(--text-secondary);
font-size: var(--text-xs);
line-height: 1.5;
line-height: 1.6;
}
.field-wide {
@@ -98,32 +140,41 @@
.admin-panel :deep(.el-form-item__label) {
color: var(--text-secondary);
font-size: var(--text-xs);
font-weight: 700;
line-height: 1.4;
margin-bottom: 6px;
font-size: var(--text-sm);
font-weight: 600;
line-height: 1.5;
margin-bottom: var(--space-2);
}
.cell-subtle {
color: var(--text-secondary);
display: block;
font-size: var(--text-xs);
line-height: 1.5;
line-height: 1.6;
}
.cell-stack {
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.binding-card {
margin-top: var(--space-3);
background: var(--bg-surface);
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
}
.binding-card :deep(.el-card__header) {
padding: var(--space-3) var(--space-4);
background: var(--bg-subtle);
background: var(--bg-surface);
border-bottom: 1px solid var(--border-default);
}
.binding-card :deep(.el-card__body) {
display: grid;
gap: var(--space-3);
gap: var(--space-4);
padding: var(--space-4);
}
@@ -135,13 +186,14 @@
.binding-header {
display: flex;
justify-content: space-between;
gap: var(--space-3);
gap: var(--space-4);
align-items: flex-start;
}
.binding-summary {
display: grid;
gap: 4px;
gap: var(--space-2);
flex: 1;
}
.binding-title-row {
@@ -150,16 +202,19 @@
align-items: center;
flex-wrap: wrap;
color: var(--text-primary);
font-size: var(--text-base);
}
.binding-subtle {
color: var(--text-secondary);
font-size: var(--text-sm);
line-height: 1.5;
}
.binding-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--space-4);
gap: var(--space-4) var(--space-5);
}
.binding-collapsed-preview {
@@ -167,11 +222,17 @@
font-size: var(--text-sm);
}
.binding-collapsed-preview :deep(.el-descriptions__label) {
font-weight: 600;
}
.binding-actions {
display: flex;
justify-content: space-between;
gap: var(--space-3);
align-items: center;
padding-top: var(--space-3);
border-top: 1px solid var(--border-default);
}
@media (max-width: 900px) {
@@ -181,6 +242,7 @@
display: grid;
grid-template-columns: 1fr;
align-items: stretch;
gap: var(--space-3);
}
.overview-stats,
@@ -192,4 +254,37 @@
.binding-collapsed-preview :deep(.el-descriptions__body .el-descriptions__table) {
display: block;
}
.section-card :deep(.el-card__header),
.section-card :deep(.el-card__body) {
padding: var(--space-4);
}
.binding-card :deep(.el-card__header),
.binding-card :deep(.el-card__body) {
padding: var(--space-3);
}
}
.data-table {
margin-top: var(--space-4);
}
.data-table :deep(.el-table__header th) {
background: var(--bg-surface);
color: var(--text-secondary);
font-weight: 600;
font-size: var(--text-sm);
}
.data-table :deep(.el-table__body td) {
padding: var(--space-3) var(--space-2);
}
.mt-4 {
margin-top: var(--space-4);
}
.w-full {
width: 100%;
}
@@ -5,7 +5,6 @@ import { hasAdminRole } from '@/utils/admin-auth'
import AdminBindingsLookupSection from './components/AdminBindingsLookupSection.vue'
import AdminBindingsObservedSection from './components/AdminBindingsObservedSection.vue'
import AdminBindingsOverviewSection from './components/AdminBindingsOverviewSection.vue'
import AdminBindingsRuleSection from './components/AdminBindingsRuleSection.vue'
import { useFulfillmentBindings } from './composables/useFulfillmentBindings'
import { useFulfillmentBindingsLookup } from './composables/useFulfillmentBindingsLookup'
@@ -21,13 +20,6 @@ onMounted(bindings.loadConfigs)
<el-result v-if="!hasAdminRole('admin')" icon="warning" title="仅管理员可以维护履约配置" />
<template v-else>
<AdminBindingsOverviewSection
:file-path="bindings.filePath.value"
:rule-metrics="bindings.ruleMetrics.value"
:pending-observed-count="bindings.pendingObservedCount.value"
:observed-products-length="bindings.observedProducts.value.length"
/>
<el-alert
v-if="bindings.errorMessage.value"
:title="bindings.errorMessage.value"
@@ -29,7 +29,7 @@ const emit = defineEmits<{
>新商品还没配规则时可以按店铺 ID 和平台订单号临时补查查完直接导入规则草稿</span
>
</div>
<el-tag effect="plain">仅支持 Agiso 咸鱼订单</el-tag>
<el-tag effect="plain" size="small">仅支持 Agiso 咸鱼订单</el-tag>
</div>
</template>
@@ -67,23 +67,14 @@ const emit = defineEmits<{
</el-form-item>
</el-form>
<el-alert
title="查询结果只用于补配置,不会写入订单库,也不会影响现有订单数据。"
type="info"
show-icon
:closable="false"
class="mt-4"
/>
<el-alert
v-if="lookupErrorMessage"
:title="lookupErrorMessage"
type="error"
show-icon
:closable="false"
class="mt-4"
/>
<el-skeleton v-else-if="lookupLoading" :rows="4" animated class="mt-4" />
<el-skeleton v-else-if="lookupLoading" :rows="4" animated />
<template v-else-if="lookupResult">
<div class="lookup-summary">
<el-descriptions :column="3" border>
@@ -25,8 +25,10 @@ const emit = defineEmits<{
>
</div>
<el-space wrap>
<el-tag type="warning" effect="plain">待补 {{ pendingObservedCount }}</el-tag>
<el-tag effect="plain">总计 {{ observedProducts.length }}</el-tag>
<el-tag type="warning" effect="plain" size="small"
>待补 {{ pendingObservedCount }}</el-tag
>
<el-tag effect="plain" size="small">总计 {{ observedProducts.length }}</el-tag>
</el-space>
</div>
</template>
@@ -30,17 +30,17 @@ defineProps<{
</el-descriptions>
<div class="overview-stats">
<el-statistic class="overview-stat" title="规则总数" :value="ruleMetrics.totalCount" />
<el-statistic class="overview-stat" title="商品总数" :value="ruleMetrics.totalCount" />
<el-statistic class="overview-stat" title="完整规则" :value="ruleMetrics.completedCount" />
<el-statistic class="overview-stat" title="待完善" :value="ruleMetrics.draftCount" />
<el-statistic class="overview-stat" title="待补商品" :value="pendingObservedCount" />
<el-statistic class="overview-stat" title="已识别商品" :value="observedProductsLength" />
<el-statistic class="overview-stat" title="已忽略商品" :value="observedProductsLength" />
</div>
<div class="overview-notes">
<el-tag effect="plain">外部 SKU / 商品 ID / 商品名命中任一即可</el-tag>
<el-tag effect="plain">内部 SKU 决定库存绑定与履约链路</el-tag>
<el-tag effect="plain">同类商品跨平台尽量共用同一内部 SKU</el-tag>
<el-tag effect="plain" size="small">外部 SKU / 商品 ID / 商品名命中任一即可</el-tag>
<el-tag effect="plain" size="small">内部 SKU 决定库存绑定与履约链路</el-tag>
<el-tag effect="plain" size="small">同类商品跨平台尽量共用同一内部 SKU</el-tag>
</div>
</el-card>
</template>
@@ -57,11 +57,15 @@ const emit = defineEmits<{
</template>
<div class="section-mini-stats">
<el-tag type="success" effect="plain">完整 {{ ruleMetrics.completedCount }}</el-tag>
<el-tag type="warning" effect="plain">待完善 {{ ruleMetrics.draftCount }}</el-tag>
<el-tag effect="plain">人工 {{ ruleMetrics.manualCount }}</el-tag>
<el-tag effect="plain">半自动 {{ ruleMetrics.assistedCount }}</el-tag>
<el-tag effect="plain">快手 Cloud {{ ruleMetrics.kuaishouCloudCount }}</el-tag>
<el-tag type="success" effect="plain" size="small"
>完整 {{ ruleMetrics.completedCount }}</el-tag
>
<el-tag type="warning" effect="plain" size="small"
>待完善 {{ ruleMetrics.draftCount }}</el-tag
>
<el-tag effect="plain" size="small">人工 {{ ruleMetrics.manualCount }}</el-tag>
<el-tag effect="plain" size="small">半自动 {{ ruleMetrics.assistedCount }}</el-tag>
<el-tag effect="plain" size="small">快手 Cloud {{ ruleMetrics.kuaishouCloudCount }}</el-tag>
</div>
<el-alert
@@ -76,7 +80,7 @@ const emit = defineEmits<{
<el-empty
v-if="bindings.length === 0"
description="当前还没有履约规则,先新增一条。"
:image-size="60"
:image-size="80"
/>
<AdminBindingRuleCard
@@ -5,10 +5,45 @@
.section-card {
border-radius: var(--radius-lg);
border: 1px solid var(--border-default);
background: var(--bg-surface);
}
.section-card :deep(.el-card__header) {
background: var(--bg-surface);
border-bottom: 1px solid var(--border-default);
padding: var(--space-4) var(--space-5);
}
.section-card :deep(.el-card__body) {
padding: var(--space-5);
}
.card-header {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.card-header--split {
align-items: center;
flex-direction: row;
justify-content: space-between;
align-items: flex-start;
}
.card-title {
display: block;
font-size: var(--text-lg);
font-weight: 600;
color: var(--text-primary);
margin-bottom: var(--space-1);
}
.card-desc {
display: block;
font-size: var(--text-sm);
color: var(--text-secondary);
line-height: 1.5;
}
.overview-card {
@@ -32,7 +67,7 @@
padding: var(--space-3);
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
background: var(--bg-subtle);
background: var(--bg-surface);
}
.overview-stat :deep(.el-statistic__head) {
@@ -54,13 +89,51 @@
gap: var(--space-2);
}
.lookup-panel {
display: grid;
gap: var(--space-3);
padding: var(--space-4);
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
background: var(--bg-subtle);
}
.lookup-toolbar {
display: grid;
grid-template-columns: minmax(180px, 1fr) 110px 130px 180px;
gap: var(--space-3);
grid-template-columns:
minmax(260px, 1.4fr)
minmax(132px, 0.36fr)
minmax(150px, 0.44fr)
minmax(210px, 0.5fr);
gap: var(--space-3) var(--space-4);
align-items: end;
}
.lookup-field {
min-width: 0;
}
.lookup-field--number :deep(.el-input-number) {
width: 100%;
}
.lookup-action {
width: 100%;
min-height: 40px;
}
.lookup-note {
margin-top: 0;
}
.lookup-note :deep(.el-alert__content) {
min-width: 0;
}
.lookup-note :deep(.el-alert__title) {
line-height: 1.6;
}
.rule-action-row {
display: flex;
flex-wrap: wrap;
@@ -77,16 +150,19 @@
.binding-card {
margin-top: var(--space-3);
background: var(--bg-surface);
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
}
.binding-card :deep(.el-card__header) {
padding: var(--space-3) var(--space-4);
background: var(--bg-subtle);
background: var(--bg-surface);
border-bottom: 1px solid var(--border-default);
}
.binding-card :deep(.el-card__body) {
display: grid;
gap: var(--space-3);
gap: var(--space-4);
padding: var(--space-4);
}
@@ -104,7 +180,7 @@
.binding-summary {
display: grid;
gap: 4px;
gap: var(--space-2);
}
.binding-title-row {
@@ -123,7 +199,13 @@
.cell-subtle {
display: block;
font-size: var(--text-xs);
line-height: 1.5;
line-height: 1.6;
}
.cell-stack {
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.binding-collapsed-preview {
@@ -141,19 +223,14 @@
.mapping-panel {
min-width: 0;
background: var(--bg-surface);
}
.mapping-panel--external {
background: #f8fbff;
}
.mapping-panel--internal {
background: #fbfcff;
border: 1px solid var(--border-default);
border-radius: var(--radius-md);
}
.mapping-panel :deep(.el-card__header) {
padding: var(--space-3) var(--space-4);
background: var(--bg-subtle);
background: var(--bg-surface);
border-bottom: 1px solid var(--border-default);
}
.mapping-panel :deep(.el-card__body) {
@@ -204,7 +281,7 @@
min-width: 54px;
padding: 0 10px;
border-radius: var(--radius-full);
background: var(--color-primary-light);
background: var(--bg-surface);
border: 1px solid var(--border-default);
}
@@ -214,10 +291,10 @@
.field-help {
display: block;
margin-top: 6px;
margin-top: var(--space-2);
color: var(--text-secondary);
font-size: var(--text-xs);
line-height: 1.5;
line-height: 1.6;
}
.text-input {
@@ -234,10 +311,10 @@
.admin-panel :deep(.el-form-item__label) {
color: var(--text-secondary);
font-size: var(--text-xs);
font-weight: 700;
line-height: 1.4;
margin-bottom: 6px;
font-size: var(--text-sm);
font-weight: 600;
line-height: 1.5;
margin-bottom: var(--space-2);
}
.binding-actions {
@@ -245,12 +322,25 @@
flex-wrap: wrap;
gap: var(--space-3);
align-items: center;
padding-top: var(--space-3);
border-top: 1px solid var(--border-default);
}
.data-table {
margin-top: var(--space-4);
}
.data-table :deep(.el-table__header th) {
background: var(--bg-surface);
color: var(--text-secondary);
font-weight: 600;
font-size: var(--text-sm);
}
.data-table :deep(.el-table__body td) {
padding: var(--space-3) var(--space-2);
}
@media (max-width: 900px) {
.card-header--split,
.rule-action-row,
@@ -272,4 +362,14 @@
.mapping-arrow {
display: none;
}
.section-card :deep(.el-card__header),
.section-card :deep(.el-card__body) {
padding: var(--space-4);
}
.binding-card :deep(.el-card__header),
.binding-card :deep(.el-card__body) {
padding: var(--space-3);
}
}
@@ -4,7 +4,6 @@ import { onMounted } from 'vue'
import { hasAdminRole } from '@/utils/admin-auth'
import AdminKuaishouCloudNinetyoneSection from './components/AdminKuaishouCloudNinetyoneSection.vue'
import AdminKuaishouCloudOverviewSection from './components/AdminKuaishouCloudOverviewSection.vue'
import AdminKuaishouCloudRuleSection from './components/AdminKuaishouCloudRuleSection.vue'
import { useKuaishouCloudConfig } from './composables/useKuaishouCloudConfig'
import { useKuaishouCloudNinetyone } from './composables/useKuaishouCloudNinetyone'
@@ -22,11 +21,6 @@ onMounted(config.loadConfigs)
<el-result v-if="!hasAdminRole('admin')" icon="warning" title="仅管理员可以维护新履约配置" />
<template v-else>
<AdminKuaishouCloudOverviewSection
:file-path="config.filePath.value"
:metrics="config.metrics.value"
/>
<el-alert
v-if="config.errorMessage.value"
:title="config.errorMessage.value"
@@ -48,50 +48,52 @@ const emit = defineEmits<{
</div>
</template>
<el-form label-position="top" class="lookup-toolbar">
<el-form-item label="订单状态">
<el-select v-model="ninetyoneLookupForm.status" class="text-input">
<el-option label="待补全" value="pending_config" />
<el-option label="已失败" value="manual_failed" />
<el-option label="全部" value="all" />
</el-select>
</el-form-item>
<el-form-item label="页码">
<el-input-number
v-model="ninetyoneLookupForm.page"
class="text-input"
:min="1"
controls-position="right"
/>
</el-form-item>
<el-form-item label="每页条数">
<el-input-number
v-model="ninetyoneLookupForm.pageSize"
class="text-input"
:max="100"
:min="1"
controls-position="right"
/>
</el-form-item>
<el-form-item label="操作">
<el-button
:loading="ninetyoneLookupLoading"
type="primary"
class="w-full"
@click="emit('lookup')"
>
查询 91卡券订单
</el-button>
</el-form-item>
</el-form>
<div class="lookup-panel">
<el-form label-position="top" class="lookup-toolbar">
<el-form-item label="订单状态" class="lookup-field lookup-field--status">
<el-select v-model="ninetyoneLookupForm.status" class="text-input">
<el-option label="待补全" value="pending_config" />
<el-option label="已失败" value="manual_failed" />
<el-option label="全部" value="all" />
</el-select>
</el-form-item>
<el-form-item label="页码" class="lookup-field lookup-field--number">
<el-input-number
v-model="ninetyoneLookupForm.page"
class="text-input"
:min="1"
controls-position="right"
/>
</el-form-item>
<el-form-item label="每页条数" class="lookup-field lookup-field--number">
<el-input-number
v-model="ninetyoneLookupForm.pageSize"
class="text-input"
:max="100"
:min="1"
controls-position="right"
/>
</el-form-item>
<el-form-item label="操作" class="lookup-field lookup-field--action">
<el-button
:loading="ninetyoneLookupLoading"
type="primary"
class="lookup-action"
@click="emit('lookup')"
>
查询 91卡券订单
</el-button>
</el-form-item>
</el-form>
<el-alert
title="导入后会创建 provider=91kaquan、platform=kuaishou、外部 SKU=productNo 的规则草稿;保存规则后,回到“平台配置 -> 91卡券接入”重试订单。"
type="info"
show-icon
:closable="false"
class="mt-4"
/>
<el-alert
title="导入后会创建 provider=91kaquan、platform=kuaishou、外部 SKU=productNo 的规则草稿;保存规则后,回到“平台配置 -> 91卡券接入”重试订单。"
type="info"
show-icon
:closable="false"
class="lookup-note"
/>
</div>
<el-alert
v-if="ninetyoneLookupErrorMessage"