refactor: remove unused dashboard components and views
This commit is contained in:
@@ -1,88 +0,0 @@
|
||||
<template>
|
||||
<SKAnalysis
|
||||
:bar-data="barData"
|
||||
:chart1-title="chart1Title"
|
||||
:chart2-title="chart2Title"
|
||||
:chart3-title="chart3Title"
|
||||
:pie1-data="pie1Data"
|
||||
:pie2-data="pie2Data"
|
||||
:stats="stats"
|
||||
:trend-data="trendData"
|
||||
:trend-title="trendTitle"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
mdiAccountSchool,
|
||||
mdiBookOpenPageVariant,
|
||||
mdiChartPie,
|
||||
mdiCheckDecagram,
|
||||
mdiCloudDownload,
|
||||
} from '@mdi/js'
|
||||
import { ref } from 'vue'
|
||||
import SKAnalysis from '@/components/SKAnalysis.vue'
|
||||
|
||||
// Mock Data
|
||||
const stats = ref([
|
||||
{
|
||||
title: '學生總數',
|
||||
value: '2,580',
|
||||
icon: mdiAccountSchool,
|
||||
color: 'primary',
|
||||
label: '總學籍人數',
|
||||
total: '120,000',
|
||||
},
|
||||
{
|
||||
title: '平台訪問',
|
||||
value: '20,000',
|
||||
icon: mdiChartPie,
|
||||
color: 'error',
|
||||
label: '今日訪問量',
|
||||
total: '500,000',
|
||||
},
|
||||
{
|
||||
title: '教材下載',
|
||||
value: '8,000',
|
||||
icon: mdiCloudDownload,
|
||||
color: 'warning',
|
||||
label: '本月下載次數',
|
||||
total: '120,000',
|
||||
},
|
||||
{
|
||||
title: '圖書館借閱',
|
||||
value: '5,000',
|
||||
icon: mdiBookOpenPageVariant,
|
||||
color: 'success',
|
||||
label: '總借閱量',
|
||||
total: '50,000',
|
||||
},
|
||||
])
|
||||
|
||||
const trendTitle = ref('數位學習平台流量')
|
||||
const trendData = ref([0, 2, 5, 9, 5, 10, 3, 5, 0, 0, 1, 8, 2, 9, 0])
|
||||
|
||||
const chart1Title = ref('學生核心素養指標 (平均)')
|
||||
const barData = ref([
|
||||
{ label: '道德實踐 (Moral)', value: 85, color: 'info' },
|
||||
{ label: '智力發展 (Intellectual)', value: 72, color: 'success' },
|
||||
{ label: '體育健康 (Physical)', value: 90, color: 'warning' },
|
||||
{ label: '群育合作 (Social)', value: 65, color: 'error' },
|
||||
{ label: '美感教育 (Aesthetic)', value: 80, color: 'primary' },
|
||||
])
|
||||
|
||||
const chart2Title = ref('訪問裝置來源')
|
||||
const pie1Data = ref({
|
||||
value: 75,
|
||||
label: '行動裝置',
|
||||
color: 'purple-accent-2',
|
||||
})
|
||||
|
||||
const chart3Title = ref('本學期及格率')
|
||||
const pie2Data = ref({
|
||||
value: 92,
|
||||
label: '全校平均',
|
||||
color: 'teal-lighten-1',
|
||||
icon: mdiCheckDecagram,
|
||||
})
|
||||
</script>
|
||||
@@ -1,132 +0,0 @@
|
||||
<template>
|
||||
<SKDashboard
|
||||
:announcements="announcements"
|
||||
:applications="applications"
|
||||
:greeting-title="greetingTitle"
|
||||
:quick-navs="quickNavs"
|
||||
:todos="todos"
|
||||
:user-avatar="userAvatar"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
mdiAccountGroup,
|
||||
mdiBookOpenVariant,
|
||||
mdiCalendarCheck,
|
||||
mdiChartBar,
|
||||
mdiCog,
|
||||
mdiHammerWrench,
|
||||
mdiHome,
|
||||
mdiLayers,
|
||||
mdiLock,
|
||||
mdiMonitorShimmer,
|
||||
mdiSchool,
|
||||
mdiViewDashboard,
|
||||
} from '@mdi/js'
|
||||
import { ref } from 'vue'
|
||||
import SKDashboard from '@/components/SKDashboard.vue'
|
||||
|
||||
const userAvatar = ref(
|
||||
'https://avataaars.io/?avatarStyle=Circle&topType=ShortHairShortFlat&accessoriesType=Sunglasses&hairColor=Black&facialHairType=Blank&clotheType=BlazerShirt&clotheColor=Blue01&eyeType=Happy&eyebrowType=Default&mouthType=Smile&skinColor=Light'
|
||||
)
|
||||
const greetingTitle = ref('早安,王校長,開始您一天的工作吧!')
|
||||
|
||||
const applications = ref([
|
||||
{
|
||||
name: '校務行政系統',
|
||||
icon: mdiSchool,
|
||||
desc: '全校教職員工生學籍資料、人事資料、財產管理等核心系統入口。',
|
||||
group: '行政組',
|
||||
date: '2025-01-05',
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
name: '數位學習平台',
|
||||
icon: mdiMonitorShimmer,
|
||||
desc: '提供線上課程、作業繳交、測驗評量與師生互動討論功能。',
|
||||
group: '教學組',
|
||||
date: '2025-01-02',
|
||||
color: 'success',
|
||||
},
|
||||
{
|
||||
name: '圖書館系統',
|
||||
icon: mdiBookOpenVariant,
|
||||
desc: '館藏查詢、圖書借閱、還書預約與電子書資源整合平台。',
|
||||
group: '圖書館',
|
||||
date: '2024-12-28',
|
||||
color: 'warning',
|
||||
},
|
||||
{
|
||||
name: '學生請假系統',
|
||||
icon: mdiCalendarCheck,
|
||||
desc: '學生線上請假申請、導師審核、生輔組備查流程電子化。',
|
||||
group: '學務處',
|
||||
date: '2024-12-25',
|
||||
color: 'error',
|
||||
},
|
||||
{
|
||||
name: '報修系統',
|
||||
icon: mdiHammerWrench,
|
||||
desc: '校園設施設備故障通報、維修進度查詢與滿意度調查。',
|
||||
group: '總務處',
|
||||
date: '2024-12-20',
|
||||
color: 'purple',
|
||||
},
|
||||
{
|
||||
name: '會議室預約',
|
||||
icon: mdiAccountGroup,
|
||||
desc: '校內各大型會議室、視聽教室場地查詢與線上預約登記。',
|
||||
group: '總務處',
|
||||
date: '2024-12-15',
|
||||
color: 'teal',
|
||||
},
|
||||
])
|
||||
|
||||
const announcements = ref([
|
||||
{
|
||||
title: '發布全校停課通知 (凱米颱風)',
|
||||
author: '教務處',
|
||||
time: '1 小時前',
|
||||
avatarColor: 'error',
|
||||
avatarSrc: null,
|
||||
},
|
||||
{
|
||||
title: '發布 113 學年度行事曆',
|
||||
author: '王校長',
|
||||
time: '2 天前',
|
||||
avatarColor: 'primary',
|
||||
avatarSrc: userAvatar.value,
|
||||
},
|
||||
{
|
||||
title: '回覆關於營養午餐的建議',
|
||||
author: '總務主任',
|
||||
time: '3 天前',
|
||||
avatarColor: 'warning',
|
||||
avatarSrc: null,
|
||||
},
|
||||
{
|
||||
title: '更新校園防疫規定',
|
||||
author: '衛生組長',
|
||||
time: '1 週前',
|
||||
avatarColor: 'success',
|
||||
avatarSrc: null,
|
||||
},
|
||||
])
|
||||
|
||||
const quickNavs = ref([
|
||||
{ title: '首頁', icon: mdiHome, color: 'primary' },
|
||||
{ title: '控制台', icon: mdiViewDashboard, color: 'error' },
|
||||
{ title: '組件', icon: mdiLayers, color: 'warning' },
|
||||
{ title: '系統管理', icon: mdiCog, color: 'success' },
|
||||
{ title: '權限', icon: mdiLock, color: 'purple' },
|
||||
{ title: '圖表', icon: mdiChartBar, color: 'info' },
|
||||
])
|
||||
|
||||
const todos = ref([
|
||||
{ title: '審查期末考題', due: '今天 11:00', done: false },
|
||||
{ title: '簽核採購申請單', due: '今天 14:00', done: false },
|
||||
{ title: '校務會議', due: '明天 09:00', done: false },
|
||||
{ title: '教學巡堂', due: '週五 10:00', done: true },
|
||||
])
|
||||
</script>
|
||||
@@ -1,188 +0,0 @@
|
||||
<template>
|
||||
<SKDeptManagement
|
||||
:items="deptItems"
|
||||
:loading="loading"
|
||||
:status-options="statusOptions"
|
||||
@add-sub="onAddSub"
|
||||
@create="onCreate"
|
||||
@delete="onDelete"
|
||||
@edit="onEdit"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { DeptItem } from '@/components/SKDeptManagement.vue'
|
||||
import { ref } from 'vue'
|
||||
import SKDeptManagement from '@/components/SKDeptManagement.vue'
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
const statusOptions = [
|
||||
{ title: '已啟用', value: 1 },
|
||||
{ title: '已禁用', value: 0 },
|
||||
]
|
||||
|
||||
const deptItems = ref([
|
||||
{
|
||||
id: 1,
|
||||
name: '校長室',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '負責統籌全校校務發展',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '教務處',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '負責課程教學與學籍管理',
|
||||
children: [
|
||||
{
|
||||
id: 21,
|
||||
name: '教學組',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '課程編排、教師授課與教學評鑑',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
name: '註冊組',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '學生學籍管理、成績處理與升學輔導',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 23,
|
||||
name: '設備組',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '教學設備採購與維護',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '學務處',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '負責學生生活輔導與活動規劃',
|
||||
children: [
|
||||
{
|
||||
id: 31,
|
||||
name: '訓育組',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '學生自治活動、社團活動與校慶規劃',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 32,
|
||||
name: '生輔組',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '學生生活常規、出缺席管理與校園安全',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 33,
|
||||
name: '衛生組',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '校園環境衛生、傳染病防治與健康促進',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '總務處',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '負責校園營繕、財產管理與經費出納',
|
||||
children: [
|
||||
{
|
||||
id: 41,
|
||||
name: '庶務組',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '校舍修繕、物品採購與工友管理',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 42,
|
||||
name: '出納組',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '現金出納、薪津發放與學費收繳',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '輔導室',
|
||||
status: 1,
|
||||
createTime: '2023/08/01 09:00:00',
|
||||
note: '負責學生心理輔導與生涯規劃',
|
||||
children: [],
|
||||
},
|
||||
])
|
||||
|
||||
function addChildById(items: DeptItem[], parentId: string | number, child: DeptItem): boolean {
|
||||
for (const current of items) {
|
||||
if (!current) continue
|
||||
|
||||
if (current.id === parentId) {
|
||||
if (!current.children) current.children = []
|
||||
current.children.push(child)
|
||||
return true
|
||||
}
|
||||
|
||||
if (current.children && current.children.length > 0) {
|
||||
const found = addChildById(current.children, parentId, child)
|
||||
if (found) return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function updateTreeItemById(items: DeptItem[], updated: DeptItem): boolean {
|
||||
for (let i = 0; i < items.length; i += 1) {
|
||||
const current = items[i]
|
||||
if (!current) continue
|
||||
|
||||
if (current.id === updated.id) {
|
||||
items[i] = {
|
||||
...current,
|
||||
name: updated.name,
|
||||
note: updated.note,
|
||||
status: updated.status,
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if (current.children && current.children.length > 0) {
|
||||
const found = updateTreeItemById(current.children, updated)
|
||||
if (found) return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const onCreate = () => alert('Create Dept')
|
||||
function onAddSub(parent: DeptItem, newItem: DeptItem) {
|
||||
addChildById(deptItems.value, parent.id, newItem)
|
||||
}
|
||||
function onEdit(item: DeptItem) {
|
||||
updateTreeItemById(deptItems.value, item)
|
||||
}
|
||||
function onDelete(item: DeptItem) {
|
||||
if (confirm(`Delete ${item.name}?`)) {
|
||||
alert('Deleted')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
+11
-193
@@ -1,141 +1,19 @@
|
||||
<template>
|
||||
<v-container class="pa-0" fluid>
|
||||
<div class="d-flex flex-column ga-5 py-4 pr-2 pl-0">
|
||||
<v-sheet
|
||||
class="d-flex flex-column flex-sm-row align-start align-sm-center ga-4 pa-5 elevation-1"
|
||||
color="surface"
|
||||
>
|
||||
<v-avatar color="primary" size="52" variant="tonal">
|
||||
<span class="text-h5">👋</span>
|
||||
</v-avatar>
|
||||
<div>
|
||||
<div class="text-h5 font-weight-bold">歡迎使用校務資訊系統</div>
|
||||
<div class="text-body-2 text-medium-emphasis mt-1">
|
||||
使用頂部搜尋框快速找到功能,或從左側選單瀏覽所有系統模組
|
||||
</div>
|
||||
</div>
|
||||
</v-sheet>
|
||||
|
||||
<section class="d-flex flex-column">
|
||||
<div class="d-flex align-center ga-2 text-h6 font-weight-bold">📰 最新消息</div>
|
||||
<!--
|
||||
使用 v-data-iterator 讓消息列表具備一致的資料迭代結構,
|
||||
也方便未來需要加上排序 / 分頁時直接擴充。
|
||||
-->
|
||||
<v-data-iterator class="mt-2" item-key="id" :items="newsItems" :items-per-page="-1">
|
||||
<!--
|
||||
v-data-iterator 的 default slot 會提供包裝後的 items,
|
||||
這裡透過 resolveNewsItem 抽出原始資料,再沿用原本的卡片排版。
|
||||
-->
|
||||
<template #default="{ items }">
|
||||
<v-row density="compact">
|
||||
<v-col v-for="wrapped in items" :key="resolveNewsItem(wrapped).id" cols="12">
|
||||
<v-card
|
||||
class="news-item d-flex flex-column flex-sm-row ga-4 pa-4 bg-surface"
|
||||
variant="outlined"
|
||||
@click="handleNews(resolveNewsItem(wrapped))"
|
||||
>
|
||||
<v-sheet class="news-badge">
|
||||
<div class="news-badge-date">{{ resolveNewsItem(wrapped).date }}</div>
|
||||
<div class="news-badge-month">{{ resolveNewsItem(wrapped).month }}</div>
|
||||
</v-sheet>
|
||||
<div class="flex-grow-1">
|
||||
<div class="d-flex flex-wrap align-center font-weight-bold">
|
||||
{{ resolveNewsItem(wrapped).title }}
|
||||
<v-chip
|
||||
v-if="resolveNewsItem(wrapped).isNew"
|
||||
class="ml-2"
|
||||
color="primary"
|
||||
size="x-small"
|
||||
variant="flat"
|
||||
>
|
||||
NEW
|
||||
</v-chip>
|
||||
</div>
|
||||
<div class="text-body-2 text-medium-emphasis mt-2">
|
||||
{{ resolveNewsItem(wrapped).desc }}
|
||||
</div>
|
||||
<div class="d-flex ga-4 mt-3 text-caption text-medium-emphasis">
|
||||
<div class="d-flex align-center ga-1">
|
||||
<v-icon size="14" :icon="mdiFolderOutline" />
|
||||
<span>{{ resolveNewsItem(wrapped).dept }}</span>
|
||||
</div>
|
||||
<div class="d-flex align-center ga-1">
|
||||
<v-icon size="14" :icon="mdiEyeOutline" />
|
||||
<span>{{ resolveNewsItem(wrapped).views }} 次瀏覽</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
</v-data-iterator>
|
||||
</section>
|
||||
|
||||
<v-card
|
||||
class="d-flex align-center justify-space-between ga-3 px-5 py-4"
|
||||
color="secondary"
|
||||
rounded="xl"
|
||||
variant="tonal"
|
||||
@click="handleMessageCenter"
|
||||
>
|
||||
<div class="d-flex align-center ga-4">
|
||||
<v-avatar color="secondary" size="44" variant="flat">
|
||||
<span class="text-h6">✉️</span>
|
||||
</v-avatar>
|
||||
<div>
|
||||
<div class="text-subtitle-1 font-weight-bold">訊息中心</div>
|
||||
<div class="text-body-2 font-weight-bold text-on-secondary">12 筆未讀</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-body-2 font-weight-medium">查看全部 →</div>
|
||||
</v-card>
|
||||
|
||||
<section class="d-flex flex-column pb-4">
|
||||
<div class="d-flex align-center ga-2 text-h6 font-weight-bold">🚀 快速存取</div>
|
||||
<v-row class="mt-2" density="compact">
|
||||
<v-col v-for="item in quickItems" :key="item.title" cols="6" md="2" sm="4">
|
||||
<v-card
|
||||
class="d-flex flex-column align-center ga-2 text-center py-4 px-2 quick-item"
|
||||
variant="outlined"
|
||||
@click="handleQuick(item)"
|
||||
>
|
||||
<div class="text-h5">{{ item.icon }}</div>
|
||||
<div class="text-body-2 font-weight-medium">{{ item.title }}</div>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
點擊消息後顯示的對話框。
|
||||
僅負責呈現內容,不做任何延伸操作,確保互動行為單純可預期。
|
||||
-->
|
||||
<v-dialog v-model="isNewsDialogOpen" max-width="640">
|
||||
<v-card v-if="selectedNews">
|
||||
<v-card-title class="text-h6 font-weight-bold bg-primary-variant pa-4">
|
||||
{{ selectedNews.title }}
|
||||
</v-card-title>
|
||||
<v-card-subtitle class="text-body-2 pt-4 text-medium-emphasis">
|
||||
{{ selectedNews.month }} {{ selectedNews.date }} · {{ selectedNews.dept }} ·
|
||||
{{ selectedNews.views }} 次瀏覽
|
||||
</v-card-subtitle>
|
||||
<v-card-text class="pt-4">
|
||||
{{ selectedNews.desc }}
|
||||
</v-card-text>
|
||||
<v-card-actions class="justify-end">
|
||||
<v-btn color="primary" variant="text" @click="isNewsDialogOpen = false">關閉</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-container>
|
||||
<PageIndex
|
||||
:is-news-dialog-open="isNewsDialogOpen"
|
||||
:news-items="newsItems"
|
||||
:quick-items="quickItems"
|
||||
:selected-news="selectedNews"
|
||||
@message-center="handleMessageCenter"
|
||||
@news="handleNews"
|
||||
@quick="handleQuick"
|
||||
@update:is-news-dialog-open="isNewsDialogOpen = $event"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { mdiEyeOutline, mdiFolderOutline } from '@mdi/js'
|
||||
import { ref } from 'vue'
|
||||
import PageIndex from '@/components/PageIndex.vue'
|
||||
import { useMessageStore } from '@/stores/messages'
|
||||
import { useSnackbarStore } from '@/stores/snackbar'
|
||||
|
||||
@@ -189,15 +67,6 @@ const quickItems = [
|
||||
const selectedNews = ref<NewsItem | null>(null)
|
||||
const isNewsDialogOpen = ref(false)
|
||||
|
||||
// v-data-iterator 會包裝 items,這個方法用來安全地取回原始資料結構。
|
||||
function resolveNewsItem(wrapped: unknown): NewsItem {
|
||||
if (wrapped && typeof wrapped === 'object' && 'raw' in wrapped) {
|
||||
return (wrapped as { raw: NewsItem }).raw
|
||||
}
|
||||
|
||||
return wrapped as NewsItem
|
||||
}
|
||||
|
||||
function handleNews(item: NewsItem) {
|
||||
selectedNews.value = item
|
||||
isNewsDialogOpen.value = true
|
||||
@@ -212,54 +81,3 @@ function handleQuick(item: (typeof quickItems)[number]) {
|
||||
snackbar.show({ message: `前往:${item.title}`, color: 'info' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.news-item {
|
||||
cursor: pointer;
|
||||
transition:
|
||||
transform 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.news-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 10px 24px rgba(var(--v-theme-on-surface), 0.12);
|
||||
}
|
||||
|
||||
.news-badge {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgb(var(--v-theme-primary));
|
||||
color: rgb(var(--v-theme-on-primary));
|
||||
border-radius: 12px;
|
||||
padding: 10px 6px;
|
||||
min-height: 64px;
|
||||
min-width: 64px;
|
||||
}
|
||||
|
||||
.news-badge-date {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.news-badge-month {
|
||||
font-size: 12px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.quick-item {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
transform 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.quick-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 10px 24px rgba(var(--v-theme-on-surface), 0.12);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
<template>
|
||||
<SKMenuManagement
|
||||
:items="menuItems"
|
||||
:loading="loading"
|
||||
:permission-options="permissionOptions"
|
||||
:status-options="statusOptions"
|
||||
@edit="onEdit"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { MenuItem } from '@/components/SKMenuManagement.vue'
|
||||
import { ref } from 'vue'
|
||||
import SKMenuManagement from '@/components/SKMenuManagement.vue'
|
||||
|
||||
const loading = ref(false)
|
||||
const statusOptions = [
|
||||
{ title: '已啟用', value: 1 },
|
||||
{ title: '已禁用', value: 0 },
|
||||
]
|
||||
const permissionOptions = ['管理員', '一級主管', '二級主管', '使用者']
|
||||
const menuItems = ref([
|
||||
{
|
||||
id: 1,
|
||||
title: '工作台',
|
||||
permission: '使用者',
|
||||
path: '/workspace',
|
||||
component: '/dashboard/workspace/index',
|
||||
status: 1,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '系統管理',
|
||||
|
||||
permission: '管理員',
|
||||
path: '/system',
|
||||
component: 'LAYOUT',
|
||||
status: 1,
|
||||
isNew: true,
|
||||
children: [
|
||||
{
|
||||
id: 21,
|
||||
title: '菜單管理',
|
||||
|
||||
permission: '管理員',
|
||||
path: '/system/menu',
|
||||
component: '/system/menu/list',
|
||||
status: 1,
|
||||
children: [
|
||||
{
|
||||
id: 211,
|
||||
title: '新增',
|
||||
permission: '管理員',
|
||||
status: 1,
|
||||
},
|
||||
{
|
||||
id: 212,
|
||||
title: '修改',
|
||||
permission: '管理員',
|
||||
status: 1,
|
||||
},
|
||||
{
|
||||
id: 213,
|
||||
title: '刪除',
|
||||
permission: '管理員',
|
||||
status: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
title: '部門管理',
|
||||
permission: '一級主管',
|
||||
path: '/system/dept',
|
||||
component: '/system/dept/list',
|
||||
status: 1,
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: '項目',
|
||||
permission: '二級主管',
|
||||
path: '/vben-admin',
|
||||
component: 'LAYOUT',
|
||||
status: 1,
|
||||
children: [
|
||||
{
|
||||
id: 31,
|
||||
title: '文檔',
|
||||
permission: '使用者',
|
||||
path: '/vben-admin/document',
|
||||
component: 'https://doc.vben.pro',
|
||||
status: 1,
|
||||
},
|
||||
{
|
||||
id: 32,
|
||||
title: 'Ant Design Vue 版本',
|
||||
permission: '使用者',
|
||||
path: '/vben-admin/antdv',
|
||||
component: 'https://ant.vben.pro',
|
||||
status: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: '關於',
|
||||
permission: '使用者',
|
||||
path: '/about',
|
||||
component: '_core/about/index',
|
||||
status: 1,
|
||||
children: [],
|
||||
},
|
||||
])
|
||||
|
||||
function updateTreeItemById(items: MenuItem[], updated: MenuItem): boolean {
|
||||
for (let i = 0; i < items.length; i += 1) {
|
||||
const current = items[i]
|
||||
if (!current) continue
|
||||
|
||||
if (current.id === updated.id) {
|
||||
items[i] = {
|
||||
...current,
|
||||
status: updated.status,
|
||||
permission: updated.permission,
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if (current.children && current.children.length > 0) {
|
||||
const found = updateTreeItemById(current.children, updated)
|
||||
if (found) return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function onEdit(item: MenuItem) {
|
||||
updateTreeItemById(menuItems.value, item)
|
||||
}
|
||||
</script>
|
||||
@@ -1,122 +0,0 @@
|
||||
<template>
|
||||
<SKRoleManagement
|
||||
:loading="loading"
|
||||
:roles="roles"
|
||||
@create="onCreate"
|
||||
@delete="onDelete"
|
||||
@edit="onEdit"
|
||||
@reset="onReset"
|
||||
@search="onSearch"
|
||||
@update:status="onStatusUpdate"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { RoleItem } from '@/components/SKRoleManagement.vue'
|
||||
import { ref } from 'vue'
|
||||
import SKRoleManagement from '@/components/SKRoleManagement.vue'
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
const roles = ref([
|
||||
{
|
||||
name: 'Car',
|
||||
id: '2216c0ab-9d0e-4f6e-a7d6-12...',
|
||||
status: false,
|
||||
note: 'Somnus careo ultio caste vix adversus textilis vaco defero coniuratio.',
|
||||
createTime: '2022/05/13 01:03:31',
|
||||
},
|
||||
{
|
||||
name: 'Chair',
|
||||
id: '2625810b-639f-4213-944e-ae...',
|
||||
status: false,
|
||||
note: 'Ulterius tristis voluptatum demergo.',
|
||||
createTime: '2024/05/30 21:04:49',
|
||||
},
|
||||
{
|
||||
name: 'Shoes',
|
||||
id: 'c19c2b27-f9c9-46b8-93db-11f...',
|
||||
status: true,
|
||||
note: 'Illum delinquo texo tumultus perferendis debilito.',
|
||||
createTime: '2024/07/18 06:21:55',
|
||||
},
|
||||
{
|
||||
name: 'Cheese',
|
||||
id: '7d1053ac-acc1-405f-8c66-235...',
|
||||
status: true,
|
||||
note: 'Acidus vobis coruscus.',
|
||||
createTime: '2024/07/03 07:44:10',
|
||||
},
|
||||
{
|
||||
name: 'Gloves',
|
||||
id: '9bb9ed44-dfcd-11b8-bcb1-d0...',
|
||||
status: true,
|
||||
note: 'Vivo caelum quo caveo valetudo.',
|
||||
createTime: '2024/10/05 12:00:17',
|
||||
},
|
||||
{
|
||||
name: 'Shoes',
|
||||
id: 'cdb0c47a-284e-4ca3-b434-e8...',
|
||||
status: true,
|
||||
note: 'Veritas adflicto temperantia.',
|
||||
createTime: '2024/11/20 16:35:09',
|
||||
},
|
||||
{
|
||||
name: 'Computer',
|
||||
id: 'db9d1509-7247-4a38-9bd9-b...',
|
||||
status: true,
|
||||
note: 'Viridis titulus somnus voluptate voluptate aspicio sophismata ansor th...',
|
||||
createTime: '2023/02/21 06:16:25',
|
||||
},
|
||||
{
|
||||
name: 'Cheese',
|
||||
id: '1beb5ce6-11f2-490f-9549-101...',
|
||||
status: true,
|
||||
note: 'Eveniet amicitia bestia supra.',
|
||||
createTime: '2022/02/19 12:51:41',
|
||||
},
|
||||
{
|
||||
name: 'Towels',
|
||||
id: 'bd9c74bb-fc3a-4a7a-8b3f-55f...',
|
||||
status: true,
|
||||
note: 'Dapifer aliquam amoveo vitium ubi repellendus tactus bardus crepusc...',
|
||||
createTime: '2023/02/16 20:09:27',
|
||||
},
|
||||
])
|
||||
|
||||
function onSearch(params: Record<string, unknown>) {
|
||||
console.log('Search:', params)
|
||||
loading.value = true
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
alert('Search Triggered! Check Console.')
|
||||
}, 500)
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
console.log('Reset')
|
||||
}
|
||||
|
||||
function onCreate() {
|
||||
console.log('Create Role')
|
||||
alert('Create Role Clicked')
|
||||
}
|
||||
|
||||
function onEdit(item: RoleItem) {
|
||||
console.log('Edit:', item)
|
||||
alert(`Edit ${item.name}`)
|
||||
}
|
||||
|
||||
function onDelete(item: RoleItem) {
|
||||
console.log('Delete:', item)
|
||||
if (confirm(`Are you sure you want to delete ${item.name}?`)) {
|
||||
roles.value = roles.value.filter((r) => r.id !== item.id)
|
||||
}
|
||||
}
|
||||
|
||||
function onStatusUpdate(item: RoleItem, newVal: boolean) {
|
||||
// In a real app, API call here
|
||||
item.status = newVal
|
||||
console.log('Status Update:', item.name, newVal)
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user