棟別設置
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_FILE_API_BASEURL = "https://cgems.cvilux-group.com:8088"
|
||||||
VITE_MQTT_BASEURL = "wss://mqttwss.mjm-staging.developers-homelab.net"
|
VITE_MQTT_BASEURL = "wss://mqttwss.mjm-staging.developers-homelab.net"
|
||||||
VITE_FORGE_BASEURL = "https://cgems.cvilux-group.com:8088/dist"
|
VITE_FORGE_BASEURL = "https://cgems.cvilux-group.com:8088/dist"
|
@ -1,3 +1,3 @@
|
|||||||
VITE_API_BASEURL = "http://220.132.206.5:8008"
|
VITE_API_BASEURL = "https://ibms-cvilux-demo-api.production.mjmtech.com.tw"
|
||||||
VITE_FILE_API_BASEURL = "http://220.132.206.5:8085/file"
|
VITE_FILE_API_BASEURL = "https://cgems.cvilux-group.com:8088"
|
||||||
VITE_FORGE_BASEURL = "http://localhost:5173"
|
VITE_MQTT_BASEURL = "wss://mqttwss.mjm-staging.developers-homelab.net"
|
@ -6,7 +6,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"build:staging": "vite build --mode staging"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons-vue": "^7.0.1",
|
"@ant-design/icons-vue": "^7.0.1",
|
||||||
|
@ -6,7 +6,6 @@ const store = useBuildingStore();
|
|||||||
|
|
||||||
const selectBuilding = (bui) => {
|
const selectBuilding = (bui) => {
|
||||||
store.selectedBuilding = bui; // 改變 selectedBuilding,watch 會自動更新資料
|
store.selectedBuilding = bui; // 改變 selectedBuilding,watch 會自動更新資料
|
||||||
localStorage.setItem("CviBuilding", JSON.stringify(bui));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@ -28,14 +27,16 @@ onMounted(() => {
|
|||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="dropdown-content w-48 left-8 translate-y-2 z-[1] menu py-3 shadow rounded bg-[#4c625e] border text-center"
|
class="dropdown-content w-48 left-8 translate-y-2 z-[1] menu py-3 shadow rounded bg-[#4c625e] border text-center"
|
||||||
>
|
>
|
||||||
<li
|
<template v-if="store.buildings.length > 0">
|
||||||
class="text-white my-1 text-base cursor-pointer"
|
<li
|
||||||
v-for="bui in store.buildings"
|
class="text-white my-1 text-base cursor-pointer"
|
||||||
:key="bui.building_tag"
|
v-for="bui in store.buildings"
|
||||||
@click="selectBuilding(bui)"
|
:key="bui.building_tag"
|
||||||
>
|
@click="selectBuilding(bui)"
|
||||||
{{ bui.full_name }}
|
>
|
||||||
</li>
|
{{ bui.full_name }}
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -45,38 +45,46 @@ const useBuildingStore = defineStore("buildingInfo", () => {
|
|||||||
|
|
||||||
// 獲取所有建築物
|
// 獲取所有建築物
|
||||||
const fetchBuildings = async () => {
|
const fetchBuildings = async () => {
|
||||||
const res = await getBuildings();
|
// const res = await getBuildings();
|
||||||
buildings.value = res.data;
|
buildings.value = JSON.parse(localStorage.getItem("CviBuildingList")) || [];
|
||||||
if (res.data.length > 0 && !selectedBuilding.value) {
|
const storedBuilding = JSON.parse(localStorage.getItem("CviBuilding"));
|
||||||
const storedBuilding = JSON.parse(localStorage.getItem("CviBuilding"));
|
if (buildings.value.length > 0) {
|
||||||
selectedBuilding.value = storedBuilding || res.data[0]; // 預設選第一個建築
|
selectedBuilding.value = storedBuilding || buildings.value[0]; // 預設選第一個建築
|
||||||
|
} else {
|
||||||
|
selectedBuilding.value = null; // 如果沒有建築物,清空選擇
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 獲取樓層資料
|
// 獲取樓層資料
|
||||||
const fetchFloorList = async (building_guid) => {
|
const fetchFloorList = async (building_guid) => {
|
||||||
const res = await getAssetFloorList(building_guid);
|
const res = await getAssetFloorList(building_guid);
|
||||||
floorList.value = res.data[0]?.floors.map((d) => ({
|
floorList.value =
|
||||||
...d,
|
res.data[0]?.floors.map((d) => ({
|
||||||
title: d.full_name,
|
...d,
|
||||||
key: d.floor_guid,
|
title: d.full_name,
|
||||||
})) || [];
|
key: d.floor_guid,
|
||||||
|
})) || [];
|
||||||
};
|
};
|
||||||
|
|
||||||
// 獲取部門資料
|
// 獲取部門資料
|
||||||
const fetchDepartmentList = async () => {
|
const fetchDepartmentList = async () => {
|
||||||
const res = await getDepartmentList();
|
const res = await getDepartmentList();
|
||||||
deptList.value = res.data.map((d) => ({
|
deptList.value =
|
||||||
...d,
|
res.data.map((d) => ({
|
||||||
title: d.name,
|
...d,
|
||||||
key: d.id,
|
title: d.name,
|
||||||
})) || [];
|
key: d.id,
|
||||||
|
})) || [];
|
||||||
};
|
};
|
||||||
|
|
||||||
// 當 selectedBuilding 改變時,更新 floorList 和 deptList
|
// 當 selectedBuilding 改變時,更新 floorList 和 deptList
|
||||||
watch(selectedBuilding, async (newBuilding) => {
|
watch(selectedBuilding, async (newBuilding) => {
|
||||||
if (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";
|
import axios from "axios";
|
||||||
const BASEURL = import.meta.env.VITE_API_BASEURL;
|
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({
|
const instance = axios.create({
|
||||||
baseURL: BASEURL,
|
baseURL: BASEURL,
|
||||||
timeout: -1,
|
timeout: 10000, // 建議設定超時
|
||||||
headers: { Authorization: `Bearer ${useGetCookie("JWT-Authorization")}` },
|
// 移除靜態 headers
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add a request interceptor
|
// 使用共用的攔截器
|
||||||
instance.interceptors.request.use(
|
instance.interceptors.request.use(requestInterceptor, requestErrorInterceptor);
|
||||||
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);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add a response interceptor
|
// Add a response interceptor
|
||||||
instance.interceptors.response.use(
|
instance.interceptors.response.use(
|
||||||
function (response) {
|
function (response) {
|
||||||
// Any status code that lie within the range of 2xx cause this function to trigger
|
// Any status code that lie within the range of 2xx cause this function to trigger
|
||||||
// Do something with response data
|
// Do something with response data
|
||||||
const { status, data, headers } = response;
|
const { data } = response;
|
||||||
|
|
||||||
return {
|
return { ...data };
|
||||||
...data,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
// Any status codes that falls outside the range of 2xx cause this function to trigger
|
// 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({
|
export const fileInstance = axios.create({
|
||||||
baseURL: BASEURL,
|
baseURL: BASEURL,
|
||||||
timeout: -1,
|
timeout: -1,
|
||||||
headers: { Authorization: `Bearer ${useGetCookie("JWT-Authorization")}` },
|
// 移除靜態 headers
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add a request interceptor
|
// 使用共用的攔截器
|
||||||
fileInstance.interceptors.request.use(
|
fileInstance.interceptors.request.use(requestInterceptor, requestErrorInterceptor);
|
||||||
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);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add a response interceptor
|
// Add a response interceptor
|
||||||
fileInstance.interceptors.response.use(
|
fileInstance.interceptors.response.use(
|
||||||
|
@ -6,10 +6,12 @@ import * as yup from "yup";
|
|||||||
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import useUserInfoStore from "@/stores/useUserInfoStore";
|
import useUserInfoStore from "@/stores/useUserInfoStore";
|
||||||
|
import useBuildingStore from "@/stores/useBuildingStore";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openToast } = inject("app_toast");
|
const { openToast } = inject("app_toast");
|
||||||
const store = useUserInfoStore();
|
const store = useUserInfoStore();
|
||||||
|
const storeBuild = useBuildingStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
let schema = yup.object({
|
let schema = yup.object({
|
||||||
@ -35,6 +37,7 @@ const doLogin = async () => {
|
|||||||
const res = await Login(value);
|
const res = await Login(value);
|
||||||
if (res.isSuccess) {
|
if (res.isSuccess) {
|
||||||
store.user = res.data;
|
store.user = res.data;
|
||||||
|
localStorage.setItem("CviBuildingList", JSON.stringify(res.data.buildingIdList));
|
||||||
router.replace({ path: "/dashboard" });
|
router.replace({ path: "/dashboard" });
|
||||||
} else {
|
} else {
|
||||||
openToast("error", res.msg);
|
openToast("error", res.msg);
|
||||||
|
Loading…
Reference in New Issue
Block a user