feat: 更新导航结构,重构课程准备页面及其子页面,添加新组件
This commit is contained in:
parent
6221602d5e
commit
b03b2d9273
@ -10,7 +10,7 @@
|
||||
--card-foreground: 0 0% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 0 0% 3.9%;
|
||||
--primary: 0 0% 9%;
|
||||
--primary: 238.73deg 83.53% 66.67%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 0 0% 96.1%;
|
||||
--secondary-foreground: 0 0% 9%;
|
||||
@ -46,7 +46,7 @@
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 0 0% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 98%;
|
||||
--primary: 234.45deg 89.47% 73.92%;
|
||||
--primary-foreground: 0 0% 9%;
|
||||
--secondary: 0 0% 14.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
|
@ -1,7 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import type { SubNavItem } from '../nav/Secondary.vue'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import type { NavSecondaryItem } from '../nav/Secondary.vue'
|
||||
|
||||
defineProps<{ subnavs?: SubNavItem[] }>()
|
||||
defineProps<{
|
||||
navSecondary?: NavSecondaryItem[]
|
||||
contentClass?: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -9,12 +13,13 @@ defineProps<{ subnavs?: SubNavItem[] }>()
|
||||
<!-- <h1 class="pl-2 text-xl font-medium">外部标题</h1> -->
|
||||
<slot name="subnav">
|
||||
<NavSecondary
|
||||
v-if="subnavs && subnavs.length"
|
||||
:navs="subnavs"
|
||||
v-if="navSecondary && navSecondary.length"
|
||||
:navs="navSecondary"
|
||||
/>
|
||||
</slot>
|
||||
<div
|
||||
class="bg-white h-full rounded-lg shadow-sm p-8 dark:bg-neutral-900 z-20"
|
||||
class="h-full rounded-lg shadow-sm overflow-hidden"
|
||||
:class="twMerge('bg-white dark:bg-neutral-900 p-8 z-20', contentClass)"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
7
components/fn/teach/LessonPlan.vue
Normal file
7
components/fn/teach/LessonPlan.vue
Normal file
@ -0,0 +1,7 @@
|
||||
<script lang="ts" setup></script>
|
||||
|
||||
<template>
|
||||
<div>教案设计</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
export interface SubNavItem {
|
||||
export interface NavSecondaryItem {
|
||||
label: string
|
||||
to: string
|
||||
}
|
||||
@ -7,7 +7,7 @@ export interface SubNavItem {
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
navs: SubNavItem[]
|
||||
navs: NavSecondaryItem[]
|
||||
}>()
|
||||
|
||||
const route = useRoute()
|
||||
|
49
components/nav/Tertiary.vue
Normal file
49
components/nav/Tertiary.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<script lang="ts">
|
||||
export interface NavTertiaryItem {
|
||||
label: string
|
||||
to?: string
|
||||
component?: string | Component
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
navs: NavTertiaryItem[]
|
||||
modelValue?: number
|
||||
}>(),
|
||||
{
|
||||
modelValue: 0,
|
||||
},
|
||||
)
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', idx: number): void
|
||||
}>()
|
||||
|
||||
const isActiveItem = (idx: number) => {
|
||||
return props.modelValue === idx
|
||||
}
|
||||
|
||||
const onClickItem = (idx: number) => {
|
||||
emit('update:modelValue', idx)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div
|
||||
v-for="(nav, i) in navs"
|
||||
:key="i"
|
||||
class="flex justify-center items-center gap-2 p-2.5 rounded-sm cursor-pointer select-none transition-colors duration-75"
|
||||
:class="`${isActiveItem(i) ? 'bg-primary text-primary-foreground' : 'bg-accent text-foreground'}`"
|
||||
@click="onClickItem(i)"
|
||||
>
|
||||
<span class="text-sm font-medium">
|
||||
{{ nav.label }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
@ -65,7 +65,7 @@ watch(
|
||||
|
||||
<template>
|
||||
<AppContainer
|
||||
:subnavs="[
|
||||
:nav-secondary="[
|
||||
{
|
||||
label: '课程章节',
|
||||
to: `/course/${id}/chapters`,
|
||||
|
@ -1,26 +1,20 @@
|
||||
export const nav = [
|
||||
import type { NavSecondaryItem } from '~/components/nav/Secondary.vue'
|
||||
|
||||
export const nav: NavSecondaryItem[] = [
|
||||
{
|
||||
items: [
|
||||
{
|
||||
title: 'AI 教学设计',
|
||||
url: '/course/prep/teach',
|
||||
icon: 'tabler:calendar-cog',
|
||||
},
|
||||
{
|
||||
title: 'AI 课件设计',
|
||||
url: '/course/prep/deck',
|
||||
icon: 'tabler:book-2',
|
||||
},
|
||||
{
|
||||
title: 'AI 出题',
|
||||
url: '/course/prep/quiz',
|
||||
icon: 'tabler:notebook',
|
||||
},
|
||||
{
|
||||
title: '微视频制作',
|
||||
url: '/course/prep/test',
|
||||
icon: 'tabler:video',
|
||||
},
|
||||
],
|
||||
label: '教学设计',
|
||||
to: '/course/prep/teach',
|
||||
},
|
||||
{
|
||||
label: '课件设计',
|
||||
to: '/course/prep/deck',
|
||||
},
|
||||
{
|
||||
label: 'AI 出题',
|
||||
to: '/course/prep/quiz',
|
||||
},
|
||||
// {
|
||||
// label: '微视频制作',
|
||||
// to: '/course/prep/test',
|
||||
// },
|
||||
]
|
||||
|
@ -3,13 +3,32 @@ import { nav } from './config'
|
||||
|
||||
definePageMeta({
|
||||
requiresAuth: true,
|
||||
hideSidebar: true,
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: 'AI 课件设计 | 备课',
|
||||
})
|
||||
|
||||
const { setBreadcrumbs } = useBreadcrumbs()
|
||||
|
||||
onMounted(() => {
|
||||
setBreadcrumbs([
|
||||
{
|
||||
label: 'AI 备课',
|
||||
path: '/course/prep',
|
||||
},
|
||||
{
|
||||
label: 'AI 课件设计',
|
||||
},
|
||||
])
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppPageWithSidebar :sidebar-nav="nav">
|
||||
<h1>deck</h1>
|
||||
</AppPageWithSidebar>
|
||||
<AppContainer :nav-secondary="nav">
|
||||
<h1>AI 课件设计</h1>
|
||||
</AppContainer>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -3,13 +3,32 @@ import { nav } from './config'
|
||||
|
||||
definePageMeta({
|
||||
requiresAuth: true,
|
||||
hideSidebar: true,
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: 'AI 出题 | 备课',
|
||||
})
|
||||
|
||||
const { setBreadcrumbs } = useBreadcrumbs()
|
||||
|
||||
onMounted(() => {
|
||||
setBreadcrumbs([
|
||||
{
|
||||
label: 'AI 备课',
|
||||
path: '/course/prep',
|
||||
},
|
||||
{
|
||||
label: 'AI 出题',
|
||||
},
|
||||
])
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppPageWithSidebar :sidebar-nav="nav">
|
||||
<h1>quiz</h1>
|
||||
</AppPageWithSidebar>
|
||||
<AppContainer :nav-secondary="nav">
|
||||
<h1>AI 出题</h1>
|
||||
</AppContainer>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -1,19 +1,98 @@
|
||||
<script lang="ts" setup>
|
||||
import { nav } from './config'
|
||||
import { FnTeachLessonPlan } from '#components'
|
||||
import type { NavTertiaryItem } from '~/components/nav/Tertiary.vue'
|
||||
|
||||
definePageMeta({
|
||||
requiresAuth: true,
|
||||
hideSidebar: true,
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: 'AI 教学设计 | 备课',
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { setBreadcrumbs } = useBreadcrumbs()
|
||||
|
||||
const tertiaryNavs: NavTertiaryItem[] = [
|
||||
{ label: '教案设计', component: FnTeachLessonPlan },
|
||||
{ label: '案例设计' },
|
||||
{ label: '课程标准' },
|
||||
{ label: '知识图谱' },
|
||||
{ label: '课程章节' },
|
||||
{ label: '教研计划' },
|
||||
]
|
||||
|
||||
const currentNav = ref(0)
|
||||
|
||||
watch(currentNav, (val) => {
|
||||
router.replace({
|
||||
query: {
|
||||
fn: val,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (route.query.fn && !isNaN(Number(route.query.fn))) {
|
||||
currentNav.value = Number(route.query.fn)
|
||||
}
|
||||
|
||||
setBreadcrumbs([
|
||||
{
|
||||
label: 'AI 备课',
|
||||
path: '/course/prep',
|
||||
},
|
||||
{
|
||||
label: 'AI 教学设计',
|
||||
},
|
||||
])
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppPageWithSidebar :sidebar-nav="nav">
|
||||
<h1>teach</h1>
|
||||
</AppPageWithSidebar>
|
||||
<AppContainer
|
||||
:nav-secondary="nav"
|
||||
content-class="flex items-start p-0"
|
||||
>
|
||||
<div class="w-[188px] h-full border-r shadow-xl">
|
||||
<div class="flex justify-center items-center h-16 border-b gap-2">
|
||||
<Icon
|
||||
name="fluent-color:design-ideas-24"
|
||||
class="text-2xl"
|
||||
/>
|
||||
<h1 class="text-base font-medium text-foreground">AI 教学设计</h1>
|
||||
</div>
|
||||
<div class="p-2">
|
||||
<NavTertiary
|
||||
v-model="currentNav"
|
||||
:navs="tertiaryNavs"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1 h-full p-6">
|
||||
<Suspense>
|
||||
<component
|
||||
:is="tertiaryNavs[currentNav].component"
|
||||
v-if="tertiaryNavs[currentNav].component"
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
class="flex flex-col items-center justify-center w-full h-full gap-2"
|
||||
>
|
||||
<Icon
|
||||
name="tabler:mood-sad"
|
||||
class="text-6xl text-muted-foreground"
|
||||
/>
|
||||
<p class="text text-muted-foreground">
|
||||
该功能暂不可用
|
||||
</p>
|
||||
</div>
|
||||
</Suspense>
|
||||
</div>
|
||||
</AppContainer>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -5,7 +5,9 @@ definePageMeta({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>Resources</div>
|
||||
<AppContainer>
|
||||
<div>课程资源</div>
|
||||
</AppContainer>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
Loading…
Reference in New Issue
Block a user