feat: Implement editable student grid and refactor maintenance dialogs
This commit is contained in:
+25
-25
@@ -61,7 +61,7 @@
|
||||
|
||||
目前已接近薄 view 的頁面:
|
||||
|
||||
- [EditableGridMnt.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/EditableGridMnt.vue)
|
||||
- [EditableGrid.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/EditableGrid.vue)
|
||||
- [Forbidden.vue](/home/carl/git/skt-vuetify-templates/src/views/errors/Forbidden.vue)
|
||||
- [ServerError.vue](/home/carl/git/skt-vuetify-templates/src/views/errors/ServerError.vue)
|
||||
- [ServiceUnavailable.vue](/home/carl/git/skt-vuetify-templates/src/views/errors/ServiceUnavailable.vue)
|
||||
@@ -74,10 +74,10 @@
|
||||
|
||||
- [Login.vue](/home/carl/git/skt-vuetify-templates/src/views/Login.vue)
|
||||
- [Home.vue](/home/carl/git/skt-vuetify-templates/src/views/Home.vue)
|
||||
- [SingleRecordMnt.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/SingleRecordMnt.vue)
|
||||
- [MasterDetailMnt.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/MasterDetailMnt.vue)
|
||||
- [MasterDetailMntB.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/MasterDetailMntB.vue)
|
||||
- [MasterDetailMntC.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/MasterDetailMntC.vue)
|
||||
- [SingleRecord.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/SingleRecord.vue)
|
||||
- [MasterDetailA.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/MasterDetailA.vue)
|
||||
- [MasterDetailB.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/MasterDetailB.vue)
|
||||
- [MasterDetailC.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/MasterDetailC.vue)
|
||||
|
||||
目前 `views` 應遵守的原則:
|
||||
|
||||
@@ -144,23 +144,22 @@ layout 不應承擔:
|
||||
- 頁面專屬業務流程
|
||||
- 特定 domain 的資料規則
|
||||
|
||||
#### 3. `components/maintenance`
|
||||
#### 3. `components/maint`
|
||||
|
||||
這個目錄目前已經是最接近 feature folder 的區域:
|
||||
|
||||
- [EditableStudentGrid.vue](/home/carl/git/skt-vuetify-templates/src/components/maintenance/EditableStudentGrid.vue)
|
||||
- [MaintenanceCrudDialogs.vue](/home/carl/git/skt-vuetify-templates/src/components/maintenance/MaintenanceCrudDialogs.vue)
|
||||
- [MaintenanceStudentFormFields.vue](/home/carl/git/skt-vuetify-templates/src/components/maintenance/MaintenanceStudentFormFields.vue)
|
||||
- [MntDialogCard.vue](/home/carl/git/skt-vuetify-templates/src/components/maintenance/MntDialogCard.vue)
|
||||
- [MntPageCards.vue](/home/carl/git/skt-vuetify-templates/src/components/maintenance/MntPageCards.vue)
|
||||
- [MntRecordNavToolbar.vue](/home/carl/git/skt-vuetify-templates/src/components/maintenance/MntRecordNavToolbar.vue)
|
||||
- [CommonConfirmDialog.vue](/home/carl/git/skt-vuetify-templates/src/components/maint/CommonConfirmDialog.vue)
|
||||
- [EditableStudentGrid.vue](/home/carl/git/skt-vuetify-templates/src/components/maint/EditableStudentGrid.vue)
|
||||
- [MasterFormFields.vue](/home/carl/git/skt-vuetify-templates/src/components/maint/MasterFormFields.vue)
|
||||
- [MntDialogCard.vue](/home/carl/git/skt-vuetify-templates/src/components/maint/MntDialogCard.vue)
|
||||
- [MntRecordNavToolbar.vue](/home/carl/git/skt-vuetify-templates/src/components/maint/MntRecordNavToolbar.vue)
|
||||
- [PageMaint.vue](/home/carl/git/skt-vuetify-templates/src/components/maint/PageMaint.vue)
|
||||
- `master-detail/*`
|
||||
- `master-detail-b/*`
|
||||
- `master-detail-c/*`
|
||||
|
||||
結論:
|
||||
|
||||
- `components/maintenance` 已實質扮演 domain component 層
|
||||
- `components/maint` 主要扮演 maintenance domain component 層
|
||||
- 像 `ConfirmDialog` 這類通用確認視窗可以直接在頁面使用,不需要再包一層 page-specific dialog aggregator
|
||||
- 目前沒有必要為了形式硬搬到 `components/features/maintenance`
|
||||
|
||||
### `src/composables`
|
||||
@@ -254,15 +253,15 @@ layout 不應承擔:
|
||||
|
||||
這是目前在一般展示頁面中最明確的頁面分層。
|
||||
|
||||
### 模式 2:`view -> maintenance components + maintenance composables`
|
||||
### 模式 2:`view -> page-level maintenance component + maintenance components + maintenance composables`
|
||||
|
||||
已落地區域:
|
||||
|
||||
- `views/maint/*`
|
||||
- `components/maintenance/*`
|
||||
- `components/maint/*`
|
||||
- `composables/maintenance/*`
|
||||
|
||||
其中 [EditableGridMnt.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/EditableGridMnt.vue) 是目前最接近目標狀態的 maintenance 頁面。
|
||||
其中 [EditableGrid.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/EditableGrid.vue) 是目前最接近目標狀態的 maintenance 頁面。
|
||||
|
||||
### 模式 3:`router meta -> App.vue -> layout`
|
||||
|
||||
@@ -279,7 +278,7 @@ layout 不應承擔:
|
||||
以下是文件與實際程式碼之間原本不一致的地方,這次同步後已改成以現況描述:
|
||||
|
||||
- `components/base` 並非只放真正通用元件
|
||||
- 專案目前不只 maintenance 有分層,`login / dashboard / analysis / management` 也已形成 `view -> page component` 模式
|
||||
- 專案目前除了 `login / home` 的 `view -> page component` 模式外,`maintenance` 也已形成頁面級元件 + domain component 的模式
|
||||
- `stores` 與 `services` 已經是正式架構層,不能繼續省略不寫
|
||||
- `App.vue` 目前實際承擔全域 UI 組裝責任,不能只把它視為掛載入口
|
||||
- 錯誤頁已明確收斂到 `views/errors/*`
|
||||
@@ -289,10 +288,10 @@ layout 不應承擔:
|
||||
### 高優先度
|
||||
|
||||
- 繼續瘦身:
|
||||
- [SingleRecordMnt.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/SingleRecordMnt.vue)
|
||||
- [MasterDetailMnt.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/MasterDetailMnt.vue)
|
||||
- [MasterDetailMntB.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/MasterDetailMntB.vue)
|
||||
- [MasterDetailMntC.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/MasterDetailMntC.vue)
|
||||
- [SingleRecord.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/SingleRecord.vue)
|
||||
- [MasterDetailA.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/MasterDetailA.vue)
|
||||
- [MasterDetailB.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/MasterDetailB.vue)
|
||||
- [MasterDetailC.vue](/home/carl/git/skt-vuetify-templates/src/views/maint/MasterDetailC.vue)
|
||||
- 重新整理:
|
||||
- [Login.vue](/home/carl/git/skt-vuetify-templates/src/views/Login.vue)
|
||||
|
||||
@@ -305,6 +304,7 @@ layout 不應承擔:
|
||||
- 重新命名或重新安置頁面型元件:
|
||||
- [PageLogin.vue](/home/carl/git/skt-vuetify-templates/src/components/PageLogin.vue)
|
||||
- [PageIndex.vue](/home/carl/git/skt-vuetify-templates/src/components/PageIndex.vue)
|
||||
- [PageMaint.vue](/home/carl/git/skt-vuetify-templates/src/components/maint/PageMaint.vue)
|
||||
|
||||
原因:
|
||||
|
||||
@@ -322,7 +322,7 @@ layout 不應承擔:
|
||||
1. 這個檔案是否直接被 route 載入?
|
||||
- 是:優先放 `views`
|
||||
2. 這個檔案是否負責某個完整頁面的主畫面組裝?
|
||||
- 是:放頁面型元件層,不要塞進 `base`
|
||||
- 是:放頁面型元件層,且命名以 `Page` 為前綴,不要塞進 `base`
|
||||
3. 這段重複的是模板還是流程?
|
||||
- 模板:抽元件
|
||||
- 流程:抽 composable 或 store
|
||||
@@ -331,6 +331,6 @@ layout 不應承擔:
|
||||
5. 這個邏輯是否在處理 API、token、session、錯誤正規化?
|
||||
- 是:放 `services`
|
||||
6. 這個元件是否只屬於單一 domain?
|
||||
- 是:優先放到該 domain 目錄,例如 `components/maintenance`
|
||||
- 是:優先放到該 domain 目錄,例如 `components/maint`
|
||||
7. 這個抽象是否真的降低重複與理解成本?
|
||||
- 否:不要抽
|
||||
|
||||
+87
-3
@@ -59,7 +59,7 @@
|
||||
:disabled="!hasSelectedRows"
|
||||
:prepend-icon="mdiDelete"
|
||||
variant="outlined"
|
||||
@click="deleteSelectedRows"
|
||||
@click="requestDeleteSelectedRows"
|
||||
>
|
||||
批次刪除
|
||||
</v-btn>
|
||||
@@ -69,7 +69,7 @@
|
||||
:disabled="!hasAnyChange"
|
||||
:prepend-icon="mdiContentSave"
|
||||
variant="outlined"
|
||||
@click="saveAllRows"
|
||||
@click="requestSaveAllRows"
|
||||
>
|
||||
儲存變更
|
||||
</v-btn>
|
||||
@@ -289,7 +289,7 @@
|
||||
:disabled="!isBulkEditEnabled"
|
||||
size="small"
|
||||
variant="text"
|
||||
@click="deleteSingleRow(item.id)"
|
||||
@click="requestDeleteSingleRow(item.id)"
|
||||
>
|
||||
刪除
|
||||
</v-btn>
|
||||
@@ -300,10 +300,38 @@
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</div>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmDeleteSingleVisible"
|
||||
confirm-color="error"
|
||||
confirm-text="確定刪除"
|
||||
:message="singleDeleteMessage"
|
||||
title="確認刪除"
|
||||
@confirm="confirmDeleteSingleRow"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmDeleteSelectedVisible"
|
||||
confirm-color="error"
|
||||
confirm-text="確定批次刪除"
|
||||
:message="selectedDeleteMessage"
|
||||
title="確認批次刪除"
|
||||
@confirm="confirmDeleteSelectedRows"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmSaveVisible"
|
||||
confirm-text="確認儲存"
|
||||
message="確定要儲存目前所有變更嗎?"
|
||||
title="確認儲存變更"
|
||||
@confirm="confirmSaveAllRows"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { mdiContentSave, mdiDelete, mdiMagnify, mdiRestore } from '@mdi/js'
|
||||
import { computed, ref } from 'vue'
|
||||
import ConfirmDialog from '@/components/maint/CommonConfirmDialog.vue'
|
||||
import { useEditableStudentGrid } from '@/composables/maint/useEditableStudentGrid'
|
||||
|
||||
const {
|
||||
@@ -331,6 +359,62 @@ const {
|
||||
deleteSingleRow,
|
||||
resetAllRows,
|
||||
} = useEditableStudentGrid()
|
||||
|
||||
const confirmDeleteSingleVisible = ref(false)
|
||||
const confirmDeleteSelectedVisible = ref(false)
|
||||
const confirmSaveVisible = ref(false)
|
||||
const pendingDeleteRowId = ref<number | null>(null)
|
||||
|
||||
const pendingDeleteRow = computed(() =>
|
||||
pendingDeleteRowId.value === null ? null : getDraftRow(pendingDeleteRowId.value)
|
||||
)
|
||||
|
||||
const singleDeleteMessage = computed(() => {
|
||||
const row = pendingDeleteRow.value
|
||||
if (!row) {
|
||||
return '確定要刪除此筆資料嗎?此操作會在儲存後正式生效。'
|
||||
}
|
||||
|
||||
return `確定要刪除 ${row.name}(${row.studentId})嗎?此操作會在儲存後正式生效。`
|
||||
})
|
||||
|
||||
const selectedDeleteMessage = computed(
|
||||
() =>
|
||||
`確定要刪除目前選取的 ${selectedRowIds.value.length} 筆資料嗎?此操作會在儲存後正式生效。`
|
||||
)
|
||||
|
||||
function requestDeleteSingleRow(id: number) {
|
||||
pendingDeleteRowId.value = id
|
||||
confirmDeleteSingleVisible.value = true
|
||||
}
|
||||
|
||||
function confirmDeleteSingleRow() {
|
||||
if (pendingDeleteRowId.value === null) return
|
||||
|
||||
deleteSingleRow(pendingDeleteRowId.value)
|
||||
pendingDeleteRowId.value = null
|
||||
confirmDeleteSingleVisible.value = false
|
||||
}
|
||||
|
||||
function requestDeleteSelectedRows() {
|
||||
if (!hasSelectedRows.value) return
|
||||
confirmDeleteSelectedVisible.value = true
|
||||
}
|
||||
|
||||
function confirmDeleteSelectedRows() {
|
||||
deleteSelectedRows()
|
||||
confirmDeleteSelectedVisible.value = false
|
||||
}
|
||||
|
||||
function requestSaveAllRows() {
|
||||
if (!hasAnyChange.value) return
|
||||
confirmSaveVisible.value = true
|
||||
}
|
||||
|
||||
function confirmSaveAllRows() {
|
||||
saveAllRows()
|
||||
confirmSaveVisible.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -1,120 +0,0 @@
|
||||
<template>
|
||||
<common-confirm-dialog
|
||||
v-model="closeVisibleModel"
|
||||
confirm-color="error"
|
||||
confirm-text="關閉不儲存"
|
||||
message="目前有尚未儲存的內容,確定要關閉嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="emit('confirm-close')"
|
||||
/>
|
||||
|
||||
<common-confirm-dialog
|
||||
v-model="saveVisibleModel"
|
||||
:confirm-loading="props.isSaving"
|
||||
confirm-text="確認儲存"
|
||||
max-width="520"
|
||||
title="確認儲存變更"
|
||||
@confirm="emit('confirm-save')"
|
||||
>
|
||||
<div v-if="props.saveSummary.length > 0" class="d-flex flex-column ga-2">
|
||||
<div v-for="item in props.saveSummary" :key="item.label" class="d-flex flex-column">
|
||||
<div class="text-caption text-medium-emphasis">{{ item.label }}</div>
|
||||
<div v-if="item.before !== null" class="text-body-2">
|
||||
<span class="text-medium-emphasis">原:</span>
|
||||
<span :class="{ 'text-medium-emphasis': item.before === '—' }">
|
||||
{{ item.before }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-body-2">
|
||||
<span class="text-medium-emphasis">新:</span>
|
||||
<span :class="{ 'text-medium-emphasis': item.after === '—' }">
|
||||
{{ item.after }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-body-2">目前沒有可儲存的變更。</div>
|
||||
</common-confirm-dialog>
|
||||
|
||||
<common-confirm-dialog
|
||||
v-model="deleteVisibleModel"
|
||||
confirm-color="error"
|
||||
confirm-text="確定刪除"
|
||||
:message="`確定要刪除 ${props.pendingDeleteLabel} 嗎?此操作無法復原。`"
|
||||
title="確認刪除"
|
||||
@confirm="emit('confirm-delete')"
|
||||
/>
|
||||
|
||||
<common-confirm-dialog
|
||||
v-model="switchVisibleModel"
|
||||
confirm-text="確定切換"
|
||||
max-width="480"
|
||||
message="目前有尚未儲存的內容,切換為檢視模式將會捨棄變更,確定要切換嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="emit('confirm-switch')"
|
||||
/>
|
||||
|
||||
<common-confirm-dialog
|
||||
v-model="navigateVisibleModel"
|
||||
confirm-text="確定切換"
|
||||
max-width="480"
|
||||
message="目前有尚未儲存的內容,切換到其他資料將會捨棄變更,確定要切換嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="emit('confirm-navigate')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { SaveSummaryItem } from '@/composables/maint/useStudentMaintenanceForm'
|
||||
import { computed } from 'vue'
|
||||
import CommonConfirmDialog from './CommonConfirmDialog.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
closeVisible: boolean
|
||||
deleteVisible: boolean
|
||||
isSaving: boolean
|
||||
navigateVisible: boolean
|
||||
pendingDeleteLabel: string
|
||||
saveSummary: SaveSummaryItem[]
|
||||
saveVisible: boolean
|
||||
switchVisible: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'confirm-close'): void
|
||||
(event: 'confirm-delete'): void
|
||||
(event: 'confirm-navigate'): void
|
||||
(event: 'confirm-save'): void
|
||||
(event: 'confirm-switch'): void
|
||||
(event: 'update:close-visible', value: boolean): void
|
||||
(event: 'update:delete-visible', value: boolean): void
|
||||
(event: 'update:navigate-visible', value: boolean): void
|
||||
(event: 'update:save-visible', value: boolean): void
|
||||
(event: 'update:switch-visible', value: boolean): void
|
||||
}>()
|
||||
|
||||
const closeVisibleModel = computed({
|
||||
get: () => props.closeVisible,
|
||||
set: (value: boolean) => emit('update:close-visible', value),
|
||||
})
|
||||
|
||||
const saveVisibleModel = computed({
|
||||
get: () => props.saveVisible,
|
||||
set: (value: boolean) => emit('update:save-visible', value),
|
||||
})
|
||||
|
||||
const deleteVisibleModel = computed({
|
||||
get: () => props.deleteVisible,
|
||||
set: (value: boolean) => emit('update:delete-visible', value),
|
||||
})
|
||||
|
||||
const switchVisibleModel = computed({
|
||||
get: () => props.switchVisible,
|
||||
set: (value: boolean) => emit('update:switch-visible', value),
|
||||
})
|
||||
|
||||
const navigateVisibleModel = computed({
|
||||
get: () => props.navigateVisible,
|
||||
set: (value: boolean) => emit('update:navigate-visible', value),
|
||||
})
|
||||
</script>
|
||||
@@ -3,5 +3,5 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import EditableStudentGrid from '@/components/maint/EditableStudentGrid.vue'
|
||||
import EditableStudentGrid from '@/components/maint/EditableGrid.vue'
|
||||
</script>
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
:class="{ 'form-readonly': isFormReadonly }"
|
||||
@submit.prevent="requestSaveConfirmation"
|
||||
>
|
||||
<maintenance-student-form-fields
|
||||
<master-form-fields
|
||||
:departments="departments"
|
||||
:enroll-years="enrollYears"
|
||||
:field-errors="fieldErrors"
|
||||
@@ -348,25 +348,68 @@
|
||||
</v-overlay>
|
||||
</teleport>
|
||||
|
||||
<maintenance-crud-dialogs
|
||||
:close-visible="confirmCloseVisible"
|
||||
:delete-visible="confirmDeleteVisible"
|
||||
:is-saving="isSaving"
|
||||
:navigate-visible="confirmNavigateVisible"
|
||||
:pending-delete-label="pendingDeleteLabel"
|
||||
:save-summary="saveSummary"
|
||||
:save-visible="confirmSaveVisible"
|
||||
:switch-visible="confirmSwitchVisible"
|
||||
@confirm-close="confirmClose"
|
||||
@confirm-delete="confirmDelete"
|
||||
@confirm-navigate="confirmNavigate"
|
||||
@confirm-save="confirmSave"
|
||||
@confirm-switch="confirmSwitch"
|
||||
@update:close-visible="confirmCloseVisible = $event"
|
||||
@update:delete-visible="confirmDeleteVisible = $event"
|
||||
@update:navigate-visible="confirmNavigateVisible = $event"
|
||||
@update:save-visible="confirmSaveVisible = $event"
|
||||
@update:switch-visible="confirmSwitchVisible = $event"
|
||||
<ConfirmDialog
|
||||
v-model="confirmCloseVisible"
|
||||
confirm-color="error"
|
||||
confirm-text="關閉不儲存"
|
||||
message="目前有尚未儲存的內容,確定要關閉嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="confirmClose"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmSaveVisible"
|
||||
:confirm-loading="isSaving"
|
||||
confirm-text="確認儲存"
|
||||
max-width="520"
|
||||
title="確認儲存變更"
|
||||
@confirm="confirmSave"
|
||||
>
|
||||
<div v-if="saveSummary.length > 0" class="d-flex flex-column ga-2">
|
||||
<div v-for="item in saveSummary" :key="item.label" class="d-flex flex-column">
|
||||
<div class="text-caption text-medium-emphasis">{{ item.label }}</div>
|
||||
<div v-if="item.before !== null" class="text-body-2">
|
||||
<span class="text-medium-emphasis">原:</span>
|
||||
<span :class="{ 'text-medium-emphasis': item.before === '—' }">
|
||||
{{ item.before }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-body-2">
|
||||
<span class="text-medium-emphasis">新:</span>
|
||||
<span :class="{ 'text-medium-emphasis': item.after === '—' }">
|
||||
{{ item.after }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-body-2">目前沒有可儲存的變更。</div>
|
||||
</ConfirmDialog>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmDeleteVisible"
|
||||
confirm-color="error"
|
||||
confirm-text="確定刪除"
|
||||
:message="`確定要刪除 ${pendingDeleteLabel} 嗎?此操作無法復原。`"
|
||||
title="確認刪除"
|
||||
@confirm="confirmDelete"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmSwitchVisible"
|
||||
confirm-text="確定切換"
|
||||
max-width="480"
|
||||
message="目前有尚未儲存的內容,切換為檢視模式將會捨棄變更,確定要切換嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="confirmSwitch"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmNavigateVisible"
|
||||
confirm-text="確定切換"
|
||||
max-width="480"
|
||||
message="目前有尚未儲存的內容,切換到其他資料將會捨棄變更,確定要切換嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="confirmNavigate"
|
||||
/>
|
||||
|
||||
<!-- 成功提示 -->
|
||||
@@ -380,8 +423,8 @@ import { mdiBroom, mdiDelete, mdiEye, mdiMagnify, mdiPencil } from '@mdi/js'
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
import { useDisplay } from 'vuetify'
|
||||
|
||||
import MaintenanceCrudDialogs from '@/components/maint/MaintenanceCrudDialogs.vue'
|
||||
import MaintenanceStudentFormFields from '@/components/maint/MaintenanceStudentFormFields.vue'
|
||||
import ConfirmDialog from '@/components/maint/CommonConfirmDialog.vue'
|
||||
import MasterFormFields from '@/components/maint/MasterFormFields.vue'
|
||||
import MasterDetailSemesterList from '@/components/maint/master-detail/SemesterList.vue'
|
||||
import MasterDetailSemesterPanel from '@/components/maint/master-detail/SemesterPanel.vue'
|
||||
import MntDialogCard from '@/components/maint/MntDialogCard.vue'
|
||||
|
||||
@@ -267,7 +267,7 @@
|
||||
]"
|
||||
@submit.prevent="requestSaveConfirmation"
|
||||
>
|
||||
<maintenance-student-form-fields
|
||||
<master-form-fields
|
||||
:departments="departments"
|
||||
:enroll-years="enrollYears"
|
||||
:field-errors="fieldErrors"
|
||||
@@ -363,29 +363,72 @@
|
||||
</v-overlay>
|
||||
</teleport>
|
||||
|
||||
<maintenance-crud-dialogs
|
||||
:close-visible="confirmCloseVisible"
|
||||
:delete-visible="confirmDeleteVisible"
|
||||
:is-saving="isSaving"
|
||||
:navigate-visible="confirmNavigateVisible"
|
||||
:pending-delete-label="pendingDeleteLabel"
|
||||
:save-summary="saveSummary"
|
||||
:save-visible="confirmSaveVisible"
|
||||
:switch-visible="confirmSwitchVisible"
|
||||
@confirm-close="confirmClose"
|
||||
@confirm-delete="confirmDelete"
|
||||
@confirm-navigate="confirmNavigate"
|
||||
@confirm-save="confirmSave"
|
||||
@confirm-switch="confirmSwitch"
|
||||
@update:close-visible="confirmCloseVisible = $event"
|
||||
@update:delete-visible="confirmDeleteVisible = $event"
|
||||
@update:navigate-visible="confirmNavigateVisible = $event"
|
||||
@update:save-visible="confirmSaveVisible = $event"
|
||||
@update:switch-visible="confirmSwitchVisible = $event"
|
||||
<ConfirmDialog
|
||||
v-model="confirmCloseVisible"
|
||||
confirm-color="error"
|
||||
confirm-text="關閉不儲存"
|
||||
message="目前有尚未儲存的內容,確定要關閉嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="confirmClose"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmSaveVisible"
|
||||
:confirm-loading="isSaving"
|
||||
confirm-text="確認儲存"
|
||||
max-width="520"
|
||||
title="確認儲存變更"
|
||||
@confirm="confirmSave"
|
||||
>
|
||||
<div v-if="saveSummary.length > 0" class="d-flex flex-column ga-2">
|
||||
<div v-for="item in saveSummary" :key="item.label" class="d-flex flex-column">
|
||||
<div class="text-caption text-medium-emphasis">{{ item.label }}</div>
|
||||
<div v-if="item.before !== null" class="text-body-2">
|
||||
<span class="text-medium-emphasis">原:</span>
|
||||
<span :class="{ 'text-medium-emphasis': item.before === '—' }">
|
||||
{{ item.before }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-body-2">
|
||||
<span class="text-medium-emphasis">新:</span>
|
||||
<span :class="{ 'text-medium-emphasis': item.after === '—' }">
|
||||
{{ item.after }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-body-2">目前沒有可儲存的變更。</div>
|
||||
</ConfirmDialog>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmDeleteVisible"
|
||||
confirm-color="error"
|
||||
confirm-text="確定刪除"
|
||||
:message="`確定要刪除 ${pendingDeleteLabel} 嗎?此操作無法復原。`"
|
||||
title="確認刪除"
|
||||
@confirm="confirmDelete"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmSwitchVisible"
|
||||
confirm-text="確定切換"
|
||||
max-width="480"
|
||||
message="目前有尚未儲存的內容,切換為檢視模式將會捨棄變更,確定要切換嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="confirmSwitch"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmNavigateVisible"
|
||||
confirm-text="確定切換"
|
||||
max-width="480"
|
||||
message="目前有尚未儲存的內容,切換到其他資料將會捨棄變更,確定要切換嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="confirmNavigate"
|
||||
/>
|
||||
|
||||
<!-- 刪除課程確認 -->
|
||||
<common-confirm-dialog
|
||||
<ConfirmDialog
|
||||
v-model="confirmDeleteCourseVisible"
|
||||
confirm-color="error"
|
||||
confirm-text="確定移除"
|
||||
@@ -459,9 +502,8 @@ import { mdiBookPlus, mdiBroom, mdiDelete, mdiEye, mdiMagnify, mdiPencil } from
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
import { useDisplay } from 'vuetify'
|
||||
|
||||
import CommonConfirmDialog from '@/components/maint/CommonConfirmDialog.vue'
|
||||
import MaintenanceCrudDialogs from '@/components/maint/MaintenanceCrudDialogs.vue'
|
||||
import MaintenanceStudentFormFields from '@/components/maint/MaintenanceStudentFormFields.vue'
|
||||
import ConfirmDialog from '@/components/maint/CommonConfirmDialog.vue'
|
||||
import MasterFormFields from '@/components/maint/MasterFormFields.vue'
|
||||
import MasterDetailBSemesterMobilePanel from '@/components/maint/master-detail/SemesterMobilePanel.vue'
|
||||
import MasterDetailBSemesterSection from '@/components/maint/master-detail/SemesterSection.vue'
|
||||
import MntDialogCard from '@/components/maint/MntDialogCard.vue'
|
||||
|
||||
@@ -266,7 +266,7 @@
|
||||
]"
|
||||
@submit.prevent="requestSaveConfirmation"
|
||||
>
|
||||
<maintenance-student-form-fields
|
||||
<master-form-fields
|
||||
:departments="departments"
|
||||
:enroll-years="enrollYears"
|
||||
:field-errors="fieldErrors"
|
||||
@@ -361,25 +361,68 @@
|
||||
</v-overlay>
|
||||
</teleport>
|
||||
|
||||
<maintenance-crud-dialogs
|
||||
:close-visible="confirmCloseVisible"
|
||||
:delete-visible="confirmDeleteVisible"
|
||||
:is-saving="isSaving"
|
||||
:navigate-visible="confirmNavigateVisible"
|
||||
:pending-delete-label="pendingDeleteLabel"
|
||||
:save-summary="saveSummary"
|
||||
:save-visible="confirmSaveVisible"
|
||||
:switch-visible="confirmSwitchVisible"
|
||||
@confirm-close="confirmClose"
|
||||
@confirm-delete="confirmDelete"
|
||||
@confirm-navigate="confirmNavigate"
|
||||
@confirm-save="confirmSave"
|
||||
@confirm-switch="confirmSwitch"
|
||||
@update:close-visible="confirmCloseVisible = $event"
|
||||
@update:delete-visible="confirmDeleteVisible = $event"
|
||||
@update:navigate-visible="confirmNavigateVisible = $event"
|
||||
@update:save-visible="confirmSaveVisible = $event"
|
||||
@update:switch-visible="confirmSwitchVisible = $event"
|
||||
<ConfirmDialog
|
||||
v-model="confirmCloseVisible"
|
||||
confirm-color="error"
|
||||
confirm-text="關閉不儲存"
|
||||
message="目前有尚未儲存的內容,確定要關閉嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="confirmClose"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmSaveVisible"
|
||||
:confirm-loading="isSaving"
|
||||
confirm-text="確認儲存"
|
||||
max-width="520"
|
||||
title="確認儲存變更"
|
||||
@confirm="confirmSave"
|
||||
>
|
||||
<div v-if="saveSummary.length > 0" class="d-flex flex-column ga-2">
|
||||
<div v-for="item in saveSummary" :key="item.label" class="d-flex flex-column">
|
||||
<div class="text-caption text-medium-emphasis">{{ item.label }}</div>
|
||||
<div v-if="item.before !== null" class="text-body-2">
|
||||
<span class="text-medium-emphasis">原:</span>
|
||||
<span :class="{ 'text-medium-emphasis': item.before === '—' }">
|
||||
{{ item.before }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-body-2">
|
||||
<span class="text-medium-emphasis">新:</span>
|
||||
<span :class="{ 'text-medium-emphasis': item.after === '—' }">
|
||||
{{ item.after }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-body-2">目前沒有可儲存的變更。</div>
|
||||
</ConfirmDialog>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmDeleteVisible"
|
||||
confirm-color="error"
|
||||
confirm-text="確定刪除"
|
||||
:message="`確定要刪除 ${pendingDeleteLabel} 嗎?此操作無法復原。`"
|
||||
title="確認刪除"
|
||||
@confirm="confirmDelete"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmSwitchVisible"
|
||||
confirm-text="確定切換"
|
||||
max-width="480"
|
||||
message="目前有尚未儲存的內容,切換為檢視模式將會捨棄變更,確定要切換嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="confirmSwitch"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmNavigateVisible"
|
||||
confirm-text="確定切換"
|
||||
max-width="480"
|
||||
message="目前有尚未儲存的內容,切換到其他資料將會捨棄變更,確定要切換嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="confirmNavigate"
|
||||
/>
|
||||
|
||||
<!-- 成功提示 -->
|
||||
@@ -446,8 +489,8 @@ import { mdiBroom, mdiDelete, mdiEye, mdiMagnify, mdiPencil, mdiSchool } from '@
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
import { useDisplay } from 'vuetify'
|
||||
|
||||
import MaintenanceCrudDialogs from '@/components/maint/MaintenanceCrudDialogs.vue'
|
||||
import MaintenanceStudentFormFields from '@/components/maint/MaintenanceStudentFormFields.vue'
|
||||
import ConfirmDialog from '@/components/maint/CommonConfirmDialog.vue'
|
||||
import MasterFormFields from '@/components/maint/MasterFormFields.vue'
|
||||
import MasterDetailCCourseMobilePanel from '@/components/maint/master-detail/CourseMobilePanel.vue'
|
||||
import MasterDetailCCourseSection from '@/components/maint/master-detail/CourseSection.vue'
|
||||
import MntDialogCard from '@/components/maint/MntDialogCard.vue'
|
||||
|
||||
@@ -427,25 +427,68 @@
|
||||
</v-overlay>
|
||||
</teleport>
|
||||
|
||||
<maintenance-crud-dialogs
|
||||
:close-visible="confirmCloseVisible"
|
||||
:delete-visible="confirmDeleteVisible"
|
||||
:is-saving="isSaving"
|
||||
:navigate-visible="confirmNavigateVisible"
|
||||
:pending-delete-label="pendingDeleteLabel"
|
||||
:save-summary="saveSummary"
|
||||
:save-visible="confirmSaveVisible"
|
||||
:switch-visible="confirmSwitchVisible"
|
||||
@confirm-close="confirmClose"
|
||||
@confirm-delete="confirmDelete"
|
||||
@confirm-navigate="confirmNavigate"
|
||||
@confirm-save="confirmSave"
|
||||
@confirm-switch="confirmSwitch"
|
||||
@update:close-visible="confirmCloseVisible = $event"
|
||||
@update:delete-visible="confirmDeleteVisible = $event"
|
||||
@update:navigate-visible="confirmNavigateVisible = $event"
|
||||
@update:save-visible="confirmSaveVisible = $event"
|
||||
@update:switch-visible="confirmSwitchVisible = $event"
|
||||
<ConfirmDialog
|
||||
v-model="confirmCloseVisible"
|
||||
confirm-color="error"
|
||||
confirm-text="關閉不儲存"
|
||||
message="目前有尚未儲存的內容,確定要關閉嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="confirmClose"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmSaveVisible"
|
||||
:confirm-loading="isSaving"
|
||||
confirm-text="確認儲存"
|
||||
max-width="520"
|
||||
title="確認儲存變更"
|
||||
@confirm="confirmSave"
|
||||
>
|
||||
<div v-if="saveSummary.length > 0" class="d-flex flex-column ga-2">
|
||||
<div v-for="item in saveSummary" :key="item.label" class="d-flex flex-column">
|
||||
<div class="text-caption text-medium-emphasis">{{ item.label }}</div>
|
||||
<div v-if="item.before !== null" class="text-body-2">
|
||||
<span class="text-medium-emphasis">原:</span>
|
||||
<span :class="{ 'text-medium-emphasis': item.before === '—' }">
|
||||
{{ item.before }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-body-2">
|
||||
<span class="text-medium-emphasis">新:</span>
|
||||
<span :class="{ 'text-medium-emphasis': item.after === '—' }">
|
||||
{{ item.after }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-body-2">目前沒有可儲存的變更。</div>
|
||||
</ConfirmDialog>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmDeleteVisible"
|
||||
confirm-color="error"
|
||||
confirm-text="確定刪除"
|
||||
:message="`確定要刪除 ${pendingDeleteLabel} 嗎?此操作無法復原。`"
|
||||
title="確認刪除"
|
||||
@confirm="confirmDelete"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmSwitchVisible"
|
||||
confirm-text="確定切換"
|
||||
max-width="480"
|
||||
message="目前有尚未儲存的內容,切換為檢視模式將會捨棄變更,確定要切換嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="confirmSwitch"
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
v-model="confirmNavigateVisible"
|
||||
confirm-text="確定切換"
|
||||
max-width="480"
|
||||
message="目前有尚未儲存的內容,切換到其他資料將會捨棄變更,確定要切換嗎?"
|
||||
title="未儲存變更"
|
||||
@confirm="confirmNavigate"
|
||||
/>
|
||||
|
||||
<!-- 成功提示 -->
|
||||
@@ -458,7 +501,7 @@
|
||||
import { mdiBroom, mdiDelete, mdiEye, mdiMagnify, mdiPencil } from '@mdi/js'
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
import { useDisplay } from 'vuetify'
|
||||
import MaintenanceCrudDialogs from '@/components/maint/MaintenanceCrudDialogs.vue'
|
||||
import ConfirmDialog from '@/components/maint/CommonConfirmDialog.vue'
|
||||
import MntDialogCard from '@/components/maint/MntDialogCard.vue'
|
||||
import MntRecordNavToolbar from '@/components/maint/MntRecordNavToolbar.vue'
|
||||
import PageMaint from '@/components/maint/PageMaint.vue'
|
||||
|
||||
Reference in New Issue
Block a user