three.js+vue污水处理厂数字孪生平台智慧城市web3d

news/2024/11/15 12:02:35/文章来源:https://www.cnblogs.com/tiandi/p/18300886

案例效果截图如下:

 主场景三维逻辑代码如下:

<template><div class="whole"><!-- threejs画布 --><div id="threejs" ref="threejs"></div><!-- 污水厂模型加载进度条 --><a-progress:stroke-color="{from: '#00F5FF',to: '#4169E1',}":percent="0.0"trailColor="#E8E8E8"status="active"class="progress"/><!-- 标签组件 --><Label></Label><!-- 巡检数据展示面板--><div class="inspectPanel a-fadein" v-show="inspectPanelShow"><div class="panelTitle" id="panelTitle">曝气池</div><div class="panelData"><div class="left"><div class="leftTitle">介绍</div><div class="segment"></div><div class="describe" id="describe"></div></div><div class="right"><div class="rightTitle">数据记录</div><div class="segment"></div><div class="record"><div class="main" id="panelData"></div></div></div></div></div><!-- 巡检中 返回和状态按钮 --><div class="inspect" v-show="props['selectedMenu'] === 'inspect'"><div class="common" @click="endInspect"><div class="return_icon" style=""></div>
        返回</div><div class="common" @click="inspectStateChange"><div :class="inspectState ? 'stop_icon' : 'continue_icon'"></div>{{ inspectState ? '暂停' : '继续' }}</div></div><!-- 巡检进度条 --><progressBar v-show="props['selectedMenu'] === 'inspect'" :schedule="schedule" :inspectState="inspectState" @progressBarChange="progressBarChange"></progressBar><!-- 巡检速度控制条 --><speedControlBar v-show="props['selectedMenu'] === 'inspect'" :speed="speed" :inspectState="inspectState" @controlBarChange="controlBarChange"></speedControlBar></div>
</template><script setup>
import { ref, onMounted, watch } from 'vue';
// 引入threejs
import * as THREE from 'three';
// 基础配置文件——场景、灯光、相机等
import { scene, renderer, css2DRender, camera, controls } from './base/index.js';
// 添加污水厂模型函数
import { addSewageModel } from './addSewageModel/index.js';
// 添加人物模型函数
import { addPeopleModel, WalkAction } from './addPeopleModel/index.js';
// 引入tween.js,用来创建动画
import TWEEN from '@tweenjs/tween.js';
// 引入标签组件
import Label from './label/index.vue';
// 引入人物2D标签、CSS2D渲染器、标签初始化函数和建筑标签组对象
import { css2DPeopleLabel, initLabel, buildLabelGroup } from './label/index.js';
// 引入创建水面函数
import { createWaterPlane, waterPlaneGroup } from './waterPlane/index.js';
import { inspectPathArr, inspectIndex, inspectPathIndex, inspectState, inspectPanelShow, inspectLinePointGroup, openInspection, inspectionParams } from './inspection/index.js';
import progressBar from './progressBar/index.vue';
import speedControlBar from './speedControlBar/index.vue';
// 引入RGB加载器
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
import { setPoolMaterial } from './poolMaterial/index';
import Stats from 'three/examples/jsm/libs/stats.module.js';
// 首页传值
const props = defineProps(['craftAnimationStatus', // 工艺动画状态,为true时开启播放相应的工艺动画'craftAnimationType', // 工艺动画类型,根据此值决定动画的类型'selectedMenu', // 首页底部菜单按钮选中项
]);
// 传递事件
const emit = defineEmits(['closeInspect', 'craftAnimationEnd']);// threejs容器
const threejs = ref();
// 污水厂模型
let sewageModel = null;
// 人物模型
let people = null;
// 人物动画播放器
let animationMixer = null;
// 当前巡检进度百分比值
let schedule = ref(0);
// 巡检的速度
let speed = ref(0);let stats;
onMounted(async () => {//创建stats对象stats = new Stats();threejs.value.appendChild(stats.domElement);threejs.value.appendChild(renderer.domElement);threejs.value.appendChild(css2DRender.domElement);const rgbeLoader = new RGBELoader();// 环境贴图let envMap = await rgbeLoader.loadAsync('./envMap.hdr');createEnvironment(envMap);// 异步加载污水厂模型sewageModel = await addSewageModel(envMap);// 添加人物模型、人物动画播放器const { peopleGroup, mixer } = await addPeopleModel();people = peopleGroup;// 相机添加到人物模型中
  people.add(camera);animationMixer = mixer;// 允许人物模型产生阴影people.castShadow = true;scene.add(sewageModel, people, inspectLinePointGroup);// 创建水面
  createWaterPlane(sewageModel, envMap);// 设置水池材质
  setPoolMaterial(sewageModel);// 开始循环渲染
  render();// 播放首次进入动画
  eventAnimation();
});watch(() => props['craftAnimationStatus'],(e) => {if (e) {// 重置水面透明度waterPlaneGroup.children.map((obj) => {obj.material.uniforms.alpha.value = 1.0;});craftAnimation(props['craftAnimationType']);}}
);
watch(() => props['selectedMenu'],(e) => {// 巡检开启if (e === 'inspect') {// 相机角度重置camera.rotation.x = -0.9662198328141542;camera.rotation.y = 0.0004725006116027576;camera.rotation.z = 0.0006839146449353786;// 相机位置重置camera.position.set(0.103, 179.349, 123.908);// 相机观察点重置camera.lookAt(0, 1.7, 0);// 设置相机位置在人物模型后方camera.position.set(0, -5, -1);// camera.position.set(0, 1.4, -1);// 禁止相机控件旋转平移和缩放controls.enableRotate = false;controls.enablePan = false;controls.enableZoom = false;controls.target.set(0, 1.7, 0);controls.update();// 每次开启巡检时,将巡检项目索引和项目索引都重置,从第一个项目开始巡检inspectIndex.value = 0;inspectPathIndex.value = 0;// 人物步行动画开始播放
      WalkAction.play();// 人物标签开启显示css2DPeopleLabel.visible = true;// 巡检标线开启显示inspectLinePointGroup.children[inspectIndex.value].visible = true;// 建筑物标签关闭显示buildLabelGroup.children.map((item) => {item.visible = false;});} else if (e !== 'craft') {// 相机角度重置camera.rotation.x = -0.9662198328141542;camera.rotation.y = 0.0004725006116027576;camera.rotation.z = 0.0006839146449353786;// 相机位置重置camera.position.set(0.103, 179.349, 123.908);// 相机观察点重置camera.lookAt(0, 0, 0);controls.target.set(0, 0, 0);controls.update();// 重置水面透明度水面颜色waterPlaneGroup.children.map((obj) => {obj.material.uniforms.alpha.value = 1.0;obj.material.uniforms.waterColor.value = obj.color;});}}
);const clock = new THREE.Clock();
// 设置渲染帧率30FPS,默认情况下requestAnimationFrame在60帧左右,控制帧率优化性能
const FPS = 30;
// 间隔多长时间渲染一次
const renderT = 1 / FPS;
// 执行一次renderer.render,timeS重新置0
let timeS = 0;
// 渲染循环
function render() {stats.update();// 循环渲染
  renderer.render(scene, camera);// 获取两帧渲染间隔时间const T = clock.getDelta();timeS = timeS + T;animationMixer.update(T);if (timeS > renderT) {TWEEN.update();// renderer.render每执行一次,timeS置0timeS = 0;// css2D标签渲染
    css2DRender.render(scene, camera);// 水面波纹动画渲染waterPlaneGroup.children.map((item) => {item.material.uniforms['time'].value += T / 6;});// 巡检时标线和拐点动画if (inspectLinePointGroup.children[inspectIndex.value] && props['selectedMenu'] === 'inspect') {inspectLinePointGroup.children[inspectIndex.value].children.map((item) => {if (item.name === '标线') {item.material.map.offset.x -= 0.03;} else if (item.name === '拐点') {item.rotation.y += 0.02;}});}// 巡检动画if (props['selectedMenu'] === 'inspect' && inspectState.value) {openInspection(people, controls);schedule.value = inspectPathIndex.value;// 巡检速度不断更新if (inspectPathArr[inspectIndex.value]) {speed.value = inspectPathArr[inspectIndex.value].speed;}console.log('巡检动画');}}requestAnimationFrame(render);
}
// 巡检状态变化事件
function inspectStateChange() {// 巡检的状态切换inspectState.value = !inspectState.value;// 关闭巡检数据面板的显示inspectPanelShow.value = false;if (inspectState.value) {// 人物动画开始播放
    WalkAction.play();if (inspectPathIndex.value >= 100) {// 巡检项目索引加1inspectIndex.value += 1;// 巡检标记线组对象开启显示inspectLinePointGroup.children.map((item, index) => {if (index === inspectIndex.value) {item.visible = true;} else {item.visible = false;}});}} else {// 人物动画停止播放
    WalkAction.stop();}if (inspectPathIndex.value >= 100) {// 巡检项目路径索引重新置零inspectPathIndex.value = 0;}// 巡检项目索引值超过巡检路径数组时,表示已经巡检完最后一项,调用endInspect()结束巡检if (inspectIndex.value > inspectPathArr.length - 1) {endInspect();}
}
// 结束巡检
function endInspect() {// 人物位置重置people.position.set(0, 0, 0);// 人物角度重置people.rotation.y = 0;people.rotation.x = 0;people.rotation.z = 0;// 相机位置重置camera.position.set(0.103, 179.349, 123.908);// 开启相机控件旋转平移和缩放controls.enableRotate = true;controls.enablePan = true;controls.enableZoom = true;// 相机控件观察点重置controls.target.set(0, 1.7, 0);// 相机控件更新
  controls.update();// 巡检状态重置为trueinspectState.value = true;// 关闭巡检数据面板显示inspectPanelShow.value = false;// 人物标签隐藏显示css2DPeopleLabel.visible = false;// 巡检标记线组对象隐藏显示inspectLinePointGroup.children.map((item) => {item.visible = false;});// 建筑物标签开启显示buildLabelGroup.children.map((item) => {item.visible = true;});// 巡检速度重置inspectPathArr.map((item) => {item.speed = inspectionParams[item.name].speed;});// 关闭巡检emit('closeInspect');
}
// 巡检进度条变化事件
function progressBarChange(e) {inspectPathIndex.value = e;
}
// 巡检速度条变化事件
function controlBarChange(speed) {inspectPathArr[inspectIndex.value].speed = 0.4 * (speed * 0.01);
}
// 工艺动画
function craftAnimation(type) {// 重置水面透明度水面颜色waterPlaneGroup.children.map((obj) => {obj.material.uniforms.alpha.value = 1.0;obj.material.uniforms.waterColor.value = obj.color;});// 禁止相机控件旋转平移和缩放// controls.enableRotate = false;// controls.enablePan = false;// controls.enableZoom = false;// 精确曝气动画if (type === 'aeration') {const name = '南北生物池水面';// 水面世界坐标位置const position = sewageModel.getObjectByName(name).getWorldPosition(new THREE.Vector3());// 开启动画,视角切换到水面处new TWEEN.Tween(camera.position).to({ x: -113.85, y: 7.67, z: 43.59 }, 1500).easing(TWEEN.Easing.Sinusoidal.InOut).onUpdate(() => {controls.target.copy(new THREE.Vector3(-113, 2, 30));controls.update();})// 动画执行完成后.onComplete(() => {// 获取水面模型const waterPlane = waterPlaneGroup.getObjectByName(name);// 加载气泡纹理const texture = new THREE.TextureLoader().load('./bubbles.png');// 球体(气泡)材质,map气泡贴图模仿气泡效果const material = new THREE.MeshPhysicalMaterial({map: texture,color: '#fff',transparent: true,opacity: 0.6,});// 球体(气泡)组对象const sphereGroup = new THREE.Group();// 创建box3包围盒计算水面模型尺寸const box3 = new THREE.Box3();box3.expandByObject(waterPlane);// 根据水面尺寸计算出球体(气泡)出现的范围const x = ((box3.max.x - box3.min.x) / 2).toFixed(3) - '';const z = ((box3.max.z - box3.min.z) / 2).toFixed(3) - '' - 0.1;// 循环创建多个球体(气泡)for (let i = 0; i <= 2000; i++) {// 指定随机大小创建球形几何体const sphere = new THREE.SphereGeometry(Math.random() * 0.03 + 0.05);const mesh = new THREE.Mesh(sphere, material);// 随机旋转一定角度mesh.rotateX(Math.random() * Math.PI);// 设置位置
          mesh.position.copy(position);// y值置空mesh.position.y = 0;// 随机在增加一定值,使气泡在不同的位置出现mesh.position.x += Math.random() * (x - -x) + -x;mesh.position.y += Math.random() * 2;mesh.position.z += Math.random() * (z - -z) + -z;// 随机气泡上升的速度值mesh.speed = Math.random() * 0.04 + 0.04;sphereGroup.add(mesh);}scene.add(sphereGroup);// 此变量用作循环动画和销毁动画
        let bubbleRiseAnimationId;// 气泡上升动画function bubbleRise() {bubbleRiseAnimationId = requestAnimationFrame(bubbleRise);sphereGroup.children.map((item) => {item.position.y += item.speed;if (item.position.y >= position.y) item.position.y = 0;});}bubbleRise();// 水面默认的透明度let alpha = waterPlane.material.uniforms.alpha.value;const color1 = new THREE.Color('#87CEFA');const color2 = waterPlane.material.uniforms.waterColor.value;// 此变量用作循环动画和销毁动画
        let waterPlaneAnimationId;// 水面逐渐透明动画function waterPlaneTransparent() {waterPlaneAnimationId = requestAnimationFrame(waterPlaneTransparent);// 透明度大于0.3则不断降低透明度if (alpha >= 0.3) {alpha -= 0.01;waterPlane.material.uniforms.alpha.value = alpha;const newColor = color1.clone().lerp(color2.clone(), alpha);waterPlane.material.uniforms.waterColor.value = newColor;}// 透明度小于0.3else {// 延迟一定秒数后移除气泡组对象setTimeout(() => {// scene.remove(sphereGroup);}, 3000);// 传递事件告知动画执行完毕emit('craftAnimationEnd');// 销毁水面透明动画和气泡上升动画
            cancelAnimationFrame(waterPlaneAnimationId);// cancelAnimationFrame(bubbleRiseAnimationId);
          }}waterPlaneTransparent();}).start();}// 精确加药if (type === 'dosing') {const name = '东加药管2-2';// 加药管位置const position = sewageModel.getObjectByName(name).getWorldPosition(new THREE.Vector3());// 将位置偏移一下到出水口position.y -= 0.138;position.z += 0.22;// 开启Tweenjs动画,将视角切换到加药管处new TWEEN.Tween(camera.position).to({ x: 57.16, y: 2.09, z: 6.53 }, 1500).easing(TWEEN.Easing.Sinusoidal.InOut).onUpdate(() => {controls.target.copy(position);controls.update();})// 视角切换完成后.onComplete(() => {// 创建一个位置数组,因为这个加药管有多个出水口,每个位置对应一个出水口const posArr = [];// 当前出水口位置先push到数组里去
        posArr.push(position);// 获取左侧出水口位置for (let i = 1; i <= 4; i++) {const pos = position.clone();pos.x += i * 0.765;posArr.push(pos);}// 获取右侧出水口位置for (let i = 1; i <= 4; i++) {const pos = position.clone();pos.x -= i * 0.765;posArr.push(pos);}// 创建球形几何体,模仿水滴const sphereGeometry = new THREE.SphereGeometry(0.005, 16, 16);const sphereMaterial = new THREE.MeshPhongMaterial({color: '#afeeee',});// 创建球体数组,存储所有的球体const sphereArr = [];// 每个出水管球体数量const numSpheres = 300;// 遍历posArr位置数组,给每个出水管创建球体posArr.map((pos) => {for (let i = 0; i < numSpheres; i++) {const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);// 默认将其隐藏起来,因为随机高度球体会高于出水管sphere.visible = false;// 赋值出水管位置
            sphere.position.copy(pos);// 球体高度在加上一个随机值sphere.position.y += Math.random() * 2; // 不同的初始高度// 设置球体下落速度sphere.velocity = Math.random() * 0.02 + 0.01; // 随机下落速度
            sphereArr.push(sphere);scene.add(sphere);}});// 此变量用作循环动画和销毁动画
        let animationFrameId1;function animation1() {animationFrameId1 = requestAnimationFrame(animation1);// 遍历球体数组sphereArr.forEach((sphere) => {if (sphere.position.y <= position.y) {sphere.visible = true;}sphere.position.y -= sphere.velocity;if (sphere.position.y <= 0.3) {// 当球体下落到一定位置时sphere.position.y = position.y; // 重新置于顶端
            }});}animation1();const waterPlane = waterPlaneGroup.getObjectByName('东西生物池-东水面1');let alpha = waterPlane.material.uniforms.alpha.value;const color1 = new THREE.Color('#87CEFA');const color2 = waterPlane.material.uniforms.waterColor.value;// 此变量用作循环动画和销毁动画
        let animationFrameId2;function animation2() {animationFrameId2 = requestAnimationFrame(animation2);if (alpha >= 0.5) {alpha -= 0.006;waterPlane.material.uniforms.alpha.value = alpha;const newColor = color1.clone().lerp(color2.clone(), alpha);waterPlane.material.uniforms.waterColor.value = newColor;} else {emit('craftAnimationEnd');cancelAnimationFrame(animationFrameId2);}}animation2();}).start();}// 污泥回流if (type === 'sludge') {// 二沉池模型名称数组const sinkPoolNameArr = ['二沉池3水面','二沉池3水面001','二沉池4水面','二沉池4水面001',// "初沉池水面1",// "初沉池水面1001",
    ];// 生物池模型名称数组const organismPoolNameArr = ['南北生物池水面', '东西生物池-东水面1', '东西生物池-东水面2', '东西生物池-西水面1', '东西生物池-西水面2'];// 获取二沉池模型const sinkPoolArr = [];sinkPoolNameArr.map((name) => {sinkPoolArr.push(waterPlaneGroup.getObjectByName(name));});// 获取生物池模型const organismPoolArr = [];organismPoolNameArr.map((name) => {const organismPool = waterPlaneGroup.getObjectByName(name);organismPool.material.uniforms.alpha.value = 0.3;organismPool.visible = false;organismPool.userData.y = organismPool.clone().position.y;organismPool.position.y = 0;organismPoolArr.push(organismPool);});//  x: -10.84, y: 289.89, z: 276.17// 开启动画,视角切换到整个污水厂new TWEEN.Tween(camera.position).to({ x: 100, y: 100, z: 180 }, 1500).easing(TWEEN.Easing.Sinusoidal.InOut).onUpdate(() => {controls.target.set(100, 0, -30);controls.update();}).onComplete(() => {// 此变量用作循环动画和销毁动画
        let waterPlaneAnimationId;// 水面逐渐透明动画function waterPlaneTransparent() {waterPlaneAnimationId = requestAnimationFrame(waterPlaneTransparent);sinkPoolArr.map((item) => {let alpha = item.material.uniforms.alpha.value;// 透明度大于0.3则不断降低透明度if (alpha >= 0.3) {alpha -= 0.01;item.material.uniforms.alpha.value = alpha;}});if (sinkPoolArr[sinkPoolArr.length - 1].material.uniforms.alpha.value < 0.3) {// 传递事件告知动画执行完毕// emit("craftAnimationEnd");
            cancelAnimationFrame(waterPlaneAnimationId);waterLevelRise();}}waterPlaneTransparent();// 此变量用作循环动画和销毁动画
        let waterLevelRiseAnimationId;function waterLevelRise() {waterLevelRiseAnimationId = requestAnimationFrame(waterLevelRise);organismPoolArr.map((item) => {item.visible = true;const yPos = item.userData.y;let alpha = item.material.uniforms.alpha.value;if (item.position.y < yPos) {item.position.y += 0.01;}if (alpha < 1) {alpha += 0.02;item.material.uniforms.alpha.value = alpha;}if (item.position.y >= yPos && alpha >= 1) {// 传递事件告知动画执行完毕emit('craftAnimationEnd');cancelAnimationFrame(waterLevelRiseAnimationId);}});}}).start();}
}
// 首次进入动画
function eventAnimation() {new TWEEN.Tween(camera.position).to({ x: 0.103, y: 179.349, z: 123.908 }, 2000).easing(TWEEN.Easing.Sinusoidal.InOut).onUpdate(() => {controls.target.set(0, 0, 0);controls.update();}).onComplete(() => {// 初始化标签
      initLabel(sewageModel);// 将人物标签添加到人物模型中people.children[0].add(css2DPeopleLabel);// 设置位置在人物模型头顶css2DPeopleLabel.position.set(0, 2.2, 0);// 设置合适大小css2DPeopleLabel.scale.set(0.1, 0.1, 0.1);// 人物标签默认隐藏显示css2DPeopleLabel.visible = false;}).start();
}
function createEnvironment(texture) {// scene.environment = texture;// hdr作为环境贴图生效,设置.mapping为EquirectangularReflectionMappingtexture.mapping = THREE.EquirectangularReflectionMapping;// 创建一个巨大球体作为整个天空环境const sphere = new THREE.SphereGeometry(1000, 512, 512);const material = new THREE.MeshBasicMaterial({map: texture,side: THREE.DoubleSide,});const mesh = new THREE.Mesh(sphere, material);mesh.position.y -= 100;scene.add(mesh);
}
</script>
<style lang='less'>
@import './index.less';
</style>

需要全部完整案例源码,访问百度网盘:

链接:https://pan.baidu.com/s/1Ib5nq3MueA-6-OfnVvmqJg 
提取码:pgml

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

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

相关文章

反射DLL注入原理解析

反射 DLL 注入又称 RDI,与常规 DLL 注入不同的是,它不需要 LoadLibrary 这个函数来加载 dll,而是通过 DLL 内部的一个函数来自己把自己加载起来,这么说可能会有一点抽象,总之这个函数会负责解析DLL文件的头信息、导入函数的地址、处理重定位等初始化操作,先不用理解这个函…

Neo4j:图数据库的革命性力量

Neo4j 首席技术官 @prathle 撰写了一篇出色的博文,总结最近围绕 GraphRAG 的热议、我们从一年来帮助用户使用知识图谱 + LLM 构建系统中学到的东西,以及我们认为该领域的发展方向。Neo4j一时间又大火起来,本文将带你快速入门这神奇的数据库。前言 Neo4j是一款符合ACID标准的…

Linux常用文件操作命令

本章将和大家分享Linux常用的文件操作命令。本章将和大家分享Linux常用的文件操作命令。废话不多说,下面我们直接进入主题。 一、目录切换(cd命令) 在Linux系统中,cd 是一个用于切换当前工作目录的命令,它是 "change directory" 的缩写。基本用法如下所示: 1、…

Windows10下的docker容器启动命令docker -v相对路径的挂载目录位置

今天研究docker容器时,启动命令使用到了docker -v test:/app/backend/data 有个从宿主机写入文件到容器这个目录的需求,于是就尝试在宿主机上找到这个test目录 找了一圈都没找到,于是四处搜索,终于在stackoverflow上面找到了 https://stackoverflow.com/questions/61083772…

基于GA遗传优化算法的Okumura-Hata信道参数估计算法matlab仿真

1.算法仿真效果 matlab2022a仿真结果如下(完整代码运行后无水印):2.算法涉及理论知识概要遗传算法(Genetic Algorithm, GA)是一种模拟自然界生物进化过程的全局优化搜索算法,由John Holland于1975年提出。它利用达尔文的自然选择和遗传学原理,通过选择、交叉、变异等操作…

LTPSICE 小知识

1、初值设置:

软件工程进度报告——第二周

本周总结: 本周学习了Java语言的开发软件jdk的下载安装和使用方法,java代码的简单编写 1.下载安装jdk jdk需要在Oracle官网下载,下载地址:www.oracle.com下载时只需选择对应系统的安装包安装即可 2.jdk的安装目录 bin:该路径下存放了各种工具命令,其中比较重要的有:javac…

2024.07.13hadoop总结

hadoop基础概念学习在这之前并不了解hadoop,甚至没怎么听人提起过,直到学习大数据技术需要hadoop和python才开始学习。 hadoop的概念还没有完全了解完全,但是它的核心是处理和存储大数据,需要在虚拟机上面进行系统的测试

2024暑假第二周总结

运算符总结 对字面量或者变量进行操作的符号 算数运算符 加 减 乘 除 取模 取余 加减乘 public class yunsuanfu {public static void main(String[] args) {//+System.out.println(3+2);//5//-System.out.println(3-2);//1//*System.out.println(2*2);//4//如果计算的时候有小…

周总结

这周主要练习springboot3+vue3,开发大事件系统,Hadoop还未开始学,计划完成大事件开发后冲击Hadoop,在这里主要说一下我后端的开发心里路程吧。 Spring Boot 是一种基于 Spring 框架的开发工具,它旨在简化 Spring 应用程序的开发和部署过程。作为一名后端开发人员,我对 Sp…

Linux 中sed命令输出匹配字符的行号

001、[root@PC1 test]# ls a.txt [root@PC1 test]# cat a.txt ## 测试数 aa bbb dd ff 77 dd 22 44 77 88 cc dd ee ff [root@PC1 test]# sed -n /dd/p a.txt ## 输出匹配dd的行 dd ff 77 dd cc dd [root@PC1 test]# sed -n /dd/= a.txt ## 输出匹配字符的行号 2 3…