Files
ylst-h5/src/views/Design/components/Questions/Choice.vue
Huangzhe 249bd9e318 fix: 修复多选排它异常
- 修复options 获取的数据源
2025-03-25 18:40:41 +08:00

220 lines
6.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<van-field
v-model="element.stem"
:label="element.stem"
:required="element.config.is_required === 1"
label-align="top"
class="contenteditable-question-title base-select"
>
<template #left-icon> {{ isPreview ? element.title : index + 1 }}. </template>
<template #label>
<contenteditable
v-model="element.stem"
className="contenteditable-label"
:active="active"
@blur="emitValue"
:errorMessage="errorMessage"
>
</contenteditable>
</template>
<template #input>
<template v-for="item /*optionIndex*/ in element.list ?? element.options" :key="item.id">
<van-radio-group v-if="element.question_type === 1" v-model="choiceValue">
<option-action
:data="isPreview ? item.options : item"
:active="active"
:is-preview="isPreview"
:question="element"
handle=".moverQues"
>
<template #item="{ element: it, index: itIndex }">
<div class="flex" style="flex-wrap: wrap; width: 100%">
<van-radio
:key="itIndex"
:name="it.option_index"
:label="it.label"
:disabled="it.disabled"
icon-size="0.45rem"
>
<!-- 自定义文本 -->
<template #default>
<div class="flex align-center van-cell">
<div class="flex" style="width: 100%; flex-wrap: wrap">
<contenteditable
v-model="it.option"
:className="active ? 'contenteditable-input' : ''"
:active="active"
>
<template #right-icon>
<div v-if="active" class="moverQues">
<van-icon class-prefix="mobilefont" name="option "></van-icon>
</div>
</template>
</contenteditable>
</div>
</div>
</template>
</van-radio>
<textarea class="other-input" type="text" v-if="it.is_other" style="width: 100%" />
</div>
</template>
</option-action>
</van-radio-group>
<van-checkbox-group
v-if="element.question_type === 2"
v-model="value"
shape="square"
@change="handleChange"
>
<option-action
:data="isPreview ? item.options : item"
handle=".moverQues"
:active="active"
:is-preview="isPreview"
:question="element"
>
<template #item="{ element: it, index: itIndex }">
<div class="flex" style="flex-wrap: wrap; width: 100%">
<van-checkbox
:key="itIndex"
:name="it.option_index"
:label="it.label"
:disabled="it.disabled"
icon-size="0.45rem"
>
<template #default>
<div class="flex align-center van-cell">
<div class="flex" style="width: 100%; flex-wrap: wrap">
<contenteditable
v-model="it.option"
:className="active ? 'contenteditable-input' : ''"
:active="active"
>
<template #right-icon>
<div v-if="active" class="moverQues">
<van-icon class-prefix="mobilefont" name="option "></van-icon>
</div>
</template>
</contenteditable>
</div>
</div>
</template>
</van-checkbox>
<textarea class="other-input" type="text" v-if="it.is_other" style="width: 100%" />
</div>
</template>
</option-action>
</van-checkbox-group>
</template>
</template>
</van-field>
</template>
<script setup>
import OptionAction from '@/views/Design/components/ActionCompoents/OptionAction.vue';
import { defineAsyncComponent } from 'vue';
// 是否是预览
const isPreview = defineModel('isPreview', { default: false, type: Boolean });
const choiceValue = defineModel('answer', { default: '', type: String });
const value = defineModel('checkboxAnswer', { default: [], type: Array });
const errorMessage = defineModel('errorMessage', { default: '', type: String });
const Contenteditable = defineAsyncComponent(() => import('@/components/contenteditable.vue'));
defineProps({
isPreview: {
type: Boolean,
default: false
},
active: {
type: Boolean,
default: false
},
index: {
default: ''
}
});
/**
* 题目
* @type {ModelRef<Object, string, Object, Object>}
*/
const element = defineModel('element', {
type: Object,
default: () => {
return {
stem: ''
};
}
});
/**
* 控制选项,如果新增排它项, 那么就直接重新取值
* 按理说是不是 watch 更加合理
* @param names {number[]} 选中的项
*/
function handleChange(names) {
const newOption = names[names.length - 1];
// 如果names 长度小于1直接返回不处理
if (names.length < 1) return;
let options;
try {
options = element.value.options[0].options ?? element.value.list[0];
} catch (e) {
options = element.value.options[0];
}
// 如果不存在 options 和 list 属性,直接返回
if (!options) return;
// 如果 names 里面有其他的排它项,就把排它项的值去除
for (const option of options) {
if (option.is_remove_other === 1 && newOption !== option.option_index) {
value.value = value.value.filter((item) => item !== option.option_index);
}
}
if (options[Number(newOption) - 1]?.is_remove_other === 1) {
value.value = [newOption];
}
}
const emit = defineEmits(['update:element']);
const emitValue = () => {
emit('update:element', element.value);
};
</script>
<style scoped lang="scss">
.base-select {
& .van-checkbox-group,
.van-radio-group {
width: 100%;
& .van-checkbox,
.van-radio {
width: 100%;
& ::v-deep .van-checkbox__label {
width: 100%;
}
& ::v-deep .van-radio__label {
width: 100%;
}
}
}
& .other-input {
width: 100%;
min-height: 89px;
margin-top: 4px;
margin-bottom: 10px;
padding: 12px;
border: 1px solid #f4f4f4;
border-radius: 5px;
outline: none;
}
}
</style>