首頁UI調整

This commit is contained in:
koko 2025-05-21 18:00:17 +08:00
parent 0772269c33
commit 14187ad9bc
12 changed files with 211 additions and 125 deletions

7
package-lock.json generated
View File

@ -20,7 +20,6 @@
"date-fns": "^3.3.1",
"dayjs": "^1.11.10",
"echarts": "^5.4.3",
"flag-icons": "^7.2.3",
"jquery-ui": "^1.14.1",
"json-schema-generator": "^2.0.6",
"mqtt": "^5.10.3",
@ -2621,12 +2620,6 @@
"node": ">=8"
}
},
"node_modules/flag-icons": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/flag-icons/-/flag-icons-7.2.3.tgz",
"integrity": "sha512-X2gUdteNuqdNqob2KKTJTS+ZCvyWeLCtDz9Ty8uJP17Y4o82Y+U/Vd4JNrdwTAjagYsRznOn9DZ+E/Q52qbmqg==",
"license": "MIT"
},
"node_modules/follow-redirects": {
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",

View File

@ -21,7 +21,6 @@
"date-fns": "^3.3.1",
"dayjs": "^1.11.10",
"echarts": "^5.4.3",
"flag-icons": "^7.2.3",
"jquery-ui": "^1.14.1",
"json-schema-generator": "^2.0.6",
"mqtt": "^5.10.3",

View File

@ -8,7 +8,10 @@
"table": {
"no_data": "表中数据为空",
"in_otal": "笔资料",
"skip_to": "跳至"
"skip_to": "跳至",
"serial_number": "序列号",
"name": "名称",
"time": "时间"
},
"upload": {
"title": "选择一个文件或拖放到这里",
@ -20,8 +23,10 @@
"elec_consumption_comparison": "用电量比较",
"elec_consumption_comparison_trend": "用电量比较趋势",
"electricity_consumption": "用电量",
"today_electricity_consumption": "今日用电量",
"yesterday_electricity_consumption": "昨天用电量",
"today_electricity_consumption": "今日用电量 ( kWH )",
"yesterday_electricity_consumption": "昨天用电量 ( kWH )",
"instant_power": "即时功率 ( kW )",
"instant_contract_capacity_ratio": "契約容量佔比 ( % )",
"this_last_week": "本周/上周",
"thisweek_electricity_consumption": "本周用电量",
"lastweek_electricity_consumption": "上周用电量",
@ -44,7 +49,9 @@
"this_month": "本月",
"last_month": "上月",
"this_year": "今年",
"last_year": "去年"
"last_year": "去年",
"work_order": "工单",
"system_status": "系统状态"
},
"history": {
"title": "历史资料",
@ -174,7 +181,7 @@
"alarmClass": "告警条件",
"device_name": "设备名称",
"device_number": "设备编号",
"device_point_name":"点位名称",
"device_point_name": "点位名称",
"date": "发生日期",
"time": "发生时间",
"error_msg": "异常原因",
@ -231,7 +238,10 @@
"saturday": "星期六",
"schedule_name": "时段名称",
"schedule_content": "时段内容",
"reorganization": "MQTT 告警重整"
"reorganization": "MQTT 告警重整",
"online": "在线",
"offline": "离线",
"alarm": "告警"
},
"operation": {
"title": "运维管理",
@ -260,6 +270,8 @@
"responsible_vendor": "负责厂商",
"not_completed": "未完成",
"completed": "已完成",
"complete": "已完成",
"incomplete": "未完成",
"worker_id": "工作人员编号",
"notice": "注意事项",
"result_description": "结果描述",
@ -387,7 +399,7 @@
"sure_to_delete_permanent": "是否确认永久删除该项目?",
"delete_success": "删除成功",
"delete_failed": "删除失败",
"mqtt_refresh":"重新设定成功"
"mqtt_refresh": "重新设定成功"
},
"setting": {
"MQTT_parse": "MQTT 解析",

View File

@ -8,7 +8,10 @@
"table": {
"no_data": "表中數據為空",
"in_otal": "筆資料",
"skip_to": "跳至"
"skip_to": "跳至",
"serial_number": "序號",
"name": "姓名",
"time": "時間"
},
"upload": {
"title": "選擇一個文件或拖放到這裡",
@ -20,8 +23,10 @@
"elec_consumption_comparison": "用電量比較",
"elec_consumption_comparison_trend": "用電量比較趨勢",
"electricity_consumption": "用電量",
"today_electricity_consumption": "今日用電量",
"yesterday_electricity_consumption": "昨天用電量",
"today_electricity_consumption": "今日用電量 ( kWH )",
"yesterday_electricity_consumption": "昨天用電量 ( kWH )",
"instant_power": "即時功率 ( kW )",
"instant_contract_capacity_ratio": "契約容量佔比 ( % )",
"this_last_week": "本週/上週",
"thisweek_electricity_consumption": "本周用電量",
"lastweek_electricity_consumption": "上週用電量",
@ -44,7 +49,9 @@
"this_month": "本月",
"last_month": "上月",
"this_year": "今年",
"last_year": "去年"
"last_year": "去年",
"work_order": "工單",
"system_status": "系統狀態"
},
"history": {
"title": "歷史資料",
@ -174,7 +181,7 @@
"alarmClass": "告警條件",
"device_name": "設備名稱",
"device_number": "設備編號",
"device_point_name":"點位名稱",
"device_point_name": "點位名稱",
"date": "發生日期",
"time": "發生時間",
"error_msg": "異常原因",
@ -231,7 +238,10 @@
"saturday": "星期六",
"schedule_name": "時段名稱",
"schedule_content": "時段內容",
"reorganization": "MQTT 告警重整"
"reorganization": "MQTT 告警重整",
"online": "在線",
"offline": "離線",
"alarm": "告警"
},
"operation": {
"title": "運維管理",
@ -260,6 +270,8 @@
"responsible_vendor": "負責廠商",
"not_completed": "未完成",
"completed": "已完成",
"complete": "已完成",
"incomplete": "未完成",
"worker_id": "工作人員編號",
"notice": "注意事項",
"result_description": "結果描述",
@ -380,28 +392,28 @@
"restore": "復原",
"stop_edit": "停止修改",
"start_edit": "開始修改",
"convert":"轉換"
"convert": "轉換"
},
"msg": {
"sure_to_delete": "是否確認刪除該項目?",
"sure_to_delete_permanent": "是否確認永久刪除該項目?",
"delete_success": "刪除成功",
"delete_failed": "刪除失敗",
"mqtt_refresh":"重新設定成功"
"mqtt_refresh": "重新設定成功"
},
"setting": {
"MQTT_parse": "MQTT 解析",
"schema":"架構",
"point":"點位",
"description":"描述",
"IoT_point_name":"IoT 點位名稱",
"IoT_point_code":"IoT 點位代號",
"number_of_decimal_places":"小數位數",
"boolean_value":"布林值",
"hide_point":"點位顯示",
"schema_name":"架構名稱",
"IoT_point_structure" :"IoT點位結構",
"system_point_name":"系統點位名稱",
"schema": "架構",
"point": "點位",
"description": "描述",
"IoT_point_name": "IoT 點位名稱",
"IoT_point_code": "IoT 點位代號",
"number_of_decimal_places": "小數位數",
"boolean_value": "布林值",
"hide_point": "點位顯示",
"schema_name": "架構名稱",
"IoT_point_structure": "IoT點位結構",
"system_point_name": "系統點位名稱",
"json_format_text": "請貼上 JSON 格式數據",
"json_click_text": "請在左側輸入JSON並點選轉換按鈕"
}

View File

@ -8,7 +8,10 @@
"table": {
"no_data": "No data",
"in_otal": "items in total",
"skip_to": "Skip to"
"skip_to": "Skip to",
"serial_number": "Serial Number",
"name": "Name",
"time": "Time"
},
"upload": {
"title": "Select a file or drag and drop here",
@ -20,8 +23,10 @@
"elec_consumption_comparison": "Electricity Consumption Comparison",
"elec_consumption_comparison_trend": "Electricity Consumption Comparison Trend",
"electricity_consumption": "electricity consumption",
"today_electricity_consumption": "Todays electricity consumption",
"yesterday_electricity_consumption": "Yesterdays electricity consumption",
"today_electricity_consumption": "Today's electricity consumption in kWH",
"yesterday_electricity_consumption": "Yesterday's electricity consumption in kWH",
"instant_power": "Instant power kW",
"instant_contract_capacity_ratio": "Instant contract capacity ratio %",
"this_last_week": "This Week's / Last Week's",
"thisweek_electricity_consumption": "This weeks electricity consumption",
"lastweek_electricity_consumption": "Last weeks electricity consumption",
@ -44,7 +49,9 @@
"this_month": "This month",
"last_month": "Last month",
"this_year": "This year",
"last_year": "Last year"
"last_year": "Last year",
"work_order": "Work Order",
"system_status": "System Status"
},
"history": {
"title": "Historical Data",
@ -174,7 +181,7 @@
"alarmClass": "Alarm Conditions",
"device_name": "Device Name",
"device_number": "Device Number",
"device_point_name":"Point Name",
"device_point_name": "Point Name",
"date": "Occurrence Date",
"time": "Occurrence Time",
"error_msg": "Abnormal Cause",
@ -231,7 +238,10 @@
"saturday": "Saturday",
"schedule_name": "Time period name",
"schedule_content": "Time period content",
"reorganization": "MQTT Alarm Reorganization"
"reorganization": "MQTT Alarm Reorganization",
"online": "Online",
"offline": "Offline",
"alarm": "Alarm"
},
"operation": {
"title": "Operation And Maintenance Management",
@ -260,6 +270,8 @@
"responsible_vendor": "Responsible Vendor",
"not_completed": "Not Completed",
"completed": "Completed",
"complete": "Comp",
"incomplete": "Inc",
"worker_id": "Worker ID",
"notice": "Notice",
"result_description": "Result Description",
@ -387,7 +399,7 @@
"sure_to_delete_permanent": "Are you sure you want to permanently delete this item?",
"delete_success": "Delete successfully",
"delete_failed": "Delete failed",
"mqtt_refresh":"MQTT reset successful"
"mqtt_refresh": "MQTT reset successful"
},
"setting": {
"MQTT_parse": "MQTT Parse",

View File

@ -17,7 +17,6 @@ import "virtual:svg-icons-register";
// 引入项目中的全部全局组件
import SvgIcon from "@/components/svgIcon.vue";
import library from "./fontawsomeIconRegister";
import "flag-icons/css/flag-icons.min.css";
/* import font awesome icon component */
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";

View File

@ -10,12 +10,19 @@ const props = defineProps({
},
});
const currentEnergyType = ref("month");
const toggleEnergyType = () => {
currentEnergyType.value =
currentEnergyType.value === "month" ? "day" : "month";
};
const energyTypeList = ref([
{
title: t("dashboard.today_energy_consumption"),
key: "today",
},
{
title: t("dashboard.this_month_energy_consumption"),
key: "month",
},
]);
const currentEnergyType = ref({
name: "month",
});
//
const getCurrentEnergyData = () => {
@ -23,7 +30,7 @@ const getCurrentEnergyData = () => {
return []; //
}
return currentEnergyType.value === "month"
return currentEnergyType.value.name === "month"
? props.energyCostData?.rank.month || []
: props.energyCostData?.rank.day || [];
};
@ -31,44 +38,50 @@ const getCurrentEnergyData = () => {
<template>
<div class="state-box-col relative ps-2 h-full max-h-[350px]">
<div class="state-box h-full max-h-[350px] overflow-y-auto">
<div class="state-box h-full">
<!-- 標題和切換按鈕 -->
<div class="flex justify-between items-center mb-4">
<div class="flex justify-between items-center mb-2">
<h2 class="font-light relative">
{{ $t("dashboard.energy_ranking") }}
</h2>
<button @click="toggleEnergyType" class="btn btn-info btn-xs">
{{
currentEnergyType === "month"
? t("dashboard.today_energy_consumption")
: t("dashboard.this_month_energy_consumption")
}}
</button>
<Select
:value="currentEnergyType"
class="!w-24"
selectClass="border-info focus-within:border-info btn-xs text-xs"
name="name"
Attribute="title"
:options="energyTypeList"
:isTopLabelExist="false"
:isBottomLabelExist="false"
>
</Select>
</div>
<!-- 能耗排名列表 -->
<table class="table table-sm text-center">
<tbody>
<tr
v-for="(item, index) in getCurrentEnergyData()"
:key="index"
:class="[
{ 'text-red-300': index + 1 === 1 },
{ 'text-orange-300': index + 1 === 2 },
{ 'text-yellow-300': index + 1 === 3 },
{ 'text-teal-300': index + 1 > 3 },
]"
>
<td class="flex items-center">
<font-awesome-icon :icon="['fas', 'crown']" class="me-1" />{{
index + 1
}}
</td>
<td>{{ item.name }}</td>
<td>{{ item.value }}</td>
</tr>
</tbody>
</table>
<div class="max-h-[300px] overflow-y-auto">
<table class="table table-sm text-center">
<tbody>
<tr
v-for="(item, index) in getCurrentEnergyData()"
:key="index"
:class="[
{ 'text-red-300': index + 1 === 1 },
{ 'text-orange-300': index + 1 === 2 },
{ 'text-yellow-300': index + 1 === 3 },
{ 'text-teal-300': index + 1 > 3 },
]"
>
<td class="flex items-center">
<font-awesome-icon :icon="['fas', 'crown']" class="me-1" />{{
index + 1
}}
</td>
<td>{{ item.name }}</td>
<td>{{ item.value }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>

View File

@ -3,7 +3,9 @@ import { ref, watch, onMounted, onUnmounted } from "vue";
import { getEnergyInfo } from "@/apis/dashboard";
import useBuildingStore from "@/stores/useBuildingStore";
import { twMerge } from "tailwind-merge";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const store = useBuildingStore();
const energyData = ref([]);
let intervalId = null;
@ -16,21 +18,21 @@ const getEnergyInfos = async () => {
energyData.value = [
{
value: apiData.todayKWH ? apiData.todayKWH : "N/A",
label: "Today's electricity consumption in kWH",
label: t("dashboard.today_electricity_consumption"),
},
{
value: apiData.yesterdayKWH ? apiData.yesterdayKWH : "N/A",
label: "Yesterday's electricity consumption in kWH",
label: t("dashboard.yesterday_electricity_consumption"),
},
{
value: apiData.instantKW ? apiData.instantKW : "N/A",
label: "Instant power kW",
label: t("dashboard.instant_power"),
},
{
value: apiData.instantContractRatio
? apiData.instantContractRatio
: "N/A",
label: "Instant contract capacity ratio %",
label: t("dashboard.instant_contract_capacity_ratio"),
},
];
} catch (error) {

View File

@ -4,14 +4,17 @@ import { useRouter } from "vue-router";
import { getAlarmOperationInfo } from "@/apis/dashboard";
import useBuildingStore from "@/stores/useBuildingStore";
import DashboardSysProgressModal from "./DashboardSysProgressModal.vue";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const router = useRouter();
const store = useBuildingStore();
const equipmentData = ref({
title: "System Status",
title: t("dashboard.system_status"),
items: [],
});
const orderData = ref({
title: "Work Order",
title: t("dashboard.work_order"),
items: [],
});
const modalData = ref({});
@ -38,12 +41,12 @@ const getAlarmsInfos = async () => {
if (apiData && apiData.operation) {
orderData.value.items = [
{
label: "Repair",
label: t("operation.repair"),
complete: apiData.operation.repair.complete || 0,
incomplete: apiData.operation.repair.incomplete || 0,
},
{
label: "Upkeep",
label: t("operation.maintenance"),
complete: apiData.operation.upkeep.complete || 0,
incomplete: apiData.operation.upkeep.incomplete || 0,
},
@ -109,8 +112,8 @@ onUnmounted(() => {
<thead>
<tr class="border-cyan-400 text-cyan-100">
<th></th>
<th>Comp</th>
<th>Inc</th>
<th>{{ $t("operation.complete") }}</th>
<th>{{ $t("operation.incomplete") }}</th>
</tr>
</thead>
<tbody>
@ -141,9 +144,9 @@ onUnmounted(() => {
<thead>
<tr class="border-cyan-400 text-cyan-100">
<th></th>
<th>Online</th>
<th>Offline</th>
<th>Alarm</th>
<th>{{ $t("alert.online") }}</th>
<th>{{ $t("alert.offline") }}</th>
<th>{{ $t("alert.alarm") }}</th>
</tr>
</thead>
<tbody>
@ -151,33 +154,16 @@ onUnmounted(() => {
v-for="(item, index) in equipmentData.items"
:key="index"
class="border-cyan-400 cursor-pointer hover:text-info"
@click.stop.prevent="openModal(item)"
>
<th class="px-0 text-start">{{ item.label }}</th>
<td
@click.stop.prevent="
item.online && item.online.length > 0
? openModal(item.online)
: null
"
>
<td>
{{ item.online.length }}
</td>
<td
@click.stop.prevent="
item.offline && item.offline.length > 0
? openModal(item.offline)
: null
"
>
<td>
{{ item.offline.length }}
</td>
<td
@click.stop.prevent="
item.alarm && item.alarm.length > 0
? openModal(item.alarm)
: null
"
>
<td>
{{ item.alarm.length }}
</td>
</tr>

View File

@ -1,18 +1,56 @@
<script setup>
import { ref, onMounted, defineProps, inject, watch } from "vue";
import useActiveBtn from "@/hooks/useActiveBtn";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const props = defineProps({
onCancel: Function,
modalData: Object,
});
const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
const detailData = ref([]);
onMounted(() => {
setItems([
{
title: t("alert.online"),
key: "online",
active: true,
},
{
title: t("alert.offline"),
key: "offline",
active: false,
},
{
title: t("alert.alarm"),
key: "alarm",
active: false,
},
]);
});
watch(selectedBtn, (newVal, oldVal) => {
if (newVal) {
detailData.value = props.modalData[newVal.key];
}
});
</script>
<template>
<Modal id="system_status_modal" :onCancel="onCancel" :width="600">
<template #modalTitle>
<div class="flex items-center justify-between">
<h2></h2>
<ButtonGroup
:items="items"
:withLine="true"
className="btn-sm"
:onclick="
(e, item) => {
changeActiveBtn(item);
}
"
/>
<Button
type="link"
class="btn-link btn-text-without-border px-2"
@ -30,28 +68,29 @@ const props = defineProps({
<th
class="text-base border text-white text-center bg-cyan-600 bg-opacity-30"
>
Serial Number
{{ $t("table.serial_number") }}
</th>
<th
class="text-base border text-white text-center bg-cyan-600 bg-opacity-30"
>
Name
{{ $t("table.name") }}
</th>
<th
class="text-base border text-white text-center bg-cyan-600 bg-opacity-30"
>
Time
{{ $t("table.time") }}
</th>
</tr>
</thead>
<tbody>
<tr
v-for="(equipment, index) in modalData"
v-if="detailData?.length > 0"
v-for="(equipment, index) in detailData"
:key="index"
class="hover:bg-gray-700"
>
<td class="border text-white text-center">
{{ index+1 }}
{{ index + 1 }}
</td>
<td class="border text-white text-center">
{{ equipment.name }}
@ -60,6 +99,11 @@ const props = defineProps({
{{ equipment.time || "-" }}
</td>
</tr>
<tr v-else>
<td colspan="3" class="border text-white text-center">
{{ $t("table.no_data") }}
</td>
</tr>
</tbody>
</table>
</div>

View File

@ -64,12 +64,12 @@ const defaultChartOption = ref({
},
{
name: "",
type: "bar",
stack: "total",
type: "line",
data: [],
itemStyle: {
color: "#62E39A",
},
lineStyle: { width: 3 },
},
],
});

View File

@ -35,6 +35,10 @@ const groupedData = computed(() => {
return grouped;
});
const togglePowerSwitch = () => {
console.log("Power Switch");
};
</script>
<template>
@ -64,14 +68,24 @@ const groupedData = computed(() => {
{{ group.full_name }}
</td>
<td class="border text-white text-lg text-center">
{{ group.value }}
<template v-if="group.full_name === 'Power Switch'">
<input
type="checkbox"
class="toggle toggle-success"
:checked="group.value"
@change="togglePowerSwitch()"
/>
</template>
<template v-else>
{{ group.value }}
</template>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p class="text-2xl text-center my-6" v-else>{{$t("table.no_data")}}</p>
<p class="text-2xl text-center my-6" v-else>{{ $t("table.no_data") }}</p>
</template>
<style lang="scss" scoped></style>