vue vite+three在线编辑模型导入导出

文章目录

  • 一、1.0.0版本
    • 1.新增
    • 2.编辑
    • 3.导出
    • 4.导入
  • 二、2.0.0版本
    • 1. 修复模型垂直方向放置时 模型会重合
    • 4. 修复了导出导入功能 现在是1:1导出导入
    • 5. 新增一个地面 视角看不到地下 设置了禁止编辑地面 地面设置为圆形
    • 6. 新增功能 可选择基本圆形 方形 圆柱形等模型以及可放置自己的模型文件
    • 7. 优化面板样式
  • 总结

要实现一个类似于数字孪生的场景 可以在线、新增、删除模型 、以及编辑模型的颜色、长宽高
然后还要实现 编辑完后 保存为json数据 记录模型数据 既可以导入也可以导出

一、1.0.0版本

1.新增

先拿建议的立方体来代替模型
点击新增按钮就新增一个立方体
在这里插入图片描述

2.编辑

点击编辑按钮可以修改坐标 长宽高 颜色等等信息
在这里插入图片描述

3.导出

点击导出按钮 可以导出为json数据格式
在这里插入图片描述

在这里插入图片描述

4.导入

选择导入刚才的json文件
在这里插入图片描述
有一个bug 就是导入后颜色丢失了 点击模型 信息面板的颜色显示正常 渲染颜色丢失
在这里插入图片描述


源码

<template><div id="app" @click="onAppClick"><div id="info"><button @click.stop="addBuilding">新增</button><button @click.stop="showEditor">编辑</button><button @click.stop="exportModelData">导出</button><input type="file" @change="importModelData" ref="fileInput" /></div><div id="editor" v-if="editorVisible" @click.stop><h3>Edit Building</h3><label for="color">Color:</label><input type="color" id="color" v-model="selectedObjectProps.color" /><br /><label for="posX">Position X:</label><inputtype="number"id="posX"v-model="selectedObjectProps.posX"step="0.1"/><br /><label for="posY">Position Y:</label><inputtype="number"id="posY"v-model="selectedObjectProps.posY"step="0.1"/><br /><label for="posZ">Position Z:</label><inputtype="number"id="posZ"v-model="selectedObjectProps.posZ"step="0.1"/><br /><label for="scaleX">Scale X:</label><inputtype="number"id="scaleX"v-model="selectedObjectProps.scaleX"step="0.1"/><br /><label for="scaleY">Scale Y:</label><inputtype="number"id="scaleY"v-model="selectedObjectProps.scaleY"step="0.1"/><br /><label for="scaleZ">Scale Z:</label><inputtype="number"id="scaleZ"v-model="selectedObjectProps.scaleZ"step="0.1"/><br /><label for="rotX">Rotation X:</label><inputtype="number"id="rotX"v-model="selectedObjectProps.rotX"step="0.1"/><br /><label for="rotY">Rotation Y:</label><inputtype="number"id="rotY"v-model="selectedObjectProps.rotY"step="0.1"/><br /><label for="rotZ">Rotation Z:</label><inputtype="number"id="rotZ"v-model="selectedObjectProps.rotZ"step="0.1"/><br /><button @click="applyEdit">保存</button><button @click="deleteBuilding">删除</button></div><div ref="canvasContainer" style="width: 100vw; height: 100vh"></div></div>
</template><script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";export default {data() {return {editorVisible: false,selectedObject: null,selectedObjectProps: {color: "#00ff00",posX: 0,posY: 0,posZ: 0,scaleX: 1,scaleY: 1,scaleZ: 1,rotX: 0,rotY: 0,rotZ: 0,},raycaster: null,};},mounted() {this.init();this.animate();window.addEventListener("resize", this.onWindowResize, false);this.loadModelData(); // Load saved model data on page load},methods: {init() {console.log("Initializing Three.js");this.scene = new THREE.Scene();this.scene.background = new THREE.Color(0xcccccc);this.camera = new THREE.PerspectiveCamera(60,window.innerWidth / window.innerHeight,0.1,1000);this.camera.position.set(0, 10, 20);this.renderer = new THREE.WebGLRenderer({ antialias: true });this.renderer.setSize(window.innerWidth, window.innerHeight);this.$refs.canvasContainer.appendChild(this.renderer.domElement);this.controls = new OrbitControls(this.camera, this.renderer.domElement);const light = new THREE.DirectionalLight(0xffffff, 1);light.position.set(5, 10, 7.5);this.scene.add(light);this.raycaster = new THREE.Raycaster();const geometry = new THREE.BoxGeometry(1, 1, 1);const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });this.cube = new THREE.Mesh(geometry, material);this.scene.add(this.cube);},onWindowResize() {this.camera.aspect = window.innerWidth / window.innerHeight;this.camera.updateProjectionMatrix();this.renderer.setSize(window.innerWidth, window.innerHeight);},onAppClick(event) {const mouse = new THREE.Vector2();mouse.x = (event.clientX / window.innerWidth) * 2 - 1;mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;this.raycaster.setFromCamera(mouse, this.camera);const intersects = this.raycaster.intersectObjects(this.scene.children, true);if (intersects.length > 0) {this.selectedObject = intersects[0].object;console.log("Object selected:", this.selectedObject);this.showEditor();}},addBuilding() {const geometry = new THREE.BoxGeometry(1, 1, 1);const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });const building = new THREE.Mesh(geometry, material);building.position.set(Math.random() * 10 - 5, 0.5, Math.random() * 10 - 5);this.scene.add(building);},showEditor() {if (this.selectedObject) {this.editorVisible = true;this.updateEditor(this.selectedObject);}},updateEditor(object) {this.selectedObjectProps.color = `#${object.material.color.getHexString()}`;this.selectedObjectProps.posX = object.position.x;this.selectedObjectProps.posY = object.position.y;this.selectedObjectProps.posZ = object.position.z;this.selectedObjectProps.scaleX = object.scale.x;this.selectedObjectProps.scaleY = object.scale.y;this.selectedObjectProps.scaleZ = object.scale.z;this.selectedObjectProps.rotX = object.rotation.x;this.selectedObjectProps.rotY = object.rotation.y;this.selectedObjectProps.rotZ = object.rotation.z;},applyEdit() {if (this.selectedObject) {const color = this.selectedObjectProps.color;this.selectedObject.material.color.set(color);this.selectedObject.position.set(parseFloat(this.selectedObjectProps.posX),parseFloat(this.selectedObjectProps.posY),parseFloat(this.selectedObjectProps.posZ));this.selectedObject.scale.set(parseFloat(this.selectedObjectProps.scaleX),parseFloat(this.selectedObjectProps.scaleY),parseFloat(this.selectedObjectProps.scaleZ));this.selectedObject.rotation.set(parseFloat(this.selectedObjectProps.rotX),parseFloat(this.selectedObjectProps.rotY),parseFloat(this.selectedObjectProps.rotZ));}},deleteBuilding() {if (this.selectedObject) {this.scene.remove(this.selectedObject);this.selectedObject = null;this.editorVisible = false;}},animate() {requestAnimationFrame(this.animate);this.renderer.render(this.scene, this.camera);this.controls.update();},exportModelData() {const modelData = {objects: this.scene.children.filter((obj) => obj instanceof THREE.Mesh) // 过滤出是 Mesh 对象的物体.map((obj) => ({position: obj.position.toArray(),scale: obj.scale.toArray(),rotation: obj.rotation.toArray(),color: `#${obj.material.color.getHexString()}`,})),};const jsonData = JSON.stringify(modelData);const blob = new Blob([jsonData], { type: "application/json" });const url = URL.createObjectURL(blob);const a = document.createElement("a");a.style.display = "none";a.href = url;a.download = "model_data.json";document.body.appendChild(a);a.click();URL.revokeObjectURL(url);document.body.removeChild(a);},importModelData(event) {const file = event.target.files[0];if (file) {const reader = new FileReader();reader.onload = () => {try {const data = JSON.parse(reader.result);console.log("Imported data:", data); // 输出导入的完整数据,确保格式和内容正确this.clearScene();data.objects.forEach((objData, index) => {const geometry = new THREE.BoxGeometry();// 设置默认颜色为红色const color = new THREE.Color(0xff0000); // 红色// 如果数据中有颜色字段并且是合法的颜色值,则使用数据中的颜色if (objData.color && typeof objData.color === "string") {try {color.set(objData.color);} catch (error) {console.error(`Error parsing color for object ${index}:`, error);}} else {console.warn(`Invalid color value for object ${index}:`, objData.color);}const material = new THREE.MeshStandardMaterial({color: color,metalness: 0.5, // 示例中的金属度设置为0.5,可以根据需求调整roughness: 0.8, // 示例中的粗糙度设置为0.8,可以根据需求调整});const object = new THREE.Mesh(geometry, material);object.position.fromArray(objData.position);object.scale.fromArray(objData.scale);object.rotation.fromArray(objData.rotation);this.scene.add(object);});} catch (error) {console.error("Error importing model data:", error);}};reader.readAsText(file);}},clearScene() {while (this.scene.children.length > 0) {this.scene.remove(this.scene.children[0]);}},saveModelData() {const modelData = {objects: this.scene.children.map((obj) => ({position: obj.position.toArray(),scale: obj.scale.toArray(),rotation: obj.rotation.toArray(),color: `#${obj.material.color.getHexString()}`,})),};localStorage.setItem("modelData", JSON.stringify(modelData));},loadModelData() {const savedData = localStorage.getItem("modelData");if (savedData) {try {const data = JSON.parse(savedData);this.clearScene();data.objects.forEach((objData) => {const geometry = new THREE.BoxGeometry();const material = new THREE.MeshStandardMaterial({color: parseInt(objData.color.replace("#", "0x"), 16),});const object = new THREE.Mesh(geometry, material);object.position.fromArray(objData.position);object.scale.fromArray(objData.scale);object.rotation.fromArray(objData.rotation);this.scene.add(object);});} catch (error) {console.error("Error loading model data from localStorage:", error);}}},},
};
</script><style>
body {margin: 0;overflow: hidden;
}canvas {display: block;
}#info {position: absolute;top: 10px;left: 10px;background: rgba(255, 255, 255, 0.8);padding: 10px;
}#editor {position: absolute;top: 100px;left: 10px;background: rgba(255, 255, 255, 0.8);padding: 10px;
}
</style>

二、2.0.0版本

在这里插入图片描述

1. 修复模型垂直方向放置时 模型会重合

4. 修复了导出导入功能 现在是1:1导出导入

5. 新增一个地面 视角看不到地下 设置了禁止编辑地面 地面设置为圆形

6. 新增功能 可选择基本圆形 方形 圆柱形等模型以及可放置自己的模型文件

7. 优化面板样式

<template><div id="app" @click="onAppClick"><div id="info"><button @click.stop="toggleBuildingMode">{{ buildingMode ? "关闭建造模式" : "开启建造模式" }}</button><button @click.stop="showEditor">编辑所选模型</button><button @click.stop="exportModelData">导出模型数据</button><input type="file" @change="importModelData" ref="fileInput" /><input type="file" @change="importCustomModel" ref="customModelInput" /><label for="modelType">模型类型:</label><select v-model="selectedModelType"><option value="box">立方体</option><option value="sphere">球体</option><option value="cylinder">圆柱体</option><option value="custom">自定义模型</option></select></div><div id="editor" v-if="editorVisible" @click.stop><h3>编辑模型</h3><div class="form-group"><label for="color">颜色:</label><input type="color" id="color" v-model="selectedObjectProps.color" /><br /></div><div class="form-group"><label for="posX">位置 X:</label><input type="number" id="posX" v-model="selectedObjectProps.posX" step="0.1" /><br /></div><div class="form-group"><label for="posY">位置 Y:</label><input type="number" id="posY" v-model="selectedObjectProps.posY" step="0.1" /><br /></div><div class="form-group"><label for="posZ">位置 Z:</label><input type="number" id="posZ" v-model="selectedObjectProps.posZ" step="0.1" /><br /></div><div class="form-group"><label for="scaleX">缩放 X:</label><input type="number" id="scaleX" v-model="selectedObjectProps.scaleX" step="0.1" /><br /></div><div class="form-group"><label for="scaleY">缩放 Y:</label><input type="number" id="scaleY" v-model="selectedObjectProps.scaleY" step="0.1" /><br /></div><div class="form-group"><label for="scaleZ">缩放 Z:</label><input type="number" id="scaleZ" v-model="selectedObjectProps.scaleZ" step="0.1" /><br /></div><div class="form-group"><label for="rotX">旋转 X:</label><input type="number" id="rotX" v-model="selectedObjectProps.rotX" step="0.1" /><br /></div><div class="form-group"><label for="rotY">旋转 Y:</label><input type="number" id="rotY" v-model="selectedObjectProps.rotY" step="0.1" /><br /></div><div class="form-group"><label for="rotZ">旋转 Z:</label><input type="number" id="rotZ" v-model="selectedObjectProps.rotZ" step="0.1" /><br /></div><button @click="applyEdit">应用</button><button @click="deleteBuilding">删除</button></div><div ref="canvasContainer" style="width: 100vw; height: 100vh"></div></div>
</template><script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";export default {data() {return {editorVisible: false,selectedObject: null,selectedObjectProps: {color: "#000",posX: 0,posY: 0,posZ: 0,scaleX: 1,scaleY: 1,scaleZ: 1,rotX: 0,rotY: 0,rotZ: 0,},raycaster: null,buildingMode: false,selectedModelType: "box",customModel: null,};},mounted() {this.init();this.animate();window.addEventListener("resize", this.onWindowResize, false);},methods: {animate() {requestAnimationFrame(this.animate);this.renderer.render(this.scene, this.camera);this.controls.update();},init() {console.log("Initializing Three.js");this.scene = new THREE.Scene();this.scene.background = new THREE.Color('0xcccccc');this.camera = new THREE.PerspectiveCamera(60,window.innerWidth / window.innerHeight,0.1,1000);this.camera.position.set(0, 10, 20);this.renderer = new THREE.WebGLRenderer({ antialias: true });this.renderer.setSize(window.innerWidth, window.innerHeight);this.$refs.canvasContainer.appendChild(this.renderer.domElement);this.controls = new OrbitControls(this.camera, this.renderer.domElement);this.controls.minDistance = 10;this.controls.maxDistance = 50;this.controls.maxPolarAngle = Math.PI / 2;const planeGeometry = new THREE.CircleGeometry(100, 32);const planeMaterial = new THREE.MeshStandardMaterial({ color: 0x999999 });const plane = new THREE.Mesh(planeGeometry, planeMaterial);plane.rotation.x = -Math.PI / 2;plane.userData.isGround = true;this.scene.add(plane);const light = new THREE.DirectionalLight(0xffffff, 1);light.position.set(5, 10, 7.5);this.scene.add(light);this.raycaster = new THREE.Raycaster();},onWindowResize() {this.camera.aspect = window.innerWidth / window.innerHeight;this.camera.updateProjectionMatrix();this.renderer.setSize(window.innerWidth, window.innerHeight);},onAppClick(event) {const mouse = new THREE.Vector2();mouse.x = (event.clientX / window.innerWidth) * 2 - 1;mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;this.raycaster.setFromCamera(mouse, this.camera);const intersects = this.raycaster.intersectObjects(this.scene.children, true);if (this.buildingMode && intersects.length > 0) {const intersect = intersects[0];const point = intersect.point;if (intersect.object.userData.isGround) {if (this.isOverlapping(point.x, point.z)) {this.stackBuilding(point.x, point.z);} else {this.addBuilding(point.x, 0, point.z);}} else {const stackHeight = intersect.object.position.y + intersect.object.scale.y;this.addBuilding(intersect.object.position.x, stackHeight, intersect.object.position.z);}} else if (intersects.length > 0) {this.selectedObject = intersects[0].object;console.log("Object selected:", this.selectedObject);this.showEditor();}},isOverlapping(x, z) {const threshold = 1;for (let obj of this.scene.children) {if (Math.abs(obj.position.x - x) < threshold &&Math.abs(obj.position.z - z) < threshold &&!obj.userData.isGround) {return true;}}return false;},stackBuilding(x, z) {let maxY = 0;this.scene.children.forEach((obj) => {if (Math.abs(obj.position.x - x) < 1 &&Math.abs(obj.position.z - z) < 1 &&!obj.userData.isGround &&obj.position.y + obj.scale.y > maxY) {maxY = obj.position.y + obj.scale.y;}});this.addBuilding(x, maxY, z);},addBuilding(x, y, z) {let geometry;switch (this.selectedModelType) {case "sphere":geometry = new THREE.SphereGeometry(0.5, 32, 32);break;case "cylinder":geometry = new THREE.CylinderGeometry(0.5, 0.5, 1, 32);break;case "custom":if (this.customModel) {this.loadCustomModel(x, y, z);return;}break;case "box":default:geometry = new THREE.BoxGeometry(1, 1, 1);break;}if (geometry) {const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });const building = new THREE.Mesh(geometry, material);building.position.set(x, y, z);this.scene.add(building);}},loadCustomModel(x, y, z) {const loader = new GLTFLoader();loader.load(this.customModel,(gltf) => {const object = gltf.scene;object.position.set(x, y, z);this.scene.add(object);},undefined,(error) => {console.error("An error happened while loading the custom model", error);});},importCustomModel(event) {const file = event.target.files[0];this.customModel = URL.createObjectURL(file);},showEditor() {if (this.selectedObject) {this.selectedObjectProps.color = "#" + this.selectedObject.material.color.getHexString();this.selectedObjectProps.posX = this.selectedObject.position.x;this.selectedObjectProps.posY = this.selectedObject.position.y;this.selectedObjectProps.posZ = this.selectedObject.position.z;this.selectedObjectProps.scaleX = this.selectedObject.scale.x;this.selectedObjectProps.scaleY = this.selectedObject.scale.y;this.selectedObjectProps.scaleZ = this.selectedObject.scale.z;this.selectedObjectProps.rotX = this.selectedObject.rotation.x;this.selectedObjectProps.rotY = this.selectedObject.rotation.y;this.selectedObjectProps.rotZ = this.selectedObject.rotation.z;}this.editorVisible = true;},applyEdit() {if (this.selectedObject) {this.selectedObject.material.color.set(this.selectedObjectProps.color);this.selectedObject.position.set(this.selectedObjectProps.posX,this.selectedObjectProps.posY,this.selectedObjectProps.posZ);this.selectedObject.scale.set(this.selectedObjectProps.scaleX,this.selectedObjectProps.scaleY,this.selectedObjectProps.scaleZ);this.selectedObject.rotation.set(this.selectedObjectProps.rotX,this.selectedObjectProps.rotY,this.selectedObjectProps.rotZ);}this.editorVisible = false;},deleteBuilding() {if (this.selectedObject) {this.scene.remove(this.selectedObject);this.selectedObject.geometry.dispose();this.selectedObject.material.dispose();this.selectedObject = null;this.editorVisible = false;}},toggleBuildingMode() {this.buildingMode = !this.buildingMode;},exportModelData() {const modelData = this.scene.children.filter((obj) => obj.type === "Mesh" && !obj.userData.isGround).map((obj) => ({type: obj.geometry.type,position: obj.position,rotation: obj.rotation,scale: obj.scale,color: obj.material.color.getHex(),}));const blob = new Blob([JSON.stringify(modelData)], { type: "application/json" });const link = document.createElement("a");link.href = URL.createObjectURL(blob);link.download = "modelData.json";link.click();},importModelData(event) {const file = event.target.files[0];const reader = new FileReader();reader.onload = (e) => {const modelData = JSON.parse(e.target.result);this.loadModelData(modelData);};reader.readAsText(file);},loadModelData(modelData = null) {if (!modelData) {return;}modelData.forEach((data) => {let geometry;switch (data.type) {case "SphereGeometry":geometry = new THREE.SphereGeometry(0.5, 32, 32);break;case "CylinderGeometry":geometry = new THREE.CylinderGeometry(0.5, 0.5, 1, 32);break;case "BoxGeometry":default:geometry = new THREE.BoxGeometry(1, 1, 1);break;}const material = new THREE.MeshStandardMaterial({ color: data.color });const object = new THREE.Mesh(geometry, material);object.position.copy(data.position);object.rotation.copy(data.rotation);object.scale.copy(data.scale);this.scene.add(object);});},},
};
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialias;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;
}#info {position: absolute;top: 10px;left: 10px;background: rgba(255, 255, 255, 0.8);padding: 10px;border-radius: 5px;
}#editor {position: absolute;top: 50px;right: 10px;background: rgba(255, 255, 255, 0.9);padding: 10px;border-radius: 5px;z-index: 1000;width: 200px;
}#editor .form-group {margin-bottom: 10px;
}#editor label {display: block;margin-bottom: 5px;
}#editor input {width: 100%;
}
</style>

总结

未完待续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/870885.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HUGS环境配置

1. 介绍 HUGS: Holistic Urban 3D Scene Understanding via Gaussian Splatting 基于 RGB 图像对城市场景进行整体理解是一个具有挑战性但又很重要的问题。它包括理解几何和外观&#xff0c;以实现新颖的视图合成、解析语义标签和跟踪移动物体。尽管取得了长足的进步&#xf…

C# 的TaskScheduler

在C#中&#xff0c;TaskScheduler 是一个抽象类&#xff0c;用于控制任务的执行方式&#xff0c;特别是它们如何被安排到线程池中的线程上执行。 TaskScheduler 负责将 Task 对象排队并决定何时、以何种方式执行这些任务。 TaskScheduler 的作用 调度任务&#xff1a;将任务…

querylist多线程采集curlMulti时,报错Curl error(60)

前言 在使用querylist多线程采集的时候&#xff0c;报错: Curl error(60)。测试了下用http时没有问题&#xff0c;https时有问题。其原因在于多线程采集库引用的另一个库有问题。需要手动更改。 解决 找到&#xff1a;vendor/ares333/php-curl/src/Curl.php 文件&#xff0c…

网络 闲聊

闲谈 闲话 网络安全——>网络空间安全 网络空间&#xff1a;一个由信息基础设备组成互相依赖的网络 继&#xff1a;海、陆、空、天、的第五大空间 信息安全的一个发展&#xff1a; 通信保密阶段---计算机安全---信息系统安全---网络空间安全 棱镜门事件 棱镜计划&…

Visual Studio Code:深度解析与开发者的新宠

在计算机行业中&#xff0c;开发工具的选择至关重要&#xff0c;它直接影响到开发者的效率和项目的质量。近年来&#xff0c;Visual Studio Code&#xff08;简称VSCode&#xff09;凭借其强大的功能和灵活的定制性&#xff0c;在众多编辑器中脱颖而出&#xff0c;成为了开发者…

linux系统php开机自启动 phpfpm

1、关闭当前的php环境&#xff0c;运行命令&#xff0c;下面二选一&#xff0c;根据你自己情况来选 service php-fpm stop 或 systemctl stop php-fpm 2、运行命令vim /etc/systemd/system/phpfpm.service&#xff0c;输入以下代码,注意php-fpm路径需要改成自己的路径 [Unit]…

Redis原子计数器incr,防止并发请求

一、前言 在一些对高并发请求有限制的系统或者功能里&#xff0c;比如说秒杀活动&#xff0c;或者一些网站返回的当前用户过多&#xff0c;请稍后尝试。这些都是通过对同一时刻请求数量进行了限制&#xff0c;一般用作对后台系统的保护&#xff0c;防止系统因为过大的流量冲击…

Twitter API 使用教程:入门到实践

Twitter API为开发者提供了丰富的接口&#xff0c;用于访问Twitter上的公开数据和实现特定功能。从获取推文到用户认证&#xff0c;Twitter API在数据挖掘、社交分析和应用开发中扮演着重要角色。 关键词 Twitter API, 开发者指南&#xff0c;社交媒体&#xff0c;数据访问 …

elementary os 8 2024年07月新动态

具体信息请登录官网查询 **OS 7更新** Photos 8已经作为Flatpak应用发布到AppCenter。这意味着你可以通过从AppCenter安装Flatpak版本来继续接收Photos的更新&#xff0c;即使在旧版本的elementary OS上&#xff0c;而且Photos现在也很容易为那些运行除elementary OS之外的Lin…

Java中的Set系列集合超详解

Set List是有序集合的根接口&#xff0c;Set是无序集合的根接口&#xff0c;无序也就意味着元素不重复。更严格地说&#xff0c;Set集合不包含一对元素e1和e2 &#xff0c;使得e1.equals(e2) &#xff0c;并且最多一个空元素。   使用Set存储的特点与List相反&#xff1a;元素…

腾讯云如何设置二级域名?

什么是二级域名&#xff1f; 例如我已申请的域名为&#xff1a; test.com //顶级域名 现在我开发的应用要部署到二级域名&#xff1a; blog.test.com 1、打开腾讯云控制台的我的域名&#xff0c;然后点击解析 2、在我的解析页面点击添加记录&#xff0c;然后需注意红色方框处…

生物素标记的柚皮苷探针;Biotin-Naringin

生物素标记的柚皮苷探针&#xff08;Biotin-Naringin&#xff09;是一种结合了生物素&#xff08;Biotin&#xff09;和柚皮苷&#xff08;Naringin&#xff09;特性的化合物&#xff0c;它在有机合成及药物化学技术领域具有重要意义。以下是对该探针的详细解析&#xff1a; 一…

秋招Java后端开发冲刺——Mybatis

一、基本知识 1. 介绍 MyBatis 是 Apache 的一个开源项目&#xff0c;它封装了 JDBC&#xff0c;使开发者只需要关注 SQL 语句本身&#xff0c;而不需要再进行繁琐的 JDBC 编码。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java POJO&#xff08;Plain …

设计模式Base

设计模式是在软件开发过程中总结出来的一些经验&#xff0c;它们大多数都遵循一些基本原则&#xff1a; 单一职责原则&#xff08;SRP&#xff09;&#xff1a;一个类应该只有一个引起它变化的原因。也就是说&#xff0c;一个类应该只有一个职责。开放封闭原则&#xff08;OCP…

Everything搜索无法搜索到桌面的文件(无法检索C盘 或 特定路径的文件)

现象描述 在Everything搜索框中输入桌面已存在的文件或随便已知位置的文件&#xff0c;无法找到。 搜索时检索结果中明显缺少部分磁盘位置的&#xff0c;例如无法检索C盘&#xff0c;任意关键字搜索时结果中没有位于C盘的&#xff0c;无论怎样都搜不到C盘文件。 解决方法 在…

CentOS搭建FTP服务器教程

CentOS搭建FTP服务器教程 在互联网时代&#xff0c;文件传输是日常工作中不可或缺的一部分。FTP&#xff08;文件传输协议&#xff09;作为一种标准的网络协议&#xff0c;被广泛用于在互联网上传输文件。本文将详细介绍如何在CentOS系统上搭建FTP服务器&#xff0c;以便您能轻…

L1 Simple_ReAct_Agent

参考自https://www.deeplearning.ai/short-courses/ai-agents-in-langgraph&#xff0c;以下为代码的实现。 Basic ReAct Agent(manual action) import openai import re import httpx import os from dotenv import load_dotenv, find_dotenvOPENAI_API_KEY os.getenv(OPEN…

pip install .自己构建工程文件报错error: subprocess-exited-with-error解决办法

有时我们直接使用pip install xxx安装某个三方文件时候会发现安装不了,会报各种问题。 这时候我们只能通过下载源码自己手动编译。 等我们下好源码开始编译的时候又会出现很多问题。 下面就举一个栗子作为解决问题的思路: 比如我我想要安装diff-gaussian-rasterization,直…

python 66 个冷知识 0712

66个有趣的Python冷知识 字典合并 从Python 3.9开始&#xff0c;可以使用 | 操作符合并字典。 多继承 Python支持多继承&#xff0c;类可以继承多个父类。 ABC模块 abc 模块提供了定义抽象基类的工具。 泛型 typing 模块提供了泛型支持。 类型别名 使用 typing 模块可以创建…

DP讨论——设计模式怎么来的?

眼中没有设计模式&#xff0c;代码里就找不到设计模式 几年前还在搞c开发&#xff0c;觉得设计模式离我太遥远&#xff0c;而且觉得设计模式太复杂太高大上&#xff0c;比较恐惧。 后来接触了oopc&#xff08;接触了rtthread整个都是oopc实现的rtos&#xff09;&#xff0c;再…