This commit is contained in:
雷欧(林平凡)
2025-10-11 16:11:52 +08:00
parent f302c9ea69
commit 114ae26c8f

View File

@@ -120,28 +120,44 @@
</el-col> </el-col>
</el-row> </el-row>
<el-form-item label="目标账号" prop="targetAccounts" required> <el-form-item label="选择账号及子账号" required>
<el-select v-model="publishForm.targetAccounts" multiple placeholder="请选择目标ERP账号" style="width: 100%;"> <div style="border: 1px solid #dcdfe6; border-radius: 4px; padding: 15px;">
<el-checkbox-group v-model="publishForm.selectedMainAccounts" @change="onMainAccountsChange">
<div v-for="account in erpAccounts" :key="account.value" style="margin-bottom: 20px;">
<!-- 主账号复选框 -->
<el-checkbox :label="account.value" style="font-weight: bold; margin-bottom: 10px;">
{{ account.label }}
</el-checkbox>
<!-- 该主账号下的子账号选择 -->
<div v-if="publishForm.selectedMainAccounts.includes(account.value)" style="margin-left: 30px; margin-top: 10px;">
<el-select
v-model="publishForm.accountSubAccounts[account.value]"
multiple
:placeholder="`请选择${account.label}下的子账号`"
:loading="loadingSubAccounts[account.value]"
style="width: 100%;"
@visible-change="(visible) => visible && loadSubAccountsForAccount(account.value)"
>
<el-option <el-option
v-for="account in erpAccounts" v-for="subAccount in subAccountsMap[account.value] || []"
:key="account.value" :key="subAccount.value"
:label="account.label" :label="subAccount.label"
:value="account.value" :value="subAccount.value"
/> />
</el-select> </el-select>
</div>
</div>
</el-checkbox-group>
</div>
<div style="margin-top: 5px; color: #909399; font-size: 12px;"> <div style="margin-top: 5px; color: #909399; font-size: 12px;">
<i class="el-icon-info"></i> 支持选择多个账号每个商品将发送到所有选中的账号 <i class="el-icon-info"></i> 可同时选择多个账号,每个主账号下可选择多个子账号
</div> </div>
</el-form-item> </el-form-item>
<el-divider content-position="left">通用参数</el-divider> <el-divider content-position="left">通用参数</el-divider>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12">
<el-form-item label="会员名" prop="userName" required>
<el-input v-model="publishForm.userName" placeholder="请输入会员名"/>
</el-form-item>
</el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="商品类型" prop="itemBizType" required> <el-form-item label="商品类型" prop="itemBizType" required>
<el-select v-model="publishForm.itemBizType" placeholder="请选择" style="width: 100%;"> <el-select v-model="publishForm.itemBizType" placeholder="请选择" style="width: 100%;">
@@ -152,9 +168,6 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="行业类型" prop="spBizType" required> <el-form-item label="行业类型" prop="spBizType" required>
<el-select v-model="publishForm.spBizType" placeholder="请选择" style="width: 100%;"> <el-select v-model="publishForm.spBizType" placeholder="请选择" style="width: 100%;">
@@ -169,43 +182,89 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12">
<el-form-item label="类目ID" prop="channelCatId" required>
<el-input v-model="publishForm.channelCatId" placeholder="请输入类目ID"/>
</el-form-item>
</el-col>
</el-row> </el-row>
<el-row :gutter="20">
<el-col :span="8"> <el-form-item label="//" required>
<el-form-item label="省" prop="province" required> <div style="display:flex; gap:8px; width:100%">
<el-input-number v-model="publishForm.province" placeholder="省代码" style="width: 100%;"/> <el-select
v-model.number="publishForm.province"
placeholder="选择省"
style="flex:1"
filterable
@change="onProvinceChange"
>
<el-option
v-for="p in regionOptions.provinces"
:key="p.value"
:label="p.label"
:value="p.value"
/>
</el-select>
<el-select
v-model.number="publishForm.city"
placeholder="选择市"
style="flex:1"
filterable
:disabled="!publishForm.province"
@change="onCityChange"
>
<el-option
v-for="c in regionOptions.cities"
:key="c.value"
:label="c.label"
:value="c.value"
/>
</el-select>
<el-select
v-model.number="publishForm.district"
placeholder="选择区"
style="flex:1"
filterable
:disabled="!publishForm.city"
>
<el-option
v-for="a in regionOptions.areas"
:key="a.value"
:label="a.label"
:value="a.value"
/>
</el-select>
</div>
</el-form-item> </el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="市" prop="city" required>
<el-input-number v-model="publishForm.city" placeholder="市代码" style="width: 100%;"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="区" prop="district" required>
<el-input-number v-model="publishForm.district" placeholder="区代码" style="width: 100%;"/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="6">
<el-form-item label="类目" prop="channelCatId" required>
<el-select
v-model="publishForm.channelCatId"
filterable
placeholder="请选择类目"
:disabled="!categoryOptions.length"
:loading="categoryLoading"
style="width: 100%;"
@change="onCategoryChange"
>
<el-option
v-for="c in categoryOptions"
:key="c.value"
:label="c.label"
:value="c.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="邮费" prop="expressFee" required> <el-form-item label="邮费" prop="expressFee" required>
<el-input-number v-model="publishForm.expressFee" :min="0" :precision="2" placeholder="" style="width: 100%;"/> <el-input-number v-model="publishForm.expressFee" :min="0" :precision="2" placeholder="" style="width: 100%;"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="6">
<el-form-item label="库存" prop="stock" required> <el-form-item label="库存" prop="stock" required>
<el-input-number v-model="publishForm.stock" :min="1" placeholder="库存数量" style="width: 100%;"/> <el-input-number v-model="publishForm.stock" :min="1" placeholder="库存数量" style="width: 100%;"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="6">
<el-form-item label="成色" prop="stuffStatus"> <el-form-item label="成色" prop="stuffStatus">
<el-select v-model="publishForm.stuffStatus" placeholder="请选择" clearable style="width: 100%;"> <el-select v-model="publishForm.stuffStatus" placeholder="请选择" clearable style="width: 100%;">
<el-option label="全新" :value="100"/> <el-option label="全新" :value="100"/>
@@ -364,7 +423,7 @@
<script> <script>
import { parseLineReport, batchPublish, listTasks, getTask, listItems } from "@/api/jarvis/batchPublish"; import { parseLineReport, batchPublish, listTasks, getTask, listItems } from "@/api/jarvis/batchPublish";
import { getERPAccounts } from "@/api/system/jdorder"; import { getERPAccounts, getUsernames, getProvinces, getCities, getAreas, getCategories } from "@/api/system/jdorder";
import Pagination from "@/components/Pagination"; import Pagination from "@/components/Pagination";
export default { export default {
@@ -386,12 +445,13 @@ export default {
// 发品表单 // 发品表单
publishForm: { publishForm: {
taskName: "", taskName: "",
targetAccounts: [], selectedMainAccounts: [], // 选中的主账号列表
accountSubAccounts: {}, // 每个主账号对应的子账号 { appid: [subAccount1, subAccount2] }
delaySeconds: 3, delaySeconds: 3,
userName: "", userName: "",
province: null, province: 230000, // 默认黑龙江省
city: null, city: 230100, // 默认哈尔滨市
district: null, district: 230113, // 默认道外区
itemBizType: 2, itemBizType: 2,
spBizType: 3, spBizType: 3,
channelCatId: "", channelCatId: "",
@@ -402,8 +462,6 @@ export default {
channelPv: "" channelPv: ""
}, },
publishRules: { publishRules: {
targetAccounts: [{ required: true, message: "请选择目标账号", trigger: "change" }],
userName: [{ required: true, message: "请输入会员名", trigger: "blur" }],
province: [{ required: true, message: "请输入省代码", trigger: "blur" }], province: [{ required: true, message: "请输入省代码", trigger: "blur" }],
city: [{ required: true, message: "请输入市代码", trigger: "blur" }], city: [{ required: true, message: "请输入市代码", trigger: "blur" }],
district: [{ required: true, message: "请输入区代码", trigger: "blur" }], district: [{ required: true, message: "请输入区代码", trigger: "blur" }],
@@ -418,6 +476,21 @@ export default {
// ERP账号 // ERP账号
erpAccounts: [], erpAccounts: [],
// 子账号 - 每个主账号对应一个子账号列表
subAccountsMap: {}, // { appid: [{value, label}] }
loadingSubAccounts: {}, // { appid: boolean }
// 省市区
regionOptions: {
provinces: [],
cities: [],
areas: []
},
// 类目
categoryOptions: [],
categoryLoading: false,
// 发品结果 // 发品结果
publishResult: { publishResult: {
taskId: null taskId: null
@@ -443,6 +516,16 @@ export default {
}, },
created() { created() {
this.loadERPAccounts(); this.loadERPAccounts();
this.loadProvinces();
this.loadCategories();
},
watch: {
'publishForm.itemBizType'() {
this.onItemBizTypeChange();
},
'publishForm.spBizType'() {
this.onSpBizTypeChange();
}
}, },
beforeDestroy() { beforeDestroy() {
if (this.refreshTimer) { if (this.refreshTimer) {
@@ -462,6 +545,193 @@ export default {
} }
}, },
// 主账号变化
onMainAccountsChange(selectedAccounts) {
// 清理未选中账号的子账号数据
Object.keys(this.publishForm.accountSubAccounts).forEach(appid => {
if (!selectedAccounts.includes(appid)) {
this.$delete(this.publishForm.accountSubAccounts, appid);
this.$delete(this.subAccountsMap, appid);
this.$delete(this.loadingSubAccounts, appid);
}
});
// 为新选中的账号初始化数据
selectedAccounts.forEach(appid => {
if (!this.publishForm.accountSubAccounts[appid]) {
this.$set(this.publishForm.accountSubAccounts, appid, []);
}
if (!this.subAccountsMap[appid]) {
this.$set(this.subAccountsMap, appid, []);
// 自动加载子账号
this.loadSubAccountsForAccount(appid);
}
});
},
// 为指定主账号加载子账号
async loadSubAccountsForAccount(appid) {
// 如果已经加载过或正在加载,则跳过
if (this.subAccountsMap[appid]?.length > 0 || this.loadingSubAccounts[appid]) {
return;
}
this.$set(this.loadingSubAccounts, appid, true);
try {
const res = await getUsernames({ appid });
if (res.code === 200) {
this.$set(this.subAccountsMap, appid, res.data || []);
if ((res.data || []).length === 0) {
const accountName = this.erpAccounts.find(a => a.value === appid)?.label || appid;
this.$modal.msgWarning(`账号"${accountName}"下暂无可用的子账号`);
}
} else {
this.$modal.msgError(res.msg || "加载子账号失败");
}
} catch (error) {
console.error("加载子账号失败", error);
this.$modal.msgError("加载子账号失败请稍后重试");
} finally {
this.$set(this.loadingSubAccounts, appid, false);
}
},
// 加载省份
async loadProvinces() {
try {
const res = await getProvinces();
if (res.code === 200) {
this.regionOptions.provinces = res.data || [];
// 默认选择第一个省份
if (!this.publishForm.province && this.regionOptions.provinces.length) {
this.publishForm.province = this.regionOptions.provinces[0].value;
await this.loadCities(this.publishForm.province, true);
}
} else {
this.$modal.msgError(res.msg || '加载省份失败');
}
} catch (error) {
console.error('加载省份失败', error);
this.$modal.msgError('加载省份失败');
}
},
// 省份变化
async onProvinceChange() {
await this.loadCities(this.publishForm.province, false);
},
// 加载城市
async loadCities(provId, echo = false) {
if (!provId) {
this.regionOptions.cities = [];
this.regionOptions.areas = [];
this.publishForm.city = null;
this.publishForm.district = null;
return;
}
try {
const res = await getCities(provId);
if (res.code === 200) {
this.regionOptions.cities = res.data || [];
// 默认选择第一个城市
if (!this.publishForm.city && this.regionOptions.cities.length) {
this.publishForm.city = this.regionOptions.cities[0].value;
await this.loadAreas(provId, this.publishForm.city, true);
} else if (this.publishForm.city) {
await this.loadAreas(provId, this.publishForm.city, true);
} else {
this.regionOptions.areas = [];
this.publishForm.district = null;
}
} else {
this.$modal.msgError(res.msg || '加载城市失败');
}
} catch (error) {
console.error('加载城市失败', error);
this.$modal.msgError('加载城市失败');
}
},
// 城市变化
async onCityChange() {
await this.loadAreas(this.publishForm.province, this.publishForm.city, false);
},
// 加载区县
async loadAreas(provId, cityId, echo = false) {
if (!provId || !cityId) {
this.regionOptions.areas = [];
this.publishForm.district = null;
return;
}
try {
const res = await getAreas(provId, cityId);
if (res.code === 200) {
this.regionOptions.areas = res.data || [];
// 默认选择第一个区县
if (!this.publishForm.district && this.regionOptions.areas.length) {
this.publishForm.district = this.regionOptions.areas[0].value;
} else if (!echo) {
this.publishForm.district = null;
}
} else {
this.$modal.msgError(res.msg || '加载区县失败');
}
} catch (error) {
console.error('加载区县失败', error);
this.$modal.msgError('加载区县失败');
}
},
// 商品类型变化
async onItemBizTypeChange() {
this.categoryOptions = [];
this.publishForm.channelCatId = '';
await this.loadCategories();
},
// 行业类型变化
async onSpBizTypeChange() {
this.categoryOptions = [];
this.publishForm.channelCatId = '';
await this.loadCategories();
},
// 加载类目
async loadCategories() {
const itemBizType = this.publishForm.itemBizType;
const spBizType = this.publishForm.spBizType;
if (!itemBizType) {
return;
}
this.categoryLoading = true;
try {
const res = await getCategories({ itemBizType, spBizType });
if (res.code === 200) {
this.categoryOptions = res.data || [];
// 如果有类目且当前没有选中,自动选择第一个
if (!this.publishForm.channelCatId && this.categoryOptions.length) {
this.publishForm.channelCatId = this.categoryOptions[0].value;
}
} else {
this.$modal.msgError(res.msg || '加载类目失败');
}
} catch (error) {
console.error('加载类目失败', error);
this.$modal.msgError('加载类目失败');
} finally {
this.categoryLoading = false;
}
},
// 类目变化
onCategoryChange() {
// 类目变化后的回调(可用于加载属性等)
},
// 输入变化 // 输入变化
onMessageInput() { onMessageInput() {
// 可以添加实时提示 // 可以添加实时提示
@@ -532,11 +802,28 @@ export default {
return; return;
} }
if (this.publishForm.targetAccounts.length === 0) { // 验证是否选择了主账号
this.$modal.msgWarning("请至少选择一个目标账号"); if (this.publishForm.selectedMainAccounts.length === 0) {
this.$modal.msgWarning("请至少选择一个主账号");
return; return;
} }
// 验证每个主账号是否都选择了子账号
for (const appid of this.publishForm.selectedMainAccounts) {
const subAccounts = this.publishForm.accountSubAccounts[appid] || [];
if (subAccounts.length === 0) {
const accountName = this.erpAccounts.find(a => a.value === appid)?.label || appid;
this.$modal.msgWarning(`请为账号"${accountName}"选择至少一个子账号`);
return;
}
}
// 构建账号配置列表:[{targetAccount, subAccounts}]
const accountConfigs = this.publishForm.selectedMainAccounts.map(appid => ({
targetAccount: appid,
subAccounts: this.publishForm.accountSubAccounts[appid]
}));
this.publishing = true; this.publishing = true;
try { try {
const request = { const request = {
@@ -551,10 +838,10 @@ export default {
shopId: p.shopId, shopId: p.shopId,
commissionInfo: p.commissionInfo commissionInfo: p.commissionInfo
})), })),
targetAccounts: this.publishForm.targetAccounts, accountConfigs: accountConfigs,
delaySeconds: this.publishForm.delaySeconds, delaySeconds: this.publishForm.delaySeconds,
commonParams: { commonParams: {
userName: this.publishForm.userName, userName: accountConfigs[0].subAccounts[0],
province: this.publishForm.province, province: this.publishForm.province,
city: this.publishForm.city, city: this.publishForm.city,
district: this.publishForm.district, district: this.publishForm.district,