244 lines
5.7 KiB
Vue
244 lines
5.7 KiB
Vue
<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>
|