-
-
-
-
-
+
diff --git a/nuxt.config.ts b/nuxt.config.ts
index a897070..66701b8 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -35,6 +35,7 @@ export default defineNuxtConfig({
indent: 2,
quotes: 'single',
semi: false,
+ commaDangle: 'only-multiline',
},
},
},
diff --git a/package.json b/package.json
index 414b623..2e8dc63 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,9 @@
"@nuxt/test-utils": "3.17.2",
"@tanstack/vue-table": "^8.21.2",
"@vee-validate/zod": "^4.15.0",
+ "@vue-office/docx": "^1.6.3",
+ "@vue-office/excel": "^1.7.14",
+ "@vue-office/pdf": "^2.0.10",
"@vue-office/pptx": "^1.0.1",
"@vueuse/core": "^13.0.0",
"class-variance-authority": "^0.7.1",
@@ -49,7 +52,9 @@
"@vueuse/nuxt": "^13.0.0",
"dayjs": "^1.11.13",
"dayjs-nuxt": "^2.1.11",
+ "eslint-plugin-prettier": "^5.2.6",
"pinia-plugin-persistedstate": "^4.2.0",
+ "prettier": "^3.5.3",
"shadcn-nuxt": "2.0.1",
"typescript": "^5.8.2"
}
diff --git a/pages/course/[id].vue b/pages/course/[id].vue
index 92063bb..7b8c19d 100644
--- a/pages/course/[id].vue
+++ b/pages/course/[id].vue
@@ -1,8 +1,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
- {{ course?.data.courseName || "未知课程" }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/pages/course/index.vue b/pages/course/index.vue
index fab3941..f0361a8 100644
--- a/pages/course/index.vue
+++ b/pages/course/index.vue
@@ -6,7 +6,6 @@ import type { FetchError } from 'ofetch'
import { createCourse, deleteCourse, listUserCourses } from '~/api/course'
definePageMeta({
- layout: 'no-sidebar',
requiresAuth: true,
})
@@ -100,245 +99,245 @@ const onDeleteCourse = (courseId: number) => {
-
-
+
+ 还没有创建或加入课程
+
+
+
+
diff --git a/pages/course/research/index.vue b/pages/course/research/index.vue
index 347962f..b2236e5 100644
--- a/pages/course/research/index.vue
+++ b/pages/course/research/index.vue
@@ -1,6 +1,6 @@
diff --git a/pages/course/resources/index.vue b/pages/course/resources/index.vue
index c2d7d8e..64d2546 100644
--- a/pages/course/resources/index.vue
+++ b/pages/course/resources/index.vue
@@ -1,6 +1,5 @@
diff --git a/pages/preview/[resource_url].vue b/pages/preview/[resource_url].vue
index 6c3aad0..2dfdae0 100644
--- a/pages/preview/[resource_url].vue
+++ b/pages/preview/[resource_url].vue
@@ -1,9 +1,19 @@
-
+
diff --git a/pages/user/authenticate.client.vue b/pages/user/authenticate.client.vue
index 1f6797e..d7141f3 100644
--- a/pages/user/authenticate.client.vue
+++ b/pages/user/authenticate.client.vue
@@ -6,6 +6,10 @@ import * as z from 'zod'
import type { FetchError } from 'ofetch'
import { userLogin, type LoginResponse } from '~/api'
+definePageMeta({
+ layout: 'blank',
+})
+
const loginState = useLoginState()
const {
query: { redirect },
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2152a82..d98b06b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -26,6 +26,15 @@ importers:
'@vee-validate/zod':
specifier: ^4.15.0
version: 4.15.0(vue@3.5.13(typescript@5.8.2))(zod@3.24.2)
+ '@vue-office/docx':
+ specifier: ^1.6.3
+ version: 1.6.3(vue-demi@0.14.6(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
+ '@vue-office/excel':
+ specifier: ^1.7.14
+ version: 1.7.14(vue-demi@0.14.6(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
+ '@vue-office/pdf':
+ specifier: ^2.0.10
+ version: 2.0.10(vue-demi@0.14.6(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
'@vue-office/pptx':
specifier: ^1.0.1
version: 1.0.1(vue-demi@0.14.6(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
@@ -111,9 +120,15 @@ importers:
dayjs-nuxt:
specifier: ^2.1.11
version: 2.1.11(magicast@0.3.5)
+ eslint-plugin-prettier:
+ specifier: ^5.2.6
+ version: 5.2.6(eslint@9.23.0(jiti@2.4.2))(prettier@3.5.3)
pinia-plugin-persistedstate:
specifier: ^4.2.0
version: 4.2.0(@pinia/nuxt@0.10.1(magicast@0.3.5)(pinia@3.0.1(typescript@5.8.2)(vue@3.5.13(typescript@5.8.2))))(magicast@0.3.5)(pinia@3.0.1(typescript@5.8.2)(vue@3.5.13(typescript@5.8.2)))
+ prettier:
+ specifier: ^3.5.3
+ version: 3.5.3
shadcn-nuxt:
specifier: 2.0.1
version: 2.0.1(magicast@0.3.5)
@@ -959,6 +974,10 @@ packages:
resolution: {integrity: sha512-25L86MyPvnlQoX2MTIV2OiUcb6vJ6aRbFa9pbwByn95INKD5mFH2smgjDhq+fwJoqAgvgbdJLj6Tz7V9X5CFAQ==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+ '@pkgr/core@0.2.4':
+ resolution: {integrity: sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==}
+ engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+
'@polka/url@1.0.0-next.28':
resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==}
@@ -1404,6 +1423,36 @@ packages:
vue:
optional: true
+ '@vue-office/docx@1.6.3':
+ resolution: {integrity: sha512-Cs+3CAaRBOWOiW4XAhTwwxJ0dy8cPIf6DqfNvYcD3YACiLwO4kuawLF2IAXxyijhbuOeoFsfvoVbOc16A/4bZA==}
+ peerDependencies:
+ '@vue/composition-api': ^1.7.1
+ vue: ^2.0.0 || >=3.0.0
+ vue-demi: ^0.14.6
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+
+ '@vue-office/excel@1.7.14':
+ resolution: {integrity: sha512-pVUgt+emDQUnW7q22CfnQ+jl43mM/7IFwYzOg7lwOwPEbiVB4K4qEQf+y/bc4xGXz75w1/e3Kz3G6wAafmFBFg==}
+ peerDependencies:
+ '@vue/composition-api': ^1.7.1
+ vue: ^2.0.0 || >=3.0.0
+ vue-demi: ^0.14.6
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+
+ '@vue-office/pdf@2.0.10':
+ resolution: {integrity: sha512-yHVLrMAKpMPBkhBwofFyGEtEeJF0Zd7oGmf56Pe5aj/xObdRq3E1CIZqTqhWJNgHV8oLQqaX0vs4p5T1zq+GIA==}
+ peerDependencies:
+ '@vue/composition-api': ^1.7.1
+ vue: ^2.0.0 || >=3.0.0
+ vue-demi: ^0.14.6
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+
'@vue-office/pptx@1.0.1':
resolution: {integrity: sha512-+V7Kctzl6f6+Yk4NaD/wQGRIkqLWcowe0jEhPexWQb8Oilbzt1OyhWRWcMsxNDTdrgm6aMLP+0/tmw27cxddMg==}
peerDependencies:
@@ -2268,6 +2317,20 @@ packages:
peerDependencies:
eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
+ eslint-plugin-prettier@5.2.6:
+ resolution: {integrity: sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ '@types/eslint': '>=8.0.0'
+ eslint: '>=8.0.0'
+ eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0'
+ prettier: '>=3.0.0'
+ peerDependenciesMeta:
+ '@types/eslint':
+ optional: true
+ eslint-config-prettier:
+ optional: true
+
eslint-plugin-regexp@2.7.0:
resolution: {integrity: sha512-U8oZI77SBtH8U3ulZ05iu0qEzIizyEDXd+BWHvyVxTOjGwcDcvy/kEpgFG4DYca2ByRLiVPFZ2GeH7j1pdvZTA==}
engines: {node: ^18 || >=20}
@@ -2379,6 +2442,9 @@ packages:
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+ fast-diff@1.3.0:
+ resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
+
fast-fifo@1.3.2:
resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==}
@@ -3632,6 +3698,15 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
+ prettier-linter-helpers@1.0.0:
+ resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==}
+ engines: {node: '>=6.0.0'}
+
+ prettier@3.5.3:
+ resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==}
+ engines: {node: '>=14'}
+ hasBin: true
+
pretty-bytes@6.1.1:
resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
engines: {node: ^14.13.1 || >=16.0.0}
@@ -4038,6 +4113,10 @@ packages:
engines: {node: '>=14.0.0'}
hasBin: true
+ synckit@0.11.4:
+ resolution: {integrity: sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+
synckit@0.9.2:
resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==}
engines: {node: ^14.18.0 || >=16.0.0}
@@ -5759,6 +5838,8 @@ snapshots:
'@pkgr/core@0.2.2': {}
+ '@pkgr/core@0.2.4': {}
+
'@polka/url@1.0.0-next.28': {}
'@poppinss/colors@4.1.4':
@@ -6178,6 +6259,21 @@ snapshots:
optionalDependencies:
vue: 3.5.13(typescript@5.8.2)
+ '@vue-office/docx@1.6.3(vue-demi@0.14.6(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))':
+ dependencies:
+ vue: 3.5.13(typescript@5.8.2)
+ vue-demi: 0.14.6(vue@3.5.13(typescript@5.8.2))
+
+ '@vue-office/excel@1.7.14(vue-demi@0.14.6(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))':
+ dependencies:
+ vue: 3.5.13(typescript@5.8.2)
+ vue-demi: 0.14.6(vue@3.5.13(typescript@5.8.2))
+
+ '@vue-office/pdf@2.0.10(vue-demi@0.14.6(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))':
+ dependencies:
+ vue: 3.5.13(typescript@5.8.2)
+ vue-demi: 0.14.6(vue@3.5.13(typescript@5.8.2))
+
'@vue-office/pptx@1.0.1(vue-demi@0.14.6(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))':
dependencies:
vue: 3.5.13(typescript@5.8.2)
@@ -7091,6 +7187,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ eslint-plugin-prettier@5.2.6(eslint@9.23.0(jiti@2.4.2))(prettier@3.5.3):
+ dependencies:
+ eslint: 9.23.0(jiti@2.4.2)
+ prettier: 3.5.3
+ prettier-linter-helpers: 1.0.0
+ synckit: 0.11.4
+
eslint-plugin-regexp@2.7.0(eslint@9.23.0(jiti@2.4.2)):
dependencies:
'@eslint-community/eslint-utils': 4.5.1(eslint@9.23.0(jiti@2.4.2))
@@ -7254,6 +7357,8 @@ snapshots:
fast-deep-equal@3.1.3: {}
+ fast-diff@1.3.0: {}
+
fast-fifo@1.3.2: {}
fast-glob@3.3.3:
@@ -8741,6 +8846,12 @@ snapshots:
prelude-ls@1.2.1: {}
+ prettier-linter-helpers@1.0.0:
+ dependencies:
+ fast-diff: 1.3.0
+
+ prettier@3.5.3: {}
+
pretty-bytes@6.1.1: {}
process-nextick-args@2.0.1: {}
@@ -9216,6 +9327,11 @@ snapshots:
csso: 5.0.5
picocolors: 1.1.1
+ synckit@0.11.4:
+ dependencies:
+ '@pkgr/core': 0.2.4
+ tslib: 2.8.1
+
synckit@0.9.2:
dependencies:
'@pkgr/core': 0.1.2
diff --git a/stores/breadcrumbs.ts b/stores/breadcrumbs.ts
new file mode 100644
index 0000000..332b5c3
--- /dev/null
+++ b/stores/breadcrumbs.ts
@@ -0,0 +1,24 @@
+import type { IBreadcrumbItem } from '~/types'
+
+export const useBreadcrumbs = defineStore('breadcrumbs', () => {
+ const breadcrumbs = ref
([])
+
+ const setBreadcrumbs = (items: IBreadcrumbItem[]) => {
+ breadcrumbs.value = items
+ }
+
+ const clearBreadcrumbs = () => {
+ breadcrumbs.value = []
+ }
+
+ const getBreadcrumbs = () => {
+ return breadcrumbs.value
+ }
+
+ return {
+ breadcrumbs,
+ getBreadcrumbs,
+ setBreadcrumbs,
+ clearBreadcrumbs,
+ }
+})
diff --git a/types/index.ts b/types/index.ts
index ed7b963..2a5dbeb 100644
--- a/types/index.ts
+++ b/types/index.ts
@@ -2,3 +2,8 @@ export * from './user'
export * from './course'
export type { FetchError } from 'ofetch'
+
+export interface IBreadcrumbItem {
+ label: string
+ path?: string
+}
diff --git a/types/nuxt.d.ts b/types/nuxt.d.ts
new file mode 100644
index 0000000..cd2ad8f
--- /dev/null
+++ b/types/nuxt.d.ts
@@ -0,0 +1,8 @@
+declare module '#app' {
+ interface PageMeta {
+ /** 隐藏侧边栏 */
+ hideSidebar?: boolean
+ }
+}
+
+export {}