format: 代码格式化 (#160)

This commit is contained in:
dayou 2024-05-23 21:52:57 +08:00 committed by sudoooooo
parent 38566f1f60
commit 4c85fcc47e
30 changed files with 291 additions and 274 deletions

10
web/components.d.ts vendored
View File

@ -11,26 +11,30 @@ declare module 'vue' {
ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
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']
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
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']
ElInput: typeof import('element-plus/es')['ElInput'] ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption'] ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import('element-plus/es')['ElPagination'] ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover'] ElPopover: typeof import('element-plus/es')['ElPopover']
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']
ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] ElSlider: typeof import('element-plus/es')['ElSlider']
ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable'] ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTabPane: typeof import('element-plus/es')['ElTabPane'] ElTabPane: typeof import('element-plus/es')['ElTabPane']
ElTabs: typeof import('element-plus/es')['ElTabs'] ElTabs: typeof import('element-plus/es')['ElTabs']
ElTag: typeof import('element-plus/es')['ElTag']
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTooltip: typeof import('element-plus/es')['ElTooltip']
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']

View File

@ -8,10 +8,9 @@ export enum Operator {
Include = 'in', Include = 'in',
Equal = 'eq', Equal = 'eq',
NotEqual = 'neq', NotEqual = 'neq',
NotInclude = 'nin', NotInclude = 'nin'
} }
export enum PrefixID { export enum PrefixID {
Rule = 'r', Rule = 'r',
Condition = 'c' Condition = 'c'
@ -22,11 +21,9 @@ export enum Scope {
Option = 'option' Option = 'option'
} }
export type FieldTypes = string | string[]
export type FieldTypes = string | string[];
// 定义事实对象类型 // 定义事实对象类型
export type Fact = { export type Fact = {
[key: string]: any; [key: string]: any
}; }

View File

@ -1,4 +1,4 @@
import { nanoid } from 'nanoid'; import { nanoid } from 'nanoid'
import * as yup from 'yup' import * as yup from 'yup'
import { type FieldTypes, PrefixID, Operator, Scope } from './BasicType' import { type FieldTypes, PrefixID, Operator, Scope } from './BasicType'
@ -7,29 +7,29 @@ export function generateID(prefix = PrefixID.Rule) {
} }
// 定义条件规则类 // 定义条件规则类
export class ConditionNode { export class ConditionNode {
id: string = ''; id: string = ''
public field: string = ''; public field: string = ''
public operator: Operator = Operator.Include; public operator: Operator = Operator.Include
public value: FieldTypes = [] public value: FieldTypes = []
constructor(field: string = '', operator: Operator = Operator.Include, 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(PrefixID.Condition) this.id = generateID(PrefixID.Condition)
} }
setField(field: string) { setField(field: string) {
this.field = field; this.field = field
} }
setOperator(operator: Operator) { setOperator(operator: Operator) {
this.operator = operator; this.operator = operator
} }
setValue(value: FieldTypes) { setValue(value: FieldTypes) {
this.value = value; this.value = value
} }
} }
export class RuleNode { export class RuleNode {
id: string = ''; id: string = ''
conditions: ConditionNode[] = [] conditions: ConditionNode[] = []
scope: string = Scope.Question scope: string = Scope.Question
target: string = '' target: string = ''
@ -42,44 +42,44 @@ export class RuleNode {
this.target = value this.target = value
} }
addCondition(condition: ConditionNode) { addCondition(condition: ConditionNode) {
this.conditions.push(condition); this.conditions.push(condition)
} }
removeCondition(id: string) { removeCondition(id: string) {
this.conditions = this.conditions.filter(v => v.id !== id); this.conditions = this.conditions.filter((v) => v.id !== id)
} }
findCondition(conditionId: string) { findCondition(conditionId: string) {
return this.conditions.find(condition => condition.id === conditionId); return this.conditions.find((condition) => condition.id === conditionId)
} }
} }
export class RuleBuild { export class RuleBuild {
rules: RuleNode[] = []; rules: RuleNode[] = []
static instance: RuleBuild; static instance: RuleBuild
constructor() { constructor() {
this.rules = []; this.rules = []
if (!RuleBuild.instance) { if (!RuleBuild.instance) {
RuleBuild.instance = this; RuleBuild.instance = this
} }
return RuleBuild.instance; return RuleBuild.instance
} }
// 添加条件规则到规则引擎中 // 添加条件规则到规则引擎中
addRule(rule: RuleNode) { addRule(rule: RuleNode) {
this.rules.push(rule); this.rules.push(rule)
} }
removeRule(ruleId: string) { removeRule(ruleId: string) {
this.rules = this.rules.filter(rule => rule.id !== ruleId); this.rules = this.rules.filter((rule) => rule.id !== ruleId)
} }
findRule(ruleId: string) { findRule(ruleId: string) {
return this.rules.find(rule => rule.id === ruleId); return this.rules.find((rule) => rule.id === ruleId)
} }
toJson() { toJson() {
return this.rules.map(rule => { return this.rules.map((rule) => {
return { return {
target: rule.target, target: rule.target,
scope: rule.scope, scope: rule.scope,
conditions: rule.conditions.map(condition => { conditions: rule.conditions.map((condition) => {
return { return {
field: condition.field, field: condition.field,
operator: condition.operator, operator: condition.operator,
@ -94,10 +94,10 @@ export class RuleBuild {
if (ruleConf instanceof Array) { if (ruleConf instanceof Array) {
ruleConf.forEach((rule: any) => { ruleConf.forEach((rule: any) => {
const { scope, target } = rule const { scope, target } = rule
const ruleNode = new RuleNode(scope, target); const ruleNode = new RuleNode(scope, target)
rule.conditions.forEach((condition: any) => { rule.conditions.forEach((condition: any) => {
const { field, operator, value } = condition const { field, operator, value } = condition
const conditionNode = new ConditionNode(field, operator, value); const conditionNode = new ConditionNode(field, operator, value)
ruleNode.addCondition(conditionNode) ruleNode.addCondition(conditionNode)
}) })
this.addRule(ruleNode) this.addRule(ruleNode)
@ -110,7 +110,7 @@ export class RuleBuild {
} }
// 实现目标选择了下拉框置灰效果 // 实现目标选择了下拉框置灰效果
findTargetsByScope(scope: string) { findTargetsByScope(scope: string) {
return this.rules.filter(rule => rule.scope === scope).map(rule => rule.target) return this.rules.filter((rule) => rule.scope === scope).map((rule) => rule.target)
} }
// 实现前置题删除校验 // 实现前置题删除校验
findTargetsByFields(field: string) { findTargetsByFields(field: string) {
@ -126,11 +126,10 @@ export class RuleBuild {
} }
// 根据目标题获取显示逻辑 // 根据目标题获取显示逻辑
findConditionByTarget(target: string) { findConditionByTarget(target: string) {
return this.rules.filter(rule=> rule.target === target).map(item => item.conditions) return this.rules.filter((rule) => rule.target === target).map((item) => item.conditions)
} }
} }
export const ruleSchema = yup.array().of( export const ruleSchema = yup.array().of(
yup.object({ yup.object({
target: yup.string().required(), target: yup.string().required(),

View File

@ -1,17 +1,19 @@
import { Operator, type FieldTypes, type Fact } from './BasicType'
import { Operator, type FieldTypes, type Fact } from "./BasicType";
// 定义条件规则类 // 定义条件规则类
export class ConditionNode<F extends string, O extends Operator> { 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
) {}
// 计算条件规则的哈希值 // 计算条件规则的哈希值
calculateHash(): string { calculateHash(): string {
// 假设哈希值计算方法为简单的字符串拼接或其他哈希算法 // 假设哈希值计算方法为简单的字符串拼接或其他哈希算法
return this.field + this.operator + this.value; return this.field + this.operator + this.value
} }
match(facts: Fact): boolean { match(facts: Fact): boolean {
@ -24,41 +26,40 @@ export class ConditionNode<F extends string, O extends Operator> {
switch (this.operator) { switch (this.operator) {
case Operator.Equal: 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
} else { } else {
this.result = facts[this.field].includes(this.value); this.result = facts[this.field].includes(this.value)
return this.result return this.result
} }
case Operator.Include: 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
} else { } else {
this.result = facts[this.field].includes(this.value); this.result = facts[this.field].includes(this.value)
return this.result return this.result
} }
case Operator.NotInclude: 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
} else { } else {
this.result = facts[this.field].includes(this.value); this.result = facts[this.field].includes(this.value)
return this.result return this.result
} }
case Operator.NotEqual: 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
} else { } else {
this.result = facts[this.field].includes(this.value); this.result = facts[this.field].includes(this.value)
return this.result return this.result
} }
// 其他比较操作符的判断逻辑 // 其他比较操作符的判断逻辑
default: default:
return this.result return this.result
} }
} }
getResult() { getResult() {
@ -67,15 +68,18 @@ export class ConditionNode<F extends string, O extends Operator> {
} }
export class RuleNode { export class RuleNode {
conditions: Map<string, ConditionNode<string, Operator>>; // 使用哈希表存储条件规则对象 conditions: Map<string, ConditionNode<string, Operator>> // 使用哈希表存储条件规则对象
public result: boolean = false; public result: boolean = false
constructor(public target: string, public scope: string) { constructor(
this.conditions = new Map(); public target: string,
public scope: string
) {
this.conditions = new Map()
} }
// 添加条件规则到规则引擎中 // 添加条件规则到规则引擎中
addCondition(condition: ConditionNode<string, Operator>) { addCondition(condition: ConditionNode<string, Operator>) {
const hash = condition.calculateHash(); const hash = condition.calculateHash()
this.conditions.set(hash, condition); this.conditions.set(hash, condition)
} }
// 匹配条件规则 // 匹配条件规则
@ -83,11 +87,11 @@ export class RuleNode {
const res = Array.from(this.conditions.entries()).every(([, value]) => { const res = Array.from(this.conditions.entries()).every(([, value]) => {
const res = value.match(fact) const res = value.match(fact)
if (res) { if (res) {
return true; return true
} else { } else {
return false return false
} }
}); })
this.result = res this.result = res
return res return res
} }
@ -102,7 +106,7 @@ export class RuleNode {
// 计算条件规则的哈希值 // 计算条件规则的哈希值
calculateHash(): string { calculateHash(): string {
// 假设哈希值计算方法为简单的字符串拼接或其他哈希算法 // 假设哈希值计算方法为简单的字符串拼接或其他哈希算法
return this.target + this.scope; return this.target + this.scope
} }
toJson() { toJson() {
return { return {
@ -111,30 +115,33 @@ export class RuleNode {
conditions: Object.fromEntries( conditions: Object.fromEntries(
Array.from(this.conditions, ([key, value]) => [key, value.getResult()]) Array.from(this.conditions, ([key, value]) => [key, value.getResult()])
) )
};
} }
}
} }
export class RuleMatch { export class RuleMatch {
rules: Map<string, RuleNode>; rules: Map<string, RuleNode>
static instance: any; static instance: any
constructor() { constructor() {
this.rules = new Map(); this.rules = new Map()
if (!RuleMatch.instance) { if (!RuleMatch.instance) {
RuleMatch.instance = this; RuleMatch.instance = this
} }
return RuleMatch.instance; return RuleMatch.instance
} }
fromJson(ruleConf: any) { 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)
rule.conditions.forEach((condition: any) => { rule.conditions.forEach((condition: any) => {
const conditionNode = new ConditionNode(condition.field, condition.operator, condition.value); const conditionNode = new ConditionNode(
condition.field,
condition.operator,
condition.value
)
ruleNode.addCondition(conditionNode) ruleNode.addCondition(conditionNode)
}); })
this.addRule(ruleNode) this.addRule(ruleNode)
}) })
} }
@ -142,23 +149,22 @@ export class RuleMatch {
// 添加条件规则到规则引擎中 // 添加条件规则到规则引擎中
addRule(rule: RuleNode) { addRule(rule: RuleNode) {
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, Operator>) => { existRule.conditions.forEach((item: ConditionNode<string, Operator>) => {
rule.addCondition(item) rule.addCondition(item)
}) })
} }
this.rules.set(hash, rule); this.rules.set(hash, rule)
} }
// 匹配条件规则 // 匹配条件规则
match(target: string, scope: string, fact: Fact) { match(target: string, scope: string, fact: Fact) {
const hash = this.calculateHash(target, scope); const hash = this.calculateHash(target, scope)
const rule = this.rules.get(hash); const rule = this.rules.get(hash)
if (rule) { if (rule) {
const result = rule.match(fact) const result = rule.match(fact)
// this.matchCache.set(hash, result); // this.matchCache.set(hash, result);
@ -170,8 +176,8 @@ export class RuleMatch {
} }
getResult(target: string, scope: string) { getResult(target: string, scope: string) {
const hash = this.calculateHash(target, scope); const hash = this.calculateHash(target, scope)
const rule = this.rules.get(hash); const rule = this.rules.get(hash)
if (rule) { if (rule) {
const result = rule.getResult() const result = rule.getResult()
return result return result
@ -183,15 +189,17 @@ export class RuleMatch {
// 计算哈希值的方法 // 计算哈希值的方法
calculateHash(target: string, scope: string): string { calculateHash(target: string, scope: string): string {
// 假设哈希值计算方法为简单的字符串拼接或其他哈希算法 // 假设哈希值计算方法为简单的字符串拼接或其他哈希算法
return target + scope; return target + scope
} }
findTargetsByField(field: string) { findTargetsByField(field: string) {
const rules = new Map([...this.rules.entries()].filter(([, value]) => { const rules = new Map(
[...this.rules.entries()].filter(([, value]) => {
return [...value.conditions.entries()].filter(([, value]) => { return [...value.conditions.entries()].filter(([, value]) => {
return value.field === field return value.field === field
}) })
})) })
return [...rules.values()].map(obj => obj.target); )
return [...rules.values()].map((obj) => obj.target)
} }
toJson() { toJson() {
return Array.from(this.rules.entries()).map(([, value]) => { return Array.from(this.rules.entries()).map(([, value]) => {

View File

@ -1,4 +1,4 @@
import { computed } from 'vue'; import { computed } from 'vue'
import store from '@/management/store' import store from '@/management/store'
import { cleanRichText } from '@/common/xss' import { cleanRichText } from '@/common/xss'
export const useQuestionInfo = (field) => { export const useQuestionInfo = (field) => {
@ -13,7 +13,9 @@ export const useQuestionInfo = (field) => {
return (value) => { return (value) => {
const options = questionDataList.find((item) => item.field === field)?.options || [] const options = questionDataList.find((item) => item.field === field)?.options || []
if (value instanceof Array) { if (value instanceof Array) {
return options.filter((item) => value.includes(item.hash)).map((item) => cleanRichText(item.text)) return options
.filter((item) => value.includes(item.hash))
.map((item) => cleanRichText(item.text))
} else { } else {
return options.filter((item) => item.hash === value).map((item) => cleanRichText(item.text)) return options.filter((item) => item.hash === value).map((item) => cleanRichText(item.text))
} }

View File

@ -1,4 +1,4 @@
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 { cleanRichText } from '@/common/xss' import { cleanRichText } from '@/common/xss'
@ -23,7 +23,9 @@ export const useShowLogicInfo = (field) => {
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/>`
}) })
return conditions.length ? conditions.join('') + '<span> &nbsp;满足以上全部,则显示本题</span>' :'' return conditions.length
? conditions.join('') + '<span> &nbsp;满足以上全部,则显示本题</span>'
: ''
}) })
return { hasShowLogic, getShowLogicText } return { hasShowLogic, getShowLogicText }
} }

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="rule-list"> <div class="rule-list">
<RuleNodeView <RuleNodeView
v-for="(item) in list" v-for="item in list"
ref="ruleWrappers" ref="ruleWrappers"
:key="item.id" :key="item.id"
:ruleNode="item" :ruleNode="item"

View File

@ -78,7 +78,8 @@ const props = defineProps({
}) })
const fieldList = computed(() => { const fieldList = computed(() => {
const currentIndex = renderData.value.findIndex((item) => item.field === props.ruleNode.target) const currentIndex = renderData.value.findIndex((item) => item.field === props.ruleNode.target)
return renderData.value.slice(0, currentIndex) return renderData.value
.slice(0, currentIndex)
.filter((question: any) => qAbleList.includes(question.type)) .filter((question: any) => qAbleList.includes(question.type))
.map((item: any) => { .map((item: any) => {
return { return {
@ -145,9 +146,9 @@ const handleDelete = (id: any) => {
bottom: 0px; bottom: 0px;
width: 20px; width: 20px;
height: 20px; height: 20px;
background: #FEF6E6; background: #fef6e6;
border-radius: 2px; border-radius: 2px;
color: #FAA600; color: #faa600;
font-size: 12px; font-size: 12px;
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -156,7 +157,7 @@ const handleDelete = (id: any) => {
bottom: -8px; bottom: -8px;
} }
&:not(:last-child)::after { &:not(:last-child)::after {
content: ""; content: '';
display: block; display: block;
width: calc(100% - 32px); width: calc(100% - 32px);
border-top: 1px dashed #e3e4e8; border-top: 1px dashed #e3e4e8;

View File

@ -97,7 +97,9 @@ const submitForm = () => {
const targetQuestionList = computed(() => { const targetQuestionList = computed(() => {
const currntIndexs: number[] = [] const currntIndexs: number[] = []
props.ruleNode.conditions.forEach((el) => { props.ruleNode.conditions.forEach((el) => {
currntIndexs.push(renderData.value.findIndex((item: { field: string }) => item.field === el.field)) currntIndexs.push(
renderData.value.findIndex((item: { field: string }) => item.field === el.field)
)
}) })
const currntIndex = Math.max(...currntIndexs) const currntIndex = Math.max(...currntIndexs)
let questionList = cloneDeep(renderData.value.slice(currntIndex + 1)) let questionList = cloneDeep(renderData.value.slice(currntIndex + 1))
@ -105,9 +107,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: showLogicEngine.value disabled: showLogicEngine.value.findTargetsByScope('question').includes(item.field)
.findTargetsByScope('question')
.includes(item.field)
} }
}) })
}) })

View File

@ -27,7 +27,6 @@
<p class="text">{{ element.title }}</p> <p class="text">{{ element.title }}</p>
</div> </div>
</template> </template>
</draggable> </draggable>
</el-collapse-item> </el-collapse-item>
<Teleport to="body"> <Teleport to="body">
@ -211,7 +210,7 @@ const showPreview = ({ snapshot }, id) => {
&::before { &::before {
position: absolute; position: absolute;
content: ""; content: '';
height: 10px; height: 10px;
width: 10px; width: 10px;
border: 1px solid var(--el-border-color-light); border: 1px solid var(--el-border-color-light);
@ -219,7 +218,6 @@ const showPreview = ({ snapshot }, id) => {
border-bottom-color: transparent; border-bottom-color: transparent;
border-right-color: transparent; border-right-color: transparent;
} }
} }
} }
</style> </style>

View File

@ -12,19 +12,19 @@
</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: 'editIndex', name: 'editIndex',
components: { components: {
CommonTemplate, CommonTemplate,
CatalogPanel, CatalogPanel,
PreviewPanel, PreviewPanel,
SetterPanel, SetterPanel
}, }
}; }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.navbar { .navbar {

View File

@ -30,8 +30,7 @@ const routes: RouteRecordRaw[] = [
needLogin: true needLogin: true
}, },
name: 'QuestionEditPage', name: 'QuestionEditPage',
component: () => component: () => import('../pages/edit/pages/edit/index.vue'),
import('../pages/edit/pages/edit/index.vue'),
children: [ children: [
{ {
path: '', path: '',
@ -39,8 +38,7 @@ const routes: RouteRecordRaw[] = [
meta: { meta: {
needLogin: true needLogin: true
}, },
component: () => component: () => import('../pages/edit/pages/edit/QuestionEditPage.vue')
import('../pages/edit/pages/edit/QuestionEditPage.vue')
}, },
{ {
path: 'logic', path: 'logic',
@ -48,8 +46,7 @@ const routes: RouteRecordRaw[] = [
meta: { meta: {
needLogin: true needLogin: true
}, },
component: () => component: () => import('../pages/edit/pages/edit/LogicEditPage.vue')
import('../pages/edit/pages/edit/LogicEditPage.vue')
} }
] ]
}, },

View File

@ -15,8 +15,15 @@ export default {
if (res.code === 200) { if (res.code === 200) {
const metaData = res.data.surveyMetaRes const metaData = res.data.surveyMetaRes
document.title = metaData.title document.title = metaData.title
const { bannerConf, bottomConf, skinConf, baseConf, submitConf, dataConf, logicConf = {} } = const {
res.data.surveyConfRes.code bannerConf,
bottomConf,
skinConf,
baseConf,
submitConf,
dataConf,
logicConf = {}
} = res.data.surveyConfRes.code
commit('initSchema', { commit('initSchema', {
metaData, metaData,
codeData: { codeData: {
@ -29,7 +36,6 @@ export default {
logicConf logicConf
} }
}) })
} else { } else {
throw new Error(res.errmsg || '问卷不存在') throw new Error(res.errmsg || '问卷不存在')
} }

View File

@ -1,5 +1,5 @@
export default { export default {
setBannerList(state, data) { setBannerList(state, data) {
state.bannerList = data state.bannerList = data
}, }
} }

View File

@ -3,19 +3,14 @@ export const QOP_MAP = {
COPY: 'copy', COPY: 'copy',
EDIT: 'edit' EDIT: 'edit'
} }
export const qAbleList = [ export const qAbleList = ['radio', 'checkbox', 'binary-choice', 'vote']
'radio',
'checkbox',
'binary-choice',
'vote',
]
export const operatorOptions = [ export const operatorOptions = [
{ {
label: '选择了', label: '选择了',
value: 'in', value: 'in'
}, },
{ {
label: '不选择', label: '不选择',
value: 'nin', value: 'nin'
}, }
] ]

View File

@ -32,7 +32,7 @@ interface Props {
} }
interface Emit { interface Emit {
(ev: typeof FORM_CHANGE_EVENT_KEY, arg: { key: string; value: string }): void (ev: typeof FORM_CHANGE_EVENT_KEY, arg: { key: string; value: string | null }): void
} }
const emit = defineEmits<Emit>() const emit = defineEmits<Emit>()
@ -58,8 +58,8 @@ const handleSelectChange = (value: string) => {
emit(FORM_CHANGE_EVENT_KEY, { key: formdataBackfillKey, value }) emit(FORM_CHANGE_EVENT_KEY, { key: formdataBackfillKey, value })
} }
const handleSwitchChange = (value: string) => { const handleSwitchChange = (value: string | null) => {
emit(FORM_CHANGE_EVENT_KEY, { key: formdataBackfillHourKey, value: value ? 24 : null }) emit(FORM_CHANGE_EVENT_KEY, { key: formdataBackfillHourKey, value: value ? '24' : null })
} }
const watchValue = computed(() => props.formConfig.value) const watchValue = computed(() => props.formConfig.value)

View File

@ -77,15 +77,15 @@ onMounted(async () => {
if (res.code === 200) { if (res.code === 200) {
const data = res.data const data = res.data
const { bannerConf, baseConf, bottomConf, dataConf, skinConf, submitConf, logicConf } = data.code const { bannerConf, baseConf, bottomConf, dataConf, skinConf, submitConf, logicConf } =
data.code
const questionData = { const questionData = {
bannerConf, bannerConf,
baseConf, baseConf,
bottomConf, bottomConf,
dataConf, dataConf,
skinConf, skinConf,
submitConf, submitConf
} }
document.title = data.title document.title = data.title

View File

@ -1,6 +1,6 @@
<template> <template>
<form ref="ruleForm" :model="formValues" :rules="rules"> <form ref="ruleForm" :model="formValues" :rules="rules">
<div v-for="(item) in renderData" :key="item.field"> <div v-for="item in renderData" :key="item.field">
<QuestionWrapper <QuestionWrapper
class="gap" class="gap"
v-bind="$attrs" v-bind="$attrs"

View File

@ -29,7 +29,7 @@ const props = defineProps({
default: () => { default: () => {
return {} return {}
} }
}, }
}) })
const emit = defineEmits(['change']) const emit = defineEmits(['change'])
@ -47,13 +47,19 @@ const questionConfig = computed(() =>{
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(QUESTION_TYPE.CHOICES.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(QUESTION_TYPE.RATES.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)
moduleConfig.rangeConfig = unref(rangeConfig) moduleConfig.rangeConfig = unref(rangeConfig)
moduleConfig.othersValue = unref(othersValue) moduleConfig.othersValue = unref(othersValue)
@ -73,7 +79,9 @@ const visible = computed(() => {
return ruleEngine.match(field, 'question', formValues.value) return ruleEngine.match(field, 'question', formValues.value)
}) })
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) {
@ -88,7 +96,8 @@ watch(() => visible.value, (newVal, oldVal) => {
} }
store.commit('changeFormData', data) store.commit('changeFormData', data)
} }
}) }
)
const handleChange = (data) => { const handleChange = (data) => {
emit('change', data) emit('change', data)

View File

@ -1,11 +1,13 @@
export const QUESTION_TYPE = { export const QUESTION_TYPE = {
VOTE: 'vote', VOTE: 'vote',
CHECKBOX: 'checkbox', CHECKBOX: 'checkbox',
CHOICES: [ // 选择类题型分类 CHOICES: [
// 选择类题型分类
'radio', 'radio',
'checkbox', 'checkbox'
], ],
RATES: [ // 评分题题型分类 RATES: [
// 评分题题型分类
'radio-star', 'radio-star',
'radio-nps' 'radio-nps'
] ]

View File

@ -11,8 +11,7 @@ export const useShowInput = (questionKey) => {
const rangeKey = `${questionKey}_${key}` const rangeKey = `${questionKey}_${key}`
othersValue[rangeKey] = formValues[rangeKey] othersValue[rangeKey] = formValues[rangeKey]
curRange.othersKey = rangeKey, ;(curRange.othersKey = rangeKey), (curRange.othersValue = formValues[rangeKey])
curRange.othersValue = formValues[rangeKey]
if (!questionVal.toString().includes(key) && formValues[rangeKey]) { if (!questionVal.toString().includes(key) && formValues[rangeKey]) {
// 如果分值被未被选中且对应的填写更多有值,则清空填写更多 // 如果分值被未被选中且对应的填写更多有值,则清空填写更多
const data = { const data = {
@ -25,6 +24,5 @@ export const useShowInput = (questionKey) => {
} }
} }
return { rangeConfig, othersValue } return { rangeConfig, othersValue }
} }

View File

@ -3,7 +3,7 @@ export const useShowOthers = (questionKey) => {
const formValues = store.state.formValues const formValues = store.state.formValues
const questionVal = formValues[questionKey] const questionVal = formValues[questionKey]
let othersValue = {} let othersValue = {}
let options = store.state.questionData[questionKey].options.map(optionItem => { let options = store.state.questionData[questionKey].options.map((optionItem) => {
if (optionItem.others) { if (optionItem.others) {
const opKey = `${questionKey}_${optionItem.hash}` const opKey = `${questionKey}_${optionItem.hash}`
othersValue[opKey] = formValues[opKey] othersValue[opKey] = formValues[opKey]

View File

@ -1,9 +1,8 @@
import store from '../store/index' import store from '../store/index'
export const useVoteMap = (questionKey) => { export const useVoteMap = (questionKey) => {
let voteTotal = store.state.voteMap?.[questionKey]?.total || 0 let voteTotal = store.state.voteMap?.[questionKey]?.total || 0
const options = store.state.questionData[questionKey].options.map(option => { const options = store.state.questionData[questionKey].options.map((option) => {
const optionHash = option.hash const optionHash = option.hash
const voteCount = store.state.voteMap?.[questionKey]?.[optionHash] || 0 const voteCount = store.state.voteMap?.[questionKey]?.[optionHash] || 0

View File

@ -9,7 +9,7 @@ export default {
questionSeq.reduce((pre, item) => { questionSeq.reduce((pre, item) => {
const questionArr = [] const questionArr = []
item.forEach(questionKey => { item.forEach((questionKey) => {
console.log('题目重新计算') console.log('题目重新计算')
const question = { ...questionData[questionKey] } const question = { ...questionData[questionKey] }
// 开启显示序号 // 开启显示序号

View File

@ -52,5 +52,5 @@ export default {
}, },
setRuleEgine(state, ruleEngine) { setRuleEgine(state, ruleEngine) {
state.ruleEngine = ruleEngine state.ruleEngine = ruleEngine
}, }
} }