Files
ylst-pc/src/views/Answer/questions/QRadio.vue

244 lines
5.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>
<AnswerViewer :isMobile="isMobile" :config="config" :stem="stem" :answerSurveySn="answerSurveySn" :answerSn="answerSn" :question="question" :cartWaresLength="cartWaresLength"
@custom-next="$emit('next')" @custom-previous="$emit('previous')" @onHoldToCart="onHoldToCart">
<a-radio-group v-model:value="value" @change="changeValue" :disabled="disabled">
<div class="radio-group">
<div
class="radio"
v-for="option in options"
:key="option.option_key"
:style="isMobile ? 'width: 100%' : `width: calc(100% / ${(config.each_number || 1)} - 33px)`"
v-show="!hideOptions.includes(option.option_key)"
>
<a-radio :value="option.option_key" />
<div class="option scrollbar answer-color">
<rich-text :nodes="option.option" isPreview />
</div>
<a-input
v-if="option.is_other"
v-model:value="option.value"
@change="changeInput($event, option.option_key)"
/>
</div>
</div>
</a-radio-group>
</AnswerViewer>
</template>
<script>
import RichText from "@/components/RichText.vue";
import { computed, defineComponent, inject, ref, watch } from "vue";
import AnswerViewer from "./components/AnswerViewer";
export default defineComponent({
components: { RichText, AnswerViewer },
props: {
// 题干
stem: {
type: String,
default: "",
},
// 列表
list: {
type: Array,
default: () => [],
},
// 配置
config: {
type: Object,
default: () => {},
},
// 答案
answer: {
type: Object,
default: () => {},
},
// 隐藏选项
hideOptions: {
type: Array,
default: () => [],
},
// 是否禁用
disabled: {
type: Boolean,
default: false,
},
// 是否移动端
isMobile: {
type: Boolean,
default: false,
},
// 样本SN
answerSn: {
type: String,
default: ""
},
answerSurveySn: {
type: String,
default: ""
},
question: {
type: Object,
default: () => ({})
},
},
setup(props, context) {
const value = ref(""); // 值
const options = ref([]); // 选项
// 初始化
function init() {
props.list.forEach((list) => {
options.value = [...options.value, ...list.options];
});
sortOptions();
if (props.answer) {
value.value = Object.keys(props.answer)[0];
options.value.forEach((option) => {
if (option.is_other && option.option_key === value.value) {
option.value = props.answer[value.value];
}
});
}
}
init();
// 排序(其他项不参与随机)
function sortOptions() {
if (props.config.select_random) {
const common = [];
const others = [];
options.value.forEach((option) => {
if (option.is_other) {
others.push(option);
} else {
common.push(option);
}
});
options.value = common.concat(others);
}
}
// 选择回调
function changeValue(e) {
// 更新答案
const option = options.value.find((option) => option.option_key === e.target.value);
context.emit("update:answer", {
[e.target.value]: option.value || (option.is_other ? "" : "1"),
});
// 清空未选中项输入框值
options.value.forEach((option) => {
if (option.is_other && option.option_key !== e.target.value) {
option.value = "";
}
});
}
// 输入回调
function changeInput(e, key) {
value.value = key;
// 更新答案
context.emit("update:answer", { [key]: e.target.value });
}
// 监听答案
watch(
() => props.answer,
() => {
context.emit("changeAnswer", {
options: options.value,
value: value.value,
});
},
{
deep: true,
immediate: true,
}
);
// 监听list更新关联选项
watch(
() => props.list,
() => {
// 更新关联题选项
let newOptions = [];
props.list.forEach((list) => {
newOptions = [...newOptions, ...list.options];
});
// 其他项
newOptions.forEach((option) => {
if (option.is_other && option.option_key === value.value) {
const timer = setTimeout(() => {
option.value = props.answer[value.value];
clearTimeout(timer);
});
}
});
options.value = newOptions;
sortOptions();
// 清空值和答案
if (
value.value &&
options.value.findIndex((option) => option.option_key === value.value) === -1
) {
// 清空值
value.value = "";
// 清空答案
context.emit("update:answer", null);
}
},
{
deep: true,
}
);
const onHoldToCart = (target) => {
value.value = target.option_key;
changeValue({
target: {
value: target.option_key
}
});
}
const cartWaresLength = computed(() => {
if(!props.answer) return 0;
return Object.keys(props.answer).length;
});
return { value, options, changeValue, changeInput, onHoldToCart, cartWaresLength };
},
});
</script>
<style lang="scss" scoped>
.radio-group {
display: flex;
flex-wrap: wrap;
margin-bottom: -18px;
.radio {
display: flex;
align-items: center;
margin-bottom: 18px;
margin-right: 32px;
.option {
margin-right: 8px;
overflow: auto;
}
}
.ant-input {
width: 225px;
}
}
.ant-radio-group {
width: 100%;
}
</style>