Merge branch 'bjxz-dev' of http://139.9.66.234:18023/kun/mobile-workflow into bjxz-dev

This commit is contained in:
kun 2024-05-08 22:23:02 +08:00
commit 83f717ec05
2 changed files with 300 additions and 4 deletions

View File

@ -21,7 +21,7 @@
<script> <script>
import { showItem } from '@/utils/tool.js' import { showItem } from '@/utils/tool.js'
import WFormItem from './WFormItem.vue' import WFormItem from './WFormItem.vue'
import { CompareFuncs } from "./form/compare/CompareOptions.js";
//import FormComponents from '@/components/form/ComponentsExport.js' //import FormComponents from '@/components/form/ComponentsExport.js'
export default { export default {
@ -38,7 +38,10 @@
config: { // config: { //
type: Object, type: Object,
default: () => { default: () => {
return {} return {
ruleType: "SIMPLE",
rules: [],
}
} }
}, },
jsonConf: { //json jsonConf: { //json
@ -60,7 +63,7 @@
rules() { rules() {
const formRule = {} const formRule = {}
this.formFields.forEach(v => { this.formFields.forEach(v => {
if (v.props.required) { if (v.props.required && v.perm !== 'H') {
formRule[v.id] = { formRule[v.id] = {
rules: [{ rules: [{
required: true, required: true,
@ -76,11 +79,23 @@
this.jsonConf.forEach(field => this.loadInnerField(field, fields)) this.jsonConf.forEach(field => this.loadInnerField(field, fields))
console.log(JSON.stringify(fields),666) console.log(JSON.stringify(fields),666)
return fields return fields
},
formItemMap() {
const map = new Map()
this.loadFormItemMap(this.jsonConf, map)
return map
} }
}, },
data() { data() {
return { return {
//
formPermHis: {},
compareFunc: {},
//
oldFormData: {},
//
conditionFields: new Set(),
execute: null
} }
}, },
onReady() { onReady() {
@ -103,6 +118,179 @@
// call(false) // call(false)
console.log('表单错误信息:', err); 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() {
if (this.config.ruleType === 'SIMPLE') {
this.analyseRules()
} else {
this.analyseJsRules()
}
},
async analyseJsRules() {
if (!(this.execute instanceof Function)) {
this.execute = new Function(`${this.config.ruleJs || 'function doChange(){}'}\r\n return doChange`)
this.execute = this.execute()
}
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':
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: {
modelValue: {
deep: true,
immediate: true,
handler() {
console.log(this.modelValue)
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'] emits: ['update:modelValue']

View File

@ -0,0 +1,108 @@
//字符串比较选项
const strCompareOptions = [
{name: '等于', symbol: 'EQ', compare: (a, b) => a == b[0]},
{name: '不等于', symbol: 'NEQ', compare: (a, b) => a != b[0]},
{name: '为其之一', symbol: 'IN', compare: (a, b) => (b || []).includes(a)},
{name: '不为其之一', symbol: 'NIN', compare: (a, b) => !(b || []).includes(a)},
{name: '含有', symbol: 'LIKE', compare: (a, b) => (b || '').includes(a)},
]
const strArrCompareOptions = [
{name: '包含', symbol: 'HS', compare: (a, b) => checkElementsExistInArray(b, a)},
{name: '不包含', symbol: 'NHS', compare: (a, b) => !checkElementsExistInArray(b, a)},
]
const numCompareOptions = [
{name: '大于', symbol: 'GT', compare: (a, b) => a > b},
{name: '小于', symbol: 'LT', compare: (a, b) => a < b},
{name: '等于', symbol: 'EQ', compare: (a, b) => a == b},
{name: '不等于', symbol: 'NEQ', compare: (a, b) => a != b},
{name: '大于等于', symbol: 'GT_EQ', compare: (a, b) => a >= b},
{name: '小于等于', symbol: 'LT_EQ', compare: (a, b) => a <= b},
{name: '在内或相等', symbol: 'IN_EQ', compare: (a, b) => a >= b[0] && a <= b[1]},
{name: '在内或不等', symbol: 'IN_NEQ', compare: (a, b) => a == b},
{name: '为其之一', symbol: 'IN', compare: (a, b) => (b || []).includes(a)},
{name: '不为其之一', symbol: 'NIN', compare: (a, b) => !(b || []).includes(a)},
]
const orgCompareOptions = [
{name: '是', symbol: 'EQ', compare: (a, b) => a[0].id == b[0].id},
{name: '不是', symbol: 'NEQ', compare: (a, b) => a[0].id != b[0].id},
{name: '为其之一', symbol: 'IN', compare: (a, b) => checkElementsExistInArray(a, b, 'id')},
{name: '含有', symbol: 'HS', compare: (a, b) => checkElementsExistInArray(b, a, 'id')},
{name: '不含有', symbol: 'NHS', compare: (a, b) => !checkElementsExistInArray(b, a, 'id')},
]
const timeCompareOptions = [
{name: '在之前', symbol: 'LT', compare: (a, b) => isBefore(a, b[0])},
{name: '在之后', symbol: 'GT', compare: (a, b) => isAfter(a, b[0])},
{name: '在其中', symbol: 'IN', compare: (a, b) => isBefore(b[0], a) && isAfter(b[1], a)},
]
const timeArrCompareOptions = [
{name: '包含', symbol: 'HS', compare: (a, b) => isBefore(a[0], b[0]) && isAfter(a[1], b[0])},
{name: '不包含', symbol: 'NHS', compare: (a, b) => isBefore(a[0], b[0]) || isAfter(b[0], a[1])},
]
function isBefore(a, b){
return new Date(a).getTime() >= new Date(a).getTime()
}
function isAfter(a, b){
return new Date(a).getTime() <= new Date(a).getTime()
}
//加载比较函数对象
function getCompareFucs(){
let cpFuncs = {
strCompare:{},
strArrCompare:{},
numCompare:{},
orgCompare:{},
timeCompare:{},
timeArrCompare:{}
}
strCompareOptions.forEach(v => cpFuncs.strCompare[v.symbol] = v.compare)
strArrCompareOptions.forEach(v => cpFuncs.strArrCompare[v.symbol] = v.compare)
numCompareOptions.forEach(v => cpFuncs.numCompare[v.symbol] = v.compare)
orgCompareOptions.forEach(v => cpFuncs.orgCompare[v.symbol] = v.compare)
timeCompareOptions.forEach(v => cpFuncs.timeCompare[v.symbol] = v.compare)
timeArrCompareOptions.forEach(v => cpFuncs.timeArrCompare[v.symbol] = v.compare)
return cpFuncs
}
//校验数组A是否包含在B内
export function checkElementsExistInArray(A, B, key) {
if (A.length === 0 || B.length === 0){
return false
}
for (let i = 0; i < A.length; i++) {
let found = false;
for (let j = 0; j < B.length; j++) {
if (key){
if (A[i][key] == B[j][key]) {
found = true;
break;
}
}else {
if (A[i] == B[j]) {
found = true;
break;
}
}
}
if (!found) {
return false;
}
}
return true;
}
export const CompareFuncs = getCompareFucs()
export default {
strCompareOptions, strArrCompareOptions,
numCompareOptions, orgCompareOptions,
timeCompareOptions, timeArrCompareOptions
}