fix(expressTemplate): 修正运费模板计费方式类型及删除报错
- 将运费模板和详情模型中的计费方式 type 从 string 改为 boolean 类型 - 修改相关页面中计费方式显示及选择控件为布尔值 true/false 表示按件/按重量 - 统一删除操作使用后端返回的主键 id 替代废弃的 shopExpressTemplateId - 修复删除运费模板时报错“参数格式错误: id 的值 'undefined' 无法转换为 Integer” - ele-modal 关闭按钮定位修复,兼容最大化按钮时的偏移问题 - 小程序端 checkout 运费模板接入,支持动态计算显示运费费用 - 优化编辑表单中首件/续件数量或重量的动态标签和占位提示逻辑
This commit is contained in:
@@ -21,3 +21,38 @@
|
|||||||
- **search.vue**: 修正类型导入、添加搜索输入框、添加批量删除按钮(disabled 联动 selection)
|
- **search.vue**: 修正类型导入、添加搜索输入框、添加批量删除按钮(disabled 联动 selection)
|
||||||
- **Detail Edit**: templateId 改为下拉选择(从 listShopExpressTemplate 加载选项)
|
- **Detail Edit**: templateId 改为下拉选择(从 listShopExpressTemplate 加载选项)
|
||||||
- 修复 rules 类型错误(reactive<Record<string, any>>)
|
- 修复 rules 类型错误(reactive<Record<string, any>>)
|
||||||
|
|
||||||
|
### Bug 修复
|
||||||
|
- **JSON 反序列化错误**: 后端 type 字段为 Java Boolean,前端 radio 值从字符串 "0"/"1" 改为 true/false,Model 中 type 类型从 string 改为 boolean
|
||||||
|
- **ele-modal X按钮错位**: component.less 添加 ele-modal 关闭按钮定位修复,有最大化按钮时右移 56px
|
||||||
|
- **shopExpressTemplate/index.vue**: selection 绑定从 `:selection` 修正为 `v-model:selection`
|
||||||
|
|
||||||
|
## 小程序端运费模板接入(guilixu-taro checkout)
|
||||||
|
|
||||||
|
### 现状分析
|
||||||
|
- checkout.tsx 运费硬编码"免运费",零处 import shopExpressTemplate API
|
||||||
|
- ShopGoods 模型中有 expressTemplateId 字段,运费模板与商品关联
|
||||||
|
- ShopExpressTemplate 有 firstNum/firstAmount/extraNum/extraAmount 定价字段
|
||||||
|
- 地址模型只有 province/city 字符串名,无数字 ID,地区匹配暂不可行
|
||||||
|
|
||||||
|
### 实现方案
|
||||||
|
采用主模板定价方案(不依赖地区匹配):
|
||||||
|
- 创建 src/utils/expressFee.ts:computeExpressFee() 工具函数
|
||||||
|
- 按模板分组、合并同模板商品数量、应用计费公式
|
||||||
|
- fee = firstAmount + extraAmount * ceil(max(0, Q - firstNum) / extraNum)
|
||||||
|
- 修改 checkout.tsx:添加 expressFee 状态 + useEffect 自动计算 + 动态显示运费 + 纳入总价
|
||||||
|
|
||||||
|
### 注意事项
|
||||||
|
- 购物车 items 不包含 product 嵌套对象,cart checkout 时 expressTemplateId 为 undefined,运费显示为 0(免运费)
|
||||||
|
- buyNow 流程 items 包含 product 数据,运费计算正常工作
|
||||||
|
- 后端创建订单时会独立计算运费,前端仅用于展示预览
|
||||||
|
|
||||||
|
## 修复 shopExpressTemplate 删除报错
|
||||||
|
|
||||||
|
- 问题:删除运费模板时报错 "参数格式错误: id 的值 'undefined' 无法转换为 Integer"
|
||||||
|
- 根因:后端返回的主键字段是 `id`,但前端代码用了 `row.shopExpressTemplateId`(Model 中定义了两个字段,实际后端只返回 `id`)
|
||||||
|
- 修复文件:
|
||||||
|
- `src/views/shop/shopExpressTemplate/index.vue`:`row-key`、删除、批量删除均改为用 `row.id`
|
||||||
|
- `src/views/shop/shopExpressTemplateDetail/index.vue`:同上
|
||||||
|
- `src/views/shop/shopExpressTemplateDetail/components/shopExpressTemplateDetailEdit.vue`:下拉选择器 `field-names` 的 `value` 改为 `'id'`
|
||||||
|
- 注意:该模块 Model 中 `shopExpressTemplateId` 和 `id` 并存,建议后续清理废弃字段
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ export interface ShopExpressTemplate {
|
|||||||
shopExpressTemplateId?: number;
|
shopExpressTemplateId?: number;
|
||||||
/** 旧字段ID(兼容) */
|
/** 旧字段ID(兼容) */
|
||||||
id?: number;
|
id?: number;
|
||||||
/** 计费方式: 0=按件, 1=按重量 */
|
/** 计费方式: true=按件, false=按重量 */
|
||||||
type?: string;
|
type?: boolean;
|
||||||
/** 模板名称 */
|
/** 模板名称 */
|
||||||
title?: string;
|
title?: string;
|
||||||
/** 首件价格 */
|
/** 首件价格 */
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ export interface ShopExpressTemplateDetail {
|
|||||||
id?: number;
|
id?: number;
|
||||||
/** 所属运费模板ID */
|
/** 所属运费模板ID */
|
||||||
templateId?: number;
|
templateId?: number;
|
||||||
/** 计费方式: 0=按件, 1=按重量 */
|
/** 计费方式: true=按件, false=按重量 */
|
||||||
type?: string;
|
type?: boolean;
|
||||||
/** 省份ID */
|
/** 省份ID */
|
||||||
provinceId?: number;
|
provinceId?: number;
|
||||||
/** 城市ID */
|
/** 城市ID */
|
||||||
@@ -46,7 +46,7 @@ export interface ShopExpressTemplateDetailParam extends PageParam {
|
|||||||
/** 所属运费模板ID */
|
/** 所属运费模板ID */
|
||||||
templateId?: number;
|
templateId?: number;
|
||||||
/** 计费方式 */
|
/** 计费方式 */
|
||||||
type?: string;
|
type?: boolean;
|
||||||
/** 状态 */
|
/** 状态 */
|
||||||
status?: number;
|
status?: number;
|
||||||
keywords?: string;
|
keywords?: string;
|
||||||
|
|||||||
@@ -85,3 +85,36 @@
|
|||||||
border-radius: 0 0 12px 12px;
|
border-radius: 0 0 12px 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ele-modal 最大化按钮与关闭按钮位置修复 */
|
||||||
|
.ele-modal .ant-modal-header {
|
||||||
|
.ant-modal-close {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 当存在最大化按钮时,关闭按钮左移 */
|
||||||
|
.ele-modal-maximize-btn + .ant-modal-close,
|
||||||
|
.ele-modal-maximize-btn ~ .ant-modal-close {
|
||||||
|
right: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 针对 ant-modal 关闭按钮的兜底修复 */
|
||||||
|
.ant-modal .ant-modal-close {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,16 +30,16 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="计费方式" name="type">
|
<a-form-item label="计费方式" name="type">
|
||||||
<a-radio-group v-model:value="form.type">
|
<a-radio-group v-model:value="form.type">
|
||||||
<a-radio value="0">按件</a-radio>
|
<a-radio :value="true">按件</a-radio>
|
||||||
<a-radio value="1">按重量</a-radio>
|
<a-radio :value="false">按重量</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="首件数量/重量" name="firstNum">
|
<a-form-item :label="form.type ? '首件数量' : '首重重量'" name="firstNum">
|
||||||
<a-input-number
|
<a-input-number
|
||||||
:min="0"
|
:min="0"
|
||||||
:precision="2"
|
:precision="2"
|
||||||
class="ele-fluid"
|
class="ele-fluid"
|
||||||
placeholder="请输入首件数量/重量"
|
:placeholder="form.type ? '请输入首件数量' : '请输入首重重量'"
|
||||||
v-model:value="form.firstNum"
|
v-model:value="form.firstNum"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -52,12 +52,12 @@
|
|||||||
v-model:value="form.firstAmount"
|
v-model:value="form.firstAmount"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="续件数量/重量" name="extraNum">
|
<a-form-item :label="form.type ? '续件数量' : '续重重量'" name="extraNum">
|
||||||
<a-input-number
|
<a-input-number
|
||||||
:min="0"
|
:min="0"
|
||||||
:precision="2"
|
:precision="2"
|
||||||
class="ele-fluid"
|
class="ele-fluid"
|
||||||
placeholder="请输入续件数量/重量"
|
:placeholder="form.type ? '请输入续件数量' : '请输入续重重量'"
|
||||||
v-model:value="form.extraNum"
|
v-model:value="form.extraNum"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
const form = reactive<ShopExpressTemplate>({
|
const form = reactive<ShopExpressTemplate>({
|
||||||
shopExpressTemplateId: undefined,
|
shopExpressTemplateId: undefined,
|
||||||
id: undefined,
|
id: undefined,
|
||||||
type: '0',
|
type: true,
|
||||||
title: undefined,
|
title: undefined,
|
||||||
firstAmount: undefined,
|
firstAmount: undefined,
|
||||||
extraAmount: undefined,
|
extraAmount: undefined,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||||
<ele-pro-table
|
<ele-pro-table
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
row-key="shopExpressTemplateId"
|
row-key="id"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:datasource="datasource"
|
:datasource="datasource"
|
||||||
:customRow="customRow"
|
:customRow="customRow"
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'type'">
|
<template v-if="column.key === 'type'">
|
||||||
<a-tag v-if="record.type === '0'" color="blue">按件</a-tag>
|
<a-tag v-if="record.type === true" color="blue">按件</a-tag>
|
||||||
<a-tag v-else-if="record.type === '1'" color="cyan">按重量</a-tag>
|
<a-tag v-else-if="record.type === false" color="cyan">按重量</a-tag>
|
||||||
<span v-else>{{ record.type }}</span>
|
<span v-else>{{ record.type }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="column.key === 'status'">
|
<template v-if="column.key === 'status'">
|
||||||
@@ -200,7 +200,7 @@
|
|||||||
/* 删除单个 */
|
/* 删除单个 */
|
||||||
const remove = (row: ShopExpressTemplate) => {
|
const remove = (row: ShopExpressTemplate) => {
|
||||||
const hide = message.loading('请求中..', 0);
|
const hide = message.loading('请求中..', 0);
|
||||||
removeShopExpressTemplate(row.shopExpressTemplateId)
|
removeShopExpressTemplate(row.id)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
hide();
|
hide();
|
||||||
message.success(msg);
|
message.success(msg);
|
||||||
@@ -226,7 +226,7 @@
|
|||||||
onOk: () => {
|
onOk: () => {
|
||||||
const hide = message.loading('请求中..', 0);
|
const hide = message.loading('请求中..', 0);
|
||||||
removeBatchShopExpressTemplate(
|
removeBatchShopExpressTemplate(
|
||||||
selection.value.map((d) => d.shopExpressTemplateId)
|
selection.value.map((d) => d.id)
|
||||||
)
|
)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
hide();
|
hide();
|
||||||
|
|||||||
@@ -26,13 +26,13 @@
|
|||||||
placeholder="请选择所属运费模板"
|
placeholder="请选择所属运费模板"
|
||||||
v-model:value="form.templateId"
|
v-model:value="form.templateId"
|
||||||
:options="templateOptions"
|
:options="templateOptions"
|
||||||
:field-names="{ label: 'title', value: 'shopExpressTemplateId' }"
|
:field-names="{ label: 'title', value: 'id' }"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="计费方式" name="type">
|
<a-form-item label="计费方式" name="type">
|
||||||
<a-radio-group v-model:value="form.type">
|
<a-radio-group v-model:value="form.type">
|
||||||
<a-radio value="0">按件</a-radio>
|
<a-radio :value="true">按件</a-radio>
|
||||||
<a-radio value="1">按重量</a-radio>
|
<a-radio :value="false">按重量</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="省份ID" name="provinceId">
|
<a-form-item label="省份ID" name="provinceId">
|
||||||
@@ -51,12 +51,12 @@
|
|||||||
v-model:value="form.cityId"
|
v-model:value="form.cityId"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="首件数量/重量" name="firstNum">
|
<a-form-item :label="form.type ? '首件数量' : '首重重量'" name="firstNum">
|
||||||
<a-input-number
|
<a-input-number
|
||||||
:min="0"
|
:min="0"
|
||||||
:precision="2"
|
:precision="2"
|
||||||
class="ele-fluid"
|
class="ele-fluid"
|
||||||
placeholder="请输入首件数量/重量"
|
:placeholder="form.type ? '请输入首件数量' : '请输入首重重量'"
|
||||||
v-model:value="form.firstNum"
|
v-model:value="form.firstNum"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -69,12 +69,12 @@
|
|||||||
v-model:value="form.firstAmount"
|
v-model:value="form.firstAmount"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="续件数量/重量" name="extraNum">
|
<a-form-item :label="form.type ? '续件数量' : '续重重量'" name="extraNum">
|
||||||
<a-input-number
|
<a-input-number
|
||||||
:min="0"
|
:min="0"
|
||||||
:precision="2"
|
:precision="2"
|
||||||
class="ele-fluid"
|
class="ele-fluid"
|
||||||
placeholder="请输入续件数量/重量"
|
:placeholder="form.type ? '请输入续件数量' : '请输入续重重量'"
|
||||||
v-model:value="form.extraNum"
|
v-model:value="form.extraNum"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -156,7 +156,7 @@
|
|||||||
shopExpressTemplateDetailId: undefined,
|
shopExpressTemplateDetailId: undefined,
|
||||||
id: undefined,
|
id: undefined,
|
||||||
templateId: undefined,
|
templateId: undefined,
|
||||||
type: '0',
|
type: true,
|
||||||
provinceId: undefined,
|
provinceId: undefined,
|
||||||
cityId: undefined,
|
cityId: undefined,
|
||||||
firstNum: undefined,
|
firstNum: undefined,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||||
<ele-pro-table
|
<ele-pro-table
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
row-key="shopExpressTemplateDetailId"
|
row-key="id"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:datasource="datasource"
|
:datasource="datasource"
|
||||||
:customRow="customRow"
|
:customRow="customRow"
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'type'">
|
<template v-if="column.key === 'type'">
|
||||||
<a-tag v-if="record.type === '0'" color="blue">按件</a-tag>
|
<a-tag v-if="record.type === true" color="blue">按件</a-tag>
|
||||||
<a-tag v-else-if="record.type === '1'" color="cyan">按重量</a-tag>
|
<a-tag v-else-if="record.type === false" color="cyan">按重量</a-tag>
|
||||||
<span v-else>{{ record.type }}</span>
|
<span v-else>{{ record.type }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="column.key === 'status'">
|
<template v-if="column.key === 'status'">
|
||||||
@@ -214,7 +214,7 @@
|
|||||||
/* 删除单个 */
|
/* 删除单个 */
|
||||||
const remove = (row: ShopExpressTemplateDetail) => {
|
const remove = (row: ShopExpressTemplateDetail) => {
|
||||||
const hide = message.loading('请求中..', 0);
|
const hide = message.loading('请求中..', 0);
|
||||||
removeShopExpressTemplateDetail(row.shopExpressTemplateDetailId)
|
removeShopExpressTemplateDetail(row.id)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
hide();
|
hide();
|
||||||
message.success(msg);
|
message.success(msg);
|
||||||
@@ -240,7 +240,7 @@
|
|||||||
onOk: () => {
|
onOk: () => {
|
||||||
const hide = message.loading('请求中..', 0);
|
const hide = message.loading('请求中..', 0);
|
||||||
removeBatchShopExpressTemplateDetail(
|
removeBatchShopExpressTemplateDetail(
|
||||||
selection.value.map((d) => d.shopExpressTemplateDetailId)
|
selection.value.map((d) => d.id)
|
||||||
)
|
)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
hide();
|
hide();
|
||||||
|
|||||||
Reference in New Issue
Block a user