Skip to content

Commit

Permalink
fix: 多级联动题重命名为cascader
Browse files Browse the repository at this point in the history
  • Loading branch information
skique committed Dec 9, 2024
1 parent ab328eb commit 11d9c8c
Show file tree
Hide file tree
Showing 17 changed files with 717 additions and 54 deletions.
2 changes: 1 addition & 1 deletion server/src/enums/question.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ export enum QUESTION_TYPE {
/**
* 多级联动
*/
MULTILEVEL = 'multilevel',
CASCADER = 'cascader',
}
10 changes: 5 additions & 5 deletions server/src/interfaces/survey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ export interface NPS {
rightText: string;
}

export interface MultilevelItem {
export interface CascaderItem {
hash: string;
text: string;
children?: MultilevelItem[];
children?: CascaderItem[];
}

export interface MultilevelData {
export interface CascaderDate {
placeholder: Array<{
hash: string;
text: string;
}>;
children: Array<MultilevelItem>;
children: Array<CascaderItem>;
}

export interface TextRange {
Expand Down Expand Up @@ -74,7 +74,7 @@ export interface DataItem {
rangeConfig?: any;
starStyle?: string;
innerType?: string;
multilevelData: MultilevelData;
cascaderData: CascaderDate;
}

export interface Option {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class DataStatisticController {
QUESTION_TYPE.RADIO_STAR,
QUESTION_TYPE.RADIO_NPS,
QUESTION_TYPE.VOTE,
QUESTION_TYPE.MULTILEVEL,
QUESTION_TYPE.CASCADER,
];
const fieldList = responseSchema.code.dataConf.dataList
.filter((item) => allowQuestionType.includes(item.type as QUESTION_TYPE))
Expand Down
6 changes: 3 additions & 3 deletions server/src/modules/survey/services/dataStatistic.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ export class DataStatisticService {
}
// 将多级联动id还原成选项文案
if (
itemConfig.multilevelData &&
itemConfig.type === QUESTION_TYPE.MULTILEVEL
itemConfig.cascaderData &&
itemConfig.type === QUESTION_TYPE.CASCADER
) {
let optionTextMap = keyBy(itemConfig.multilevelData.children, 'hash');
let optionTextMap = keyBy(itemConfig.cascaderData.children, 'hash');
data[itemKey] = data[itemKey]
?.split(',')
.map((v) => {
Expand Down
4 changes: 2 additions & 2 deletions server/src/modules/survey/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,9 @@ export function handleAggretionData({ dataMap, item }) {
summary,
},
};
} else if (type == QUESTION_TYPE.MULTILEVEL) {
} else if (type == QUESTION_TYPE.CASCADER) {
const aggregation = getTextPaths(
dataMap[item.field].multilevelData.children,
dataMap[item.field].cascaderData.children,
);
return {
...item,
Expand Down
Binary file not shown.
6 changes: 3 additions & 3 deletions web/src/common/typeEnum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export enum QUESTION_TYPE {
RADIO_STAR = 'radio-star',
RADIO_NPS = 'radio-nps',
VOTE = 'vote',
MULTILEVEL = 'multilevel',
CASCADER = 'cascader',
}

// 题目类型标签映射对象
Expand All @@ -21,7 +21,7 @@ export const typeTagLabels: Record<QUESTION_TYPE, string> = {
[QUESTION_TYPE.RADIO_STAR]: '评分',
[QUESTION_TYPE.RADIO_NPS]: 'NPS评分',
[QUESTION_TYPE.VOTE]: '投票',
[QUESTION_TYPE.MULTILEVEL]: '多级联动'
[QUESTION_TYPE.CASCADER]: '多级联动'
}

// 输入类题型
Expand All @@ -42,4 +42,4 @@ export const CHOICES = [
export const RATES = [QUESTION_TYPE.RADIO_STAR, QUESTION_TYPE.RADIO_NPS]

// 高级题型分类
export const ADVANCED = [QUESTION_TYPE.MULTILEVEL]
export const ADVANCED = [QUESTION_TYPE.CASCADER]
12 changes: 6 additions & 6 deletions web/src/management/config/questionMenuConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ export const menuItems = {
icon: 'tixing-toupiao',
title: '投票'
},
multilevel: {
type: 'multilevel',
path: 'MultilevelModule',
snapshot: '/imgs/question-type-snapshot/multilevel.webp',
icon: 'multilevel-select',
cascader: {
type: 'cascader',
path: 'CascaderModule',
snapshot: '/imgs/question-type-snapshot/cascader.webp',
icon: 'cascader-select',
title: '多级联动'
}
}
Expand All @@ -74,7 +74,7 @@ const menuGroup = [
questionList: ['radio', 'checkbox', 'binary-choice', 'radio-star', 'radio-nps', 'vote']
}, {
title: '高级题型',
questionList: ['multilevel']
questionList: ['cascader']
}
]

Expand Down
138 changes: 138 additions & 0 deletions web/src/management/hooks/useCascaderPull.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { ElMessageBox } from 'element-plus'
import { ref } from 'vue'
import { cloneDeep } from 'lodash-es'

interface NodeItem {
hash: string,
text: string,
children?: NodeItem[],
}

type CascaderDate = {
placeholder: Array<{
hash: string,
text: string,
}>,
children: Array<NodeItem>,
}

export const useCascaderPull = () => {
const maxCount = 3;
const optionsCount = 50;
const cascaderVal = ref<Array<null | NodeItem>>([]);
const cascaderData = ref<CascaderDate | null>(null)
let hashArr: Array<string> = [];


const extractHash = (obj: CascaderDate): Array<string> => {
const hashes: Array<string> = [];

function recurse(currentObj: any) {
if (Array.isArray(currentObj)) {
currentObj.forEach(item => recurse(item));
} else if (typeof currentObj === 'object' && currentObj !== null) {
if (currentObj.hash) {
hashes.push(currentObj.hash);
}
for (const key in currentObj) {
// eslint-disable-next-line no-prototype-builtins
if (currentObj.hasOwnProperty(key as any)) {
recurse(currentObj[key]);
}
}
}
}

recurse(obj);
return hashes;
}

const getRandom = () => {
return Math.random().toString().slice(-6)
}

const getNewHash = () => {
let random = getRandom()
while (random in hashArr) {
random = getRandom()
}
hashArr.push(random)
return random
}

const addCascaderNode = (key: number) => {
const nodeItem: NodeItem = (key == 0 ? cascaderData.value : cascaderVal.value[key - 1]) as NodeItem
if (nodeItem.children && nodeItem.children.length > optionsCount) {
ElMessageBox.alert(`当前最多添加${optionsCount}个选项`, '提示', {
confirmButtonText: '确定',
type: 'warning'
})
return
}
const optionStr = `选项${nodeItem?.children ? nodeItem?.children?.length + 1 : 1}`
nodeItem.children?.push({
hash: getNewHash(),
text: optionStr,
children: []
})
}

const resetCascaderVal = (index: number) => {
for (let i = cascaderVal.value.length; index < i; i--) {
cascaderVal.value[i - 1] = null;
}
}

const removeCascaderNode = (nodeItem: NodeItem, index: number, key: number) => {
try {
if (key == 0 && cascaderData.value?.children && cascaderData.value?.children?.length<=1) {
ElMessageBox.alert('至少保留一个选项', '提示', {
confirmButtonText: '确定',
type: 'warning'
})
return
}
if (nodeItem.children) {
nodeItem.children[index].children = [];
}
nodeItem.children?.splice(index, 1)
resetCascaderVal(key)
} catch (error) {
console.log(error)
}
}

const editCascaderNode = (nodeItem: NodeItem, index: number, text: string) => {
nodeItem.children && (nodeItem.children[index].text = text)
}


const setCascaderVal = (data: NodeItem, index: number) => {
if (cascaderVal.value[index]?.hash == data.hash) return
resetCascaderVal(index)
cascaderVal.value[index] = data
}


const loadInitData = (data: CascaderDate) => {
cascaderData.value = cloneDeep(data);
cascaderVal.value = [];
for (let index = 0; index < maxCount; index++) {
cascaderVal.value.push(null)
}
hashArr = extractHash(cascaderData.value);
}



return {
addCascaderNode,
removeCascaderNode,
editCascaderNode,
loadInitData,
setCascaderVal,

cascaderVal,
cascaderData
}
}
58 changes: 29 additions & 29 deletions web/src/management/hooks/useMultilevelPull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@ interface NodeItem {
children?: NodeItem[],
}

type MultilevelDat = {
type CascaderDate = {
placeholder: Array<{
hash: string,
text: string,
}>,
children: Array<NodeItem>,
}

export const useMultilevelPull = () => {
export const useCascaderPull = () => {
const maxCount = 3;
const optionsCount = 50;
const multilevelVal = ref<Array<null | NodeItem>>([]);
const multilevelData = ref<MultilevelDat | null>(null)
const cascaderVal = ref<Array<null | NodeItem>>([]);
const cascaderData = ref<CascaderDate | null>(null)
let hashArr: Array<string> = [];


const extractHash = (obj: MultilevelDat): Array<string> => {
const extractHash = (obj: CascaderDate): Array<string> => {
const hashes: Array<string> = [];

function recurse(currentObj: any) {
Expand Down Expand Up @@ -60,8 +60,8 @@ export const useMultilevelPull = () => {
return random
}

const addMultilevelNode = (key: number) => {
const nodeItem: NodeItem = (key == 0 ? multilevelData.value : multilevelVal.value[key - 1]) as NodeItem
const addCascaderNode = (key: number) => {
const nodeItem: NodeItem = (key == 0 ? cascaderData.value : cascaderVal.value[key - 1]) as NodeItem
if (nodeItem.children && nodeItem.children.length > optionsCount) {
ElMessageBox.alert(`当前最多添加${optionsCount}个选项`, '提示', {
confirmButtonText: '确定',
Expand All @@ -77,15 +77,15 @@ export const useMultilevelPull = () => {
})
}

const resetMultilevelVal = (index: number) => {
for (let i = multilevelVal.value.length; index < i; i--) {
multilevelVal.value[i - 1] = null;
const resetCascaderVal = (index: number) => {
for (let i = cascaderVal.value.length; index < i; i--) {
cascaderVal.value[i - 1] = null;
}
}

const removeMultilevelNode = (nodeItem: NodeItem, index: number, key: number) => {
const removeCascaderNode = (nodeItem: NodeItem, index: number, key: number) => {
try {
if (key == 0 && multilevelData.value?.children && multilevelData.value?.children?.length<=1) {
if (key == 0 && cascaderData.value?.children && cascaderData.value?.children?.length<=1) {
ElMessageBox.alert('至少保留一个选项', '提示', {
confirmButtonText: '确定',
type: 'warning'
Expand All @@ -96,43 +96,43 @@ export const useMultilevelPull = () => {
nodeItem.children[index].children = [];
}
nodeItem.children?.splice(index, 1)
resetMultilevelVal(key)
resetCascaderVal(key)
} catch (error) {
console.log(error)
}
}

const editMultilevelNode = (nodeItem: NodeItem, index: number, text: string) => {
const editCascaderNode = (nodeItem: NodeItem, index: number, text: string) => {
nodeItem.children && (nodeItem.children[index].text = text)
}


const setMultilevelVal = (data: NodeItem, index: number) => {
if (multilevelVal.value[index]?.hash == data.hash) return
resetMultilevelVal(index)
multilevelVal.value[index] = data
const setCascaderVal = (data: NodeItem, index: number) => {
if (cascaderVal.value[index]?.hash == data.hash) return
resetCascaderVal(index)
cascaderVal.value[index] = data
}


const loadInitData = (data: MultilevelDat) => {
multilevelData.value = cloneDeep(data);
multilevelVal.value = [];
const loadInitData = (data: CascaderDate) => {
cascaderData.value = cloneDeep(data);
cascaderVal.value = [];
for (let index = 0; index < maxCount; index++) {
multilevelVal.value.push(null)
cascaderVal.value.push(null)
}
hashArr = extractHash(multilevelData.value);
hashArr = extractHash(cascaderData.value);
}



return {
addMultilevelNode,
removeMultilevelNode,
editMultilevelNode,
addCascaderNode,
removeCascaderNode,
editCascaderNode,
loadInitData,
setMultilevelVal,
setCascaderVal,

multilevelVal,
multilevelData
cascaderVal,
cascaderData
}
}
Loading

0 comments on commit 11d9c8c

Please sign in to comment.