fix: 以 systemConfig 判斷 Dashboard 左上生產指標顯示
This commit is contained in:
parent
94568c3f86
commit
d88dfe3c85
@ -15,19 +15,22 @@ import useBuildingStore from "@/stores/useBuildingStore";
|
||||
import { getSystemDevices, getSystemRealTime } from "@/apis/system";
|
||||
import DashboardRefrig from "./components/DashboardRefrig.vue";
|
||||
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||
const buildingStore = useBuildingStore()
|
||||
const buildingStore = useBuildingStore();
|
||||
|
||||
const subscribeData = ref([]);
|
||||
const systemData = ref({});
|
||||
let intervalId = null;
|
||||
|
||||
const productVisible = ref(false); // 產品產量儀表是否顯示
|
||||
const productCompleteVisible = ref(false); // 今日達成率是否顯示
|
||||
|
||||
// 開始定時器
|
||||
const startInterval = () => {
|
||||
// 清除之前的定時器(如果存在)
|
||||
if (intervalId) {
|
||||
clearInterval(intervalId);
|
||||
}
|
||||
|
||||
|
||||
// 每5秒呼叫一次 getData
|
||||
intervalId = setInterval(() => {
|
||||
getData();
|
||||
@ -37,29 +40,32 @@ const startInterval = () => {
|
||||
const getData = async () => {
|
||||
const res = await getSystemDevices({
|
||||
building_guid: buildingStore.selectedBuilding?.building_guid,
|
||||
})
|
||||
});
|
||||
|
||||
subscribeData.value = res.data;
|
||||
console.log("devices", subscribeData.value);
|
||||
|
||||
subscribeData.value = res.data
|
||||
console.log("devices", subscribeData.value)
|
||||
|
||||
// 轉換資料格式
|
||||
const transformedData = {};
|
||||
|
||||
subscribeData.value.forEach(floor => {
|
||||
|
||||
subscribeData.value.forEach((floor) => {
|
||||
if (floor.device_list && floor.device_list.length > 0) {
|
||||
const fullUrl = floor.floor_map_name;
|
||||
const uuid = fullUrl ? fullUrl.replace(/\.svg$/, "") : "";
|
||||
transformedData[uuid] = floor.device_list.map(device => {
|
||||
transformedData[uuid] = floor.device_list.map((device) => {
|
||||
// 解析座標
|
||||
const coordinates = JSON.parse(device.device_coordinate || '[0,0]');
|
||||
const coordinates = JSON.parse(device.device_coordinate || "[0,0]");
|
||||
const x = coordinates[0];
|
||||
const y = coordinates[1];
|
||||
|
||||
|
||||
// 決定設備狀態和顏色
|
||||
let state = "Online";
|
||||
let bgColor = device.device_normal_color;
|
||||
|
||||
if (device.device_status === "Offline" || device.device_status === null) {
|
||||
|
||||
if (
|
||||
device.device_status === "Offline" ||
|
||||
device.device_status === null
|
||||
) {
|
||||
state = "Offline";
|
||||
bgColor = device.device_close_color;
|
||||
}
|
||||
@ -80,7 +86,9 @@ const getData = async () => {
|
||||
points: device.points || [],
|
||||
floor: floor.full_name,
|
||||
state: state,
|
||||
icon: device.device_image ? `${FILE_BASEURL}/upload/device_icon/${device.device_image}` : '',
|
||||
icon: device.device_image
|
||||
? `${FILE_BASEURL}/upload/device_icon/${device.device_image}`
|
||||
: "",
|
||||
bgColor: bgColor,
|
||||
Online_color: device.device_normal_color,
|
||||
Offline_color: device.device_close_color,
|
||||
@ -92,15 +100,15 @@ const getData = async () => {
|
||||
buying_date: device.buying_date,
|
||||
created_at: device.created_at,
|
||||
bgSize: 50,
|
||||
}
|
||||
},
|
||||
];
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
console.log("transformedData", transformedData);
|
||||
systemData.value = transformedData;
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => buildingStore.selectedBuilding,
|
||||
@ -111,7 +119,7 @@ watch(
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
@ -126,29 +134,38 @@ onUnmounted(() => {
|
||||
<template>
|
||||
<div class="flex flex-wrap justify-between">
|
||||
<div
|
||||
class="order-3 lg:order-1 w-full lg:w-1/4 h-full flex flex-col justify-start z-10 border-dashboard gap-5"
|
||||
class="order-3 lg:order-1 w-full lg:w-1/4 min-h-screen flex flex-col justify-start z-10 border-dashboard gap-5"
|
||||
>
|
||||
<div>
|
||||
<DashboardProduct />
|
||||
<!-- 無資料時:完整隱藏區塊,不留空白 -->
|
||||
<div class="mb-6">
|
||||
<DashboardProduct
|
||||
@visible-change="(v) => (productVisible = v)"
|
||||
v-show="productVisible"
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<DashboardProductComplete />
|
||||
<div class="mb-6">
|
||||
<DashboardProductComplete
|
||||
@visible-change="(v) => (productCompleteVisible = v)"
|
||||
v-show="productVisible"
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<div class="mb-6">
|
||||
<DashboardIndoor />
|
||||
</div>
|
||||
<div class="mt-10">
|
||||
|
||||
<div class="mb-10">
|
||||
<DashboardRefrig />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="order-1 lg:order-2 w-full lg:w-2/4 relative lg:static min-h-[300px] lg:h-full"
|
||||
>
|
||||
<DashboardFloorBar />
|
||||
<DashboardEffectScatter :data="systemData"/>
|
||||
<DashboardEffectScatter :data="systemData" />
|
||||
</div>
|
||||
<div class="order-2 w-full lg:hidden my-3">
|
||||
<DashboardSysCard :data="systemData"/>
|
||||
<div class="order-2 w-full lg:hidden my-3">
|
||||
<DashboardSysCard :data="systemData" />
|
||||
</div>
|
||||
<div
|
||||
class="order-last w-full lg:w-1/4 flex flex-col justify-start border-dashboard z-20 gap-5"
|
||||
|
@ -216,6 +216,7 @@ onUnmounted(() => {
|
||||
{{ $t("dashboard.no_data") }}
|
||||
</div>
|
||||
<LineChart
|
||||
v-if="!noData"
|
||||
id="dashboard_other_real_temp"
|
||||
class="min-h-[260px] max-h-fit"
|
||||
:option="defaultChartOption"
|
||||
|
@ -1,8 +1,54 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import GaugeChart from "@/components/chart/GaugeChart.vue";
|
||||
import { CHART_COLOR, SECOND_CHART_COLOR } from "@/constant";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
|
||||
const buildingStore = useBuildingStore();
|
||||
const visible = ref(false); // 改用整體顯示/隱藏
|
||||
|
||||
const emit = defineEmits(["visible-change"]);
|
||||
|
||||
// 監聽 guid,取 sysConfig 後判斷顯示
|
||||
watch(
|
||||
() => buildingStore.selectedBuilding?.building_guid,
|
||||
async (guid) => {
|
||||
if (!guid) {
|
||||
visible.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
await buildingStore.getSysConfig(guid);
|
||||
|
||||
// 與檔案一一致:先嘗試 .value,再嘗試非 .value(相容 ref/reactive)
|
||||
const cfg = buildingStore.sysConfig?.value ?? buildingStore.sysConfig;
|
||||
const showIndicator = !!cfg?.show_production_indicator;
|
||||
|
||||
console.log("[DashboardProduct] guid:", guid);
|
||||
console.log("[DashboardProduct] sysConfig:", cfg);
|
||||
console.log("[DashboardProduct] show_production_indicator:", showIndicator);
|
||||
|
||||
if (showIndicator === false) {
|
||||
visible.value = false; // 整個元件不顯示
|
||||
return;
|
||||
}
|
||||
|
||||
// 允許顯示整個元件
|
||||
visible.value = true;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 把 visible 變化回報給父層(立刻、且每次變動)
|
||||
watch(
|
||||
visible,
|
||||
(v) => {
|
||||
emit("visible-change", v);
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 圖表設定
|
||||
const sameOptionAttr = {
|
||||
type: "gauge",
|
||||
center: ["50%", "60%"],
|
||||
@ -119,10 +165,12 @@ onMounted(() => {
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<!-- 僅在 show_production_indicator === true 時渲染整個元件 -->
|
||||
<div v-if="visible">
|
||||
<h3 class="text-info text-xl text-center mb-3">
|
||||
{{ $t("dashboard.production_quantity") }}
|
||||
</h3>
|
||||
|
||||
<div class="w-full grid grid-cols-3">
|
||||
<div>
|
||||
<GaugeChart
|
||||
@ -150,6 +198,7 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- shouldShow 為 null 或 false 時都不顯示任何東西(避免閃動與空白框) -->
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
@ -1,7 +1,48 @@
|
||||
<script setup>
|
||||
import useActiveBtn from "@/hooks/useActiveBtn";
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import DashboardProductCompleteModal from "./DashboardProductCompleteModal.vue";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
|
||||
const buildingStore = useBuildingStore();
|
||||
const visible = ref(false); // 整體顯示/隱藏
|
||||
|
||||
const emit = defineEmits(["visible-change"]);
|
||||
|
||||
// 監聽 guid → 取 sysConfig → 用 show_production_indicator 控制顯示
|
||||
watch(
|
||||
() => buildingStore.selectedBuilding?.building_guid,
|
||||
async (guid) => {
|
||||
if (!guid) {
|
||||
visible.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
await buildingStore.getSysConfig(guid);
|
||||
|
||||
// 相容 ref/reactive 的讀法(避免 .value 混亂)
|
||||
const cfg = buildingStore.sysConfig?.value ?? buildingStore.sysConfig;
|
||||
const flag = !!cfg?.show_production_indicator;
|
||||
|
||||
// 若需要除錯可開啟:
|
||||
// console.log("[DashboardProductRate] guid:", guid);
|
||||
// console.log("[DashboardProductRate] sysConfig:", cfg);
|
||||
// console.log("[DashboardProductRate] show_production_indicator:", flag);
|
||||
|
||||
visible.value = flag;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 把 visible 變化回報給父層(立刻、且每次變動)
|
||||
watch(
|
||||
visible,
|
||||
(v) => {
|
||||
emit("visible-change", v);
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
|
||||
const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
|
||||
|
||||
@ -44,54 +85,57 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DashboardProductCompleteModal />
|
||||
<div class="mb-3 relative">
|
||||
<h3 class="text-info text-xl text-center">
|
||||
{{ $t("dashboard.today_production_rate") }} (%)
|
||||
</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-xs btn-success absolute top-0 right-0"
|
||||
@click.stop="openModal"
|
||||
>
|
||||
{{ $t("button.edit") }}
|
||||
</button>
|
||||
</div>
|
||||
<div className="my-3 w-full flex justify-center relative">
|
||||
<ButtonConnectedGroup
|
||||
:items="items"
|
||||
:onclick="
|
||||
(e, item) => {
|
||||
changeActiveBtn(item);
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<template
|
||||
v-if="progress_data && selectedBtn && progress_data[selectedBtn.key - 1]"
|
||||
>
|
||||
<div
|
||||
class="grid grid-cols-6 gap-3 justify-items-end items-center"
|
||||
v-for="{ pac, value, target, percentage } in progress_data[
|
||||
selectedBtn.key - 1
|
||||
].data"
|
||||
:key="pac"
|
||||
>
|
||||
<span class="col-span-1 text-lg">{{ pac }}</span>
|
||||
<progress
|
||||
v-if="target !== 0"
|
||||
class="progress progress-info col-span-4"
|
||||
:value="value"
|
||||
:max="target"
|
||||
></progress>
|
||||
<span class="col-span-1 text-lg justify-self-start"
|
||||
>{{ percentage }} %</span
|
||||
<!-- 依 show_production_indicator 控制整個元件顯示 -->
|
||||
<div v-if="visible">
|
||||
<DashboardProductCompleteModal />
|
||||
<div class="mb-3 relative">
|
||||
<h3 class="text-info text-xl text-center">
|
||||
{{ $t("dashboard.today_production_rate") }} (%)
|
||||
</h3>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-xs btn-success absolute top-0 right-0"
|
||||
@click.stop="openModal"
|
||||
>
|
||||
{{ $t("button.edit") }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p class="text-center mt-8 text-lg">尚未設定目標值</p>
|
||||
</template>
|
||||
<div className="my-3 w-full flex justify-center relative">
|
||||
<ButtonConnectedGroup
|
||||
:items="items"
|
||||
:onclick="
|
||||
(e, item) => {
|
||||
changeActiveBtn(item);
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<template
|
||||
v-if="progress_data && selectedBtn && progress_data[selectedBtn.key - 1]"
|
||||
>
|
||||
<div
|
||||
class="grid grid-cols-6 gap-3 justify-items-end items-center"
|
||||
v-for="{ pac, value, target, percentage } in progress_data[
|
||||
selectedBtn.key - 1
|
||||
].data"
|
||||
:key="pac"
|
||||
>
|
||||
<span class="col-span-1 text-lg">{{ pac }}</span>
|
||||
<progress
|
||||
v-if="target !== 0"
|
||||
class="progress progress-info col-span-4"
|
||||
:value="value"
|
||||
:max="target"
|
||||
></progress>
|
||||
<span class="col-span-1 text-lg justify-self-start"
|
||||
>{{ percentage }} %</span
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p class="text-center mt-8 text-lg">尚未設定目標值</p>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped></style>
|
||||
|
@ -218,10 +218,11 @@ onUnmounted(() => {
|
||||
{{ $t("dashboard.no_data") }}
|
||||
</div>
|
||||
<LineChart
|
||||
id="dashboard_refrigeration"
|
||||
v-if="!noData"
|
||||
id="dashboard_other_real_temp"
|
||||
class="min-h-[260px] max-h-fit"
|
||||
:option="defaultChartOption"
|
||||
ref="other_real_temp_chart"
|
||||
ref="indoorChartRef"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user