From 059630ba2c41d2214312e2db2f22780fddd47700 Mon Sep 17 00:00:00 2001 From: ZF sun <34314687@qq.com> Date: Sat, 18 Jul 2026 10:55:39 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E5=95=86?= =?UTF-8?q?=E5=93=81=E7=95=99=E8=A8=80=E8=A1=A8=E5=8D=95=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E6=9B=BF=E6=8D=A2=E4=B8=BAdiy-form=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 移除页面data中维护的留言表单数据,改为通过computed实时从商品详情数据构建diy-form所需格式 2. 替换ns-newform为diy-form组件,使用raw模式并接管表单提交逻辑 3. 完善平台别名映射,新增更多小程序平台兼容配置 4. 为diy-form新增占位符样式属性绑定 5. 重构商品表单接口处理逻辑,统一所有元数据字段的初始化和兼容处理 --- common/js/form-platform-mixin.js | 17 +++++++++---- common/js/goods_detail_base.js | 43 +++++++++++++++++++++++--------- components-diy/diy-form.vue | 3 +++ pages_goods/detail.vue | 26 +++++++++++++++---- pages_goods/public/js/detail.js | 16 ++++++------ 5 files changed, 75 insertions(+), 30 deletions(-) diff --git a/common/js/form-platform-mixin.js b/common/js/form-platform-mixin.js index 4e229a3..ba4580a 100644 --- a/common/js/form-platform-mixin.js +++ b/common/js/form-platform-mixin.js @@ -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' }; }, /** diff --git a/common/js/goods_detail_base.js b/common/js/goods_detail_base.js index 55e2d98..5600656 100644 --- a/common/js/goods_detail_base.js +++ b/common/js/goods_detail_base.js @@ -321,12 +321,10 @@ export default { }, /** * 获取商品表单 - * 后端与 /form/api/form/info 对齐:res.data = {json_data:[...组件], form_config:{...样式(camelCase)}} - * - 把组件数组塞进 goodsSkuDetail.goods_form(保持下游 用法不变) - * - 把 form_config 单独存到 goodsSkuDetail.goods_form_config,下游 消费 - * 历史扁平数组兼容:若后端还是返回 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) + ); } }, /** diff --git a/components-diy/diy-form.vue b/components-diy/diy-form.vue index 7e0caa7..b2c5d47 100644 --- a/components-diy/diy-form.vue +++ b/components-diy/diy-form.vue @@ -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'), diff --git a/pages_goods/detail.vue b/pages_goods/detail.vue index 1eb63bb..7cf20c8 100644 --- a/pages_goods/detail.vue +++ b/pages_goods/detail.vue @@ -411,11 +411,12 @@ --> - + @@ -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: { /** * 发送商品信息到智能客服 diff --git a/pages_goods/public/js/detail.js b/pages_goods/public/js/detail.js index c9c90ea..38ecf59 100644 --- a/pages_goods/public/js/detail.js +++ b/pages_goods/public/js/detail.js @@ -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 只暴露 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;