新增回到首頁按鈕 | 優化視角設定邏輯 | 調整權限清除邏輯 | 更新庫存顯示邏輯

This commit is contained in:
koko 2025-10-13 14:06:14 +08:00
parent 2948a95b56
commit a002901d26
11 changed files with 91 additions and 34 deletions

View File

@ -39,6 +39,7 @@ const {
subComponents, subComponents,
clearSprites, clearSprites,
updateTemp, updateTemp,
fitToView,
} = useSystemStatusByBaja(); } = useSystemStatusByBaja();
// meter label 2D // meter label 2D
@ -182,6 +183,28 @@ onUnmounted(() => {
) )
" "
> >
<!-- 回到 Home 視角 -->
<div class="absolute top-0 right-[26%] z-30">
<button
class="p-4"
@click="fitToView()"
aria-label="回到初始視角"
title="回到初始視角"
>
<!-- Home Icon -->
<svg
xmlns="http://www.w3.org/2000/svg"
width="25"
height="25"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="m21.743 12.331l-9-10c-.379-.422-1.107-.422-1.486 0l-9 10a1 1 0 0 0-.17 1.076c.16.361.518.593.913.593h2v7a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-4h4v4a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-7h2a.998.998 0 0 0 .743-1.669"
/>
</svg>
</button>
</div>
<p class="absolute z-10 top-14 left-[27%]"> <p class="absolute z-10 top-14 left-[27%]">
更新時間 : {{ props.realTime }} 更新時間 : {{ props.realTime }}
</p> </p>
@ -246,7 +269,7 @@ onUnmounted(() => {
} }
.homeViewWrapper { .homeViewWrapper {
transform: scale(1.5) translateX(350%) translateY(0%) !important; display: none !important;
} }
.heatbar { .heatbar {

View File

@ -141,6 +141,8 @@ export default function useSystemStatusByBaja() {
} = JSON.parse(searchParams.value.target_position); } = JSON.parse(searchParams.value.target_position);
const newTarget = new THREE.Vector3(x1, y1, z1); const newTarget = new THREE.Vector3(x1, y1, z1);
forgeViewer.value.navigation.setView(newPosition, newTarget); forgeViewer.value.navigation.setView(newPosition, newTarget);
// 強制 up vector 為 Z 軸朝上,確保視角水平
forgeViewer.value.navigation.setCameraUpVector(new THREE.Vector3(0, 0, 1));
}; };
const hideAllObjects = (instanceTree, filDbids = []) => { const hideAllObjects = (instanceTree, filDbids = []) => {
@ -497,5 +499,6 @@ export default function useSystemStatusByBaja() {
clearSprites, clearSprites,
clearSingleSprite, clearSingleSprite,
updateTemp, updateTemp,
fitToView,
}; };
} }

View File

@ -88,16 +88,19 @@ router.beforeEach(async (to, from, next) => {
if (location.pathname.includes("logoutConfirm")) { if (location.pathname.includes("logoutConfirm")) {
document.cookie = "JWT-Authorization="; document.cookie = "JWT-Authorization=";
auth.user.token = ""; auth.user.token = "";
auth.clearAuthPage && auth.clearAuthPage();
// 清除 cookie token // 清除 cookie token
next({ path: "/login" }); next({ path: "/login" });
} }
if ((authRequired && !token) || to.path === "/") { if ((authRequired && !token) || to.path === "/") {
auth.user.token = ""; auth.user.token = "";
auth.clearAuthPage && auth.clearAuthPage();
next({ path: "/login" }); next({ path: "/login" });
} else if (!authRequired) { } else if (!authRequired) {
document.cookie = "JWT-Authorization="; document.cookie = "JWT-Authorization=";
auth.user.token = ""; auth.user.token = "";
auth.clearAuthPage && auth.clearAuthPage();
} else { } else {
auth.user.token = token; auth.user.token = token;
} }

View File

@ -1,18 +1,32 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { ref } from "vue"; import { ref } from "vue";
const AUTH_PAGE_KEY = "pccv_auth_page";
const useUserInfoStore = defineStore("userInfo", () => { const useUserInfoStore = defineStore("userInfo", () => {
const user = ref({ const user = ref({
token: "", token: "",
expires: 0, expires: 0,
}); });
const auth_page = ref([]); // 初始化時從 sessionStorage 載入
const storedAuthPage = sessionStorage.getItem(AUTH_PAGE_KEY);
const auth_page = ref(storedAuthPage ? JSON.parse(storedAuthPage) : []);
const updateAuthPage = (data) => { const updateAuthPage = (data) => {
auth_page.value = data; auth_page.value = data;
sessionStorage.setItem(AUTH_PAGE_KEY, JSON.stringify(data));
}; };
return { user, auth_page, updateAuthPage }; // 提供一個清除權限的方法(例如登出時用)
const clearAuthPage = () => {
auth_page.value = [];
sessionStorage.removeItem(AUTH_PAGE_KEY);
};
return { user, auth_page, updateAuthPage, clearAuthPage };
}); });
export default useUserInfoStore; export default useUserInfoStore;

View File

@ -1,8 +1,16 @@
<template> <template>
<div class="card rounded-md bg-neutral text-neutral-content shadow-sm shadow-gray-400"> <div class="card rounded-md bg-neutral text-neutral-content shadow-sm shadow-gray-400">
<div class="card-body text-xs px-1 py-2"> <div class="card-body text-xs px-1 py-2">
<p>安全存量: {{ safety_stock }} </p> <p>備註: {{
<p>目前存量: {{ current_stock }} </p> item_id === 1
? ""
: item_id === 2
? "1、2、5、6槽"
: item_id === 3
? "3、4槽"
: "其他"
}} </p>
<p>最大存量: {{ current_stock }} </p>
<p>{{ updateTime }}</p> <p>{{ updateTime }}</p>
</div> </div>
</div> </div>
@ -10,7 +18,7 @@
<script setup> <script setup>
defineProps({ defineProps({
safety_stock: { item_id: {
type: Number, type: Number,
required: true, required: true,
}, },

View File

@ -14,7 +14,7 @@ const getCompletion = async () => {
title: item.name, title: item.name,
percentage: item.percentage, percentage: item.percentage,
current_stock: item.current_stock, current_stock: item.current_stock,
safety_stock: item.safety_stock, item_id: item.item_id,
updateTime: dayjs(item.updated_at).format("YYYY-MM-DD HH:mm:ss"), updateTime: dayjs(item.updated_at).format("YYYY-MM-DD HH:mm:ss"),
})); }));
}; };
@ -47,7 +47,7 @@ onMounted(() => {
v-for="(card, index) in descriptionCards" v-for="(card, index) in descriptionCards"
:key="index" :key="index"
:title="card.title" :title="card.title"
:safety_stock="card.safety_stock" :item_id="card.item_id"
:current_stock="card.current_stock" :current_stock="card.current_stock"
:updateTime="card.updateTime" :updateTime="card.updateTime"
/> />

View File

@ -59,7 +59,7 @@ import { twMerge } from "tailwind-merge";
:class=" :class="
twMerge( twMerge(
'text-2xl border-2 border-slate-400 rounded-full', 'text-2xl border-2 border-slate-400 rounded-full',
item.qcResult ? item.qcResult.trim() : 'text-slate-400' typeof item.qcResult === 'string' ? item.qcResult.trim() : 'text-slate-400'
) )
" "
/> />

View File

@ -154,11 +154,11 @@ watch(searchParams, (newVal, oldValue) => {
key: 1, key: 1,
active: parseInt(newVal?.Cumulant) === 1, active: parseInt(newVal?.Cumulant) === 1,
}, },
{ // {
title: "累積數據", // title: "",
key: 2, // key: 2,
active: parseInt(newVal?.Cumulant) === 2, // active: parseInt(newVal?.Cumulant) === 2,
}, // },
]); ]);
} }
}); });
@ -180,13 +180,13 @@ onMounted(() => {
? parseInt(searchParams.value.Cumulant) === 1 ? parseInt(searchParams.value.Cumulant) === 1
: true, : true,
}, },
{ // {
title: "累積數據", // title: "",
key: 2, // key: 2,
active: searchParams.value.Cumulant // active: searchParams.value.Cumulant
? parseInt(searchParams.value.Cumulant) === 2 // ? parseInt(searchParams.value.Cumulant) === 2
: false, // : false,
}, // },
]); ]);
}); });

View File

@ -12,8 +12,8 @@ const columns = [
title: "設備名稱", title: "設備名稱",
key: "device_name", key: "device_name",
width: "30%", width: "30%",
filter: true, // filter: true,
sort: true, // sort: true,
}, },
{ {
title: "點位", title: "點位",
@ -22,8 +22,8 @@ const columns = [
{ {
title: "數值", title: "數值",
key: "value", key: "value",
sort: true, // sort: true,
filter: true, // filter: true,
}, },
{ {
title: "記錄時間", title: "記錄時間",

View File

@ -15,7 +15,7 @@ const emit = defineEmits(["pushData", "resetModalForm"]);
const settingScheme = yup.object({ const settingScheme = yup.object({
total_capacity: yup.number().required("必填").min(0, "不能小於0"), total_capacity: yup.number().required("必填").min(0, "不能小於0"),
safety_stock: yup.number().required("必填").min(0, "不能小於0"), // safety_stock: yup.number().required("").min(0, "0"),
current_stock: yup.number().required("必填").min(0, "不能小於0"), current_stock: yup.number().required("必填").min(0, "不能小於0"),
}); });
@ -70,7 +70,7 @@ const onOk = async () => {
}}</span> }}</span>
</template> </template>
</Input> </Input>
<Input <!-- <Input
:value="formState" :value="formState"
class="my-2" class="my-2"
name="safety_stock" name="safety_stock"
@ -82,9 +82,15 @@ const onOk = async () => {
formErrorMsg.safety_stock formErrorMsg.safety_stock
}}</span> }}</span>
</template> </template>
</Input> </Input> -->
<Input :value="formState" class="my-2" name="current_stock"> <Input :value="formState" class="my-2" name="current_stock">
<template #topLeft>{{formState?.type == 1 ? "目前存量" : "入庫量"}}</template> <template #topLeft>{{
formState?.type == 1
? "每周盤點量"
: formState?.item_id == 1
? "本周醱酵量"
: "每日過濾量"
}}</template>
<template #bottomLeft> <template #bottomLeft>
<span class="text-error text-base">{{ <span class="text-error text-base">{{
formErrorMsg.current_stock formErrorMsg.current_stock

View File

@ -16,8 +16,8 @@ const { openToast } = inject("app_toast");
const settingColumns = [ const settingColumns = [
{ title: "項目", key: "name" }, { title: "項目", key: "name" },
{ title: "總庫存量(噸)", key: "total_capacity" }, { title: "總庫存量(噸)", key: "total_capacity" },
{ title: "安全存量(噸)", key: "safety_stock" }, // { title: "()", key: "safety_stock" },
{ title: "目前存量(噸)", key: "current_stock" }, { title: "每周盤點量(噸)", key: "current_stock" },
{ title: "更新時間", key: "updated_at" }, { title: "更新時間", key: "updated_at" },
{ title: "功能", key: "operation" }, { title: "功能", key: "operation" },
]; ];
@ -25,8 +25,8 @@ const settingColumns = [
const recordColumns = [ const recordColumns = [
{ title: "項目", key: "item_name", filter: true }, { title: "項目", key: "item_name", filter: true },
{ title: "總庫存量(噸)", key: "total_capacity" }, { title: "總庫存量(噸)", key: "total_capacity" },
{ title: "安全存量(噸)", key: "safety_stock" }, // { title: "()", key: "safety_stock" },
{ title: "目前存量(噸)", key: "current_stock" }, { title: "每周盤點量(噸)", key: "current_stock" },
{ title: "操作類型", key: "type" }, { title: "操作類型", key: "type" },
{ title: "最後修改者", key: "user_name", filter: true }, { title: "最後修改者", key: "user_name", filter: true },
{ title: "日期", key: "time", sort: true }, { title: "日期", key: "time", sort: true },
@ -113,7 +113,7 @@ const openModal = (type, item_id, record) => {
item_id: item_id, item_id: item_id,
name: record.name, name: record.name,
total_capacity: record.total_capacity, total_capacity: record.total_capacity,
safety_stock: record.safety_stock, // safety_stock: record.safety_stock,
current_stock: record.current_stock, current_stock: record.current_stock,
}; };
} else { } else {