refactor(api): 重命名 questionDetails 函数为 saveQuestions

- 将 questionDetails 函数重命名为 saveQuestions,以更好地反映其功能
- 保留了函数的原始逻辑,仅更改了名称
This commit is contained in:
陈昱达
2025-03-12 12:09:32 +08:00
parent 4f047b8b59
commit 5dd48c6a94
11 changed files with 2137 additions and 156 deletions

View File

@@ -19,7 +19,7 @@ export function sync(params) {
method: 'get' method: 'get'
}); });
} }
export function questionDetails(params) { export function saveQuestions(params) {
// let sn = params.sn; // let sn = params.sn;
// delete params.sn; // delete params.sn;
return request({ return request({

View File

@@ -17,7 +17,9 @@ export default {
_string2json(value) { _string2json(value) {
try { try {
value = JSON.parse(value); value = JSON.parse(value);
} catch (e) {} } catch (e) {
// 以后再说
}
return value; return value;
}, },

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,11 @@
:index="index" :index="index"
:chooseQuestionId="chooseQuestionId" :chooseQuestionId="chooseQuestionId"
@get-choose-question-id="getChooseQuestionId" @get-choose-question-id="getChooseQuestionId"
@move="emitFun.move"
@copy="emitFun.copy"
@delete="emitFun.delete"
@setting="emitFun.setting"
@logics="emitFun.logics"
> >
<!-- 选择题 --> <!-- 选择题 -->
<Choice <Choice
@@ -103,6 +108,8 @@
</div> </div>
</template> </template>
</choose-question> </choose-question>
<!-- 增加控制按钮-->
<slot name="button" :item="element"></slot>
<!-- {{ element.question_type }}--> <!-- {{ element.question_type }}-->
<!-- {{questionInfo.survey.pages.length}}--> <!-- {{questionInfo.survey.pages.length}}-->
@@ -121,9 +128,12 @@
</template> </template>
<script setup> <script setup>
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import * as Base64 from 'js-base64';
import { ref, onMounted, watch, computed } from 'vue'; import { ref, onMounted, watch, computed } from 'vue';
import { useCounterStore } from '@/stores/counter'; import { useCounterStore } from '@/stores/counter';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useRoute } from 'vue-router';
import { saveQuestion, sync } from '@/api/design/index.js';
import Draggable from './components/Draggable.vue'; import Draggable from './components/Draggable.vue';
import Choice from './components/Questions/Choice.vue'; import Choice from './components/Questions/Choice.vue';
import ChooseQuestion from './components/ChooseQuestion.vue'; import ChooseQuestion from './components/ChooseQuestion.vue';
@@ -135,9 +145,10 @@ import TextWithImages from '@/views/Design/components/Questions/TextWithImages.v
import SignQuestion from './components/Questions/SignQuestion.vue'; import SignQuestion from './components/Questions/SignQuestion.vue';
import FileUpload from './components/Questions/FileUpload.vue'; import FileUpload from './components/Questions/FileUpload.vue';
import NPS from '@/views/Design/components/Questions/NPS.vue'; import NPS from '@/views/Design/components/Questions/NPS.vue';
import { getPages } from '@/utils/public.js';
const activeIndex = ref(-1); const activeIndex = ref(-1);
const route = useRoute();
// 获取所有的 question 列表内容 // 获取所有的 question 列表内容
const { filterGap, activeId } = defineProps({ const { filterGap, activeId } = defineProps({
filterGap: { filterGap: {
@@ -295,6 +306,47 @@ const actionFun = {
} }
}; };
// emit 事件
const saveQueItem = (logics, questions, survey) => {
saveQuestion({
sn: route.query.sn,
data: {
logics: logics || [],
questions: questions || [],
survey: {
local_pages: [],
...survey,
pages: getPages(
questionInfo.value.questions,
questionInfo.value.survey.is_one_page_one_question
),
version: Base64.encode(`${new Date().getTime()}`)
}
}
}).then(() => {
sync({ sn: route.query.sn });
});
};
const emitFun = {
move: () => {
saveQueItem();
},
copy: (item) => {
saveQueItem(null, [item]);
},
delete: () => {
saveQueItem();
},
// 右下角操作
setting: (item) => {
saveQueItem(null, [item]);
},
logics: (item) => {
saveQueItem(questionInfo.value.logics, [item]);
}
};
onMounted(() => { onMounted(() => {
questionInfo.value = store.questionsInfo.value; questionInfo.value = store.questionsInfo.value;
}); });

View File

@@ -19,6 +19,7 @@
size="0.5rem" size="0.5rem"
:active-value="1" :active-value="1"
:inactive-value="0" :inactive-value="0"
@change="saveSettings"
></van-switch> ></van-switch>
</template> </template>
</van-cell> </van-cell>
@@ -34,6 +35,7 @@
size="0.5rem" size="0.5rem"
:active-value="1" :active-value="1"
:inactive-value="0" :inactive-value="0"
@change="saveSettings"
></van-switch> ></van-switch>
</template> </template>
</van-cell> </van-cell>
@@ -53,6 +55,7 @@
<checkbox-question-action <checkbox-question-action
v-if="activeQuestion.question_type === 2" v-if="activeQuestion.question_type === 2"
v-model="activeQuestion" v-model="activeQuestion"
@save-option="saveSettings"
></checkbox-question-action> ></checkbox-question-action>
<rate-action <rate-action
v-if="activeQuestion.question_type === 5" v-if="activeQuestion.question_type === 5"
@@ -86,6 +89,7 @@
close-icon="close" close-icon="close"
round round
:style="{ minHeight: '50%', maxHeight: '75%' }" :style="{ minHeight: '50%', maxHeight: '75%' }"
@close="saveLogics"
> >
<div class="mv10"> <div class="mv10">
<header> <header>
@@ -132,10 +136,19 @@ const props = defineProps({
} }
}); });
const questions = ref(props.questions); const questions = ref(props.questions);
// emit
const emit = defineEmits(['move', 'copy', 'delete', 'setting', 'logics']);
const saveSettings = () => {
emit('setting', activeQuestion.value);
};
const saveLogics = () => {
emit('logics', activeQuestion.value);
};
// 当前题目 // 当前题目
const activeQuestion = ref(props.data); const activeQuestion = ref(props.data);
// 设置更新
const show = ref(false); const show = ref(false);
const questionShow = ref(false); const questionShow = ref(false);
const questionBeforeShow = ref(false); const questionBeforeShow = ref(false);
@@ -151,7 +164,9 @@ const deleteQuestion = () => {
}) })
.then(() => { .then(() => {
// on confirm // on confirm
const index = props.questionIndex;
questions.value.splice(props.questionIndex, 1); questions.value.splice(props.questionIndex, 1);
emit('delete', index);
}) })
.catch(() => { .catch(() => {
// on cancel // on cancel
@@ -175,6 +190,8 @@ const questionMove = (action) => {
const temp = questions.value[props.questionIndex]; const temp = questions.value[props.questionIndex];
questions.value.splice(props.questionIndex, 1); questions.value.splice(props.questionIndex, 1);
questions.value.splice(props.questionIndex + 1, 0, temp); questions.value.splice(props.questionIndex + 1, 0, temp);
emit('move', 'down');
} else if (action.action === 'up') { } else if (action.action === 'up') {
if (props.questionIndex === 0) { if (props.questionIndex === 0) {
return; return;
@@ -182,15 +199,21 @@ const questionMove = (action) => {
const temp = questions.value[props.questionIndex]; const temp = questions.value[props.questionIndex];
questions.value.splice(props.questionIndex, 1); questions.value.splice(props.questionIndex, 1);
questions.value.splice(props.questionIndex - 1, 0, temp); questions.value.splice(props.questionIndex - 1, 0, temp);
emit('move', 'up');
} else { } else {
// 复制 题目 生成新的id 更新最新的 last index // 复制 题目 生成新的id 更新最新的 last index
const temp = questions.value[props.questionIndex]; const temp = questions.value[props.questionIndex];
questions.value.splice(props.questionIndex + 1, 0, {
const newQuestion = {
...temp, ...temp,
id: uuidv4(), id: uuidv4(),
question_index: questionsInfo.value.survey.last_question_index + 1 question_index: questionsInfo.value.survey.last_question_index + 1
}); };
questions.value.splice(props.questionIndex + 1, 0, newQuestion);
questionsInfo.value.survey.last_question_index += 1; questionsInfo.value.survey.last_question_index += 1;
emit('copy', newQuestion);
questionShow.value = false;
} }
}; };
@@ -230,6 +253,7 @@ const questionSetting = (type) => {
const updateConfig = (value) => { const updateConfig = (value) => {
activeQuestion.value.config = { ...value }; activeQuestion.value.config = { ...value };
saveSettings();
}; };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@@ -9,6 +9,7 @@
input-align="right" input-align="right"
class="action-field" class="action-field"
placeholder="不限" placeholder="不限"
@blur="emit('saveOption')"
@update:model-value=" @update:model-value="
(value) => { (value) => {
actionQuestion.config.min_select = Number(value); actionQuestion.config.min_select = Number(value);
@@ -27,6 +28,7 @@
placeholder="不限" placeholder="不限"
input-align="right" input-align="right"
class="action-field" class="action-field"
@blur="emit('saveOption')"
@update:model-value=" @update:model-value="
(value) => { (value) => {
actionQuestion.config.max_select = Number(value); actionQuestion.config.max_select = Number(value);
@@ -49,7 +51,7 @@ const props = defineProps({
} }
}); });
const emit = defineEmits(['update:modelValue']); const emit = defineEmits(['update:modelValue', 'saveOption']);
const actionQuestion = computed({ const actionQuestion = computed({
get() { get() {
return props.modelValue; return props.modelValue;

View File

@@ -21,6 +21,7 @@
class="question" class="question"
:options="beforeQuesOptions" :options="beforeQuesOptions"
placeholder="请选择问题" placeholder="请选择问题"
@change="getQuestionType"
></yl-select> ></yl-select>
<!-- 为空 不为空--> <!-- 为空 不为空-->
<yl-select <yl-select
@@ -180,31 +181,34 @@ skipOption.push(
); );
// 题目选项 // 题目选项
let optionOptions = []; let optionOptions = [];
// todo 不同题型逻辑对应不同 需要开发
const changeQuestionIndex = (value, logicItem) => { const changeQuestionIndex = (value, logicItem) => {
console.log(logicItem);
if (!value) { if (!value) {
return []; return [];
} }
beforeQuesOptions.map((item) => { beforeQuesOptions.map((item) => {
if (item.question_index === value) { if (item.question_index === value) {
if (logicItem.is_option_group === 0) { if ([1, 2].includes(logicItem.question_type)) {
optionOptions = item.options[0].map((optItem) => { if (logicItem.is_option_group === 0) {
return { optionOptions = item.options[0].map((optItem) => {
...optItem, return {
label: optItem.option, ...optItem,
value: optItem.option_index label: optItem.option,
}; value: optItem.option_index
}); };
} else if (logicItem.is_option_group === 1) { });
optionOptions = item.config.option_groups.option_group.map((groupItem) => { } else if (logicItem.is_option_group === 1) {
return { optionOptions = item.config.option_groups.option_group.map((groupItem) => {
...groupItem, return {
label: groupItem.title, ...groupItem,
value: groupItem.group_index label: groupItem.title,
}; value: groupItem.group_index
}); };
} else { });
optionOptions = []; } else {
optionOptions = [];
}
} }
} }
}); });
@@ -229,7 +233,7 @@ const addLogicItem = (logIndex, item) => {
item.splice(logIndex + 1, 0, { item.splice(logIndex + 1, 0, {
logic: 'and', logic: 'and',
question_index: '', question_index: '',
question_type: '', question_type: 0,
is_answer: 1, is_answer: 1,
operator: '=', operator: '=',
option_index: '', option_index: '',
@@ -245,28 +249,16 @@ const addLogic = () => {
logics.value.push({ logics.value.push({
logic: [ logic: [
{ {
value: '',
location: 0,
date: '',
time: '',
type: 0, type: 0,
row_type: 0,
cell_type: 0,
logic: 'if', logic: 'if',
operator: '=', operator: '=',
is_answer: 1, is_answer: 1,
is_select: 0, question_type: 0,
row_index: 0, question_index: 0,
cell_index: 0,
question_type: '',
question_index: '',
relation_question_index: 0, relation_question_index: 0,
relation_question_row_index: 0, relation_question_row_index: 0,
relation_question_cell_index: 0, relation_question_cell_index: 0,
is_option_group: '', option_index: 0
option_index: '',
skip_type: null,
question_id: null
} }
], ],
skip_type: props.skipType, skip_type: props.skipType,
@@ -323,6 +315,12 @@ const symbolOptions = [
} }
]; ];
const getQuestionType = (value) => {
console.log(beforeQuesOptions);
const type = beforeQuesOptions.filter((item) => item.question_index === value)[0];
console.log(type);
};
const logicIf = (value, index) => { const logicIf = (value, index) => {
if (value === 'always') { if (value === 'always') {
logics.value[index].logic = [logics.value[index].logic[0]]; logics.value[index].logic = [logics.value[index].logic[0]];

View File

@@ -17,20 +17,13 @@
v-model:data="element" v-model:data="element"
:questions="questions" :questions="questions"
:questionIndex="index" :questionIndex="index"
@move="emit('move', $event)"
@copy="emit('copy', $event)"
@delete="emit('delete', $event)"
@setting="emit('setting', $event)"
@logics="emit('logics', $event)"
></question-action> ></question-action>
</template> </template>
<!-- <div-->
<!-- v-for="item in questionAction"-->
<!-- :key="item.key"-->
<!-- class=""-->
<!-- :class="item.class ? item.class : ''"-->
<!-- @click="itemAction(item)"-->
<!-- >-->
<!-- <i class="icon iconfont choose-question-active-container-icon" v-html="item.icon"></i>-->
<!-- <div class="choose-question-active-container-name">-->
<!-- {{ item.name }}-->
<!-- </div>-->
<!-- </div>-->
</van-cell> </van-cell>
</div> </div>
</div> </div>
@@ -59,70 +52,14 @@ const props = defineProps({
} }
}); });
const element = ref(props.element); const element = ref(props.element);
// 选中题目后出现的操作 // 选中题目后出现的操作
// const questionAction = ref([ const emit = defineEmits(['getChooseQuestionId', 'move', 'copy']);
// {
// icon: '&#xe630;',
// name: '编辑',
// key: 'edit',
// class: ''
// },
// {
// icon: '&#xe632;',
// name: '复制',
// key: 'copy',
// class: ''
// },
// {
// icon: '&#xe6a0;',
// name: '移动',
// key: 'moveUp',
// class: 'moverQues'
// },
// // {
// // icon:'',
// // name:'下移',
// // key:'moveDown',
// // class:''
// // },
// {
// icon: '&#xe63f;',
// name: '删除',
// key: 'delete',
// class: ''
// }
// ]);
const emit = defineEmits(['getChooseQuestionId']);
// 选中题目 // 选中题目
const chooseItem = () => { const chooseItem = () => {
// 使用从 defineProps 接收的 element 对象 // 使用从 defineProps 接收的 element 对象
emit('getChooseQuestionId', props.element); emit('getChooseQuestionId', props.element);
}; };
// const itemAction = (item) => {
// switch (item.key) {
// case 'edit':
// // vue router跳转到/edit
//
// router.push({
// path: '/design/edit',
// query: {
// id: props.element.id
// }
// });
// break;
// case 'copy':
// break;
// case 'moveUp':
// break;
// case 'moveDown':
// break;
// case 'delete':
// break;
// }
// };
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.choose-question-container { .choose-question-container {

View File

@@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
// import { ref } from 'vue'; // import { ref } from 'vue';
import { consoleSurveys } from '@/api/home/index.js'; import { consoleSurveys } from '@/api/home/index.js';
import { snQuestions, questionDetails } from '@/api/design/index.js'; import { snQuestions, saveQuestions } from '@/api/design/index.js';
import { surveys } from './Hooks/useRequestHooks'; import { surveys } from './Hooks/useRequestHooks';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useCounterStore } from '@/stores/counter'; import { useCounterStore } from '@/stores/counter';
@@ -11,14 +11,6 @@ const counterStore = useCounterStore();
const store = storeToRefs(counterStore); const store = storeToRefs(counterStore);
const router = useRouter(); const router = useRouter();
// const surveys = ref([]);
//
// getQuestionList({}).then((res) => {
// console.log(res.data.data);
// surveys.value = res.data.data;
// });
console.log(surveys);
const createdQuestion = (item) => { const createdQuestion = (item) => {
const query = { const query = {
@@ -35,7 +27,7 @@ const createdQuestion = (item) => {
if (ques.data) { if (ques.data) {
ques.data.data.survey.introduction = `<p>为优化活动服务品质,烦请完成问卷,感谢配合!您的反馈至关重要!(此提示语为默认提示语,您可选择自行输入本问卷的提示语)</p>`; ques.data.data.survey.introduction = `<p>为优化活动服务品质,烦请完成问卷,感谢配合!您的反馈至关重要!(此提示语为默认提示语,您可选择自行输入本问卷的提示语)</p>`;
store.questionsInfo.value = ques.data.data; store.questionsInfo.value = ques.data.data;
questionDetails({ saveQuestions({
sn: res.data.data.sn, sn: res.data.data.sn,
introduction: ques.data.data.survey.introduction, introduction: ques.data.data.survey.introduction,
title: ques.data.data.survey.title title: ques.data.data.survey.title

View File

@@ -25,17 +25,23 @@
></contenteditable> ></contenteditable>
</div> </div>
<button v-if="questionInfo.questions.length === 0" @click="show = true">添加题目</button> <van-button v-if="questionInfo.questions.length === 0" size="small" @click="show = true">
添加题目
</van-button>
</div> </div>
</van-cell-group> </van-cell-group>
<div class="ques"> <div class="ques">
<!-- 题目--> <!-- 题目-->
<Design <Design :active-id="activeId" class="design" @get-active-question="getActiveQuestion">
:active-id="activeId" <template #button="{ item }">
class="desgin" <div class="design-button">
@get-active-question="getActiveQuestion" <van-button v-if="activeId === item.id" size="small" @click="show = true">
></Design> 添加题目
</van-button>
</div>
</template>
</Design>
<!-- <van-button @click="show = true">添加题目</van-button>--> <!-- <van-button @click="show = true">添加题目</van-button>-->
<!-- 弹出的新增题目弹窗--> <!-- 弹出的新增题目弹窗-->
<van-popup <van-popup
@@ -74,9 +80,9 @@
<span>投放设置</span> <span>投放设置</span>
</div> </div>
<div class="survey-action_btn"> <div class="survey-action_btn">
<van-button size="small">预览</van-button> <van-button size="small" @click="previewQuestion">预览</van-button>
<van-button size="small">保存</van-button> <van-button size="small" @click="saveAs">保存</van-button>
<van-button size="small" @click="$router.push({ name: 'publish' })">投放</van-button> <van-button size="small" @click="publishQuestion">投放</van-button>
</div> </div>
</div> </div>
</div> </div>
@@ -96,6 +102,7 @@
size="0.5rem" size="0.5rem"
:active-value="1" :active-value="1"
:inactive-value="0" :inactive-value="0"
@change="saveIsOnePage"
></van-switch> ></van-switch>
</template> </template>
</van-cell> </van-cell>
@@ -281,7 +288,7 @@ import { ref, computed, onMounted, watch } from 'vue';
import * as Base64 from 'js-base64'; import * as Base64 from 'js-base64';
import { import {
getSetting, getSetting,
questionDetails, saveQuestions,
saveQuestion, saveQuestion,
snQuestions, snQuestions,
sync, sync,
@@ -302,8 +309,9 @@ import {
signQuestion, signQuestion,
nps nps
} from '@/utils/importJsons'; } from '@/utils/importJsons';
import { useRoute } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import YLPicker from '@/components/YLPicker.vue'; import YLPicker from '@/components/YLPicker.vue';
import { getPages } from '@/utils/public';
// 获取 Store 实例 // 获取 Store 实例
const counterStore = useCounterStore(); const counterStore = useCounterStore();
@@ -314,6 +322,7 @@ const activeQuestionIndex = ref(-1);
const currentDate = ref(); const currentDate = ref();
const currentType = ref(); const currentType = ref();
const route = useRoute(); const route = useRoute();
const router = useRouter();
const surveyTitle = route.meta.title as string; const surveyTitle = route.meta.title as string;
const show = ref(false); const show = ref(false);
// const textModel = ref(false); // const textModel = ref(false);
@@ -344,6 +353,7 @@ const onConfirmDate = (e) => {
// 获取选中的题目 // 获取选中的题目
const getActiveQuestion = (activeQues) => { const getActiveQuestion = (activeQues) => {
chooseQuestionId.value = activeQues.id; chooseQuestionId.value = activeQues.id;
activeId.value = activeQues.id;
// 在questions 里 查找index 给 activeQuestionIndex // 在questions 里 查找index 给 activeQuestionIndex
questionInfo.value.questions.forEach((item, index) => { questionInfo.value.questions.forEach((item, index) => {
if (item.id === activeQues.id) { if (item.id === activeQues.id) {
@@ -353,7 +363,7 @@ const getActiveQuestion = (activeQues) => {
}; };
const saveTitle = () => { const saveTitle = () => {
questionDetails({ saveQuestions({
sn: route.query.sn, sn: route.query.sn,
title: questionInfo.value.survey.title, title: questionInfo.value.survey.title,
introduction: questionInfo.value.survey.introduction introduction: questionInfo.value.survey.introduction
@@ -482,9 +492,10 @@ const saveQuestionItem = (questionJson) => {
questions: [questionJson], questions: [questionJson],
survey: { survey: {
local_pages: [], local_pages: [],
pages: questionInfo.value.questions.map((item) => { pages: getPages(
return [item.question_index]; questionInfo.value.questions,
}), questionInfo.value.survey.is_one_page_one_question
),
version: Base64.encode(`${new Date().getTime()}`) version: Base64.encode(`${new Date().getTime()}`)
} }
} }
@@ -520,6 +531,13 @@ const saveSetting = (parentKey, childKeys) => {
}); });
}; };
// 保存是否每页一题
const saveIsOnePage = () => {
saveQuestions({
sn: route.query.sn,
is_one_page_one_question: questionInfo.value.survey.is_one_page_one_question
});
};
const init = () => { const init = () => {
// event.detail 为当前输入的值 // event.detail 为当前输入的值
show.value = true; show.value = true;
@@ -565,6 +583,20 @@ watch(
}, },
{ deep: true } { deep: true }
); );
// 保存 目前没有任何逻辑可以执行所有保存
const saveAs = () => {
// 保存所有
};
// 投放
const publishQuestion = () => {
router.push({ name: 'publish', query: { ...route.query } });
};
// 预览
const previewQuestion = () => {
router.push({ name: 'preview', query: { ...route.query } });
};
onMounted(async() => { onMounted(async() => {
await getQuestionDetail(); // 等待接口返回数据 await getQuestionDetail(); // 等待接口返回数据
}); });
@@ -598,8 +630,10 @@ onMounted(async() => {
& > button { & > button {
margin: 20px; margin: 20px;
border-radius: 10px;
background-color: lightgreen; //border-radius: 10px;
background-color: #70b936;
color: #fff;
} }
} }
} }
@@ -624,8 +658,21 @@ onMounted(async() => {
font-size: 16px; font-size: 16px;
} }
& .desgin { & .design {
padding-bottom: 50px; padding-bottom: 60px;
& .design-button {
width: 100%;
text-align: center;
::v-deep .van-button {
background-color: #70b936;
//width: 140px;
color: #fff;
font-size: 12px;
}
}
} }
.ques_list { .ques_list {

View File

@@ -42,8 +42,7 @@
height: 50px; height: 50px;
background-color: white; background-color: white;
" "
> ></div>
</div>
</div> </div>
</template> </template>
@@ -77,7 +76,7 @@ onMounted(async() => {
}); });
// 分享链接 // 分享链接
const shareLink = () => { const shareLink = () => {
const url = window.location.href; // const url = window.location.href;
const params = { const params = {
type: 'shareToWx', type: 'shareToWx',
title: '分享标题', title: '分享标题',