刪除按鈕點選後新增"確認刪除" | 能源管理語言切換時即時更新 | 樓層新增與修改bug修正 | 系統監控filter暫時移除device_coordinate_3d條件

This commit is contained in:
koko 2024-11-06 17:27:03 +08:00
parent b6890e8311
commit 5cb8e7da6e
19 changed files with 199 additions and 73 deletions

View File

@ -18,15 +18,16 @@ const cancelToastOpen = () => {
};
};
const openToast = (status, content, to = "body") => {
const openToast = (status, content, to = "body", confirm = null) => {
isToastOpen.value = {
open: true,
content,
status,
to,
confirm,
};
};
provide("app_toast", { openToast });
provide("app_toast", { openToast, cancelToastOpen });
</script>
<template>
@ -35,6 +36,7 @@ provide("app_toast", { openToast });
:open="isToastOpen.open"
:status="isToastOpen.status"
:cancel="cancelToastOpen"
:confirm="isToastOpen.confirm"
:to="isToastOpen.to"
/>
<div v-if="store.user.token" class="min-h-screen">

View File

@ -1,12 +1,14 @@
<script setup>
import { defineProps, ref, watch } from "vue";
import { twMerge } from "tailwind-merge";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const props = defineProps({
content: String,
status: String,
open: Boolean,
cancel: Function,
confirm: Function,
to: {
default: "body",
type: String,
@ -19,7 +21,7 @@ watch(
() => props.open,
(newVal) => {
isOpen.value = newVal;
if (newVal) {
if (newVal && props.status !== "warning") {
setTimeout(() => {
props.cancel && props.cancel();
}, 3000);
@ -40,6 +42,8 @@ watch(
? 'alert-info'
: status === 'error'
? 'alert-error text-white'
: status === 'warning'
? 'alert-warning bg-yellow-400'
: 'alert-success'
)
"
@ -58,6 +62,10 @@ watch(
></path>
</svg>
<span>{{ content }}</span>
<div v-if="status === 'warning'">
<button @click="props.cancel && props.cancel();" className="btn btn-sm btn-outline me-2">{{$t("button.cancel")}}</button>
<button @click="props.confirm && props.confirm()" className="btn btn-sm">{{$t("button.confirm")}}</button>
</div>
</div>
</template>
</Teleport>

View File

@ -28,7 +28,7 @@ const src = import.meta.env.MODE === "production" ? "./logo.svg" : Logo;
<template>
<header class="navbar bg-dark text-light-info w-full relative z-50">
<div class="navbar-start">
<div class="navbar-start min-w-[480px] lg:min-w-[440px]">
<div tabindex="0" role="button" class="btn btn-ghost lg:hidden" @click="toggleMenu">
<svg
xmlns="http://www.w3.org/2000/svg"

View File

@ -269,6 +269,12 @@
"password_format": "密码长度至少8码必须包含英文及数字",
"start_time_placeholder": "请输入预计开始日期",
"rename": "重新命名",
"download": "下载"
"download": "下载",
"confirm": "确认"
},
"msg":{
"sure_to_delete": "是否确认删除该项目?",
"delete_success": "删除成功",
"delete_failed": "删除失败"
}
}

View File

@ -269,6 +269,12 @@
"password_format": "密碼長度至少8碼必須包含英文及數字",
"start_time_placeholder": "請輸入預計開始日期",
"rename": "重新命名",
"download": "下載"
"download": "下載",
"confirm": "確認"
},
"msg":{
"sure_to_delete": "是否確認刪除該項目?",
"delete_success": "刪除成功",
"delete_failed": "刪除失敗"
}
}

View File

@ -269,6 +269,12 @@
"password_format": "The password must be at least 8 characters long and must contain English and numbers.",
"start_time_placeholder": "Please enter expected start date",
"rename": "Rename",
"download": "Download"
"download": "Download",
"confirm": "Confirm"
},
"msg":{
"sure_to_delete": "Are you sure to delete this item?",
"delete_success": "Delete successfully",
"delete_failed": "Delete failed"
}
}

View File

@ -8,7 +8,7 @@ import { getAssetFloorList } from "@/apis/asset";
import dayjs from "dayjs";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { openToast } = inject("app_toast");
const { openToast, cancelToastOpen } = inject("app_toast");
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
const { searchParams, changeParams } = useSearchParam();
@ -32,7 +32,7 @@ const getAssetData = async () => {
const res = await getAssetList(searchParams.value?.subSys_id);
if (res.isSuccess) {
// device_coordinate
res.data.forEach(d => {
res.data.forEach((d) => {
const floorGuid = d.floor_guid;
if (!totalCoordinates.value[floorGuid]) {
totalCoordinates.value[floorGuid] = [];
@ -164,10 +164,16 @@ const edit = async (id) => {
};
const remove = async (id) => {
const res = await deleteAssetItem(id);
if (res.isSuccess) {
getAssetData();
}
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
await cancelToastOpen();
const res = await deleteAssetItem(id);
if (res.isSuccess) {
getAssetData();
openToast("success", t("msg.delete_success"));
} else {
openToast("error", res.msg);
}
});
};
provide("asset_table_data", {

View File

@ -13,6 +13,7 @@ import { twMerge } from "tailwind-merge";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { openToast, cancelToastOpen } = inject("app_toast");
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
const { totalCoordinates } = inject("asset_table_data");
const { updateRightFields, formErrorMsg, formState } = inject(
@ -165,9 +166,9 @@ const {
const onOk = async () => {
const value = handleSubmit(floorScheme, FloorFormState.value);
const formData = new FormData(form.value);
formData.append("floor_guid", currentFloor.value.floor_guid);
formData.append("floor_guid", selectedOption.value === "add" ? null :currentFloor.value.floor_guid);
formData.append("building_tag", store.selectedBuilding.building_tag);
formData.append("initMapName", FloorFormState.value.floorFile[0].name);
formData.append("initMapName", FloorFormState.value.floorFile[0]?.name);
formData.append("mapFile", FloorFormState.value.floorFile[0]);
formData.delete("floorFile");
for (let [key, value] of formData) {
@ -181,13 +182,18 @@ const onOk = async () => {
}
};
const onDelete = async () => {
console.log("guild", formState.value.floor_guid);
const res = await deleteAssetFloor({
floor_guid: formState.value.floor_guid,
openToast("warning", t("msg.sure_to_delete"), "#asset_add_table_item", async () => {
await cancelToastOpen();
const res = await deleteAssetFloor({
floor_guid: formState.value.floor_guid,
});
if (res.isSuccess) {
getFloors();
openToast("success", t("msg.delete_success"), "#asset_add_table_item");
} else {
openToast("error", res.msg, "#asset_add_table_item");
}
});
if (res.isSuccess) {
getFloors();
}
};
const onCancel = () => {

View File

@ -10,7 +10,7 @@ import { onMounted, ref, inject, computed } from "vue";
import AccountPasswordModal from "./AccountPasswordModal.vue";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { openToast } = inject("app_toast");
const { openToast, cancelToastOpen } = inject("app_toast");
const columns = computed(() => [
{
@ -123,13 +123,16 @@ const resetModalForm = () => {
};
const removeAccount = async (id) => {
const res = await delAccount(id);
if (res.isSuccess) {
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
await cancelToastOpen();
const res = await delAccount(id);
if (res.isSuccess) {
getDataSource();
} else {
openToast("error", res.msg);
}
openToast("success", t("msg.delete_success"));
} else {
openToast("error", res.msg);
}
});
};
</script>

View File

@ -3,9 +3,10 @@ import Table from "@/components/customUI/Table.vue";
import Input from "@/components/customUI/Input.vue";
import { getAccountRoleList, delRole } from "@/apis/account";
import RoleAuthModal from "./RoleAuthModal.vue";
import { ref, onMounted, computed } from "vue";
import { ref, onMounted, computed, inject } from "vue";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { openToast, cancelToastOpen } = inject("app_toast");
const columns = computed(() => [
{
title: t("accountManagement.index"),
@ -60,11 +61,18 @@ const add = () => {
};
const remove = async (Id) => {
const res = await delRole(Id);
// getRole();
dataSource.value = dataSource.value.filter(
({ role_guid }) => role_guid !== Id
);
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
await cancelToastOpen();
const res = await delRole(Id);
if (res.isSuccess) {
dataSource.value = dataSource.value.filter(
({ role_guid }) => role_guid !== Id
);
openToast("success", t("msg.delete_success"));
} else {
openToast("error", res.msg);
}
});
};
const cancelModal = () => {

View File

@ -4,7 +4,7 @@ import { getAlarmMemberList, deleteAlarmMember } from "@/apis/alert";
import AlertNotifyTableAddModal from "./AlertNotifyTableAddModal.vue";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { openToast } = inject("app_toast");
const { openToast, cancelToastOpen } = inject("app_toast");
const tableData = ref([]);
const editRecord = ref(null);
const { noticeList } = inject("notify_table");
@ -75,12 +75,16 @@ const onCancel = () => {
};
const remove = async (id) => {
const res = await deleteAlarmMember(id);
if (res.isSuccess) {
fetchTableData();
} else {
openToast("error", res.msg);
}
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
await cancelToastOpen();
const res = await deleteAlarmMember(id);
if (res.isSuccess) {
fetchTableData();
openToast("success", t("msg.delete_success"));
} else {
openToast("error", res.msg);
}
});
};
</script>

View File

@ -27,7 +27,7 @@ const mockData = [
<div
v-for="(item, index) in mockData"
:key="index"
class="xl:w-1/4 lg:w-1/2 w-full item-data-box relative px-3"
class="xl:w-1/4 md:w-1/2 w-full item-data-box relative px-3"
>
<div :class="twMerge('item-data', index % 2 === 0 ? 'blue' : 'green')">
<h2>{{ item.value }}</h2>

View File

@ -117,7 +117,7 @@ const orderData = ref({
}
.state-box .title {
@apply relative flex items-center mb-6;
@apply relative flex items-center mb-4;
}
.state-box .title .state-title01 {

View File

@ -14,7 +14,7 @@ const defaultChartOption = ref({
},
},
legend: {
data: [ t("energy.peak"), t("energy.semi_peak"), t("energy.off_peak")],
data: [],
textStyle: {
color: "#ffffff",
fontSize: 14,
@ -44,7 +44,7 @@ const defaultChartOption = ref({
},
series: [
{
name: t("energy.peak"),
name: "",
type: "bar",
stack: "total",
data: [],
@ -53,7 +53,7 @@ const defaultChartOption = ref({
},
},
{
name: t("energy.semi_peak"),
name: "",
type: "bar",
stack: "total",
data: [],
@ -62,7 +62,7 @@ const defaultChartOption = ref({
},
},
{
name: t("energy.off_peak"),
name: "",
type: "bar",
stack: "total",
data: [],
@ -73,12 +73,23 @@ const defaultChartOption = ref({
],
});
const updateChartNames = () => {
defaultChartOption.value.legend.data = [
t("energy.peak"),
t("energy.semi_peak"),
t("energy.off_peak"),
];
defaultChartOption.value.series[0].name = t("energy.peak");
defaultChartOption.value.series[1].name = t("energy.semi_peak");
defaultChartOption.value.series[2].name = t("energy.off_peak");
};
// taipower_data
watch(
taipower_data,
() => {
//
const months = taipower_data.value.map(item => item.month);
const months = taipower_data.value.map((item) => item.month);
const kWhPeak = taipower_data.value.map((item) => item.kWhPeak);
const kWhHalfPeak = taipower_data.value.map((item) => item.kWhHalfPeak);
const kWhOffPeak = taipower_data.value.map((item) => item.kWhOffPeak);
@ -91,6 +102,15 @@ watch(
},
{ deep: true }
);
// locale
watch(locale, () => {
updateChartNames();
});
onMounted(() => {
updateChartNames();
});
</script>
<template>

View File

@ -1,6 +1,6 @@
<script setup>
import BarChart from "@/components/chart/BarChart.vue";
import { ref, inject, watch } from "vue";
import { ref, onMounted, inject, watch } from "vue";
import { useI18n } from "vue-i18n";
const { t, locale } = useI18n();
@ -14,7 +14,7 @@ const defaultChartOption = ref({
},
},
legend: {
data: [t("energy.carbon_equivalent")],
data: [],
textStyle: {
color: "#ffffff",
fontSize: 14,
@ -44,7 +44,7 @@ const defaultChartOption = ref({
},
series: [
{
name: t("energy.carbon_equivalent"),
name: "",
type: "bar",
data: [],
itemStyle: {
@ -54,6 +54,13 @@ const defaultChartOption = ref({
],
});
const updateChartNames = () => {
defaultChartOption.value.legend.data = [
t("energy.carbon_equivalent"),
];
defaultChartOption.value.series[0].name = t("energy.carbon_equivalent");
};
// taipower_data
watch(
taipower_data,
@ -68,6 +75,15 @@ watch(
},
{ deep: true }
);
// locale
watch(locale, () => {
updateChartNames();
});
onMounted(() => {
updateChartNames();
});
</script>
<template>

View File

@ -15,11 +15,7 @@ const defaultChartOption = ref({
},
},
legend: {
data: [
t("energy.fixed_elec_cost"),
t("energy.var_elec_cost"),
t("energy.total_elec_cost"),
],
data: [],
textStyle: {
color: "#ffffff",
fontSize: 14,
@ -49,7 +45,7 @@ const defaultChartOption = ref({
},
series: [
{
name: t("energy.fixed_elec_cost"),
name: "",
type: "bar",
stack: "total",
data: [],
@ -58,7 +54,7 @@ const defaultChartOption = ref({
},
},
{
name: t("energy.var_elec_cost"),
name: "",
type: "bar",
stack: "total",
data: [],
@ -67,7 +63,7 @@ const defaultChartOption = ref({
},
},
{
name: t("energy.total_elec_cost"),
name: "",
type: "bar",
stack: "total",
data: [],
@ -78,12 +74,23 @@ const defaultChartOption = ref({
],
});
const updateChartNames = () => {
defaultChartOption.value.legend.data = [
t("energy.fixed_elec_cost"),
t("energy.var_elec_cost"),
t("energy.total_elec_cost"),
];
defaultChartOption.value.series[0].name = t("energy.fixed_elec_cost");
defaultChartOption.value.series[1].name = t("energy.var_elec_cost");
defaultChartOption.value.series[2].name = t("energy.total_elec_cost");
};
// taipower_data
watch(
taipower_data,
() => {
//
const months = taipower_data.value.map(item => item.month);
const months = taipower_data.value.map((item) => item.month);
const costTotal = taipower_data.value.map((item) => item.costTotal);
const costBase = taipower_data.value.map((item) => item.costBase);
const costChange = taipower_data.value.map((item) => item.costChange);
@ -96,6 +103,15 @@ watch(
},
{ deep: true }
);
// locale
watch(locale, () => {
updateChartNames();
});
onMounted(() => {
updateChartNames();
});
</script>
<template>

View File

@ -6,6 +6,7 @@ import GraphModal from "./GraphModal.vue";
import { downloadExcelByHref } from "@/util/downloadExcel";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { openToast, cancelToastOpen } = inject("app_toast");
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
const columns = computed(() => [
@ -43,8 +44,16 @@ const updateEditRecord = (data) => {
};
const delRecord = async (id) => {
const res = await delGraphData(id);
getData(parseInt(searchParams.value.id));
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
await cancelToastOpen();
const res = await delGraphData(id);
if (res.isSuccess) {
getData(parseInt(searchParams.value.id));
openToast("success", t("msg.delete_success"));
} else {
openToast("error", res.msg);
}
});
};
watch(

View File

@ -8,6 +8,7 @@ import {
import useSearchParam from "@/hooks/useSearchParam";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { openToast, cancelToastOpen } = inject("app_toast");
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
const { searchParams } = useSearchParam();
@ -25,15 +26,21 @@ const changeData = (record) => {
};
const deleteItem = async (id) => {
let res;
if (searchParams.value?.work_type < 3) {
res = await deleteOperationRecord(id);
} else {
res = await deleteOperationCompany(id);
}
if (res.isSuccess) {
search();
}
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
await cancelToastOpen();
let res;
if (searchParams.value?.work_type < 3) {
res = await deleteOperationRecord(id);
} else {
res = await deleteOperationCompany(id);
}
if (res.isSuccess) {
search();
openToast("success", t("msg.delete_success"));
} else {
openToast("error", res.msg);
}
});
};
</script>

View File

@ -56,7 +56,9 @@ const getData = async () => {
building_tag: buildingStore.selectedBuilding?.building_tag,
})
const devices = res.data.map(d => ({
...d, key: d.full_name, device_list: d.device_list.filter(({ device_coordinate_3d }) => device_coordinate_3d).map((dev, index) => ({
...d,
key: d.full_name,
device_list: d.device_list.map((dev, index) => ({
...dev,
forge_dbid: parseInt(dev.forge_dbid),
room_dbid: parseInt(dev.room_dbid),
@ -72,6 +74,7 @@ const getData = async () => {
raw_data.value = devices
data.value = devices
console.log("devices", res.data,devices)
}
const subscribeData = ref([]); // flat data