提交 5100075e authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 c6ef9ea4
...@@ -94,18 +94,20 @@ const handlePreview: UploadProps['onPreview'] = uploadFile => { ...@@ -94,18 +94,20 @@ const handlePreview: UploadProps['onPreview'] = uploadFile => {
:file-list="fileList" :file-list="fileList"
class="uploader" class="uploader"
> >
<template v-if="showFileList"> <slot>
<template v-if="$attrs['list-type'] === 'picture-card'"> <template v-if="showFileList">
<el-icon><Plus /></el-icon> <template v-if="$attrs['list-type'] === 'picture-card'">
<el-icon><Plus /></el-icon>
</template>
<template v-else>
<el-button type="primary" round>点击上传</el-button>
</template>
</template> </template>
<template v-else> <div class="avatar-uploader" v-else>
<el-button type="primary" round>点击上传</el-button> <el-image :src="(modelValue as string)" fit="contain" v-if="modelValue" />
</template> <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</template> </div>
<div class="avatar-uploader" v-else> </slot>
<el-image :src="(modelValue as string)" fit="contain" v-if="modelValue" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</div>
<template #tip> <template #tip>
<div class="el-upload__tip"><slot name="tip"></slot></div> <div class="el-upload__tip"><slot name="tip"></slot></div>
</template> </template>
...@@ -140,4 +142,9 @@ const handlePreview: UploadProps['onPreview'] = uploadFile => { ...@@ -140,4 +142,9 @@ const handlePreview: UploadProps['onPreview'] = uploadFile => {
height: 100%; height: 100%;
text-align: center; text-align: center;
} }
.suggestion-file {
display: inline-block;
margin-top: 10px;
color: blue;
}
</style> </style>
...@@ -66,10 +66,14 @@ function handleSubmit() { ...@@ -66,10 +66,14 @@ function handleSubmit() {
paper_id: paperId, paper_id: paperId,
type, type,
question: JSON.stringify(genSubmitQuestion(questionList)) question: JSON.stringify(genSubmitQuestion(questionList))
}).then(() => {
ElMessage.success('提交成功')
emit('update')
}) })
.then(() => {
ElMessage.success('提交成功')
emit('update')
})
.catch(() => {
submitLoading = false
})
} }
// 自动提交 // 自动提交
function handleAutoSubmit() { function handleAutoSubmit() {
...@@ -112,7 +116,7 @@ function genSubmitQuestion(questionList: PaperQuestionType[]) { ...@@ -112,7 +116,7 @@ function genSubmitQuestion(questionList: PaperQuestionType[]) {
<div class="course-exam-card-bd"> <div class="course-exam-card-bd">
<div class="course-exam-left"> <div class="course-exam-left">
<div class="course-exam-scroll"> <div class="course-exam-scroll">
<CourseExamQuestion :question="currentQuestion" :index="questionIndex + 1"> <CourseExamQuestion :question="currentQuestion" :status="status" :index="questionIndex + 1">
<template #index>{{ questionIndex + 1 }}/{{ questionLength }}</template> <template #index>{{ questionIndex + 1 }}/{{ questionLength }}</template>
</CourseExamQuestion> </CourseExamQuestion>
</div> </div>
...@@ -125,7 +129,7 @@ function genSubmitQuestion(questionList: PaperQuestionType[]) { ...@@ -125,7 +129,7 @@ function genSubmitQuestion(questionList: PaperQuestionType[]) {
</div> </div>
<div class="course-exam-right"> <div class="course-exam-right">
<div class="course-exam-scroll"> <div class="course-exam-scroll">
<CourseExamQuestionNumbers :index="questionIndex" :status="1" /> <CourseExamQuestionNumbers :index="questionIndex" :status="status" />
</div> </div>
<div class="course-exam-buttons"> <div class="course-exam-buttons">
<el-button <el-button
......
...@@ -6,6 +6,7 @@ import { questionType } from '@/utils/dictionary' ...@@ -6,6 +6,7 @@ import { questionType } from '@/utils/dictionary'
interface Props { interface Props {
index: number index: number
status: number
question: PaperQuestionType question: PaperQuestionType
} }
const props = defineProps<Props>() const props = defineProps<Props>()
...@@ -28,11 +29,12 @@ const questionTypeText = computed(() => { ...@@ -28,11 +29,12 @@ const questionTypeText = computed(() => {
<CourseExamQuestionItem <CourseExamQuestionItem
v-for="(item, index) in question.children" v-for="(item, index) in question.children"
:question="item" :question="item"
:status="status"
:index="index + 1" :index="index + 1"
:key="item.id" :key="item.id"
/> />
</template> </template>
<CourseExamQuestionItem :question="question" :index="index" v-else /> <CourseExamQuestionItem :question="question" :status="status" :index="index" v-else />
</div> </div>
</div> </div>
</template> </template>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import type { PaperQuestionType } from '@/types' import type { PaperQuestionType } from '@/types'
interface Props { interface Props {
index: number index: number
status: number
question: PaperQuestionType question: PaperQuestionType
} }
const { question } = defineProps<Props>() const { question } = defineProps<Props>()
...@@ -17,18 +18,9 @@ const currentOptions = computed(() => { ...@@ -17,18 +18,9 @@ const currentOptions = computed(() => {
// 英文字母 + 名称 // 英文字母 + 名称
item.abc = A_Z[index] item.abc = A_Z[index]
item.abc_option = `${A_Z[index]}. ${item.option}` item.abc_option = `${A_Z[index]}. ${item.option}`
// 提交时的选中状态
// item.checked = this.question.user_answer.includes(item.id)
// 处理正确的选中状态
// const hasChecked = Object.prototype.hasOwnProperty.call(item, 'isRight')
// const rightAnswer = this.question.question_answer || []
// if (!hasChecked && rightAnswer) {
// item.isRight = Array.isArray(rightAnswer) ? rightAnswer.includes(item.id) : rightAnswer === item.id
// }
return item return item
}) })
}) })
// 26个英文字母 // 26个英文字母
const A_Z = $computed(() => { const A_Z = $computed(() => {
const result = [] const result = []
...@@ -37,11 +29,24 @@ const A_Z = $computed(() => { ...@@ -37,11 +29,24 @@ const A_Z = $computed(() => {
} }
return result return result
}) })
// 试题类型
const questionType = computed(() => { const questionType = computed(() => {
return question.child_question_type || question.question_type return question.child_question_type || question.question_type
}) })
// 正确答案
const correctAnswerText = computed(() => {
return question.question_options
.filter((item: any) => item.checked)
.map((item: any) => item.abc)
.join('、')
})
// 提交的答案
const submitAnswerText = computed(() => {
return question.question_options
.filter((item: any) => item.user_checked)
.map((item: any) => item.abc)
.join('、')
})
const value = computed({ const value = computed({
get() { get() {
return question.user_answer return question.user_answer
...@@ -100,7 +105,7 @@ const checkboxValues = computed({ ...@@ -100,7 +105,7 @@ const checkboxValues = computed({
></el-input> ></el-input>
</template> </template>
</div> </div>
<!-- <div class="question-item-ft" v-if="hasResult"> <div class="question-item-ft" v-if="status === 3">
<h3 class="question-item-ft__title">答案解析</h3> <h3 class="question-item-ft__title">答案解析</h3>
<template v-if="questionType !== 3"> <template v-if="questionType !== 3">
<div class="answer-item"> <div class="answer-item">
...@@ -113,16 +118,16 @@ const checkboxValues = computed({ ...@@ -113,16 +118,16 @@ const checkboxValues = computed({
</div> </div>
</template> </template>
<template v-else> <template v-else>
<div class="answer-item" v-if="question.comment"> <div class="answer-item" v-if="question.reviews">
<div class="answer-item-label">老师点评:</div> <div class="answer-item-label">老师点评:</div>
<div class="answer-item-content">{{ question.comment }}</div> <div class="answer-item-content">{{ question.reviews }}</div>
</div> </div>
</template> </template>
<div class="answer-item" v-if="question.question_analysis"> <div class="answer-item" v-if="question.question_analysis">
<div class="answer-item-label">解析:</div> <div class="answer-item-label">解析:</div>
<div class="answer-item-content" v-html="question.question_analysis"></div> <div class="answer-item-content" v-html="question.question_analysis"></div>
</div> </div>
</div> --> </div>
</div> </div>
</template> </template>
......
...@@ -12,41 +12,32 @@ const questionList = $ref<PaperQuestionType[]>(inject('questionList')) ...@@ -12,41 +12,32 @@ const questionList = $ref<PaperQuestionType[]>(inject('questionList'))
// 试题索引 // 试题索引
let questionIndex = $ref<number>(inject('questionIndex')) let questionIndex = $ref<number>(inject('questionIndex'))
const questionNumTips: any = {
1: [
{ class: 'is-info', name: '已答' },
{ class: 'is-default', name: '未答' },
{ class: 'is-success', name: '当前' }
],
2: [
{ class: 'is-success', name: '答对' },
{ class: 'is-error', name: '答错' },
{ class: 'is-info', name: '未答' }
]
}
const questionNum = computed(() => { const questionNum = computed(() => {
return questionNumTips[props.status] if (props.status === 3) {
return [
{ class: 'is-success', name: '答对' },
{ class: 'is-error', name: '答错' },
{ class: 'is-info', name: '未答' }
]
} else {
return [
{ class: 'is-info', name: '已答' },
{ class: 'is-default', name: '未答' },
{ class: 'is-success', name: '当前' }
]
}
}) })
function genClass(data: any, index: number) { function genClass(data: any, index: number) {
// answer(0:未做,1:正确,2:错误) if (props.status === 3) {
if (props.status === 1) {
return {
'is-info': !!data.user_answer, // 已做
'is-success': index === questionIndex // 当前
}
}
if (props.status === 2) {
return { return {
'is-success': data.answer === 1, // 答对 'is-success': data.user_answer_status, // 答对
'is-error': data.answer === 2, // 答错 'is-error': !data.user_answer_status, // 答错
'is-info': data.answer === 0 // 未答 'is-info': !data.user_answer // 未答
} }
} } else {
if (props.status === 3) {
return { return {
'is-success': data.checked_flag, // 已批阅 'is-info': !!data.user_answer, // 已做
'is-error': !data.checked_flag, // 未批阅 'is-success': index === questionIndex // 当前
'is-info': data.answer === 0 // 未做
} }
} }
} }
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
import AppUpload from '@/components/base/AppUpload.vue' import AppUpload from '@/components/base/AppUpload.vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import AppEditor from '@/components/base/AppEditor.vue'
import { getCourseWork, submitCourseWork } from '../api' import { getCourseWork, submitCourseWork } from '../api'
const { query } = useRoute() const { query } = useRoute()
...@@ -79,7 +81,7 @@ onMounted(() => { ...@@ -79,7 +81,7 @@ onMounted(() => {
<el-input v-model="form.title" /> <el-input v-model="form.title" />
</el-form-item> </el-form-item>
<el-form-item label="作业正文" prop="password"> <el-form-item label="作业正文" prop="password">
<el-input type="textarea" v-model="form.content" /> <AppEditor v-model="form.content" :disabled="disabled" />
</el-form-item> </el-form-item>
<el-form-item label="上传附件" prop="password_r"> <el-form-item label="上传附件" prop="password_r">
<AppUpload v-model="form.attachments" :disabled="disabled"></AppUpload> <AppUpload v-model="form.attachments" :disabled="disabled"></AppUpload>
......
...@@ -2,19 +2,25 @@ ...@@ -2,19 +2,25 @@
import type { PaperQuestionType } from '@/types' import type { PaperQuestionType } from '@/types'
import CourseExamCard from '../components/CourseExamCard.vue' import CourseExamCard from '../components/CourseExamCard.vue'
import { getPaper } from '../api' import { getPaper } from '../api'
const route = useRoute() const route = useRoute()
const courseId = $ref(route.query.course_id as string) const courseId = $ref(route.query.course_id as string)
const semesterId = $ref(route.query.semester_id as string) const semesterId = $ref(route.query.semester_id as string)
const paperId = $ref(route.query.paper_id as string) const paperId = $ref(route.query.paper_id as string)
const type = $ref(parseInt(route.query.type as string)) const type = $ref(parseInt(route.query.type as string))
const detail = reactive({ status: 1 }) const detail = reactive({ status: 1 })
const questionList = ref<PaperQuestionType[]>([]) let questionList = $ref<PaperQuestionType[]>([])
provide('questionList', questionList) provide('questionList', $$(questionList))
let loading = $ref<boolean>(false)
// 获取试卷详情 // 获取试卷详情
function fetchInfo() { function fetchInfo() {
loading = true
getPaper({ course_id: courseId, semester_id: semesterId, paper_id: paperId, type }).then(res => { getPaper({ course_id: courseId, semester_id: semesterId, paper_id: paperId, type }).then(res => {
const { question, status, score_details } = res.data
Object.assign(detail, res.data) Object.assign(detail, res.data)
questionList.value = res.data.question questionList = status === 3 ? score_details : question
loading = false
}) })
} }
onMounted(() => { onMounted(() => {
...@@ -23,5 +29,5 @@ onMounted(() => { ...@@ -23,5 +29,5 @@ onMounted(() => {
</script> </script>
<template> <template>
<CourseExamCard :status="detail.status" @update="fetchInfo"></CourseExamCard> <CourseExamCard :status="detail.status" @update="fetchInfo" v-loading="loading"></CourseExamCard>
</template> </template>
...@@ -7,3 +7,12 @@ export function updateUser(data: { real_name: string; avatar: string; gender: nu ...@@ -7,3 +7,12 @@ export function updateUser(data: { real_name: string; avatar: string; gender: nu
export function updatePassword(data: { old_password: string; password: string; password_r: string }) { export function updatePassword(data: { old_password: string; password: string; password_r: string }) {
return httpRequest.post('/api/usercenter/v2/frontend/user/change-pwd-by-cookie', data) return httpRequest.post('/api/usercenter/v2/frontend/user/change-pwd-by-cookie', data)
} }
// 获取投诉建议列表
export function getSuggestionList(params?: { page?: number; limit?: number; status?: string }) {
return httpRequest.get('/api/saas/api/v1/suggestion/list', { params })
}
// 提交投诉建议
export function submitSuggestion(data: { title: string; content: string; files?: string }) {
return httpRequest.post('/api/saas/api/v1/suggestion/complaint', data)
}
<script setup lang="ts"></script> <script setup lang="ts">
import type { SuggestionType } from '../types'
import SuggestionsForm from './SuggestionsForm.vue'
import { getSuggestionList } from '../api'
const dialogVisible = ref<boolean>(false)
const dataset = reactive<{ total: number; list: SuggestionType[] }>({ total: 0, list: [] })
const params = reactive({ limit: 100, status: '' })
function fetchList() {
getSuggestionList(params).then(res => {
const { total = 0, data = [] } = res.data
dataset.total = total
dataset.list = data
})
}
watchEffect(() => {
fetchList()
})
function handleUpdate() {
dialogVisible.value = false
fetchList()
}
</script>
<template> <template>
<el-tabs> <el-tabs v-model="params.status">
<el-tab-pane label="全部"> </el-tab-pane> <el-tab-pane label="全部" name=""> </el-tab-pane>
<el-tab-pane label="待处理" lazy></el-tab-pane> <el-tab-pane label="待处理" name="1" lazy></el-tab-pane>
<el-tab-pane label="已处理" lazy></el-tab-pane> <el-tab-pane label="已处理" name="2" lazy></el-tab-pane>
</el-tabs> </el-tabs>
<el-button round>创建</el-button> <el-button round type="warning" @click="dialogVisible = true" style="margin-bottom: 20px">创建</el-button>
<el-collapse v-if="dataset.list.length">
<el-collapse-item v-for="item in dataset.list" :name="item.id" :key="item.id">
<template #title>
<el-button type="primary" size="small" round style="margin-right: 10px" v-if="item.status === 1"
>待处理</el-button
>
<el-button color="#E8E8E8" size="small" round style="margin-right: 10px" v-if="item.status === 2"
>已处理</el-button
>
<h2 class="suggestion-title">{{ item.title }}</h2>
</template>
<div class="suggestion-main">
<div class="suggestion-content" v-html="item.content"></div>
<a :href="item.files" target="_blank" class="suggestion-file" v-if="item.files">下载附件</a>
<p class="t1">发布于:{{ item.created_time }}</p>
<template v-if="item.status === 2">
<h2 class="suggestion-title">问题回复</h2>
<div class="suggestion-content" v-html="item.reply"></div>
</template>
</div>
</el-collapse-item>
</el-collapse>
<SuggestionsForm v-model="dialogVisible" @update="handleUpdate"></SuggestionsForm>
</template> </template>
<style lang="scss" scoped>
.suggestion-main {
margin-left: 70px;
.t1 {
margin-top: 10px;
font-size: 14px;
font-weight: 400;
line-height: 24px;
color: #999999;
}
.suggestion-title {
margin-top: 28px;
}
}
.suggestion-title {
font-size: 16px;
font-weight: 500;
line-height: 27px;
color: #333333;
}
.suggestion-content {
font-size: 14px;
font-weight: 400;
line-height: 24px;
color: #666666;
:deep(img) {
max-width: 100%;
}
}
</style>
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import AppUpload from '@/components/base/AppUpload.vue'
import AppEditor from '@/components/base/AppEditor.vue'
import type { FormInstance, FormRules } from 'element-plus'
import { submitSuggestion } from '../api'
const emit = defineEmits<{
(e: 'update'): void
}>()
const formRef = $ref<FormInstance>()
const form = reactive({
title: '',
content: '',
files: ''
})
const rules = ref<FormRules>({
title: [{ required: true, message: '请输入问题描述', trigger: 'blur' }],
content: [{ required: true, message: '请输入问题详情', trigger: 'blur' }]
})
// 提交
function handleSubmit() {
formRef?.validate().then(update)
}
// 修改
const update = () => {
submitSuggestion(form).then(() => {
ElMessage({ message: '提交成功', type: 'success' })
emit('update')
formRef?.resetFields()
})
}
</script>
<template>
<el-dialog title="投诉建议" width="800px">
<el-form ref="formRef" :model="form" :rules="rules" hide-required-asterisk label-position="top">
<el-form-item label="问题描述" prop="title">
<el-input v-model="form.title" />
</el-form-item>
<el-form-item label="问题详情" prop="content">
<AppEditor v-model="form.content" />
</el-form-item>
<el-form-item label="上传附件" prop="files">
<AppUpload v-model="form.files">
<el-button round>点击上传</el-button>
<p>{{ form.files }}</p>
</AppUpload>
</el-form-item>
<el-form-item>
<el-button type="primary" round auto-insert-space @click="handleSubmit">提交</el-button>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script setup lang="ts"></script>
<template>
<el-tabs>
<el-tab-pane label="全部"> </el-tab-pane>
<el-tab-pane label="待处理" lazy></el-tab-pane>
<el-tab-pane label="已处理" lazy></el-tab-pane>
</el-tabs>
<el-button round>创建</el-button>
</template>
export interface SuggestionType {
content: string
created_time: string
files: string
id: string
reply: string
title: string
status: 1 | 2
}
...@@ -146,6 +146,7 @@ export interface PaperQuestionType { ...@@ -146,6 +146,7 @@ export interface PaperQuestionType {
score: number score: number
children?: PaperQuestionType[] children?: PaperQuestionType[]
user_answer: string user_answer: string
reviews?: string
} }
export interface PaperQuestionOptionType { export interface PaperQuestionOptionType {
checked_option: string checked_option: string
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论