新增巡檢任務與巡檢設定初頁面,調整側邊欄與麵包屑組件的路由配置

This commit is contained in:
huliang 2025-11-13 17:23:47 +08:00
parent 9bcbad5ee3
commit 0e33a0b64f
6 changed files with 94 additions and 157 deletions

View File

@ -8,17 +8,10 @@
</el-breadcrumb-item>
<el-breadcrumb-item
v-for="(item, idx) in breadcrumbs"
:key="item.path || idx"
:to="
item.path && idx !== breadcrumbs.length - 1
? { path: item.path }
: undefined
"
:key=" idx"
:to="item.name ? { name: item.name } : undefined"
>
<span v-if="!item.path || idx === breadcrumbs.length - 1">{{
item.title || item.name
}}</span>
<span v-else>{{ item.title || item.name }}</span>
<span>{{ item.title }}</span>
</el-breadcrumb-item>
</el-breadcrumb>
</template>
@ -28,84 +21,30 @@ import { computed } from "vue";
import { useRoute } from "vue-router";
import { menuConfig } from "../../constants/menuConfig.js";
//
function findMenuItem(route) {
for (const menu of menuConfig) {
for (const child of menu.children) {
//
if (child.routeName === route.name || child.path === route.path) {
return { parent: menu, item: child };
const route = useRoute();
function findBreadcrumbs(menu, route, path = []) {
for (const item of menu) {
const currentPath = [...path, { title: item.title, name: item.routeName || null }];
if (item.routeName === route.name) {
if (item.params) {
const paramsMatch = Object.keys(item.params).every(key => item.params[key] == route.params[key]);
if (paramsMatch) {
return currentPath;
}
// /plant/:id
if (
child.routeName === "PlantInfo" &&
route.path &&
route.path.startsWith("/plant/")
) {
return { parent: menu, item: child };
} else {
return currentPath;
}
}
if (item.children) {
const result = findBreadcrumbs(item.children, route, currentPath);
if (result) return result;
}
}
return null;
}
function buildBreadcrumb(route) {
const match = findMenuItem(route);
if (!match) return [];
const crumbs = [
{
name: match.parent.title,
title: match.parent.title,
path: null,
meta: { title: match.parent.title },
},
];
let itemTitle = match.item.title;
if (route.name === "PlantInfo" && route.params.id) {
const plantNames = {
"1": "四磺子坪",
"2": "宜蘭大清水",
"3": "宜蘭小清水",
};
itemTitle = plantNames[route.params.id] || match.item.title;
}
crumbs.push({
name: itemTitle,
title: itemTitle,
path: match.item.path,
meta: { title: itemTitle },
});
return crumbs;
}
const route = useRoute();
const breadcrumbs = computed(() => {
const menuBreadcrumbs = buildBreadcrumb(route);
if (menuBreadcrumbs.length > 0) {
return menuBreadcrumbs;
}
const matchedRoutes = route.matched.filter((r) => r.meta && r.meta.title);
if (matchedRoutes.length === 0) {
return [];
}
const currentRoute = matchedRoutes[matchedRoutes.length - 1];
if (currentRoute.meta.parentTitle) {
return [
{
title: currentRoute.meta.parentTitle,
path: null,
},
{
title: currentRoute.meta.title,
path: currentRoute.path,
},
];
}
return matchedRoutes.map((r) => ({
title: r.meta.title,
name: r.name,
path: r.path,
}));
return findBreadcrumbs(menuConfig, route) || [];
});
</script>

View File

@ -16,7 +16,7 @@
<span>結元能源</span>
</div>
<el-sub-menu v-for="menu in menuConfig" :key="menu.id" :index="menu.id">
<el-sub-menu v-for="menu in menuConfig" :key="menu.title" :index="menu.title">
<template #title>
<el-icon>
<component :is="getIconComponent(menu.icon)" />
@ -26,8 +26,8 @@
<el-menu-item
v-for="item in menu.children"
:key="item.id"
:index="item.path || item.id"
:key="item.title"
:index="item.title"
@click="handleMenuClick(item)"
>
{{ item.title }}
@ -73,12 +73,9 @@ const getIconComponent = (iconName) => {
//
const handleMenuClick = (item) => {
if (item.path) {
if (item.routeName && item.params) {
router.push({ name: item.routeName, params: item.params });
} else {
router.push(item.path);
}
if (item.routeName) {
router.push({ name: item.routeName, params: item.params || {} });
return;
}
};
@ -87,12 +84,12 @@ const activeMenuIndex = computed(() => {
//
for (const menu of menuConfig) {
for (const item of menu.children) {
if (item.routeName === route.name || item.path === route.path) {
return item.path || item.id;
if (item.routeName === route.name) {
return item.title;
}
}
}
return route.name || route.path;
return '';
});
</script>

View File

@ -1,129 +1,102 @@
export const menuConfig = [
{
id: 'overview',
title: '總覽',
icon: 'Location',
children: [
{
id: 'PlantsMap',
title: '地圖總覽',
path: '/plantsMap',
routeName: 'PlantsMap'
},
{
id: 'PlantsOverview',
title: '電廠總覽',
path: '/plants',
routeName: 'PlantsOverview'
}
]
},
{
id: 'factory-info',
title: '電廠資訊',
icon: 'Postcard',
children: [
{
id: 'plant-1',
title: '四磺子坪',
path: '/plant/1',
routeName: 'PlantInfo',
params: { id: 1 }
},
{
id: 'plant-2',
title: '宜蘭大清水',
path: '/plant/2',
routeName: 'PlantInfo',
params: { id: 2 }
},
{
id: 'plant-3',
title: '宜蘭小清水',
path: '/plant/3',
routeName: 'PlantInfo',
params: { id: 3 }
}
]
},
{
id: 'inspection',
title: '巡檢系統',
icon: 'DocumentChecked',
children: [
{
id: 'inspection-task',
title: '巡檢任務'
title: '巡檢任務',
routeName: 'PatrolMission',
},
{
id: 'inspection-setting',
title: '巡檢設定'
title: '巡檢設定',
routeName: 'PatrolSetting',
}
]
},
{
id: 'report',
title: '報表查詢',
icon: 'DataLine',
children: [
{
id: 'PlantsReport',
title: '電廠報表',
path: '/plantsReport',
routeName: 'PlantsReport'
}
]
},
{
id: 'alert',
title: '即時告警',
icon: 'Bell',
children: [
{
id: 'alert-event',
title: '異常事件查詢'
}
]
},
{
id: 'material',
title: '備料管理',
icon: 'MessageBox',
children: [
{
id: 'material-item',
title: '備品料件管理'
},
{
id: 'material-location',
title: '倉庫櫃位管理'
}
]
},
{
id: 'security',
title: '智慧安防',
icon: 'VideoCamera',
children: [
{
id: 'security-system',
title: '安防系統'
}
]
},
{
id: 'system',
title: '系統設定',
icon: 'Setting',
children: [
{
id: 'system-factory',
title: '電廠設定',
path: '/plantSetting',
routeName: 'PlantSetting'
},
{
id: 'system-account',
title: '帳號設定'
}
]

View File

@ -1,62 +1,51 @@
import { createRouter, createWebHashHistory } from "vue-router";
import Home from "../views/Home.vue";
import PlantsOverview from "../views/PlantsOverview.vue";
import PatrolMission from "../views/PatrolMission.vue";
import PatrolSetting from "../views/PatrolSetting.vue";
import PlantReport from "../views/PlantReport.vue";
import PlantInfo from "../views/PlantInfo.vue";
import PlantSetting from "../views/PlantSetting.vue";
const routes = [
{
path: "/",
redirect: "/plantsMap"
},
{
path: "/plantsMap",
name: "PlantsMap",
component: Home,
meta: {
title: "地圖總覽",
icon: "Location",
menuGroup: "overview",
parentTitle: "總覽",
},
component: Home
},
{
path: "/plants",
name: "PlantsOverview",
component: PlantsOverview,
meta: {
title: "電廠總覽",
icon: "Postcard",
menuGroup: "overview",
parentTitle: "總覽"
},
component: PlantsOverview
},
{
path: "/plant/:id",
name: "PlantInfo",
component: PlantInfo,
meta: {
title: "電廠詳細",
menuGroup: "factory-info",
parentTitle: "電廠資訊",
component: PlantInfo
},
{
path: "/patrolMission",
name: "PatrolMission",
component: PatrolMission
},
{
path: "/patrolSetting",
name: "PatrolSetting",
component: PatrolSetting
},
{
path: "/plantsReport",
name: "PlantsReport",
component: PlantReport,
meta: {
title: "電廠報表",
menuGroup: "report",
parentTitle: "報表查詢",
},
component: PlantReport
},
{
path: "/plantSetting",
name: "PlantSetting",
component: PlantSetting,
meta: {
title: "電廠設定",
menuGroup: "report",
parentTitle: "系統設定",
},
component: PlantSetting
}
];

View File

@ -0,0 +1,9 @@
<template>
</template>
<script setup>
import { ref, computed } from "vue";
</script>
<style scoped></style>

View File

@ -0,0 +1,30 @@
<template>
<el-row :gutter="20" style="margin-top: 20px">
<el-col :xs="24">
<el-card shadow="always" class="custom-card">
<template #header
><el-radio-group v-model="radio" size="large" fill="#409eff">
<el-radio-button label="樣板管理" value="template" />
<el-radio-button label="任務管理" value="task" /> </el-radio-group
></template>
<div v-if="radio === 'template'">
<!-- 樣板管理內容 -->
<p>這裡是樣板管理</p>
</div>
<div v-if="radio === 'task'">
<!-- 任務管理內容 -->
<p>這裡是任務管理</p>
</div>
</el-card>
</el-col>
</el-row>
</template>
<script setup>
import { ref } from "vue";
const radio = ref("template");
</script>
<style scoped></style>