优化履约配置界面
This commit is contained in:
+159
@@ -285,6 +285,150 @@
|
||||
border: 1px solid var(--border-default);
|
||||
}
|
||||
|
||||
.rule-editor {
|
||||
display: grid;
|
||||
gap: var(--space-3);
|
||||
}
|
||||
|
||||
.rule-editor-main {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
|
||||
gap: var(--space-3);
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.rule-panel {
|
||||
display: grid;
|
||||
align-content: start;
|
||||
gap: var(--space-4);
|
||||
min-width: 0;
|
||||
padding: var(--space-4);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--bg-surface);
|
||||
}
|
||||
|
||||
.rule-panel--strategy {
|
||||
background: var(--bg-subtle);
|
||||
}
|
||||
|
||||
.rule-panel-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-3);
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.rule-panel-head > span {
|
||||
color: var(--text-secondary);
|
||||
font-size: var(--text-xs);
|
||||
line-height: 1.5;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.rule-panel-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
min-width: 0;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.rule-panel-title strong {
|
||||
font-size: var(--text-base);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.rule-step {
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
width: 30px;
|
||||
height: 24px;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-subtle);
|
||||
color: var(--text-secondary);
|
||||
font-size: var(--text-xs);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.rule-panel--strategy .rule-step {
|
||||
background: var(--bg-surface);
|
||||
}
|
||||
|
||||
.mapping-grid--core {
|
||||
gap: var(--space-3) var(--space-4);
|
||||
}
|
||||
|
||||
.strategy-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(150px, 0.24fr) minmax(150px, 0.24fr) minmax(0, 1fr);
|
||||
gap: var(--space-4);
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.strategy-checks {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-2) var(--space-4);
|
||||
min-height: 32px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.advanced-fields {
|
||||
border: 1px dashed var(--border-default);
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--bg-surface);
|
||||
}
|
||||
|
||||
.advanced-fields summary {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-3);
|
||||
align-items: center;
|
||||
padding: var(--space-3) var(--space-4);
|
||||
color: var(--text-primary);
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.advanced-fields summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.advanced-fields summary span {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.advanced-fields summary small {
|
||||
color: var(--text-secondary);
|
||||
font-size: var(--text-xs);
|
||||
line-height: 1.5;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.advanced-fields summary::after {
|
||||
content: '展开';
|
||||
flex: 0 0 auto;
|
||||
min-width: 40px;
|
||||
color: var(--color-primary);
|
||||
font-size: var(--text-xs);
|
||||
font-weight: 700;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.advanced-fields[open] summary {
|
||||
border-bottom: 1px dashed var(--border-default);
|
||||
}
|
||||
|
||||
.advanced-fields[open] summary::after {
|
||||
content: '收起';
|
||||
}
|
||||
|
||||
.advanced-grid {
|
||||
padding: var(--space-4);
|
||||
}
|
||||
|
||||
.field-wide {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
@@ -320,6 +464,7 @@
|
||||
.binding-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
gap: var(--space-3);
|
||||
align-items: center;
|
||||
padding-top: var(--space-3);
|
||||
@@ -353,12 +498,26 @@
|
||||
|
||||
.overview-stats,
|
||||
.lookup-toolbar,
|
||||
.rule-editor-main,
|
||||
.strategy-grid,
|
||||
.mapping-editor,
|
||||
.mapping-grid,
|
||||
.mapping-extra {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.rule-panel-head,
|
||||
.advanced-fields summary {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.rule-panel-head > span,
|
||||
.advanced-fields summary small {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mapping-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
+183
-153
@@ -77,16 +77,164 @@ const emit = defineEmits<{
|
||||
}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<div v-else class="mapping-editor">
|
||||
<el-card shadow="never" class="mapping-panel mapping-panel--external">
|
||||
<template #header>
|
||||
<div class="mapping-panel-head">
|
||||
<strong>外部商品</strong>
|
||||
<span>来源平台 / 快手侧命中条件</span>
|
||||
<div v-else class="rule-editor">
|
||||
<div class="rule-editor-main">
|
||||
<section class="rule-panel rule-panel--match">
|
||||
<div class="rule-panel-head">
|
||||
<div class="rule-panel-title">
|
||||
<span class="rule-step">01</span>
|
||||
<strong>商品匹配</strong>
|
||||
</div>
|
||||
<span>订单进来后先命中这里</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-form label-position="top" class="mapping-grid">
|
||||
<el-form label-position="top" class="mapping-grid mapping-grid--core">
|
||||
<el-form-item label="外部 SKU / productNo" class="field-wide">
|
||||
<el-input
|
||||
v-model="item.externalSkuCode"
|
||||
class="text-input"
|
||||
maxlength="120"
|
||||
placeholder="优先填写 91 卡券 productNo,例如 183999074512936"
|
||||
/>
|
||||
<small class="field-help">最推荐的命中条件。没有特殊情况时,只填这一项即可。</small>
|
||||
</el-form-item>
|
||||
<el-form-item label="内部 SKU">
|
||||
<el-input
|
||||
v-model="item.internalSkuCode"
|
||||
class="text-input"
|
||||
maxlength="80"
|
||||
placeholder="必填,例如 romantic-destiny-pack"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="内部商品名">
|
||||
<el-input
|
||||
v-model="item.internalSkuName"
|
||||
class="text-input"
|
||||
maxlength="120"
|
||||
placeholder="后台识别用,建议填清楚"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</section>
|
||||
|
||||
<section class="rule-panel rule-panel--delivery">
|
||||
<div class="rule-panel-head">
|
||||
<div class="rule-panel-title">
|
||||
<span class="rule-step">02</span>
|
||||
<strong>履约资源</strong>
|
||||
</div>
|
||||
<span>账号、cloud SKU 和核销店铺</span>
|
||||
</div>
|
||||
|
||||
<el-form label-position="top" class="mapping-grid mapping-grid--core">
|
||||
<el-form-item label="cloud 账号优先级" class="field-wide">
|
||||
<el-select
|
||||
v-model="item.cloudSourceKeys"
|
||||
class="text-input"
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
placeholder="按顺序选择可用于履约的 cloud 账号"
|
||||
@change="emit('handleCloudSourceKeysChanged')"
|
||||
>
|
||||
<el-option
|
||||
v-for="opt in cloudtentaclesSourceOptions"
|
||||
:key="opt.key"
|
||||
:label="opt.label || opt.key"
|
||||
:value="opt.key"
|
||||
/>
|
||||
</el-select>
|
||||
<small class="field-help">执行时从左到右尝试,SKU 列表使用第一个账号加载。</small>
|
||||
</el-form-item>
|
||||
<el-form-item label="cloud SKU">
|
||||
<el-select
|
||||
v-model="item.cloudSkuId"
|
||||
class="text-input"
|
||||
placeholder="请选择 cloud SKU"
|
||||
@change="emit('handleCloudSkuSelected', item.cloudSkuId)"
|
||||
@visible-change="emit('handleCloudSkuDropdownVisible', $event)"
|
||||
>
|
||||
<el-option label="请选择 cloud SKU" :value="0" />
|
||||
<el-option
|
||||
v-for="sku in getCloudSkuOptions(item)"
|
||||
:key="sku.id"
|
||||
:label="formatCloudSkuOptionLabel(sku)"
|
||||
:value="sku.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="cloud SKU 名称">
|
||||
<el-input
|
||||
:model-value="item.cloudSkuName"
|
||||
class="text-input"
|
||||
placeholder="选择后自动带出"
|
||||
readonly
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="快手核销店铺" class="field-wide">
|
||||
<el-select
|
||||
v-model="item.kuaishouConsumeShopId"
|
||||
class="text-input"
|
||||
placeholder="请选择已配置 Cookie 的快手小店"
|
||||
@change="emit('handleKuaishouConsumeShopSelected')"
|
||||
>
|
||||
<el-option label="请选择已配置 Cookie 的快手小店" value="" />
|
||||
<el-option
|
||||
v-for="shop in getKuaishouConsumeShopOptions()"
|
||||
:key="shop.shopId"
|
||||
:label="formatKuaishouConsumeShopOption(shop)"
|
||||
:value="shop.shopId"
|
||||
/>
|
||||
</el-select>
|
||||
<small class="field-help">来自“平台店铺 -> 快手小店核销”配置。</small>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="rule-panel rule-panel--strategy">
|
||||
<div class="rule-panel-head">
|
||||
<div class="rule-panel-title">
|
||||
<span class="rule-step">03</span>
|
||||
<strong>执行策略</strong>
|
||||
</div>
|
||||
<span>一般保持默认即可</span>
|
||||
</div>
|
||||
|
||||
<el-form label-position="top" class="strategy-grid">
|
||||
<el-form-item label="优先级">
|
||||
<el-input-number
|
||||
v-model="item.priority"
|
||||
class="text-input"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="最低保留余额">
|
||||
<el-input-number
|
||||
v-model="item.minAssetReserve"
|
||||
class="text-input"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="自动动作" class="field-wide">
|
||||
<div class="strategy-checks">
|
||||
<el-checkbox v-model="item.enabled">启用规则</el-checkbox>
|
||||
<el-checkbox v-model="item.autoBuyEnabled">自动购买</el-checkbox>
|
||||
<el-checkbox v-model="item.autoReturnNumberAfterDispatch">发货后退号</el-checkbox>
|
||||
<el-checkbox v-model="item.autoConsumeAfterDispatch">发货后核销</el-checkbox>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</section>
|
||||
|
||||
<details class="advanced-fields">
|
||||
<summary>
|
||||
<span>高级匹配与备注</span>
|
||||
<small>多店铺、多平台或人工排查时再展开</small>
|
||||
</summary>
|
||||
<el-form label-position="top" class="mapping-grid advanced-grid">
|
||||
<el-form-item label="来源 provider">
|
||||
<el-input
|
||||
v-model="item.provider"
|
||||
@@ -103,7 +251,7 @@ const emit = defineEmits<{
|
||||
placeholder="默认 kuaishou"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="店铺 ID" class="field-wide">
|
||||
<el-form-item label="店铺 ID">
|
||||
<el-input
|
||||
v-model="item.shopId"
|
||||
class="text-input"
|
||||
@@ -111,20 +259,12 @@ const emit = defineEmits<{
|
||||
placeholder="留空表示跨店铺共用"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="外部 SKU">
|
||||
<el-input
|
||||
v-model="item.externalSkuCode"
|
||||
class="text-input"
|
||||
maxlength="120"
|
||||
placeholder="例如 91卡券 productNo"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="外部商品 ID">
|
||||
<el-input
|
||||
v-model="item.externalItemId"
|
||||
class="text-input"
|
||||
maxlength="120"
|
||||
placeholder="平台商品 ID"
|
||||
placeholder="平台商品 ID,可选"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="外部商品名" class="field-wide">
|
||||
@@ -132,153 +272,47 @@ const emit = defineEmits<{
|
||||
v-model="item.externalSkuName"
|
||||
class="text-input"
|
||||
maxlength="200"
|
||||
placeholder="用于名称匹配"
|
||||
placeholder="只有需要按名称匹配时再填"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="解析商品名" class="field-wide">
|
||||
<el-form-item label="解析商品名">
|
||||
<el-input
|
||||
v-model="item.resolvedSkuName"
|
||||
class="text-input"
|
||||
maxlength="120"
|
||||
placeholder="可作为商品名兜底"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<div class="mapping-arrow" aria-hidden="true">
|
||||
<span>映射到</span>
|
||||
</div>
|
||||
|
||||
<el-card shadow="never" class="mapping-panel mapping-panel--internal">
|
||||
<template #header>
|
||||
<div class="mapping-panel-head">
|
||||
<strong>内部履约</strong>
|
||||
<span>内部 SKU + cloud 资源</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-form label-position="top" class="mapping-grid">
|
||||
<el-form-item label="内部 SKU">
|
||||
<el-input
|
||||
v-model="item.internalSkuCode"
|
||||
class="text-input"
|
||||
maxlength="80"
|
||||
placeholder="必填,用于生成任务"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="优先级">
|
||||
<el-input-number
|
||||
v-model="item.priority"
|
||||
class="text-input"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="内部商品名" class="field-wide">
|
||||
<el-input
|
||||
v-model="item.internalSkuName"
|
||||
class="text-input"
|
||||
maxlength="120"
|
||||
placeholder="展示用,可选但建议填"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="cloud 账号优先级" class="field-wide">
|
||||
<el-select
|
||||
v-model="item.cloudSourceKeys"
|
||||
class="text-input"
|
||||
multiple
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
placeholder="按顺序选择可用于履约的 cloud 账号"
|
||||
@change="emit('handleCloudSourceKeysChanged')"
|
||||
>
|
||||
<el-option
|
||||
v-for="opt in cloudtentaclesSourceOptions"
|
||||
:key="opt.key"
|
||||
:label="opt.label || opt.key"
|
||||
:value="opt.key"
|
||||
/>
|
||||
</el-select>
|
||||
<small class="field-help">执行时会从左到右尝试,SKU 列表使用第一个账号加载。</small>
|
||||
</el-form-item>
|
||||
<el-form-item label="cloud SKU ID">
|
||||
<el-select
|
||||
v-model="item.cloudSkuId"
|
||||
class="text-input"
|
||||
@change="emit('handleCloudSkuSelected', item.cloudSkuId)"
|
||||
@visible-change="emit('handleCloudSkuDropdownVisible', $event)"
|
||||
>
|
||||
<el-option label="请选择 cloud SKU" :value="0" />
|
||||
<el-option
|
||||
v-for="sku in getCloudSkuOptions(item)"
|
||||
:key="sku.id"
|
||||
:label="formatCloudSkuOptionLabel(sku)"
|
||||
:value="sku.id"
|
||||
/>
|
||||
</el-select>
|
||||
<small class="field-help">先填内部 SKU / 商品名,再选择会更容易匹配。</small>
|
||||
</el-form-item>
|
||||
<el-form-item label="cloud SKU 名称" class="field-wide">
|
||||
<el-input
|
||||
:model-value="item.cloudSkuName"
|
||||
class="text-input"
|
||||
placeholder="选择 cloud SKU 后自动带出"
|
||||
readonly
|
||||
placeholder="商品名兜底,可选"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="虚拟号 VN Key">
|
||||
<el-input class="text-input" model-value="1" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="最低保留余额">
|
||||
<el-input-number
|
||||
v-model="item.minAssetReserve"
|
||||
<el-form-item label="核销店铺 ID">
|
||||
<el-input
|
||||
:model-value="item.kuaishouConsumeShopId || '-'"
|
||||
class="text-input"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
readonly
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="核销店铺名">
|
||||
<el-input
|
||||
:model-value="item.kuaishouConsumeShopName || '-'"
|
||||
class="text-input"
|
||||
readonly
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" class="field-wide">
|
||||
<el-input
|
||||
v-model="item.notes"
|
||||
class="text-input textarea-input"
|
||||
maxlength="400"
|
||||
placeholder="绑定场景、客服注意事项等"
|
||||
type="textarea"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<el-form v-if="!isCollapsed" label-position="top" class="mapping-extra">
|
||||
<el-form-item label="快手核销店铺" class="field-wide">
|
||||
<el-select
|
||||
v-model="item.kuaishouConsumeShopId"
|
||||
class="text-input"
|
||||
placeholder="请选择已配置 Cookie 的快手小店"
|
||||
@change="emit('handleKuaishouConsumeShopSelected')"
|
||||
>
|
||||
<el-option label="请选择已配置 Cookie 的快手小店" value="" />
|
||||
<el-option
|
||||
v-for="shop in getKuaishouConsumeShopOptions()"
|
||||
:key="shop.shopId"
|
||||
:label="formatKuaishouConsumeShopOption(shop)"
|
||||
:value="shop.shopId"
|
||||
/>
|
||||
</el-select>
|
||||
<small class="field-help"
|
||||
>来自"平台店铺 -> 快手小店核销"配置,保存时会自动带出店铺名。</small
|
||||
>
|
||||
</el-form-item>
|
||||
<el-form-item label="核销店铺 ID">
|
||||
<el-input :model-value="item.kuaishouConsumeShopId || '-'" class="text-input" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="核销店铺名">
|
||||
<el-input :model-value="item.kuaishouConsumeShopName || '-'" class="text-input" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" class="field-wide">
|
||||
<el-input
|
||||
v-model="item.notes"
|
||||
class="text-input textarea-input"
|
||||
maxlength="400"
|
||||
placeholder="绑定场景、客服注意事项等"
|
||||
type="textarea"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-alert
|
||||
v-if="validationState?.localId === item.localId"
|
||||
:title="validationState?.message"
|
||||
@@ -294,11 +328,7 @@ const emit = defineEmits<{
|
||||
:closable="false"
|
||||
/>
|
||||
|
||||
<div class="binding-actions">
|
||||
<el-checkbox v-model="item.enabled">启用规则</el-checkbox>
|
||||
<el-checkbox v-model="item.autoBuyEnabled">自动购买</el-checkbox>
|
||||
<el-checkbox v-model="item.autoReturnNumberAfterDispatch">发货后退号</el-checkbox>
|
||||
<el-checkbox v-model="item.autoConsumeAfterDispatch">发货后核销</el-checkbox>
|
||||
<div v-if="!isCollapsed" class="binding-actions">
|
||||
<el-button link type="danger" @click="emit('remove')">删除</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
Reference in New Issue
Block a user