This commit is contained in:
huliang 2025-05-09 18:10:10 +08:00
parent 7599b7fa3a
commit 48dd8d62bb
11 changed files with 141 additions and 60 deletions

View File

@ -9,23 +9,27 @@ const alarmDataStore = useAlarmDataStore();
<template> <template>
<a-card class="card"> <a-card class="card">
<h5>Alarm</h5> <h5>異常告警</h5>
<table className="table w-full"> <table className="table w-full">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>異常類別</th>
<th>In Alarm Count</th> <th>發報中</th>
<th>Unacked Count</th> <th>未確認</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="(item, index) in alarmDataStore.alarmData" :key="index"> <tr
v-for="(item, index) in alarmDataStore.alarmData"
:key="index"
:class="item.alarmCount > 0 ? 'animate-pulse' : ''"
>
<td> <td>
<font-awesome-icon <font-awesome-icon
v-if="item.alarmCount > 0" v-if="item.alarmCount > 0"
:icon="['fas', 'exclamation-circle']" :icon="['fas', 'exclamation-circle']"
class="text-rose-600 text-lg animate-pulse -ms-5" class="text-rose-600 text-base -ms-5"
/> />
{{ item.name }} {{ item.name }}
</td> </td>
@ -35,10 +39,11 @@ const alarmDataStore = useAlarmDataStore();
<router-link <router-link
:to="{ :to="{
name: 'baja', name: 'baja',
query: { ord: encodeURIComponent(item.Ord) }, query: { pagename: 'alert',
ord: encodeURIComponent(item.Ord) },
}" }"
class="flex items-center justify-between gap-8" class="flex items-center justify-between gap-8"
>view</router-link >查看</router-link
> >
</td> </td>
</tr> </tr>
@ -53,21 +58,21 @@ const alarmDataStore = useAlarmDataStore();
h5 { h5 {
margin: 0; margin: 0;
font-weight: 700; font-weight: 700;
font-size: 18px; font-size: 33px;
color: #141414; color: #141414;
} }
.table th { .table th {
text-align: left; text-align: left;
border-bottom: 1px solid rgba(0, 0, 0, 0.05); border-bottom: 1px solid rgba(0, 0, 0, 0.05);
font-size: 15px; font-size: 1.125rem;
font-weight: 600; font-weight: 600;
padding: 8px 0; padding: 8px 0;
color: #8c8c8c; color: #8c8c8c;
} }
.table td { .table td {
font-size: 15px; font-size: 1.125rem;
padding: 16px 0px; padding: 8px 0px;
white-space: nowrap; white-space: nowrap;
} }
</style> </style>

View File

@ -14,8 +14,8 @@ const props = defineProps({
const yesterdayTodayChart = ref(null); const yesterdayTodayChart = ref(null);
const weekComparisonChart = ref(null); const weekComparisonChart = ref(null);
let yesterdayTodayEChart = null; let yesterdayTodayEChart = null;
let weekComparisonEChart = null; let weekComparisonEChart = null;
watch( watch(
() => props.yesterdayTodayData, () => props.yesterdayTodayData,
@ -70,7 +70,21 @@ onUnmounted(() => {
// option // option
const generateCylinderChartOption = (data) => { const generateCylinderChartOption = (data) => {
const barWidth = 15; const dataCount = data.categories.length; //
let barWidth = 15; //
let symbolOffset = 0; //
if (dataCount <= 7) {
barWidth = 15;
symbolOffset = 9;
} else if (dataCount <= 10) {
barWidth = 10;
symbolOffset = 6;
} else {
barWidth = 8;
symbolOffset = 5;
}
const color1 = { const color1 = {
// //
type: "linear", type: "linear",
@ -157,7 +171,7 @@ const generateCylinderChartOption = (data) => {
name: null, name: null,
type: "pictorialBar", type: "pictorialBar",
symbolSize: [barWidth, 5], symbolSize: [barWidth, 5],
symbolOffset: [-9, -4], // symbolOffset: [-symbolOffset, -4], //
symbolPosition: "end", symbolPosition: "end",
data: data.values[0].value, data: data.values[0].value,
z: 12, z: 12,
@ -172,7 +186,7 @@ const generateCylinderChartOption = (data) => {
name: null, name: null,
type: "pictorialBar", type: "pictorialBar",
symbolSize: [barWidth, 5], symbolSize: [barWidth, 5],
symbolOffset: [9, -4], // symbolOffset: [symbolOffset, -4], //
symbolPosition: "end", symbolPosition: "end",
data: data.values[1].value, data: data.values[1].value,
itemStyle: { itemStyle: {
@ -188,7 +202,7 @@ const generateCylinderChartOption = (data) => {
name: null, name: null,
type: "pictorialBar", type: "pictorialBar",
symbolSize: [barWidth, 5], symbolSize: [barWidth, 5],
symbolOffset: [-9, 4], // symbolOffset: [-symbolOffset, 4], //
symbolPosition: "start", symbolPosition: "start",
data: data.values[0].value, data: data.values[0].value,
z: 12, z: 12,
@ -200,7 +214,7 @@ const generateCylinderChartOption = (data) => {
name: null, name: null,
type: "pictorialBar", type: "pictorialBar",
symbolSize: [barWidth, 5], symbolSize: [barWidth, 5],
symbolOffset: [9, 4], // symbolOffset: [symbolOffset, 4], //
symbolPosition: "start", symbolPosition: "start",
data: data.values[1].value, data: data.values[1].value,
itemStyle: { itemStyle: {

View File

@ -46,7 +46,9 @@ const handleClick = (ord) => {
if (ord) { if (ord) {
router.push({ router.push({
name: "baja", name: "baja",
query: { ord: encodeURIComponent(ord) }, query: {
pagename: 'system',
ord: encodeURIComponent(ord) },
}); });
} }
}; };
@ -54,8 +56,8 @@ const handleClick = (ord) => {
<template> <template>
<a-card class="card h-full mb-4"> <a-card class="card h-full mb-4">
<div class="flex items-cemter justify-between mb-4"> <div class="flex items-center justify-between mb-4">
<h5>System</h5> <h5>系統監控</h5>
<NavBuild /> <NavBuild />
</div> </div>
<div v-if="flattenedItems.length > 0"> <div v-if="flattenedItems.length > 0">
@ -93,7 +95,7 @@ const handleClick = (ord) => {
h5 { h5 {
margin: 0; margin: 0;
font-weight: 700; font-weight: 700;
font-size: 18px; font-size: 33px;
color: #141414; color: #141414;
} }
</style> </style>

View File

@ -18,7 +18,12 @@ const preOpenKeys = ref([]); // 用於儲存之前展開的 submenu
const filteredItems = computed(() => { const filteredItems = computed(() => {
if (navStore.menuList && navStore.menuList.length > 0) { if (navStore.menuList && navStore.menuList.length > 0) {
return navStore.menuList[0].children; if(navStore.menuList[0].children.length > 1){
return navStore.menuList[0].children;
}else{
return navStore.menuList[0].children[0].children;
}
} }
return []; return [];
}); });
@ -27,7 +32,8 @@ const handleClick = (ord) => {
if (ord) { if (ord) {
router.push({ router.push({
name: "baja", name: "baja",
query: { ord: encodeURIComponent(ord) }, query: { pagename: 'system',
ord: encodeURIComponent(ord) },
}); });
} }
}; };

View File

@ -44,7 +44,7 @@ onBeforeUnmount(() => {
<router-link <router-link
:to="{ :to="{
name: 'baja', name: 'baja',
query: { ord: encodeURIComponent(child.Ord) }, query: { pagename: 'alarm', ord: encodeURIComponent(child.Ord) },
}" }"
class="flex items-center justify-between gap-8" class="flex items-center justify-between gap-8"
> >
@ -54,7 +54,7 @@ onBeforeUnmount(() => {
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>
</template> </template>
<a-badge :count="totalAlarmCount" :overflow-count="999"> <a-badge :count="totalAlarmCount" :overflow-count="999" class="!mt-3">
<a class="flex flex-col items-center"> <a class="flex flex-col items-center">
<font-awesome-icon :icon="['fas', 'bell']" size="2x" /> <font-awesome-icon :icon="['fas', 'bell']" size="2x" />
<span class="text-sm">告警</span> <span class="text-sm">告警</span>

View File

@ -26,7 +26,7 @@ watch(
<template> <template>
<a-select <a-select
v-if="buildmenu && buildmenu.length > 0" v-if="buildmenu && buildmenu.length > 1"
:default-value="buildmenu[0] ? buildmenu[0].label : null" :default-value="buildmenu[0] ? buildmenu[0].label : null"
@change="handleBuildClick" @change="handleBuildClick"
placeholder="請選擇建築" placeholder="請選擇建築"

View File

@ -108,19 +108,24 @@ const updateTime = () => {
if (window.require && window.requirejs) { if (window.require && window.requirejs) {
window.requirejs(["baja!"], (baja) => { window.requirejs(["baja!"], (baja) => {
const bAbsTime = baja.AbsTime.make({ jsDate: date }); const bAbsTime = baja.AbsTime.make({ jsDate: date });
bAbsTime.toDateTimeString().then((dateTimeStr) => { bAbsTime
dateTime.value = dateTimeStr; .toDateTimeString()
}); .then((dateTimeStr) => {
dateTime.value = dateTimeStr;
})
.catch((error) => {
console.error("轉換時間字串失敗:", error);
});
}); });
} }
}; };
onMounted(() => { onMounted(() => {
setTimeout(() => {
initializeData(); //
}, 500);
updateTime(); // updateTime(); //
intervalId = setInterval(updateTime, 1000); intervalId = setInterval(updateTime, 1000);
setTimeout(() => {
initializeData();
}, 1000);
}); });
onUnmounted(() => { onUnmounted(() => {

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import { computed, defineProps } from "vue"; import { computed, defineProps, ref, watch } from "vue";
import { useRouter } from "vue-router"; import { useRouter, useRoute } from "vue-router";
import NavBuild from "./NavBuild.vue"; import NavBuild from "./NavBuild.vue";
import NavWeather from "./NavWeather.vue"; import NavWeather from "./NavWeather.vue";
import NavAlarm from "./NavAlarm.vue"; import NavAlarm from "./NavAlarm.vue";
@ -8,6 +8,7 @@ import useNiagaraDataStore from "@/stores/useNiagaraDataStore";
import useNavDataStore from "@/stores/useNavDataStore"; import useNavDataStore from "@/stores/useNavDataStore";
const router = useRouter(); const router = useRouter();
const route = useRoute();
const niagaraStore = useNiagaraDataStore(); const niagaraStore = useNiagaraDataStore();
const navStore = useNavDataStore(); const navStore = useNavDataStore();
@ -16,8 +17,14 @@ const props = defineProps({
userName: String, userName: String,
}); });
const activePageName = ref("home");
const openSystemMonitor = () => {
props.open();
};
function correctImageUrl(imageUrl) { function correctImageUrl(imageUrl) {
if (!imageUrl) return ''; // if (!imageUrl) return ""; //
const stringUrlNiagara = "file:^"; const stringUrlNiagara = "file:^";
const stringUrlNiagara2 = "station:|file:^"; const stringUrlNiagara2 = "station:|file:^";
@ -62,53 +69,64 @@ const dynamicMenu = computed(() =>
); );
const userList = computed(() => niagaraStore.userList?.children || []); const userList = computed(() => niagaraStore.userList?.children || []);
watch(
() => route.query.pagename,
(newPagename) => {
activePageName.value = newPagename || "home" ; //
},
{
immediate: true,
}
);
</script> </script>
<template> <template>
<a-layout-header class="header"> <a-layout-header class="header">
<div class="flex items-center"> <div class="flex items-center">
<img v-if="logoUrl" :src="logoUrl" alt="Logo" class="logo" /> <img v-if="logoUrl" :src="logoUrl" alt="Logo" class="logo" />
<a href="./index.html" class="text-2xl font-bold mx-4">{{ <a href="./index.html" class="text-[33px] font-bold mx-4">{{
systemName systemName
}}</a> }}</a>
<!-- <NavBuild /> --> <!-- <NavBuild /> -->
</div> </div>
<ul class="nav-menu flex gap-10"> <ul class="nav-menu flex gap-10">
<li> <li :class="{ 'link-active': activePageName === 'home' }">
<router-link <router-link
:to=" :to="
homeData.ord !== 'null' homeData.ord !== 'null'
? { ? {
name: 'baja', name: 'baja',
query: { ord: encodeURIComponent(homeData.ord) }, query: {
pagename: 'home',
ord: encodeURIComponent(homeData.ord),
},
} }
: '/' : '/'
" "
class="nav-link"
> >
<img <img :src="homeData.icon" alt="home_icon" class="icon" />
:src="homeData.icon"
alt="home_icon"
class="icon"
/>
<span class="text-sm">首頁</span> <span class="text-sm">首頁</span>
</router-link> </router-link>
</li> </li>
<li> <li :class="{ 'link-active': activePageName === 'system' }">
<a <a @click.prevent="openSystemMonitor" class="nav-link">
@click="props.open" <img :src="systemData.icon" alt="system_icon" class="icon" />
>
<img
:src="systemData.icon"
alt="system_icon"
class="icon"
/>
<span class="text-sm">系統監控</span> <span class="text-sm">系統監控</span>
</a> </a>
</li> </li>
<li v-for="item in dynamicMenu" :key="item.key"> <li
v-for="item in dynamicMenu"
:key="item.key"
:class="{ 'link-active': activePageName === item.ord }"
>
<router-link <router-link
:to="{ name: 'baja', query: { ord: encodeURIComponent(item.ord) } }" :to="{
name: 'baja',
query: { pagename: item.ord, ord: encodeURIComponent(item.ord) },
}"
class="nav-link"
> >
<img :src="item.icon" alt="menu_icon" class="icon" /> <img :src="item.icon" alt="menu_icon" class="icon" />
<span class="text-sm">{{ item.name }}</span> <span class="text-sm">{{ item.name }}</span>
@ -130,7 +148,10 @@ const userList = computed(() => niagaraStore.userList?.children || []);
<router-link <router-link
:to="{ :to="{
name: 'baja', name: 'baja',
query: { ord: encodeURIComponent(child.ord) }, query: {
pagename: 'user',
ord: encodeURIComponent(child.ord),
},
}" }"
> >
{{ child.name }} {{ child.name }}
@ -158,6 +179,13 @@ const userList = computed(() => niagaraStore.userList?.children || []);
align-items: center; align-items: center;
} }
.nav-menu li.link-active .icon {
filter: brightness(1.2);
}
.nav-menu li.link-active span {
color: #43daff;
}
.header { .header {
background-color: #fff; background-color: #fff;
width: 100%; width: 100%;

View File

@ -1 +1,4 @@
@import "tailwindcss"; @import "tailwindcss";
:root {
font-family:"Microsoft JhengHei", "Noto Sans CJK TC", STHeiti, sans-serif, serif;
}

View File

@ -32,7 +32,7 @@ const elecStat = ref([
}, },
{ {
value: 0, value: 0,
label: "容積占比", label: "契約容量佔比",
unit: "%", unit: "%",
icon: "charging-station", icon: "charging-station",
}, },

View File

@ -1,13 +1,28 @@
<script setup> <script setup>
import { computed } from "vue"; import { computed, onMounted } from "vue";
import { useRouter } from "vue-router";
import useNiagaraDataStore from "@/stores/useNiagaraDataStore"; import useNiagaraDataStore from "@/stores/useNiagaraDataStore";
const niagaraStore = useNiagaraDataStore(); const niagaraStore = useNiagaraDataStore();
const router = useRouter();
const homeData = computed(() => { const homeData = computed(() => {
const data = niagaraStore.headerList.children?.[2] || {}; const data = niagaraStore.headerList.children?.[2] || {};
return { return {
...data, ...data,
}; };
}); });
onMounted(() => {
router.push({
name: "NotFound",
query: {
pagename: "notfound",
ord: null,
},
});
});
</script> </script>
<template> <template>
<a-result status="404" title="404" sub-title="抱歉您造訪的頁面不存在"> <a-result status="404" title="404" sub-title="抱歉您造訪的頁面不存在">
@ -18,7 +33,10 @@ const homeData = computed(() => {
homeData.ord !== 'null' homeData.ord !== 'null'
? { ? {
name: 'baja', name: 'baja',
query: { ord: encodeURIComponent(homeData.ord) }, query: {
pagename: 'notfound',
ord: encodeURIComponent(homeData.ord),
},
} }
: '/' : '/'
" "