feat:更新记录模块
This commit is contained in:
@@ -1,9 +0,0 @@
|
|||||||
import { cloudService } from './index'
|
|
||||||
import type { IExamRecord } from '@/types/exam.ts'
|
|
||||||
|
|
||||||
export const addExamRecordApi = (data: IExamRecord): Promise<boolean> =>
|
|
||||||
cloudService({
|
|
||||||
url: '/study-api/exam/record',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import { cloudService } from './index'
|
import { cloudService } from './index'
|
||||||
import type { IMistake } from '@/types/mistake.ts'
|
import type { IMistake } from '@/types/mistake.ts'
|
||||||
|
|
||||||
export const queryMistakeListApi = (): Promise<IMistake[]> =>
|
export const queryMistakeListApi = (subject: string): Promise<IMistake[]> =>
|
||||||
cloudService({
|
cloudService({
|
||||||
url: '/study-api/mistake',
|
url: `/study-api/mistake/${subject}`,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
|
|
||||||
export const addMistakeListApi = (data: IMistake[]): Promise<boolean> =>
|
export const addMistakeListApi = (subject: string, data: IMistake[]): Promise<boolean> =>
|
||||||
cloudService({
|
cloudService({
|
||||||
url: '/study-api/mistake',
|
url: `/study-api/mistake/${subject}`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
import { cloudService } from './index'
|
|
||||||
import type { IPracticeRecord } from '@/types/practice.ts'
|
|
||||||
|
|
||||||
export const queryPracticeRecordApi = (id: number): Promise<IPracticeRecord[]> =>
|
|
||||||
cloudService({
|
|
||||||
url: `/study-api/practice/record/${id}`,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
|
|
||||||
export const addPracticeRecordApi = (data: IPracticeRecord): Promise<boolean> =>
|
|
||||||
cloudService({
|
|
||||||
url: '/study-api/practice/record',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
15
src/apis/record.ts
Normal file
15
src/apis/record.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { cloudService } from './index'
|
||||||
|
import type { IRecord } from '@/types/record.ts'
|
||||||
|
|
||||||
|
export const queryRecordApi = (subject: string): Promise<IRecord[]> =>
|
||||||
|
cloudService({
|
||||||
|
url: `/study-api/record/${subject}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
|
||||||
|
export const addRecordApi = (subject: string, data: IRecord): Promise<boolean> =>
|
||||||
|
cloudService({
|
||||||
|
url: `/study-api/record/${subject}`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
@@ -42,20 +42,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { usePracticeStore } from '@/stores/practice.ts'
|
|
||||||
import { useLibraryStore } from '@/stores/library.ts'
|
|
||||||
import { useMistakeStore } from '@/stores/mistake.ts'
|
import { useMistakeStore } from '@/stores/mistake.ts'
|
||||||
import { useQuestionStore } from '@/stores/question.ts'
|
import { useQuestionStore } from '@/stores/question.ts'
|
||||||
import { useExamStore } from '@/stores/exam.ts'
|
import { useRecordStore } from '@/stores/record.ts'
|
||||||
|
import { useLibraryStore } from '@/stores/library.ts'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { getMistakeList, isAnswerCorrect, optLetter } from '@/utils/practiceUtil.ts'
|
import { getMistakeList, isAnswerCorrect, optLetter } from '@/utils/practiceUtil.ts'
|
||||||
import type { IMistake } from '@/types/mistake.ts'
|
import type { IMistake } from '@/types/mistake.ts'
|
||||||
|
|
||||||
const practiceStore = usePracticeStore()
|
|
||||||
const libraryStore = useLibraryStore()
|
|
||||||
const mistakeStore = useMistakeStore()
|
const mistakeStore = useMistakeStore()
|
||||||
const questionStore = useQuestionStore()
|
const questionStore = useQuestionStore()
|
||||||
const examStore = useExamStore()
|
const recordStore = useRecordStore()
|
||||||
|
const libraryStore = useLibraryStore()
|
||||||
|
|
||||||
const submitAnswerClick = async () => {
|
const submitAnswerClick = async () => {
|
||||||
if (questionStore.questionList.find((item) => item.select.length === 0)) {
|
if (questionStore.questionList.find((item) => item.select.length === 0)) {
|
||||||
@@ -70,77 +68,46 @@ const submitAnswerClick = async () => {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
await addMistakeList()
|
await addMistakeList()
|
||||||
|
await addRecord()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (questionStore.type === 'Practice') {
|
const addRecord = async () => {
|
||||||
await addPracticeRecord()
|
const totalCount = questionStore.checkList.length
|
||||||
const { totalCount, correctCount, wrongCount } = practiceStore.currentRecord
|
const correctCount = questionStore.checkList.filter((c) => c.isCorrect).length
|
||||||
await ElMessageBox.alert(
|
const wrongCount = totalCount - correctCount
|
||||||
`共 ${totalCount} 题 · 正确 ${correctCount} · 错误 ${wrongCount}`,
|
|
||||||
'训练结果',
|
recordStore.currentRecord = {
|
||||||
{
|
type: questionStore.type,
|
||||||
confirmButtonText: '确认'
|
totalCount,
|
||||||
}
|
correctCount,
|
||||||
)
|
wrongCount
|
||||||
} else {
|
}
|
||||||
await addExamRecord()
|
await recordStore.addRecord(libraryStore.currentFile.subject)
|
||||||
const { totalCount, correctCount, wrongCount } = examStore.currentRecord
|
|
||||||
await ElMessageBox.alert(
|
await ElMessageBox.alert(
|
||||||
`共 ${totalCount} 题 · 正确 ${correctCount} · 错误 ${wrongCount}`,
|
`共 ${totalCount} 题 · 正确 ${correctCount} · 错误 ${wrongCount}`,
|
||||||
'考试结果',
|
'结果',
|
||||||
{
|
{
|
||||||
confirmButtonText: '确认'
|
confirmButtonText: '确认'
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
}
|
|
||||||
|
|
||||||
const addPracticeRecord = async () => {
|
|
||||||
const totalCount = questionStore.checkList.length
|
|
||||||
const correctCount = questionStore.checkList.filter((c) => c.isCorrect).length
|
|
||||||
|
|
||||||
practiceStore.currentRecord = {
|
|
||||||
libraryFileId: libraryStore.currentFile.id,
|
|
||||||
totalCount,
|
|
||||||
correctCount,
|
|
||||||
wrongCount: totalCount - correctCount
|
|
||||||
}
|
|
||||||
await practiceStore.addRecord()
|
|
||||||
}
|
|
||||||
|
|
||||||
const addExamRecord = async () => {
|
|
||||||
const totalCount = questionStore.checkList.length
|
|
||||||
const correctCount = questionStore.checkList.filter((c) => c.isCorrect).length
|
|
||||||
|
|
||||||
examStore.currentRecord = {
|
|
||||||
subject: examStore.config.subject,
|
|
||||||
totalCount,
|
|
||||||
correctCount,
|
|
||||||
wrongCount: totalCount - correctCount
|
|
||||||
}
|
|
||||||
await examStore.addRecord()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const addMistakeList = async () => {
|
const addMistakeList = async () => {
|
||||||
const mistakeList = getMistakeList(questionStore.questionList, questionStore.checkList)
|
const mistakeList = getMistakeList(questionStore.questionList, questionStore.checkList)
|
||||||
mistakeStore.currentMistakes = []
|
mistakeStore.currentMistakes = []
|
||||||
const subject = questionStore.type === 'Practice' ? libraryStore.currentFile.subject : examStore.config.subject
|
|
||||||
const module = questionStore.type === 'Practice' ? libraryStore.currentFile.module : ''
|
|
||||||
const name = questionStore.type === 'Practice' ? libraryStore.currentFile.name : ''
|
|
||||||
|
|
||||||
mistakeList.forEach((item) => {
|
mistakeList.forEach((item) => {
|
||||||
const mistake:IMistake = {
|
const mistake: IMistake = {
|
||||||
answer: item.answer,
|
answer: item.answer,
|
||||||
module,
|
|
||||||
name,
|
|
||||||
options: item.options,
|
options: item.options,
|
||||||
question: item.question,
|
question: item.question,
|
||||||
subject,
|
|
||||||
type: item.type
|
type: item.type
|
||||||
}
|
}
|
||||||
mistakeStore.currentMistakes.push(mistake)
|
mistakeStore.currentMistakes.push(mistake)
|
||||||
})
|
})
|
||||||
await mistakeStore.addMistakeList()
|
await mistakeStore.addMistakeList(libraryStore.currentFile.subject)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import type { IExamConfig, IExamRecord } from '@/types/exam.ts'
|
import type { IExamConfig } from '@/types/exam.ts'
|
||||||
import { addExamRecordApi } from '@/apis/exam.ts'
|
|
||||||
|
|
||||||
export const useExamStore = defineStore('exam', {
|
export const useExamStore = defineStore('exam', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
config: {} as IExamConfig,
|
config: {} as IExamConfig
|
||||||
currentRecord: {} as IExamRecord
|
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
getEmptyConfig(): IExamConfig {
|
getEmptyConfig(): IExamConfig {
|
||||||
@@ -14,9 +12,6 @@ export const useExamStore = defineStore('exam', {
|
|||||||
subject: '',
|
subject: '',
|
||||||
total: 50
|
total: 50
|
||||||
}
|
}
|
||||||
},
|
|
||||||
async addRecord() {
|
|
||||||
await addExamRecordApi(this.currentRecord)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ export const useMistakeStore = defineStore('mistake', {
|
|||||||
currentMistakes: [] as IMistake[]
|
currentMistakes: [] as IMistake[]
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
async queryMistakeList() {
|
async queryMistakeList(subject: string) {
|
||||||
this.mistakeList = await queryMistakeListApi()
|
this.mistakeList = await queryMistakeListApi(subject)
|
||||||
},
|
},
|
||||||
async addMistakeList() {
|
async addMistakeList(subject: string) {
|
||||||
await addMistakeListApi(this.currentMistakes)
|
await addMistakeListApi(subject, this.currentMistakes)
|
||||||
},
|
},
|
||||||
async deleteMistakeById(id: number) {
|
async deleteMistakeById(id: number) {
|
||||||
await deleteMistakeApi(id)
|
await deleteMistakeApi(id)
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
import { defineStore } from 'pinia'
|
|
||||||
import { addPracticeRecordApi, queryPracticeRecordApi } from '@/apis/practice.ts'
|
|
||||||
import type { IPracticeRecord } from '@/types/practice.ts'
|
|
||||||
|
|
||||||
export const usePracticeStore = defineStore('practice', {
|
|
||||||
state: () => ({
|
|
||||||
libraryFileId: 0,
|
|
||||||
recordList: [] as IPracticeRecord[],
|
|
||||||
currentRecord: {} as IPracticeRecord
|
|
||||||
}),
|
|
||||||
actions: {
|
|
||||||
async queryRecord() {
|
|
||||||
this.recordList = await queryPracticeRecordApi(this.libraryFileId)
|
|
||||||
},
|
|
||||||
async addRecord() {
|
|
||||||
await addPracticeRecordApi(this.currentRecord)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import type { IPracticeCheck, IPracticeRecord } from '@/types/practice.ts'
|
|
||||||
import type { IQuestion } from '@/types/question.ts'
|
import type { IQuestion } from '@/types/question.ts'
|
||||||
|
import type { IRecord, IRecordCheck } from '@/types/record.ts'
|
||||||
|
|
||||||
export const useQuestionStore = defineStore('question', {
|
export const useQuestionStore = defineStore('question', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
@@ -8,7 +8,7 @@ export const useQuestionStore = defineStore('question', {
|
|||||||
type: 'Practice' as 'Practice' | 'Exam',
|
type: 'Practice' as 'Practice' | 'Exam',
|
||||||
questionContent: '',
|
questionContent: '',
|
||||||
questionList: [] as IQuestion[],
|
questionList: [] as IQuestion[],
|
||||||
recordList: [] as IPracticeRecord[],
|
recordList: [] as IRecord[],
|
||||||
checkList: [] as IPracticeCheck[]
|
checkList: [] as IRecordCheck[]
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
18
src/stores/record.ts
Normal file
18
src/stores/record.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { addRecordApi, queryRecordApi } from '@/apis/record.ts'
|
||||||
|
import type { IRecord } from '@/types/record.ts'
|
||||||
|
|
||||||
|
export const useRecordStore = defineStore('record', {
|
||||||
|
state: () => ({
|
||||||
|
recordList: [] as IRecord[],
|
||||||
|
currentRecord: {} as IRecord
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
async queryRecord(subject: string) {
|
||||||
|
this.recordList = await queryRecordApi(subject)
|
||||||
|
},
|
||||||
|
async addRecord(subject: string) {
|
||||||
|
await addRecordApi(subject, this.currentRecord)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -2,12 +2,3 @@ export interface IExamConfig {
|
|||||||
subject: string;
|
subject: string;
|
||||||
total: number;
|
total: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IExamRecord {
|
|
||||||
id?: number;
|
|
||||||
subject: string;
|
|
||||||
totalCount: number;
|
|
||||||
correctCount: number;
|
|
||||||
wrongCount: number;
|
|
||||||
createTime?: string;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
export interface IMistake {
|
export interface IMistake {
|
||||||
id?: number;
|
id?: number;
|
||||||
subject: string;
|
|
||||||
module: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
type: string;
|
||||||
question: string;
|
question: string;
|
||||||
options: string[];
|
options: string[];
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
export interface IPracticeCheck {
|
export interface IRecordCheck {
|
||||||
id: number;
|
id: number;
|
||||||
answer: string[];
|
answer: string[];
|
||||||
select: string[];
|
select: string[];
|
||||||
isCorrect: boolean;
|
isCorrect: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPracticeRecord {
|
export interface IRecord {
|
||||||
id?: number;
|
id?: number;
|
||||||
libraryFileId:number;
|
type: string;
|
||||||
totalCount: number;
|
totalCount: number;
|
||||||
correctCount: number;
|
correctCount: number;
|
||||||
wrongCount: number;
|
wrongCount: number;
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<question-list v-if="questionStore.questionList.length > 0"/>
|
<question-list v-if="questionStore.questionList.length > 0"/>
|
||||||
|
<p v-else>请点击「开始考试」按钮进入考试</p>
|
||||||
|
|
||||||
<exam-dialog />
|
<exam-dialog />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,13 +7,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="filter-bar card-item">
|
||||||
|
<div class="filter-row">
|
||||||
|
<span class="filter-label">学科</span>
|
||||||
|
<el-segmented v-model="libraryStore.selectedSubject"
|
||||||
|
:options="libraryStore.subjectOptions"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mistake-record">
|
<div class="mistake-record">
|
||||||
<div v-if="mistakeStore.mistakeList.length" class="mistake-list">
|
<div v-if="mistakeStore.mistakeList.length" class="mistake-list">
|
||||||
<el-card v-for="item in mistakeStore.mistakeList"
|
<el-card v-for="item in mistakeStore.mistakeList"
|
||||||
:key="item.id" class="mistake-card" shadow="never">
|
:key="item.id" class="mistake-card" shadow="never">
|
||||||
<div class="library">
|
<div class="library">
|
||||||
<el-tag type="primary" effect="dark">{{ item.subject }} · {{ item.module }}</el-tag>
|
<el-tag type="primary" effect="dark">{{ libraryStore.selectedSubject }}</el-tag>
|
||||||
<el-button type="success" size="small" @click="deleteClick(item.id)">已掌握</el-button>
|
<el-button type="success" size="small" @click="deleteClick(item)">已掌握</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="question">{{ item.question }}</div>
|
<div class="question">{{ item.question }}</div>
|
||||||
@@ -38,11 +46,13 @@ import { useMistakeStore } from '@/stores/mistake.ts'
|
|||||||
import { optLetter } from '@/utils/practiceUtil.ts'
|
import { optLetter } from '@/utils/practiceUtil.ts'
|
||||||
import type { IMistake } from '@/types/mistake.ts'
|
import type { IMistake } from '@/types/mistake.ts'
|
||||||
import { ElMessageBox } from 'element-plus'
|
import { ElMessageBox } from 'element-plus'
|
||||||
|
import { useLibraryStore } from '@/stores/library.ts'
|
||||||
|
|
||||||
const mistakeStore = useMistakeStore()
|
const mistakeStore = useMistakeStore()
|
||||||
|
const libraryStore = useLibraryStore()
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await mistakeStore.queryMistakeList()
|
await mistakeStore.queryMistakeList(libraryStore.selectedSubject as string)
|
||||||
})
|
})
|
||||||
|
|
||||||
const optionClass = (item: IMistake, index: number) => {
|
const optionClass = (item: IMistake, index: number) => {
|
||||||
@@ -53,14 +63,14 @@ const optionClass = (item: IMistake, index: number) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteClick = (id: number) => {
|
const deleteClick = (mistake: IMistake) => {
|
||||||
ElMessageBox.confirm('确定已掌握该错题?', '提示', {
|
ElMessageBox.confirm('确定已掌握该错题?', '提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
}).then(async () => {
|
}).then(async () => {
|
||||||
await mistakeStore.deleteMistakeById(id)
|
await mistakeStore.deleteMistakeById(mistake.id as number)
|
||||||
await mistakeStore.queryMistakeList()
|
await mistakeStore.queryMistakeList(libraryStore.selectedSubject as string)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user