分享react+three.js展示温湿度采集终端

前言

气象站将采集到的相关气象数据通过GPRS/3G/4G无线网络发送到气象站监测中心,摆脱了地理空间的限制。

前端:气象站主机将采集好的气象数据存储到本地,通过RS485等线路与GPRS/3G/4G无线设备相连。

通信:GPRS/3G/4G无线设备通过互联网与物联网云平台相连,气象站有计划的将收集到的气象信息通过无线设备发送到监控数据中心。

后台:气象监控中心通过互联网实现了对前端所有的自动气象站数据的采集和整合。

1、摆脱了地理空间的限制,可以在有无线信号的任何地方架设自动气象站点。

2、高规格工业级无线通信设备,有力的保证了气象数据的稳定可靠。

3、体积小巧、安装方便,使得现场安装调试人员轻松高效。

4、费用低廉,降低了运用成本。

温度、湿度等环境数据整合,趋势模拟。

温湿度采集终端

Pt100 就是说它的阻值在 0 度时为 100 欧姆, PT100 温度传感器。是一种以铂(Pt) 作成的电阻式温度传感器,属于正电阻系数, 其电阻和温度变化的关系式如下: R=Ro(1+α T)。广泛应用于实验室及工业环境。

技术参数

       存储温度:-10 ~ +55 °C、湿度 0~85%RH

       测量精度:温度: ±0.5°C ~ ±0.7°C

       显示分辨率: 0.1 C

       记录时间间隔:2秒~24小时

       存储:数据存储量 65000组数据

       电池电量:电池类型 1颗 2600mA 18650锂电池 

       电池寿命:3 年(测量速率在10秒/刷新 300秒/记录)

       尺寸:135mm×125mm×36mm

       材料/外壳: ABS工程塑料

PLC版

web简版

react+three.js,无三维建模软件,web三维展现温湿度采集器

应用程序的模块化理念,使用模块来构建你的代码。通过将实现隐藏在一个简单的接口后面,您可以使您的应用程序万无一失且易于使用。它只做它应该做的,没有别的 通过隐藏实现,我们对使用我们代码的人实施了良好的编码风格。您可以访问的实现越多,它就越有可能成为您以后必须处理的复杂的半生不熟的“修复”。创建3D场景时,唯一的限制是您的想象力 - 以及您的技术知识深度。要点是如何描述3D空间的坐标系和用于在坐标系内移动对象。场景图是一种用于描述构成我们场景的对象层次结构的结构,向量是用于描述3D空间中的位置(以及许多其他事物) ,还有不少于两种描述旋转的方式:欧拉角Euler angles和四元数quaternions

依赖

"react": "^18.2.0",

"three": "^0.162.0",

app.tsx

import React, { useEffect, useRef, useState } from 'react'
import './App.css';
import { World } from './World/World.js';

interface appProps {
  style?: Record<string, unknown>;
  [key: string]: unknown;
}

function App(props: appProps) {

  const { style, ...pros} = props;

  const renderRef = useRef(null);

  let  world: World;

  useEffect(() => {
    // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
    if (renderRef && renderRef.current) {
      // Get a reference to the container element
      //const container = document.querySelector('#scene-container');
      //const container = document.getElementById('scene-container')
      // 1. Create an instance of the World app
      //world = new World(container);
      world = new World(renderRef.current);
      
      // 2. Render the scene
      // start the animation loop
      world.start();
    }

    const timer = setInterval(() => {
      if(isAutoRotate){
        world.start();
        world.tick();
      }else{
        world.stop();
      }
    }, 1);

    return () => {
      cancelAnimationFrame(1);
      clearInterval(timer);
    };

  }, [renderRef])


  return (
    <div className="App">
      <header className="header"></header>
      <main>
        <div id="scene-container" ref={renderRef} style={{ position: 'relative', width: '100%', height: 'calc( 100vh - 100px )', ...style }} {...pros}>
          </div>
      </main>
      <footer style={ { background: 'skyblue', height: '30px' }}></footer>
    </div>
  )
}

export default App;

world.js

/* eslint-disable no-undef */
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
/*
 * @Date: 2024-03-21 14:57:52
 * @LastEditors: david
 * @LastEditTime: 2024-03-21 17:04:01
 * @FilePath: .\src\components\World.js
 * @Description: 创建三维场景单例
 */
import { createCamera } from '../components/camera.js';
import { createCube } from '../components/cube.js';
import { createScene } from '../components/scene.js';
import { createControls } from '../components/controls.js';
import { createLights } from '../components/lights.js';

import { createRenderer } from '../systems/renderer.js';
import { Resizer } from '../systems/Resizer.js';
import { Loop } from '../systems/Loop.js';

// These variables are module-scoped: we cannot access them
// from outside the module 将相机、渲染器和场景创建为模块作用域变量
let camera;
//let scene;
let light;
let renderer;
let controls;
let loop;
// 温湿度采集器
import { changeMaterial, updateData } from '../components/canvasTexture.js'


/**
 * @description: 初始化三维场景 容器
 * @param {string} container - 三维场景挂载的div容器
 * @return {*}
 */
class World {
    // 1. Create an instance of the World app
    constructor(container) {
        // 首次使用构造器实例
        if (!(World.instance instanceof World)) {
            // 初始化相机
            camera = createCamera();
            // 初始化场景
            model.scene = createScene();
            // 初始化灯光
            light = createLights({
                directionX: 30,
                directionY: 10,
                directionZ: 0.5
              });
            model.scene.add(...light);
            // 初始化渲染器
            renderer = createRenderer();
            renderer.setSize(container.clientWidth, container.clientHeight);
            // Type: Element | String
            container.appendChild(renderer.domElement);
            // container.innerHTML = null;

            loop = new Loop(camera, model.scene, renderer);

            // 初始化控制器
            controls = createControls(camera,renderer)

            //loop.updatables.push(controls);

            // 添加模型
            const cube = createCube();
            model.scene.add(cube);

            const  collectorCube = changeMaterial();
            // async await Promise resole reject Promise.all 解决异步加载模型和贴图
            collectorCube.then((res) => {
              model.scene.add(res);
              //loop.updatables.push(res);
            }).catch(err => {
              console.log('温湿度采集器添加失败:'+err)
            })

            // stop the cube's animation
            loop.updatables.push(cube);

            controls.addEventListener('change', () => {
                this.render();
            });

            const resizer = new Resizer(container, camera, renderer);
            resizer.onResize = () => {
                this.render();
            };

            this.render();
            this.animate();

            // 将this挂载到World这个类的instance属性上
            World.instance = this
        }
        return World.instance
    }
    // 2. Render the scene
    render() {
        // draw a single frame
        if ((Boolean(renderer)) && (Boolean(model.scene)) && (Boolean(camera))) {
            renderer.render(model.scene, camera);
        }
    }
    animate(){
        try{
            // eslint-disable-next-line no-undef
            //requestAnimationFrame(this.animate);
            requestAnimationFrame(this.animate.bind(this));
            TWEEN.update();
            //更新控制器
            this.render()
        } catch (error) {
            // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
            console.log(`Failed to add world imagery: ${error}`);
        }
        // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
        if (controls) {
            controls.update();
        }
    }
}

export { World };

camera.js

import { PerspectiveCamera, MathUtils } from 'three';

function createCamera() {
  const camera = new PerspectiveCamera(
    45, // fov = Field Of View
    1, // aspect ratio (dummy value)
    0.1, // near clipping plane
    10000, // far clipping plane
  );

  // move the camera back so we can view the scene
  // camera.position.set(0, 0, 30);

  const layoutWidth = 25;

  const angle = camera.fov / 2;  // 夹角
  const rad = MathUtils.degToRad(angle);  // 转为弧度值
  const cameraZ = layoutWidth / 2 / Math.tan(rad);
  // 调整相机的 Z 轴位置,使桌台元素完整显示到场景
  camera.position.set(0, 15, cameraZ);

  return camera;
}

export { createCamera };

scene.js

import { Color, Scene, Fog } from 'three';

function createScene() {
  const scene = new Scene();
  scene.background = new Color(0xe6f4ff);
  scene.fog = new Fog( 0xa0a0a0, 5, 250 );

  return scene;
}

export { createScene };

controls.js

import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
function createControls ( Camera, renderer ) {
  // 轨道控制器
  const controls  = new OrbitControls(Camera, renderer.domElement);

  //设置控制器的中心点
  controls.target.set(0, 10, 0);
  const distanceZ = Camera.position.z;
  // 如果使用animate方法时,将此函数删除
  //controls.addEventListener( 'change', render );
  // 使动画循环使用时阻尼或自转 意思是否有惯性
  controls.enableDamping = false;
  //动态阻尼系数 就是鼠标拖拽旋转灵敏度
  // 阻尼系数
  controls.dampingFactor = 0.1;

  controls.minPolarAngle = Math.PI / 12;
  controls.maxPolarAngle = (Math.PI * 19) / 40;
  //是否可以缩放
  controls.enableZoom = true;
  //是否自动旋转
  controls.autoRotate = true;
  controls.autoRotateSpeed = 0.5;
  //设置相机距离原点的最远距离
  //controls.minDistance = 10;
  //设置相机距离原点的最远距离
  //controls.maxDistance = 200;
  controls.minDistance = distanceZ / 10;  // 相机离目标点的最小距离(放大)
  controls.maxDistance = distanceZ * 10;  // 相机离目标点的最大距离(缩小)
  //是否开启右键拖拽
  controls.enablePan = true;
  controls.tick = () => controls.update();

  return controls;
}

export { createControls };

lights.js

import { HemisphereLight, AmbientLight, DirectionalLight, DirectionalLightHelper, SpotLight, SpotLightHelper } from 'three';

function createLights({ directionX, directionY, directionZ }) {
  const hemisphere = new HemisphereLight(0xffffff, 0xffffff, 0.6);
  // move the light right, up, and towards us
  hemisphere.position.set(10, 10, 10);

  const ambient = new AmbientLight(0xffffff, 1);  // 环境光
  const spot = new SpotLight(0xfdf4d5);
  spot.position.set(5, directionY * 4, 0);
  spot.angle = Math.PI / 2;
  spot.power = 2000;
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const spotLightHelper = new SpotLightHelper(spot, 0x00f);

  const direct = new DirectionalLight(0xffffff, 3);  // 平行光
  direct.position.set(-directionX / 3, directionY * 4, directionZ * 1.5);
  direct.castShadow = true;
  direct.shadow.camera.left = -directionX;
  direct.shadow.camera.right = directionX;
  direct.shadow.camera.top = directionZ;
  direct.shadow.camera.bottom = -directionZ;

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const directLightHelper = new DirectionalLightHelper(direct, 1, 0xf00);

  return [hemisphere, ambient, spot, direct];

}

export { createLights };

cube.js

import { BoxGeometry, Mesh, 
  //MeshBasicMaterial, 
  MeshStandardMaterial, MathUtils  } from 'three';
function createCube() {
  // create a geometry
  const geometry = new BoxGeometry(1, 1, 1);

  // create a default (white) Basic material
  // const material = new MeshBasicMaterial();
  // Switch the old "basic" material to
  // a physically correct "standard" material
  const spec = {
    color: 'purple',
  }
  const material = new MeshStandardMaterial(spec);
  
  // create a Mesh containing the geometry and material
  const cube = new Mesh(geometry, material);

  cube.position.set(0, 10, 0);

  // cube.rotation.set(-0.5, -0.1, 0.8);
  const radiansPerSecond = MathUtils.degToRad(30);
  // this method will be called once per frame
  cube.tick = (delta) => {
    // increase the cube's rotation each frame
    cube.rotation.z += radiansPerSecond * delta;
    cube.rotation.x += radiansPerSecond * delta;
    cube.rotation.y += radiansPerSecond * delta;
  };

  return cube;
}

export { createCube };

loop.js

import { Clock } from "three";
const clock = new Clock();

class Loop {
  constructor(camera, scene, renderer) {
    this.camera = camera;
    this.scene = scene;
    this.renderer = renderer;
    // somewhere in the Loop class:
    this.updatables = []
  }
  start() {
    this.renderer.setAnimationLoop(() => {
        // tell every animated object to tick forward one frame
        // this.tick();
        // render a frame
        this.renderer.render(this.scene, this.camera);
    });
  }
  stop() {
    this.renderer.setAnimationLoop(null);
  }
  tick(){
    // only call the getDelta function once per frame!
    const delta = clock.getDelta();
    // console.log(
    //   `The last frame rendered in ${delta * 1000} milliseconds`,
    // );
    // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
    if(this.updatables.length){
        for (const object of this.updatables) {
            if(typeof object.tick == 'function'){
                object.tick(delta);
            }
        }
    }
  }
}

export { Loop };

renderer.js

import { WebGLRenderer, PCFSoftShadowMap } from 'three';

function createRenderer() {
  const renderer = new WebGLRenderer({ 
    alpha: true, // 透明度
    antialias: true // 开启抗锯齿
  });
  // turn on the physically correct lighting model
  renderer.physicallyCorrectLights = true;
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = PCFSoftShadowMap;
  renderer.setClearColor('#f8f8f6', 1);
  // eslint-disable-next-line no-undef
  renderer.setPixelRatio(window.devicePixelRatio);
  return renderer;
}

export { createRenderer };

resizer.js

const setSize = (container, camera, renderer) => {
    // Set the camera's aspect ratio
    camera.aspect = container.clientWidth / container.clientHeight;

    // update the camera's frustum
    camera.updateProjectionMatrix();

    // update the size of the renderer AND the canvas
    renderer.setSize(container.clientWidth, container.clientHeight);

    // set the pixel ratio (for mobile devices)
    // eslint-disable-next-line no-undef
    renderer.setPixelRatio(window.devicePixelRatio);
};

class Resizer {
    constructor(container, camera, renderer) {
        // set initial size on load
        setSize(container, camera, renderer);
        // eslint-disable-next-line no-undef
        window.addEventListener("resize", () => {
            // set the size again if a resize occurs
            setSize(container, camera, renderer);
            // perform any custom actions
            this.onResize();
        });
    }
    // 空方法, 我们可以从Resizer类的外部自定义。
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    onResize() {}
  }
  
  export { Resizer };

canvasTexture.js

/* eslint-disable no-undef */
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
import { CanvasTexture, MeshLambertMaterial, BoxGeometry, Mesh,    } from 'three';
import moment from 'moment';
import collectorImg from '../assets/images/collector.png';
const meshcolor = 0xa1a5a9;
let cube;
let timeNow = new Date().valueOf();
let time = { hum: 40.0, tep: 20.0 };

// 方法二:放大画布之后,需要把每一个绘制的 api 都乘以 dpr
// * 这样一来使用的时候就会很麻烦,所以我们需要把所有的绘制操作进行统一封装
// 可以参考这个库:https://github.com/jondavidjohn/hidpi-canvas-polyfill,不过这个库也不是所有 api 都覆盖
const adaptDPR = (canvas)=> { // 在初始化 canvas 的时候就要调用该方法
  const context = canvas.getContext('2d');
  const devicePixelRatio = window.devicePixelRatio || 1;
  const backingStoreRatio = context.webkitBackingStorePixelRatio ||
                            context.mozBackingStorePixelRatio ||
                            context.msBackingStorePixelRatio ||
                            context.oBackingStorePixelRatio ||
                            context.backingStorePixelRatio || 1;
  const ratiodpr = devicePixelRatio / backingStoreRatio;
  const { width, height } = canvas;
  // 重新设置 canvas 自身宽高大小和 css 大小。放大 canvas;css 保持不变,因为我们需要那么多的点
  // upscale the canvas if the two ratios don't match
  if (devicePixelRatio !== backingStoreRatio) {
    canvas.width = width * ratiodpr;
    canvas.height = height * ratiodpr;
    canvas.style.width = width + 'px';
    canvas.style.height = height + 'px';
    // 注意这里没有用 scale
    // now scale the context to counter
    // the fact that we've manually scaled
    // our canvas element 通过backing store的像素比例和设备像素比(dpr)来控制你的图片和canvas是保证图片质量和清晰的保证。
    context.scale(ratiodpr, ratiodpr);
  }
}
// 每个涉及绘制的 api 时都乘以 dpr
// 获取带数据的canvas
const getTextCanvas = async ({ tep, hum }) => {
  const time = moment().format('HH:mm:ss');
  const width = 310, height = 173;
  const canvas = document.createElement('canvas');
  canvas.width = width;
  canvas.height = height;
  adaptDPR(canvas);
  const ctx = canvas.getContext('2d');
  return new Promise((resole) => {
    if (ctx) {
      const img = new Image();
      img.src = collectorImg;
      //图片加载完后,将其显示在canvas中
      img.onload = () => {
        ctx.drawImage(img, 0, 0, width, height);
        ctx.font = 18 + 'px " bold';
        ctx.fillStyle = '#333';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        // 实时温度
        ctx.fillText(tep, width * 0.33, height * 0.44);
        // 实时湿度
        ctx.fillText(hum, width * 0.33, height * 0.70);
        // 数据采集时间
        ctx.font = 10 + 'px " bold';
        ctx.fillText(time, width * 0.24 , height * 0.245);
        resole(canvas);
      };
    }
  });
}

// 改变材质种类
const changeMaterial = async () => {
    const canvas = await getTextCanvas({ hum: 40, tep: 20 });
    if (canvas) {
        const texture = new CanvasTexture(canvas);
        const materials = [
        new MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),
        new MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),
        new MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),
        new MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),
        new MeshLambertMaterial({
            color: meshcolor,
            opacity: 1,
            transparent: true,
            map: texture,
        }),
        new MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),
        ];
        const geometry = new BoxGeometry(8.404, 6.16, 1);
        cube = new Mesh(geometry, materials);
        cube.position.set(0, 15, 0);
        //scene.add(cube);
        return cube;
    }
}

const updateData = async () => {
    if (new Date().valueOf() - timeNow > 500) {
        timeNow = new Date().valueOf();
        changeValues();
    }
    const canvas = await getTextCanvas(time);
    if (canvas && cube) {
        cube.material[4].map = new CanvasTexture(canvas);
        cube.material.map.needsUpdate = true;
    }
}

// 更新time数据
const changeValues = () => {
    const hum = parseFloat((39 + Math.random() * 10).toFixed(1));
    const tep = parseFloat((19 + Math.random() * 5).toFixed(1));
    setTime({ hum: hum, tep: tep})
}

const setTime = (date)=>{
    time = date
}

export {
    changeMaterial,
    updateData
}

采集器正面贴图,空出需要动态渲染的时间、温度、湿度,采集器用用最简单的长方形盒子代替。

index.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

index.html

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="renderer" content="webkit">
    <meta name="force-rendering" content="webkit">
    <meta name="google-site-verification" content="FTeR0c8arOPKh8c5DYh_9uu98_zJbaWw53J-Sch9MTg">
    <meta data-rh="true" name="keywords" content="React three.js World示例">
    <meta data-rh="true" name="description" content="React three.js World示例">
    <meta data-rh="true" property="og:title" content="React three.js World示例">
    <link rel="icon" href="./favicon.ico">
    <title>React three.js World示例</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue 03 组件通信

Vue学习 Vue 0301 浏览器本地存储localStorageSessionStorage案例 todolist的完善 02 组件自定义事件Custom Events基本使用解绑自定义事件注意事项①② 总结案例 todolist的完善 03 全局事件总线GlobalEventBus案例 todolist的完善 04 消息的订阅与发布案例 todolist的完善 05…

利用R语言和curl库实现网页爬虫的技术要点解析

R语言简介 R语言是一种自由、跨平台的编程语言和软件环境&#xff0c;专门用于统计计算和数据可视化。它具有丰富的数据处理、统计分析和图形展示功能&#xff0c;被广泛应用于数据科学、机器学习、统计建模等领域。 R语言技术优势 丰富的数据处理功能&#xff1a; R语言拥有…

unity双层滑动实现

实现功能&#xff1a; 当滑动列表中内容处于顶端的时候&#xff0c;向上滑动优先滑动整个滑动列表&#xff0c;当滑动列表移动到设置位置&#xff0c;即设定的最高处时&#xff0c;继续移动列表内内容。向下移动亦然&#xff0c;当内容处于滑动列表顶端时&#xff0c;移动整个滑…

低功耗、低成本 NAS/公共文件夹 的可能性

使用现状&#xff1a;多台工作电脑&#xff0c;家里人手一台&#xff0c;还在两个住处 有好几台工作电脑&#xff0c;不同电脑不同OS有不同的用途&#xff0c;最大的问题就是各个电脑上文件的同步问题&#xff0c;这里当然就需要局域网里的公共文件夹&#xff0c;在NAS的问题上…

R语言使用dietaryindex包计算NHANES数据多种营养指数(2)

健康饮食指数 (HEI) 是评估一组食物是否符合美国人膳食指南 (DGA) 的指标。Dietindex包提供用户友好的简化方法&#xff0c;将饮食摄入数据标准化为基于指数的饮食模式&#xff0c;从而能够评估流行病学和临床研究中对这些模式的遵守情况&#xff0c;从而促进精准营养。 该软件…

Unity3d使用Jenkins自动化打包(Windows)(一)

文章目录 前言一、安装JDK二、安装Jenkins三、Jenkins插件安装和使用基础操作 实战一基础操作 实战二 四、离线安装总结 前言 本篇旨在介绍基础的安装和操作流程&#xff0c;只需完成一次即可。后面的篇章将深入探讨如何利用Jenkins为Unity项目进行打包。 一、安装JDK 1、进入…

【嵌入式机器学习开发实战】(十二)—— 政安晨:通过ARM-Linux掌握基本技能【C语言程序的安装运行】

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 嵌入式机器学习开发实战 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 在ARM-Linux系统中&#xff0c;C语言程序的安装和运行可…

快速上手Spring Cloud 六:容器化与微服务化

快速上手Spring Cloud 一&#xff1a;Spring Cloud 简介 快速上手Spring Cloud 二&#xff1a;核心组件解析 快速上手Spring Cloud 三&#xff1a;API网关深入探索与实战应用 快速上手Spring Cloud 四&#xff1a;微服务治理与安全 快速上手Spring Cloud 五&#xff1a;Spring …

啥也不会的大学生看过来,这8步就能系统入门stm32单片机???

大家好&#xff0c;今天给大家介绍啥也不会的大学生看过来&#xff0c;这8步就能系统入门stm32单片机&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 对于没有任何基础的大学生来…

数据库原理与应用(SQL Server)笔记 关系数据库

目录 一、关系数据库的基本概念&#xff08;一&#xff09;关系数据库的定义&#xff08;二&#xff09;基本表、视图&#xff08;三&#xff09;元组、属性、域&#xff08;四&#xff09;候选码、主码、外码 二、关系模型三、关系的完整性&#xff08;一&#xff09;实体完整…

快速上手Spring Cloud五:Spring Cloud与持续集成/持续部署(CI/CD)

快速上手Spring Cloud 一&#xff1a;Spring Cloud 简介 快速上手Spring Cloud 二&#xff1a;核心组件解析 快速上手Spring Cloud 三&#xff1a;API网关深入探索与实战应用 快速上手Spring Cloud 四&#xff1a;微服务治理与安全 快速上手Spring Cloud 五&#xff1a;Spring …

神策数据参与制定首份 SDK 网络安全国家标准

国家市场监督管理总局、国家标准化管理委员会发布中华人民共和国国家标准公告&#xff08;2023 年第 13 号&#xff09;&#xff0c;全国信息安全标准化技术委员会归口的 3 项国家标准正式发布。其中&#xff0c;首份 SDK 国家标准《信息安全技术 移动互联网应用程序&#xff0…

根据实例逐行分析NIO到底在做什么

Selector&#xff08;选择器&#xff09;是 Channel 的多路复用器&#xff0c;它可以同时监控多个 Channel 的 IO 状况&#xff0c;允许单个线程来操作多个 Channel。Channel在从Buffer中获取数据。 选择器、通道、缓冲池是NIO的核心组件。 一、新建选择器 此时选择器内只包含…

HackTheBox-Machines--Legacy

文章目录 1 端口扫描2 测试思路3 445端口漏洞测试4 flag Legacy 测试过程 1 端口扫描 nmap -sC -sV 10.129.227.1812 测试思路 目标开启了135、139、445端口&#xff0c;445 SMB服务存在很多可利用漏洞&#xff0c;所以测试点先从445端口开始。而且在Nmap扫描结果中&#xff0c…

操作系统练习-操作系统的发展与分类

批量处理系统 ----------------------------------------------------------------------------------------------------------------------------- 1. 下列关于批处理系统的叙述中&#xff0c;正确的是( )。 I.批处理系统允许多个用户与计算…

百度智能云千帆,产业创新新引擎

本文整理自 3 月 21 日百度副总裁谢广军的主题演讲《百度智能云千帆&#xff0c;产业创新新引擎》。 各位领导、来宾、媒体朋友们&#xff0c;大家上午好。很高兴今天在石景山首钢园&#xff0c;和大家一起沟通和探讨大模型的发展趋势&#xff0c;以及百度最近一段时间的思考和…

camtasia怎么添加背景图 camtasia怎么添加背景音乐

在进行视频编辑时&#xff0c;添加合适的背景图和背景音乐是很重要的。美观的背景图可以增强视频的视觉体验&#xff0c;让画面更加生动和谐&#xff0c;而添加背景音乐&#xff0c;则能够调节气氛&#xff0c;让观众更好地沉浸到视频中。接下来我将为大家介绍&#xff1a;camt…

专题:一个自制代码生成器(嵌入式脚本语言)之应用实例

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 专题&#xff1a;一个自制代码…

网络原理-传输层-UDP报文结构

本文介绍UDP报文 有很多友友搞不清楚UDP报文的详细结构还有TCP的详细结构,所以专门分开来讲 以免弄混. 首先我们先看一下整个UDP结构,让大家有一个全方面的认识 下面我们来详细解释UDP报 16位源端口号(本机):就是2字节大小,16个二进制位. 16位目的端口号(目的机):也是2字节…

element-ui autocomplete 组件源码分享

紧接着 input 组件的源码&#xff0c;分享带输入建议的 autocomplete 组件&#xff0c;在 element-ui 官方文档上&#xff0c;没有这个组件的 api 目录&#xff0c;它的 api 是和 input 组件的 api 在一起的&#xff0c;看完源码之后发现&#xff0c;源码当中 autocomplete 组件…
最新文章