|
|
@@ -45,9 +45,55 @@
|
|
|
</template>
|
|
|
</view>
|
|
|
|
|
|
+ <view v-if="field.quizResults.length" class="task-detail-field__quizzes">
|
|
|
+ <view
|
|
|
+ v-for="(quiz, quizIndex) in field.quizResults"
|
|
|
+ :key="`${quiz.name}-${quizIndex}`"
|
|
|
+ class="quiz-result"
|
|
|
+ >
|
|
|
+ <view class="quiz-result__header">
|
|
|
+ <view class="quiz-result__icon">
|
|
|
+ <view class="quiz-result__icon-line quiz-result__icon-line--short" />
|
|
|
+ <view class="quiz-result__icon-line" />
|
|
|
+ <view class="quiz-result__icon-line" />
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="quiz-result__heading">
|
|
|
+ <text class="quiz-result__title">{{ quiz.name }}</text>
|
|
|
+ <text class="quiz-result__count">共 {{ quiz.questions.length }} 题</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view v-if="quiz.questions.length" class="quiz-result__questions">
|
|
|
+ <view
|
|
|
+ v-for="(question, questionIndex) in quiz.questions"
|
|
|
+ :key="`${questionIndex}-${question.question}`"
|
|
|
+ class="quiz-result__question"
|
|
|
+ >
|
|
|
+ <text class="quiz-result__number">{{ questionIndex + 1 }}</text>
|
|
|
+
|
|
|
+ <view class="quiz-result__question-main">
|
|
|
+ <text class="quiz-result__question-title">{{ question.question }}</text>
|
|
|
+ <view class="quiz-result__answer">
|
|
|
+ <text class="quiz-result__answer-label">作答</text>
|
|
|
+ <text
|
|
|
+ class="quiz-result__answer-value"
|
|
|
+ :class="{ 'quiz-result__answer-value--empty': !question.answered }"
|
|
|
+ >
|
|
|
+ {{ question.answer }}
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view v-else class="quiz-result__empty">暂无答题记录</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
<view v-if="field.text" class="task-detail-field__text">{{ field.text }}</view>
|
|
|
<view
|
|
|
- v-else-if="!field.attachments.length"
|
|
|
+ v-else-if="!field.attachments.length && !field.quizResults.length"
|
|
|
class="task-detail-field__text task-detail-field__text--empty"
|
|
|
>
|
|
|
-
|
|
|
@@ -71,11 +117,13 @@ import type {
|
|
|
} from '@/services/modules/task/taskFrom/type'
|
|
|
|
|
|
import { toFullUrl } from '../utils'
|
|
|
+import { parseQuizResult } from './quizResult'
|
|
|
import TaskDetailSummary from './TaskDetailSummary.vue'
|
|
|
|
|
|
const IMAGE_FIELD_TYPES = new Set(['img', 'sign'])
|
|
|
const IMAGE_AND_FILE_FIELD_TYPE = 'imgandfile'
|
|
|
const FILE_URL_FIELD_TYPE = 'fileurl'
|
|
|
+const QUIZ_FIELD_TYPE = 'quiz'
|
|
|
const DICT_FIELD_TYPES = new Set(['select', 'domain', 'multiple_select'])
|
|
|
const FILE_EXTENSIONS = new Set(['pdf', 'ppt', 'pptx'])
|
|
|
const IMAGE_EXTENSIONS = new Set([
|
|
|
@@ -167,6 +215,7 @@ const dictLabelsByField = computed(() => {
|
|
|
* 其余情况在 item.label 为空时用 value 回显。
|
|
|
* img、sign 类型转成图片列表;imgAndFile 根据值末尾来源标记转成图片或文件;
|
|
|
* fileurl 解析 value 中的 JSON 数组,取 url 和 fileName 展示附件,仅图片后缀使用图片预览;
|
|
|
+ * quiz 反序列化 value 并展示问卷名称、问题和答案,解析失败时保留原始 value 回显;
|
|
|
* 其余类型显示标准化后的 label。
|
|
|
*/
|
|
|
const contentFields = computed(() => {
|
|
|
@@ -179,6 +228,9 @@ const contentFields = computed(() => {
|
|
|
const items = field.items.map((item) => ({
|
|
|
...item,
|
|
|
label: resolveItemLabel(name, item),
|
|
|
+ quizResult: isQuizFieldType(item.type)
|
|
|
+ ? parseQuizResult(item.value, item.label?.trim() || name)
|
|
|
+ : null,
|
|
|
}))
|
|
|
const attachments = items.flatMap((item) => {
|
|
|
if (isFileUrlFieldType(item.type)) {
|
|
|
@@ -205,12 +257,14 @@ const contentFields = computed(() => {
|
|
|
const imageUrls = uniqueAttachments
|
|
|
.filter((attachment) => attachment.type === 'image')
|
|
|
.map((attachment) => attachment.url)
|
|
|
+ const quizResults = items.flatMap((item) => (item.quizResult ? [item.quizResult] : []))
|
|
|
const text = items
|
|
|
.filter(
|
|
|
(item) =>
|
|
|
!isImageFieldType(item.type) &&
|
|
|
!isImageAndFileFieldType(item.type) &&
|
|
|
- !isFileUrlFieldType(item.type)
|
|
|
+ !isFileUrlFieldType(item.type) &&
|
|
|
+ !item.quizResult
|
|
|
)
|
|
|
.map((item) => item.label)
|
|
|
.filter(Boolean)
|
|
|
@@ -222,6 +276,7 @@ const contentFields = computed(() => {
|
|
|
required: field.required,
|
|
|
attachments: uniqueAttachments,
|
|
|
imageUrls,
|
|
|
+ quizResults,
|
|
|
text,
|
|
|
}
|
|
|
})
|
|
|
@@ -259,6 +314,10 @@ const isFileUrlFieldType = (type: string): boolean => {
|
|
|
return type.trim().toLowerCase() === FILE_URL_FIELD_TYPE
|
|
|
}
|
|
|
|
|
|
+const isQuizFieldType = (type: string): boolean => {
|
|
|
+ return type.trim().toLowerCase() === QUIZ_FIELD_TYPE
|
|
|
+}
|
|
|
+
|
|
|
const parseFileUrlAttachments = (value: string): DetailAttachment[] => {
|
|
|
try {
|
|
|
const files: unknown = JSON.parse(value)
|
|
|
@@ -523,6 +582,170 @@ const showFileMessage = (title: string): void => {
|
|
|
margin-top: 18rpx;
|
|
|
}
|
|
|
|
|
|
+.task-detail-field__quizzes {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 18rpx;
|
|
|
+ margin-top: 18rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result {
|
|
|
+ overflow: hidden;
|
|
|
+ border: 1rpx solid #e6eef8;
|
|
|
+ border-radius: 18rpx;
|
|
|
+ background: #fff;
|
|
|
+ box-shadow: 0 8rpx 24rpx rgba(44, 112, 181, 0.07);
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 18rpx;
|
|
|
+ padding: 22rpx 24rpx;
|
|
|
+ background: linear-gradient(135deg, #f2f8ff 0%, #f8fbff 54%, #eef7ff 100%);
|
|
|
+ border-bottom: 1rpx solid #e5eef8;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__icon {
|
|
|
+ display: flex;
|
|
|
+ flex-shrink: 0;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ gap: 6rpx;
|
|
|
+ width: 54rpx;
|
|
|
+ height: 54rpx;
|
|
|
+ padding: 0 13rpx;
|
|
|
+ background: linear-gradient(145deg, #4cacfa, #2788e7);
|
|
|
+ border-radius: 15rpx;
|
|
|
+ box-shadow: 0 7rpx 14rpx rgba(39, 136, 231, 0.2);
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__icon-line {
|
|
|
+ width: 28rpx;
|
|
|
+ height: 4rpx;
|
|
|
+ background: rgba(255, 255, 255, 0.94);
|
|
|
+ border-radius: 3rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__icon-line--short {
|
|
|
+ width: 19rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__heading {
|
|
|
+ display: flex;
|
|
|
+ min-width: 0;
|
|
|
+ flex: 1;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 16rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__title {
|
|
|
+ overflow: hidden;
|
|
|
+ color: #1c344f;
|
|
|
+ font-size: 29rpx;
|
|
|
+ font-weight: 650;
|
|
|
+ line-height: 42rpx;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__count {
|
|
|
+ flex-shrink: 0;
|
|
|
+ padding: 5rpx 14rpx;
|
|
|
+ color: #3188d9;
|
|
|
+ font-size: 20rpx;
|
|
|
+ line-height: 30rpx;
|
|
|
+ background: rgba(59, 155, 237, 0.1);
|
|
|
+ border-radius: 20rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__questions {
|
|
|
+ padding: 0 24rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__question {
|
|
|
+ display: flex;
|
|
|
+ gap: 18rpx;
|
|
|
+ padding: 24rpx 0;
|
|
|
+ border-bottom: 1rpx solid #edf2f7;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__question:last-child {
|
|
|
+ border-bottom: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__number {
|
|
|
+ display: flex;
|
|
|
+ flex-shrink: 0;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 42rpx;
|
|
|
+ height: 42rpx;
|
|
|
+ color: #fff;
|
|
|
+ font-size: 22rpx;
|
|
|
+ font-weight: 650;
|
|
|
+ line-height: 42rpx;
|
|
|
+ text-align: center;
|
|
|
+ background: #3b9bed;
|
|
|
+ border-radius: 50%;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__question-main {
|
|
|
+ min-width: 0;
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__question-title {
|
|
|
+ display: block;
|
|
|
+ color: #1e293b;
|
|
|
+ font-size: 27rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ line-height: 40rpx;
|
|
|
+ word-break: break-all;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__answer {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ gap: 12rpx;
|
|
|
+ margin-top: 12rpx;
|
|
|
+ padding: 14rpx 16rpx;
|
|
|
+ background: #f7f9fc;
|
|
|
+ border-radius: 12rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__answer-label {
|
|
|
+ flex-shrink: 0;
|
|
|
+ padding: 2rpx 10rpx;
|
|
|
+ color: #3b82c4;
|
|
|
+ font-size: 20rpx;
|
|
|
+ line-height: 30rpx;
|
|
|
+ background: #e7f2fc;
|
|
|
+ border-radius: 8rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__answer-value {
|
|
|
+ min-width: 0;
|
|
|
+ color: #314158;
|
|
|
+ font-size: 25rpx;
|
|
|
+ line-height: 34rpx;
|
|
|
+ white-space: pre-wrap;
|
|
|
+ word-break: break-all;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__answer-value--empty {
|
|
|
+ color: #9aa6b5;
|
|
|
+}
|
|
|
+
|
|
|
+.quiz-result__empty {
|
|
|
+ padding: 36rpx 24rpx;
|
|
|
+ color: #9aa6b5;
|
|
|
+ font-size: 24rpx;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+
|
|
|
.task-detail-field__image {
|
|
|
width: 196rpx;
|
|
|
height: 196rpx;
|