123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- <template>
- <StudyLayout>
- <div class="grid h-full w-full grid-cols-10 gap-6 overflow-hidden p-3">
- <div
- class="col-span-3 flex h-full flex-col overflow-hidden rounded-xl bg-white shadow-md"
- >
- <div class="bg-[var(--czr-main-sub-color)] px-4 py-3 text-white">
- <div class="flex items-center text-base font-bold">
- <i class="fas fa-book mr-2"></i>
- 知识点分类
- <div class="ml-auto flex space-x-1 font-normal">
- <div
- id="expandAll"
- class="text-subject-color flex items-center text-xs hover:underline"
- @click="ref_tree.expandAll()"
- >
- <i class="fas fa-plus-square mr-1"></i>
- <span>全部展开</span>
- </div>
- <div
- id="collapseAll"
- class="text-subject-color flex items-center text-xs hover:underline"
- @click="ref_tree.collapseAll()"
- >
- <i class="fas fa-minus-square mr-1"></i>
- <span>全部折叠</span>
- </div>
- </div>
- </div>
- </div>
- <div class="border-b border-b-[#e5e7eb] p-3">
- <div class="relative">
- <div class="">
- <q-input
- v-model="state.tree.text"
- outlined
- placeholder="搜索知识点..."
- :dense="true"
- >
- <template v-slot:prepend>
- <q-icon name="search" />
- </template>
- <template v-slot:append>
- <q-icon
- v-if="state.tree.text !== ''"
- name="clear"
- class="cursor-pointer"
- @click="state.tree.text = ''"
- />
- </template>
- </q-input>
- </div>
- </div>
- </div>
- <div class="flex-1 overflow-y-auto p-2" v-loading="state.tree.loading">
- <q-tree
- ref="ref_tree"
- :nodes="state.tree.data"
- node-key="value"
- label-key="label"
- v-model:selected="state.selected"
- :filter="state.tree.text"
- no-transition
- >
- <template v-slot:default-header="prop">
- <div class="flex w-full items-center text-sm">
- <div class="">
- {{ prop.node.label }}
- </div>
- <div class="ml-auto break-keep">
- {{ prop.node.total }}/{{ prop.node.totalMake }}题
- </div>
- </div>
- </template>
- </q-tree>
- </div>
- </div>
- <div
- class="col-span-7 flex h-full flex-col overflow-hidden rounded-xl bg-white shadow-md"
- >
- <div class="bg-[var(--czr-main-sub-color)] px-4 py-3 text-white">
- <div class="relative flex items-center text-base font-bold">
- <i class="fas fa-book mr-2"></i>
- 题目列表
- <span class="text-base" v-if="state.selected">
- ({{ treeMapCpt.get(state.selected)?.label }} - 共{{
- state.question.total
- }}题)
- </span>
- <div class="absolute right-2 ml-auto flex">
- <q-select
- class="select ml-4 w-[100px]"
- rounded
- standout="focus"
- v-model="state.question.type"
- :options="['错题', '正确题']"
- :dense="true"
- @update:modelValue="initQuestion"
- >
- </q-select>
- </div>
- </div>
- </div>
- <div
- class="flex-1 overflow-y-auto p-4"
- id="questionsContainer"
- v-loading="state.question.loading"
- >
- <template v-if="state.question.data?.length > 0">
- <listCom :data="state.question.data" />
- <!-- 分页控件 -->
- <div class="mt-6 flex justify-center">
- <div class="q-pa-lg flex-center flex">
- <q-pagination
- v-model="state.question.page"
- :max="Math.ceil(state.question.total / state.question.size)"
- :max-pages="6"
- boundary-numbers
- @update:modelValue="initQuestion"
- />
- </div>
- </div>
- </template>
- <template v-else>
- <div
- class="flex size-full items-center justify-center text-base font-semibold text-gray-700"
- >
- 暂无数据
- </div>
- </template>
- </div>
- </div>
- </div>
- </StudyLayout>
- </template>
- <script setup lang="ts">
- 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'
- import listCom from './list.vue'
- import { v4 } from 'uuid'
- const AppStore = useAppStore()
- const route = useRoute()
- const state: any = reactive({
- selected: null,
- tree: {
- text: '',
- loading: false,
- data: [],
- },
- question: {
- uuid: '',
- loading: false,
- type: '错题',
- data: [],
- total: 0,
- page: 1,
- size: 10,
- },
- })
- const ref_tree = ref()
- const treeMapCpt = computed(() => {
- const map = new Map()
- const deep = (arr) => {
- arr.forEach((v) => {
- map.set(v.value, v)
- if (v.children?.length > 0) {
- deep(v.children)
- }
- })
- }
- deep(state.tree.data)
- return map
- })
- 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: any = []) => {
- return arr.map((v) => {
- v.total = v.size || 0
- v.totalMake = v.questionSize || 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)
- })
- .finally(() => {
- state.tree.loading = false
- })
- }
- const initQuestion = () => {
- if (!state.selected) {
- return
- }
- state.question.loading = true
- state.question.data = []
- const uuid = v4()
- state.question.uuid = uuid + ''
- trainingCampQuestionList({
- pageNum: state.question.page,
- pageSize: state.question.size,
- category: AppStore.studentInfo?.grade,
- subject: route.meta.subjectId,
- correct: state.question.type !== '错题',
- questionTypeCode: treeMapCpt.value.get(state.selected).questionTypeCode,
- studentId: AppStore.studentInfo?.studentId,
- })
- .then(({ rows, total }: any) => {
- if (uuid === state.question.uuid) {
- 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-main-color)',
- )
- })
- </script>
- <style lang="scss" scoped>
- $primary: red;
- .search-input:focus {
- box-shadow: 0 0 0 3px rgba(var(--czr-main-color-rgb), 0.2);
- }
- :deep(.select) {
- .ellipsis {
- color: #ffffff;
- }
- .q-select__dropdown-icon {
- color: #ffffff;
- }
- }
- :deep(.date) {
- .q-placeholder {
- color: #ffffff;
- }
- }
- :deep(.focus) {
- background: rgba(0, 0, 0, 0.1) !important;
- }
- :deep(.q-tree__node--selected),
- :deep(.q-tree__node--selected .q-tree__node-header-content) {
- color: var(--czr-main-color) !important;
- }
- // FILE (create it): src/quasar-variables.sass
- </style>
|