Files
ylst-h5/src/views/Design/components/ActionCompoents/QuestionAction.vue
陈昱达 eb9f6aa7ed feat(component): 优化 contenteditable组件功能
- 添加 showAction 控制编辑按钮显示
- 实现文本域聚焦和失焦时的编辑按钮显示和隐藏
-优化键盘弹出和收起时的编辑按钮显示逻辑
-修复文档中描述的产品问卷配置- 优化问卷设计页面的题目编辑功能
2025-03-07 13:27:39 +08:00

259 lines
7.0 KiB
Vue

<template>
<div class="container question-action-container flex">
<van-icon name="clear" @click="deleteQuestion"></van-icon>
<van-icon name="setting" @click="openQuestionSettingModel"></van-icon>
<van-icon name="more" @click="openQuestionActionModel"></van-icon>
</div>
<!-- 操作项弹窗-->
<van-action-sheet v-model:show="show" title="">
<template #description>
<div class="flex flex-start">操作选项</div>
</template>
<van-cell-group :border="false" class="ml10">
<van-cell title="此题必答" :border="false" label-align="left">
<template #right-icon>
<van-switch
v-model="activeQuestion.config.is_required"
class="option-action-sheet-switch"
size="0.5rem"
:active-value="1"
:inactive-value="0"
></van-switch>
</template>
</van-cell>
<van-cell title="选项随机" :border="false">
<template #right-icon>
<van-switch
v-model="activeQuestion.config.select_random"
class="option-action-sheet-switch"
size="0.5rem"
:active-value="1"
:inactive-value="0"
></van-switch>
</template>
</van-cell>
<van-divider></van-divider>
<van-cell title="题前隐藏" :border="false" @click="questionSetting('before')">
<template #right-icon>
<span> {{ getSkipTypeText(1) }} <van-icon name="arrow"></van-icon></span>
</template>
</van-cell>
<van-cell title="题后跳转" :border="false" @click="questionSetting('after')">
<template #right-icon>
<span> {{ getSkipTypeText(0) }} <van-icon name="arrow"></van-icon></span>
</template>
</van-cell>
<van-divider></van-divider>
<!-- 根据不同题型 展示不同的操作-->
<checkbox-question-action
v-if="activeQuestion.question_type === 2"
v-model="activeQuestion"
></checkbox-question-action>
<rate-action
v-if="activeQuestion.question_type === 5"
:config="activeQuestion.config"
@update-config="updateConfig"
></rate-action>
</van-cell-group>
</van-action-sheet>
<!-- 移动 复制-->
<van-action-sheet
v-model:show="questionShow"
title=""
:actions="actions"
cancel-text="取消"
@select="questionMove"
>
<!-- <van-cell-group :border="false" class="ml10">-->
<!-- <van-cell title="下移题目" :border="false" @click="questionMove('down')"></van-cell>-->
<!-- <van-cell title="上移题目" :border="false" @click="questionMove('up')"></van-cell>-->
<!-- </van-cell-group>-->
</van-action-sheet>
<!-- 题目操作 题前 题后-->
<van-popup
v-model:show="questionBeforeShow"
:close-on-click-overlay="false"
title="题前隐藏逻辑"
label="题前隐藏逻辑"
position="bottom"
closeable
close-icon="close"
round
:style="{ minHeight: '50%', maxHeight: '75%' }"
>
<div class="mv10">
<header>
<strong>{{ skipType === 0 ? '题后跳转逻辑' : '题前隐藏逻辑' }}</strong>
</header>
<!-- 题前 题后逻辑 本来打算拆成两个 但是 只有最后的处理不一样-->
<div class="before-or-after">
<question-before :skipType="skipType" :activeQuestion="activeQuestion"></question-before>
</div>
</div>
</van-popup>
</template>
<script setup>
import checkboxQuestionAction from './components/QuestionItemAction/checkboxQuestionAction.vue';
import { showConfirmDialog } from 'vant';
import { ref } from 'vue';
import { useCounterStore } from '@/stores/counter';
import { storeToRefs } from 'pinia';
import QuestionBefore from '@/views/Design/components/ActionCompoents/components/QuestionItemAction/QuestionBefore.vue';
import RateAction from './components/RateAction.vue';
import { v4 as uuidv4 } from 'uuid';
const store = useCounterStore();
const { questionsInfo } = storeToRefs(store);
const logics = questionsInfo.value.logics;
const props = defineProps({
index: {
type: Number,
default: 0
},
data: {
type: Object,
default: () => {
// 传递
}
},
questions: {
type: Array,
default: () => []
},
questionIndex: {
type: Number,
default: 0
}
});
const questions = ref(props.questions);
// 当前题目
const activeQuestion = ref(props.data);
const show = ref(false);
const questionShow = ref(false);
const questionBeforeShow = ref(false);
const actions = [
{ name: '上移题目', action: 'up' },
{ name: '下移题目', action: 'down' },
{ name: '复制题目', action: 'copy' }
];
const deleteQuestion = () => {
showConfirmDialog({
title: '提示',
message: '是否删除问题?'
})
.then(() => {
// on confirm
questions.value.splice(props.questionIndex, 1);
})
.catch(() => {
// on cancel
});
};
// 打开题目弹窗
const openQuestionActionModel = () => {
show.value = true;
};
const openQuestionSettingModel = () => {
questionShow.value = true;
};
// 题目上下移动
const questionMove = (action) => {
if (action.action === 'down') {
if (props.questionIndex === questions.value.length - 1) {
return;
}
const temp = questions.value[props.questionIndex];
questions.value.splice(props.questionIndex, 1);
questions.value.splice(props.questionIndex + 1, 0, temp);
} else if (action.action === 'up') {
if (props.questionIndex === 0) {
return;
}
const temp = questions.value[props.questionIndex];
questions.value.splice(props.questionIndex, 1);
questions.value.splice(props.questionIndex - 1, 0, temp);
} else {
// 复制 题目 生成新的id 更新最新的 last index
const temp = questions.value[props.questionIndex];
questions.value.splice(props.questionIndex + 1, 0, {
...temp,
id: uuidv4(),
question_index: questionsInfo.value.survey.last_question_index + 1
});
questionsInfo.value.survey.last_question_index += 1;
}
};
const skipType = ref(-1);
// 获取题前隐藏 和题后 跳转 文字
const getSkipTypeText = (skipType) => {
const ls = [];
logics.map((item) => {
if (
item.skip_type === skipType
&& item.question_index === activeQuestion.value.question_index
) {
ls.push(item);
}
});
let text = '未设置';
if (ls.length > 0) {
text = `已配置 (${ls.length})`;
}
return text;
};
// 题前 题后逻辑配置
const questionSetting = (type) => {
switch (type) {
case 'before':
questionBeforeShow.value = true;
break;
case 'after':
questionBeforeShow.value = true;
break;
}
skipType.value = type === 'before' ? 1 : 0;
};
const updateConfig = (value) => {
activeQuestion.value.config = { ...value };
};
</script>
<style scoped lang="scss">
.ml10 {
margin-left: 10px;
}
.mv10 {
margin: 10px;
}
.before-or-after {
overflow: auto;
height: 500px;
}
.y-select {
min-width: 10vw;
//max-width: 90vw;
}
.question-action-container {
font-size: 20px;
& .van-icon + .van-icon {
margin-left: 5px;
}
}
</style>