feat: load fleet space

This commit is contained in:
Huh Hyeongjun 2025-02-25 22:41:09 +09:00
parent 700e9d3b25
commit 353fb4ce0d
6 changed files with 134 additions and 8 deletions

33
package-lock.json generated
View File

@ -12,6 +12,7 @@
"@react-three/drei": "^10.0.2",
"@react-three/fiber": "^9.0.4",
"@types/three": "^0.173.0",
"axios": "^1.7.9",
"deventds2": "^0.1.10",
"leaflet": "^1.9.4",
"lucide-react": "^0.475.0",
@ -5973,6 +5974,32 @@
"node": ">=4"
}
},
"node_modules/axios": {
"version": "1.7.9",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
"integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/axobject-query": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
@ -15565,6 +15592,12 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/psl": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",

View File

@ -14,6 +14,7 @@
"@react-three/drei": "^10.0.2",
"@react-three/fiber": "^9.0.4",
"@types/three": "^0.173.0",
"axios": "^1.7.9",
"deventds2": "^0.1.10",
"leaflet": "^1.9.4",
"lucide-react": "^0.475.0",

10
src/api/axios.ts Normal file
View File

@ -0,0 +1,10 @@
import axios from "axios";
import { getCookie } from "../utils/cookie";
const instanceFleet = axios.create({
baseURL: `https://api.fleet.cartesiancs.com/api/`,
timeout: 7000,
headers: { "x-access-token": getCookie("token") },
});
export default instanceFleet;

View File

@ -2,11 +2,18 @@ import { create } from "zustand";
type ActionStore = {
action: boolean;
fleetSpaceId: string;
exportType: "glb" | "fleet";
setAction: (action: boolean) => void;
setFleet: (fleetSpaceId: string, exportType: "glb" | "fleet") => void;
};
export const useActionStore = create<ActionStore>((set) => ({
action: false,
fleetSpaceId: "",
exportType: "glb",
setAction: (action) => set(() => ({ action: action })),
setFleet: (fleetSpaceId, exportType) =>
set(() => ({ fleetSpaceId: fleetSpaceId, exportType: exportType })),
}));

View File

@ -6,6 +6,7 @@ import * as THREE from "three";
import { useActionStore } from "@/state/exportStore";
import { GLTFExporter } from "three/examples/jsm/Addons.js";
import Car from "./Car";
import instanceFleet from "@/api/axios";
function Building({
shape,
@ -130,13 +131,38 @@ function Roads({ area }: { area: any }) {
export function Export() {
const { scene } = useThree();
const action = useActionStore((state) => state.action);
const fleetSpaceId = useActionStore((state) => state.fleetSpaceId);
const exportType = useActionStore((state) => state.exportType);
const setAction = useActionStore((state) => state.setAction);
useEffect(() => {
if (action === true) {
setAction(false);
exportGLB();
}
}, [action, setAction, scene]);
const uploadFleet = async (blob) => {
const formData = new FormData();
formData.append("object", blob, "box3d.glb");
formData.append("title", "New Object");
formData.append("description", "");
formData.append("spaceId", fleetSpaceId);
const requestUploadFile = await instanceFleet.post(
"space/file/mesh",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
},
}
);
};
const exportGLB = () => {
const sceneClone = scene.clone(true);
sceneClone.traverse((child) => {
@ -151,13 +177,20 @@ export function Export() {
(result) => {
if (result instanceof ArrayBuffer) {
const blob = new Blob([result], { type: "model/gltf-binary" });
const link = document.createElement("a");
link.style.display = "none";
document.body.appendChild(link);
link.href = URL.createObjectURL(blob);
link.download = "scene.glb";
link.click();
document.body.removeChild(link);
if (exportType == "glb") {
const link = document.createElement("a");
link.style.display = "none";
document.body.appendChild(link);
link.href = URL.createObjectURL(blob);
link.download = "scene.glb";
link.click();
document.body.removeChild(link);
}
if (exportType == "fleet") {
uploadFleet(blob);
}
} else {
console.error("GLB export failed: unexpected result", result);
}

View File

@ -19,6 +19,7 @@ import { Modal } from "@/components/modal/Modal";
import { TopNav } from "@/components/nav/TopNav";
import { getCookie } from "@/utils/cookie";
import { Row } from "@/components/flex/Row";
import instanceFleet from "@/api/axios";
const IconSize = css({
width: "14px",
@ -33,9 +34,12 @@ function App() {
const [isWarnModal, setIsWarnModal] = useState(false);
const [isExportModal, setIsExportModal] = useState(false);
const [isFleetLogin, setIsFleetLogin] = useState(false);
const [isFleetModal, setIsFleetModal] = useState(false);
const [spaceList, setSpaceList] = useState([]);
const setCenter = useAreaStore((state) => state.setCenter);
const setAction = useActionStore((state) => state.setAction);
const setFleet = useActionStore((state) => state.setFleet);
const checkIsBig = () => {
const a = areaData[0].lat - areaData[1].lat;
@ -58,6 +62,31 @@ function App() {
setAction(true);
};
const getFleetSpaces = async () => {
const getSpace: any = await instanceFleet.get("space");
setSpaceList([
...getSpace.data.spaces.map((item) => {
return {
...item,
key: item.id,
};
}),
]);
};
const putGlbOnFleetSpace = (spaceId) => {
setFleet(spaceId, "fleet");
setTimeout(() => {
exportFleet();
}, 100);
};
const loadFleetSpace = () => {
getFleetSpaces();
setIsFleetModal(true);
};
const checkFleetLogin = () => {
try {
const isCookie = getCookie("token");
@ -174,7 +203,9 @@ function App() {
</Button>
{isFleetLogin ? (
<Button isShow={true}>Fleet Interlock</Button>
<Button isShow={true} onClick={loadFleetSpace}>
Fleet Interlock
</Button>
) : (
<Button
isShow={true}
@ -187,6 +218,17 @@ function App() {
</Column>
</Modal>
<Modal isOpen={isFleetModal} onClose={() => setIsFleetModal(false)}>
<Column gap="0.5rem">
<Title>Select Fleet Space</Title>
{spaceList.map((item, index) => (
<Button isShow={true} onClick={() => putGlbOnFleetSpace(item.id)}>
{item.title}
</Button>
))}
</Column>
</Modal>
<Space></Space>
</div>
);