diff --git a/.env.development b/.env.development
index 6da8916..8988210 100644
--- a/.env.development
+++ b/.env.development
@@ -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"
\ No newline at end of file
diff --git a/.env.staging b/.env.staging
index 3a51cfe..3e57378 100644
--- a/.env.staging
+++ b/.env.staging
@@ -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"
\ No newline at end of file
+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"
\ No newline at end of file
diff --git a/package.json b/package.json
index abef3dc..7f18668 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/src/components/navbar/NavbarBuilding.vue b/src/components/navbar/NavbarBuilding.vue
index 7270901..e6198b1 100644
--- a/src/components/navbar/NavbarBuilding.vue
+++ b/src/components/navbar/NavbarBuilding.vue
@@ -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"
>
-
- {{ bui.full_name }}
-
+
+
+ {{ bui.full_name }}
+
+
-
\ No newline at end of file
+
diff --git a/src/stores/useBuildingStore.js b/src/stores/useBuildingStore.js
index 94d2787..a396bda 100644
--- a/src/stores/useBuildingStore.js
+++ b/src/stores/useBuildingStore.js
@@ -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(),
+ ]);
}
});
diff --git a/src/util/request.js b/src/util/request.js
index 9c3a0e6..b7cd089 100644
--- a/src/util/request.js
+++ b/src/util/request.js
@@ -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(
diff --git a/src/views/login/Login.vue b/src/views/login/Login.vue
index 8de3f15..0f1260d 100644
--- a/src/views/login/Login.vue
+++ b/src/views/login/Login.vue
@@ -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);