123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- <template>
- <z-paging ref="paging" v-model="list" @query="handleQuery" @on-refresh="handleRefresh">
- <template #top>
- <mx-index-menus :columns="subjectMenus.length" :data="subjectMenus" :rows="1"
- class="!mx-0 !rounded-none" custom-action container-wrap-class="px-10 py-20"
- icon-size="36" title-class="text-content text-xs" @click="handleMenuClick"/>
- </template>
- <view v-if="list.length" class="p-30">
- <tree-view :tree-data="list">
- <template #command="{node}">
- <uv-button v-if="empty(node.children)" type="primary" shape="circle" text="开始练习"
- plain :custom-style="{height: '32px'}" @click="handleLeafClick(node)"/>
- </template>
- </tree-view>
- </view>
- </z-paging>
- </template>
- <script setup>
- import {ref, watchEffect} from 'vue'
- import _ from "lodash";
- import {useUserStorePageFilter} from "@/hooks/useUserStorePageFilter";
- import {empty} from "@/uni_modules/uv-ui-tools/libs/function/test";
- import {useTransfer} from "@/hooks/useTransfer";
- import TreeView from "@/pages/topic-center/index/components/tree-view.vue";
- import {useCacheStore} from "@/hooks/useCacheStore";
- import {cacheActions} from "@/hooks/defineCacheActions";
- const props = defineProps({
- subject: {
- type: Object,
- default: () => ({})
- }
- })
- const {transferTo} = useTransfer()
- const {dispatchCache, removeCache} = useCacheStore()
- const paging = ref(null)
- const list = ref([])
- const {menus} = useUserStorePageFilter("TopicCenter")
- const subjectMenus = ref([])
- const getSubjectMenus = function (subject) {
- return menus.value.filter(m => {
- const includeSatisfied = () => m.includeSubjects.includes(subject.subjectName)
- const excludeSatisfied = () => !m.excludeSubjects.includes(subject.subjectName)
- if (empty(m.includeSubjects) && empty(m.excludeSubjects)) return true
- if (m.includeSubjects?.length && m.excludeSubjects?.length) {
- const intersect = _.intersection(m.includeSubjects, m.excludeSubjects)
- if (intersect.length) throw new Error('conflicting subject: ' + intersect.join(','))
- return includeSatisfied() && excludeSatisfied()
- }
- if (m.includeSubjects?.length) return includeSatisfied()
- if (m.excludeSubjects?.length) return excludeSatisfied()
- })
- }
- const handleQuery = async () => {
- const {subjectId} = props.subject
- try {
- const data = await dispatchCache(cacheActions.getKnowledgeTree, {subjectId})
- data.forEach(k => k.expanded = false) // 默认收起,因为有缓存,防止用户之前打开过多引起渲染缓慢
- paging.value.completeByTotal(data, data.length)
- } catch {
- paging.value.complete(false)
- }
- }
- const handleRefresh = () => {
- const {subjectId} = props.subject
- removeCache(cacheActions.getKnowledgeTree, {subjectId})
- }
- const handleMenuClick = (menu) => {
- if (!menu.path) return
- transferTo(menu.path, menu.nextData, props.subject)
- }
- const handleLeafClick = (node) => {
- const next = {
- type: 1,
- knowledgeId: node.id,
- testType: 0,
- title: '知识点练习'
- }
- transferTo('/pages/topic-center/paper-exam/paper-exam', next)
- }
- // hooks
- // NOTE:因为dispatchCache要固化getSubjectMenus,所以调用要放在methods定义之后
- // NOTE:另外缓存需要用参数区隔,所以这里将prop.subject定义成了参数,否则,几个tabs会命中同一缓存,因为他们调用了相同的方法
- // NOTE:直接使用dispatchCache(action[Function]...)时特别要注意通过payload区分缓存结果!
- watchEffect(async () => subjectMenus.value = await dispatchCache(getSubjectMenus, props.subject))
- </script>
- <style scoped>
- </style>
|