This commit is contained in:
Leo
2025-12-02 01:45:22 +08:00
parent 86e8fefb97
commit a12a17df21
2 changed files with 663 additions and 1 deletions

View File

@@ -0,0 +1,650 @@
<template>
<el-dialog
:visible.sync="visible"
width="900px"
:close-on-click-modal="false"
@close="handleClose"
top="5vh"
>
<!-- 自定义标题 -->
<div slot="title" class="dialog-title">
<i class="el-icon-user"></i>
<span>分销标识接收人配置</span>
<el-tag v-if="hasConfigured" type="success" size="mini" style="margin-left: 10px;">
<i class="el-icon-success"></i> 已配置 {{ configuredCount }}
</el-tag>
</div>
<div class="config-container">
<!-- 左侧配置表单 -->
<div class="config-left">
<div class="config-section">
<div class="section-header">
<i class="el-icon-setting"></i>
<span>分销标识接收人映射</span>
<el-button
type="text"
size="mini"
icon="el-icon-plus"
@click="handleAddConfig"
style="margin-left: auto;"
>
添加配置
</el-button>
</div>
<div class="config-list">
<div
v-for="(item, index) in configList"
:key="index"
class="config-item"
>
<div class="item-header">
<el-input
v-model="item.distributionMark"
placeholder="分销标识F、PDD、H-TF"
size="small"
style="width: 200px;"
@blur="handleDistributionMarkChange(item, index)"
/>
<el-button
type="danger"
size="mini"
icon="el-icon-delete"
@click="handleRemoveConfig(index)"
style="margin-left: 10px;"
>
删除
</el-button>
</div>
<div class="item-content">
<el-input
v-model="item.touser"
placeholder="接收人列表多个用逗号分隔abc,bcd,efg"
size="small"
style="margin-top: 8px;"
/>
<div class="item-hint">
<i class="el-icon-info"></i>
配置键名logistics.push.touser.{{ item.distributionMark || '分销标识' }}
</div>
</div>
</div>
<div v-if="configList.length === 0" class="empty-state">
<i class="el-icon-document-add"></i>
<p>暂无配置点击"添加配置"开始设置</p>
</div>
</div>
</div>
</div>
<!-- 右侧状态信息 -->
<div class="config-right">
<!-- 配置状态提示 -->
<div class="status-card">
<div class="status-icon" :class="hasConfigured ? 'success' : 'warning'">
<i :class="hasConfigured ? 'el-icon-success' : 'el-icon-warning'"></i>
</div>
<div class="status-text">
<div class="status-title">{{ hasConfigured ? '配置完成' : '配置未完成' }}</div>
<div class="status-desc">
{{ hasConfigured ? `已配置 ${configuredCount} 个分销标识的接收人` : '请至少配置一个分销标识的接收人' }}
</div>
</div>
</div>
<!-- 快速帮助 -->
<div class="help-card">
<div class="card-header">
<i class="el-icon-question"></i>
<span>配置说明</span>
</div>
<div class="help-content">
<div class="help-item">
<i class="el-icon-check"></i>
<span>分销标识必须与订单中的分销标识完全匹配</span>
</div>
<div class="help-item">
<i class="el-icon-check"></i>
<span>接收人列表用逗号分隔例如abc,bcd,efg</span>
</div>
<div class="help-item">
<i class="el-icon-check"></i>
<span>配置会自动保存到系统配置表中</span>
</div>
<div class="help-item">
<i class="el-icon-check"></i>
<span>推送时会根据订单的分销标识自动匹配接收人</span>
</div>
</div>
</div>
<!-- 常见分销标识 -->
<div class="help-card">
<div class="card-header">
<i class="el-icon-collection-tag"></i>
<span>常见分销标识</span>
</div>
<div class="help-content">
<div class="tag-list">
<el-tag
v-for="mark in commonDistributionMarks"
:key="mark"
size="small"
@click="handleQuickAdd(mark)"
style="cursor: pointer; margin: 4px;"
>
{{ mark }}
</el-tag>
</div>
</div>
</div>
</div>
</div>
<!-- 操作按钮 -->
<div slot="footer" class="footer-buttons">
<div class="footer-left">
<el-button @click="handleLoadFromOrders" :loading="loadLoading" icon="el-icon-refresh" size="small">
从订单加载分销标识
</el-button>
</div>
<div class="footer-right">
<el-button @click="handleClose" size="small">取消</el-button>
<el-button type="primary" @click="handleSave" :loading="saveLoading" size="small">
<i class="el-icon-check"></i> 保存配置
</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
import { listConfig, getConfigKey, addConfig, updateConfig } from '@/api/system/config'
import { listJDOrders } from '@/api/system/jdorder'
export default {
name: 'DistributionMarkTouserConfig',
props: {
value: {
type: Boolean,
default: false
}
},
data() {
return {
visible: false,
configList: [],
saveLoading: false,
loadLoading: false,
commonDistributionMarks: ['F', 'PDD', 'H-TF', 'H', 'TF'],
configKeyPrefix: 'logistics.push.touser.'
}
},
computed: {
hasConfigured() {
return this.configList.some(item =>
item.distributionMark && item.touser && item.distributionMark.trim() && item.touser.trim()
)
},
configuredCount() {
return this.configList.filter(item =>
item.distributionMark && item.touser && item.distributionMark.trim() && item.touser.trim()
).length
}
},
watch: {
value(val) {
this.visible = val
if (val) {
this.loadConfig()
}
},
visible(val) {
this.$emit('input', val)
}
},
methods: {
/** 加载当前配置 */
async loadConfig() {
try {
// 先尝试从系统配置中加载已有的配置
// 由于我们不知道有哪些分销标识,先加载所有以 logistics.push.touser. 开头的配置
const res = await listConfig({
configKey: 'logistics.push.touser.',
pageNum: 1,
pageSize: 100
})
if (res.code === 200 && res.rows && res.rows.length > 0) {
this.configList = res.rows
.filter(item => item.configKey && item.configKey.startsWith(this.configKeyPrefix))
.map(item => {
const distributionMark = item.configKey.replace(this.configKeyPrefix, '')
return {
distributionMark: distributionMark,
touser: item.configValue || '',
configId: item.configId,
configKey: item.configKey,
configName: item.configName
}
})
}
// 如果没有配置,至少添加一个空项
if (this.configList.length === 0) {
this.configList.push({
distributionMark: '',
touser: '',
configId: null,
configKey: '',
configName: ''
})
}
} catch (e) {
console.error('加载配置失败:', e)
// 即使加载失败,也至少添加一个空项
if (this.configList.length === 0) {
this.configList.push({
distributionMark: '',
touser: '',
configId: null,
configKey: '',
configName: ''
})
}
}
},
/** 从订单中加载分销标识 */
async handleLoadFromOrders() {
this.loadLoading = true
try {
const res = await listJDOrders({
pageNum: 1,
pageSize: 1000
})
if (res.code === 200 && res.rows) {
// 提取所有不重复的分销标识
const distributionMarks = [...new Set(
res.rows
.map(order => order.distributionMark)
.filter(mark => mark && mark.trim())
)].sort()
// 为每个分销标识添加配置项(如果不存在)
distributionMarks.forEach(mark => {
const exists = this.configList.some(item => item.distributionMark === mark)
if (!exists) {
this.configList.push({
distributionMark: mark,
touser: '',
configId: null,
configKey: this.configKeyPrefix + mark,
configName: `${mark}分销标识接收人`
})
}
})
this.$message.success(`已加载 ${distributionMarks.length} 个分销标识`)
}
} catch (e) {
this.$message.error('加载分销标识失败:' + (e.message || '未知错误'))
} finally {
this.loadLoading = false
}
},
/** 快速添加分销标识 */
handleQuickAdd(mark) {
const exists = this.configList.some(item => item.distributionMark === mark)
if (!exists) {
this.configList.push({
distributionMark: mark,
touser: '',
configId: null,
configKey: this.configKeyPrefix + mark,
configName: `${mark}分销标识接收人`
})
this.$message.success(`已添加分销标识:${mark}`)
} else {
this.$message.info(`分销标识 ${mark} 已存在`)
}
},
/** 添加配置项 */
handleAddConfig() {
this.configList.push({
distributionMark: '',
touser: '',
configId: null,
configKey: '',
configName: ''
})
},
/** 删除配置项 */
handleRemoveConfig(index) {
this.configList.splice(index, 1)
// 如果删除后列表为空,至少保留一个空项
if (this.configList.length === 0) {
this.handleAddConfig()
}
},
/** 分销标识变化时更新配置键名 */
handleDistributionMarkChange(item, index) {
if (item.distributionMark && item.distributionMark.trim()) {
item.configKey = this.configKeyPrefix + item.distributionMark.trim()
item.configName = `${item.distributionMark.trim()}分销标识接收人`
} else {
item.configKey = ''
item.configName = ''
}
},
/** 保存配置 */
async handleSave() {
// 验证配置
const validConfigs = this.configList.filter(item =>
item.distributionMark && item.distributionMark.trim() &&
item.touser && item.touser.trim()
)
if (validConfigs.length === 0) {
this.$message.warning('请至少配置一个有效的分销标识和接收人')
return
}
// 检查是否有重复的分销标识
const marks = validConfigs.map(item => item.distributionMark.trim())
const uniqueMarks = [...new Set(marks)]
if (marks.length !== uniqueMarks.length) {
this.$message.warning('存在重复的分销标识,请检查')
return
}
this.saveLoading = true
try {
// 保存每个配置项
const savePromises = validConfigs.map(async (item) => {
const configData = {
configKey: this.configKeyPrefix + item.distributionMark.trim(),
configName: `${item.distributionMark.trim()}分销标识接收人`,
configValue: item.touser.trim(),
configType: 'N',
remark: `分销标识 ${item.distributionMark.trim()} 对应的企业微信接收人列表`
}
if (item.configId) {
// 更新现有配置
configData.configId = item.configId
return updateConfig(configData)
} else {
// 新增配置
return addConfig(configData)
}
})
await Promise.all(savePromises)
this.$message.success(`配置保存成功!共保存 ${validConfigs.length} 项配置`)
// 重新加载配置
await this.loadConfig()
this.$emit('config-updated')
} catch (e) {
this.$message.error('保存失败:' + (e.message || '未知错误'))
} finally {
this.saveLoading = false
}
},
/** 关闭对话框 */
handleClose() {
this.visible = false
}
}
}
</script>
<style scoped>
/* 标题样式 */
.dialog-title {
display: flex;
align-items: center;
font-size: 16px;
font-weight: 500;
}
.dialog-title i {
margin-right: 8px;
font-size: 18px;
}
/* 容器布局 */
.config-container {
display: flex;
gap: 20px;
min-height: 400px;
}
.config-left {
flex: 1;
display: flex;
flex-direction: column;
gap: 15px;
}
.config-right {
width: 300px;
display: flex;
flex-direction: column;
gap: 15px;
}
/* 配置区块 */
.config-section {
background: #f5f7fa;
border-radius: 6px;
padding: 15px;
}
.section-header {
display: flex;
align-items: center;
font-size: 14px;
font-weight: 500;
color: #303133;
margin-bottom: 12px;
padding-bottom: 8px;
border-bottom: 2px solid #e4e7ed;
}
.section-header i {
margin-right: 6px;
font-size: 16px;
color: #409eff;
}
/* 配置列表 */
.config-list {
display: flex;
flex-direction: column;
gap: 15px;
max-height: 500px;
overflow-y: auto;
}
.config-item {
background: white;
border: 1px solid #e4e7ed;
border-radius: 6px;
padding: 12px;
}
.item-header {
display: flex;
align-items: center;
}
.item-content {
margin-top: 8px;
}
.item-hint {
font-size: 12px;
color: #909399;
margin-top: 6px;
display: flex;
align-items: center;
gap: 4px;
}
.item-hint i {
color: #409eff;
}
.empty-state {
text-align: center;
padding: 40px 20px;
color: #909399;
}
.empty-state i {
font-size: 48px;
margin-bottom: 10px;
display: block;
}
/* 状态卡片 */
.status-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 8px;
padding: 20px;
color: white;
display: flex;
align-items: center;
gap: 15px;
box-shadow: 0 2px 12px rgba(102, 126, 234, 0.3);
}
.status-card.warning {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
.status-icon {
width: 48px;
height: 48px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
flex-shrink: 0;
}
.status-icon.success {
background: rgba(103, 194, 58, 0.2);
}
.status-icon.warning {
background: rgba(230, 162, 60, 0.2);
}
.status-text {
flex: 1;
}
.status-title {
font-size: 16px;
font-weight: 500;
margin-bottom: 5px;
}
.status-desc {
font-size: 12px;
opacity: 0.9;
line-height: 1.5;
}
/* 帮助卡片 */
.help-card {
background: white;
border: 1px solid #e4e7ed;
border-radius: 6px;
overflow: hidden;
}
.card-header {
background: #f5f7fa;
padding: 12px 15px;
font-size: 14px;
font-weight: 500;
color: #303133;
display: flex;
align-items: center;
border-bottom: 1px solid #e4e7ed;
}
.card-header i {
margin-right: 6px;
color: #409eff;
}
.help-content {
padding: 15px;
display: flex;
flex-direction: column;
gap: 10px;
}
.help-item {
display: flex;
align-items: flex-start;
gap: 8px;
font-size: 13px;
color: #606266;
line-height: 1.6;
}
.help-item i {
color: #67c23a;
margin-top: 2px;
flex-shrink: 0;
}
.tag-list {
display: flex;
flex-wrap: wrap;
gap: 4px;
}
/* 底部按钮 */
.footer-buttons {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 10px;
}
.footer-left,
.footer-right {
display: flex;
gap: 8px;
}
/* 响应式调整 */
@media (max-width: 768px) {
.config-container {
flex-direction: column;
}
.config-right {
width: 100%;
}
}
</style>

View File

@@ -64,6 +64,7 @@
<el-button type="warning" size="small" icon="el-icon-download" @click="handleExport" v-hasPermi="['system:jdorder:export']">导出</el-button> <el-button type="warning" size="small" icon="el-icon-download" @click="handleExport" v-hasPermi="['system:jdorder:export']">导出</el-button>
<el-button type="success" size="small" icon="el-icon-setting" @click="showAutoWriteConfig = true" title="配置H-TF订单自动写入腾讯文档">腾峰文档配置</el-button> <el-button type="success" size="small" icon="el-icon-setting" @click="showAutoWriteConfig = true" title="配置H-TF订单自动写入腾讯文档">腾峰文档配置</el-button>
<el-button type="info" size="small" icon="el-icon-monitor" @click="showPushMonitor = true" title="查看推送监控和历史记录">推送监控</el-button> <el-button type="info" size="small" icon="el-icon-monitor" @click="showPushMonitor = true" title="查看推送监控和历史记录">推送监控</el-button>
<el-button type="warning" size="small" icon="el-icon-user" @click="showTouserConfig = true" title="配置分销标识对应的企业微信接收人">接收人配置</el-button>
<el-button type="primary" size="small" icon="el-icon-refresh-right" @click="handleBatchSyncLogistics" :loading="batchSyncLoading" title="批量同步物流链接到腾讯文档"> <el-button type="primary" size="small" icon="el-icon-refresh-right" @click="handleBatchSyncLogistics" :loading="batchSyncLoading" title="批量同步物流链接到腾讯文档">
<i v-if="!batchSyncLoading"></i> <i v-if="!batchSyncLoading"></i>
一键发货到腾峰 一键发货到腾峰
@@ -440,6 +441,9 @@
<!-- 腾讯文档推送监控 --> <!-- 腾讯文档推送监控 -->
<tencent-doc-push-monitor v-model="showPushMonitor" /> <tencent-doc-push-monitor v-model="showPushMonitor" />
<!-- 分销标识接收人配置 -->
<distribution-mark-touser-config v-model="showTouserConfig" @config-updated="handleTouserConfigUpdated" />
</div> </div>
</template> </template>
@@ -449,13 +453,15 @@ import { fillLogisticsByOrderNo, getTokenStatus, getTencentDocAuthUrl, testUserI
import ListLayout from '@/components/ListLayout' import ListLayout from '@/components/ListLayout'
import TencentDocAutoWriteConfig from './components/TencentDocAutoWriteConfig' import TencentDocAutoWriteConfig from './components/TencentDocAutoWriteConfig'
import TencentDocPushMonitor from './components/TencentDocPushMonitor' import TencentDocPushMonitor from './components/TencentDocPushMonitor'
import DistributionMarkTouserConfig from './components/DistributionMarkTouserConfig'
export default { export default {
name: 'JDOrderList', name: 'JDOrderList',
components: { components: {
ListLayout, ListLayout,
TencentDocAutoWriteConfig, TencentDocAutoWriteConfig,
TencentDocPushMonitor TencentDocPushMonitor,
DistributionMarkTouserConfig
}, },
data() { data() {
return { return {
@@ -499,6 +505,7 @@ export default {
// H-TF订单自动写入配置 // H-TF订单自动写入配置
showAutoWriteConfig: false, showAutoWriteConfig: false,
showPushMonitor: false, showPushMonitor: false,
showTouserConfig: false,
// 批量同步loading状态 // 批量同步loading状态
batchSyncLoading: false, batchSyncLoading: false,
// 批量标记后返到账loading状态 // 批量标记后返到账loading状态
@@ -1165,6 +1172,11 @@ export default {
this.$message.success('H-TF订单自动写入配置已更新') this.$message.success('H-TF订单自动写入配置已更新')
}, },
/** 分销标识接收人配置更新后的回调 */
handleTouserConfigUpdated() {
this.$message.success('分销标识接收人配置已更新')
},
/** 批量标记后返到账(赔付金额>0的订单 */ /** 批量标记后返到账(赔付金额>0的订单 */
async handleBatchMarkRebateReceived() { async handleBatchMarkRebateReceived() {
try { try {