<template> <div class="app-container"> <el-form ref="form" :model="form" :rules="rules" label-width="150px"> <products-selector ref="productSelector" v-model="form.productIdList" show-all @setall="isAllProduct = $event" :default-ids="form.productIdList" enable-filtered @setFiltered="isAllFilteredProduct = $event" class="mb-20" /> <routers-selector v-model="selectedRoutes" :type="type" /> <el-card style="margin-bottom: 10px"> <div slot="header" style="font-size: 20px"> {{ $t("价格设置") }} <!--空运只有阶梯价格,不显示阶梯价格勾选--> <span v-if="type != 'air'"> <el-checkbox label="" @change="form.stepPrice = $event ? 1 : 0">{{ $t("阶梯价格") }}</el-checkbox> </span> </div> <el-row :gutter="20"> <el-col :span="12"> <el-form-item :label="$t('预付')" prop="needPay"> <el-radio-group v-model="form.needPay"> <el-radio :label="1">{{ $t("预付") }}</el-radio> <el-radio :label="0">{{ $t("均可") }}</el-radio> </el-radio-group> </el-form-item> <el-form-item :label="$t('单价模式')" prop="priceType"> <dict-selector :type="DICT_TYPE.ECW_PRICE_TYPE" v-model="form.priceType" form-type="radio" formatter="number" /> </el-form-item> <el-form-item :label="$t('最小起计量')" :prop="`minWeight`"> <el-input-number v-model="form.minWeight" class="w-100" :min="0" :controls="false" /> / <selector v-model="form.minWeightUnit" :options="unitList" :label-field="$l(null, 'title')" value-field="id" class="w-100" disabled /> </el-form-item> </el-col> <el-col :span="12"> <quick-set :unit-list="unitList" :currency-list="currencyList" :value="form" type="sea" ></quick-set> </el-col> </el-row> <template v-if="form.stepPrice"> <!--全包价--> <template v-if="form.priceType == 1"> <div v-for="(item, index) in form.fullPriceStepList" :key="index"> <price-step ref="stepPrice" :index="index" :currency-list="currencyList" :unit-list="unitList" field-prefix="all" :price-name="$t('全包价')" :show-add="index === form.fullPriceStepList.length - 1" :value="item" @add="handleAddPrice('fullPriceStepList', $event)" @delete="handleDeletePrice('fullPriceStepList', $event)" @changeUnit=" handleUnitChange(form.fullPriceStepList, index, ...$event) " ></price-step> </div> </template> <el-row v-else :gutter="20" class="mt-20"> <el-col :span="12"> <div v-for="(item, index) in form.freightPriceStepList" :key="index" > <price-step ref="stepPrice" :index="index" :currency-list="currencyList" :unit-list="unitList" field-prefix="transport" :price-name="$t('运费')" :show-add="index === form.freightPriceStepList.length - 1" :value="item" @add="handleAddPrice('freightPriceStepList', $event)" @delete="handleDeletePrice('freightPriceStepList', $event)" @changeUnit=" handleUnitChange( form.freightPriceStepList, index, ...$event ) " ></price-step> </div> </el-col> <el-col :span="12"> <div v-for="(item, index) in form.clearancePriceStepList" :key="index" > <price-step ref="stepPrice" :index="index" :currency-list="currencyList" :unit-list="unitList" field-prefix="clearance" :price-name="$t('清关费')" :show-add="index === form.clearancePriceStepList.length - 1" :value="item" @add="handleAddPrice('clearancePriceStepList', $event)" @delete="handleDeletePrice('clearancePriceStepList', $event)" @changeUnit=" handleUnitChange( form.clearancePriceStepList, index, ...$event ) " ></price-step> </div> </el-col> </el-row> </template> <template v-else-if="form.priceType === 1"> <sea-price ref="seaPrice" :currency-list="currencyList" :unit-list="unitList" :value="form" field-prefix="all" :price-name="$t('全包价')" packaging-field="fullPricePackagingList" @changeUnit="handleFormUnitChange($event)" ></sea-price> </template> <template v-else> <el-row :gutter="20"> <el-col :span="12"> <sea-price ref="seaPrice" :currency-list="currencyList" :unit-list="unitList" :value="form" field-prefix="transport" :price-name="$t('运费')" packaging-field="freightPricePackagingList" @changeUnit="handleFormUnitChange($event)" ></sea-price> </el-col> <el-col :span="12"> <sea-price ref="seaPrice" :currency-list="currencyList" :unit-list="unitList" :value="form" field-prefix="clearance" :price-name="$t('清关费')" packaging-field="clearancePricePackagingList" @changeUnit="handleFormUnitChange($event)" ></sea-price> </el-col> </el-row> </template> <el-form-item :label="$t('价格有效期')"> <el-date-picker v-model="form.validateStartDate" value-format="yyyy-MM-dd HH:mm:ss" ></el-date-picker> - <el-date-picker v-model="form.validateEndDate" value-format="yyyy-MM-dd HH:mm:ss" ></el-date-picker> </el-form-item> </el-card> <el-card> <div slot="header" style="font-size: 20px"> {{ $t("基础信息") }} </div> <el-form-item :label="$t('是否预约入仓')" prop="needBook"> <el-radio v-model.number="form.needBook" :label="1">{{ $t("是") }}</el-radio> <el-radio v-model.number="form.needBook" :label="0">{{ $t("否") }}</el-radio> </el-form-item> <!--下面几个字段只有批量设置海运才需要--> <template v-if="type == 'sea'"> <el-form-item :label="$t('每日入仓上限')" prop="dayLimit" v-if="form.needBook == 1" > <el-input v-model.number="form.dayLimit" type="number" class="w-100" />{{ $t("立方米") }} </el-form-item> <el-form-item :label="$t('货柜位置')" prop="containerLocation"> <dict-selector :type="DICT_TYPE.ECW_CONTAINER_LOCATION" v-model="form.containerLocation" /> </el-form-item> <el-form-item :label="$t('订单方数上限')" prop="square"> <el-input v-model.number="form.square" type="number" style="width: 200px" /> </el-form-item> </template> <el-form-item :label="$t('是否单询')" prop="inquiry"> <dict-selector :type="DICT_TYPE.NEED_ORDER_INQUIRY" v-model="form.needOrderInquiry" form-type="radio" formatter="number" ></dict-selector> </el-form-item> </el-card> </el-form> <div style="margin: 20px 0"> <el-button @click="submitForm" type="primary" :loading="loading">{{ $t("确认提交") }}</el-button> <el-button type="default" @click="$router.back()">{{ $t("返回上一页") }}</el-button> </div> </div> </template> <script> import RoutersSelector from "@/components/RoutersSelector"; import { batchUpdateProductPrice, getProductPrice, } from "@/api/ecw/productPrice"; import { getCurrencyList } from "@/api/ecw/currency"; import { getUnitList } from "@/api/ecw/unit"; import ProductsSelector from "@/components/ProductsSelector"; import Selector from "@/components/Selector"; import Inputor from "@/components/Inputor"; import Decimal from "decimal.js"; import { getProduct } from "@/api/ecw/product"; import QuickSet from "@/views/ecw/productPrice/components/QuickSet.vue"; import PriceStep from "@/views/ecw/productPrice/components/PriceStep.vue"; import SeaPrice from "@/views/ecw/productPrice/components/SeaPrice.vue"; import Template from "@/views/cms/template/index.vue"; const DEFAULT_PRICE_UNIT = 1; const DEFAULT_VOLUME_UNIT = 7; const DEFAULT_WEIGHT_UNIT = 7; export default { components: { Template, SeaPrice, PriceStep, QuickSet, RoutersSelector, ProductsSelector, Selector, Inputor, }, data() { return { checkList: [], selectedRoutes: [], // 勾选的路线渠道 form: { specialList: [], priceStepList: [], stepPrice: 0, priceType: null, minWeightUnit: null, allVolumeUnit: DEFAULT_VOLUME_UNIT, transportVolumeUnit: DEFAULT_VOLUME_UNIT, clearanceVolumeUnit: DEFAULT_VOLUME_UNIT, // advanceStatus: 0, // needBook: 0, // dayLimit: 10000 }, isAllProduct: false, // 是否全部商品 isAllFilteredProduct: false, // 是否勾選全部搜索結果 specialProducts: [], // priceStepList: [{},{}], // 阶梯价格 // specialList:[], // 特殊需求,默认四个 rules() {}, product: null, /* productType: null, */ currencyList: [], unitList: [], productTypeList: [], productDisabled: true, lineList: [], //路线数组 loading: false, // 批量加价/减价 quickForm: {}, }; }, computed: { rules() { return { priceType: [{ required: true, message: this.$t("请选择单价模式") }], }; }, // 类型,默认海运sea,air表示空运 type() { let type = this.$route.path.split(/[-_]/).pop(); if (type == "air" || type == "sea") return type; return null; }, // 默认运费的货币和体积单位 currencyAndUnit() { let currency = null, unit = null, fields = null; // 如果是阶梯价格则取第一阶梯,否则就取form中的字段 let obj = this.form.stepPrice == 1 ? this.form.priceStepList[0] : this.form; // 全包价 if (this.form.priceType == 1) { currency = obj.allPriceUnit; unit = obj.allVolumeUnit; } else { currency = obj.transportPriceUnit; unit = obj.transportVolumeUnit; } return { currency, unit }; }, // 判断是否空值 isEmpty() { return (content) => { return !content && content !== 0 && content !== "0"; }; }, }, watch: { checkList() { //选择路线 if (this.checkList.length > 0) { this.form.lineChannelList = this.checkList.map((item) => { return { lineId: item, shippingChannelId: 0 }; }); } else { this.form.lineChannelList = []; } }, product() { this.$set(this.form, "productType", this.product.typeId); }, "form.stepPrice"(stepPrice) { if (this.form.stepPrice === 1) { this.initStepPrice(); } this.syncMinWeightUnit(); }, "form.priceType"(priceType) { if (this.form.stepPrice === 1) { this.initStepPrice(); } this.syncMinWeightUnit(); }, "form.needBook"(val) { if (val) this.$set(this.form, "dayLimit", 10000); else delete this.form.dayLimit; }, }, async created() { this.currencyList = (await getCurrencyList())?.data || []; this.unitList = (await getUnitList())?.data || []; await this.$nextTick(); // 如果是复制,则获取数据并填充,先复制,然后填充特需,避免数据的特需不全导致部分不显示 if (this.$route.query.templateId) { await this.getTemplateDetail(this.$route.query.templateId); } // 从价格中获取特需的默认单位 this.getDictDatas(this.DICT_TYPE.ECW_SPECIAL_REQ_FOR_LINE_PRODUCTS).forEach( (item) => { // 没有的才push,已有的可能是从复制模板携带过来的数据 if ( !this.form.specialList.find( (special) => special.specialDictType == item.value ) ) { console.log("特需push", item.value); this.form.specialList.push({ clearancePrice: null, clearancePriceUnit: DEFAULT_PRICE_UNIT, clearanceVolumeUnit: DEFAULT_VOLUME_UNIT, specialDictType: item.value, transportPrice: null, transportPriceUnit: DEFAULT_PRICE_UNIT, transportVolumeUnit: DEFAULT_VOLUME_UNIT, }); } else console.log("已存在特需", item.value); } ); }, methods: { // 获取模板数据(复制的源路线价格信息) async getTemplateDetail(id) { const res = await getProductPrice(id); // 填充商品、线路、价格信息、出货渠道(空运) // this.form.productIdList = [res.data.productId] /* 23-11-07要求不复制商品和线路 https://zentao.test.jdshangmen.com/bug-view-5145.html this.selectedRoutes = [{ "lineId": res.data.warehouseLineId, "channelId": res.data.shippingChannelId, "transportId": res.data.warehouseLineDO.transportType, "shippingChannelId":res.data.channelId }]*/ // 要复制过来的字段 const { allPrice, allPriceUnit, allVolumeUnit, transportPrice, transportPriceUnit, transportVolumeUnit, clearancePrice, clearancePriceUnit, clearanceVolumeUnit, priceType, stepPrice, specialList, priceStepList, minWeight, minWeightUnit, needOrderInquiry, needBook, needPay, freightPriceStepList, clearancePriceStepList, fullPriceStepList, } = res.data; const data = { allPrice, allPriceUnit, allVolumeUnit, transportPrice, transportPriceUnit, transportVolumeUnit, clearancePrice, clearancePriceUnit, clearanceVolumeUnit, priceType, stepPrice, specialList, priceStepList, minWeight, minWeightUnit, needOrderInquiry, needBook, needPay, freightPriceStepList, clearancePriceStepList, fullPriceStepList, }; // 海运需要填充货柜位置和订单方数上限 if (this.type == "sea") { data.containerLocation = res.data.containerLocation; data.square = res.data.square; } this.$set(this, "form", Object.assign({}, this.form, data)); // 产品选择器默认选择的商品 /* 23-11-07要求不复制商品和线路 https://zentao.test.jdshangmen.com/bug-view-5145.html getProduct(res.data.productId).then(res => { this.$refs.productSelector.choose(res.data) })*/ }, // 设置最小起计量单位 syncMinWeightUnit() { // 如果是阶梯价 if (this.form.stepPrice) { const field = this.form.priceType === 1 ? "fullPriceStepList" : "freightPriceStepList"; const stepPriceList = this.form[field]; if (stepPriceList?.length) { this.form.minWeightUnit = stepPriceList[0]?.weightUnit || DEFAULT_WEIGHT_UNIT; } else { this.form.minWeightUnit = DEFAULT_WEIGHT_UNIT; } } else { this.form.minWeightUnit = this.form[ this.form.priceType === 1 ? "allVolumeUnit" : "transportVolumeUnit" ] || DEFAULT_WEIGHT_UNIT; } }, handleAddPrice(field, fieldPrefix) { if (!this.form[field]) { this.$set(this.form, field, []); } let priceUnit = DEFAULT_PRICE_UNIT; let volumeUnit = DEFAULT_VOLUME_UNIT; let weightUnit = DEFAULT_WEIGHT_UNIT; if (this.form[field].length) { const first = this.form[field][0]; priceUnit = first[`${fieldPrefix}PriceUnit`]; volumeUnit = first[`${fieldPrefix}VolumeUnit`]; weightUnit = first.weightUnit; } console.log("添加价格的默认单位", { priceUnit, volumeUnit, weightUnit, }); this.form[field].push({ [`${fieldPrefix}PriceUnit`]: priceUnit, [`${fieldPrefix}VolumeUnit`]: volumeUnit, weightUnit: weightUnit, specialList: [], }); }, handleDeletePrice(field, index) { this.form[field].splice(index, 1); }, handleUnitChange(stepPriceList, index, data) { console.log("handleUnitChange", ...arguments); if (index > 0) return; const isVolumeUnit = data.field.indexOf("VolumeUnit") > -1; // 如果是重量单位,且不是清关费想换的,则需要同步最小起计量单位 if (isVolumeUnit && data.type != "clearance") { this.form.minWeightUnit = data.value; } stepPriceList.forEach((item) => { item[data.field] = data.value; // 如果是设置体积单位,则还需要同步到阶梯重量单位 if (isVolumeUnit) { item["weightUnit"] = data.value; } if (item.packagingList?.length) { item.packagingList.forEach((p) => { if (data.field.indexOf("PriceUnit") > -1) { p["packagingPriceUnit"] = data.value; } if (data.field.indexOf("VolumeUnit") > -1) { p["packagingVolumeUnit"] = data.value; } }); } if (item.specialList?.length) { item.specialList.forEach((p) => { p[data.field] = data.value; }); } }); }, // 获得用语提交的阶梯价副本 getPriceList(stepList, prefix) { if (!stepList?.length) return []; let stepPriceList = JSON.parse(JSON.stringify(stepList)); stepPriceList.forEach((item, index) => { item.rankNum = index + 1; item.packagingList = item.packagingList.filter( (p) => !!p.packagingTypes?.length ); item.packagingList = item.packagingList.map((p) => { p.packagingTypes = p.packagingTypes.join(","); return p; }); }); // 240121应老王要求,未设置价格的不提交 return stepPriceList.filter((item) => { return !!item[`${prefix}Price`]; }); }, // 格式化包装类型费用 getPackingPrice(packging) { if (!packging?.length) return; packging = JSON.parse(JSON.stringify(packging)); return packging .filter((item) => !!item.packagingTypes) .map((item) => { item.packagingTypes = item.packagingTypes?.join(",") || ""; return item; }); }, // 非阶梯价格更新单位 handleFormUnitChange(data) { console.log("handleFormUnitChange", { ...data }); // 海运非阶梯价没有重量单位,所以按照体积单位同步最小起计量单位 if ( data.field === "transportVolumeUnit" || data.field == "allVolumeUnit" ) { this.form.minWeightUnit = data.value; } if (this.form.specialList?.length) { this.form.specialList.forEach((p) => { p[data.field] = data.value; }); } // 同步包装的单位 let packingField = { transportVolumeUnit: "freightPricePackagingList", clearanceVolumeUnit: "clearancePricePackagingList", allVolumeUnit: "fullPricePackagingList", transportPriceUnit: "freightPricePackagingList", clearancePriceUnit: "clearancePricePackagingList", }[data.field]; if (!this.form[packingField]?.length) { return false; } this.form[packingField].forEach((item) => { if (data.field.indexOf("PriceUnit") > -1) { item["packagingPriceUnit"] = data.value; } if (data.field.indexOf("VolumeUnit") > -1) { item["packagingVolumeUnit"] = data.value; } }); }, initStepPrice() { if (this.form.priceType == 1 && !this.form.fullPriceStepList?.length) { this.handleAddPrice("fullPriceStepList", "all"); } if (this.form.priceType === 0) { if (!this.form.freightPriceStepList?.length) { this.handleAddPrice("freightPriceStepList", "transport"); } if (!this.form.clearancePriceStepList?.length) { this.handleAddPrice("clearancePriceStepList", "clearance"); } } }, submitForm() { this.$refs["form"].validate(async (valid) => { if (!valid) { return; } //lanbm 2024-04-12 添加单价模式校验 if (this.form.priceType == 0 || this.form.priceType == 1) { } else { this.$message.error(this.$t("请选择单价模式")); return; } //end lanbm 2024-04-12 添加单价模式校验 // 只有新增的时候做判断 if ( !this.$route.query.ids && (!this.selectedRoutes || !this.selectedRoutes.length) ) { this.$message.error(this.$t("请选择线路")); return; } let data = Object.assign({}, this.form, { // lineChannelList: this.selectedRoutes, // specialList: this.specialProducts, isAllProduct: this.isAllProduct ? 1 : 0, // 阶梯价 freightPriceStepList: [], clearancePriceStepList: [], fullPriceStepList: [], // 非阶梯价包装类型 freightPricePackagingList: [], clearancePricePackagingList: [], fullPricePackagingList: [], }); // 如果是勾選了全部篩選商品,則獲取商品ID if (this.isAllFilteredProduct) { data.productIdList = await this.$refs.productSelector.getFilteredIds(); } if ( !data.isAllProduct && (!data.productIdList || !data.productIdList.length) ) { return this.$message.error("请选择商品"); } // 阶梯价校验 /* 根据甲方要求不做校验,所有字段均可留空,https://zentao.test.jdshangmen.com/bug-view-5915.html if(this.$refs.stepPrice){ let isValid = true for (let stepPrice of this.$refs.stepPrice){ if(!stepPrice.validate()){ isValid = false break } } if(!isValid)return } */ if (data.stepPrice) { // 全包价 if (this.form.priceType == 1) { data.fullPriceStepList = this.getPriceList( this.form.fullPriceStepList, "all" ); } else { data.clearancePriceStepList = this.getPriceList( this.form.clearancePriceStepList, "clearance" ); data.freightPriceStepList = this.getPriceList( this.form.freightPriceStepList, "transport" ); } } // 非阶梯价则需要提交包装类型 else { if (this.form.priceType == 1) { data.fullPricePackagingList = this.getPackingPrice( this.form.fullPricePackagingList ); } else { data.freightPricePackagingList = this.getPackingPrice( this.form.freightPricePackagingList ); data.clearancePricePackagingList = this.getPackingPrice( this.form.clearancePricePackagingList ); } } data.lineChannelList = this.selectedRoutes; if (data.lineChannelList.length < 1) { return this.$message.error(this.$t("请选择需要修改的路线")); } await this.$confirm( this.$t("已选择{route}条路线,{product}个商品;确认提交修改?", { route: data.lineChannelList.length, product: this.isAllProduct ? this.$refs.productSelector.allTotal : data.productIdList.length, }) ); this.loading = true; console.log("提交批量修改", data); batchUpdateProductPrice(data) .then((response) => { this.$modal.msgSuccess(this.$t("修改成功")); this.$router.replace( "/lineProject/product-price?" + new URLSearchParams(this.$route.query).toString() ); }) .finally((res) => (this.loading = false)); }); }, // 快捷设置,只更新默认运费 quickSet() { // 字段,根据是否全包价来取 let field = this.form.priceType == 1 ? "allPrice" : "transportPrice"; // 取得要加的数额(减少则是负数) let amount = Decimal(this.quickForm.plus || -this.quickForm.minus); this.form.priceStepList.forEach((item) => { // 加上对应的价格,但是不能小于0 this.$set( item, field, Math.max( 0, Decimal(item[field] || 0) .plus(amount) .toNumber() ) ); }); }, }, }; </script> <style scoped> .w100 { width: 100px; } .mr10 { margin-right: 10px; } </style>