refactor: 重构商品留言表单逻辑,替换为diy-form组件
1. 移除页面data中维护的留言表单数据,改为通过computed实时从商品详情数据构建diy-form所需格式 2. 替换ns-newform为diy-form组件,使用raw模式并接管表单提交逻辑 3. 完善平台别名映射,新增更多小程序平台兼容配置 4. 为diy-form新增占位符样式属性绑定 5. 重构商品表单接口处理逻辑,统一所有元数据字段的初始化和兼容处理
This commit is contained in:
@@ -37,8 +37,7 @@ export default {
|
||||
computed: {
|
||||
/**
|
||||
* 当前运行平台标识(与后端 formConfig.terminal 键名对齐)
|
||||
* 后端在 formConfig.terminal 下挂的差异化配置键:h5 / weapp / mp-harmony / app
|
||||
* 这里返回的 key 必须与后端设计器输出的 terminal 字段名一致
|
||||
* 后端 terminal 键:h5 / weapp / harmony / app / mp-alipay / mp-baidu / mp-toutiao
|
||||
*/
|
||||
platform() {
|
||||
// #ifdef H5
|
||||
@@ -69,8 +68,8 @@ export default {
|
||||
},
|
||||
/**
|
||||
* 后端键名 → 内部 platform 名 兼容层
|
||||
* 不同后端序列化路径可能用 mp-weixin / wechat / mp-harmony 等不同的 key,
|
||||
* 在这里统一映射到内部 platform 名,避免 config() 里到处写 if/else。
|
||||
* canonical 与 platform() 返回值一致;别名为兼容 DB 旧 app_type(upgrade-to-ai-agent.sql)
|
||||
* 及 uniapp / 设计器的历史命名。键名严格区分大小写。
|
||||
*/
|
||||
platformAliases() {
|
||||
return {
|
||||
@@ -80,7 +79,15 @@ export default {
|
||||
'wechat': 'weapp',
|
||||
'harmony': 'harmony',
|
||||
'app': 'app',
|
||||
'app-plus': 'app'
|
||||
'app-plus': 'app',
|
||||
'mp-alipay': 'mp-alipay',
|
||||
'aliapp': 'mp-alipay',
|
||||
'alipay': 'mp-alipay',
|
||||
'mp-baidu': 'mp-baidu',
|
||||
'baiduapp': 'mp-baidu',
|
||||
'baidu': 'mp-baidu',
|
||||
'mp-toutiao': 'mp-toutiao',
|
||||
'toutiao': 'mp-toutiao'
|
||||
};
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -321,12 +321,10 @@ export default {
|
||||
},
|
||||
/**
|
||||
* 获取商品表单
|
||||
* 后端与 /form/api/form/info 对齐:res.data = {json_data:[...组件], form_config:{...样式(camelCase)}}
|
||||
* - 把组件数组塞进 goodsSkuDetail.goods_form(保持下游 <ns-form :data> 用法不变)
|
||||
* - 把 form_config 单独存到 goodsSkuDetail.goods_form_config,下游 <ns-form :formConfig="..."> 消费
|
||||
* 历史扁平数组兼容:若后端还是返回 list 形态(旧实现),form_config 留空,走 ns-form 默认值。
|
||||
* 数据兜底:res.data 为 null(商品没绑表单)时也初始化为空数组 + 空对象,
|
||||
* 避免下游 v-bind 把 undefined 传给 ns-newform 的 Array-typed :data prop。
|
||||
* 后端 goodsform 接口与 info() 对齐,返回 {json_data, form_config(camelCase),
|
||||
* form_name, form_tip, form_banner, show_banner, show_tip}。
|
||||
* 全部字段都落到 goodsSkuDetail 上:表单字段 / 样式 / banner / tip 元数据,
|
||||
* 给 detail.vue 的 diy-form 直接消费。所有分支都做兜底初始化,避免下游拿到 undefined。
|
||||
*/
|
||||
async getGoodsForm() {
|
||||
const res = await this.$api.sendRequest({
|
||||
@@ -336,20 +334,41 @@ export default {
|
||||
},
|
||||
async: false
|
||||
});
|
||||
if (!res || res.code != 0 || !res.data) {
|
||||
// 商品没绑表单 / 接口报错:保持 goods_form 是空数组,避免下游 type 警告
|
||||
const empty = () => {
|
||||
this.$set(this.goodsSkuDetail, 'goods_form', []);
|
||||
this.$set(this.goodsSkuDetail, 'goods_form_config', {});
|
||||
this.$set(this.goodsSkuDetail, 'goods_form_name', '');
|
||||
this.$set(this.goodsSkuDetail, 'goods_form_tip', '');
|
||||
this.$set(this.goodsSkuDetail, 'goods_form_banner', '');
|
||||
this.$set(this.goodsSkuDetail, 'goods_form_show_banner', false);
|
||||
this.$set(this.goodsSkuDetail, 'goods_form_show_tip', false);
|
||||
};
|
||||
if (!res || res.code != 0 || !res.data) {
|
||||
empty();
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(res.data)) {
|
||||
// 旧版扁平数组兼容
|
||||
empty();
|
||||
this.$set(this.goodsSkuDetail, 'goods_form', res.data);
|
||||
this.$set(this.goodsSkuDetail, 'goods_form_config', {});
|
||||
} else {
|
||||
this.$set(this.goodsSkuDetail, 'goods_form', res.data.json_data || []);
|
||||
this.$set(this.goodsSkuDetail, 'goods_form_config', res.data.form_config || {});
|
||||
return;
|
||||
}
|
||||
this.$set(this.goodsSkuDetail, 'goods_form', res.data.json_data || []);
|
||||
this.$set(this.goodsSkuDetail, 'goods_form_config', res.data.form_config || {});
|
||||
this.$set(this.goodsSkuDetail, 'goods_form_name', res.data.form_name || '');
|
||||
this.$set(this.goodsSkuDetail, 'goods_form_tip', res.data.form_tip || '');
|
||||
this.$set(this.goodsSkuDetail, 'goods_form_banner', res.data.form_banner || '');
|
||||
// show_banner/show_tip 后端存 0/1,归一化 boolean
|
||||
this.$set(
|
||||
this.goodsSkuDetail,
|
||||
'goods_form_show_banner',
|
||||
res.data.show_banner == 1 ? true : (res.data.show_banner === 0 ? false : true)
|
||||
);
|
||||
this.$set(
|
||||
this.goodsSkuDetail,
|
||||
'goods_form_show_tip',
|
||||
res.data.show_tip == 1 ? true : (res.data.show_tip === 0 ? false : true)
|
||||
);
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -182,6 +182,9 @@ export default {
|
||||
labelColor: pick('labelColor', 'label_color'),
|
||||
requiredColor: pick('requiredColor', 'required_color'),
|
||||
checkedColor: pick('checkedColor', 'checked_color'),
|
||||
// 占位符:遗漏会被 ns-newform SCSS 默认值回退覆盖
|
||||
placeholderColor: pick('placeholderColor', 'placeholder_color'),
|
||||
placeholderFontSize: pick('placeholderFontSize', 'placeholder_font_size'),
|
||||
submitText: pick('submitText', 'submit_text'),
|
||||
submitColor: pick('submitColor', 'submit_color'),
|
||||
submitBgColor: pick('submitBgColor', 'submit_bg_color'),
|
||||
|
||||
@@ -411,11 +411,12 @@
|
||||
</view> -->
|
||||
<!-- v-if="goodsSkuDetail.goodsForm" -->
|
||||
<view style="padding: 0 30rpx;">
|
||||
<ns-newform
|
||||
:data="informationform"
|
||||
:form-config="goodsSkuDetail.goods_form_config"
|
||||
ref="form"
|
||||
></ns-newform>
|
||||
<diy-form
|
||||
:value="formDiyValue"
|
||||
dataMode="raw"
|
||||
:show-submit="false"
|
||||
ref="form"
|
||||
></diy-form>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="button-box"><button type="primary" @click="saveubfirnation()">{{ $lang('goods.detail.confirm') }}</button></view>
|
||||
@@ -549,6 +550,21 @@ export default {
|
||||
nsGoodsPromotion
|
||||
},
|
||||
mixins: [base, detail, scroll],
|
||||
computed: {
|
||||
// diy-form raw 模式 value:banner/tip 由独立列归一化后的 goods_form_* 提供,
|
||||
// 与 formdata.vue 的 diyValue 同源;本页 :show-submit="false" 走外部"确定"按钮提交。
|
||||
formDiyValue() {
|
||||
const sku = this.goodsSkuDetail || {};
|
||||
return {
|
||||
jsonData: sku.goods_form || [],
|
||||
formConfig: sku.goods_form_config || {},
|
||||
show_banner: sku.goods_form_show_banner === true,
|
||||
form_banner: sku.goods_form_banner || '',
|
||||
show_tip: sku.goods_form_show_tip === true,
|
||||
form_tip: sku.goods_form_tip || ''
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 发送商品信息到智能客服
|
||||
|
||||
@@ -24,9 +24,10 @@ export default {
|
||||
|
||||
membercard: null, // 会员卡信息
|
||||
hackReset: true,
|
||||
cardOff: false,
|
||||
informationform:[]//留言表单
|
||||
|
||||
cardOff: false
|
||||
// 留言表单数据不再在 data() 维护:detail.vue 的 computed formDiyValue
|
||||
// 直接从 goodsSkuDetail.goods_form / goods_form_config / goods_form_* 实时读取并打包成
|
||||
// diy-form raw 模式期望的 value 结构。
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -221,7 +222,6 @@ export default {
|
||||
|
||||
//商品留言打开
|
||||
showinformation(){
|
||||
this.informationform = this.goodsSkuDetail?.goods_form ?? [];
|
||||
this.$refs.informationPopup.open();
|
||||
},
|
||||
//商品留言关闭
|
||||
@@ -230,18 +230,18 @@ export default {
|
||||
},
|
||||
//保存商品留言
|
||||
saveubfirnation(){
|
||||
//缺少
|
||||
// ref 指向 <diy-form>:diy-form 只暴露 getFormData() 方法,无 formData 属性
|
||||
if (!this.$refs.form.verify()) return;
|
||||
|
||||
|
||||
// uni.setStorageSync('goodFormData', {
|
||||
// goods_id: this.goodsSkuDetail.goods_id,
|
||||
// form_data: this.$refs.form.formData
|
||||
// form_data: this.$refs.form.getFormData()
|
||||
// });
|
||||
this.$api.sendRequest({
|
||||
url: '/api/goods/information',
|
||||
data: {
|
||||
goods_id: this.goodsSkuDetail.goods_id,
|
||||
form_data: JSON.stringify(this.$refs.form.formData)
|
||||
form_data: JSON.stringify(this.$refs.form.getFormData())
|
||||
},
|
||||
success: res => {
|
||||
var data = res.data;
|
||||
|
||||
Reference in New Issue
Block a user