fixing adn docing

This commit is contained in:
skytek_xinliang
2026-06-01 14:44:39 +08:00
parent 7b0cfe4448
commit f61432ad8a
17 changed files with 25 additions and 41 deletions
+2 -2
View File
@@ -57,13 +57,13 @@ router -> AppShell -> layout -> view -> Section -> Item
- `views/FncPage.vue` - `views/FncPage.vue`
- `views/Settings.vue` - `views/Settings.vue`
- `views/maint/*` - `views/maint/*`
- `components/MaintShell.vue` - `components/maint/MaintShell.vue`
- `components/maint/*` - `components/maint/*`
- `components/sections/*` - `components/sections/*`
- `components/items/*` - `components/items/*`
- `composables/page-drivers/*MaintenancePage.ts` - `composables/page-drivers/*MaintenancePage.ts`
- `composables/maint/*` - `composables/maint/*`
- `composables/commands/*` - `composables/useCrudCommands.ts`
- `stores/students.ts` - `stores/students.ts`
- `stores/semesters.ts` - `stores/semesters.ts`
- demo assets 與 demo language keys - demo assets 與 demo language keys
+1 -1
View File
@@ -97,7 +97,7 @@ Layout composables
- `src/views/maint/*` - `src/views/maint/*`
- `src/components/maint/*` - `src/components/maint/*`
- `src/composables/maint/*` - `src/composables/maint/*`
- `src/components/MaintShell.vue` - `src/components/maint/MaintShell.vue`
- `src/stores/students.ts` - `src/stores/students.ts`
- `src/stores/semesters.ts` - `src/stores/semesters.ts`
- `src/views/FncPage.vue` - `src/views/FncPage.vue`
+1 -1
View File
@@ -9,7 +9,7 @@
- `layouts/`App Shell 層的 layout 元件。詳見 `src/components/layouts/GUIDE.md` - `layouts/`App Shell 層的 layout 元件。詳見 `src/components/layouts/GUIDE.md`
- `base/`:真正跨頁共用的基礎元件。詳見 `src/components/base/GUIDE.md` - `base/`:真正跨頁共用的基礎元件。詳見 `src/components/base/GUIDE.md`
`MaintShell.vue` 是 maintenance 頁面的通用外殼元件,放在 `src/components/` 頂層 `MaintShell.vue` 是 maintenance 頁面的通用外殼元件,放在 `src/components/maint/`
## 規則 ## 規則
@@ -1,7 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
interface Props { interface Props {
title: string title: string
backLabel?: string
error?: string error?: string
loading?: boolean loading?: boolean
message?: string message?: string
@@ -10,7 +9,6 @@ interface Props {
} }
withDefaults(defineProps<Props>(), { withDefaults(defineProps<Props>(), {
backLabel: '返回',
resetLabel: '清除', resetLabel: '清除',
submitLabel: '存檔', submitLabel: '存檔',
}) })
@@ -50,7 +48,6 @@ const emit = defineEmits<{
{{ submitLabel }} {{ submitLabel }}
</v-btn> </v-btn>
<v-btn type="button" variant="tonal" @click="emit('reset')">{{ resetLabel }}</v-btn> <v-btn type="button" variant="tonal" @click="emit('reset')">{{ resetLabel }}</v-btn>
<v-btn type="button" variant="text" @click="emit('back')">{{ backLabel }}</v-btn>
</v-row> </v-row>
</v-card> </v-card>
</v-container> </v-container>
+1 -7
View File
@@ -6,9 +6,7 @@ interface Props {
loading?: boolean loading?: boolean
} }
withDefaults(defineProps<Props>(), { withDefaults(defineProps<Props>(), {})
backLabel: '返回',
})
const emit = defineEmits<{ const emit = defineEmits<{
search: [] search: []
@@ -38,9 +36,5 @@ const emit = defineEmits<{
</v-card> </v-card>
<slot name="sections" /> <slot name="sections" />
<v-row class="pa-4">
<v-btn variant="tonal" @click="emit('back')">{{ backLabel }}</v-btn>
</v-row>
</v-container> </v-container>
</template> </template>
+5 -11
View File
@@ -4,12 +4,13 @@
## 子目錄 ## 子目錄
- `page-drivers/`:頁面資料協調與 page model 組裝。 - `page-drivers/`:頁面資料協調與 page model 組裝(僅複雜頁面使用)
- `commands/`:命令式副作用流程,例如 create/edit/save/delete。
- `layout/`AppShell / layout 狀態與事件協調。
- `maint/`maintenance demo 的表單、CRUD、editable grid 狀態。 - `maint/`maintenance demo 的表單、CRUD、editable grid 狀態。
- `layout/`AppShell / layout 狀態與事件協調。
頂層也可放通用 composable,例如 `useApiCall.ts`:封裝 loading / data / error / execute 模式、自動 snackbar 錯誤提示與取消請求過濾。適合為單一 API 呼叫提供輕量狀態管理,但不替代 page driver 或 command composable。 頂層放通用 composable
- `useApiCall.ts`:封裝 loading / data / error / execute 模式。
- `useCrudCommands.ts`:通用 CRUD 狀態機(新增 / 編輯 / 檢視 / 儲存 / highlight)。
## 新增規則 ## 新增規則
@@ -40,11 +41,4 @@ const { pageModel, search, handleSubmit } = useXxxPage()
``` ```
模板中直接使用,不寫 `.value``:page="pageModel"``v-model="search"` 模板中直接使用,不寫 `.value``:page="pageModel"``v-model="search"`
## Commands
Command composable 負責副作用流程,不負責畫面布局:
- 新增 / 編輯 / 刪除 / 儲存
- 儲存前確認
- 成功後重新載入或 highlight
- 與 store/service 的 mutation 流程 - 與 store/service 的 mutation 流程
@@ -1,6 +1,6 @@
import { computed, ref, watch } from 'vue' import { computed, ref, watch } from 'vue'
import { useDisplay } from 'vuetify' import { useDisplay } from 'vuetify'
import { useCrudCommands } from '@/composables/commands/useCrudCommands' import { useCrudCommands } from '@/composables/useCrudCommands'
import { useMaintenanceCrudFlow } from '@/composables/maint/useMaintenanceCrudFlow' import { useMaintenanceCrudFlow } from '@/composables/maint/useMaintenanceCrudFlow'
import { import {
type StudentFormState, type StudentFormState,
+1 -1
View File
@@ -29,7 +29,7 @@ const pageModel = computed(() => ({ title: '我的頁面' }))
```vue ```vue
<script setup lang="ts"> <script setup lang="ts">
import MaintShell from '@/components/MaintShell.vue' import MaintShell from '@/components/maint/MaintShell.vue'
import { useXxxPage } from '@/composables/page-drivers/useXxxPage' import { useXxxPage } from '@/composables/page-drivers/useXxxPage'
const { pageModel, search, handleSave, ... } = useXxxPage() const { pageModel, search, handleSave, ... } = useXxxPage()
</script> </script>
+7 -3
View File
@@ -4,12 +4,12 @@ import BaseFormTextField from '@/components/base/BaseFormTextField.vue'
import SectionFormPage from '@/components/sections/SectionFormPage.vue' import SectionFormPage from '@/components/sections/SectionFormPage.vue'
import { useSectionsDemoPage } from '@/composables/page-drivers/useSectionsDemoPage' import { useSectionsDemoPage } from '@/composables/page-drivers/useSectionsDemoPage'
const { demoForm, handleFormBack, handleFormSubmit, pageModel, resetDemoForm } = useSectionsDemoPage() const { demoForm, handleFormBack, handleFormSubmit, pageModel, resetDemoForm } =
useSectionsDemoPage()
</script> </script>
<template> <template>
<SectionFormPage <SectionFormPage
back-label="回到列表"
reset-label="清除" reset-label="清除"
submit-label="送出" submit-label="送出"
:message="pageModel.formMessage" :message="pageModel.formMessage"
@@ -27,7 +27,11 @@ const { demoForm, handleFormBack, handleFormSubmit, pageModel, resetDemoForm } =
<BaseFormSelect v-model="demoForm.owner" label="單位" :items="pageModel.ownerOptions" /> <BaseFormSelect v-model="demoForm.owner" label="單位" :items="pageModel.ownerOptions" />
</v-col> </v-col>
<v-col cols="12" md="3"> <v-col cols="12" md="3">
<BaseFormSelect v-model="demoForm.category" label="類型" :items="pageModel.categoryOptions" /> <BaseFormSelect
v-model="demoForm.category"
label="類型"
:items="pageModel.categoryOptions"
/>
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<BaseFormTextField v-model="demoForm.description" label="說明" /> <BaseFormTextField v-model="demoForm.description" label="說明" />
+1 -6
View File
@@ -8,12 +8,7 @@ const { handleQueryBack, handleQuerySearch, pageModel, queryFilters } = useSecti
</script> </script>
<template> <template>
<SectionQueryPage <SectionQueryPage title="查詢頁DEMO" @back="handleQueryBack" @search="handleQuerySearch">
back-label="回到列表"
title="查詢頁DEMO"
@back="handleQueryBack"
@search="handleQuerySearch"
>
<template #filters> <template #filters>
<v-col cols="12" md="4"> <v-col cols="12" md="4">
<BaseFormTextField v-model="queryFilters.keyword" label="關鍵字" /> <BaseFormTextField v-model="queryFilters.keyword" label="關鍵字" />
+1 -1
View File
@@ -1,6 +1,6 @@
# Maintenance Views Guide # Maintenance Views Guide
`views/maint` 是維護頁 demo。所有檔案都是自含的 route entry,UI 與流程直接在 view 中組合 `MaintShell``components/sections``components/items` 與 composable。 `views/maint` 是維護頁 demo。所有檔案都是自含的 route entry,UI 與流程直接在 view 中組合 `components/maint/MaintShell``components/sections``components/items` 與 composable。
## 目前範本 ## 目前範本
+1 -1
View File
@@ -5,7 +5,7 @@ import DetailSidePanel from '@/components/maint/master-detail/DetailSidePanel.vu
import MasterFileFormFields from '@/components/maint/MasterFileFormFields.vue' import MasterFileFormFields from '@/components/maint/MasterFileFormFields.vue'
import MntDialogCard from '@/components/maint/MntDialogCard.vue' import MntDialogCard from '@/components/maint/MntDialogCard.vue'
import MntRecordNavToolbar from '@/components/maint/MntRecordNavToolbar.vue' import MntRecordNavToolbar from '@/components/maint/MntRecordNavToolbar.vue'
import MaintShell from '@/components/MaintShell.vue' import MaintShell from '@/components/maint/MaintShell.vue'
import SectionDataTable from '@/components/sections/SectionDataTable.vue' import SectionDataTable from '@/components/sections/SectionDataTable.vue'
import SectionSearchPanel from '@/components/sections/SectionSearchPanel.vue' import SectionSearchPanel from '@/components/sections/SectionSearchPanel.vue'
import { useMasterDetailAMaintenancePage } from '@/composables/page-drivers/useMasterDetailAMaintenancePage' import { useMasterDetailAMaintenancePage } from '@/composables/page-drivers/useMasterDetailAMaintenancePage'
+1 -1
View File
@@ -511,7 +511,7 @@ import DetailFullHeightPanel from '@/components/maint/master-detail/DetailFullHe
import MasterFileFormFields from '@/components/maint/MasterFileFormFields.vue' import MasterFileFormFields from '@/components/maint/MasterFileFormFields.vue'
import MntDialogCard from '@/components/maint/MntDialogCard.vue' import MntDialogCard from '@/components/maint/MntDialogCard.vue'
import MntRecordNavToolbar from '@/components/maint/MntRecordNavToolbar.vue' import MntRecordNavToolbar from '@/components/maint/MntRecordNavToolbar.vue'
import MaintShell from '@/components/MaintShell.vue' import MaintShell from '@/components/maint/MaintShell.vue'
import { useMaintenanceCrudFlow } from '@/composables/maint/useMaintenanceCrudFlow' import { useMaintenanceCrudFlow } from '@/composables/maint/useMaintenanceCrudFlow'
import { useStudentMaintenanceForm } from '@/composables/maint/useStudentMaintenanceForm' import { useStudentMaintenanceForm } from '@/composables/maint/useStudentMaintenanceForm'
import { type CourseRecord, type SemesterRecord, useSemesterStore } from '@/stores/semesters' import { type CourseRecord, type SemesterRecord, useSemesterStore } from '@/stores/semesters'
+1 -1
View File
@@ -498,7 +498,7 @@ import DetailSimpleList from '@/components/maint/master-detail/DetailSimpleList.
import MasterFileFormFields from '@/components/maint/MasterFileFormFields.vue' import MasterFileFormFields from '@/components/maint/MasterFileFormFields.vue'
import MntDialogCard from '@/components/maint/MntDialogCard.vue' import MntDialogCard from '@/components/maint/MntDialogCard.vue'
import MntRecordNavToolbar from '@/components/maint/MntRecordNavToolbar.vue' import MntRecordNavToolbar from '@/components/maint/MntRecordNavToolbar.vue'
import MaintShell from '@/components/MaintShell.vue' import MaintShell from '@/components/maint/MaintShell.vue'
import { useMaintenanceCrudFlow } from '@/composables/maint/useMaintenanceCrudFlow' import { useMaintenanceCrudFlow } from '@/composables/maint/useMaintenanceCrudFlow'
import { useStudentMaintenanceForm } from '@/composables/maint/useStudentMaintenanceForm' import { useStudentMaintenanceForm } from '@/composables/maint/useStudentMaintenanceForm'
import { type CourseRecord, type SemesterRecord, useSemesterStore } from '@/stores/semesters' import { type CourseRecord, type SemesterRecord, useSemesterStore } from '@/stores/semesters'
+1 -1
View File
@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import MaintShell from '@/components/MaintShell.vue' import MaintShell from '@/components/maint/MaintShell.vue'
import SectionDataTable from '@/components/sections/SectionDataTable.vue' import SectionDataTable from '@/components/sections/SectionDataTable.vue'
import SectionFormPanel from '@/components/sections/SectionFormPanel.vue' import SectionFormPanel from '@/components/sections/SectionFormPanel.vue'
import SectionSearchPanel from '@/components/sections/SectionSearchPanel.vue' import SectionSearchPanel from '@/components/sections/SectionSearchPanel.vue'