mobile-workflow/components/FormRender.vue

416 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>
<w-form-item :ref="item.name == 'TableList' ? 'validateTable' : ''" @validateFn="validateFn" :type="item.name" :validateFlag="item.validateFlag" v-model="_value[item.id]" :form-props="item.props"
:readonly="item.perm !== 'E'" :formData="_value" />
</uni-forms-item>
</uni-forms>
</view>
</template>
<script>
import {
showItem
} from '@/utils/tool.js'
import WFormItem from './WFormItem.vue'
import {
CompareFuncs
} from "./form/compare/CompareOptions.js";
//import FormComponents from '@/components/form/ComponentsExport.js'
export default {
name: 'FormRender',
options: {
styleIsolation: 'shared'
},
components: {
WFormItem
},
props: {
modelValue: { //表单双向绑定的值
type: Object,
default: () => {
return {}
}
},
config: { //表单联动相关配置
type: Object,
default: () => {
return {
ruleType: "SIMPLE",
rules: [],
}
}
},
jsonConf: { //表单json配置用来渲染表单
type: Array,
default: () => {
return []
}
}
},
computed: {
_value: {
get() {
return this.modelValue
},
set(val) {
this.$forceUpdate();
emit('update:modelValue', val)
}
},
rules() {
const formRule = {}
this.formFields.forEach(v => {
if (v.props.required && v.perm !== 'H') {
formRule[v.id] = {
rules: [{
required: true,
errorMessage: '请填写' + v.title
}]
}
}
})
return formRule
},
formFields() {
const fields = []
this.jsonConf.forEach(field => this.loadInnerField(field, fields))
return fields.map((item) => {
if(item.name == 'TableList') {
item.validateFlag = null;
}
return item
})
},
formItemMap() {
const map = new Map()
this.loadFormItemMap(this.jsonConf, map)
return map
}
},
data() {
return {
//缓存下原始权限设置
formPermHis: {},
compareFunc: {},
//缓存旧值
oldFormData: {},
//缓存所有用到的条件字段
conditionFields: new Set(),
execute: null,
// 特殊标识
isUse: 1
}
},
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)
}
},
validateFn(call) {
console.log("我是表格", call)
this.validateFnUp = call;
},
validate(call) {
console.log(1111111)
if(this.validateFnUp) {
this.validateFnUp((valid) => {
if(!valid) {
call(false)
}
})
}
// this.$validateTable((res) => {
// console.log(222222, res)
// })
// this.$refs.wFormItemRef.$emit("validateTable", (res) => {
// console.log(1111111, res)
// })
// console.log(3333333, JSON.stringify(this.$refs.wFormItemRef))
// this.$refs['wFormItemRef'].validateTable((res) => {
// console.log(22222, res)
// })
this.$refs['wflowForm'].validate().then(res => {
// console.log(4444444, JSON.stringify(this.modelValue))
const dataList = Object.values(this.modelValue);
console.log(4444444, JSON.stringify(dataList))
const result = dataList[0] instanceof Array ? dataList[0][dataList[0].length - 1] : dataList;
const columns = this.formFields.filter(item => item.props.columns && item.props.columns instanceof Array);
// console.log(JSON.stringify(dataList[0]))
// console.log(4444444, JSON.stringify(columns))
const flag = columns.length > 0 ? columns[0].props.columns.every((v, i)=> {
if((i == columns[0].props.columns.length - 1) && result[v.id]){
// console.log(5555555, JSON.stringify(result[v.id]))
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
}
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)
return v.props.required == false || (v.props.required == true && result[v.id] != null);
}) : true;
console.log(3333333, flag)
call(flag)
console.log('表单数据信息:', JSON.stringify(res));
}).catch(err => {
call(false)
console.log('表单错误信息:', err);
})
},
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() {
// console.log("~~~~~~~~~~~~~~~~~~规则类型"+ this.config.ruleType)
if (this.config.ruleType === 'SIMPLE') {
this.analyseRules()
// this.analyseJsRules()
} else {
this.analyseJsRules()
}
},
async analyseJsRules() {
// console.log(this.config.ruleJs, this.execute)
// 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)
this.execute(this._value, this.formItemMap)
},
async analyseRules() {
(this.config.rules || []).forEach((rule, i) => {
//解析表单联动条件
const result = this.parserRule(rule.condition)
// console.log(`解析规则 ${(i + 1)}: ${result}`)
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':
case 'CascaderSelect':
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: {
config: {
deep: true,
immediate: true,
handler(newVal, oldVal) {
// console.log("~~~~~~~~~~~~config配置",JSON.stringify(this.config))
if (this.config) {
this.execute = new Function(`${this.config.ruleJs || 'function doChange(){}'}\r\n return doChange`)
this.execute = this.execute()
if (Object.keys(this.formPermHis).length === 0) {
this.formItemMap.forEach(item => {
this.formPermHis[item.id] = item.perm
})
}
this.analyseFormRule()
}
}
},
modelValue: {
deep: true,
immediate: true,
handler(newVal, oldVal) {
// console.log("~~~~~~~~~~~~modelValue配置",JSON.stringify(newVal))
// console.log("~~~~~~~~~~~~modelValue配置",JSON.stringify(oldVal))
if (this.config) {
if (Object.keys(this.formPermHis).length === 0) {
this.formItemMap.forEach(item => {
this.formPermHis[item.id] = item.perm
})
}
this.analyseFormRule()
}
}
},
},
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>