docs(pages): clarify page driver component boundaries
Add inline comments to page components documenting how page models, v-model state, and emitted user intents flow through the page driver. This clarifies that page components remain presentation-focused while routing, dialog state, CRUD side effects, and command handling stay in the page driver or related composables.docs(pages): clarify page driver component boundaries Add inline comments to page components documenting how page models, v-model state, and emitted user intents flow through the page driver. This clarifies that page components remain presentation-focused while routing, dialog state, CRUD side effects, and command handling stay in the page driver or related composables.
This commit is contained in:
@@ -8,5 +8,6 @@ defineProps<{
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Page component 接收 page model,再把頁面標題轉交給既有 editable grid feature component。 -->
|
||||
<EditableStudentGrid :title="page.title" />
|
||||
</template>
|
||||
|
||||
@@ -7,6 +7,7 @@ defineProps<{
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Page component 只呈現 page driver 解析後的功能代碼,不直接讀 route params。 -->
|
||||
<v-sheet height="100%" width="100%">
|
||||
{{ page.fncId }}
|
||||
</v-sheet>
|
||||
|
||||
@@ -7,16 +7,19 @@ defineProps<{
|
||||
selectedNews: HomeNewsItem | null
|
||||
}>()
|
||||
|
||||
// 首頁互動都往上 emit,讓 page driver 統一處理 dialog、訊息中心與 snackbar。
|
||||
const emit = defineEmits<{
|
||||
news: [item: HomeNewsItem]
|
||||
'message-center': []
|
||||
quick: [item: HomeQuickItem]
|
||||
}>()
|
||||
|
||||
// 新聞 dialog 開關是 PageIndex 的雙向 UI 狀態,由 view/page driver 持有。
|
||||
const isNewsDialogOpen = defineModel<boolean>('newsDialogOpen', { default: false })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- PageHome 作為 page component,把 page model 拆給既有 PageIndex 外殼與事件。 -->
|
||||
<PageIndex
|
||||
v-model:is-news-dialog-open="isNewsDialogOpen"
|
||||
:news-items="page.newsItems"
|
||||
|
||||
@@ -6,6 +6,7 @@ defineProps<{
|
||||
page: MaintenancePageModel
|
||||
}>()
|
||||
|
||||
// PageMaintenance 只轉發維護頁使用者意圖,CRUD 副作用交給 page driver / command composable。
|
||||
const emit = defineEmits<{
|
||||
(e: 'create'): void
|
||||
(e: 'edit', record: unknown): void
|
||||
@@ -14,10 +15,12 @@ const emit = defineEmits<{
|
||||
(e: 'search', criteria: Record<string, unknown>): void
|
||||
}>()
|
||||
|
||||
// 搜尋面板開關是頁面 UI 狀態,用 v-model 交回 view/page driver。
|
||||
const searchPanelOpen = defineModel<boolean>('searchPanelOpen', { default: false })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- PageMaint 提供維護頁外殼;搜尋欄位與表格內容由 slot 交給各頁組合。 -->
|
||||
<PageMaint
|
||||
:title="page.title"
|
||||
:search-panel-open="searchPanelOpen"
|
||||
|
||||
@@ -73,6 +73,7 @@ defineProps<{
|
||||
|
||||
const form = defineModel<StudentFormState>('form', { required: true })
|
||||
const detailFormModel = defineModel<SemesterRecord | null>('detailForm', { required: true })
|
||||
// 主檔表單、子檔表單與搜尋條件都由 page driver 持有,Page component 只透過 v-model 回寫。
|
||||
const search = defineModel<{
|
||||
studentId: string
|
||||
name: string
|
||||
@@ -82,6 +83,7 @@ const search = defineModel<{
|
||||
}>('search', { required: true })
|
||||
const searchPanelOpen = defineModel<boolean>('searchPanelOpen', { required: true })
|
||||
|
||||
// 主從維護頁的 CRUD 與導覽意圖都往上 emit,讓 page driver / command composable 統一處理。
|
||||
const emit = defineEmits<{
|
||||
(e: 'add-semester'): void
|
||||
(e: 'cancel-detail-edit'): void
|
||||
@@ -122,11 +124,13 @@ const emit = defineEmits<{
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- PageMaintenance 提供維護頁外殼;主從頁在 slots 中組合搜尋、表格與子檔內容。 -->
|
||||
<PageMaintenance
|
||||
v-model:search-panel-open="searchPanelOpen"
|
||||
:page="page"
|
||||
@create="emit('create')"
|
||||
>
|
||||
<!-- 搜尋欄位沿用 SectionSearchPanel,搜尋條件透過 v-model 回到 page driver。 -->
|
||||
<template #search-fields>
|
||||
<SectionSearchPanel
|
||||
v-model="search"
|
||||
@@ -136,6 +140,7 @@ const emit = defineEmits<{
|
||||
@reset="emit('reset-search')"
|
||||
/>
|
||||
</template>
|
||||
<!-- 主檔表格沿用 SectionDataTable,列操作只 emit 使用者意圖。 -->
|
||||
<template #table>
|
||||
<SectionDataTable
|
||||
:current-page="currentPage"
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<template>
|
||||
<!-- Page component 組合 PageMaint 外殼、主檔表格、子檔區與 dialog;流程狀態集中在本頁 script。 -->
|
||||
<page-maint
|
||||
:search-panel-open="searchPanelOpen"
|
||||
:title="page.title"
|
||||
@create="openAddDialog"
|
||||
@toggle-search="searchPanelOpen = !searchPanelOpen"
|
||||
>
|
||||
<!-- 搜尋欄位放在 PageMaint 的 search-fields slot,讓外殼固定、欄位由頁面決定。 -->
|
||||
<template #search-fields>
|
||||
<v-col cols="12" md="2">
|
||||
<div id="search-student-id-label" class="text-body-2 text-medium-emphasis pl-2">學號</div>
|
||||
@@ -78,6 +80,7 @@
|
||||
<v-btn color="primary" disabled :prepend-icon="mdiMagnify" variant="tonal">查詢</v-btn>
|
||||
</v-col>
|
||||
</template>
|
||||
<!-- table slot 放主檔表格與列操作,操作事件再交給頁面流程函式處理。 -->
|
||||
<template #table>
|
||||
<v-data-table
|
||||
v-model:page="currentPage"
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<template>
|
||||
<!-- Page component 組合 PageMaint 外殼、主檔表格、子檔區與 dialog;流程狀態集中在本頁 script。 -->
|
||||
<page-maint
|
||||
:search-panel-open="searchPanelOpen"
|
||||
:title="page.title"
|
||||
@create="openAddDialog"
|
||||
@toggle-search="searchPanelOpen = !searchPanelOpen"
|
||||
>
|
||||
<!-- 搜尋欄位放在 PageMaint 的 search-fields slot,讓外殼固定、欄位由頁面決定。 -->
|
||||
<template #search-fields>
|
||||
<v-col cols="12" md="2">
|
||||
<div id="search-student-id-label" class="text-body-2 text-medium-emphasis pl-2">學號</div>
|
||||
@@ -78,6 +80,7 @@
|
||||
<v-btn color="primary" disabled :prepend-icon="mdiMagnify" variant="tonal">查詢</v-btn>
|
||||
</v-col>
|
||||
</template>
|
||||
<!-- table slot 放主檔表格與列操作,操作事件再交給頁面流程函式處理。 -->
|
||||
<template #table>
|
||||
<v-data-table
|
||||
v-model:page="currentPage"
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<script setup lang="ts">
|
||||
import BaseFormSelect from '@/components/base/BaseFormSelect.vue'
|
||||
import BaseFormTextField from '@/components/base/BaseFormTextField.vue'
|
||||
import SectionQueryPage from '@/components/sections/SectionQueryPage.vue'
|
||||
import type {
|
||||
ReportFilters,
|
||||
SectionsDemoPageModel,
|
||||
} from '@/composables/page-drivers/useSectionsDemoPage'
|
||||
|
||||
defineProps<{
|
||||
page: SectionsDemoPageModel
|
||||
}>()
|
||||
|
||||
// Page component 只接收 page driver 組好的 page model;查詢條件用 v-model 回寫給 view/page driver。
|
||||
const queryFilters = defineModel<ReportFilters>('queryFilters', { required: true })
|
||||
|
||||
// 使用者意圖往上 emit,由 page driver 決定查詢、返回等副作用。
|
||||
const emit = defineEmits<{
|
||||
(e: 'back'): void
|
||||
(e: 'search'): void
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SectionQueryPage
|
||||
back-label="回到列表"
|
||||
title="查詢頁DEMO"
|
||||
@back="emit('back')"
|
||||
@search="emit('search')"
|
||||
>
|
||||
<!-- SectionQueryPage 決定查詢頁外殼;欄位內容由 filters slot 交給頁面自行組合。 -->
|
||||
<template #filters>
|
||||
<v-col cols="12" md="4">
|
||||
<BaseFormTextField v-model="queryFilters.keyword" label="關鍵字" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<BaseFormSelect v-model="queryFilters.owner" label="單位" :items="page.ownerOptions" />
|
||||
</v-col>
|
||||
</template>
|
||||
|
||||
<!-- results slot 放查詢結果;資料仍由 page model 提供,這裡只負責呈現。 -->
|
||||
<template #results>
|
||||
<v-alert v-if="page.queryMessage" class="mb-3" type="success" variant="tonal">
|
||||
{{ page.queryMessage }}
|
||||
</v-alert>
|
||||
<v-table density="compact">
|
||||
<thead class="bg-primary">
|
||||
<tr>
|
||||
<th>名稱</th>
|
||||
<th>單位</th>
|
||||
<th>狀態</th>
|
||||
<th>更新日</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-if="page.reports.length === 0">
|
||||
<td class="text-center" colspan="4">尚無查詢結果</td>
|
||||
</tr>
|
||||
<tr v-for="row in page.reports" :key="row.id">
|
||||
<td>{{ row.title }}</td>
|
||||
<td>{{ row.owner }}</td>
|
||||
<td>{{ row.status }}</td>
|
||||
<td>{{ row.updatedAt }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</template>
|
||||
</SectionQueryPage>
|
||||
</template>
|
||||
@@ -7,5 +7,6 @@ defineProps<{
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Page component 只呈現 page driver 組好的設定頁 model。 -->
|
||||
<div>{{ page.title }}</div>
|
||||
</template>
|
||||
|
||||
@@ -18,7 +18,7 @@ const emit = defineEmits<{
|
||||
|
||||
<template>
|
||||
<v-container fluid class="pt-2 px-1">
|
||||
<v-card>
|
||||
<v-card class="mb-2">
|
||||
<v-card-title class="text-title-large bg-primary">{{ title }}</v-card-title>
|
||||
<v-card-text class="pa-4">
|
||||
<v-alert v-if="error" class="mb-4" type="error" variant="tonal">{{ error }}</v-alert>
|
||||
|
||||
Reference in New Issue
Block a user