新增表单提交流程

master
于肖磊 2025-07-09 16:48:33 +08:00
parent 0f83d1bee4
commit 1d9cd71fac
6 changed files with 256 additions and 17 deletions

View File

@ -28,7 +28,6 @@
@dataAddressChange="data_address_change"
@openRegion="open_region"
@helpIconEvent="help_icon_event"
@subformHelpIconEvent="subform_help_icon_event"
@zIndexChange="z_index_change"
@regionEvent="region_event"
@subformDataChange="subform_data_change"
@ -42,7 +41,7 @@
<iconfont name="icon-detail" size="30rpx" color="#666" propContainerDisplay="flex" ></iconfont>
{{ overall_config.save_draft_title }}
</view>
<button v-if="overall_config.is_show_submit == '1'" class="flex-1 submit_title flex-row align-c jc-c" :style="'background:' + submit_bg_color" type="default">{{ overall_config.submit_title }}</button>
<button v-if="overall_config.is_show_submit == '1'" class="flex-1 submit_title flex-row align-c jc-c" :style="'background:' + submit_bg_color" type="default" :disable="is_submit_disable" @tap="submit_click">{{ overall_config.submit_title }}</button>
</view>
</view>
</view>
@ -55,7 +54,7 @@
</template>
<script>
import { isEmpty, common_form_styles_computer } from '@/common/js/common/common.js';
import { isEmpty, common_form_styles_computer, get_format_checks } from '@/common/js/common/common.js';
const app = getApp();
import componentShow from '@/pages/form-input/components/form-input/modules/component-show/index.vue';
export default {
@ -97,6 +96,7 @@ export default {
popup_help_content: '',
scrollTop: 0,
z_index_id: '',
is_submit_disable: false
};
},
watch: {
@ -284,11 +284,6 @@ export default {
this.setData({ popup_help_content: val });
this.$refs.popup.open();
},
//
subform_help_icon_event(e) {
this.setData({ popup_help_content: e });
this.$refs.popup.open();
},
//
region_event(e) {
const { value, id, province_name, city_name, county_name } = e;
@ -314,6 +309,244 @@ export default {
});
this.setData({ data_list: data });
},
submit_click() {
//
const new_data = this.submit_data_check();
//
const data = new_data.find((item) => item.com_data.common_config.is_error === '1' || (item.key === 'subform' && item.com_data.data_list.some((item1) => item1.data_list.some(list_item => list_item.com_data.common_config.is_error === '1'))));
if (!isEmpty(data)) {
if (data.key === 'subform') {
// error
if (data.com_data.common_config.is_error == '1') {
app.globalData.showToast(`${data.com_data.title}${data.com_data.common_config.error_text}`, 'error');
} else {
//
app.globalData.showToast(`请检查${data.com_data.title}内的填写`, 'error');
}
} else {
app.globalData.showToast(`${data.com_data.title}${data.com_data.common_config.error_text}`, 'error');
}
//
const old_data = [...this.data_list];
const data_list = old_data.map(item => {
const match = new_data.find(el => el.id === item.id);
return { ...item, ...match };
});
this.setData({ data_list: data_list });
} else {
this.submit_data_parameter_handle();
}
},
submit_data_parameter_handle() {
const submit_data = {};
const filter_data = ['video', 'img', 'auxiliary-line', 'position', 'rect', 'round', 'text', 'attachments'];
//
this.filteredDiyData.forEach((item) => {
if (!filter_data.includes(item.key)) {
const name = isEmpty(item.form_name) ? item.id : item.form_name;
const value = isEmpty(item.com_data.form_value) ? '' : item.com_data.form_value;
const com_data = item.com_data;
if (item.key ==='subform') {
const data_list = com_data.data_list;
submit_data[name] = data_list.map((subform_item) => {
const data = {};
//
subform_item.data_list.forEach((item1) => {
const subform_name = isEmpty(item1.form_name) ? item1.id : item1.form_name;
const subform_com_data = item1.com_data;
const subform_value = isEmpty(subform_com_data.form_value) ? '' : subform_com_data.form_value;
if (!filter_data.includes(item1.key)) {
if (item1.key == 'address') {
data[`${ subform_name }_province_id`] = subform_value[0] || '';
data[`${ subform_name }_city_id`] = subform_value[1] || '';
data[`${ subform_name }_county_id`] = subform_value[2] || '';
//
submit_data[`${ name }_province_name`] = subform_com_data.province_name || '';
submit_data[`${ name }_city_name`] = subform_com_data.city_name || ''
submit_data[`${ name }_county_name`] = subform_com_data.county_name || ''
} else {
data[subform_name] = subform_value;
}
}
});
return data;
});
} else if (item.key ==='phone') {
submit_data[`${ name }`] = value || '';
//
if (com_data.is_sms_verification == '1') {
submit_data[`${ name }_verify`] = com_data?.form_value_code || '';
}
} else if (item.key == 'address') {
submit_data[`${ name }_province_id`] = value[0] || '';
submit_data[`${ name }_city_id`] = value[1] || '';
submit_data[`${ name }_county_id`] = value[2] || '';
//
submit_data[`${ name }_province_name`] = com_data.province_name || '';
submit_data[`${ name }_city_name`] = com_data.city_name || ''
submit_data[`${ name }_county_name`] = com_data.county_name || ''
//
if (com_data.address_type == 'detailed') {
submit_data[`${ name }_address`] = com_data?.detailed_value || '';
}
} else if (['select', 'radio-btns'].includes(item.key)) {
submit_data[name] = value;
const value_list = com_data.option_list.filter((item) => item.is_other == '1');
if (value_list.length > 0) {
submit_data[`${ name }_other_value`] = com_data?.other_value || '';
}
} else {
submit_data[name] = value;
}
}
});
const params = {
forminput_id: this.propDataFormId,
...submit_data
}
this.is_submit_disable = true;
uni.request({
url: app.globalData.get_request_url('save', 'forminputdata'),
method: 'POST',
data: params,
dataType: 'json',
success: (res) => {
this.is_submit_disable = false;
app.globalData.showToast('提交成功', 'success');
},
fail: (res) => {
this.is_submit_disable = false;
app.globalData.showToast('提交失败', 'error');
}
});
},
submit_data_check() {
//
const fieldCheckMap = {
'address': { is_format: false, type: 'address' },
'number': { is_format: false, type: 'number' },
'checkbox': { is_format: true, type: 'checkbox' },
'select-multi': { is_format: true, type: 'checkbox' },
'date': { is_format: false, type: 'time' },
'date-group': { is_format: false, type: 'time' },
'single-text': { is_format: false, type: '' },
'multi-text': { is_format: false, type: '' },
'rich-text': { is_format: false, type: '' },
'radio-btns': { is_format: false, type: 'radio' },
'select': { is_format: false, type: 'select' },
'pwd': { is_format: false, type: '' },
'score': { is_format: false, type: 'score' },
'upload-attachments': { is_format: false, type: 'upload' },
'upload-img': { is_format: false, type: 'upload' },
'upload-video': { is_format: false, type: 'upload' }
};
const data = JSON.parse(JSON.stringify(this.filteredDiyData));
//
data?.forEach((item) => {
const com_data = item.com_data;
//
if (com_data.is_required === '1') {
//
if (item.key === 'phone') {
const { is_error = '0', error_text = '' } = this.handlePhoneValidation(com_data);
com_data.common_config.is_error = is_error;
com_data.common_config.error_text = error_text;
}
//
else if (fieldCheckMap[item.key]) {
const { is_format, type } = fieldCheckMap[item.key];
const { is_error = '0', error_text = '' } = get_format_checks(com_data, com_data.form_value, is_format, type);
com_data.common_config.is_error = is_error;
com_data.common_config.error_text = error_text;
}
};
/**
* 子表单处理逻辑
* 1. 检查子表单中是否有必填项
* 2. 验证子表单整体必填性
* 3. 处理子表单内各字段的验证
*/
if (item.key === 'subform') {
//
if (com_data.is_required === '1' && com_data.data_list.length <= 0) {
com_data.common_config.is_error = '1';
com_data.common_config.error_text = '请填写至少一条记录';
} else {
com_data.common_config.is_error = '0';
com_data.common_config.error_text = '';
}
//
if (com_data.data_list.length > 0) {
//
com_data.data_list.forEach((form_item, index) => {
//
const form_data = this.filtered_Data(form_item.data_list);
form_data.forEach((data_item) => {
//
if (data_item.com_data.is_required !== '1') return;
//
const checkConfig = fieldCheckMap[data_item.key];
if (checkConfig) {
//
if (data_item.key === 'phone') {
const { is_error = '0', error_text = '' } = this.handlePhoneValidation(data_item);
data_item.com_data.common_config.is_error = is_error;
data_item.com_data.common_config.error_text = error_text;
}
//
else if (fieldCheckMap[data_item.key]) {
const { is_format, type } = fieldCheckMap[data_item.key];
const { is_error = '0', error_text = '' } = get_format_checks(data_item.com_data, data_item.com_data.form_value, is_format, type);
data_item.com_data.common_config.is_error = is_error;
data_item.com_data.common_config.error_text = error_text;
}
}
});
});
}
}
});
return data;
},
//
handlePhoneValidation(com_data) {
if (com_data.is_sms_verification === '1' && com_data.is_required === '1' && isEmpty(com_data.form_value_code)) {
com_data.common_config.is_error = '1';
com_data.common_config.error_text = '短信验证码不能为空';
return;
}
com_data.common_config.format = com_data.is_telephone === '1' ? 'telephone-number' : 'phone-number';
return get_format_checks(com_data, com_data.form_value_code, true);
},
//
filtered_Data(children) {
const componentMap = new Map(children.map((item) => [item.id, item]));
//
const list = children.filter((item) => ['single-text', 'select', 'radio-btns'].includes(item.key) && ['select', 'radio-btns'].includes(item.com_data.type) && item.com_data.show_hidden_list.length > 0);
const list_map = list.map((item) => ({ id: item.id, list: item.com_data.show_hidden_list }));
return children.filter((item) => {
//
if (item.is_enable !== '1') return false;
if (list_map.length === 0) return true;
//
const isShownByRule = list_map.some((list_item) => {
const targetComponent = componentMap.get(list_item.id);
//
if (!targetComponent) return false;
return list_item.list.some(hidden_item => {
//
if (hidden_item.is_show.includes(item.id)) {
return targetComponent.com_data.form_value.includes(hidden_item.value);
} else {
return true;
}
});
});
return isShownByRule;
});
},
z_index_change(e) {
this.setData({
z_index_id: e

View File

@ -123,8 +123,8 @@
:propTitleStyle="propTitleStyle"
:propHelpIconStyle="propHelpIconStyle"
:propFieldLabelStyle="propFieldLabelStyle"
:propDataFormId="propDataFormId"
@subformHelpIconEvent="subform_help_icon_event"
:propDataFormId="propDataFormId"
@helpIconEvent="subform_help_icon_event"
@subformDataChange="subform_data_change"
/>
</view>
@ -273,7 +273,7 @@ export default {
this.$emit('helpIconEvent', e.currentTarget.dataset.value);
},
subform_help_icon_event(e) {
this.$emit('subformHelpIconEvent', e);
this.$emit('helpIconEvent', e);
},
data_change(e) {
this.$emit('dataChange', e);

View File

@ -240,9 +240,6 @@ export default {
help_icon_event(e) {
this.$emit('helpIconEvent', e.currentTarget.dataset.value);
},
subform_help_icon_event(e) {
this.$emit('subformHelpIconEvent', e, this.propIndex);
},
data_change(e) {
this.$emit('dataChange', e, this.propIndex);
},

View File

@ -5,7 +5,7 @@
<template v-if="isEmpty(form_value_data)"><view class="placeholder cr-gray text-line-1">{{ placeholder }}</view></template>
<template v-else>
<view :class="'flex-row align-c' + (is_multicolour == '1' ? ' gap-10' : '')">
<view class="text-size-sm nowrap text-line-1" v-for="(item, index) in form_value_data" :key="index" :style="is_multicolour == '1' ? 'background:' + item.color + ';color:' + (item.is_other == '1' ? '#141E31' : '#fff') + ';border-radius:8rpx;' + color_style : color_style + 'padding-left:0rpx;padding-right:0rpx;'">{{ item.name || item.value }}{{ index != form_value_data.length - 1 && is_multicolour !== '1' ? ',' : ''}}</view>
<view class="text-size-sm nowrap" v-for="(item, index) in form_value_data" :key="index" :style="is_multicolour == '1' ? 'background:' + item.color + ';color:' + (item.is_other == '1' ? '#141E31' : '#fff') + ';border-radius:8rpx;' + color_style : color_style + 'padding-left:0rpx;padding-right:0rpx;'">{{ item.name || item.value }}{{ index != form_value_data.length - 1 && is_multicolour !== '1' ? ',' : ''}}</view>
</view>
</template>
</view>

View File

@ -5,7 +5,7 @@
<template v-if="isEmpty(form_value)"><view class="placeholder cr-gray text-line-1">{{ placeholder }}</view></template>
<template v-else>
<view class="flex-row align-c">
<view class="text-size-sm text-line-1" :style="is_multicolour == '1' ? 'background:' + form_value_data.color + ';color:' + (form_value_data.is_other == '1' ? '#141E31' : '#fff') + ';border-radius:8rpx;' + color_style : color_style + 'padding-left:0rpx;padding-right:0rpx;'">{{ form_value_data.name || form_value }}</view>
<view class="text-size-sm" :style="is_multicolour == '1' ? 'background:' + form_value_data.color + ';color:' + (form_value_data.is_other == '1' ? '#141E31' : '#fff') + ';border-radius:8rpx;' + color_style : color_style + 'padding-left:0rpx;padding-right:0rpx;'">{{ form_value_data.name || form_value }}</view>
</view>
</template>
</view>

View File

@ -55,7 +55,7 @@
@dataCheck="data_check"
@dataOptionChange="data_option_change"
@openRegion="open_region"
@helpIconEvent="help_icon_event"
@helpIconEvent="subform_help_icon_event"
@regionEvent="region_event"
@zIndexChange="z_index_change"
/>
@ -142,6 +142,12 @@
};
},
watch: {
propValue: {
handler(val) {
this.init();
},
deep: true,
},
propKey(val) {
//
this.init();
@ -231,6 +237,9 @@
help_icon_event(e) {
this.$emit('helpIconEvent', e.currentTarget.dataset.value);
},
subform_help_icon_event(e) {
this.$emit('helpIconEvent', e);
},
//
data_check(e, index) {
const { is_error, error_text, value, id } = e;