2024-04-28 10:10:03 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view class="wflow-form">
|
|
|
|
|
|
<uni-forms ref="wflowForm" class="wflow-form" :rules="rules" :modelValue="_value" label-position="top"
|
|
|
|
|
|
label-width="200">
|
|
|
|
|
|
<uni-forms-item :class="`w-form-item ${item.perm === 'R' ? 'w-form-item-r':''}`" v-for="item in formFields"
|
|
|
|
|
|
v-show="showItem(item, _value[item.id])" :name="item.id" :key="item.id" :required="item.props.required">
|
|
|
|
|
|
<template v-slot:label>
|
|
|
|
|
|
<view class="w-form-title">
|
|
|
|
|
|
<text style="color: #CE5266;" v-if="item.props.required && item.perm === 'E'">* </text>
|
|
|
|
|
|
<text style="font-size: 32rpx;">{{item.title}}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
2024-06-07 16:48:09 +08:00
|
|
|
|
<!-- {{item.name}} -->
|
|
|
|
|
|
<w-form-item :type="item.name" :title="item.title" v-model="_value[item.id]" :form-props="item.props"
|
2024-04-28 10:10:03 +08:00
|
|
|
|
:readonly="item.perm !== 'E'" :formData="_value" />
|
|
|
|
|
|
</uni-forms-item>
|
|
|
|
|
|
</uni-forms>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
2024-06-05 21:35:18 +08:00
|
|
|
|
import {
|
|
|
|
|
|
showItem
|
|
|
|
|
|
} from '@/utils/tool.js'
|
2024-04-28 10:10:03 +08:00
|
|
|
|
import WFormItem from './WFormItem.vue'
|
2024-06-05 21:35:18 +08:00
|
|
|
|
import {
|
|
|
|
|
|
CompareFuncs
|
|
|
|
|
|
} from "./form/compare/CompareOptions.js";
|
2024-04-28 10:10:03 +08:00
|
|
|
|
//import FormComponents from '@/components/form/ComponentsExport.js'
|
|
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
name: 'FormRender',
|
2024-06-05 21:35:18 +08:00
|
|
|
|
options: {
|
|
|
|
|
|
styleIsolation: 'shared'
|
|
|
|
|
|
},
|
|
|
|
|
|
components: {
|
|
|
|
|
|
WFormItem
|
|
|
|
|
|
},
|
2024-04-28 10:10:03 +08:00
|
|
|
|
props: {
|
|
|
|
|
|
modelValue: { //表单双向绑定的值
|
|
|
|
|
|
type: Object,
|
|
|
|
|
|
default: () => {
|
|
|
|
|
|
return {}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
config: { //表单联动相关配置
|
|
|
|
|
|
type: Object,
|
|
|
|
|
|
default: () => {
|
2024-05-08 21:13:11 +08:00
|
|
|
|
return {
|
|
|
|
|
|
ruleType: "SIMPLE",
|
|
|
|
|
|
rules: [],
|
|
|
|
|
|
}
|
2024-04-28 10:10:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
jsonConf: { //表单json配置,用来渲染表单
|
|
|
|
|
|
type: Array,
|
|
|
|
|
|
default: () => {
|
|
|
|
|
|
return []
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
computed: {
|
|
|
|
|
|
_value: {
|
|
|
|
|
|
get() {
|
|
|
|
|
|
return this.modelValue
|
|
|
|
|
|
},
|
|
|
|
|
|
set(val) {
|
|
|
|
|
|
emit('update:modelValue', val)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
rules() {
|
|
|
|
|
|
const formRule = {}
|
|
|
|
|
|
this.formFields.forEach(v => {
|
2024-05-08 21:13:11 +08:00
|
|
|
|
if (v.props.required && v.perm !== 'H') {
|
2024-04-28 10:10:03 +08:00
|
|
|
|
formRule[v.id] = {
|
|
|
|
|
|
rules: [{
|
|
|
|
|
|
required: true,
|
|
|
|
|
|
errorMessage: '请填写' + v.title
|
|
|
|
|
|
}]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
return formRule
|
|
|
|
|
|
},
|
|
|
|
|
|
formFields() {
|
|
|
|
|
|
const fields = []
|
|
|
|
|
|
this.jsonConf.forEach(field => this.loadInnerField(field, fields))
|
|
|
|
|
|
return fields
|
2024-05-08 21:13:11 +08:00
|
|
|
|
},
|
|
|
|
|
|
formItemMap() {
|
|
|
|
|
|
const map = new Map()
|
|
|
|
|
|
this.loadFormItemMap(this.jsonConf, map)
|
|
|
|
|
|
return map
|
2024-04-28 10:10:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
2024-05-08 21:13:11 +08:00
|
|
|
|
//缓存下原始权限设置
|
|
|
|
|
|
formPermHis: {},
|
|
|
|
|
|
compareFunc: {},
|
|
|
|
|
|
//缓存旧值
|
|
|
|
|
|
oldFormData: {},
|
|
|
|
|
|
//缓存所有用到的条件字段
|
|
|
|
|
|
conditionFields: new Set(),
|
2024-06-05 21:35:18 +08:00
|
|
|
|
execute: null,
|
|
|
|
|
|
// 特殊标识
|
|
|
|
|
|
isUse: 1
|
2024-04-28 10:10:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
onReady() {
|
|
|
|
|
|
this.$refs['wflowForm'].setRules(this.rules)
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
showItem,
|
|
|
|
|
|
loadInnerField(field, items) {
|
|
|
|
|
|
if (field.name === 'SpanLayout') {
|
|
|
|
|
|
field.props.items.forEach(f => this.loadInnerField(f, items))
|
|
|
|
|
|
} else {
|
|
|
|
|
|
items.push(field)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
validate(call) {
|
|
|
|
|
|
this.$refs['wflowForm'].validate().then(res => {
|
2024-06-14 19:30:44 +08:00
|
|
|
|
// console.log(4444444, JSON.stringify(this.modelValue))
|
2024-06-19 14:56:32 +08:00
|
|
|
|
const dataList = Object.values(this.modelValue);
|
|
|
|
|
|
const result = dataList[0] instanceof Array ? dataList[0][dataList[0].length - 1] : dataList;
|
|
|
|
|
|
// console.log(JSON.stringify(dataList[0]))
|
|
|
|
|
|
// console.log(4444444, JSON.stringify(this.formFields[this.formFields.length - 1].props.columns))
|
2024-06-18 15:43:58 +08:00
|
|
|
|
const flag = this.formFields[this.formFields.length - 1].props.columns ? this.formFields[this.formFields.length - 1].props.columns.every((v, i)=> {
|
2024-06-14 19:30:44 +08:00
|
|
|
|
if((i == this.formFields[this.formFields.length - 1].props.columns.length - 1) && result[v.id]){
|
2024-06-19 14:56:32 +08:00
|
|
|
|
// console.log(5555555, JSON.stringify(result[v.id]))
|
2024-06-14 19:30:44 +08:00
|
|
|
|
if(result[v.id][0].id){
|
|
|
|
|
|
return true
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// console.log(22222, JSON.stringify(v.props.columns))
|
|
|
|
|
|
return v.props.columns.every(e => {
|
|
|
|
|
|
// console.log(1111111, e.props.required,e.id, JSON.stringify(result[e.id]), JSON.stringify(result[v.id]))
|
|
|
|
|
|
return e.props.required == false || (e.props.required == true && result[v.id][0][e.id] != null&& result[v.id][0][e.id] != undefined);
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2024-06-19 14:56:32 +08:00
|
|
|
|
if(result instanceof Array){
|
|
|
|
|
|
// console.log(22222, v.props.required, JSON.stringify(result[result.length - 1]), v.id)
|
|
|
|
|
|
return v.props.required == false || (v.props.required == true && result[result.length - 1][0][v.id] != null && result[result.length - 1][0][v.id] != "")
|
|
|
|
|
|
}
|
|
|
|
|
|
// console.log(22222, v.props.required, JSON.stringify(result), v.id)
|
2024-06-14 19:30:44 +08:00
|
|
|
|
return v.props.required == false || (v.props.required == true && result[v.id] != null);
|
2024-06-18 15:43:58 +08:00
|
|
|
|
}) : true;
|
2024-06-19 14:56:32 +08:00
|
|
|
|
// console.log(3333333, flag)
|
2024-06-14 19:30:44 +08:00
|
|
|
|
call(flag)
|
|
|
|
|
|
console.log('表单数据信息:', JSON.stringify(res));
|
2024-04-28 10:10:03 +08:00
|
|
|
|
}).catch(err => {
|
2024-06-14 19:30:44 +08:00
|
|
|
|
call(false)
|
2024-04-28 10:10:03 +08:00
|
|
|
|
console.log('表单错误信息:', err);
|
|
|
|
|
|
})
|
2024-05-08 21:13:11 +08:00
|
|
|
|
},
|
|
|
|
|
|
loadFormItemMap(forms, map) {
|
|
|
|
|
|
forms.forEach(item => {
|
|
|
|
|
|
if (item.name === 'TableList') {
|
|
|
|
|
|
map.set(item.id, item)
|
|
|
|
|
|
this.loadFormItemMap(item.props.columns, map)
|
|
|
|
|
|
} else if (item.name === 'SpanLayout') {
|
|
|
|
|
|
this.loadFormItemMap(item.props.items, map)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
map.set(item.id, item)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
//解析表单联动规则
|
|
|
|
|
|
parserRule(cdRule) {
|
|
|
|
|
|
const condition = cdRule.condition
|
|
|
|
|
|
//在这里可以实现一个算法,按条件层级去解析,不需要解析所有条件,先不实现
|
|
|
|
|
|
if (cdRule.children.length > 0) {
|
|
|
|
|
|
for (let i = 0; i < cdRule.children.length; i++) {
|
|
|
|
|
|
const result = this.parserRule(cdRule.children[i])
|
|
|
|
|
|
if (cdRule.logic) {
|
|
|
|
|
|
//如果是且关系,有一个为假就是假
|
|
|
|
|
|
if (!result) {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
//如果是或关系,有一个为真就是真
|
|
|
|
|
|
if (result) {
|
|
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
//遍历完了返回最终结果
|
|
|
|
|
|
return cdRule.logic
|
|
|
|
|
|
} else {
|
|
|
|
|
|
//解析条件
|
|
|
|
|
|
try {
|
|
|
|
|
|
return this.compare(condition)
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
async doActions(actions) {
|
|
|
|
|
|
(actions || []).forEach(action => {
|
|
|
|
|
|
//执行预设的动作
|
|
|
|
|
|
switch (action.type) {
|
|
|
|
|
|
case 'SHOW':
|
|
|
|
|
|
action.targets.forEach(tg => this.showField(tg));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'HIDE':
|
|
|
|
|
|
action.targets.forEach(tg => this.hideField(tg));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'DISABLE':
|
|
|
|
|
|
action.targets.forEach(tg => this.disableField(tg));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'UPDATE':
|
|
|
|
|
|
action.targets.forEach(tg => this.updateField(tg, action.value));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'ENABLE':
|
|
|
|
|
|
action.targets.forEach(tg => this.enableField(tg, action.value));
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
analyseFormRule() {
|
2024-06-05 21:35:18 +08:00
|
|
|
|
// console.log("~~~~~~~~~~~~~~~~~~规则类型"+ this.config.ruleType)
|
2024-05-08 21:13:11 +08:00
|
|
|
|
if (this.config.ruleType === 'SIMPLE') {
|
|
|
|
|
|
this.analyseRules()
|
2024-05-18 20:34:50 +08:00
|
|
|
|
this.analyseJsRules()
|
2024-05-08 21:13:11 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
this.analyseJsRules()
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
async analyseJsRules() {
|
2024-06-14 11:07:45 +08:00
|
|
|
|
// if (!(this.execute instanceof Function)) {
|
|
|
|
|
|
// this.execute = new Function(`${this.config.ruleJs || 'function doChange(){}'}\r\n return doChange`)
|
|
|
|
|
|
// this.execute = this.execute()
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// this.execute = new Function(`${this.config.ruleJs || 'function doChange(){}'}\r\n return doChange`)
|
|
|
|
|
|
// this.execute = this.execute()
|
|
|
|
|
|
// }
|
|
|
|
|
|
// console.log(this._value, this.formItemMap,888999)
|
2024-05-08 21:13:11 +08:00
|
|
|
|
this.execute(this._value, this.formItemMap)
|
|
|
|
|
|
},
|
|
|
|
|
|
async analyseRules() {
|
|
|
|
|
|
(this.config.rules || []).forEach((rule, i) => {
|
|
|
|
|
|
//解析表单联动条件
|
|
|
|
|
|
const result = this.parserRule(rule.condition)
|
2024-06-05 21:35:18 +08:00
|
|
|
|
// console.log(`解析规则 ${(i + 1)}: ${result}`)
|
2024-05-08 21:13:11 +08:00
|
|
|
|
this.doActions(result ? rule.action.with : rule.action.other)
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
compare(condition) {
|
|
|
|
|
|
//要判断组件类型,再取其值
|
|
|
|
|
|
const source = this._value[condition.field]
|
|
|
|
|
|
//动态调用函数
|
|
|
|
|
|
let compareType = null
|
|
|
|
|
|
switch (condition.fieldType) {
|
|
|
|
|
|
case 'AmountInput':
|
|
|
|
|
|
case 'NumberInput':
|
|
|
|
|
|
case 'Score':
|
|
|
|
|
|
case 'CalcFormula':
|
|
|
|
|
|
compareType = 'numCompare';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'TextInput':
|
|
|
|
|
|
case 'TextareaInput':
|
|
|
|
|
|
case 'SelectInput':
|
|
|
|
|
|
case 'Location':
|
|
|
|
|
|
case 'Provinces':
|
|
|
|
|
|
compareType = 'strCompare'
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'MultipleSelect':
|
|
|
|
|
|
compareType = 'strArrCompare';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'DateTime':
|
|
|
|
|
|
compareType = 'timeCompare';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'DateTimeRange':
|
|
|
|
|
|
compareType = 'timeArrCompare';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'DeptPicker':
|
|
|
|
|
|
case 'UserPicker':
|
|
|
|
|
|
compareType = 'orgCompare';
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
return CompareFuncs[compareType][condition.compare](source,
|
|
|
|
|
|
condition.fixed ? condition.compareVal :
|
|
|
|
|
|
this._value[condition.compareVal[0]])
|
|
|
|
|
|
},
|
|
|
|
|
|
isRequired(item) {
|
|
|
|
|
|
return this.rules[item.id] !== undefined
|
|
|
|
|
|
},
|
|
|
|
|
|
hideField(id) {
|
|
|
|
|
|
const field = this.formItemMap.get(id)
|
|
|
|
|
|
if (field) {
|
|
|
|
|
|
field.perm = 'H'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
showField(id) {
|
|
|
|
|
|
const field = this.formItemMap.get(id)
|
|
|
|
|
|
if (field) {
|
|
|
|
|
|
field.perm = this.formPermHis[id] || 'E'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
disableField(id) {
|
|
|
|
|
|
const field = this.formItemMap.get(id)
|
|
|
|
|
|
if (field) {
|
|
|
|
|
|
field.perm = 'R'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
enableField(id) {
|
|
|
|
|
|
const field = this.formItemMap.get(id)
|
|
|
|
|
|
if (field) {
|
|
|
|
|
|
field.perm = 'E'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
updateField(id, val) {
|
|
|
|
|
|
const field = this.formItemMap.get(id)
|
|
|
|
|
|
if (field) {
|
|
|
|
|
|
this._value[id] = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
watch: {
|
2024-05-18 20:34:50 +08:00
|
|
|
|
config: {
|
|
|
|
|
|
deep: true,
|
|
|
|
|
|
immediate: true,
|
2024-06-05 21:35:18 +08:00
|
|
|
|
handler(newVal, oldVal) {
|
2024-06-14 11:07:45 +08:00
|
|
|
|
// console.log("~~~~~~~~~~~~config配置",JSON.stringify(this.config))
|
2024-05-18 20:34:50 +08:00
|
|
|
|
if (this.config) {
|
2024-06-14 11:07:45 +08:00
|
|
|
|
this.execute = new Function(`${this.config.ruleJs || 'function doChange(){}'}\r\n return doChange`)
|
|
|
|
|
|
this.execute = this.execute()
|
2024-05-18 20:34:50 +08:00
|
|
|
|
if (Object.keys(this.formPermHis).length === 0) {
|
|
|
|
|
|
this.formItemMap.forEach(item => {
|
|
|
|
|
|
this.formPermHis[item.id] = item.perm
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
this.analyseFormRule()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2024-05-08 21:13:11 +08:00
|
|
|
|
modelValue: {
|
|
|
|
|
|
deep: true,
|
|
|
|
|
|
immediate: true,
|
2024-06-05 21:35:18 +08:00
|
|
|
|
handler(newVal, oldVal) {
|
2024-06-14 11:07:45 +08:00
|
|
|
|
// console.log("~~~~~~~~~~~~modelValue配置",JSON.stringify(newVal))
|
|
|
|
|
|
// console.log("~~~~~~~~~~~~modelValue配置",JSON.stringify(oldVal))
|
2024-05-08 21:13:11 +08:00
|
|
|
|
if (this.config) {
|
|
|
|
|
|
if (Object.keys(this.formPermHis).length === 0) {
|
|
|
|
|
|
this.formItemMap.forEach(item => {
|
|
|
|
|
|
this.formPermHis[item.id] = item.perm
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
this.analyseFormRule()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-18 20:34:50 +08:00
|
|
|
|
},
|
2024-04-28 10:10:03 +08:00
|
|
|
|
},
|
|
|
|
|
|
emits: ['update:modelValue']
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
|
|
|
.w-form-item {
|
|
|
|
|
|
padding: 0 16rpx 32rpx 16rpx;
|
|
|
|
|
|
background-color: white;
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
font-size: 32rpx !important;
|
|
|
|
|
|
|
|
|
|
|
|
.uni-forms-item__error {
|
|
|
|
|
|
padding-top: 0 !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.uni-easyinput__content-input {
|
|
|
|
|
|
height: 30px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.w-form-title {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 13rpx 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|