feat: 更新导航结构,重构课程准备页面及其子页面,添加新组件
This commit is contained in:
parent
6221602d5e
commit
b03b2d9273
@ -10,7 +10,7 @@
|
|||||||
--card-foreground: 0 0% 3.9%;
|
--card-foreground: 0 0% 3.9%;
|
||||||
--popover: 0 0% 100%;
|
--popover: 0 0% 100%;
|
||||||
--popover-foreground: 0 0% 3.9%;
|
--popover-foreground: 0 0% 3.9%;
|
||||||
--primary: 0 0% 9%;
|
--primary: 238.73deg 83.53% 66.67%;
|
||||||
--primary-foreground: 0 0% 98%;
|
--primary-foreground: 0 0% 98%;
|
||||||
--secondary: 0 0% 96.1%;
|
--secondary: 0 0% 96.1%;
|
||||||
--secondary-foreground: 0 0% 9%;
|
--secondary-foreground: 0 0% 9%;
|
||||||
@ -46,7 +46,7 @@
|
|||||||
--card-foreground: 0 0% 98%;
|
--card-foreground: 0 0% 98%;
|
||||||
--popover: 0 0% 3.9%;
|
--popover: 0 0% 3.9%;
|
||||||
--popover-foreground: 0 0% 98%;
|
--popover-foreground: 0 0% 98%;
|
||||||
--primary: 0 0% 98%;
|
--primary: 234.45deg 89.47% 73.92%;
|
||||||
--primary-foreground: 0 0% 9%;
|
--primary-foreground: 0 0% 9%;
|
||||||
--secondary: 0 0% 14.9%;
|
--secondary: 0 0% 14.9%;
|
||||||
--secondary-foreground: 0 0% 98%;
|
--secondary-foreground: 0 0% 98%;
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
<script lang="ts" setup>
|
<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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -9,12 +13,13 @@ defineProps<{ subnavs?: SubNavItem[] }>()
|
|||||||
<!-- <h1 class="pl-2 text-xl font-medium">外部标题</h1> -->
|
<!-- <h1 class="pl-2 text-xl font-medium">外部标题</h1> -->
|
||||||
<slot name="subnav">
|
<slot name="subnav">
|
||||||
<NavSecondary
|
<NavSecondary
|
||||||
v-if="subnavs && subnavs.length"
|
v-if="navSecondary && navSecondary.length"
|
||||||
:navs="subnavs"
|
:navs="navSecondary"
|
||||||
/>
|
/>
|
||||||
</slot>
|
</slot>
|
||||||
<div
|
<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 />
|
<slot />
|
||||||
</div>
|
</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">
|
<script lang="ts">
|
||||||
export interface SubNavItem {
|
export interface NavSecondaryItem {
|
||||||
label: string
|
label: string
|
||||||
to: string
|
to: string
|
||||||
}
|
}
|
||||||
@ -7,7 +7,7 @@ export interface SubNavItem {
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
defineProps<{
|
defineProps<{
|
||||||
navs: SubNavItem[]
|
navs: NavSecondaryItem[]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const route = useRoute()
|
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>
|
<template>
|
||||||
<AppContainer
|
<AppContainer
|
||||||
:subnavs="[
|
:nav-secondary="[
|
||||||
{
|
{
|
||||||
label: '课程章节',
|
label: '课程章节',
|
||||||
to: `/course/${id}/chapters`,
|
to: `/course/${id}/chapters`,
|
||||||
|
@ -1,26 +1,20 @@
|
|||||||
export const nav = [
|
import type { NavSecondaryItem } from '~/components/nav/Secondary.vue'
|
||||||
|
|
||||||
|
export const nav: NavSecondaryItem[] = [
|
||||||
{
|
{
|
||||||
items: [
|
label: '教学设计',
|
||||||
{
|
to: '/course/prep/teach',
|
||||||
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/deck',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'AI 出题',
|
||||||
|
to: '/course/prep/quiz',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// label: '微视频制作',
|
||||||
|
// to: '/course/prep/test',
|
||||||
|
// },
|
||||||
]
|
]
|
||||||
|
@ -3,13 +3,32 @@ import { nav } from './config'
|
|||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
|
hideSidebar: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: 'AI 课件设计 | 备课',
|
||||||
|
})
|
||||||
|
|
||||||
|
const { setBreadcrumbs } = useBreadcrumbs()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setBreadcrumbs([
|
||||||
|
{
|
||||||
|
label: 'AI 备课',
|
||||||
|
path: '/course/prep',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'AI 课件设计',
|
||||||
|
},
|
||||||
|
])
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<AppPageWithSidebar :sidebar-nav="nav">
|
<AppContainer :nav-secondary="nav">
|
||||||
<h1>deck</h1>
|
<h1>AI 课件设计</h1>
|
||||||
</AppPageWithSidebar>
|
</AppContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -3,13 +3,32 @@ import { nav } from './config'
|
|||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
|
hideSidebar: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: 'AI 出题 | 备课',
|
||||||
|
})
|
||||||
|
|
||||||
|
const { setBreadcrumbs } = useBreadcrumbs()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setBreadcrumbs([
|
||||||
|
{
|
||||||
|
label: 'AI 备课',
|
||||||
|
path: '/course/prep',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'AI 出题',
|
||||||
|
},
|
||||||
|
])
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<AppPageWithSidebar :sidebar-nav="nav">
|
<AppContainer :nav-secondary="nav">
|
||||||
<h1>quiz</h1>
|
<h1>AI 出题</h1>
|
||||||
</AppPageWithSidebar>
|
</AppContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -1,19 +1,98 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { nav } from './config'
|
import { nav } from './config'
|
||||||
|
import { FnTeachLessonPlan } from '#components'
|
||||||
|
import type { NavTertiaryItem } from '~/components/nav/Tertiary.vue'
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
|
hideSidebar: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: 'AI 教学设计 | 备课',
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<AppPageWithSidebar :sidebar-nav="nav">
|
<AppContainer
|
||||||
<h1>teach</h1>
|
:nav-secondary="nav"
|
||||||
</AppPageWithSidebar>
|
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>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -5,7 +5,9 @@ definePageMeta({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>Resources</div>
|
<AppContainer>
|
||||||
|
<div>课程资源</div>
|
||||||
|
</AppContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
Loading…
Reference in New Issue
Block a user