Files
ylst-pc/src/views/Answer/questions/Question.vue
2022-10-26 10:39:41 +08:00

395 lines
10 KiB
Vue

<template>
<div class="question">
<!-- 高级题型不显示 -->
<div class="question-inner-wrapper" v-if="questionType <= 100">
<div class="title" :style="`color: ${themeColor.stemColor}`">
<span v-if="showTitle" class="question-inner-span" v-html="title"></span>
<div class="stem">
<rich-text :nodes="`${newTitle}${tip}`" isPreview />
</div>
</div>
<Remark
:title="title + '问题评论'"
:type="3"
:questionIndex="questionIndex"
v-if="!isAnswer"
style="margin-bottom: 22px;"
/>
</div>
<div v-if="error && questionType <= 100" class="error">{{ error }}</div>
<!-- -->
<slot />
</div>
</template>
<script>
import RichText from "@/components/RichText.vue";
import { computed, defineComponent, inject } from "vue";
import Remark from "../components/Remark/index.vue";
export default defineComponent({
components: { RichText, Remark },
props: {
// 标题
stem: {
type: String,
default: "",
},
title: {
type: String,
default: "",
},
// 标题
tip: {
type: String,
default: "",
},
// 错误
error: {
type: String,
default: "",
},
// 题型
questionType: {
type: Number,
default: 0,
},
// 题号
questionIndex: {
type: Number,
default: 0,
},
// 问卷列表
questions: {
type: Array,
default: () => [],
},
// 是否显示题号
showTitle: {
type: [Boolean, Number],
default: false,
},
// 是否移动端
isMobile: {
type: Boolean,
default: false,
},
// 是否答题模式
isAnswer: {
type: Boolean,
default: false,
},
},
setup(props) {
const themeColor = inject("themeColor"); // 主题颜色
const buttonColor = themeColor.value?.buttonColor; // 按钮颜色
const buttonTextColor = themeColor.value?.buttonTextColor; // 按钮文字颜色
const answerColor = themeColor.value?.answerColor || "#333333"; // 答案颜色
const answerColor30 = toRgba(answerColor, 0.3); // 背景颜色(透明度30s)
const answerColor10 = toRgba(answerColor, 0.1); // 背景颜色(透明度10)
const answerBorder = answerColor === "#333333" ? "#d9d9d9" : answerColor; // 边框颜色
const answerPlaceholder = toRgba(answerColor, 0.3); // placeholder颜色
// 16进制转rgba
function toRgba(color, opacity) {
return (
"rgba(" +
parseInt(color.substring(1, 3), 16) +
"," +
parseInt(color.substring(3, 5), 16) +
"," +
parseInt(color.substring(5, 7), 16) +
"," +
opacity +
")"
);
}
const newTitle = computed(() => {
let title = props.stem;
const matchArr = title.match(/(\[%cite\(.*?\)%\])/g) || [];
matchArr.forEach((matchValue) => {
const value = matchValue.replace("[%cite(", "").replace(")%]", "");
let replacement = ""; // 替换文本
// 查找引用问题
const question = props.questions.find((question) => {
// 矩阵题
if (question.question_type >= 8 && question.question_type <= 11) {
return question.title === value.split("_R")[0].split("_C")[0];
}
// 排序题
if (question.question_type === 16) {
return question.title === value.split("_A")[0];
}
return question.title === value;
});
if (question) {
let options = []; // 选项
question.list.forEach((list) => {
options = [...options, ...list.options];
});
if (question.answer) {
const { answer } = question;
if (question.question_type === 1) {
// 查找引用选项(单选)
const option = options.find((option) => option.option_key === Object.keys(answer)[0]);
if (answer[option.option_key] === "1") {
replacement = option.option;
} else {
replacement = answer[option.option_key];
}
} else if (
question.question_type === 2 &&
Object.keys(answer).length >= question.config.min_select
) {
// 查找引用选项(多选)
options.forEach((option) => {
if (answer[option.option_key] === "1") {
replacement += option.option;
} else if (answer[option.option_key]) {
replacement += answer[option.option_key];
}
});
} else if (question.question_type === 4) {
// 查找引用选项(填空)
replacement = answer.value;
} else if (question.question_type === 5 && options.length > 1) {
// 查找引用选项(打分)
options.forEach((option) => {
replacement += option.option;
});
} else if (question.question_type === 17) {
// 查找引用选项(恒定总和)
options.forEach((option) => {
replacement += option.option;
});
} else if (question.question_type >= 8 && question.question_type <= 11) {
// 查找引用选项(矩阵题)
// const val = value.split("_").reverse()[0];
// let row = [];
// let col = [];
// question.list.forEach((list) => {
// if (list.type === 1) {
// row = [...row, ...list.options];
// } else if (list.type === 2) {
// col = [...col, ...list.options];
// }
// });
// if (val[0] === "R") {
// col.forEach((colItem) => {
// replacement += colItem.option;
// });
// } else if (val[0] === "C") {
// row.forEach((rowItem) => {
// replacement += rowItem.option;
// });
// }
} else if (question.question_type === 16) {
// 查找引用选项(排序)
let optionKey;
const sort = value.split("_A")[1] * 1;
Object.keys(answer).forEach((key) => {
if (answer[key] === sort) {
optionKey = key;
}
});
const option = options.find((option) => option.option_key === optionKey);
replacement += option?.option || "";
}
}
}
title = title
.replace(`${matchValue}`, replacement)
.replaceAll("<p ", "<span ")
.replaceAll("<p>", "<span>")
.replaceAll("</p>", "</span>");
});
return title;
});
return {
newTitle,
buttonColor,
buttonTextColor,
themeColor,
answerColor,
answerColor30,
answerColor10,
answerBorder,
answerPlaceholder,
};
},
});
</script>
<style lang="scss" scoped>
.question {
.question-inner-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
}
.title {
flex: 1;
min-height: 24px;
margin-bottom: 24px;
display: flex;
> span {
flex-shrink: 0;
}
.stem {
flex: 1;
}
}
.error {
font-size: 12px;
color: #ff374f;
line-height: 20px;
margin: -22px 0 10px;
}
:deep(p) {
margin-bottom: 0;
}
}
// .question-inner-span {
// width: 100%;
// }
</style>
<style lang="scss" scoped>
:deep(.ant-radio-inner) {
border-color: v-bind(answerColor) !important;
background-color: transparent;
}
:deep(.ant-radio-inner::after) {
background-color: v-bind(answerColor);
}
:deep(.ant-checkbox-inner) {
border-color: v-bind(answerColor) !important;
background-color: transparent;
}
:deep(.ant-checkbox-checked .ant-checkbox-inner) {
background-color: v-bind(answerColor);
}
:deep(.ant-input) {
color: v-bind(answerColor);
border-color: v-bind(answerBorder) !important;
background-color: transparent;
}
:deep(.ant-input-number) {
color: v-bind(answerColor);
border-color: v-bind(answerBorder) !important;
background-color: transparent;
}
:deep(.ant-select-selector) {
color: v-bind(answerColor);
border-color: v-bind(answerBorder) !important;
background-color: transparent !important;
}
:deep(.ant-input:hover) {
border-color: v-bind(answerColor);
}
:deep(.ant-input::placeholder) {
color: v-bind(answerPlaceholder) !important;
}
:deep(.ant-select-selection-placeholder) {
color: v-bind(answerPlaceholder) !important;
}
// :deep(.ant-rate) {
// color: v-bind(answerColor) !important;
// }
// :deep(.ant-rate-star-zero .ant-rate-star-second) {
// color: v-bind(answerColor30);
// }
:deep(.num-item) {
color: v-bind(answerColor) !important;
border-color: v-bind(answerColor) !important;
}
:deep(.num-item-active) {
color: #fff !important;
border-color: v-bind(answerColor) !important;
background-color: v-bind(answerColor) !important;
}
// :deep(.num-item:hover) {
// color: #fff !important;
// border-color: v-bind(answerColor) !important;
// background-color: v-bind(answerColor) !important;
// }
:deep(.rich-rate-item-active) {
border-color: v-bind(answerColor) !important;
background-color: v-bind(answerColor) !important;
}
// :deep(.rich-rate-item:hover) {
// border-color: v-bind(answerColor) !important;
// background-color: v-bind(answerColor) !important;
// }
:deep(.step-inner) {
border-color: v-bind(answerColor) !important;
}
:deep(.ant-slider-track) {
background-color: v-bind(answerColor) !important;
}
:deep(.ant-slider-handle) {
border-color: v-bind(answerColor) !important;
}
:deep(.ant-slider-dot-active) {
border-color: v-bind(answerColor) !important;
}
:deep(.ant-slider-mark-text) {
color: v-bind(answerColor);
}
:deep(.ant-upload) {
border-color: v-bind(answerBorder) !important;
background-color: v-bind(answerColor10) !important;
}
:deep(.pfe-button) {
color: v-bind(buttonTextColor) !important;
background-color: v-bind(buttonColor) !important;
}
// 公共样式
:deep(.answer-color) {
color: v-bind(answerColor) !important;
}
:deep(.answer-border) {
border-color: v-bind(answerBorder) !important;
}
:deep(.answer-background30) {
background-color: v-bind(answerColor30) !important;
}
:deep(.answer-background10) {
background-color: v-bind(answerColor10) !important;
}
</style>