From fddd8f0586b629c9110ed37d4bf338e6e407a7f7 Mon Sep 17 00:00:00 2001 From: wuweihua <88888888> Date: Wed, 9 Sep 2026 10:33:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=85=AC=E5=85=B1=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruoyi/price/domain/BmsProductCountry.java | 2 + .../mapper/price/BmsProductCountryMapper.xml | 16 +- .../src/components/SimpleTable/index.vue | 121 +++++ bms-front/src/main.js | 2 + .../components/ProductCountryDrawer.vue | 107 +++++ .../product/components/ProductFormDialog.vue | 157 +++++++ .../components/ProductSurchargeDrawer.vue | 136 ++++++ .../product/components/SurchargeRelDialog.vue | 98 ++++ .../src/views/price/basic/product/index.vue | 420 +----------------- bms-front/src/views/price/billing/quote.vue | 2 - bms-front/src/views/price/set/create.vue | 48 +- 11 files changed, 658 insertions(+), 451 deletions(-) create mode 100644 bms-front/src/components/SimpleTable/index.vue create mode 100644 bms-front/src/views/price/basic/product/components/ProductCountryDrawer.vue create mode 100644 bms-front/src/views/price/basic/product/components/ProductFormDialog.vue create mode 100644 bms-front/src/views/price/basic/product/components/ProductSurchargeDrawer.vue create mode 100644 bms-front/src/views/price/basic/product/components/SurchargeRelDialog.vue diff --git a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/domain/BmsProductCountry.java b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/domain/BmsProductCountry.java index 39a62a42..46e12cd3 100644 --- a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/domain/BmsProductCountry.java +++ b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/domain/BmsProductCountry.java @@ -34,4 +34,6 @@ public class BmsProductCountry implements Serializable private Date updatedAt; /** query only: true = expire_date is null */ private Boolean openOnly; + /** query only: ACTIVE已生效 / PENDING待生效 / EXPIRED已失效(按生效/失效日期与当前日期派生) */ + private String effectStatus; } diff --git a/bms-back/ruoyi-system/src/main/resources/mapper/price/BmsProductCountryMapper.xml b/bms-back/ruoyi-system/src/main/resources/mapper/price/BmsProductCountryMapper.xml index ce8d09c3..1e9b6125 100644 --- a/bms-back/ruoyi-system/src/main/resources/mapper/price/BmsProductCountryMapper.xml +++ b/bms-back/ruoyi-system/src/main/resources/mapper/price/BmsProductCountryMapper.xml @@ -20,12 +20,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + + case + when expire_date is not null and expire_date <= curdate() then 'EXPIRED' + when effective_date is null or effective_date > curdate() then 'PENDING' + else 'ACTIVE' + end + + select detail_id, product_code, country_name, country_code, weight_min, weight_max, freight_price, registration_fee, size_limit, last_mile, lead_time, - effective_date, expire_date, created_at, updated_at + effective_date, expire_date, created_at, updated_at, + as effect_status from bms_product_country @@ -53,6 +64,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" AND expire_date is null + + AND () = #{effectStatus} + order by effective_date desc, country_name asc, weight_min asc, detail_id asc diff --git a/bms-front/src/components/SimpleTable/index.vue b/bms-front/src/components/SimpleTable/index.vue new file mode 100644 index 00000000..be8d3aa6 --- /dev/null +++ b/bms-front/src/components/SimpleTable/index.vue @@ -0,0 +1,121 @@ + + + + + diff --git a/bms-front/src/main.js b/bms-front/src/main.js index c665eab8..a77e923d 100644 --- a/bms-front/src/main.js +++ b/bms-front/src/main.js @@ -47,6 +47,7 @@ import DictTag from '@/components/DictTag' import BasicForm from '@/components/BasicForm' // 公共表格组件 import BasicTable from '@/components/BasicTable' +import SimpleTable from '@/components/SimpleTable' const app = createApp(App) @@ -71,6 +72,7 @@ app.component('RightToolbar', RightToolbar) app.component('Editor', Editor) app.component('BasicForm', BasicForm) app.component('BasicTable', BasicTable) +app.component('SimpleTable', SimpleTable) app.use(router) app.use(store) diff --git a/bms-front/src/views/price/basic/product/components/ProductCountryDrawer.vue b/bms-front/src/views/price/basic/product/components/ProductCountryDrawer.vue new file mode 100644 index 00000000..4e27a857 --- /dev/null +++ b/bms-front/src/views/price/basic/product/components/ProductCountryDrawer.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/bms-front/src/views/price/basic/product/components/ProductFormDialog.vue b/bms-front/src/views/price/basic/product/components/ProductFormDialog.vue new file mode 100644 index 00000000..a2d0b8fa --- /dev/null +++ b/bms-front/src/views/price/basic/product/components/ProductFormDialog.vue @@ -0,0 +1,157 @@ + + + diff --git a/bms-front/src/views/price/basic/product/components/ProductSurchargeDrawer.vue b/bms-front/src/views/price/basic/product/components/ProductSurchargeDrawer.vue new file mode 100644 index 00000000..25c18bdf --- /dev/null +++ b/bms-front/src/views/price/basic/product/components/ProductSurchargeDrawer.vue @@ -0,0 +1,136 @@ + + + + + diff --git a/bms-front/src/views/price/basic/product/components/SurchargeRelDialog.vue b/bms-front/src/views/price/basic/product/components/SurchargeRelDialog.vue new file mode 100644 index 00000000..2cd3900f --- /dev/null +++ b/bms-front/src/views/price/basic/product/components/SurchargeRelDialog.vue @@ -0,0 +1,98 @@ + + + diff --git a/bms-front/src/views/price/basic/product/index.vue b/bms-front/src/views/price/basic/product/index.vue index 6c18b83d..633f3f4e 100644 --- a/bms-front/src/views/price/basic/product/index.vue +++ b/bms-front/src/views/price/basic/product/index.vue @@ -39,186 +39,16 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 启用(按生效日期自动:待生效/已生效) - 已失效 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- 新增关联 -
- - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - 产品级(全部明细) - 明细级(指定国家×重量段) - - - - - - - - - - - + + + import ExcelImportDialog from '@/components/ExcelImportDialog' -import { listProduct, getProduct, addProduct, updateProduct, delProduct, listProductCountries } from '@/api/price/product' -import { listSurchargeByProduct, listSurcharge, addSurchargeRel, delSurchargeRel } from '@/api/price/surcharge' -import { listRegionOptions } from '@/api/data/region' -import { onMounted } from 'vue' +import ProductFormDialog from './components/ProductFormDialog.vue' +import ProductCountryDrawer from './components/ProductCountryDrawer.vue' +import ProductSurchargeDrawer from './components/ProductSurchargeDrawer.vue' +import { listProduct, delProduct } from '@/api/price/product' const { proxy } = getCurrentInstance() -const { bms_product_effect_status, bms_tax_mode, bms_round_mode, bms_charge_type } = useDict('bms_product_effect_status', 'bms_tax_mode', 'bms_round_mode', 'bms_charge_type') +const { bms_product_effect_status } = useDict('bms_product_effect_status') + const tableRef = ref() -const importRef = ref() const formRef = ref() -const open = ref(false) -const title = ref('') -const countryOpen = ref(false) -const countryTitle = ref('') -const countryLoading = ref(false) -const countryList = ref([]) -const countryKeyword = ref('') - -const surchargeOpen = ref(false) -const surchargeTitle = ref('') -const surchargeLoading = ref(false) -const surchargeList = ref([]) -const currentProduct = ref(null) -const regionOptions = ref([]) - -const surchargePool = ref([]) -const relOpen = ref(false) -const relTitle = ref('') -const relFormRef = ref() -const filteredCountryList = computed(() => { - const kw = countryKeyword.value.trim().toLowerCase() - if (!kw) return countryList.value - return countryList.value.filter(r => - String(r.countryName || '').toLowerCase().includes(kw) || - String(r.countryCode || '').toLowerCase().includes(kw) - ) -}) +const countryRef = ref() +const surchargeRef = ref() +const importRef = ref() const columns = [ { prop: 'productCode', label: '产品代码', minWidth: 110 }, @@ -308,16 +114,6 @@ const searchColumns = [ } ] -const data = reactive({ - form: {}, - rules: { - productCode: [{ required: true, message: '产品代码不能为空', trigger: 'blur' }], - productName: [{ required: true, message: '产品名称不能为空', trigger: 'blur' }], - taxMode: [{ required: true, message: '请选择税模式', trigger: 'change' }] - } -}) -const { form, rules } = toRefs(data) - function queryList(params) { return listProduct(params) } @@ -334,32 +130,12 @@ function resolveEffectStatus(row) { return String(row.effectiveDate).slice(0, 10) <= todayStr() ? 'ACTIVE' : 'PENDING' } -// 已生效不可编辑/删除 function isProductActive(row) { return resolveEffectStatus(row) === 'ACTIVE' } -function reset() { - form.value = { - productId: undefined, - productCode: undefined, - productName: undefined, - serviceLevel: undefined, - cargoAttr: undefined, - destRegion: undefined, - updateNote: undefined, - taxMode: 'TAX_INCLUDED', - effectiveDate: undefined, - status: '0', - remark: undefined - } - proxy.resetForm('formRef') -} - function handleAdd() { - reset() - open.value = true - title.value = '新建产品' + formRef.value.open() } function handleUpdate(row) { @@ -367,24 +143,7 @@ function handleUpdate(row) { proxy.$modal.msgError('已生效的产品不可编辑') return } - reset() - getProduct(row.productId).then(res => { - form.value = res.data - open.value = true - title.value = '修改产品' - }) -} - -function submitForm() { - proxy.$refs['formRef'].validate(valid => { - if (!valid) return - const req = form.value.productId ? updateProduct(form.value) : addProduct(form.value) - req.then(() => { - proxy.$modal.msgSuccess('操作成功') - open.value = false - tableRef.value.refresh() - }) - }) + formRef.value.open(row) } function handleDelete(ids) { @@ -400,155 +159,8 @@ function handleDelete(ids) { function handleImport() { importRef.value.open() } - -function openCountries(row) { - countryTitle.value = `${row.productCode} · ${row.productName} · 国家服务明细` - countryOpen.value = true - countryLoading.value = true - countryList.value = [] - countryKeyword.value = '' - listProductCountries(row.productCode).then(res => { - // 按 ISO2 排序,保证相同国家相邻,便于合并单元格 - const list = (res.data || []).slice().sort((a, b) => { - return String(a.countryCode || '').localeCompare(String(b.countryCode || '')) - }) - countryList.value = list - }).finally(() => { - countryLoading.value = false - }) -} - -// 弹窗表格合并:相同 countryCode 的连续行合并「国家」「ISO2」列 -function countrySpanMethod({ column, rowIndex }) { - if (column.property !== 'countryName' && column.property !== 'countryCode') return - const list = filteredCountryList.value - if (!list.length) return - const cur = list[rowIndex]?.countryCode - if (rowIndex > 0 && list[rowIndex - 1]?.countryCode === cur) { - return { rowspan: 0, colspan: 0 } - } - let count = 1 - while (rowIndex + count < list.length && list[rowIndex + count]?.countryCode === cur) count++ - return { rowspan: count, colspan: 1 } -} - -// ===== 产品附加费关联 ===== -const relData = reactive({ - relForm: {}, - relRules: { - scId: [{ required: true, message: '请选择附加费', trigger: 'change' }] - } -}) -const { relForm, relRules } = toRefs(relData) - -function openSurcharges(row) { - currentProduct.value = row - surchargeTitle.value = `${row.productCode} · ${row.productName} · 附加费关联` - surchargeOpen.value = true - loadSurcharges() -} - -function loadSurcharges() { - if (!currentProduct.value) return - surchargeLoading.value = true - listSurchargeByProduct(currentProduct.value.productCode).then(res => { - surchargeList.value = res.data || [] - }).finally(() => { - surchargeLoading.value = false - }) -} - -function loadSurchargePool() { - return listSurcharge({ ssCode: 'on', pageNum: 1, pageSize: 1000 }).then(res => { - surchargePool.value = res.rows || [] - }) -} - -function resetRelForm() { - relForm.value = { - scId: undefined, - scope: 'PRODUCT', - detailId: undefined - } - relFormRef.value && relFormRef.value.resetFields() -} - -function handleRelAdd() { - resetRelForm() - relTitle.value = '新增附加费关联' - relOpen.value = true - loadSurchargePool() -} - -function submitRel() { - relFormRef.value.validate(valid => { - if (!valid) return - if (relForm.value.scope === 'DETAIL' && !relForm.value.detailId) { - proxy.$modal.msgError('请选择明细') - return - } - const payload = { - scId: relForm.value.scId, - productId: currentProduct.value ? currentProduct.value.productId : undefined, - productCode: currentProduct.value ? currentProduct.value.productCode : undefined, - detailId: relForm.value.scope === 'DETAIL' ? relForm.value.detailId : null - } - addSurchargeRel(payload).then(() => { - proxy.$modal.msgSuccess('关联成功') - relOpen.value = false - loadSurcharges() - tableRef.value.refresh() - }) - }) -} - -function handleRelDelete(relId) { - proxy.$modal.confirm('是否确认解绑该附加费?').then(() => { - return delSurchargeRel(relId) - }).then(() => { - proxy.$modal.msgSuccess('解绑成功') - loadSurcharges() - tableRef.value.refresh() - }).catch(() => {}) -} - -function detailLabel(d) { - const w = d.weightMin != null && d.weightMax != null ? `${d.weightMin}-${d.weightMax}kg` : '-' - return `${d.countryName || d.countryCode || '-'} · ${w}` -} - -function chargeTypeLabel(val) { - const found = bms_charge_type.value.find(c => c.value === val) - return found ? found.label : (val || '-') -} - -function roundModeLabel(val) { - const found = bms_round_mode.value.find(d => d.value === val) - return found ? found.label : (val || '-') -} - -function formatChargeValue(row) { - if (row.chargeValue == null) return '-' - const v = Number(row.chargeValue) - if (row.chargeType === 'RATE') return (v * 100).toFixed(2) + '%' - return v + ' ' + (row.currency || 'CNY') -} - -function countryLabel(code) { - if (!code) return '全部' - const found = regionOptions.value.find(r => r.countryCode2 === code) - return found ? (found.countryNameCn || found.countryNameEn || code) : code -} - -onMounted(() => { - listRegionOptions().then(res => { - regionOptions.value = res.data || [] - }) -}) diff --git a/bms-front/src/views/price/billing/quote.vue b/bms-front/src/views/price/billing/quote.vue index 4f37345f..b7b9ed1b 100644 --- a/bms-front/src/views/price/billing/quote.vue +++ b/bms-front/src/views/price/billing/quote.vue @@ -176,7 +176,6 @@
- {{ viewResult.quoteId }} {{ viewResult.customerId }} {{ viewResult.productName || '-' }} ({{ viewResult.productCode }}) {{ viewResult.countryName || '-' }} ({{ viewResult.countryCode }}) @@ -240,7 +239,6 @@ const historyLoading = ref(false) const viewResult = ref(null) const historyColumns = [ - { label: '试算ID', prop: 'quoteId', align: 'center', width: 90 }, { label: '客户ID', prop: 'customerId', align: 'center', width: 90 }, { label: '产品', prop: 'product', minWidth: 160, slot: 'product' }, { label: '国家', prop: 'country', minWidth: 130, slot: 'country' }, diff --git a/bms-front/src/views/price/set/create.vue b/bms-front/src/views/price/set/create.vue index 6828f271..b4cf6c00 100644 --- a/bms-front/src/views/price/set/create.vue +++ b/bms-front/src/views/price/set/create.vue @@ -4,7 +4,6 @@ - @@ -256,29 +255,10 @@ - - - - - - - - - - - -
取消 上一步 - 下一步 + 下一步 保存草稿 保存并提交审核
@@ -286,7 +266,7 @@