forge定位修改 | 運維大類小類搜尋、廠商非必填

This commit is contained in:
koko 2024-12-06 17:18:18 +08:00
parent 3d06cab696
commit d05f9ab130
9 changed files with 102 additions and 71 deletions

View File

@ -17,8 +17,8 @@ import instance from "@/util/request";
import apihandler from "@/util/apihandler";
import { object } from "yup";
export const getAssetSubList = async (variable_id) => {
const res = await instance.post(GET_ASSET_SUB_LIST_API, { variable_id });
export const getAssetSubList = async (id) => {
const res = await instance.post(GET_ASSET_SUB_LIST_API, { id });
return apihandler(res.code, res.data, {
msg: res.msg,

View File

@ -1,7 +1,7 @@
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
const forgeDom = ref(null);
let viewer = null;
@ -34,6 +34,20 @@ const initViewer = (container) => {
});
};
//
const setCameraPosition = (position, target) => {
const nav = viewer.navigation;
// 使 THREE.Vector3
const newPosition = new THREE.Vector3(position.x, position.y, position.z);
const newTarget = new THREE.Vector3(target.x, target.y, target.z);
//
nav.setView(newPosition, newTarget);
console.log("攝影機定位完成:");
console.log("新位置:", newPosition);
console.log("新焦點:", newTarget);
};
// 使 .svf
const loadModel = (filePath) => {
return new Promise((resolve, reject) => {
@ -43,6 +57,21 @@ const loadModel = (filePath) => {
(model) => {
viewer.impl.invalidate(true);
viewer.fitToView();
//
setTimeout(() => {
setCameraPosition(
{
x: -212.33421531428007,
y: 299.3895400707608,
z: 157.48711907404862,
}, //
{
x: 151.61159898775077,
y: -196.55136189609067,
z: -136.47282256290345,
} //
);
}, 500);
resolve(model);
console.log("模型加載完成");
},
@ -54,7 +83,7 @@ const loadModel = (filePath) => {
onMounted(async () => {
console.log("Forge 加載");
await initViewer(forgeDom.value);
const filePath = `${FILE_BASEURL}/upload/forge/0.svf`;
const filePath = `${FILE_BASEURL}/upload/forge/0.svf`;
loadModel(filePath);
});
@ -85,5 +114,4 @@ onUnmounted(() => {
display: none;
bottom: 200px;
}
</style>

View File

@ -30,7 +30,7 @@ const props = defineProps({
});
const store = useHeatmapBarStore();
const { updateDataVisualization, createSprites, showSubSystemObjects, forgeClickListener, clear } = useForgeSprite()
const { updateDataVisualization, createSprites, showSubSystemObjects, forgeClickListener, clear, setCameraPosition } = useForgeSprite()
const forgeDom = ref(null);
@ -80,6 +80,20 @@ const loadModel = (viewer, filePath) => {
(model) => {
viewer.impl.invalidate(true);
viewer.fitToView();
setTimeout(() => {
setCameraPosition(
{
x: 241.40975707867645,
y: -260.4481491801548,
z: 129.5719879121458,
}, //
{
x: -183.36302786348594,
y: 194.05657710941966,
z: -149.3902249981004,
} //
);
}, 500);
updateDataVisualization(viewer)
resolve(model);
console.log("模型加載完成");

View File

@ -1,7 +1,7 @@
import { watch, inject, markRaw, ref, computed, provide } from "vue";
import useAlarmStore from "@/stores/useAlarmStore";
import hexToRgb from "@/util/hexToRgb";
import useSystemShowData from "@/hooks/useSystemShowData"
import useSystemShowData from "@/hooks/useSystemShowData";
import useForgeHeatmap from "./useForgeHeatmap";
import useForgeFloor from "./useForgeFloor";
@ -14,7 +14,19 @@ export default function useForgeSprite() {
let lastClickedDbId = null;
const { createHeatMap, updateViewExtension } = useForgeHeatmap();
const { updateViewerFloor } = useForgeFloor();
const { updateViewerFloor } = useForgeFloor();
const setCameraPosition = (position, target) => {
// 使用 THREE.Vector3 定義位置與焦點
const newPosition = new THREE.Vector3(position.x, position.y, position.z);
const newTarget = new THREE.Vector3(target.x, target.y, target.z);
// 設定攝影機的新位置與焦點
forgeViewer.value.navigation.setView(newPosition, newTarget);
// 確保 Home 視角
forgeViewer.value.autocam.setCurrentViewAsHome(true);
};
const updateDataVisualization = async (viewer) => {
if (!forgeViewer.value) {
@ -26,7 +38,7 @@ export default function useForgeSprite() {
);
dataVizExtn.value = markRaw(dataVisualization);
updateViewExtension(markRaw(viewer), markRaw(dataVisualization));
updateViewerFloor(markRaw(viewer), markRaw(dataVisualization))
updateViewerFloor(markRaw(viewer), markRaw(dataVisualization));
};
function onSpriteClicked(event) {
@ -51,7 +63,7 @@ export default function useForgeSprite() {
}
}
const { flatSubData } = useSystemShowData()
const { flatSubData } = useSystemShowData();
// 創建 sprites
const createSprites = async () => {
@ -135,7 +147,7 @@ export default function useForgeSprite() {
);
};
const cardfitToView = async ([forge_dbid,spriteDbId]) => {
const cardfitToView = async ([forge_dbid, spriteDbId]) => {
try {
// 相機調整
const nav = forgeViewer.value.navigation;
@ -149,7 +161,6 @@ export default function useForgeSprite() {
const fov = nav.getVerticalFov();
nav.setRequestTransition(true, camera.position, target, fov);
if (lastClickedDbId !== null && lastClickedDbId !== spriteDbId) {
dataVizExtn.value.invalidateViewables([lastClickedDbId], (viewable) => {
return {
@ -157,7 +168,7 @@ export default function useForgeSprite() {
};
});
}
dataVizExtn.value.invalidateViewables([spriteDbId], (viewable) => {
return {
scale: 2.0, // 設置為 scale 2
@ -165,12 +176,10 @@ export default function useForgeSprite() {
});
lastClickedDbId = spriteDbId;
} catch (error) {
console.error("Error in cardfitToView:", error);
}
};
const hideAllObjects = () => {
const tree = forgeViewer.value.model.getInstanceTree();
@ -201,10 +210,9 @@ export default function useForgeSprite() {
forgeViewer.value.tearDown();
};
return {
createSprites,
setCameraPosition,
updateDataVisualization,
showSubSystemObjects,
forgeClickListener,

View File

@ -10,7 +10,7 @@ const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
const getSubSystems = async (id) => {
const res = await getAssetSubList(id);
sub = res.data.map((d, index) => ({
const sub = res.data.map((d, index) => ({
...d,
title: d.system_key,
key: d.id,
@ -34,7 +34,7 @@ watch(
() => searchParams,
(newValue) => {
if(newValue.value.mainSys_id){
getSubSystems(newValue.value.mainSys_id);
getSubSystems(parseInt(newValue.value.mainSys_id));
}
},
{

View File

@ -63,18 +63,10 @@ watch(
if (newValue.work_type === "3") {
isSearchDisabled.value = false;
initSubmit(true);
} else if (newSelected) {
if (newValue.search_type === "date") {
isSearchDisabled.value = !(
keys.length ===
newSelected?.params.length + 2
);
initSubmit(keys.length === newSelected?.params.length + 2);
} else if (newValue.search_type === "serial") {
isSearchDisabled.value = !(keys.length === newSelected?.params.length);
initSubmit(keys.length === newSelected?.params.length);
}
isSearchDisabled.value = !searchParams.value.sub_system_tag;
initSubmit(searchParams.value.sub_system_tag);
}
},
{

View File

@ -9,7 +9,6 @@ import { twMerge } from "tailwind-merge";
import { useI18n } from "vue-i18n";
const { t, locale } = useI18n();
const { searchParams, changeParams } = useSearchParam();
const { search } = inject("operation_table");
const form = ref(null);
@ -48,7 +47,9 @@ const setButtonItems = () => {
title: t("operation.company_info"),
key: "company_info",
active: false,
active: searchParams.value.work_type === null,
active:
searchParams.value.work_type === null ||
searchParams.value.work_type === "3",
work_type: 3,
params: [],
},
@ -93,7 +94,6 @@ watch(
searchParams.value[key] ?? null,
])
);
changeParams({
...oldSearchParams,
work_type: newWorkType?.work_type,
@ -103,22 +103,6 @@ watch(
}
}
);
watch(
searchParams,
(newValue, oldValue) => {
if (
newValue.work_type &&
oldValue.work_type &&
newValue.work_type !== oldValue.work_type
) {
search();
}
},
{
deep: true,
}
);
</script>
<template>
@ -154,7 +138,6 @@ watch(
<OperationSearchType :selected="selectedSearchType" />
<OperationActionButton :selectedWorkType="selectedWorkType" />
</div>
</form>
</template>

View File

@ -1,12 +1,12 @@
<script setup>
import { getAssetMainList, getAssetSubList } from "@/apis/asset";
import { computed, onMounted, ref, watch } from "vue";
import { computed, onMounted, ref, watch,inject } from "vue";
import useSearchParam from "@/hooks/useSearchParam";
import useActiveBtn from "@/hooks/useActiveBtn";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { searchParams, changeParams } = useSearchParam();
const { search } = inject("operation_table");
//
const {
items: sysMainTagItems,
@ -58,20 +58,29 @@ watch(selectedMainSysItems, (newValue) => {
mainSys_id: newValue.key,
sub_system_tag: null,
});
getSubSystems(newValue.key);
});
// watch(selectedSysItems, (newValue) => {
// changeParams({
// ...searchParams.value,
// sub_system_tag: newValue.map((d) => d.key),
// });
// });
watch(selectedSysItems, (newValue) => {
changeParams({
...searchParams.value,
sub_system_tag: newValue.map((d) => d.key),
});
});
watch(
() => searchParams,
searchParams,
(newValue, oldValue) => {
if (newValue.mainSys_id && newValue.mainSys_id !== oldValue.mainSys_id) {
getSubSystems(newValue.value.mainSys_id);
if (
newValue.work_type &&
oldValue.work_type &&
newValue.work_type !== oldValue.work_type
) {
changeParams({
...searchParams.value,
sub_system_tag: sysTagItems.value.map((item) => item.key)[0],
});
search();
}
},
{

View File

@ -72,16 +72,13 @@ const formState = ref([
let companySchema = yup.object({
name: yup.string().required(t("button.required")),
contact_person: yup.string().required(t("button.required")),
email: yup.string().email().required(t("button.required")),
phone: yup
.string()
.phone("TW", t("button.phone_format"))
.required(t("button.required")),
city: yup.string().required(t("button.required")),
address: yup.string().required(t("button.required")),
tax_id_number: yup.string().required(t("button.required")),
remark: yup.string().required(t("button.required")),
contact_person: yup.string().nullable(true),
email: yup.string().email().nullable(true),
phone: yup.string().nullable(true),
city: yup.string().nullable(true),
address: yup.string().nullable(true),
tax_id_number: yup.string().nullable(true),
remark: yup.string().nullable(true),
});
let maintainSchema = yup.object({