|
@@ -4,7 +4,7 @@
|
|
|
<div
|
|
|
class="col-span-1 flex h-full flex-col overflow-hidden rounded-xl bg-white shadow-md"
|
|
|
>
|
|
|
- <div class="bg-[var(--czr-chinese-sub-color)] p-4 text-white">
|
|
|
+ <div class="bg-[var(--czr-main-sub-color)] p-4 text-white">
|
|
|
<div class="flex items-center text-xl font-bold">
|
|
|
<i class="fas fa-book mr-2"></i>
|
|
|
知识点分类
|
|
@@ -32,7 +32,7 @@
|
|
|
<div class="relative">
|
|
|
<div class="">
|
|
|
<q-input
|
|
|
- v-model="state.treeText"
|
|
|
+ v-model="state.tree.text"
|
|
|
outlined
|
|
|
placeholder="搜索知识点..."
|
|
|
:dense="true"
|
|
@@ -42,31 +42,33 @@
|
|
|
</template>
|
|
|
<template v-slot:append>
|
|
|
<q-icon
|
|
|
- v-if="state.treeText !== ''"
|
|
|
+ v-if="state.tree.text !== ''"
|
|
|
name="clear"
|
|
|
class="cursor-pointer"
|
|
|
- @click="state.treeText = ''"
|
|
|
+ @click="state.tree.text = ''"
|
|
|
/>
|
|
|
</template>
|
|
|
</q-input>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="flex-1 overflow-y-auto p-2">
|
|
|
+ <div class="flex-1 overflow-y-auto p-2" v-loading="state.tree.loading">
|
|
|
<q-tree
|
|
|
ref="ref_tree"
|
|
|
- :nodes="treeData"
|
|
|
- node-key="name"
|
|
|
- label-key="name"
|
|
|
+ :nodes="state.tree.data"
|
|
|
+ node-key="value"
|
|
|
+ label-key="label"
|
|
|
v-model:selected="state.selected"
|
|
|
- :filter="state.treeText"
|
|
|
+ :filter="state.tree.text"
|
|
|
>
|
|
|
<template v-slot:default-header="prop">
|
|
|
<div class="flex w-full items-center text-sm">
|
|
|
<div class="">
|
|
|
- {{ prop.node.name }}
|
|
|
+ {{ prop.node.label }}
|
|
|
+ </div>
|
|
|
+ <div class="ml-auto">
|
|
|
+ {{ prop.node.totalMake }}/{{ prop.node.total }}题
|
|
|
</div>
|
|
|
- <div class="ml-auto">{{ prop.node.total }}题</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
</q-tree>
|
|
@@ -75,65 +77,24 @@
|
|
|
<div
|
|
|
class="col-span-3 flex h-full flex-col overflow-hidden rounded-xl bg-white shadow-md"
|
|
|
>
|
|
|
- <div class="bg-[var(--czr-chinese-sub-color)] p-4 text-white">
|
|
|
+ <div class="bg-[var(--czr-main-sub-color)] p-4 text-white">
|
|
|
<div class="relative flex items-center text-xl font-bold">
|
|
|
<i class="fas fa-book mr-2"></i>
|
|
|
题目列表
|
|
|
<span class="text-base" v-if="state.selected">
|
|
|
- ({{ treeMapCpt.get(state.selected).name }} - 共{{
|
|
|
- treeMapCpt.get(state.selected).total
|
|
|
+ ({{ treeMapCpt.get(state.selected)?.label }} - 共{{
|
|
|
+ state.question.total
|
|
|
}}题)
|
|
|
</span>
|
|
|
<div class="absolute right-2 ml-auto flex">
|
|
|
- <q-input
|
|
|
- class="date w-[250px]"
|
|
|
- rounded
|
|
|
- standout="focus"
|
|
|
- :dense="true"
|
|
|
- v-model="dateStr"
|
|
|
- readonly
|
|
|
- >
|
|
|
- <template v-slot:prepend>
|
|
|
- <q-icon name="event" class="cursor-pointer" color="white">
|
|
|
- <q-popup-proxy
|
|
|
- cover
|
|
|
- transition-show="scale"
|
|
|
- transition-hide="scale"
|
|
|
- >
|
|
|
- <q-date
|
|
|
- v-model="state.query.date"
|
|
|
- mask="YYYY-MM-DD"
|
|
|
- range
|
|
|
- >
|
|
|
- <div class="row items-center justify-end">
|
|
|
- <q-btn
|
|
|
- v-close-popup
|
|
|
- label="关闭"
|
|
|
- color="primary"
|
|
|
- flat
|
|
|
- />
|
|
|
- </div>
|
|
|
- </q-date>
|
|
|
- </q-popup-proxy>
|
|
|
- </q-icon>
|
|
|
- </template>
|
|
|
- <template v-slot:append>
|
|
|
- <q-icon
|
|
|
- v-if="dateStr"
|
|
|
- name="clear"
|
|
|
- class="cursor-pointer"
|
|
|
- @click="state.query.date = {}"
|
|
|
- color="white"
|
|
|
- />
|
|
|
- </template>
|
|
|
- </q-input>
|
|
|
<q-select
|
|
|
class="select ml-4 w-[100px]"
|
|
|
rounded
|
|
|
standout="focus"
|
|
|
- v-model="state.query.p2"
|
|
|
- :options="['全部题', '错题', '正确题']"
|
|
|
+ v-model="state.question.type"
|
|
|
+ :options="['错题', '正确题']"
|
|
|
:dense="true"
|
|
|
+ @change="initQuestion"
|
|
|
>
|
|
|
</q-select>
|
|
|
</div>
|
|
@@ -141,14 +102,14 @@
|
|
|
</div>
|
|
|
<div class="flex-1 overflow-y-auto p-4" id="questionsContainer">
|
|
|
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
|
|
- <template v-for="(item, index) in state.list">
|
|
|
+ <template v-for="(item, index) in state.question.data">
|
|
|
<div
|
|
|
class="question-card overflow-hidden rounded-xl border border-[#e5e7eb] bg-white shadow-sm"
|
|
|
>
|
|
|
<div class="p-4">
|
|
|
<div class="mb-3 flex items-start justify-between">
|
|
|
<div class="text-base font-semibold text-gray-800">
|
|
|
- 题目 {{ index + 1 }} - {{ item.name }}
|
|
|
+ 题目 {{ index + 1 }}
|
|
|
</div>
|
|
|
<div class="flex space-x-1">
|
|
|
<q-btn
|
|
@@ -165,7 +126,7 @@
|
|
|
class="bg-gray-light mb-4 flex justify-center rounded-lg p-4"
|
|
|
>
|
|
|
<img
|
|
|
- :src="item.question"
|
|
|
+ :src="item.questionContent"
|
|
|
alt="题目图片"
|
|
|
class="max-h-40 rounded"
|
|
|
/>
|
|
@@ -175,7 +136,7 @@
|
|
|
class="bg-gray-light mb-4 flex justify-center rounded-lg p-4"
|
|
|
>
|
|
|
<img
|
|
|
- :src="item.answer"
|
|
|
+ :src="item.questionAnswer"
|
|
|
alt="答案图片"
|
|
|
class="max-h-32 rounded"
|
|
|
/>
|
|
@@ -186,11 +147,11 @@
|
|
|
视频解析:
|
|
|
</div>
|
|
|
<ul class="space-y-2">
|
|
|
- <template v-for="video in item.videos">
|
|
|
+ <template v-for="video in item.questionVideos">
|
|
|
<li
|
|
|
class="video-item flex items-center justify-between rounded-lg border border-[#e5e7eb] p-2"
|
|
|
>
|
|
|
- <span class="text-sm">{{ video.name }}</span>
|
|
|
+ <span class="text-sm">{{ video.fileName }}</span>
|
|
|
<div
|
|
|
class="play-video bg-subject-color hover:bg-subject-dark rounded-full p-1.5 transition-colors"
|
|
|
@click="state.showVideo = true"
|
|
@@ -307,257 +268,115 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { computed, onBeforeMount, onMounted, reactive, ref } from 'vue'
|
|
|
+import { computed, onBeforeMount, onMounted, reactive, ref, watch } from 'vue'
|
|
|
import StudyLayout from '@/views/study/components/study-layout.vue'
|
|
|
import { Plus } from '@element-plus/icons-vue'
|
|
|
+import {
|
|
|
+ trainingCampQuestionList,
|
|
|
+ trainingCampQuestionTypeTree,
|
|
|
+} from '@/api/modules/study'
|
|
|
+import { useAppStore } from '@/stores'
|
|
|
+import { useRoute } from 'vue-router'
|
|
|
|
|
|
+const AppStore = useAppStore()
|
|
|
+const route = useRoute()
|
|
|
const state: any = reactive({
|
|
|
selected: null,
|
|
|
- treeText: '',
|
|
|
- query: {
|
|
|
- p2: '错题',
|
|
|
- date: {},
|
|
|
+ tree: {
|
|
|
+ text: '',
|
|
|
+ loading: false,
|
|
|
+ data: [],
|
|
|
+ },
|
|
|
+ question: {
|
|
|
+ loading: false,
|
|
|
+ type: '错题',
|
|
|
+ data: [],
|
|
|
+ total: 0,
|
|
|
+ page: 1,
|
|
|
},
|
|
|
showVideo: false,
|
|
|
showHistory: false,
|
|
|
- list: [
|
|
|
- {
|
|
|
- name: '下列汉字中属于独体字的是哪一项?',
|
|
|
- question: 'https://picsum.photos/id/24/400/200',
|
|
|
- answer: 'https://picsum.photos/id/26/400/150',
|
|
|
- videos: [
|
|
|
- {
|
|
|
- name: '独体字与合体字的区别',
|
|
|
- url: 'http://cyberplayer.bcelive.com/videoworks/mda-kbuhu4wqdi08dwix/cyberplayer/mp4/cyberplayer-demo.mp4',
|
|
|
- },
|
|
|
- {
|
|
|
- name: '常见独体字结构分析',
|
|
|
- url: 'http://cyberplayer.bcelive.com/videoworks/mda-kbuhu4wqdi08dwix/cyberplayer/mp4/cyberplayer-demo.mp4',
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '找出下列选项中书写有误的汉字并改正?',
|
|
|
- question: 'https://picsum.photos/id/24/400/200',
|
|
|
- answer: 'https://picsum.photos/id/26/400/150',
|
|
|
- videos: [
|
|
|
- {
|
|
|
- name: '汉字结构分类详解',
|
|
|
- url: 'http://cyberplayer.bcelive.com/videoworks/mda-kbuhu4wqdi08dwix/cyberplayer/mp4/cyberplayer-demo.mp4',
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '下列哪个汉字是上下结构?',
|
|
|
- question: 'https://picsum.photos/id/24/400/200',
|
|
|
- answer: 'https://picsum.photos/id/26/400/150',
|
|
|
- videos: [
|
|
|
- {
|
|
|
- name: '汉字结构分类详解',
|
|
|
- url: 'http://cyberplayer.bcelive.com/videoworks/mda-kbuhu4wqdi08dwix/cyberplayer/mp4/cyberplayer-demo.mp4',
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '下列哪组汉字都是左右结构?',
|
|
|
- question: 'https://picsum.photos/id/24/400/200',
|
|
|
- answer: 'https://picsum.photos/id/26/400/150',
|
|
|
- videos: [
|
|
|
- {
|
|
|
- name: '汉字结构分类详解',
|
|
|
- url: 'http://cyberplayer.bcelive.com/videoworks/mda-kbuhu4wqdi08dwix/cyberplayer/mp4/cyberplayer-demo.mp4',
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- ],
|
|
|
-})
|
|
|
-const dateStr = computed(() => {
|
|
|
- if (state.query.date.from && state.query.date.to) {
|
|
|
- return `${state.query.date.from} - ${state.query.date.to}`
|
|
|
- }
|
|
|
- return ''
|
|
|
})
|
|
|
const ref_tree = ref()
|
|
|
-const treeData = [
|
|
|
- {
|
|
|
- name: '基础知识',
|
|
|
- total: 328,
|
|
|
- children: [
|
|
|
- {
|
|
|
- name: '字音字形',
|
|
|
- total: 128,
|
|
|
- children: [
|
|
|
- {
|
|
|
- name: '声母韵母',
|
|
|
- total: 48,
|
|
|
- children: [
|
|
|
- { name: '声母辨析', total: 25 },
|
|
|
- { name: '韵母辨析', total: 18 },
|
|
|
- { name: '整体认读音节', total: 5 },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '字形结构',
|
|
|
- total: 80,
|
|
|
- children: [
|
|
|
- { name: '独体字', total: 24 },
|
|
|
- { name: '合体字', total: 32 },
|
|
|
- { name: '形近字', total: 16 },
|
|
|
- { name: '多音字', total: 8 },
|
|
|
- ],
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '词语辨析',
|
|
|
- total: 145,
|
|
|
- children: [
|
|
|
- { name: '近义词', total: 45 },
|
|
|
- { name: '反义词', total: 35 },
|
|
|
- { name: '成语辨析', total: 50 },
|
|
|
- { name: '熟语运用', total: 15 },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '句子运用',
|
|
|
- total: 55,
|
|
|
- children: [
|
|
|
- { name: '病句辨析', total: 30 },
|
|
|
- { name: '修辞手法', total: 15 },
|
|
|
- { name: '句式转换', total: 10 },
|
|
|
- ],
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '文言文',
|
|
|
- total: 196,
|
|
|
- children: [
|
|
|
- {
|
|
|
- name: '文言实词',
|
|
|
- total: 96,
|
|
|
- children: [
|
|
|
- { name: '一词多义', total: 40 },
|
|
|
- { name: '古今异义', total: 35 },
|
|
|
- { name: '通假字', total: 21 },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '文言虚词',
|
|
|
- total: 65,
|
|
|
- children: [
|
|
|
- { name: '之乎者也', total: 35 },
|
|
|
- { name: '而何乃焉', total: 30 },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '文言句式',
|
|
|
- total: 35,
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '现代文阅读',
|
|
|
- total: 178,
|
|
|
- children: [
|
|
|
- {
|
|
|
- name: '记叙文',
|
|
|
- total: 78,
|
|
|
- children: [
|
|
|
- { name: '写人记事', total: 45 },
|
|
|
- { name: '写景状物', total: 33 },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '说明文',
|
|
|
- total: 55,
|
|
|
- children: [
|
|
|
- { name: '事物说明', total: 30 },
|
|
|
- { name: '事理说明', total: 25 },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '议论文',
|
|
|
- total: 45,
|
|
|
- children: [
|
|
|
- { name: '论点论据', total: 25 },
|
|
|
- { name: '论证方法', total: 20 },
|
|
|
- ],
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '诗歌鉴赏',
|
|
|
- total: 164,
|
|
|
- children: [
|
|
|
- {
|
|
|
- name: '古诗',
|
|
|
- total: 104,
|
|
|
- children: [
|
|
|
- { name: '唐诗', total: 45 },
|
|
|
- { name: '宋诗', total: 35 },
|
|
|
- { name: '乐府诗', total: 24 },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '词曲',
|
|
|
- total: 45,
|
|
|
- children: [
|
|
|
- { name: '宋词', total: 30 },
|
|
|
- { name: '元曲', total: 15 },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '现代诗',
|
|
|
- total: 15,
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '写作技巧',
|
|
|
- total: 120,
|
|
|
- children: [
|
|
|
- {
|
|
|
- name: '记叙文写作',
|
|
|
- total: 65,
|
|
|
- children: [
|
|
|
- { name: '人物描写', total: 35 },
|
|
|
- { name: '情节安排', total: 30 },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '议论文写作',
|
|
|
- total: 45,
|
|
|
- children: [
|
|
|
- { name: '论点确立', total: 20 },
|
|
|
- { name: '论据选择', total: 25 },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- name: '应用文写作',
|
|
|
- total: 10,
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
-]
|
|
|
const treeMapCpt = computed(() => {
|
|
|
const map = new Map()
|
|
|
const deep = (arr) => {
|
|
|
arr.forEach((v) => {
|
|
|
- map.set(v.name, v)
|
|
|
+ map.set(v.value, v)
|
|
|
if (v.children?.length > 0) {
|
|
|
deep(v.children)
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
- deep(treeData)
|
|
|
+ deep(state.tree.data)
|
|
|
+ console.log(map)
|
|
|
return map
|
|
|
})
|
|
|
-onMounted(() => {})
|
|
|
+const initTree = () => {
|
|
|
+ state.tree.loading = true
|
|
|
+ state.tree.data = []
|
|
|
+ trainingCampQuestionTypeTree({
|
|
|
+ category: AppStore.studentInfo?.grade,
|
|
|
+ subject: route.name,
|
|
|
+ studentId: AppStore.studentInfo?.studentId,
|
|
|
+ level: 1,
|
|
|
+ })
|
|
|
+ .then(({ data }: any) => {
|
|
|
+ const deep = (arr, parent = []) => {
|
|
|
+ return arr.map((v) => {
|
|
|
+ v.total = 0
|
|
|
+ v.totalMake = 0
|
|
|
+ if (v.children?.length > 0) {
|
|
|
+ v.children = deep(v.children, [...parent, v])
|
|
|
+ } else {
|
|
|
+ parent.forEach((p) => {
|
|
|
+ p.total += v.size
|
|
|
+ p.totalMake += v.questionSize
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return v
|
|
|
+ })
|
|
|
+ }
|
|
|
+ state.tree.data = deep(data)
|
|
|
+ console.log(state.tree.data)
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ state.tree.loading = false
|
|
|
+ })
|
|
|
+}
|
|
|
+const initQuestion = () => {
|
|
|
+ state.question.loading = true
|
|
|
+ state.question.total = 0
|
|
|
+ state.question.data = []
|
|
|
+ trainingCampQuestionList({
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ category: AppStore.studentInfo?.grade,
|
|
|
+ subject: route.meta.subjectId,
|
|
|
+ correct: state.question.type !== '错题',
|
|
|
+ questionTypeCode: treeMapCpt.value.get(state.selected).questionTypeCode,
|
|
|
+ })
|
|
|
+ .then(({ rows, total }: any) => {
|
|
|
+ state.question.data = rows
|
|
|
+ state.question.total = total
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ state.question.loading = false
|
|
|
+ })
|
|
|
+}
|
|
|
+watch(
|
|
|
+ () => state.selected,
|
|
|
+ (n) => {
|
|
|
+ initQuestion()
|
|
|
+ },
|
|
|
+)
|
|
|
+onMounted(() => {
|
|
|
+ initTree()
|
|
|
+})
|
|
|
onBeforeMount(() => {
|
|
|
document.documentElement.style.setProperty(
|
|
|
'--czr-quasar-color',
|
|
|
- 'var(--czr-chinese-color)',
|
|
|
+ 'var(--czr-main-color)',
|
|
|
)
|
|
|
})
|
|
|
</script>
|
|
@@ -566,7 +385,7 @@ onBeforeMount(() => {
|
|
|
$primary: red;
|
|
|
|
|
|
.search-input:focus {
|
|
|
- box-shadow: 0 0 0 3px rgba(var(--czr-chinese-color-rgb), 0.2);
|
|
|
+ box-shadow: 0 0 0 3px rgba(var(--czr-main-color-rgb), 0.2);
|
|
|
}
|
|
|
.question-card {
|
|
|
transition: all 0.3s ease;
|
|
@@ -594,7 +413,7 @@ $primary: red;
|
|
|
}
|
|
|
:deep(.q-tree__node--selected),
|
|
|
:deep(.q-tree__node--selected .q-tree__node-header-content) {
|
|
|
- color: var(--czr-chinese-color) !important;
|
|
|
+ color: var(--czr-main-color) !important;
|
|
|
}
|
|
|
// FILE (create it): src/quasar-variables.sass
|
|
|
</style>
|