修改語言包、傳入參數格式、欄位必填等bug

This commit is contained in:
koko 2025-06-19 15:33:47 +08:00
parent 3e96223bd9
commit 68d834aec9
52 changed files with 195 additions and 136 deletions

View File

@ -64,10 +64,11 @@ watch(
twMerge( twMerge(
'flex-col text-xl', 'flex-col text-xl',
cls, cls,
openChildren.includes(dataParentKey) || open ? 'flex' : 'hidden' openChildren.includes(d.key) || open ? 'flex' : 'hidden'
) )
" "
v-for="d in data" v-for="d in data"
:key="d.key"
:data-parent="d.key" :data-parent="d.key"
:open="open" :open="open"
> >

View File

@ -9,7 +9,7 @@ const props = defineProps({
type: String, type: String,
default: "", default: "",
}, },
value: String, value: Object,
isTopLabelExist: { isTopLabelExist: {
type: Boolean, type: Boolean,
default: true, default: true,

View File

@ -9,7 +9,7 @@ const props = defineProps({
type: String, type: String,
default: "", default: "",
}, },
value: String, value: Object,
isTopLabelExist: { isTopLabelExist: {
type: Boolean, type: Boolean,
default: true, default: true,

View File

@ -51,7 +51,7 @@ onMounted(() => {
: 'focus-visible:outline-none backdrop:bg-transparent', : 'focus-visible:outline-none backdrop:bg-transparent',
)" :style="modalStyle" v-draggable="draggable"> )" :style="modalStyle" v-draggable="draggable">
<div :class="twMerge( <div :class="twMerge(
'modal-box static rounded-md border border-info py-5 px-6 overflow-y-scroll bg-normal', 'modal-box static rounded-md border border-info py-5 px-6 overflow-y-auto bg-normal',
modalClass modalClass
) )
" :style="{ minWidth: isNaN(width) ? width : `${width}px` }"> " :style="{ minWidth: isNaN(width) ? width : `${width}px` }">

View File

@ -4,7 +4,7 @@ import { twMerge } from "tailwind-merge";
const props = defineProps({ const props = defineProps({
name: String, name: String,
value: String, value: Object,
items: Array, items: Array,
isLabelExist: { isLabelExist: {
type: Boolean, type: Boolean,

View File

@ -18,7 +18,7 @@ const props = defineProps({
Attribute: String, Attribute: String,
onChange: Function, onChange: Function,
selectClass: String, selectClass: String,
value: String || Number, value: Object,
isTopLabelExist: { isTopLabelExist: {
type: Boolean, type: Boolean,
default: true, default: true,

View File

@ -18,7 +18,7 @@ const props = defineProps({
Attribute: String, Attribute: String,
onChange: Function, onChange: Function,
selectClass: String, selectClass: String,
value: String || Number, value: Object,
isTopLabelExist: { isTopLabelExist: {
type: Boolean, type: Boolean,
default: true, default: true,
@ -70,9 +70,7 @@ const props = defineProps({
:class="twMerge(disabled ? `text-white` : 'text-dark')" :class="twMerge(disabled ? `text-white` : 'text-dark')"
:value="option.value || option.key || option" :value="option.value || option.key || option"
> >
<span>
{{ option[Attribute] || option }} {{ option[Attribute] || option }}
</span>
</option> </option>
</select> </select>
<div :class="twMerge(isBottomLabelExist ? 'label' : '')"> <div :class="twMerge(isBottomLabelExist ? 'label' : '')">

View File

@ -3,7 +3,7 @@ import { defineProps } from "vue";
const props = defineProps({ const props = defineProps({
name: String, name: String,
value: String, value: Object,
placeholder: String, placeholder: String,
}); });
</script> </script>

View File

@ -1,5 +1,6 @@
<script setup> <script setup>
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import { useRouter } from "vue-router";
import NavbarItem from "./NavbarItem.vue"; import NavbarItem from "./NavbarItem.vue";
import NavbarBuilding from "./NavbarBuilding.vue"; import NavbarBuilding from "./NavbarBuilding.vue";
import Logo from "@/assets/img/logo.svg"; import Logo from "@/assets/img/logo.svg";
@ -10,6 +11,7 @@ import { twMerge } from "tailwind-merge";
const user = ref(""); const user = ref("");
const menuShow = ref(true); const menuShow = ref(true);
const router = useRouter();
const store = useUserInfoStore(); const store = useUserInfoStore();
onMounted(() => { onMounted(() => {
@ -24,12 +26,25 @@ const toggleMenu = () => {
}; };
const src = import.meta.env.MODE === "production" ? "./logo.svg" : Logo; const src = import.meta.env.MODE === "production" ? "./logo.svg" : Logo;
const logout = () => {
document.cookie = "JWT-Authorization=; Max-Age=0";
document.cookie = "user_name=; Max-Age=0";
store.user.token = "";
store.user.user_name = "";
router.push({ path: "/login" });
};
</script> </script>
<template> <template>
<header class="navbar bg-dark text-light-info w-full relative z-50"> <header class="navbar bg-dark text-light-info w-full relative z-50">
<div class="navbar-start min-w-[480px] lg:min-w-[440px]"> <div class="navbar-start min-w-[480px] lg:min-w-[440px]">
<div tabindex="0" role="button" class="btn btn-ghost lg:hidden" @click="toggleMenu"> <div
tabindex="0"
role="button"
class="btn btn-ghost lg:hidden"
@click="toggleMenu"
>
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5" class="h-5 w-5"
@ -93,12 +108,12 @@ const src = import.meta.env.MODE === "production" ? "./logo.svg" : Logo;
class="dropdown-content translate-y-2 z-[100] menu py-3 shadow rounded w-32 bg-[#4c625e] border text-center" class="dropdown-content translate-y-2 z-[100] menu py-3 shadow rounded w-32 bg-[#4c625e] border text-center"
> >
<li class="text-white"> <li class="text-white">
<router-link <a
to="logout" href="#"
type="link" @click.prevent="logout"
class="flex flex-col justify-center items-center" class="flex flex-col justify-center items-center"
>{{ $t("sign_out") }} >{{ $t("sign_out") }}
</router-link> </a>
</li> </li>
</ul> </ul>
</div> </div>

View File

@ -399,7 +399,8 @@
"sure_to_delete_permanent": "是否确认永久删除该项目?", "sure_to_delete_permanent": "是否确认永久删除该项目?",
"delete_success": "删除成功", "delete_success": "删除成功",
"delete_failed": "删除失败", "delete_failed": "删除失败",
"mqtt_refresh": "重新设定成功" "mqtt_refresh": "重新设定成功",
"schema_name_required": "架构名称栏位必填"
}, },
"setting": { "setting": {
"MQTT_parse": "MQTT 解析", "MQTT_parse": "MQTT 解析",

View File

@ -399,7 +399,8 @@
"sure_to_delete_permanent": "是否確認永久刪除該項目?", "sure_to_delete_permanent": "是否確認永久刪除該項目?",
"delete_success": "刪除成功", "delete_success": "刪除成功",
"delete_failed": "刪除失敗", "delete_failed": "刪除失敗",
"mqtt_refresh": "重新設定成功" "mqtt_refresh": "重新設定成功",
"schema_name_required": "架構名稱欄位必填"
}, },
"setting": { "setting": {
"MQTT_parse": "MQTT 解析", "MQTT_parse": "MQTT 解析",

View File

@ -399,7 +399,8 @@
"sure_to_delete_permanent": "Are you sure you want to permanently delete this item?", "sure_to_delete_permanent": "Are you sure you want to permanently delete this item?",
"delete_success": "Delete successfully", "delete_success": "Delete successfully",
"delete_failed": "Delete failed", "delete_failed": "Delete failed",
"mqtt_refresh": "MQTT reset successful" "mqtt_refresh": "MQTT reset successful",
"schema_name_required": "The schema name field is required"
}, },
"setting": { "setting": {
"MQTT_parse": "MQTT Parse", "MQTT_parse": "MQTT Parse",

View File

@ -107,15 +107,6 @@ router.beforeEach(async (to, from, next) => {
const token = useGetCookie("JWT-Authorization"); const token = useGetCookie("JWT-Authorization");
const user_name = useGetCookie("user_name"); const user_name = useGetCookie("user_name");
if (to.path === "/logout") {
document.cookie = "JWT-Authorization=; Max-Age=0";
document.cookie = "user_name=; Max-Age=0";
auth.user.token = "";
auth.user.user_name = "";
window.location.reload();
next({ path: "/login" });
}
if ((authRequired && !token) || to.path === "/") { if ((authRequired && !token) || to.path === "/") {
auth.user.token = ""; auth.user.token = "";
next({ path: "/login" }); next({ path: "/login" });

View File

@ -61,9 +61,8 @@ const onReset = () => {
? t('assetManagement.edit_system_category') ? t('assetManagement.edit_system_category')
: t('assetManagement.add_system_category') : t('assetManagement.add_system_category')
" "
:open="open"
:onCancel="onReset" :onCancel="onReset"
width="300" :width="300"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 flex flex-col items-center"> <form ref="form" class="mt-5 flex flex-col items-center">
@ -75,7 +74,7 @@ const onReset = () => {
</span></template </span></template
> >
</Input> </Input>
<Input name="system_value" :value="formState" :readonly="props.formState?.id"> <Input name="system_value" :value="formState" :readonly="Boolean(props.formState?.id)">
<template #topLeft>{{ $t("assetManagement.system_value") }}</template> <template #topLeft>{{ $t("assetManagement.system_value") }}</template>
<template #bottomLeft <template #bottomLeft
><span class="text-error text-base"> ><span class="text-error text-base">

View File

@ -95,9 +95,8 @@ const onOk = async () => {
? t('assetManagement.edit_device_category') ? t('assetManagement.edit_device_category')
: t('assetManagement.add_device_category') : t('assetManagement.add_device_category')
" "
:open="open"
:onCancel="onCancel" :onCancel="onCancel"
width="300" :width="300"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 flex flex-col items-center"> <form ref="form" class="mt-5 flex flex-col items-center">
@ -112,7 +111,7 @@ const onOk = async () => {
<Input <Input
name="system_value" name="system_value"
:value="formState" :value="formState"
:readonly="props.formState?.id" :readonly="Boolean(props.formState?.id)"
> >
<template #topLeft>{{ $t("assetManagement.system_value") }}</template> <template #topLeft>{{ $t("assetManagement.system_value") }}</template>
<template #bottomLeft <template #bottomLeft
@ -128,7 +127,7 @@ const onOk = async () => {
name="system_parent_id" name="system_parent_id"
:value="formState" :value="formState"
selectClass="border-info focus-within:border-info" selectClass="border-info focus-within:border-info"
:disabled="props.formState?.id" :disabled="Boolean(props.formState?.id)"
> >
<template #topLeft>{{ <template #topLeft>{{
$t("assetManagement.system_parent") $t("assetManagement.system_parent")

View File

@ -4,12 +4,14 @@ import { onMounted, ref, watch, inject, provide, computed } from "vue";
import useSearchParam from "@/hooks/useSearchParam"; import useSearchParam from "@/hooks/useSearchParam";
import AssetTableAddModal from "./AssetTableAddModal.vue"; import AssetTableAddModal from "./AssetTableAddModal.vue";
import { getOperationCompanyList } from "@/apis/operation"; import { getOperationCompanyList } from "@/apis/operation";
import { getAssetFloorList } from "@/apis/asset"; import { postMQTTRefresh } from "@/apis/alert";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
const { t } = useI18n(); const { t } = useI18n();
const { openToast, cancelToastOpen } = inject("app_toast"); const { openToast, cancelToastOpen } = inject("app_toast");
const { companyOptions, departmentList, floors } = inject("asset_modal_options"); const { companyOptions, departmentList, floors } = inject(
"asset_modal_options"
);
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL; const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
const { searchParams, changeParams } = useSearchParam(); const { searchParams, changeParams } = useSearchParam();
@ -33,7 +35,8 @@ const getAssetData = async () => {
floor: floors.value.find(({ floor_guid }) => d.floor_guid === floor_guid) floor: floors.value.find(({ floor_guid }) => d.floor_guid === floor_guid)
?.full_name, ?.full_name,
company: companyOptions.value.find(({ id }) => d.operation_id === id), company: companyOptions.value.find(({ id }) => d.operation_id === id),
department: departmentList.value.find(({ id }) => d.department_id === id)?.name, department: departmentList.value.find(({ id }) => d.department_id === id)
?.name,
buying_date: d?.buying_date buying_date: d?.buying_date
? dayjs(d?.buying_date).format("YYYY-MM-DD") ? dayjs(d?.buying_date).format("YYYY-MM-DD")
: "", : "",
@ -44,6 +47,15 @@ const getAssetData = async () => {
} }
}; };
const refreshMQTT = async () => {
const res = await postMQTTRefresh();
if (res.isSuccess) {
openToast("success", t("msg.mqtt_refresh"));
} else {
openToast("error", res.msg, "#outliers_add_table_item");
}
};
onMounted(async () => { onMounted(async () => {
getAssetData(); getAssetData();
}); });
@ -113,8 +125,8 @@ watch(
(newValue) => { (newValue) => {
if (newValue.value?.subSys_id) { if (newValue.value?.subSys_id) {
getAssetData(); getAssetData();
}else{ } else {
tableData.value=[]; tableData.value = [];
} }
}, },
{ {
@ -162,7 +174,7 @@ const remove = async (id) => {
const res = await deleteAssetItem(id); const res = await deleteAssetItem(id);
if (res.isSuccess) { if (res.isSuccess) {
getAssetData(); getAssetData();
openToast("success", t("msg.delete_success")); openToast("success", t("msg.delete_success"));
} else { } else {
openToast("error", res.msg); openToast("error", res.msg);
} }
@ -175,14 +187,21 @@ provide("asset_table_data", {
</script> </script>
<template> <template>
<div class="flex justify-start items-center mt-10"> <div class="flex justify-between items-center mt-10">
<h3 class="text-xl mr-5">{{ $t("assetManagement.device_list") }}</h3> <div class="flex">
<AssetTableAddModal <h3 class="text-xl mr-5">{{ $t("assetManagement.device_list") }}</h3>
:openModal="openModal" <AssetTableAddModal
:onCancel="onCancel" :openModal="openModal"
:editRecord="editRecord" :onCancel="onCancel"
:getData="getAssetData" :editRecord="editRecord"
/> :getData="getAssetData"
/>
</div>
<button class="btn btn-sm btn-add" @click.prevent="refreshMQTT">
<font-awesome-icon :icon="['fas', 'cog']" />{{
$t("alert.reorganization")
}}
</button>
</div> </div>
<Table :columns="columns" :dataSource="tableData" class="mt-3"> <Table :columns="columns" :dataSource="tableData" class="mt-3">
<template #bodyCell="{ record, column, index }"> <template #bodyCell="{ record, column, index }">

View File

@ -108,9 +108,8 @@ const closeModal = () => {
<Modal <Modal
id="asset_add_table_item" id="asset_add_table_item"
:title="editRecord?.main_id ? $t('assetManagement.edit_device') : $t('assetManagement.add_device')" :title="editRecord?.main_id ? $t('assetManagement.edit_device') : $t('assetManagement.add_device')"
:open="open"
:onCancel="closeModal" :onCancel="closeModal"
width="1600" :width="1600"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="grid grid-cols-5 gap-5"> <form ref="form" class="grid grid-cols-5 gap-5">

View File

@ -127,7 +127,7 @@ const onCancel = () => {
id="asset_add_dept" id="asset_add_dept"
:title="t('assetManagement.department')" :title="t('assetManagement.department')"
:onCancel="onCancel" :onCancel="onCancel"
width="400" :width="400"
> >
<template #modalContent> <template #modalContent>
<form ref="form"> <form ref="form">

View File

@ -138,7 +138,7 @@ onMounted(async () => {
id="asset_add_graph_item" id="asset_add_graph_item"
:title="t('graphManagement.title')" :title="t('graphManagement.title')"
:onCancel="onCancel" :onCancel="onCancel"
width="500" :width="500"
> >
<template #modalContent> <template #modalContent>
<ul class="menu bg-base-200 rounded-box text-lg w-full mt-3"> <ul class="menu bg-base-200 rounded-box text-lg w-full mt-3">

View File

@ -225,7 +225,7 @@ const deleteItem = (value) => {
id="asset_add_IoT_item" id="asset_add_IoT_item"
:title="t('assetManagement.associated_device')" :title="t('assetManagement.associated_device')"
:onCancel="onCancel" :onCancel="onCancel"
width="900" :width="900"
> >
<template #modalContent> <template #modalContent>
<ButtonGroup <ButtonGroup

View File

@ -106,7 +106,7 @@ const onCancel = () => {
</button> </button>
</div> </div>
<Modal id="mqtt_test" title="MQTT Topic" :onCancel="onCancel" width="400"> <Modal id="mqtt_test" title="MQTT Topic" :onCancel="onCancel" :width="400">
<template #modalContent> <template #modalContent>
<!-- 顯示接收到的訊息 --> <!-- 顯示接收到的訊息 -->
<div v-if="receivedMessages.length > 0" class="overflow-y-auto h-96"> <div v-if="receivedMessages.length > 0" class="overflow-y-auto h-96">

View File

@ -2,7 +2,7 @@
import ButtonGroup from "@/components/customUI/ButtonGroup.vue"; import ButtonGroup from "@/components/customUI/ButtonGroup.vue";
import Account from "./components/Account.vue"; import Account from "./components/Account.vue";
import Role from "./components/Role.vue"; import Role from "./components/Role.vue";
import { computed, watch, onBeforeMount } from "vue"; import { computed, watch, onBeforeMount, markRaw } from "vue";
import useActiveBtn from "@/hooks/useActiveBtn"; import useActiveBtn from "@/hooks/useActiveBtn";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
const { t, locale } = useI18n(); const { t, locale } = useI18n();
@ -18,13 +18,13 @@ const initializeItems = () => {
title: t("accountManagement.account_title"), title: t("accountManagement.account_title"),
key: "account", key: "account",
active: true, active: true,
component: Account, component: markRaw(Account),
}, },
{ {
title: t("accountManagement.role_title"), title: t("accountManagement.role_title"),
key: "role", key: "role",
active: false, active: false,
component: Role, component: markRaw(Role),
}, },
]); ]);
}; };

View File

@ -127,7 +127,7 @@ const onOk = async () => {
id="account_user_modal" id="account_user_modal"
:title="formState?.Id ? t('button.edit') : t('button.add')" :title="formState?.Id ? t('button.edit') : t('button.add')"
:onCancel="onCancel" :onCancel="onCancel"
width="710" :width="710"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between"> <form ref="form" class="mt-5 w-full flex flex-wrap justify-between">

View File

@ -9,7 +9,7 @@ const { t } = useI18n();
const { openToast } = inject("app_toast"); const { openToast } = inject("app_toast");
const props = defineProps({ const props = defineProps({
account: String, account: Object,
}); });
const formState = ref({ const formState = ref({
@ -48,7 +48,7 @@ const onOk = async () => {
id="account_user_password_modal" id="account_user_password_modal"
:title="t('accountManagement.change_password')" :title="t('accountManagement.change_password')"
:onCancel="onCancel" :onCancel="onCancel"
width="710" :width="710"
> >
<template #modalContent> <template #modalContent>
<p class="mt-10 text-3xl">{{ account.Name }}</p> <p class="mt-10 text-3xl">{{ account.Name }}</p>

View File

@ -13,7 +13,7 @@ import useActiveBtn from "@/hooks/useActiveBtn";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
const { t } = useI18n(); const { t } = useI18n();
const props = defineProps({ const props = defineProps({
selectedRole: String, selectedRole: Object,
cancelModal: Function, cancelModal: Function,
disabled: Boolean, disabled: Boolean,
update: Function, update: Function,

View File

@ -2,7 +2,7 @@
import ButtonGroup from "@/components/customUI/ButtonGroup.vue"; import ButtonGroup from "@/components/customUI/ButtonGroup.vue";
import AlertQuery from "./components/AlertQuery/AlertQuery.vue"; import AlertQuery from "./components/AlertQuery/AlertQuery.vue";
import AlertSetting from "./components/AlertSetting/AlertSetting.vue"; import AlertSetting from "./components/AlertSetting/AlertSetting.vue";
import { computed, watch, onBeforeMount } from "vue"; import { computed, watch, onBeforeMount, markRaw } from "vue";
import useActiveBtn from "@/hooks/useActiveBtn"; import useActiveBtn from "@/hooks/useActiveBtn";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
const { t, locale } = useI18n(); const { t, locale } = useI18n();
@ -18,13 +18,13 @@ const initializeItems = () => {
title: t("alert.query_title"), title: t("alert.query_title"),
key: "Query", key: "Query",
active: true, active: true,
component: AlertQuery, component: markRaw(AlertQuery),
}, },
{ {
title: t("alert.setting_title"), title: t("alert.setting_title"),
key: "Setting", key: "Setting",
active: false, active: false,
component: AlertSetting, component: markRaw(AlertSetting),
}, },
]); ]);
}; };

View File

@ -160,7 +160,7 @@ watch(
id="alert_action_item" id="alert_action_item"
:title="t('alert.repair_order')" :title="t('alert.repair_order')"
:onCancel="onCancel" :onCancel="onCancel"
width="710" :width="710"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between"> <form ref="form" class="mt-5 w-full flex flex-wrap justify-between">
@ -199,7 +199,7 @@ watch(
{ {
key: 1, key: 1,
value: 1, value: 1,
title: $t('alert.maintenance'), title: $t('operation.maintenance'),
}, },
{ {
key: 2, key: 2,

View File

@ -94,9 +94,8 @@ const closeModal = () => {
<Modal <Modal
id="notify_add_table_item" id="notify_add_table_item"
:title="t('alert.notify_list')" :title="t('alert.notify_list')"
:open="open"
:onCancel="closeModal" :onCancel="closeModal"
width="300" :width="300"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 flex flex-col items-center"> <form ref="form" class="mt-5 flex flex-col items-center">
@ -128,7 +127,7 @@ const closeModal = () => {
<p class="text-light text-base">{{ $t("alert.notify_items") }}</p> <p class="text-light text-base">{{ $t("alert.notify_items") }}</p>
<AlertNoticesTable <AlertNoticesTable
:SaveCheckAuth="SaveCheckAuth" :SaveCheckAuth="SaveCheckAuth"
:NoticeData="[noticeList[2]]" :NoticeData="[noticeList[1]]"
:onChange="onChange" :onChange="onChange"
/> />
<span class="text-error text-base"> <span class="text-error text-base">

View File

@ -119,9 +119,8 @@ const closeModal = () => {
<Modal <Modal
id="outliers_add_table_item" id="outliers_add_table_item"
:title="t('alert.alarm_settings')" :title="t('alert.alarm_settings')"
:open="open"
:onCancel="closeModal" :onCancel="closeModal"
width="710" :width="710"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between"> <form ref="form" class="mt-5 w-full flex flex-wrap justify-between">

View File

@ -10,17 +10,17 @@ const { locale } = useI18n();
const timesList = ref([]); const timesList = ref([]);
const noticeList = ref([]); const noticeList = ref([]);
const timesListData = async () => { // const timesListData = async () => {
const res = await getAlarmScheduleList(); // const res = await getAlarmScheduleList();
timesList.value = res.data.map((items) => ({ // timesList.value = res.data.map((items) => ({
...items, // ...items,
key:items.id, // key:items.id,
schedule_array: JSON.parse(items.schedule_json).map((time, index) => ({ // schedule_array: JSON.parse(items.schedule_json).map((time, index) => ({
day: index + 1, // day: index + 1,
time, // time,
})), // })),
})); // }));
}; // };
const NoticeListData = async () => { const NoticeListData = async () => {
const res = await getNoticeList(locale.value); const res = await getNoticeList(locale.value);
@ -32,11 +32,15 @@ watch(locale, () => {
}); });
onMounted(() => { onMounted(() => {
timesListData(); // timesListData();
NoticeListData(); NoticeListData();
}); });
provide("notify_table", { timesList, noticeList, timesListData }); provide("notify_table", {
timesList,
noticeList,
// timesListData
});
</script> </script>
<template> <template>

View File

@ -16,7 +16,7 @@ import { twMerge } from "tailwind-merge";
const store = useBuildingStore(); const store = useBuildingStore();
const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn(); const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
let intervalId = null; let intervalId = null;
const energyCostData = ref(null); const energyCostData = ref({});
const formState = ref({ const formState = ref({
building_guid: null, building_guid: null,
floor_guid: "all", floor_guid: "all",

View File

@ -26,7 +26,7 @@ const currentEnergyType = ref({
// //
const getCurrentEnergyData = () => { const getCurrentEnergyData = () => {
if (!props.energyCostData) { if (!props.energyCostData || !props.energyCostData.rank) {
return []; // return []; //
} }

View File

@ -35,6 +35,16 @@ watch(selectedBtn, (newVal, oldVal) => {
detailData.value = props.modalData[newVal.key]; detailData.value = props.modalData[newVal.key];
} }
}); });
watch(
() => props.modalData,
(newVal, oldVal) => {
if (newVal) {
changeActiveBtn(items.value[0]);
}
},
{ immediate: true }
);
</script> </script>
<template> <template>
@ -51,13 +61,13 @@ watch(selectedBtn, (newVal, oldVal) => {
} }
" "
/> />
<Button <button
type="link" type="link"
class="btn-link btn-text-without-border px-2" class="btn-link btn-text-without-border px-2"
@click="onCancel" @click="onCancel"
> >
<font-awesome-icon :icon="['fas', 'times']" class="text-[#a5abb1]" /> <font-awesome-icon :icon="['fas', 'times']" class="text-[#a5abb1]" />
</Button> </button>
</div> </div>
</template> </template>
<template #modalContent> <template #modalContent>

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref, onMounted, watch } from "vue"; import { ref, onMounted, watch, markRaw } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import EnergyChart from "./components/EnergyChart/EnergyChart.vue"; import EnergyChart from "./components/EnergyChart/EnergyChart.vue";
@ -14,12 +14,12 @@ const updateComponent = () => {
if (main_system_id === "energy_chart") { if (main_system_id === "energy_chart") {
if (sub_system_id === "chart") { if (sub_system_id === "chart") {
currentComponent.value = EnergyChart; currentComponent.value = markRaw(EnergyChart);
} else { } else {
currentComponent.value = EnergyHistoryTable; currentComponent.value = markRaw(EnergyHistoryTable);
} }
} else if (main_system_id === "energy_report") { } else if (main_system_id === "energy_report") {
currentComponent.value = EnergyReport; currentComponent.value = markRaw(EnergyReport);
} else { } else {
currentComponent.value = null; currentComponent.value = null;
} }

View File

@ -42,7 +42,7 @@ const onOk = async () => {
const res = await postEditCarbonValue({ const res = await postEditCarbonValue({
...values, ...values,
"building_guid":store.selectedBuilding.building_guid, building_guid: store.selectedBuilding.building_guid,
}); });
if (res.isSuccess) { if (res.isSuccess) {
props.getData(); props.getData();
@ -67,19 +67,24 @@ const closeModal = () => {
</script> </script>
<template> <template>
<button class="btn btn-sm btn-success ms-auto me-3" @click.stop.prevent="openModal"> <button
class="btn btn-sm btn-success ms-auto me-3"
@click.stop.prevent="openModal"
>
{{ $t("button.edit") }} {{ $t("button.edit") }}
</button> </button>
<Modal <Modal
id="carbon_emission_item" id="carbon_emission_item"
:title="t('energy.edit_carbon_emission')" :title="t('energy.edit_carbon_emission')"
:onCancel="closeModal" :onCancel="closeModal"
width="300" :width="300"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 flex flex-col items-center"> <form ref="form" class="mt-5 flex flex-col items-center">
<Input :value="formState" class="w-full" name="coefficient"> <Input :value="formState" class="w-full" name="coefficient">
<template #topLeft>{{$t('energy.carbon_emission_coefficient')}}</template> <template #topLeft>{{
$t("energy.carbon_emission_coefficient")
}}</template>
<template #bottomLeft> <template #bottomLeft>
<span class="text-error text-base"> <span class="text-error text-base">
{{ formErrorMsg.coefficient }} {{ formErrorMsg.coefficient }}

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref, onMounted, nextTick, watch, inject } from "vue"; import { ref, onMounted, watch, inject } from "vue";
import * as echarts from "echarts"; import * as echarts from "echarts";
import { getRealTimeDist } from "@/apis/energy"; import { getRealTimeDist } from "@/apis/energy";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
@ -7,6 +7,7 @@ const { search_data } = inject("energy_data");
const { t } = useI18n(); const { t } = useI18n();
const chartDiv = ref(null); const chartDiv = ref(null);
let myChart = null; // myChart
const chartOption = { const chartOption = {
tooltip: { tooltip: {
@ -91,12 +92,18 @@ const loadData = async (value) => {
chartOption.series[0].links = links; chartOption.series[0].links = links;
// //
const myChart = echarts.init(chartDiv.value); if (myChart) {
myChart.dispose(); //
}
myChart = echarts.init(chartDiv.value);
myChart.setOption(chartOption); myChart.setOption(chartOption);
} }
} else { } else {
// //
echarts.init(chartDiv.value).clear(); if (myChart) {
myChart.dispose(); //
myChart = null;
}
} }
}; };
@ -115,6 +122,12 @@ watch(
deep: true, deep: true,
} }
); );
onMounted(() => {
//
myChart = echarts.init(chartDiv.value);
myChart.setOption(chartOption);
});
</script> </script>
<template> <template>
@ -138,4 +151,4 @@ ul li:last-child:after {
@apply absolute top-0 bottom-0 left-full block w-full h-[1px] bg-slate-600 m-auto z-10; @apply absolute top-0 bottom-0 left-full block w-full h-[1px] bg-slate-600 m-auto z-10;
content: ""; content: "";
} }
</style> </style>

View File

@ -81,7 +81,7 @@ const onCancel = () => {
id="immediate_demand_add_item" id="immediate_demand_add_item"
:title="t('energy.edit_automatic_demand')" :title="t('energy.edit_automatic_demand')"
:onCancel="closeModal" :onCancel="closeModal"
width="300" :width="300"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 flex flex-col items-center"> <form ref="form" class="mt-5 flex flex-col items-center">

View File

@ -132,7 +132,7 @@ const columns = computed(() => {
key: "endTime", key: "endTime",
}, },
{ {
title: t("energy.ectricity_classification"), title: t("energy.electricity_classification"),
key: "elecType", key: "elecType",
}, },
{ {

View File

@ -126,7 +126,7 @@ watch(
<button class="btn btn-add mr-3" @click.stop.prevent="openModal"> <button class="btn btn-add mr-3" @click.stop.prevent="openModal">
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }} <font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
</button> </button>
<Modal id="graph_add_item" :title="t('graphManagement.upload')" :onCancel="onCancel" width="800"> <Modal id="graph_add_item" :title="t('graphManagement.upload')" :onCancel="onCancel" :width="800">
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5"> <form ref="form" class="mt-5">
<div class="mb-2"> <div class="mb-2">

View File

@ -110,7 +110,7 @@ const checkedBuilding = computed(() => {
if ( if (
selectedDeviceNumber.value?.filter( selectedDeviceNumber.value?.filter(
(d) => d.split("_")[1] === building_tag (d) => d?.split("_")[1] === building_tag
).length === allDevices.length ).length === allDevices.length
) { ) {
selected.push(building_tag); selected.push(building_tag);

View File

@ -7,7 +7,7 @@ import { twMerge } from "tailwind-merge";
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n(); const { t, locale } = useI18n();
const props = defineProps({ const props = defineProps({
selected: String, selected: Object,
}); });
const { searchParams, changeParams } = useSearchParam(); const { searchParams, changeParams } = useSearchParam();

View File

@ -226,7 +226,7 @@ watch(
</script> </script>
<template> <template>
<Modal id="operation_action_item" :onCancel="onCancel" width="710"> <Modal id="operation_action_item" :onCancel="onCancel" :width="710">
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between"> <form ref="form" class="mt-5 w-full flex flex-wrap justify-between">
<template v-if="searchParams?.work_type < 3"> <template v-if="searchParams?.work_type < 3">

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref, onMounted, watch } from "vue"; import { ref, onMounted, watch, markRaw } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import Dept from "./components/Dept.vue"; import Dept from "./components/Dept.vue";
@ -19,21 +19,21 @@ const updateComponent = () => {
const { main_system_id, sub_system_id } = route.params; const { main_system_id, sub_system_id } = route.params;
if (sub_system_id === "Department") { if (sub_system_id === "Department") {
currentComponent.value = Dept; currentComponent.value = markRaw(Dept);
} else if (sub_system_id === "ElecType") { } else if (sub_system_id === "ElecType") {
currentComponent.value = ElecType; currentComponent.value = markRaw(ElecType);
} else if (sub_system_id === "Vendor") { } else if (sub_system_id === "Vendor") {
currentComponent.value = Vendor; currentComponent.value = markRaw(Vendor);
} else if (sub_system_id === "Floor") { } else if (sub_system_id === "Floor") {
currentComponent.value = Floors; currentComponent.value = markRaw(Floors);
} else if (sub_system_id === "Building") { } else if (sub_system_id === "Building") {
currentComponent.value = Building; currentComponent.value = markRaw(Building);
} else if (sub_system_id === "ElecPricing") { } else if (sub_system_id === "ElecPricing") {
currentComponent.value = ElecPriceManagement; currentComponent.value = markRaw(ElecPriceManagement);
} else if (sub_system_id === "MQTT_Result") { } else if (sub_system_id === "MQTT_Result") {
currentComponent.value = MQTTList; currentComponent.value = markRaw(MQTTList);
} else if (sub_system_id === "Demand") { } else if (sub_system_id === "Demand") {
currentComponent.value = Demand; currentComponent.value = markRaw(Demand);
} }
}; };

View File

@ -46,7 +46,7 @@ const onOk = async () => {
id="build_modal" id="build_modal"
:title="props.formState?.building_guid ? t('button.edit') : t('button.add')" :title="props.formState?.building_guid ? t('button.edit') : t('button.add')"
:onCancel="onCancel" :onCancel="onCancel"
width="400" :width="400"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between"> <form ref="form" class="mt-5 w-full flex flex-wrap justify-between">

View File

@ -48,7 +48,7 @@ const onOk = async () => {
id="dept_modal" id="dept_modal"
:title="props.formState?.id ? t('button.edit') : t('button.add')" :title="props.formState?.id ? t('button.edit') : t('button.add')"
:onCancel="onCancel" :onCancel="onCancel"
width="400" :width="400"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between"> <form ref="form" class="mt-5 w-full flex flex-wrap justify-between">

View File

@ -2,7 +2,7 @@
import ButtonGroup from "@/components/customUI/ButtonGroup.vue"; import ButtonGroup from "@/components/customUI/ButtonGroup.vue";
import ElecPriceRes from "./ElecPriceRes.vue"; import ElecPriceRes from "./ElecPriceRes.vue";
import ElecPriceStd from "./ElecPriceStd.vue"; import ElecPriceStd from "./ElecPriceStd.vue";
import { computed, watch, onBeforeMount, ref, provide } from "vue"; import { computed, watch, onBeforeMount, ref, provide, markRaw } from "vue";
import useActiveBtn from "@/hooks/useActiveBtn"; import useActiveBtn from "@/hooks/useActiveBtn";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { getTimeElec } from "@/apis/energy"; import { getTimeElec } from "@/apis/energy";
@ -26,13 +26,13 @@ const initializeItems = () => {
title: t("energy.residential"), title: t("energy.residential"),
key: "Residential", key: "Residential",
active: true, active: true,
component: ElecPriceRes, component: markRaw(ElecPriceRes),
}, },
{ {
title: t("energy.standard"), title: t("energy.standard"),
key: "Standard", key: "Standard",
active: false, active: false,
component: ElecPriceStd, component: markRaw(ElecPriceStd),
}, },
]); ]);
}; };

View File

@ -46,7 +46,7 @@ const onOk = async () => {
id="elec_modal" id="elec_modal"
:title="props.formState?.id ? t('button.edit') : t('button.add')" :title="props.formState?.id ? t('button.edit') : t('button.add')"
:onCancel="onCancel" :onCancel="onCancel"
width="400" :width="400"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between"> <form ref="form" class="mt-5 w-full flex flex-wrap justify-between">

View File

@ -66,7 +66,7 @@ const onOk = async () => {
id="floor_modal" id="floor_modal"
:title="props.formState?.floor_guid ? t('button.edit') : t('button.add')" :title="props.formState?.floor_guid ? t('button.edit') : t('button.add')"
:onCancel="onCancel" :onCancel="onCancel"
width="400" :width="400"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between"> <form ref="form" class="mt-5 w-full flex flex-wrap justify-between">

View File

@ -102,6 +102,10 @@ watch(
); );
const onOk = async () => { const onOk = async () => {
if (!schemaName.value) {
openToast("error", t("msg.schema_name_required"), "#MQTT_Parse_item");
return;
}
const points = formStates.value.map((state) => ({ const points = formStates.value.map((state) => ({
PointOrg: state.PointOrg, PointOrg: state.PointOrg,
PointSys: props.pointsData.find((point) => point.id === state.item_id) PointSys: props.pointsData.find((point) => point.id === state.item_id)
@ -181,13 +185,14 @@ const onCancel = () => {
type="text" type="text"
v-model.text="schemaName" v-model.text="schemaName"
class="input border-info focus-within:border-info" class="input border-info focus-within:border-info"
required
/> />
</div> </div>
<table class="table w-1/2 mt-2"> <table class="table w-1/2 mt-2">
<thead> <thead>
<tr> <tr>
<th>{{$t("setting.IoT_point_structure")}}</th> <th>{{ $t("setting.IoT_point_structure") }}</th>
<th>{{$t("setting.system_point_name")}}</th> <th>{{ $t("setting.system_point_name") }}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>

View File

@ -60,7 +60,7 @@ const onOk = async () => {
id="company_modal" id="company_modal"
:title="props.formState?.id ? t('button.edit') : t('button.add')" :title="props.formState?.id ? t('button.edit') : t('button.add')"
:onCancel="onCancel" :onCancel="onCancel"
width="710" :width="710"
> >
<template #modalContent> <template #modalContent>
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between"> <form ref="form" class="mt-5 w-full flex flex-wrap justify-between">

View File

@ -32,7 +32,7 @@ const cancelDialog = () => {
frameborder="0" frameborder="0"
class="w-full h-full" class="w-full h-full"
></iframe> ></iframe>
<Button <button
type="link" type="link"
class="btn-link btn-text-without-border z-20 absolute right-[2.3rem] top-[2.2rem]" class="btn-link btn-text-without-border z-20 absolute right-[2.3rem] top-[2.2rem]"
@click="cancelDialog" @click="cancelDialog"
@ -41,7 +41,7 @@ const cancelDialog = () => {
:icon="['fas', 'times']" :icon="['fas', 'times']"
class="text-[#a5abb1] text-2xl" class="text-[#a5abb1] text-2xl"
/> />
</Button> </button>
</dialog> </dialog>
<template v-if="showData.length > 0"> <template v-if="showData.length > 0">

View File

@ -33,25 +33,25 @@ const onCancel = () => {
<div class="card-title py-2 border-b border-zinc-700 justify-between"> <div class="card-title py-2 border-b border-zinc-700 justify-between">
<h3>{{ data?.value?.full_name }}</h3> <h3>{{ data?.value?.full_name }}</h3>
<div> <div>
<Button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('desktop')"> <button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('desktop')">
<font-awesome-icon :icon="['fas', 'desktop']" size="lg" <font-awesome-icon :icon="['fas', 'desktop']" size="lg"
:class="twMerge(currentTab === 'desktop' ? 'text-success' : 'text-[#a5abb1]')" /> :class="twMerge(currentTab === 'desktop' ? 'text-success' : 'text-[#a5abb1]')" />
</Button> </button>
<Button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('image')"> <button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('image')">
<font-awesome-icon :icon="['fas', 'image']" size="lg" <font-awesome-icon :icon="['fas', 'image']" size="lg"
:class="twMerge(currentTab === 'image' ? 'text-success' : 'text-[#a5abb1]')" /> :class="twMerge(currentTab === 'image' ? 'text-success' : 'text-[#a5abb1]')" />
</Button> </button>
<Button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('cog')"> <button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('cog')">
<font-awesome-icon :icon="['fas', 'cog']" size="lg" <font-awesome-icon :icon="['fas', 'cog']" size="lg"
:class="twMerge(currentTab === 'cog' ? 'text-success' : 'text-[#a5abb1]')" /> :class="twMerge(currentTab === 'cog' ? 'text-success' : 'text-[#a5abb1]')" />
</Button> </button>
<!-- <Button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('chart')"> <!-- <Button type="link" class="btn-link btn-text-without-border px-2" @click="() => changeOpenKey('chart')">
<font-awesome-icon :icon="['fas', 'chart-line']" size="lg" <font-awesome-icon :icon="['fas', 'chart-line']" size="lg"
:class="twMerge(currentTab === 'chart' ? 'text-success' : 'text-[#a5abb1]')" /> :class="twMerge(currentTab === 'chart' ? 'text-success' : 'text-[#a5abb1]')" />
</Button> --> </Button> -->
<Button type="link" class="btn-link btn-text-without-border px-2" @click="onCancel"> <button type="link" class="btn-link btn-text-without-border px-2" @click="onCancel">
<font-awesome-icon :icon="['fas', 'times']" size="lg" class="text-[#a5abb1]" /> <font-awesome-icon :icon="['fas', 'times']" size="lg" class="text-[#a5abb1]" />
</Button> </button>
</div> </div>
</div> </div>
<div class="card-body p-0"> <div class="card-body p-0">