hookehuyr

✨ feat: 联调自定义规则显示字段功能

<!--
* @Date: 2022-08-30 13:46:51
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2023-02-10 15:34:39
* @LastEditTime: 2023-02-27 14:24:03
* @FilePath: /data-table/src/components/PickerField/index.vue
* @Description: 单列选择器组件
-->
......@@ -37,6 +37,7 @@
const props = defineProps({
item: Object,
});
const emit = defineEmits(["active"]);
// TEST: 测试新功能:选择其他选项时,下方出现输入框,如果其他项被选中,输入框值为最终录入值。
// 绑定值发生变化时回调,处理选项为其他时的输入项录入
......@@ -61,6 +62,8 @@ const showPicker = ref(false);
const onConfirm = ({ selectedOptions }) => {
props.item.value = selectedOptions[0]?.value;
showPicker.value = false;
// 触发点自定义监听事件,配合规则显示隐藏其他字段
emit("active", { key: props.item.key, value: selectedOptions[0]?.value, type: "picker" });
// if (add_info_key.value === props.item.value) {
// has_add_info.value = true;
// }
......
<!--
* @Date: 2022-07-18 10:22:22
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2023-02-23 15:41:13
* @LastEditTime: 2023-02-27 18:52:17
* @FilePath: /data-table/src/views/index.vue
* @Description: 首页
-->
<template>
<van-notice-bar
v-if="formSetting.sjsj_is_count_down"
left-icon="volume-o"
:text="notice_text"
scrollable
mode="closeable"
/>
<div class="table-box" :style="{ margin: is_pc ? '1rem 0' : '1rem', overflow: 'auto'}">
<van-notice-bar v-if="formSetting.sjsj_is_count_down" left-icon="volume-o" :text="notice_text" scrollable
mode="closeable" />
<div class="table-box" :style="{ margin: is_pc ? '1rem 0' : '1rem', overflow: 'auto' }">
<template v-if="PHeader.visible">
<van-image
v-if="PHeader.type === 'image'"
width="100%"
:src="PHeader.cover"
fit="cover"
/>
<van-image v-if="PHeader.type === 'image'" width="100%" :src="PHeader.cover" fit="cover" />
<template v-if="PHeader.type === 'carousel'">
<van-swipe class="my-swipe" lazy-render indicator-color="white">
<van-swipe-item v-for="image in PHeader.cover" :key="index"
><img :src="image" style="height: 12rem; width: 100%; object-fit: cover"
/></van-swipe-item>
<van-swipe-item v-for="image in PHeader.cover" :key="index"><img :src="image"
style="height: 12rem; width: 100%; object-fit: cover" /></van-swipe-item>
</van-swipe>
</template>
<div v-if="PHeader.type === 'text'" class="PHeader-Text" v-html="PHeader.banner" />
......@@ -35,22 +24,15 @@
<van-config-provider :theme-vars="themeVars">
<van-form @submit="onSubmit" scroll-to-error="true">
<van-cell-group :border="false">
<component
v-for="(item, index) in formData"
:id="item.key"
:ref="(el) => setRefMap(el, item)"
:key="index"
:is="item.component"
:item="item"
@active="onActive"
/>
</van-cell-group>
<div v-if="formData.length && PCommit.visible" style="margin: 16px">
<van-button round block type="primary" native-type="submit">
{{ PCommit.text ? PCommit.text : '提交' }}
</van-button>
</div>
<!-- <van-cell-group :border="false">
<component v-for="(item, index) in formData" :id="item.key" :ref="(el) => setRefMap(el, item)" :key="index"
:is="item.component" :item="item" @active="onActive" />
</van-cell-group>
<div v-if="formData.length && PCommit.visible" style="margin: 16px">
<van-button round block type="primary" native-type="submit">
{{ PCommit.text ? PCommit.text : '提交' }}
</van-button>
</div>
<!-- <van-cell-group :border="false">
<component
v-for="(item, index) in mockData"
:id="item.key"
......@@ -59,19 +41,17 @@
:is="item.component"
:item="item"
@active="onActive"
/>
</van-cell-group>
<div v-if="mockData.length && PCommit.visible" style="margin: 16px">
<van-button round block type="primary" native-type="submit">
{{ PCommit.text ? PCommit.text : '提交' }}
</van-button>
</div> -->
/>
</van-cell-group>
<div v-if="mockData.length && PCommit.visible" style="margin: 16px">
<van-button round block type="primary" native-type="submit">
{{ PCommit.text ? PCommit.text : '提交' }}
</van-button>
</div> -->
</van-form>
</van-config-provider>
</div>
<div
style="text-align: center; color: #545454; font-size: 0.85rem; padding-bottom: 1rem"
>
<div style="text-align: center; color: #545454; font-size: 0.85rem; padding-bottom: 1rem">
提交即授权该表单收集你的填写信息
</div>
<van-overlay :show="show">
......@@ -89,7 +69,8 @@
<div style="text-align: center; margin-top: 0.5rem;">请输入密码填写表单</div>
<van-config-provider :theme-vars="themeVars">
<van-form>
<van-field v-model="mmtx_password" type="password" autocomplete label="密码" style="border: 1px solid #dfdfdf; margin: 1rem 0; border-radius: 5px;" />
<van-field v-model="mmtx_password" type="password" autocomplete label="密码"
style="border: 1px solid #dfdfdf; margin: 1rem 0; border-radius: 5px;" />
<van-button @click="onSubmitPwd" type="primary" round block>验证并填写表单</van-button>
</van-form>
</van-config-provider>
......@@ -260,6 +241,81 @@ onMounted(async () => {
};
}
formData.value = formatData(page_form);
// TODO: 等待真实数据结构 重构规则数据结构
const rule_list = [
{
"mode": "SHOW",
"field_names": [
"man_inpu"
],
"logical_op": "OR",
"expr_list": [
{
"field_name": "sex",
"op": "IN",
"values": [
"男"
]
}
],
"text": ""
},
{
"mode": "SHOW",
"field_names": [
"woman_input"
],
"logical_op": "OR",
"expr_list": [
{
"field_name": "sex",
"op": "IN",
"values": [
"女"
]
}
],
"text": ""
},
{
"mode": "HIDE",
"field_names": [
"phone",
"id_card"
],
"logical_op": "AND",
"expr_list": [
{
"field_name": "more",
"op": "IN",
"values": [
"不想填了",
]
},
{
"field_name": "field_9",
"op": "IN",
"values": [
"说明1",
]
}
],
"text": ""
}
];
formData.value.forEach(item => {
rule_list.forEach(rule => {
if (rule.field_names?.includes(item.key)) {
item.field_rules = {
mode: rule.mode,
logical_op: rule.logical_op,
expr_list: rule.expr_list,
}
}
})
})
mockData.value = [
{
key: "111",
......@@ -348,6 +404,44 @@ const checkUserPassword = async () => {
}
}
// 根据规则隐藏相应字段
const checkRules = (field) => {
formData.value.forEach(item => {
// 只检查存在规则的字段
if (item.field_rules) {
let condition = '';
// 多个规则的满足条件,为全且或者全或
const op = item.field_rules?.logical_op === 'AND' ? '&&' : '||';
item.field_rules?.expr_list.forEach(expr => {
if (typeof postData.value[expr['field_name']] === 'string') { // 表单值为字符串(单选,下拉)
const k = !!expr['values'].includes(postData.value[expr['field_name']])
condition += `${k} ${op}`
}
if (typeof postData.value[expr['field_name']] === 'object') { // 表单值为数组(多选)
const k = !!(_.intersection(expr['values'], postData.value[expr['field_name']])).length;
condition += `${k} ${op}`
}
});
// 把结果转换为布尔值
if (item.field_rules?.logical_op === 'AND') {
if (condition.indexOf('false') >= 0) {
condition = false;
} else {
condition = true;
}
}
if (item.field_rules?.logical_op === 'OR') {
if (condition.indexOf('true') >= 0) {
condition = true;
} else {
condition = false;
}
}
item['component_props']['disabled'] = item.field_rules?.mode === 'SHOW' ? !condition : condition;
}
})
}
// 操作绑定自定义字段回调
const onActive = (item) => {
if (item.key === "area_picker") {
......@@ -365,10 +459,13 @@ const onActive = (item) => {
if (item.type === "rate") {
postData.value = _.assign(postData.value, { [item.key]: item.value });
}
if (item.type === "radio") {
// if (item.type === "picker") { // 下拉框控件
// // console.warn(item);
// }
if (item.type === "radio") { // 单选控件
postData.value = _.assign(postData.value, { [item.key]: item.affix ? item.affix : item.value });
}
if (item.type === "checkbox") {
if (item.type === "checkbox") { // 多选控件
const checkbox_value = _.cloneDeep(item.value)
checkbox_value.forEach((element, index) => {
for (const key in item.affix) {
......@@ -379,6 +476,9 @@ const onActive = (item) => {
});
postData.value = _.assign(postData.value, { [item.key]: checkbox_value });
}
// 检查规则,会影响字段显示
checkRules(item);
};
// 检验没有绑定name的输入项
......@@ -510,6 +610,7 @@ const onSubmit = async (values) => {
text-align: center;
white-space: pre-wrap;
}
.table-desc {
padding: 0rem 1rem;
color: #666;
......@@ -520,6 +621,7 @@ const onSubmit = async (values) => {
width: 100%;
}
}
.table-box {
background-color: #ffffff;
padding-bottom: 1rem;
......@@ -543,6 +645,7 @@ const onSubmit = async (values) => {
align-items: center;
justify-content: center;
height: 100%;
.block {
width: 80vw;
background-color: #fff;
......@@ -554,7 +657,7 @@ const onSubmit = async (values) => {
.PHeader-Text {
padding: 1rem;
font-weight: bold;
white-space:pre;
white-space: pre;
}
// :deep(.van-icon) { // 处理正式服务器上箭头上下位移问题
......