用電即時分佈圖表 | 首頁進度小卡 | 系統小卡樣式修改 | 歷史資料新增大類 | 設備管理修改文字
This commit is contained in:
parent
c5345db462
commit
a7054c07b5
@ -1,2 +1,3 @@
|
|||||||
|
export const GET_REALTIME_DIST_API = `/api/Energe/GetRealTimeDistribution`;
|
||||||
export const GET_ELECUSE_DAY_API = `/api/Energe/GetElecUseDay`;
|
export const GET_ELECUSE_DAY_API = `/api/Energe/GetElecUseDay`;
|
||||||
export const GET_TAI_POWER_API = `/api/Energe/GetTaipower`;
|
export const GET_TAI_POWER_API = `/api/Energe/GetTaipower`;
|
@ -1,10 +1,20 @@
|
|||||||
import {
|
import {
|
||||||
|
GET_REALTIME_DIST_API,
|
||||||
GET_ELECUSE_DAY_API,
|
GET_ELECUSE_DAY_API,
|
||||||
GET_TAI_POWER_API,
|
GET_TAI_POWER_API,
|
||||||
} from "./api";
|
} from "./api";
|
||||||
import instance from "@/util/request";
|
import instance from "@/util/request";
|
||||||
import apihandler from "@/util/apihandler";
|
import apihandler from "@/util/apihandler";
|
||||||
|
|
||||||
|
export const getRealTimeDist = async () => {
|
||||||
|
const res = await instance.post(GET_REALTIME_DIST_API);
|
||||||
|
|
||||||
|
return apihandler(res.code, res.data, {
|
||||||
|
msg: res.msg,
|
||||||
|
code: res.code,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const getElecUseDay = async () => {
|
export const getElecUseDay = async () => {
|
||||||
const res = await instance.post(GET_ELECUSE_DAY_API);
|
const res = await instance.post(GET_ELECUSE_DAY_API);
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
"title": "历史资料",
|
"title": "历史资料",
|
||||||
"building_name": "厂区",
|
"building_name": "厂区",
|
||||||
"device_name": "设备名称",
|
"device_name": "设备名称",
|
||||||
|
"system_category": "系统类别",
|
||||||
"device_category": "设备类别",
|
"device_category": "设备类别",
|
||||||
"category": "类别",
|
"category": "类别",
|
||||||
"value": "数值",
|
"value": "数值",
|
||||||
@ -243,7 +244,7 @@
|
|||||||
"phone": "手机",
|
"phone": "手机",
|
||||||
"created_at": "建立时间",
|
"created_at": "建立时间",
|
||||||
"operation": "功能",
|
"operation": "功能",
|
||||||
"name_placeholder": "请输入使用者名称",
|
"name_placeholder": "请输入使用者、帐号名称",
|
||||||
"role_placeholder": "请输入角色名称",
|
"role_placeholder": "请输入角色名称",
|
||||||
"change_password": "变更密码",
|
"change_password": "变更密码",
|
||||||
"choose": "选择"
|
"choose": "选择"
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
"title": "歷史資料",
|
"title": "歷史資料",
|
||||||
"building_name": "廠區",
|
"building_name": "廠區",
|
||||||
"device_name": "設備名稱",
|
"device_name": "設備名稱",
|
||||||
|
"system_category": "系統類別",
|
||||||
"device_category": "設備類別",
|
"device_category": "設備類別",
|
||||||
"category": "類別",
|
"category": "類別",
|
||||||
"value": "數值",
|
"value": "數值",
|
||||||
@ -243,7 +244,7 @@
|
|||||||
"phone": "手機",
|
"phone": "手機",
|
||||||
"created_at": "建立時間",
|
"created_at": "建立時間",
|
||||||
"operation": "功能",
|
"operation": "功能",
|
||||||
"name_placeholder": "請輸入使用者名稱",
|
"name_placeholder": "請輸入使用者、帳號名稱",
|
||||||
"role_placeholder": "請輸入角色名稱",
|
"role_placeholder": "請輸入角色名稱",
|
||||||
"change_password": "變更密碼",
|
"change_password": "變更密碼",
|
||||||
"choose": "選擇"
|
"choose": "選擇"
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
"title": "Historical Data",
|
"title": "Historical Data",
|
||||||
"building_name": "Building",
|
"building_name": "Building",
|
||||||
"device_name": "Device Name",
|
"device_name": "Device Name",
|
||||||
|
"system_category": "System Category",
|
||||||
"device_category": "Device Category",
|
"device_category": "Device Category",
|
||||||
"category": "Category",
|
"category": "Category",
|
||||||
"value": "Value",
|
"value": "Value",
|
||||||
@ -155,7 +156,7 @@
|
|||||||
"phone": "Phone",
|
"phone": "Phone",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"created_at": "Creation Date",
|
"created_at": "Creation Date",
|
||||||
"maintenance": "Maintenance",
|
"maintenance": "Upkeep",
|
||||||
"repair": "Repair",
|
"repair": "Repair",
|
||||||
"company_info": "Company Info",
|
"company_info": "Company Info",
|
||||||
"repair_item": "Repair Item",
|
"repair_item": "Repair Item",
|
||||||
@ -243,8 +244,8 @@
|
|||||||
"phone": "Phone",
|
"phone": "Phone",
|
||||||
"created_at": "Created Time",
|
"created_at": "Created Time",
|
||||||
"operation": "Function",
|
"operation": "Function",
|
||||||
"name_placeholder": "Please enter user name",
|
"name_placeholder": "Please enter the user's name / account",
|
||||||
"role_placeholder": "Please enter the role name",
|
"role_placeholder": "Please enter the role's name",
|
||||||
"change_password": "Change Password",
|
"change_password": "Change Password",
|
||||||
"choose": "Choose"
|
"choose": "Choose"
|
||||||
},
|
},
|
||||||
@ -261,8 +262,8 @@
|
|||||||
"submit": "Submit",
|
"submit": "Submit",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"deselect_all": "Deselect all",
|
"deselect_all": "Deselect All",
|
||||||
"select_all": "Select all",
|
"select_all": "Select All",
|
||||||
"phone_format": "Please enter the correct phone number format",
|
"phone_format": "Please enter the correct phone number format",
|
||||||
"email_format": "Please enter correct email address",
|
"email_format": "Please enter correct email address",
|
||||||
"password_format": "The password must be at least 8 characters long and must contain English and numbers.",
|
"password_format": "The password must be at least 8 characters long and must contain English and numbers.",
|
||||||
|
@ -147,7 +147,7 @@ const removeAccount = async (id) => {
|
|||||||
:placeholder="t('accountManagement.name_placeholder')"
|
:placeholder="t('accountManagement.name_placeholder')"
|
||||||
name="Full_name"
|
name="Full_name"
|
||||||
:value="searchData"
|
:value="searchData"
|
||||||
class="mr-3"
|
class="mr-3 w-96"
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
:placeholder="t('accountManagement.role_placeholder')"
|
:placeholder="t('accountManagement.role_placeholder')"
|
||||||
|
@ -1,93 +1,87 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from "vue";
|
import { ref, computed } from "vue";
|
||||||
|
|
||||||
// Mock data based on the image, grouped data
|
const equipmentData = ref({
|
||||||
const mockData = ref([
|
title: "System Status",
|
||||||
{
|
items: [
|
||||||
title: "Abnormal state",
|
{ label: "Auxiliary", online: 6, offline: 0, alarm: 0 },
|
||||||
items: [
|
{ label: "Air Detection", online: 31, offline: 0, alarm: 2 },
|
||||||
[
|
{ label: "Electricity", online: 12, offline: 0, alarm: 1 },
|
||||||
{ label: "Abnormal", value: 0 },
|
{ label: "Lighting", online: 20, offline: 3, alarm: 0 },
|
||||||
{ label: "Return", value: 5168 },
|
{ label: "Air Condition", online: 23, offline: 0, alarm: 0 },
|
||||||
],
|
],
|
||||||
[
|
});
|
||||||
{ label: "Confirmed", value: 182 },
|
|
||||||
{ label: "Unacknowledged", value: 4986 },
|
|
||||||
],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Progress",
|
|
||||||
items: [
|
|
||||||
[
|
|
||||||
{ label: "Not dispatched", value: 5126 },
|
|
||||||
{ label: "Dispatched", value: 42 },
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{ label: "Completed", value: 28 },
|
|
||||||
{ label: "Unfinished", value: 14 },
|
|
||||||
],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Compute progress value for each group
|
const orderData = ref({
|
||||||
const getProgressValue = (group) => {
|
title: "Work Order",
|
||||||
const total = group.reduce((sum, item) => sum + item.value, 0);
|
items: [
|
||||||
return (group[0].value / total) * 100;
|
{ label: "Unassigned", value: 2 },
|
||||||
};
|
{ label: "Assigned", value: 4 },
|
||||||
|
{ label: "Completed", value: 1 },
|
||||||
|
],
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-wrap">
|
<div class="flex flex-wrap">
|
||||||
<div
|
<div class="w-full sm:w-3/5 state-box-col relative ps-2">
|
||||||
v-for="(section, index) in mockData"
|
|
||||||
:key="index"
|
|
||||||
class="w-full sm:w-1/2 state-box-col relative px-4"
|
|
||||||
>
|
|
||||||
<div class="state-box">
|
<div class="state-box">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<img class="state-title01" src="@ASSET/img/state-title01.svg" />
|
<img class="state-title01" src="@ASSET/img/state-title01.svg" />
|
||||||
<span>{{ section.title }}</span>
|
<span class="">{{ equipmentData.title }}</span>
|
||||||
<img class="state-title02" src="@ASSET/img/state-title02.svg" />
|
<img class="state-title02" src="@ASSET/img/state-title02.svg" />
|
||||||
</div>
|
</div>
|
||||||
|
<table class="table table-sm text-center">
|
||||||
<div
|
<thead>
|
||||||
v-for="(group, groupIndex) in section.items"
|
<tr class="border-cyan-400 text-cyan-100">
|
||||||
:key="groupIndex"
|
<th></th>
|
||||||
class="item"
|
<th>Online</th>
|
||||||
>
|
<th>Offline</th>
|
||||||
<div class="item-title">
|
<th>Alarm</th>
|
||||||
<div
|
</tr>
|
||||||
v-for="(item, itemIndex) in group"
|
</thead>
|
||||||
:key="itemIndex"
|
<tbody>
|
||||||
class="text"
|
<tr
|
||||||
|
v-for="(item, index) in equipmentData.items"
|
||||||
|
:key="index"
|
||||||
|
class="border-cyan-400"
|
||||||
>
|
>
|
||||||
<div class="text-position">
|
<th class="px-0 text-start">{{ item.label }}</th>
|
||||||
<span>{{ item.label }}</span>
|
<td>{{ item.online }}</td>
|
||||||
<span>{{ item.value }}</span>
|
<td>{{ item.offline }}</td>
|
||||||
</div>
|
<td>{{ item.alarm }}</td>
|
||||||
</div>
|
</tr>
|
||||||
</div>
|
</tbody>
|
||||||
<div class="state-ul">
|
</table>
|
||||||
<img src="@ASSET/img/state-ul.svg" />
|
</div>
|
||||||
<div class="box">
|
</div>
|
||||||
<div class="mark">
|
<div class="w-full sm:w-2/5 state-box-col relative ps-2">
|
||||||
<span class="w-10">{{ group[0].value }}</span>
|
<div class="state-box">
|
||||||
<span
|
<div class="title">
|
||||||
><img class="w-[50px]" src="@ASSET/img/state-ul-text.svg" />
|
<img class="state-title01" src="@ASSET/img/state-title01.svg" />
|
||||||
</span>
|
<span>{{ orderData.title }}</span>
|
||||||
<span class="w-10">{{ group[1].value }}</span>
|
<img class="state-title02" src="@ASSET/img/state-title02.svg" />
|
||||||
</div>
|
|
||||||
<progress
|
|
||||||
class="progress [&::-webkit-progress-value]:bg-red-600 [&::-moz-progress-bar]:bg-red-600"
|
|
||||||
:value="getProgressValue(group)"
|
|
||||||
max="100"
|
|
||||||
size=""
|
|
||||||
></progress>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<table class="table table-sm text-center">
|
||||||
|
<thead>
|
||||||
|
<tr class="border-cyan-400 text-cyan-100">
|
||||||
|
<th></th>
|
||||||
|
<th>value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="(item, index) in orderData.items"
|
||||||
|
:key="index"
|
||||||
|
class="border-cyan-400"
|
||||||
|
>
|
||||||
|
<th class="px-0 text-start">
|
||||||
|
<span>{{ item.label }}</span>
|
||||||
|
</th>
|
||||||
|
<td>{{ item.value }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -107,7 +101,7 @@ const getProgressValue = (group) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.state-box {
|
.state-box {
|
||||||
@apply border-2 border-light-info rounded-sm py-2 px-6 text-white relative;
|
@apply h-80 border-2 border-light-info rounded-sm py-2 px-6 text-white relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.state-box:after {
|
.state-box:after {
|
||||||
@ -133,58 +127,4 @@ const getProgressValue = (group) => {
|
|||||||
.state-box .title .state-title02 {
|
.state-box .title .state-title02 {
|
||||||
@apply w-5 ml-1.5;
|
@apply w-5 ml-1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.state-box .item-title {
|
|
||||||
@apply flex justify-between items-center m-auto mb-1 relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.state-box .item-title:after {
|
|
||||||
@apply absolute right-0 -bottom-2.5 w-full h-4 bg-no-repeat bg-center z-10;
|
|
||||||
content: "";
|
|
||||||
background-image: url(@ASSET/img/text-position-line.svg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.state-box .item-title .text {
|
|
||||||
@apply w-1/2 m-0 mb-1.5 flex justify-center items-center relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.state-box .item-title .text .text-position span {
|
|
||||||
@apply block text-center text-xs;
|
|
||||||
}
|
|
||||||
|
|
||||||
.state-box .item-title .text .text-position span:nth-child(2) {
|
|
||||||
text-shadow: 0px 0px 5px rgba(255, 255, 255, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mark {
|
|
||||||
@apply flex justify-between items-center mb-2.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.state-ul {
|
|
||||||
@apply relative mb-2.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.state-ul::after {
|
|
||||||
@apply absolute -left-3.5 top-0 w-4 h-16 bg-no-repeat bg-center z-10;
|
|
||||||
content: "";
|
|
||||||
background-image: url(@ASSET/img/state-ul-background01.svg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.state-ul .box {
|
|
||||||
@apply absolute top-1/2 w-4/5 left-0 right-0 m-auto text-center -translate-y-1/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress {
|
|
||||||
@apply w-full h-3 rounded;
|
|
||||||
appearance: none;
|
|
||||||
|
|
||||||
&::-webkit-progress-bar {
|
|
||||||
border: 1px solid #ffffff;
|
|
||||||
background-color: #5eabea;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-progress-value {
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,35 +1,29 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, nextTick } from "vue";
|
import { ref, onMounted, nextTick, computed } from "vue";
|
||||||
import * as echarts from "echarts";
|
import * as echarts from "echarts";
|
||||||
|
import { getRealTimeDist } from "@/apis/energy";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const chartDiv = ref(null);
|
const chartDiv = ref(null);
|
||||||
|
|
||||||
const chartOption = {
|
const chartOption = {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: "item",
|
trigger: "item",
|
||||||
formatter: "{b}: {c}kWh",
|
formatter: (p) => {
|
||||||
|
return `${p.name}: ${p.value}kWh (${p.data.percentage}%)`;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
type: "sankey",
|
type: "sankey",
|
||||||
layout: "none",
|
layout: "none",
|
||||||
nodeWidth: 20,
|
nodeWidth: 10,
|
||||||
nodeGap: 10,
|
nodeGap: 10,
|
||||||
data: [
|
right: 180,
|
||||||
{ name: "Total", value: 100 },
|
data: [],
|
||||||
{ name: "HVAC System", value: 40 },
|
links: [],
|
||||||
{ name: "Lighting System", value: 25 },
|
|
||||||
{ name: "Elevator System", value: 15 },
|
|
||||||
{ name: "Outlets", value: 10 },
|
|
||||||
{ name: "Others", value: 10 },
|
|
||||||
],
|
|
||||||
links: [
|
|
||||||
{ source: "Total", target: "HVAC System", value: 40 },
|
|
||||||
{ source: "Total", target: "Lighting System", value: 25 },
|
|
||||||
{ source: "Total", target: "Elevator System", value: 15 },
|
|
||||||
{ source: "Total", target: "Outlets", value: 10 },
|
|
||||||
{ source: "Total", target: "Others", value: 10 },
|
|
||||||
],
|
|
||||||
emphasis: {
|
emphasis: {
|
||||||
focus: "adjacency",
|
focus: "adjacency",
|
||||||
},
|
},
|
||||||
@ -37,6 +31,9 @@ const chartOption = {
|
|||||||
position: "right",
|
position: "right",
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: "#fff",
|
color: "#fff",
|
||||||
|
formatter: (p) => {
|
||||||
|
return `${p.name} (${p.data.percentage}%)`;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
borderWidth: 0,
|
borderWidth: 0,
|
||||||
@ -50,11 +47,42 @@ const chartOption = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
const loadData = async () => {
|
||||||
nextTick(() => {
|
const res = await getRealTimeDist();
|
||||||
|
if (res.isSuccess) {
|
||||||
|
const rawData = res.data;
|
||||||
|
const totalValue = rawData.reduce((acc, item) => acc + item.value, 0);
|
||||||
|
|
||||||
|
// 構造 data 節點
|
||||||
|
const data = [
|
||||||
|
{ name: "Total", value: totalValue, percentage: 100 },
|
||||||
|
...rawData.map((item) => ({
|
||||||
|
name: item.key,
|
||||||
|
value: item.value,
|
||||||
|
percentage: item.percentage,
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
|
||||||
|
// 構造 links 連結
|
||||||
|
const links = rawData.map((item) => ({
|
||||||
|
source: "Total",
|
||||||
|
target: item.key,
|
||||||
|
value: item.value,
|
||||||
|
percentage: item.percentage,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 更新 chartOption
|
||||||
|
chartOption.series[0].data = data;
|
||||||
|
chartOption.series[0].links = links;
|
||||||
|
|
||||||
|
// 初始化圖表
|
||||||
const myChart = echarts.init(chartDiv.value);
|
const myChart = echarts.init(chartDiv.value);
|
||||||
myChart.setOption(chartOption);
|
myChart.setOption(chartOption);
|
||||||
});
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadData();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -64,19 +92,7 @@ onMounted(() => {
|
|||||||
{{ $t("energy.elec_consumption") }}
|
{{ $t("energy.elec_consumption") }}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="chart-container">
|
<div class="chart-container">
|
||||||
<div ref="chartDiv" class="w-full min-h-[190px] h-full"></div>
|
<div ref="chartDiv" class="w-full min-h-[200px] h-full"></div>
|
||||||
</div>
|
|
||||||
<div class="text-sm mt-3.5">
|
|
||||||
<ul class="flex flex-wrap items-center text-white">
|
|
||||||
<li class="pr-5 relative z-20">
|
|
||||||
<span class="pr-3.5"> {{ $t("energy.total_elec") }} (kWh)</span>
|
|
||||||
<span class="pr-3.5">160.05</span>
|
|
||||||
</li>
|
|
||||||
<li class="pr-5 relative z-20">
|
|
||||||
<span class="pr-3.5">{{ $t("energy.green_elec") }} (kWh)</span>
|
|
||||||
<span class="pr-3.5">39.50</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -25,8 +25,15 @@ import dayjs from "dayjs";
|
|||||||
|
|
||||||
const { searchParams, changeParams } = useSearchParam();
|
const { searchParams, changeParams } = useSearchParam();
|
||||||
|
|
||||||
// 選小類
|
|
||||||
const store = useBuildingStore();
|
const store = useBuildingStore();
|
||||||
|
// 選大類
|
||||||
|
const {
|
||||||
|
items: sysMainTagItems,
|
||||||
|
changeActiveBtn: changeMainSysActiveBtn,
|
||||||
|
setItems: setMainSysItems,
|
||||||
|
selectedBtn: selectedMainSysItems,
|
||||||
|
} = useActiveBtn();
|
||||||
|
// 選小類
|
||||||
const {
|
const {
|
||||||
items: sysTagItems,
|
items: sysTagItems,
|
||||||
changeActiveBtn: changeSysActiveBtn,
|
changeActiveBtn: changeSysActiveBtn,
|
||||||
@ -34,6 +41,38 @@ const {
|
|||||||
selectedBtn: selectedSysItems,
|
selectedBtn: selectedSysItems,
|
||||||
} = useActiveBtn();
|
} = useActiveBtn();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => store.mainSys,
|
||||||
|
() => {
|
||||||
|
setMainSysItems(
|
||||||
|
store.mainSubSys.map(({ full_name, main_system_tag }, index) => ({
|
||||||
|
title: full_name,
|
||||||
|
key: main_system_tag,
|
||||||
|
active: searchParams.value.main_system_tag
|
||||||
|
? searchParams.value.main_system_tag === mian_system_tag
|
||||||
|
: index === 0,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => selectedMainSysItems,
|
||||||
|
(newVal, oldVal) => {
|
||||||
|
setSysItems(
|
||||||
|
store.subSys.filter((s) => s.main_system_tag === newVal.value?.key).map(({ full_name, sub_system_tag }, index) => ({
|
||||||
|
title: full_name,
|
||||||
|
key: sub_system_tag,
|
||||||
|
active: index === 0,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true,
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => selectedSysItems,
|
() => selectedSysItems,
|
||||||
(newVal, oldVal) => {
|
(newVal, oldVal) => {
|
||||||
@ -54,21 +93,6 @@ watch(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
|
||||||
() => store.subSys,
|
|
||||||
() => {
|
|
||||||
setSysItems(
|
|
||||||
store.subSys.map(({ full_name, sub_system_tag }, index) => ({
|
|
||||||
title: full_name,
|
|
||||||
key: sub_system_tag,
|
|
||||||
active: searchParams.value.sub_system_tag
|
|
||||||
? searchParams.value.sub_system_tag === sub_system_tag
|
|
||||||
: index === 0,
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 設定點位
|
// 設定點位
|
||||||
const {
|
const {
|
||||||
items: points,
|
items: points,
|
||||||
@ -82,7 +106,7 @@ const getPoint = async (deviceList) => {
|
|||||||
setPoints(
|
setPoints(
|
||||||
res.data.map((d, index) => ({
|
res.data.map((d, index) => ({
|
||||||
...d,
|
...d,
|
||||||
title: d.points,
|
title: d.item_name,
|
||||||
key: d.points,
|
key: d.points,
|
||||||
active: index === 0,
|
active: index === 0,
|
||||||
}))
|
}))
|
||||||
@ -118,10 +142,10 @@ watch(searchParams, (newVal, oldValue) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setSysItems(
|
setMainSysItems(
|
||||||
store.subSys.map(({ full_name, sub_system_tag }, index) => ({
|
store.mainSubSys.map(({ full_name, main_system_tag }, index) => ({
|
||||||
title: full_name,
|
title: full_name,
|
||||||
key: sub_system_tag,
|
key: main_system_tag,
|
||||||
active: index === 0,
|
active: index === 0,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
@ -136,7 +160,23 @@ onBeforeMount(() => {
|
|||||||
<div class="flex flex-col custom-border p-4 mb-4">
|
<div class="flex flex-col custom-border p-4 mb-4">
|
||||||
<!-- <HistoryFavoriteOption class="mb-4" />-->
|
<!-- <HistoryFavoriteOption class="mb-4" />-->
|
||||||
<div class="flex items-center gap-4 mb-4">
|
<div class="flex items-center gap-4 mb-4">
|
||||||
<h2 class="text-lg font-bold ps-2">{{ $t("history.device_category") }} :</h2>
|
<h2 class="text-lg font-bold ps-2">
|
||||||
|
{{ $t("history.system_category") }} :
|
||||||
|
</h2>
|
||||||
|
<ButtonGroup
|
||||||
|
:items="sysMainTagItems"
|
||||||
|
:withLine="true"
|
||||||
|
:onclick="
|
||||||
|
(e, item) => {
|
||||||
|
changeMainSysActiveBtn(item);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-4 mb-4">
|
||||||
|
<h2 class="text-lg font-bold ps-2">
|
||||||
|
{{ $t("history.device_category") }} :
|
||||||
|
</h2>
|
||||||
<ButtonGroup
|
<ButtonGroup
|
||||||
:items="sysTagItems"
|
:items="sysTagItems"
|
||||||
:withLine="true"
|
:withLine="true"
|
||||||
|
@ -65,9 +65,12 @@ watch(searchParams, (newValue, oldValue) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-wrap mt-3">
|
<div class="flex flex-wrap items-center mt-6">
|
||||||
|
<h2 class="text-lg font-bold ps-1 pe-4">
|
||||||
|
{{ $t("history.device_category") }} :
|
||||||
|
</h2>
|
||||||
<button
|
<button
|
||||||
class="btn btn-success mr-4"
|
class="btn btn-sm btn-success"
|
||||||
@click.stop.prevent="changeCheckedItem"
|
@click.stop.prevent="changeCheckedItem"
|
||||||
>
|
>
|
||||||
{{ checkedItem.length === store.subSys.length ? t("button.deselect_all") : t("button.select_all") }}
|
{{ checkedItem.length === store.subSys.length ? t("button.deselect_all") : t("button.select_all") }}
|
||||||
|
@ -216,7 +216,7 @@ provide("system_selectedDevice", { selectedDeviceRealtime, selectedDevice, getCu
|
|||||||
<SystemInfoModal :data="selectedDevice" />
|
<SystemInfoModal :data="selectedDevice" />
|
||||||
<SystemFloorBar />
|
<SystemFloorBar />
|
||||||
<div class="grid grid-cols-2 gap-5 mt-8 mb-4">
|
<div class="grid grid-cols-2 gap-5 mt-8 mb-4">
|
||||||
<div class="col-span-1 h-[80vh] flex flex-col justify-start">
|
<div class="col-span-1 h-[79vh] flex flex-col justify-start">
|
||||||
<div>
|
<div>
|
||||||
<div class="flex mb-4 items-center">
|
<div class="flex mb-4 items-center">
|
||||||
<span class="flex items-center mr-3" v-if="statusList?.device_normal_text">
|
<span class="flex items-center mr-3" v-if="statusList?.device_normal_text">
|
||||||
@ -237,13 +237,13 @@ provide("system_selectedDevice", { selectedDeviceRealtime, selectedDevice, getCu
|
|||||||
</div>
|
</div>
|
||||||
<SystemSubBar class="mt-2 mb-4" />
|
<SystemSubBar class="mt-2 mb-4" />
|
||||||
</div>
|
</div>
|
||||||
<div class="h-full max-h-[75vh] pr-2 overflow-y-auto">
|
<div class="h-full pr-2 overflow-y-auto">
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-1 h-full flex flex-col justify-between">
|
<div class="col-span-1 h-full flex flex-col justify-between">
|
||||||
<SystemMode />
|
<SystemMode />
|
||||||
<div class="min-h-[75vh] relative">
|
<div class="h-full relative">
|
||||||
<SystemFloor
|
<SystemFloor
|
||||||
:class="twMerge('absolute h-full w-full', route.query.mode === '2D' ? 'opacity-100 z-10' : 'opacity-0 z-0')" />
|
:class="twMerge('absolute h-full w-full', route.query.mode === '2D' ? 'opacity-100 z-10' : 'opacity-0 z-0')" />
|
||||||
<div
|
<div
|
||||||
|
@ -22,14 +22,14 @@ const fitToView = (forge_dbid) => {
|
|||||||
<div class="equipment-show" v-for="d in showData" :key="d.full_name">
|
<div class="equipment-show" v-for="d in showData" :key="d.full_name">
|
||||||
<template v-if="d.device_list.length > 0">
|
<template v-if="d.device_list.length > 0">
|
||||||
<p class="title">{{ d.full_name }}</p>
|
<p class="title">{{ d.full_name }}</p>
|
||||||
<div class="grid grid-cols-3 gap-5">
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-5">
|
||||||
<div class="col-auto relative" v-for="device in d.device_list" :key="device.device_guid">
|
<div class="col-auto relative" v-for="device in d.device_list" :key="device.device_guid">
|
||||||
<div class="item h-full">
|
<div class="item h-full">
|
||||||
<div class="left h-full flex flex-wrap justify-center">
|
<div class="left h-full flex flex-wrap justify-center">
|
||||||
<div class="sec02 w-full">
|
<div class="sec02 w-full">
|
||||||
<img v-if="device.device_image_url" :src="device.device_image_url" alt="" class="w-8 h-8">
|
<img v-if="device.device_image_url" :src="device.device_image_url" alt="" >
|
||||||
<span class="w-8 h-8" v-else></span>
|
<span v-else></span>
|
||||||
<span class="w-32 break-all">{{ device.full_name }}</span>
|
<span>{{ device.full_name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between w-full self-end">
|
<div class="flex justify-between w-full self-end">
|
||||||
<div class="sec03">
|
<div class="sec03">
|
||||||
@ -60,7 +60,7 @@ const fitToView = (forge_dbid) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
@apply flex items-center border border-success py-4 px-5 relative mb-5 after:absolute after:right-0 after:top-3 after:w-6 after:h-10 after:bg-[url(/src/assets/img/equipment/state-background.svg)] after:z-10;
|
@apply flex items-center border border-success rounded shadow-emerald-600 shadow-inner py-4 px-5 relative mb-5 after:absolute after:right-0 after:top-3 after:w-6 after:h-10 after:bg-[url(/src/assets/img/equipment/state-background.svg)] after:z-10;
|
||||||
;
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ const fitToView = (forge_dbid) => {
|
|||||||
background: url(/src/assets/img/equipment/state-title.svg) center center;
|
background: url(/src/assets/img/equipment/state-title.svg) center center;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: -10px;
|
bottom: -18px;
|
||||||
height: 25px;
|
height: 25px;
|
||||||
width: 105px;
|
width: 105px;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
@ -118,10 +118,14 @@ const fitToView = (forge_dbid) => {
|
|||||||
display: block;
|
display: block;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
width: 2rem !important;
|
||||||
|
height: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.equipment-show .item .sec02 span:nth-child(2) {
|
.equipment-show .item .sec02 span:nth-child(2) {
|
||||||
font-size: 1.5rem;
|
font-size: 1.4rem;
|
||||||
|
width: calc(100% - 2rem);
|
||||||
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.equipment-show .item .sec03 {
|
.equipment-show .item .sec03 {
|
||||||
|
@ -16,7 +16,7 @@ const data = computed(() => {
|
|||||||
|
|
||||||
const columns = [{
|
const columns = [{
|
||||||
title: t("system.attribute"),
|
title: t("system.attribute"),
|
||||||
key: "points"
|
key: "full_name"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("system.value"),
|
title: t("system.value"),
|
||||||
|
Loading…
Reference in New Issue
Block a user