perl:代码优化 (#139)
This commit is contained in:
parent
990126f976
commit
c714f13905
7
web/components.d.ts
vendored
7
web/components.d.ts
vendored
@ -12,12 +12,10 @@ declare module 'vue' {
|
|||||||
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
||||||
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
||||||
ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
|
ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
|
||||||
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
|
|
||||||
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
ElForm: typeof import('element-plus/es')['ElForm']
|
ElForm: typeof import('element-plus/es')['ElForm']
|
||||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
|
||||||
ElIconCheck: typeof import('@element-plus/icons-vue')['Check']
|
ElIconCheck: typeof import('@element-plus/icons-vue')['Check']
|
||||||
ElIconLoading: typeof import('@element-plus/icons-vue')['Loading']
|
ElIconLoading: typeof import('@element-plus/icons-vue')['Loading']
|
||||||
ElInput: typeof import('element-plus/es')['ElInput']
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
@ -28,6 +26,7 @@ declare module 'vue' {
|
|||||||
ElRadio: typeof import('element-plus/es')['ElRadio']
|
ElRadio: typeof import('element-plus/es')['ElRadio']
|
||||||
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
|
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
|
||||||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
||||||
|
ElRow: typeof import('element-plus/es')['ElRow']
|
||||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||||
ElSlider: typeof import('element-plus/es')['ElSlider']
|
ElSlider: typeof import('element-plus/es')['ElSlider']
|
||||||
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
||||||
@ -38,9 +37,6 @@ declare module 'vue' {
|
|||||||
ElTag: typeof import('element-plus/es')['ElTag']
|
ElTag: typeof import('element-plus/es')['ElTag']
|
||||||
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
|
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
|
||||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||||
'IEp-[]': typeof import('~icons/ep/[]')['default']
|
|
||||||
'IEp-[test]': typeof import('~icons/ep/[test]')['default']
|
|
||||||
'IEp-]': typeof import('~icons/ep/]')['default']
|
|
||||||
IEpBottom: typeof import('~icons/ep/bottom')['default']
|
IEpBottom: typeof import('~icons/ep/bottom')['default']
|
||||||
IEpCheck: typeof import('~icons/ep/check')['default']
|
IEpCheck: typeof import('~icons/ep/check')['default']
|
||||||
IEpCirclePlus: typeof import('~icons/ep/circle-plus')['default']
|
IEpCirclePlus: typeof import('~icons/ep/circle-plus')['default']
|
||||||
@ -64,6 +60,5 @@ declare module 'vue' {
|
|||||||
}
|
}
|
||||||
export interface ComponentCustomProperties {
|
export interface ComponentCustomProperties {
|
||||||
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
|
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
|
||||||
vPopover: typeof import('element-plus/es')['ElPopoverDirective']
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,28 @@
|
|||||||
export type BasicOperator = 'in' | 'eq' | 'neq' | 'nin' | 'gt';
|
/**
|
||||||
// in:包含, 选择了,任一
|
* in:包含, 选择了,任一
|
||||||
// eq: 等于,选择了,全部
|
* eq: 等于,选择了,全部
|
||||||
// nin: 不包含,不选择,任一
|
* nin: 不包含,不选择,任一
|
||||||
// neq:不等于,不选择,全部,可以实现“填写了”
|
* neq:不等于,不选择,全部,可以实现“填写了”
|
||||||
|
*/
|
||||||
|
export enum Operator {
|
||||||
|
Include = 'in',
|
||||||
|
Equal = 'eq',
|
||||||
|
NotEqual = 'neq',
|
||||||
|
NotInclude = 'nin',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export enum PrefixID {
|
||||||
|
Rule = 'r',
|
||||||
|
Condition = 'c'
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Scope {
|
||||||
|
Question = 'question',
|
||||||
|
Option = 'option'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export type FieldTypes = string | string[];
|
export type FieldTypes = string | string[];
|
||||||
|
|
||||||
// 定义事实对象类型
|
// 定义事实对象类型
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
import * as yup from 'yup'
|
import * as yup from 'yup'
|
||||||
import { type BasicOperator, type FieldTypes } from './BasicType'
|
import { type FieldTypes, PrefixID, Operator, Scope } from './BasicType'
|
||||||
|
|
||||||
export function generateID(prefix = 'r') {
|
export function generateID(prefix = PrefixID.Rule) {
|
||||||
return `${prefix}-${nanoid(5)}`
|
return `${prefix}-${nanoid(5)}`
|
||||||
}
|
}
|
||||||
// 定义条件规则类
|
// 定义条件规则类
|
||||||
export class ConditionNode {
|
export class ConditionNode {
|
||||||
id: string = '';
|
id: string = '';
|
||||||
public field: string = '';
|
public field: string = '';
|
||||||
public operator: BasicOperator = 'in';
|
public operator: Operator = Operator.Include;
|
||||||
public value: FieldTypes = []
|
public value: FieldTypes = []
|
||||||
constructor(field: string = '', operator: BasicOperator = 'in', value: FieldTypes = []) {
|
constructor(field: string = '', operator: Operator = Operator.Include, value: FieldTypes = []) {
|
||||||
this.field = field;
|
this.field = field;
|
||||||
this.operator = operator;
|
this.operator = operator;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.id = generateID('c')
|
this.id = generateID(PrefixID.Condition)
|
||||||
}
|
}
|
||||||
setField(field: string) {
|
setField(field: string) {
|
||||||
this.field = field;
|
this.field = field;
|
||||||
}
|
}
|
||||||
setOperator(operator: BasicOperator) {
|
setOperator(operator: Operator) {
|
||||||
this.operator = operator;
|
this.operator = operator;
|
||||||
}
|
}
|
||||||
setValue(value: FieldTypes) {
|
setValue(value: FieldTypes) {
|
||||||
@ -31,10 +31,10 @@ export class ConditionNode {
|
|||||||
export class RuleNode {
|
export class RuleNode {
|
||||||
id: string = '';
|
id: string = '';
|
||||||
conditions: ConditionNode[] = []
|
conditions: ConditionNode[] = []
|
||||||
scope: string = 'question'
|
scope: string = Scope.Question
|
||||||
target: string = ''
|
target: string = ''
|
||||||
constructor(scope:string = 'question', target: string = '') {
|
constructor(scope:string = Scope.Question, target: string = '') {
|
||||||
this.id = generateID('r')
|
this.id = generateID(PrefixID.Rule)
|
||||||
this.scope = scope
|
this.scope = scope
|
||||||
this.target = target
|
this.target = target
|
||||||
}
|
}
|
||||||
@ -54,8 +54,14 @@ export class RuleNode {
|
|||||||
|
|
||||||
export class RuleBuild {
|
export class RuleBuild {
|
||||||
rules: RuleNode[] = [];
|
rules: RuleNode[] = [];
|
||||||
|
static instance: RuleBuild;
|
||||||
constructor() {
|
constructor() {
|
||||||
this.rules = [];
|
this.rules = [];
|
||||||
|
if (!RuleBuild.instance) {
|
||||||
|
RuleBuild.instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RuleBuild.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加条件规则到规则引擎中
|
// 添加条件规则到规则引擎中
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
import { type BasicOperator, type FieldTypes, type Fact } from "./BasicType";
|
import { Operator, type FieldTypes, type Fact } from "./BasicType";
|
||||||
|
|
||||||
// 定义条件规则类
|
// 定义条件规则类
|
||||||
export class ConditionNode<F extends string, O extends BasicOperator> {
|
export class ConditionNode<F extends string, O extends Operator> {
|
||||||
// 默认显示
|
// 默认显示
|
||||||
public result: boolean = false;
|
public result: boolean = false;
|
||||||
constructor(public field: F, public operator: O, public value: FieldTypes) {
|
constructor(public field: F, public operator: O, public value: FieldTypes) {
|
||||||
@ -22,7 +22,7 @@ export class ConditionNode<F extends string, O extends BasicOperator> {
|
|||||||
return this.result
|
return this.result
|
||||||
}
|
}
|
||||||
switch (this.operator) {
|
switch (this.operator) {
|
||||||
case 'eq':
|
case Operator.Equal:
|
||||||
if(this.value instanceof Array) {
|
if(this.value instanceof Array) {
|
||||||
this.result = this.value.every(v => facts[this.field].includes(v))
|
this.result = this.value.every(v => facts[this.field].includes(v))
|
||||||
return this.result
|
return this.result
|
||||||
@ -30,7 +30,7 @@ export class ConditionNode<F extends string, O extends BasicOperator> {
|
|||||||
this.result = facts[this.field].includes(this.value);
|
this.result = facts[this.field].includes(this.value);
|
||||||
return this.result
|
return this.result
|
||||||
}
|
}
|
||||||
case 'in':
|
case Operator.Include:
|
||||||
if(this.value instanceof Array) {
|
if(this.value instanceof Array) {
|
||||||
this.result = this.value.some(v => facts[this.field].includes(v))
|
this.result = this.value.some(v => facts[this.field].includes(v))
|
||||||
return this.result
|
return this.result
|
||||||
@ -38,7 +38,7 @@ export class ConditionNode<F extends string, O extends BasicOperator> {
|
|||||||
this.result = facts[this.field].includes(this.value);
|
this.result = facts[this.field].includes(this.value);
|
||||||
return this.result
|
return this.result
|
||||||
}
|
}
|
||||||
case 'nin':
|
case Operator.NotInclude:
|
||||||
if(this.value instanceof Array) {
|
if(this.value instanceof Array) {
|
||||||
this.result = this.value.some(v => !facts[this.field].includes(v))
|
this.result = this.value.some(v => !facts[this.field].includes(v))
|
||||||
return this.result
|
return this.result
|
||||||
@ -46,7 +46,7 @@ export class ConditionNode<F extends string, O extends BasicOperator> {
|
|||||||
this.result = facts[this.field].includes(this.value);
|
this.result = facts[this.field].includes(this.value);
|
||||||
return this.result
|
return this.result
|
||||||
}
|
}
|
||||||
case 'neq':
|
case Operator.NotEqual:
|
||||||
if(this.value instanceof Array) {
|
if(this.value instanceof Array) {
|
||||||
this.result = this.value.every(v => !facts[this.field].includes(v))
|
this.result = this.value.every(v => !facts[this.field].includes(v))
|
||||||
return this.result
|
return this.result
|
||||||
@ -67,13 +67,13 @@ export class ConditionNode<F extends string, O extends BasicOperator> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class RuleNode {
|
export class RuleNode {
|
||||||
conditions: Map<string, ConditionNode<string, BasicOperator>>; // 使用哈希表存储条件规则对象
|
conditions: Map<string, ConditionNode<string, Operator>>; // 使用哈希表存储条件规则对象
|
||||||
public result: boolean = false;
|
public result: boolean = false;
|
||||||
constructor(public target: string, public scope: string) {
|
constructor(public target: string, public scope: string) {
|
||||||
this.conditions = new Map();
|
this.conditions = new Map();
|
||||||
}
|
}
|
||||||
// 添加条件规则到规则引擎中
|
// 添加条件规则到规则引擎中
|
||||||
addCondition(condition: ConditionNode<string, BasicOperator>) {
|
addCondition(condition: ConditionNode<string, Operator>) {
|
||||||
const hash = condition.calculateHash();
|
const hash = condition.calculateHash();
|
||||||
this.conditions.set(hash, condition);
|
this.conditions.set(hash, condition);
|
||||||
}
|
}
|
||||||
@ -118,8 +118,16 @@ export class RuleNode {
|
|||||||
|
|
||||||
export class RuleMatch {
|
export class RuleMatch {
|
||||||
rules: Map<string, RuleNode>;
|
rules: Map<string, RuleNode>;
|
||||||
constructor(ruleConf: any) {
|
static instance: any;
|
||||||
|
constructor() {
|
||||||
this.rules = new Map();
|
this.rules = new Map();
|
||||||
|
if (!RuleMatch.instance) {
|
||||||
|
RuleMatch.instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RuleMatch.instance;
|
||||||
|
}
|
||||||
|
fromJson(ruleConf:any) {
|
||||||
if(ruleConf instanceof Array) {
|
if(ruleConf instanceof Array) {
|
||||||
ruleConf.forEach((rule: any) => {
|
ruleConf.forEach((rule: any) => {
|
||||||
const ruleNode = new RuleNode(rule.target, rule.scope);
|
const ruleNode = new RuleNode(rule.target, rule.scope);
|
||||||
@ -130,7 +138,6 @@ export class RuleMatch {
|
|||||||
this.addRule(ruleNode)
|
this.addRule(ruleNode)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加条件规则到规则引擎中
|
// 添加条件规则到规则引擎中
|
||||||
@ -138,7 +145,7 @@ export class RuleMatch {
|
|||||||
const hash = rule.calculateHash();
|
const hash = rule.calculateHash();
|
||||||
if (this.rules.has(hash)) {
|
if (this.rules.has(hash)) {
|
||||||
const existRule: any = this.rules.get(hash);
|
const existRule: any = this.rules.get(hash);
|
||||||
existRule.conditions.forEach((item: ConditionNode<string, BasicOperator>) => {
|
existRule.conditions.forEach((item: ConditionNode<string, Operator>) => {
|
||||||
rule.addCondition(item)
|
rule.addCondition(item)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
23
web/src/management/hooks/useQuestionInfo.js
Normal file
23
web/src/management/hooks/useQuestionInfo.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { computed } from 'vue';
|
||||||
|
import store from '@/management/store'
|
||||||
|
import { cleanRichText } from '@/common/xss'
|
||||||
|
export const useQuestionInfo = (field) => {
|
||||||
|
const getQuestionTitle = computed(() => {
|
||||||
|
const questionDataList = store.state.edit.schema.questionDataList
|
||||||
|
return () => {
|
||||||
|
return questionDataList.find((item) => item.field === field)?.title
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const getOptionTitle = computed(() => {
|
||||||
|
const questionDataList = store.state.edit.schema.questionDataList
|
||||||
|
return (value) => {
|
||||||
|
const options = questionDataList.find((item) => item.field === field)?.options || []
|
||||||
|
if(value instanceof Array) {
|
||||||
|
return options.filter((item) => value.includes(item.hash)).map((item) => cleanRichText(item.text))
|
||||||
|
} else {
|
||||||
|
return options.filter((item) => item.hash === value).map((item) => cleanRichText(item.text))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return { getQuestionTitle, getOptionTitle }
|
||||||
|
}
|
@ -1,23 +0,0 @@
|
|||||||
import { computed } from 'vue';
|
|
||||||
import store from '@/management/store'
|
|
||||||
import { cleanRichText } from '@/common/xss'
|
|
||||||
export const useQuestionInfo = (field: string) => {
|
|
||||||
const getQuestionTitle = computed(() => {
|
|
||||||
const questionDataList = store.state.edit.schema.questionDataList
|
|
||||||
return () => {
|
|
||||||
return questionDataList.find((item: any) => item.field === field)?.title
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const getOptionTitle = computed(() => {
|
|
||||||
const questionDataList = store.state.edit.schema.questionDataList
|
|
||||||
return (value: string | Array<string>) => {
|
|
||||||
const options = questionDataList.find((item: any) => item.field === field)?.options || []
|
|
||||||
if(value instanceof Array) {
|
|
||||||
return options.filter((item: any) => value.includes(item.hash)).map((item: any) => cleanRichText(item.text))
|
|
||||||
} else {
|
|
||||||
return options.filter((item: any) => item.hash === value).map((item: any) => cleanRichText(item.text))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return { getQuestionTitle, getOptionTitle }
|
|
||||||
}
|
|
7
web/src/management/hooks/useShowLogicEngine.js
Normal file
7
web/src/management/hooks/useShowLogicEngine.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
import { RuleBuild } from '@/common/logicEngine/RuleBuild'
|
||||||
|
|
||||||
|
export const showLogicEngine = ref()
|
||||||
|
export const initShowLogicEngine = (ruleConf) => {
|
||||||
|
showLogicEngine.value = new RuleBuild().fromJson(ruleConf)
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
import { computed, unref } from 'vue';
|
import { computed, unref } from 'vue';
|
||||||
import { useQuestionInfo } from './useQuestionInfo'
|
import { useQuestionInfo } from './useQuestionInfo'
|
||||||
import { flatten } from 'lodash-es'
|
import { flatten } from 'lodash-es'
|
||||||
import store from '@/management/store'
|
|
||||||
import { cleanRichText } from '@/common/xss'
|
import { cleanRichText } from '@/common/xss'
|
||||||
|
import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||||
|
|
||||||
// 目标题的显示逻辑提示文案
|
// 目标题的显示逻辑提示文案
|
||||||
export const useShowLogicInfo = (field: string) => {
|
export const useShowLogicInfo = (field) => {
|
||||||
const hasShowLogic = computed(() => {
|
const hasShowLogic = computed(() => {
|
||||||
const logicEngine = store.state.logic.showLogicEngine
|
const logicEngine = showLogicEngine.value
|
||||||
// 判断该题是否作为了显示逻辑前置题
|
// 判断该题是否作为了显示逻辑前置题
|
||||||
const isField = logicEngine?.findTargetsByFields(field)?.length > 0
|
const isField = logicEngine?.findTargetsByFields(field)?.length > 0
|
||||||
// 判断该题是否作为了显示逻辑目标题
|
// 判断该题是否作为了显示逻辑目标题
|
||||||
@ -15,11 +15,11 @@ export const useShowLogicInfo = (field: string) => {
|
|||||||
return isField || isTarget
|
return isField || isTarget
|
||||||
})
|
})
|
||||||
const getShowLogicText = computed(() => {
|
const getShowLogicText = computed(() => {
|
||||||
const logicEngine = store.state.logic.showLogicEngine
|
const logicEngine = showLogicEngine.value
|
||||||
// 获取目标题的规则
|
// 获取目标题的规则
|
||||||
const rules = logicEngine?.findConditionByTarget(field) || []
|
const rules = logicEngine?.findConditionByTarget(field) || []
|
||||||
|
|
||||||
const conditions = flatten(rules).map((item:any) => {
|
const conditions = flatten(rules).map((item) => {
|
||||||
const { getQuestionTitle, getOptionTitle } = useQuestionInfo(item.field)
|
const { getQuestionTitle, getOptionTitle } = useQuestionInfo(item.field)
|
||||||
return `<span>【 ${cleanRichText(getQuestionTitle.value())}】 选择了 【${getOptionTitle.value(unref(item.value)).join('、')}】</span> <br/>`
|
return `<span>【 ${cleanRichText(getQuestionTitle.value())}】 选择了 【${getOptionTitle.value(unref(item.value)).join('、')}】</span> <br/>`
|
||||||
})
|
})
|
@ -115,7 +115,6 @@ const onMoveDown = () => {
|
|||||||
isHover.value = false
|
isHover.value = false
|
||||||
}
|
}
|
||||||
const onDelete = async () => {
|
const onDelete = async () => {
|
||||||
// const target = store.state.logic.showLogicEngine.findTargetsByFields(props.moduleConfig.field)
|
|
||||||
if(unref(hasShowLogic)) {
|
if(unref(hasShowLogic)) {
|
||||||
ElMessageBox.alert('该问题被逻辑依赖,请先删除逻辑依赖', '提示', {
|
ElMessageBox.alert('该问题被逻辑依赖,请先删除逻辑依赖', '提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
|
@ -22,7 +22,7 @@ import LeftMenu from '@/management/components/LeftMenu.vue'
|
|||||||
|
|
||||||
import CommonTemplate from './components/CommonTemplate.vue'
|
import CommonTemplate from './components/CommonTemplate.vue'
|
||||||
import Navbar from './components/ModuleNavbar.vue'
|
import Navbar from './components/ModuleNavbar.vue'
|
||||||
|
import { initShowLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||||
export default {
|
export default {
|
||||||
name: 'questionEditPage',
|
name: 'questionEditPage',
|
||||||
components: {
|
components: {
|
||||||
@ -34,7 +34,8 @@ export default {
|
|||||||
this.$store.commit('edit/setSurveyId', this.$route.params.id)
|
this.$store.commit('edit/setSurveyId', this.$route.params.id)
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch('edit/init')
|
await this.$store.dispatch('edit/init')
|
||||||
await this.$store.dispatch('logic/initShowLogic', this.$store.state.edit.schema.logicConf.showLogicConf || {})
|
// await this.$store.dispatch('logic/initShowLogic', this.$store.state.edit.schema.logicConf.showLogicConf || {})
|
||||||
|
await initShowLogicEngine(this.$store.state.edit.schema.logicConf.showLogicConf || {})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ElMessage.error(error.message)
|
ElMessage.error(error.message)
|
||||||
// 自动跳转回列表页
|
// 自动跳转回列表页
|
||||||
|
@ -5,14 +5,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { get as _get } from 'lodash-es'
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message.scss'
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
|
||||||
import { get as _get } from 'lodash-es'
|
|
||||||
|
|
||||||
import { publishSurvey, saveSurvey } from '@/management/api/survey'
|
import { publishSurvey, saveSurvey } from '@/management/api/survey'
|
||||||
|
import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||||
import buildData from './buildData'
|
import buildData from './buildData'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -68,15 +66,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateLogicConf() {
|
updateLogicConf() {
|
||||||
if(this.$store.state.logic.showLogicEngine) {
|
if(showLogicEngine.value) {
|
||||||
try {
|
try {
|
||||||
this.$store.state.logic.showLogicEngine.validateSchema()
|
showLogicEngine.value.validateSchema()
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const showLogicConf = this.$store.state.logic.showLogicEngine.toJson()
|
const showLogicConf = showLogicEngine.value.toJson()
|
||||||
// 更新逻辑配置
|
// 更新逻辑配置
|
||||||
this.$store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
this.$store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import 'element-plus/theme-chalk/src/message.scss'
|
|||||||
|
|
||||||
import { saveSurvey } from '@/management/api/survey'
|
import { saveSurvey } from '@/management/api/survey'
|
||||||
import buildData from './buildData'
|
import buildData from './buildData'
|
||||||
|
import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {},
|
components: {},
|
||||||
@ -89,14 +90,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateLogicConf() {
|
updateLogicConf() {
|
||||||
if(this.$store.state.logic.showLogicEngine) {
|
if(showLogicEngine.value) {
|
||||||
try {
|
try {
|
||||||
this.$store.state.logic.showLogicEngine.validateSchema()
|
showLogicEngine.value.validateSchema()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const showLogicConf = this.$store.state.logic.showLogicEngine.toJson()
|
const showLogicConf = showLogicEngine.value.toJson()
|
||||||
// 更新逻辑配置
|
// 更新逻辑配置
|
||||||
this.$store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
this.$store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
||||||
}
|
}
|
||||||
|
@ -20,25 +20,22 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { shallowRef, computed } from 'vue'
|
import { shallowRef, computed } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { RuleNode, ConditionNode } from '@/common/logicEngine/RuleBuild'
|
||||||
|
import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||||
import RuleNodeView from './components/RuleNodeView.vue'
|
import RuleNodeView from './components/RuleNodeView.vue'
|
||||||
|
|
||||||
import { RuleNode, ConditionNode } from '@/common/logicEngine/RuleBuild'
|
|
||||||
|
|
||||||
const store = useStore()
|
|
||||||
|
|
||||||
const list = computed(() => {
|
const list = computed(() => {
|
||||||
return store.state.logic.showLogicEngine?.rules || []
|
return showLogicEngine.value?.rules || []
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
const condition = new ConditionNode()
|
const condition = new ConditionNode()
|
||||||
const ruleNode = new RuleNode()
|
const ruleNode = new RuleNode()
|
||||||
ruleNode.addCondition(condition)
|
ruleNode.addCondition(condition)
|
||||||
store.state.logic.showLogicEngine.addRule(ruleNode)
|
showLogicEngine.value.addRule(ruleNode)
|
||||||
}
|
}
|
||||||
const handleDetele = (id: string) => {
|
const handleDetele = (id: string) => {
|
||||||
store.state.logic.showLogicEngine.removeRule(id)
|
showLogicEngine.value.removeRule(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ruleWrappers = shallowRef([])
|
const ruleWrappers = shallowRef([])
|
||||||
|
@ -7,14 +7,14 @@
|
|||||||
:inline="true"
|
:inline="true"
|
||||||
:model="ruleNode"
|
:model="ruleNode"
|
||||||
>
|
>
|
||||||
<conditionView
|
<ConditionView
|
||||||
v-for="(conditionNode, index) in ruleNode.conditions"
|
v-for="(conditionNode, index) in ruleNode.conditions"
|
||||||
:key="conditionNode.id"
|
:key="conditionNode.id"
|
||||||
:index="index"
|
:index="index"
|
||||||
:ruleNode="ruleNode"
|
:ruleNode="ruleNode"
|
||||||
:conditionNode="conditionNode"
|
:conditionNode="conditionNode"
|
||||||
@delete="handleDeleteCondition"
|
@delete="handleDeleteCondition"
|
||||||
></conditionView>
|
></ConditionView>
|
||||||
<div class="target-wrapper">
|
<div class="target-wrapper">
|
||||||
<div class="line">
|
<div class="line">
|
||||||
<span class="desc">则显示</span>
|
<span class="desc">则显示</span>
|
||||||
@ -46,18 +46,14 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, shallowRef, inject, type ComputedRef } from 'vue'
|
import { ref, computed, shallowRef, inject, type ComputedRef } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
|
||||||
import { ElMessageBox } from 'element-plus'
|
import { ElMessageBox } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message-box.scss'
|
import 'element-plus/theme-chalk/src/message-box.scss'
|
||||||
|
|
||||||
import { RuleNode } from '@/common/logicEngine/RuleBuild'
|
import { RuleNode } from '@/common/logicEngine/RuleBuild'
|
||||||
import { cleanRichText } from '@/common/xss'
|
import { cleanRichText } from '@/common/xss'
|
||||||
|
import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||||
|
import ConditionView from './ConditionView.vue'
|
||||||
|
|
||||||
import conditionView from './ConditionView.vue'
|
|
||||||
|
|
||||||
const store = useStore()
|
|
||||||
const renderData = inject<ComputedRef<Array<any>>>('renderData') || ref([])
|
const renderData = inject<ComputedRef<Array<any>>>('renderData') || ref([])
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -107,7 +103,7 @@ const targetQuestionList = computed(() => {
|
|||||||
return {
|
return {
|
||||||
label: `${item.showIndex ? item.indexNumber + '.' : ''} ${cleanRichText(item.title)}`,
|
label: `${item.showIndex ? item.indexNumber + '.' : ''} ${cleanRichText(item.title)}`,
|
||||||
value: item.field,
|
value: item.field,
|
||||||
disabled: store.state.logic.showLogicEngine
|
disabled: showLogicEngine.value
|
||||||
.findTargetsByScope('question')
|
.findTargetsByScope('question')
|
||||||
.includes(item.field)
|
.includes(item.field)
|
||||||
}
|
}
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
<template>
|
|
||||||
<commonTemplate>
|
|
||||||
<template #left>
|
|
||||||
<CatalogPanel></CatalogPanel>
|
|
||||||
</template>
|
|
||||||
<template #center>
|
|
||||||
<PreviewPanel></PreviewPanel>
|
|
||||||
</template>
|
|
||||||
<template #right>
|
|
||||||
<SetterPanel></SetterPanel>
|
|
||||||
</template>
|
|
||||||
</commonTemplate>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import commonTemplate from '../components/CommonTemplate.vue'
|
|
||||||
import CatalogPanel from '../modules/questionModule/CatalogPanel.vue'
|
|
||||||
import PreviewPanel from '../modules/questionModule/PreviewPanel.vue'
|
|
||||||
import SetterPanel from '../modules/questionModule/SetterPanel.vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'EditPage',
|
|
||||||
components: {
|
|
||||||
commonTemplate,
|
|
||||||
CatalogPanel,
|
|
||||||
PreviewPanel,
|
|
||||||
SetterPanel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.navbar {
|
|
||||||
border-bottom: 1px solid #e7e9eb;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="logic-wrapper">
|
<div class="logic-wrapper">
|
||||||
<RuleListView></RuleListView>
|
<RulePanel></RulePanel>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, provide } from 'vue'
|
import { computed, provide } from 'vue'
|
||||||
import RuleListView from '../../modules/logicModule/RulePanel.vue'
|
import RulePanel from '../../modules/logicModule/RulePanel.vue'
|
||||||
import { filterQuestionPreviewData } from '@/management/utils/index'
|
import { filterQuestionPreviewData } from '@/management/utils/index'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
<template>
|
<template>
|
||||||
<commonTemplate>
|
<CommonTemplate>
|
||||||
<template #left>
|
<template #left>
|
||||||
<catalogPanel />
|
<CatalogPanel />
|
||||||
</template>
|
</template>
|
||||||
<template #center>
|
<template #center>
|
||||||
<previewPanel />
|
<PreviewPanel />
|
||||||
</template>
|
</template>
|
||||||
<template #right>
|
<template #right>
|
||||||
<setterPanel />
|
<SetterPanel />
|
||||||
</template>
|
</template>
|
||||||
</commonTemplate>
|
</CommonTemplate>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import commonTemplate from '../../components/CommonTemplate.vue';
|
import CommonTemplate from '../../components/CommonTemplate.vue';
|
||||||
import catalogPanel from '../../modules/questionModule/CatalogPanel.vue';
|
import CatalogPanel from '../../modules/questionModule/CatalogPanel.vue';
|
||||||
import previewPanel from '../../modules/questionModule/PreviewPanel.vue';
|
import PreviewPanel from '../../modules/questionModule/PreviewPanel.vue';
|
||||||
import setterPanel from '../../modules/questionModule/SetterPanel.vue';
|
import SetterPanel from '../../modules/questionModule/SetterPanel.vue';
|
||||||
export default {
|
export default {
|
||||||
name: 'editInde1111x',
|
name: 'editIndex',
|
||||||
components: {
|
components: {
|
||||||
commonTemplate,
|
CommonTemplate,
|
||||||
catalogPanel,
|
CatalogPanel,
|
||||||
previewPanel,
|
PreviewPanel,
|
||||||
setterPanel,
|
SetterPanel,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import SettingPanel from '../modules/settingModule/SettingPanel.vue'
|
import SettingPanel from '../../modules/settingModule/SettingPanel'
|
||||||
export default {
|
export default {
|
||||||
name: 'SettingPage',
|
name: 'SettingPage',
|
||||||
components: {
|
components: {
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<commonTemplate>
|
<CommonTemplate>
|
||||||
<template #left>
|
<template #left>
|
||||||
<CatalogPanel />
|
<CatalogPanel />
|
||||||
</template>
|
</template>
|
||||||
@ -9,10 +9,10 @@
|
|||||||
<template #right>
|
<template #right>
|
||||||
<SetterPanel />
|
<SetterPanel />
|
||||||
</template>
|
</template>
|
||||||
</commonTemplate>
|
</CommonTemplate>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import commonTemplate from '../../components/CommonTemplate.vue'
|
import CommonTemplate from '../../components/CommonTemplate.vue'
|
||||||
import CatalogPanel from '../../modules/settingModule/skin/CatalogPanel.vue'
|
import CatalogPanel from '../../modules/settingModule/skin/CatalogPanel.vue'
|
||||||
import PreviewPanel from '../../modules/settingModule/skin/PreviewPanel.vue'
|
import PreviewPanel from '../../modules/settingModule/skin/PreviewPanel.vue'
|
||||||
import SetterPanel from '../../modules/settingModule/skin/SetterPanel.vue'
|
import SetterPanel from '../../modules/settingModule/skin/SetterPanel.vue'
|
||||||
@ -20,7 +20,7 @@ import SetterPanel from '../../modules/settingModule/skin/SetterPanel.vue'
|
|||||||
export default {
|
export default {
|
||||||
name: 'ContentPage',
|
name: 'ContentPage',
|
||||||
components: {
|
components: {
|
||||||
commonTemplate,
|
CommonTemplate,
|
||||||
CatalogPanel,
|
CatalogPanel,
|
||||||
PreviewPanel,
|
PreviewPanel,
|
||||||
SetterPanel
|
SetterPanel
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<commonTemplate>
|
<CommonTemplate>
|
||||||
<template #left>
|
<template #left>
|
||||||
<ResultCatalog />
|
<ResultCatalog />
|
||||||
</template>
|
</template>
|
||||||
@ -9,11 +9,11 @@
|
|||||||
<template #right>
|
<template #right>
|
||||||
<ResultSetter />
|
<ResultSetter />
|
||||||
</template>
|
</template>
|
||||||
</commonTemplate>
|
</CommonTemplate>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import commonTemplate from '../../components/CommonTemplate.vue'
|
import CommonTemplate from '../../components/CommonTemplate.vue'
|
||||||
import ResultCatalog from '../../modules/settingModule/result/CatalogPanel.vue'
|
import ResultCatalog from '../../modules/settingModule/result/CatalogPanel.vue'
|
||||||
import ResultPreview from '../../modules/settingModule/result/PreviewPanel.vue'
|
import ResultPreview from '../../modules/settingModule/result/PreviewPanel.vue'
|
||||||
import ResultSetter from '../../modules/settingModule/result/SetterPanel.vue'
|
import ResultSetter from '../../modules/settingModule/result/SetterPanel.vue'
|
||||||
@ -21,7 +21,7 @@ import ResultSetter from '../../modules/settingModule/result/SetterPanel.vue'
|
|||||||
export default {
|
export default {
|
||||||
name: 'ResultPage',
|
name: 'ResultPage',
|
||||||
components: {
|
components: {
|
||||||
commonTemplate,
|
CommonTemplate,
|
||||||
ResultCatalog,
|
ResultCatalog,
|
||||||
ResultPreview,
|
ResultPreview,
|
||||||
ResultSetter
|
ResultSetter
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export const type = {
|
export const type = {
|
||||||
normal: '调查问卷',
|
normal: '基础调查',
|
||||||
vote: '投票评选',
|
vote: '投票评选',
|
||||||
nps: 'NPS评分',
|
nps: 'NPS评分',
|
||||||
register: '在线报名'
|
register: '在线报名'
|
||||||
|
@ -59,7 +59,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
meta: {
|
meta: {
|
||||||
needLogin: true
|
needLogin: true
|
||||||
},
|
},
|
||||||
component: () => import('../pages/edit/pages/SettingPage.vue')
|
component: () => import('../pages/edit/pages/setting/index.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'skin',
|
path: 'skin',
|
||||||
@ -118,7 +118,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
name: 'login',
|
name: 'login',
|
||||||
component: () => import('../pages/login/LoginPage.vue'),
|
component: () => import('../pages/login/LoginPage.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '登陆'
|
title: '登录'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { getBannerData } from '@/management/api/skin.js'
|
import { getBannerData } from '@/management/api/skin.js'
|
||||||
import { RuleBuild } from '@/common/logicEngine/RuleBuild'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async getBannerData({ state, commit }) {
|
async getBannerData({ state, commit }) {
|
||||||
@ -10,9 +9,5 @@ export default {
|
|||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
commit('setBannerList', res.data)
|
commit('setBannerList', res.data)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
initShowLogic({ commit }, ruleConf) {
|
|
||||||
const showLogicEngine = new RuleBuild(ruleConf)
|
|
||||||
commit('setShowLogicEngine', showLogicEngine)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { createStore } from 'vuex'
|
import { createStore } from 'vuex'
|
||||||
import edit from './edit'
|
import edit from './edit'
|
||||||
import user from './user'
|
import user from './user'
|
||||||
import logic from './logic'
|
|
||||||
|
|
||||||
import actions from './actions'
|
import actions from './actions'
|
||||||
import mutations from './mutations'
|
import mutations from './mutations'
|
||||||
@ -14,7 +13,6 @@ export default createStore({
|
|||||||
actions,
|
actions,
|
||||||
modules: {
|
modules: {
|
||||||
edit,
|
edit,
|
||||||
user,
|
user
|
||||||
logic
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
import { RuleBuild } from '@/common/logicEngine/RuleBuild'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
namespaced: true,
|
|
||||||
state: {
|
|
||||||
showLogicEngine: null
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
setShowLogicEngine(state, logicEngine) {
|
|
||||||
state.showLogicEngine = logicEngine
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
initShowLogic({ commit }, ruleConf) {
|
|
||||||
const showLogicEngine = new RuleBuild().fromJson(ruleConf)
|
|
||||||
commit('setShowLogicEngine', showLogicEngine)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,7 +2,4 @@ export default {
|
|||||||
setBannerList(state, data) {
|
setBannerList(state, data) {
|
||||||
state.bannerList = data
|
state.bannerList = data
|
||||||
},
|
},
|
||||||
setShowLogicEngine(state, logicEngine) {
|
|
||||||
state.logicEngine = logicEngine
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
export default {
|
export default {
|
||||||
bannerList: [],
|
bannerList: []
|
||||||
logicEngine: null
|
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup>
|
||||||
import { ref, computed, inject } from 'vue'
|
import { ref, computed, inject } from 'vue'
|
||||||
import OptionConfig from '../AdvancedConfig/OptionConfig.vue'
|
import OptionConfig from '../AdvancedConfig/OptionConfig.vue'
|
||||||
import RateConfig from '../AdvancedConfig/RateConfig.vue'
|
import RateConfig from '../AdvancedConfig/RateConfig.vue'
|
||||||
@ -75,7 +75,7 @@ defineProps({
|
|||||||
})
|
})
|
||||||
const emit = defineEmits(['addOther', 'optionChange', 'change'])
|
const emit = defineEmits(['addOther', 'optionChange', 'change'])
|
||||||
|
|
||||||
const moduleConfig = inject('moduleConfig') as any
|
const moduleConfig = inject('moduleConfig')
|
||||||
const optionConfigVisible = ref(false)
|
const optionConfigVisible = ref(false)
|
||||||
const openOptionConfig = () => {
|
const openOptionConfig = () => {
|
||||||
console.log('open')
|
console.log('open')
|
||||||
@ -85,10 +85,10 @@ const openOptionConfig = () => {
|
|||||||
const addOther = () => {
|
const addOther = () => {
|
||||||
emit('addOther')
|
emit('addOther')
|
||||||
}
|
}
|
||||||
const handleOptionChange = (value: any[]) => {
|
const handleOptionChange = (value) => {
|
||||||
emit('optionChange', value)
|
emit('optionChange', value)
|
||||||
}
|
}
|
||||||
const handleChange = (data: any) => {
|
const handleChange = (data) => {
|
||||||
emit('change', data)
|
emit('change', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ const rateConfigVisible = ref(false)
|
|||||||
const openRateConfig = () => {
|
const openRateConfig = () => {
|
||||||
rateConfigVisible.value = true
|
rateConfigVisible.value = true
|
||||||
}
|
}
|
||||||
const onVisibleChange = (val: boolean) => {
|
const onVisibleChange = (val) => {
|
||||||
rateConfigVisible.value = val
|
rateConfigVisible.value = val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import AlertDialog from './components/AlertDialog.vue'
|
|||||||
|
|
||||||
import LogoIcon from './components/LogoIcon.vue'
|
import LogoIcon from './components/LogoIcon.vue'
|
||||||
import { get as _get } from 'lodash-es'
|
import { get as _get } from 'lodash-es'
|
||||||
import { ruleConf } from '@/common/logicEngine/ruleConf'
|
import { initRuleEngine } from '@/render/hooks/useRuleEngine.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: 'App',
|
||||||
@ -69,7 +69,7 @@ export default {
|
|||||||
this.setSkin(skinConf)
|
this.setSkin(skinConf)
|
||||||
this.$store.commit('setSurveyPath', surveyPath)
|
this.$store.commit('setSurveyPath', surveyPath)
|
||||||
this.$store.dispatch('init', questionData)
|
this.$store.dispatch('init', questionData)
|
||||||
this.$store.dispatch('initRuleEngine', logicConf?.showLogicConf);
|
initRuleEngine(logicConf?.showLogicConf)
|
||||||
this.$store.dispatch('getEncryptInfo')
|
this.$store.dispatch('getEncryptInfo')
|
||||||
} else {
|
} else {
|
||||||
throw new Error(res.errmsg)
|
throw new Error(res.errmsg)
|
||||||
|
@ -16,6 +16,9 @@ import { useShowOthers } from '@/render/hooks/useShowOthers'
|
|||||||
import { useShowInput } from '@/render/hooks/useShowInput'
|
import { useShowInput } from '@/render/hooks/useShowInput'
|
||||||
import store from '@/render/store'
|
import store from '@/render/store'
|
||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
import { ruleEngine } from '@/render/hooks/useRuleEngine.js'
|
||||||
|
import { QUESTION_TYPE } from '@/render/constant/index'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
indexNumber: {
|
indexNumber: {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
@ -38,21 +41,20 @@ const questionConfig = computed(() =>{
|
|||||||
const { type, field, options, ...rest } = cloneDeep(moduleConfig)
|
const { type, field, options, ...rest } = cloneDeep(moduleConfig)
|
||||||
// console.log(field,'这里依赖的formValue,所以change时会触发重新计算')
|
// console.log(field,'这里依赖的formValue,所以change时会触发重新计算')
|
||||||
let alloptions = options
|
let alloptions = options
|
||||||
if(type === 'vote') {
|
if(type === QUESTION_TYPE.VOTE) {
|
||||||
const { options, voteTotal } = useVoteMap(field)
|
const { options, voteTotal } = useVoteMap(field)
|
||||||
const voteOptions = unref(options)
|
const voteOptions = unref(options)
|
||||||
alloptions = alloptions.map((obj, index) => Object.assign(obj, voteOptions[index]))
|
alloptions = alloptions.map((obj, index) => Object.assign(obj, voteOptions[index]))
|
||||||
moduleConfig.voteTotal = unref(voteTotal)
|
moduleConfig.voteTotal = unref(voteTotal)
|
||||||
}
|
}
|
||||||
if(['radio','checkbox'].includes(type) && options.filter(optionItem => optionItem.others).length > 0) {
|
if(QUESTION_TYPE.CHOICES.includes(type) && options.filter(optionItem => optionItem.others).length > 0) {
|
||||||
let { options, othersValue } = useShowOthers(field)
|
let { options, othersValue } = useShowOthers(field)
|
||||||
const othersOptions = unref(options)
|
const othersOptions = unref(options)
|
||||||
alloptions = alloptions.map((obj, index) => Object.assign(obj, othersOptions[index]))
|
alloptions = alloptions.map((obj, index) => Object.assign(obj, othersOptions[index]))
|
||||||
moduleConfig.othersValue = unref(othersValue)
|
moduleConfig.othersValue = unref(othersValue)
|
||||||
}
|
}
|
||||||
if(['radio-star','radio-nps'].includes(type) && Object.keys(rest.rangeConfig).filter(index => rest.rangeConfig[index].isShowInput).length > 0) {
|
if(QUESTION_TYPE.RATES.includes(type) && Object.keys(rest.rangeConfig).filter(index => rest.rangeConfig[index].isShowInput).length > 0) {
|
||||||
let { rangeConfig, othersValue } = useShowInput(field)
|
let { rangeConfig, othersValue } = useShowInput(field)
|
||||||
// console.log({rangeConfig, othersValue})
|
|
||||||
moduleConfig.rangeConfig = unref(rangeConfig)
|
moduleConfig.rangeConfig = unref(rangeConfig)
|
||||||
moduleConfig.othersValue = unref(othersValue)
|
moduleConfig.othersValue = unref(othersValue)
|
||||||
}
|
}
|
||||||
@ -63,22 +65,21 @@ const questionConfig = computed(() =>{
|
|||||||
value: formValues.value[props.moduleConfig.field]
|
value: formValues.value[props.moduleConfig.field]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { field } = props.moduleConfig
|
||||||
|
|
||||||
const visible = computed(() => {
|
const visible = computed(() => {
|
||||||
const { field } = props.moduleConfig
|
// computed有计算缓存,当match有变化的时候触发重新计算
|
||||||
const matchRule = store.state.ruleEngine.rules.get(field+'question')
|
return ruleEngine.match(field, 'question', formValues.value)
|
||||||
if(matchRule) {
|
|
||||||
return matchRule.result
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(() => visible.value, (newVal, oldVal) => {
|
watch(() => visible.value, (newVal, oldVal) => {
|
||||||
// 题目从显示到隐藏,需要清空值
|
// 题目从显示到隐藏,需要清空值
|
||||||
const { field, type, innerType } = props.moduleConfig
|
const { field, type, innerType } = props.moduleConfig
|
||||||
if(!newVal && oldVal) {
|
if(!newVal && oldVal) {
|
||||||
let value = ''
|
let value = ''
|
||||||
// 题型是多选,或者子题型是多选(innerType是用于投票)
|
// 题型是多选,或者子题型是多选(innerType是用于投票)
|
||||||
if (/checkbox/.test(type) || innerType === 'checkbox') {
|
if (type === QUESTION_TYPE.CHECKBOX || innerType === QUESTION_TYPE.CHECKBOX) {
|
||||||
value = value ? [value] : []
|
value = value ? [value] : []
|
||||||
}
|
}
|
||||||
const data = {
|
const data = {
|
||||||
@ -86,29 +87,14 @@ watch(() => visible.value, (newVal, oldVal) => {
|
|||||||
value: value
|
value: value
|
||||||
}
|
}
|
||||||
store.commit('changeFormData', data)
|
store.commit('changeFormData', data)
|
||||||
notifyMatch(field)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleChange = (data) => {
|
const handleChange = (data) => {
|
||||||
const { key } = data
|
|
||||||
// console.log(key, '触发change事件')
|
|
||||||
emit('change', data)
|
emit('change', data)
|
||||||
// 处理投票题
|
// 处理投票题
|
||||||
if(props.moduleConfig.type === 'vote') {
|
if(props.moduleConfig.type === QUESTION_TYPE.VOTE) {
|
||||||
store.dispatch('updateVoteData', data)
|
store.dispatch('updateVoteData', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理显示逻辑
|
|
||||||
notifyMatch(key)
|
|
||||||
}
|
|
||||||
const notifyMatch = (key) => {
|
|
||||||
let fact = unref(formValues)
|
|
||||||
const targets = store.state.ruleEngine.findTargetsByField(key) || []
|
|
||||||
// 前置题改变通知目标题更新规则匹配
|
|
||||||
targets.forEach((target) => {
|
|
||||||
store.state.ruleEngine.match(target, 'question', fact)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
12
web/src/render/constant/index.js
Normal file
12
web/src/render/constant/index.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export const QUESTION_TYPE = {
|
||||||
|
VOTE: 'vote',
|
||||||
|
CHECKBOX: 'checkbox',
|
||||||
|
CHOICES: [ // 选择类题型分类
|
||||||
|
'radio',
|
||||||
|
'checkbox',
|
||||||
|
],
|
||||||
|
RATES: [ // 评分题题型分类
|
||||||
|
'radio-star',
|
||||||
|
'radio-nps'
|
||||||
|
]
|
||||||
|
}
|
6
web/src/render/hooks/useRuleEngine.js
Normal file
6
web/src/render/hooks/useRuleEngine.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { RuleMatch } from '@/common/logicEngine/RulesMatch'
|
||||||
|
|
||||||
|
export const ruleEngine = new RuleMatch()
|
||||||
|
export const initRuleEngine = (ruleConf) => {
|
||||||
|
ruleEngine.fromJson(ruleConf)
|
||||||
|
}
|
@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="index">
|
<div class="index">
|
||||||
<progressBar />
|
<ProgressBar />
|
||||||
<div class="wrapper" ref="box">
|
<div class="wrapper" ref="box">
|
||||||
<HeaderSetter></HeaderSetter>
|
<HeaderSetter></HeaderSetter>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<MainTitle></MainTitle>
|
<MainTitle></MainTitle>
|
||||||
<MainRenderer ref="main"></MainRenderer>
|
<MainRenderer ref="main"></MainRenderer>
|
||||||
<submit :validate="validate" :renderData="renderData" @submit="onSubmit"></submit>
|
<Submit :validate="validate" :renderData="renderData" @submit="onSubmit"></Submit>
|
||||||
<LogoIcon />
|
<LogoIcon />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -16,11 +16,11 @@
|
|||||||
<script>
|
<script>
|
||||||
import HeaderSetter from '../components/HeaderSetter.vue'
|
import HeaderSetter from '../components/HeaderSetter.vue'
|
||||||
import MainTitle from '../components/MainTitle.vue'
|
import MainTitle from '../components/MainTitle.vue'
|
||||||
import submit from '../components/SubmitSetter.vue'
|
import Submit from '../components/SubmitSetter.vue'
|
||||||
import MainRenderer from '../components/MainRenderer.vue'
|
import MainRenderer from '../components/MainRenderer.vue'
|
||||||
import AlertDialog from '../components/AlertDialog.vue'
|
import AlertDialog from '../components/AlertDialog.vue'
|
||||||
import ConfirmDialog from '../components/ConfirmDialog.vue'
|
import ConfirmDialog from '../components/ConfirmDialog.vue'
|
||||||
import progressBar from '../components/ProgressBar.vue'
|
import ProgressBar from '../components/ProgressBar.vue'
|
||||||
import LogoIcon from '../components/LogoIcon.vue'
|
import LogoIcon from '../components/LogoIcon.vue'
|
||||||
|
|
||||||
import { submitForm } from '../api/survey'
|
import { submitForm } from '../api/survey'
|
||||||
@ -44,9 +44,9 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
HeaderSetter,
|
HeaderSetter,
|
||||||
MainTitle,
|
MainTitle,
|
||||||
submit,
|
Submit,
|
||||||
MainRenderer,
|
MainRenderer,
|
||||||
progressBar,
|
ProgressBar,
|
||||||
LogoIcon
|
LogoIcon
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -93,22 +93,10 @@ export default {
|
|||||||
},
|
},
|
||||||
getSubmitData() {
|
getSubmitData() {
|
||||||
const formValues = cloneDeep(this.$store.state.formValues)
|
const formValues = cloneDeep(this.$store.state.formValues)
|
||||||
// 填写更多-处理提交数据
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 显示逻辑-处理提交数据
|
|
||||||
const formModel = Object.keys(formValues)
|
|
||||||
.filter(key => this.$store.state.ruleEngine.getResult(key, 'question'))
|
|
||||||
.reduce((obj, key) => {
|
|
||||||
obj[key] = formValues[key];
|
|
||||||
return obj;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
surveyPath: this.surveyPath,
|
surveyPath: this.surveyPath,
|
||||||
data: JSON.stringify(formModel),
|
data: JSON.stringify(formValues),
|
||||||
difTime: Date.now() - this.$store.state.enterTime,
|
difTime: Date.now() - this.$store.state.enterTime,
|
||||||
clientTime: Date.now()
|
clientTime: Date.now()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user