diff --git a/src/components/pages/PageMaintenance.vue b/src/components/pages/PageMaintenance.vue new file mode 100644 index 0000000..83c2072 --- /dev/null +++ b/src/components/pages/PageMaintenance.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/composables/page-drivers/useMaintenancePage.ts b/src/composables/page-drivers/useMaintenancePage.ts new file mode 100644 index 0000000..23a920f --- /dev/null +++ b/src/composables/page-drivers/useMaintenancePage.ts @@ -0,0 +1,46 @@ +import { computed, ref } from 'vue' +import type { MaintenancePageModel } from '@/models/page' + +export interface UseMaintenancePageOptions { + title: string + records: unknown[] + itemsPerPage?: number +} + +export function useMaintenancePage(options: UseMaintenancePageOptions) { + const search = ref>({}) + const searchPanelOpen = ref(false) + const currentPage = ref(1) + const itemsPerPage = options.itemsPerPage ?? 10 + + const pageCount = computed(() => + Math.max(1, Math.ceil(options.records.length / itemsPerPage)) + ) + + const pageModel = computed(() => ({ + type: 'maintenance', + title: options.title, + records: options.records, + loading: false, + error: null, + })) + + function load() { + // 由呼叫方在 load 中觸發資料載入;未來可擴充為非同步 + } + + function resetSearch() { + search.value = {} + } + + return { + pageModel, + search, + searchPanelOpen, + currentPage, + itemsPerPage, + pageCount, + load, + resetSearch, + } +} diff --git a/src/models/page.ts b/src/models/page.ts new file mode 100644 index 0000000..0a32be8 --- /dev/null +++ b/src/models/page.ts @@ -0,0 +1,12 @@ +export interface BasePageModel { + title: string + loading?: boolean + error?: string | null +} + +export interface MaintenancePageModel extends BasePageModel { + type: 'maintenance' + records: unknown[] +} + +export type PageModel = MaintenancePageModel diff --git a/src/models/student.ts b/src/models/student.ts new file mode 100644 index 0000000..2e32a29 --- /dev/null +++ b/src/models/student.ts @@ -0,0 +1,13 @@ +export interface StudentRecord { + id: number + studentId: string + name: string + department: string + grade: number + enrollYear: number + credits: number + advisor: string + email: string + phone: string + status: string +} diff --git a/src/shell/AppShell.vue b/src/shell/AppShell.vue new file mode 100644 index 0000000..376d7a0 --- /dev/null +++ b/src/shell/AppShell.vue @@ -0,0 +1,35 @@ + + + diff --git a/src/shell/AppTabs.vue b/src/shell/AppTabs.vue new file mode 100644 index 0000000..e958e66 --- /dev/null +++ b/src/shell/AppTabs.vue @@ -0,0 +1,114 @@ + + + diff --git a/src/shell/GlobalOverlays.vue b/src/shell/GlobalOverlays.vue new file mode 100644 index 0000000..d8a7e65 --- /dev/null +++ b/src/shell/GlobalOverlays.vue @@ -0,0 +1,199 @@ + + + diff --git a/src/stores/menu.ts b/src/stores/menu.ts index 4b01f08..14ed286 100644 --- a/src/stores/menu.ts +++ b/src/stores/menu.ts @@ -6,6 +6,7 @@ import { menuApi, type MenuNode } from '@/services/modules/menu' export interface LayoutMenuItem { title: string path?: string + icon?: string navigable?: boolean subItems?: LayoutMenuItem[] } diff --git a/src/stores/students.ts b/src/stores/students.ts index 8dcda7a..3d89d35 100644 --- a/src/stores/students.ts +++ b/src/stores/students.ts @@ -1,19 +1,8 @@ +import type { StudentRecord } from '@/models/student' import { defineStore } from 'pinia' import { ref } from 'vue' -export interface StudentRecord { - id: number - studentId: string - name: string - department: string - grade: number - enrollYear: number - credits: number - advisor: string - email: string - phone: string - status: string -} +export type { StudentRecord } from '@/models/student' const seedStudents: StudentRecord[] = [ {