棟別設置
This commit is contained in:
parent
14e3f9ea4a
commit
f0e9d7fda6
@ -1,4 +1,4 @@
|
||||
VITE_API_BASEURL = "https://ibms-cvilux-api.production.mjmtech.com.tw"
|
||||
VITE_API_BASEURL = "https://ibms-cvilux-demo-api.production.mjmtech.com.tw"
|
||||
VITE_FILE_API_BASEURL = "https://cgems.cvilux-group.com:8088"
|
||||
VITE_MQTT_BASEURL = "wss://mqttwss.mjm-staging.developers-homelab.net"
|
||||
VITE_FORGE_BASEURL = "https://cgems.cvilux-group.com:8088/dist"
|
@ -1,3 +1,3 @@
|
||||
VITE_API_BASEURL = "http://220.132.206.5:8008"
|
||||
VITE_FILE_API_BASEURL = "http://220.132.206.5:8085/file"
|
||||
VITE_FORGE_BASEURL = "http://localhost:5173"
|
||||
VITE_API_BASEURL = "https://ibms-cvilux-demo-api.production.mjmtech.com.tw"
|
||||
VITE_FILE_API_BASEURL = "https://cgems.cvilux-group.com:8088"
|
||||
VITE_MQTT_BASEURL = "wss://mqttwss.mjm-staging.developers-homelab.net"
|
@ -6,7 +6,8 @@
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"build:staging": "vite build --mode staging"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
|
@ -6,7 +6,6 @@ const store = useBuildingStore();
|
||||
|
||||
const selectBuilding = (bui) => {
|
||||
store.selectedBuilding = bui; // 改變 selectedBuilding,watch 會自動更新資料
|
||||
localStorage.setItem("CviBuilding", JSON.stringify(bui));
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
@ -28,16 +27,18 @@ onMounted(() => {
|
||||
tabindex="0"
|
||||
class="dropdown-content w-48 left-8 translate-y-2 z-[1] menu py-3 shadow rounded bg-[#4c625e] border text-center"
|
||||
>
|
||||
<li
|
||||
class="text-white my-1 text-base cursor-pointer"
|
||||
v-for="bui in store.buildings"
|
||||
:key="bui.building_tag"
|
||||
@click="selectBuilding(bui)"
|
||||
>
|
||||
{{ bui.full_name }}
|
||||
</li>
|
||||
<template v-if="store.buildings.length > 0">
|
||||
<li
|
||||
class="text-white my-1 text-base cursor-pointer"
|
||||
v-for="bui in store.buildings"
|
||||
:key="bui.building_tag"
|
||||
@click="selectBuilding(bui)"
|
||||
>
|
||||
{{ bui.full_name }}
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
@ -45,38 +45,46 @@ const useBuildingStore = defineStore("buildingInfo", () => {
|
||||
|
||||
// 獲取所有建築物
|
||||
const fetchBuildings = async () => {
|
||||
const res = await getBuildings();
|
||||
buildings.value = res.data;
|
||||
if (res.data.length > 0 && !selectedBuilding.value) {
|
||||
const storedBuilding = JSON.parse(localStorage.getItem("CviBuilding"));
|
||||
selectedBuilding.value = storedBuilding || res.data[0]; // 預設選第一個建築
|
||||
// const res = await getBuildings();
|
||||
buildings.value = JSON.parse(localStorage.getItem("CviBuildingList")) || [];
|
||||
const storedBuilding = JSON.parse(localStorage.getItem("CviBuilding"));
|
||||
if (buildings.value.length > 0) {
|
||||
selectedBuilding.value = storedBuilding || buildings.value[0]; // 預設選第一個建築
|
||||
} else {
|
||||
selectedBuilding.value = null; // 如果沒有建築物,清空選擇
|
||||
}
|
||||
};
|
||||
|
||||
// 獲取樓層資料
|
||||
const fetchFloorList = async (building_guid) => {
|
||||
const res = await getAssetFloorList(building_guid);
|
||||
floorList.value = res.data[0]?.floors.map((d) => ({
|
||||
...d,
|
||||
title: d.full_name,
|
||||
key: d.floor_guid,
|
||||
})) || [];
|
||||
floorList.value =
|
||||
res.data[0]?.floors.map((d) => ({
|
||||
...d,
|
||||
title: d.full_name,
|
||||
key: d.floor_guid,
|
||||
})) || [];
|
||||
};
|
||||
|
||||
// 獲取部門資料
|
||||
const fetchDepartmentList = async () => {
|
||||
const res = await getDepartmentList();
|
||||
deptList.value = res.data.map((d) => ({
|
||||
...d,
|
||||
title: d.name,
|
||||
key: d.id,
|
||||
})) || [];
|
||||
deptList.value =
|
||||
res.data.map((d) => ({
|
||||
...d,
|
||||
title: d.name,
|
||||
key: d.id,
|
||||
})) || [];
|
||||
};
|
||||
|
||||
// 當 selectedBuilding 改變時,更新 floorList 和 deptList
|
||||
watch(selectedBuilding, async (newBuilding) => {
|
||||
if (newBuilding) {
|
||||
await Promise.all([fetchFloorList(newBuilding.building_guid), fetchDepartmentList()]);
|
||||
localStorage.setItem("CviBuilding", JSON.stringify(newBuilding))
|
||||
await Promise.all([
|
||||
fetchFloorList(newBuilding.building_guid),
|
||||
fetchDepartmentList(),
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -2,38 +2,59 @@ import useGetCookie from "@/hooks/useGetCookie";
|
||||
import axios from "axios";
|
||||
const BASEURL = import.meta.env.VITE_API_BASEURL;
|
||||
|
||||
// --- 請求攔截器的共用邏輯 ---
|
||||
const requestInterceptor = (config) => {
|
||||
// 確保 headers 物件存在
|
||||
if (!config.headers) {
|
||||
config.headers = {};
|
||||
}
|
||||
|
||||
// 1. 取得並附加最新的 Token
|
||||
const token = useGetCookie("JWT-Authorization");
|
||||
if (token) {
|
||||
// 正確做法:修改屬性,而不是覆蓋整個物件
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
// 2. 取得並附加選定的建築物 GUID
|
||||
const storedBuilding = localStorage.getItem("CviBuilding");
|
||||
if (storedBuilding) {
|
||||
try {
|
||||
const buildingObject = JSON.parse(storedBuilding);
|
||||
if (buildingObject && buildingObject.building_guid) {
|
||||
// 與後端約定好要用哪個標頭,這裡使用 'X-Building-GUID' 作為範例
|
||||
config.headers["X-Building-GUID"] = buildingObject.building_guid;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("解析 localStorage 中的 CviBuilding 失敗:", e);
|
||||
}
|
||||
}
|
||||
return config;
|
||||
};
|
||||
|
||||
const requestErrorInterceptor = (error) => {
|
||||
return Promise.reject(error);
|
||||
};
|
||||
|
||||
|
||||
// --- 一般 API 實例 ---
|
||||
const instance = axios.create({
|
||||
baseURL: BASEURL,
|
||||
timeout: -1,
|
||||
headers: { Authorization: `Bearer ${useGetCookie("JWT-Authorization")}` },
|
||||
timeout: 10000, // 建議設定超時
|
||||
// 移除靜態 headers
|
||||
});
|
||||
|
||||
// Add a request interceptor
|
||||
instance.interceptors.request.use(
|
||||
function (config) {
|
||||
// Do something before request is sent
|
||||
const token = useGetCookie("JWT-Authorization");
|
||||
config.headers = {
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
return config;
|
||||
},
|
||||
function (error) {
|
||||
// Do something with request error
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
// 使用共用的攔截器
|
||||
instance.interceptors.request.use(requestInterceptor, requestErrorInterceptor);
|
||||
|
||||
// Add a response interceptor
|
||||
instance.interceptors.response.use(
|
||||
function (response) {
|
||||
// Any status code that lie within the range of 2xx cause this function to trigger
|
||||
// Do something with response data
|
||||
const { status, data, headers } = response;
|
||||
const { data } = response;
|
||||
|
||||
return {
|
||||
...data,
|
||||
};
|
||||
return { ...data };
|
||||
},
|
||||
function (error) {
|
||||
// Any status codes that falls outside the range of 2xx cause this function to trigger
|
||||
@ -45,27 +66,16 @@ instance.interceptors.response.use(
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// --- 檔案處理 API 實例 ---
|
||||
export const fileInstance = axios.create({
|
||||
baseURL: BASEURL,
|
||||
timeout: -1,
|
||||
headers: { Authorization: `Bearer ${useGetCookie("JWT-Authorization")}` },
|
||||
// 移除靜態 headers
|
||||
});
|
||||
|
||||
// Add a request interceptor
|
||||
fileInstance.interceptors.request.use(
|
||||
function (config) {
|
||||
// Do something before request is sent
|
||||
const token = useGetCookie("JWT-Authorization");
|
||||
config.headers = {
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
return config;
|
||||
},
|
||||
function (error) {
|
||||
// Do something with request error
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
// 使用共用的攔截器
|
||||
fileInstance.interceptors.request.use(requestInterceptor, requestErrorInterceptor);
|
||||
|
||||
// Add a response interceptor
|
||||
fileInstance.interceptors.response.use(
|
||||
|
@ -6,10 +6,12 @@ import * as yup from "yup";
|
||||
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||
import { useRouter } from "vue-router";
|
||||
import useUserInfoStore from "@/stores/useUserInfoStore";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
const { openToast } = inject("app_toast");
|
||||
const store = useUserInfoStore();
|
||||
const storeBuild = useBuildingStore();
|
||||
const router = useRouter();
|
||||
|
||||
let schema = yup.object({
|
||||
@ -35,6 +37,7 @@ const doLogin = async () => {
|
||||
const res = await Login(value);
|
||||
if (res.isSuccess) {
|
||||
store.user = res.data;
|
||||
localStorage.setItem("CviBuildingList", JSON.stringify(res.data.buildingIdList));
|
||||
router.replace({ path: "/dashboard" });
|
||||
} else {
|
||||
openToast("error", res.msg);
|
||||
|
Loading…
Reference in New Issue
Block a user