refactor(diy-form): 重构自定义表单组件,替换为通用表单组件

1.  替换硬编码表单项为可配置的ns-newform组件
2.  支持横向/纵向两种布局模式
3.  添加表单Banner、提示语配置能力
4.  统一表单提交逻辑,新增表单校验和重置功能
5.  优化ns-newform组件样式与交互细节
This commit is contained in:
2026-06-08 16:47:02 +08:00
parent 4f44b4f574
commit 14ba88b645
2 changed files with 439 additions and 249 deletions

View File

@@ -1,47 +1,36 @@
<template>
<view data-component-name="diy-form" class="diy-from" :style="style">
<view class="fui-cell-group">
<view class="fui-cell ">
<view class="fui-cell-label ">您的姓名</view>
<view class="fui-cell-info">
<input v-model="Form.realname" class="fui-input" placeholder="请输入您的姓名" value=""></input>
</view>
</view>
<view class="fui-cell ">
<view class="fui-cell-label">手机号码</view>
<view class="fui-cell-info">
<input v-model="Form.mobile" class="fui-input" maxlength="11" placeholder="请输入您的手机号"
type="number"></input>
</view>
</view>
<view class="fui-cell ">
<view class="fui-cell-label">您的邮箱</view>
<view class="fui-cell-info">
<input v-model="Form.mailbox" class="fui-input" placeholder="请输入您的邮箱" type="text"></input>
</view>
</view>
<view class="fui-cell">
<view class="fui-cell-label">所在城市</view>
<view class="fui-cell-info">
<input v-model="Form.citys" class="fui-input" placeholder="请输入您的所在地" value=""></input>
</view>
</view>
<view class="fui-cell">
<view class="fui-cell-label">备注</view>
<view class="fui-cell-info">
<input v-model="Form.remark" class="fui-input" placeholder="请输入备注" value=""></input>
</view>
</view>
<view data-component-name="diy-form" class="diy-from" :class="[formLayoutClass]" :style="style">
<!-- Banner -->
<view v-if="value.show_banner && value.form_banner" class="form-banner">
<image :src="$util.img(value.form_banner)" mode="widthFix" class="banner-img" />
</view>
<view @tap.stop="submitform" class="fui-btn btn-danger block mtop">提交信息</view>
<!-- 提示语 -->
<view v-if="value.show_tip && value.form_tip" class="form-tip">{{ value.form_tip }}</view>
<!-- 表单组件 -->
<ns-newform
:data="formComponents"
:customAttr="value"
:mode="value.form_layout === 'vertical' ? 'vertical' : 'horizontal'"
:labelWidthMode="value.label_width_mode"
:labelFixedWidth="value.label_fixed_width"
:labelFontSize="value.label_font_size"
:labelColor="value.label_color"
:requiredColor="value.required_color"
ref="nsNewform"
/>
<!-- 提交按钮 -->
<view @click.stop="submitForm" class="fui-btn btn-danger block mtop">提交信息</view>
</view>
</template>
<script>
// 自定义表单
import DiyMinx from './minx.js'
import NsNewform from '../pages_tool/_components/ns-newform/ns-newform.vue'
export default {
name: 'diy-from',
components: { NsNewform },
props: {
value: {
type: Object
@@ -50,54 +39,94 @@ export default {
mixins: [DiyMinx],
data() {
return {
loading: true,
markers: [],
Form: {
realname: '',
mobile: '',
mailbox: '',
citys: '',
remark: '',
}
formComponents: [] // 转换后的表单组件
};
},
created() {
this.initForm();
},
watch: {
// 组件刷新监听
componentRefresh: function (nval) {
// this.getDataList();
'value.formComponents': {
deep: true,
handler() {
this.initForm();
}
}
},
computed: {
markerst() {
return [{
id: 1,
latitude: this.value.list[0].lat,
longitude: this.value.list[0].lng
}]
},
style() {
var css = '';
css += 'background-color:' + this.value.contentBgColor + ';';
if (this.value.elementAngle == 'round') {
if (this.value.elementAngle === 'round') {
css += 'border-top-left-radius:' + this.value.topElementAroundRadius * 2 + 'rpx;';
css += 'border-top-right-radius:' + this.value.topElementAroundRadius * 2 + 'rpx;';
css += 'border-bottom-left-radius:' + this.value.bottomElementAroundRadius * 2 + 'rpx;';
css += 'border-bottom-right-radius:' + this.value.bottomElementAroundRadius * 2 + 'rpx;';
}
return css;
},
formLayoutClass() {
return this.value.form_layout === 'vertical' ? 'form-vertical' : 'form-horizontal';
}
},
methods: {
submitform() {
// 初始化表单 - 将 diy-form 的数据格式转换成 ns-newform 的格式
initForm() {
var components = this.value.formComponents || [];
// 转换格式:type -> controller
this.formComponents = components.map(function(item) {
return {
controller: item.type,
value: item.value,
val: item.value.default || '' // 添加初始值
};
});
},
// 提交表单
submitForm() {
var self = this;
// 使用 ns-newform 的验证
if (this.$refs.nsNewform && this.$refs.nsNewform.verify) {
var verifyResult = this.$refs.nsNewform.verify();
if (!verifyResult) {
return;
}
}
// 获取表单数据
var submitData = {};
if (this.$refs.nsNewform && this.$refs.nsNewform.formData) {
this.$refs.nsNewform.formData.forEach(function(item, index) {
submitData[index] = item.val;
});
}
// 提交到后端
this.$api.sendRequest({
url: '/api/member/information',
data: this.Form,
success: res => {
this.$util.showToast({
title: res.message
});
url: '/form/api/form/create',
data: {
form_id: this.value.form_id || 0,
form_data: JSON.stringify(submitData),
component_id: this.value.id || '',
form_name: this.value.form_name || '默认表单'
},
success: function(res) {
if (res.code === 0) {
uni.showToast({
title: '提交成功',
icon: 'success'
});
// 重置表单
if (self.$refs.nsNewform && self.$refs.nsNewform.setFormData) {
self.$refs.nsNewform.setFormData();
}
} else {
uni.showToast({
title: res.message || '提交失败',
icon: 'none'
});
}
}
});
}
@@ -108,7 +137,29 @@ export default {
<style lang="scss">
.diy-from {
background: #fff;
padding-bottom: 20rpx;
padding: 0 30rpx 20rpx;
border-radius: 10rpx;
.form-banner {
width: 100%;
overflow: hidden;
margin: 0 -30rpx;
.banner-img {
width: 100%;
display: block;
}
}
.form-tip {
padding: 30rpx 0;
text-align: center;
color: #666;
font-size: 28rpx;
}
.fui-btn {
margin: 30rpx 0 0;
}
}
</style>
</style>