创建一个electron桌面备忘录

news2024/11/19 9:31:50

 

 

Sound Of Silence

1.创建electron项目命令: npm create @quick-start/electron my-new-project

        2选择:√ Select a framework: » vue

        √ Add TypeScript? ... No

        √ Add Electron updater plugin? ... Yes

        √ Enable Electron download mirror proxy? ... Yes

        3.命令:cd my-new-project

        4.命令:yarn

        5.启动命令: yarn dev

        6.打包命令:yarn build:win

 主进程代码index.js:

import { app, shell, BrowserWindow, ipcMain } from 'electron'
import { join } from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset'
function createWindow() {
  // Create the browser window.创建浏览器窗口。
  const mainWindow = new BrowserWindow({
    width: 900,
    height: 670,
    // 设置窗口的尺寸是否包含窗口边框和标题栏
    useContentSize: true,
    // 在创建 Electron 主窗口时禁用窗口外框
    frame: false,
    // 控制是否显示的变量
    show: false,
    // 设置自动隐藏菜单栏为 true
    autoHideMenuBar: true,
    alwaysOnTop: true,
    ...(process.platform === 'linux' ? { icon } : {}),
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false
    }
  })
  mainWindow.on('ready-to-show', () => {
    mainWindow.show()
  })
  mainWindow.webContents.setWindowOpenHandler((details) => {
    shell.openExternal(details.url)
    return { action: 'deny' }
  })
  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
  } else {
    mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
  }
}
app.whenReady().then(() => {
  electronApp.setAppUserModelId('com.electron')
  app.on('browser-window-created', (_, window) => {
    optimizer.watchWindowShortcuts(window)
  })
  ipcMain.on('ping', () => console.log('pong'))
  createWindow()
  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

preload预加载的代码index.js:

import { contextBridge } from 'electron'
import { electronAPI } from '@electron-toolkit/preload'

// Custom APIs for renderer
const api = {}

// Use `contextBridge` APIs to expose Electron APIs to
// renderer only if context isolation is enabled, otherwise
// just add to the DOM global.
if (process.contextIsolated) {
  try {
    contextBridge.exposeInMainWorld('electron', electronAPI)
    contextBridge.exposeInMainWorld('api', api)
  } catch (error) {
    console.error(error)
  }
} else {
  window.electron = electronAPI
  window.api = api
}

渲染进程的代码main.js:

import './assets/css/main.css'
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')

index.html

 

<!doctype html>
<html>
<head>
  <meta charset="UTF-8" />
  <title></title>
  <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
  <meta http-equiv="Content-Security-Policy" />
  <!-- content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"  -->
  <!-- <iframe frameborder="0" width="0" height="0"></iframe> -->
</head>
<body>
  <div id="app"></div>
  <script type="module" src="/src/main.js"></script>
</body>
</html>

 App.vue

<template>
  <MyLogs />
</template>
<script setup>
import MyLogs from './components/MyLogs.vue'
</script>

 MyLogs.vue

<template>
  <div>
    <div class="header">
      <a href="https://blog.csdn.net/lulei5153" title="与妖为邻CSDN博客" class="" target="_blank">
        <img src="../assets/img/kong.jpg" alt="与妖为邻" style="border-radius: 50%" />
      </a>
      <button v-if="!formVisible" class="openForm" @click="openForm">编辑</button>
      <button v-if="formVisible" @click="closeForm">取消编辑</button>
      <NowTime />
      <iframe
        ref="weather"
        frameborder="0"
        width="150"
        height="36"
        scrolling="no"
        hspace="0"
        src="https://i.tianqi.com/?c=code&id=99"
        style="margin-left: 20px"
      ></iframe>
      <span class="windowTool">
        <i class="minimize"><img src="../assets/img/最小化.svg" alt="最小化" /></i>
        <i class="maximize"><img src="../assets/img/最大化.svg" alt="最大化" /></i>
        <i class="close"><img src="../assets/img/关闭.svg" alt="关闭" /></i>
      </span>
    </div>
    <form
      v-if="formVisible"
      class="draggable-form"
      :style="{ top: formPosition.y + 'px', left: formPosition.x + 'px' }"
      @submit.prevent="addMemo"
    >
      <div v-drag drag-min-top="50" class="form-title" @mousedown="startDrag">{{ formTitle }}</div>
      <div class="form-content">
        <input type="reset" value="重置" />
        <textarea v-model="newItem" rows="10" placeholder="请输入备注内容"></textarea>
        <button type="submit" class="addBtn">添加</button>
      </div>
    </form>
    <div class="memo" @click="handleMemoAction">
      <div v-for="(memo, index) in memos" :key="index" class="item">
        <span class="item-number">{{ index + 1 }}.</span>
        <button v-if="showActions && !memo.finished" @click="completeMemo(index)">完成</button>
        <button v-if="showActions && memo.finished" @click="cancelMemo(index)">取消</button>
        <span class="text-content" :class="{ content: true, finish: memo.finished }">
          {{ memo.name }}
        </span>
        <button v-if="showActions && memo.finished" @click="reworkMemo(index)">修改</button>
        <button
          v-if="showActions && memo.finished"
          v-show="noindex == index ? false : true"
          class="deleteBtn"
          @click="deleteMemo(index)"
        >
          删除
        </button>
        <span v-show="noindex == index ? true : false" class="alter">
          <textarea v-model="newItem" rows="10"></textarea>
          <button @click="csu">提交</button>
        </span>
      </div>
    </div>
  </div>
</template>
<script setup>
import NowTime from './NowTime.vue'
import { ref } from 'vue'
import '../assets/css/MyLogs.css'
import Drag from '../assets/js/Drag.js'
const { formTitle, formPosition, startDrag } = Drag()
const formVisible = ref(false)
const newItem = ref('')
const memos = ref([])
const showActions = ref(false)
const noindex = ref(-1)
const openForm = () => {
  formVisible.value = true
  showActions.value = true
}
const closeForm = () => {
  formVisible.value = false
  showActions.value = false
}
const reworkMemo = (index) => {
  if (newItem.value === '' || false) {
    newItem.value = memos.value[index].name
    noindex.value = index
    formVisible.value = false
    showActions.value = false
  } else {
    newItem.value = ''
    noindex.value = -1
  }
}
const csu = () => {
  if (noindex.value === -1) {
    return
  }
  memos.value[noindex.value].name = newItem.value
  // 取消备忘录的完成状态
  memos.value[noindex.value].finished = false
  noindex.value = -1
  newItem.value = ''
  saveTodo()
}
const addMemo = () => {
  if (newItem.value.trim() !== '') {
    memos.value.push({ name: newItem.value, finished: false })
    newItem.value = ''
    formVisible.value = false
    showActions.value = false
    saveTodo()
  }
}
const completeMemo = (index) => {
  memos.value[index].finished = true
  saveTodo()
}
const cancelMemo = (index) => {
  memos.value[index].finished = false
  saveTodo()
}
const deleteMemo = (index) => {
  memos.value.splice(index, 1)
  updateItemNumbers()
  formVisible.value = false
  showActions.value = false
  saveTodo()
}
const handleMemoAction = (event) => {
  const target = event.target
  if (target.innerHTML === '完成') {
    // handle complete action
  } else if (target.innerHTML === '取消') {
    // handle cancel action
  } else if (target.innerHTML === '删除') {
    // handle delete action
  }
}
const saveTodo = () => {
  localStorage.myLogs = JSON.stringify(memos.value)
}
const loadTodo = () => {
  const savedMemos = JSON.parse(localStorage.myLogs ?? '[]')
  memos.value = savedMemos
  updateItemNumbers()
}
const updateItemNumbers = () => {
  const itemNumbers = document.querySelectorAll('.item-number')
  itemNumbers.forEach((item, index) => {
    item.textContent = index + 1
  })
}
loadTodo()
</script>
<style scoped></style>

NowTime.vue

<template>
  <div>
    <p>{{ dateTime }}</p>
    <sub>{{ dayTime }}</sub>
    <p>{{ currentTime }}</p>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const dateTime = ref('')
const dayTime = ref('')
const currentTime = ref('')
const updateTime = () => {
  const now = new Date()
  const year = now.getFullYear()
  let month = now.getMonth() + 1
  const day = now.getDate()
  let hour = now.getHours()
  let min = now.getMinutes()
  let second = now.getSeconds()
  const arrWork = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
  const week = arrWork[now.getDay()]
  month = month < 10 ? '0' + month : month
  hour = hour < 10 ? '0' + hour : hour
  min = min < 10 ? '0' + min : min
  second = second < 10 ? '0' + second : second
  dateTime.value = `${year}-${month}-${day}`
  dayTime.value = `${week}`
  currentTime.value = `${hour}:${min}:${second}`
}
onMounted(() => {
  window.setInterval(updateTime, 1000)
  updateTime()
})
</script>
<style scoped>
div {
  display: flex;
}
p {
  font-size: 25px;
  background: -webkit-linear-gradient(315deg, #e1ff00 50%, #ff0000);
}
sub {
  margin: 15px 0 0 0;
  background: -webkit-linear-gradient(315deg, hsl(0, 0%, 100%) 50%, #fcf401);
}
p,
sub {
  /*将背景剪切成文字的形状*/
  background-clip: text;
  -webkit-background-clip: text;
  /*文字颜色设为透明,使文字与背景融为一体*/
  -webkit-text-fill-color: transparent;
  /* 设置字体粗细 */
  font-weight: 900;
  text-shadow: 2px -1px 8px rgba(250, 80, 193, 0.323);
}
</style>

拖拽窗口的代码Drag.js

/* eslint-disable prettier/prettier */
/* 引入 */
import { reactive, onMounted } from 'vue'
export default function () {
  /*窗口移动事件*/
  const formTitle = '鼠标事件绑定标题栏实现拖动功能'
  const formPosition = reactive({ x: 0, y: 0 }) // 记录窗口位置的变量
  const startDrag = (event) => {
    event.preventDefault() // 阻止默认拖动行为
    const offsetX = event.clientX - formPosition.x
    const offsetY = event.clientY - formPosition.y
    const onDrag = (e) => {
      let newX = e.clientX - offsetX
      let newY = e.clientY - offsetY

      // 边界检查
      newX = Math.max(0, Math.min(newX, window.innerWidth - formPosition.x))
      newY = Math.max(50, Math.min(newY, window.innerHeight - formPosition.y))

      formPosition.x = newX
      formPosition.y = newY
    }
    const onStopDrag = () => {
      document.removeEventListener('mousemove', onDrag)
      document.removeEventListener('mouseup', onStopDrag)
    }
    document.addEventListener('mousemove', onDrag)
    document.addEventListener('mouseup', onStopDrag)
  }
  onMounted(() => {
    const initialX = window.innerWidth / 4 // 窗口水平
    const initialY = window.innerHeight / 4 // 窗口垂直
    formPosition.x = initialX
    formPosition.y = initialY
  })

  return {
    formTitle,
    formPosition,
    startDrag
  }
}

MyLogs.css

button,
input {
  cursor: pointer;
  border: none;
  color: #ffffff94;
  text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
  background-color: hsla(160, 100%, 37%, 0.247);
  &:hover {
    color: #f6f200;
    background-color: hsla(160, 100%, 37%, 0.995);
    box-shadow: 0 0 15px rgba(255, 254, 254, 0.5);
  }
}
/* 头部样式 */
.header {
  width: 100%;
  height: 35px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background-color: #ffffff9c;
  -webkit-app-region: drag;
  z-index: 99;
  img {
    width: 30px;
    height: 30px;
    /* border-radius: 50%; */
    margin: 8px 0 0px 5px;
    -webkit-app-region: no-drag;
    transition: transform 0.3s ease;
    &:hover {
      transform: scale(1.2);
    }
  }
  button {
    font-size: 1.5rem;
    -webkit-app-region: no-drag;
    background-color: hsla(160, 100%, 37%, 0);
    &:hover {
      background-color: hsla(160, 100%, 37%, 0.445);
    }
  }
  iframe {
    -webkit-app-region: no-drag;
  }
  span {
    min-width: 110px;
    i {
      cursor: pointer;
      img {
        width: 30px;
        height: 30px;
        &:hover {
          background-color: hsla(0, 100%, 50%, 0.489);
        }
      }
    }
  }
}
/* 拖动窗口的样式 */
.draggable-form {
  position: absolute;
  /* 最小宽度 */
  min-width: 50%;
  border-radius: 8px;
  background-color: rgba(0, 0, 0, 0.443);
  z-index: 199;
  box-shadow: 0 0 10px rgba(255, 254, 254, 0.5);
}
.form-title {
  text-align: center;
  padding: 5px;
  color: hsla(160, 100%, 37%, 1);
  box-shadow: 0 0 3px rgba(255, 255, 255, 0.751);
  border-radius: 5px 5px 0 0;
  cursor: move;
}
.form-content {
  display: flex;
  margin: 2px 5px 5px 5px;
  box-shadow: 0 0 3px rgba(255, 255, 255, 0.751);
  border-radius: 0 0 5px 5px;
  input,
  button {
    font-size: 1.5rem;
    /* 文本竖排 */
    writing-mode: vertical-rl;
    /* 文字间距 */
    letter-spacing: 10px;
  }
  input {
    border-bottom-left-radius: 5px;
  }
  button {
    border-bottom-right-radius: 5px;
  }
  textarea {
    flex: 1;
    font-size: 1rem;
    background-color: rgba(0, 0, 0, 0.308);
    color: rgb(255, 255, 255);
    text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
    &::placeholder {
      text-align: center;
    }
  }
}
/* 文本显示区样式 */
.memo {
  display: flex;
  align-content: flex-start;
  flex-wrap: wrap;
  margin: 0 20px;
}
.item {
  margin: 5px 10px;
  padding: 0 5px;
  border-radius: 10px;
  box-shadow: 0 0 10px rgba(255, 254, 254, 0.5);
  display: flex;
  align-items: center;
  &:hover {
    box-shadow: 0 0 15px rgba(255, 254, 254, 0.5);
  }
  .alter {
    position: absolute;
    min-width: 50%;
    display: flex;
    top: 100px;
    textarea {
      flex: 1;
      font-size: 1rem;
      color: #f85f5faf;
    text-shadow: 1px 1px 1px #030303;
    background-color: hsla(160, 96%, 18%, 0.952);
    box-shadow:
    inset -2px -2px 3px rgba(255, 255, 255, 0.6),
    inset 2px 2px 3px rgba(0, 0, 0, 0.6);
    border-radius: 10px 0 0 10px;
    }
    button {
      font-size: 1.5rem;
      /* 文本竖排 */
      writing-mode: vertical-rl;
      /* 文字间距 */
      letter-spacing: 10px;
      border-radius:0 5px  5px 0;
    }
  }
}
.item-number {
  /* 粗字体 */
  font-weight: bold;
  color: #fff;
  text-shadow: 1px 1px 1px #030303;
  /* 背景颜色 */
  background-color: #fbff06b6;
  border-radius: 20px;
}
.text-content {
  color: #1ded39a0;
  text-shadow: 1px 1px 1px #030303;
  background-color: #144756;
  border-radius: 10px;
  user-select: text;
  padding: 0 5px;
  &:hover {
    color: rgb(255, 250, 250);
    text-shadow: 1px 1px 1px #030303;
    background-color: rgb(191, 210, 255);
  }
}
/* 点击完成按钮显示.finish样式  */
.finish {
  /* 文本-装饰:删除线 */
  text-decoration: line-through;
  color: #f85f5faf;
  background-color: hsla(160, 100%, 37%, 0.2);
  text-shadow: 1px 1px 1px #030303;
  box-shadow:
    inset -2px -2px 3px rgba(255, 255, 255, 0.6),
    inset 2px 2px 3px rgba(0, 0, 0, 0.6);
  border-radius: 10px;
}
/* 删除按钮样式  */
.deleteBtn {
  color: #f3d303;
  text-shadow: 1px 1px 1px rgb(0, 0, 0);
  background: #ff0000;
  border-radius: 5px;
  border: none;
  margin: 5px;
  padding: 2px;
  /* 粗体 */
  font-weight: bold;
  &:hover {
    background-color: #f3d303;
    color: #ff0505;
  }
}

 main.css

@import './base.css';
/* 全局样式 */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  user-select: none;
}
body {
  min-height: 100vh;
  color: var(--color-text);
  background: var(--color-background);
  background-image: url('../img/wavy-lines.svg');
  background-size: cover;
  line-height: 1.6;
  font-family:
    Inter,
    -apple-system,
    BlinkMacSystemFont,
    'Segoe UI',
    Roboto,
    Oxygen,
    Ubuntu,
    Cantarell,
    'Fira Sans',
    'Droid Sans',
    'Helvetica Neue',
    sans-serif;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

base.css

:root {
  --ev-c-white: #ffffff;
  --ev-c-white-soft: #f8f8f8;
  --ev-c-white-mute: #f2f2f2;
  --ev-c-black: #1b1b1f;
  --ev-c-black-soft: #222222;
  --ev-c-black-mute: #282828;
  --ev-c-gray-1: #515c67;
  --ev-c-gray-2: #414853;
  --ev-c-gray-3: #32363f;
  --ev-c-text-1: rgba(255, 255, 245, 0.86);
  --ev-c-text-2: rgba(235, 235, 245, 0.6);
  --ev-c-text-3: rgba(235, 235, 245, 0.38);
  --ev-button-alt-border: transparent;
  --ev-button-alt-text: var(--ev-c-text-1);
  --ev-button-alt-bg: var(--ev-c-gray-3);
  --ev-button-alt-hover-border: transparent;
  --ev-button-alt-hover-text: var(--ev-c-text-1);
  --ev-button-alt-hover-bg: var(--ev-c-gray-2);
  --color-background: var(--ev-c-black);
  --color-background-soft: var(--ev-c-black-soft);
  --color-background-mute: var(--ev-c-black-mute);
  --color-text: var(--ev-c-text-1);
}

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

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

相关文章

记一次生产事故,来来回回搞了一个月

&#x1f345;我是小宋&#xff0c;关注我&#xff0c;带你轻松过面试 读源码。提升简历亮点&#xff08;14个demo&#xff09; &#x1f30f;号&#xff1a;tutou123com。拉你进专属群。 记一次生产事故&#xff0c;来来回回搞了一个月 背景 我们的主要业务是台湾省的一个小…

工业自动化中OBC充电机测试负载箱的应用

在工业自动化中&#xff0c;OBC充电机是电动汽车和混合动力汽车的重要组成部分。它的主要功能是为电动汽车的电池组提供电能&#xff0c;保证车辆的正常运行。为了保证OBC充电机的性能和安全性&#xff0c;通常需要对其进行严格的测试。在这个过程中&#xff0c;负载箱是一种非…

【SQL server速成之路】函数

&#xff08;3&#xff09;LEFT函数 LEFT ( character_expression , integer_expression ) 功能&#xff1a;返回从字符串character_expression左边开始&#xff0c;由integer_expression指定个数的字符。参数character_expression&#xff1a;为字符型表达式&#xff0c;integ…

C#的Switch语句2(如何快速中断函数执行)

文章目录 switch语法结构case具体的值枚举值字符串const关键字 如果没有匹配的值default语句不一定要在最后与C的差异-case穿透&#xff08;Fall-through&#xff09; 下一篇文章 switch语法结构 基础的语法结构&#xff0c;在上一篇文章已经写了&#xff0c;具体请看&#xf…

Python --- 如何修改Jupyter Notebook在本地保存文件的默认路径?

如何修改Jupyter Notebook在本地保存文件的默认路径&#xff1f; 一直以来都比较喜欢jupter notebook&#xff0c;自从用了以后就爱上了。平时用的时候&#xff0c;因为大多都是临时调用&#xff0c;每次在界面里直接new一个新的file就开干。 曾经也想过我创建的这些python文件…

MySQL从5.7升级到8.0步骤及其问题

MySQL从5.7升级到8.0步骤及其问题 前言 本文源自微博客&#xff0c;且以获得授权&#xff0c;请尊重版权。 一、需求背景 Docker环境下&#xff0c;MySQL5.7升级到8.0&#xff0c;数据迁移时使用的是mysqldump方式迁移。 二、迁移步骤 数据备份&#xff1a; docker exec -i 1…

QEMU + Vscode + Arm Arch‘s Linux调试小记

目录 下载QEMU 下载aarch64-gcc 下载BusyBox 编译linux 6.9.5的内核 启动&#xff01; 链接到vscode进行远程调试 Reference 前几天看到了一篇讲授如何调试ARM Linux内核的文章&#xff0c;这里现在记录一下调试ARM Linux内核的办法 下载QEMU 对于Arch Linux用户而言&a…

结构思考力:让你的思维更有条理

在这个信息爆炸的时代&#xff0c;如何让自己的思维更有条理&#xff0c;更高效地沟通显得尤为重要。最近读了《结构思考力》一书。今天&#xff0c;我想和大家分享一下读后感&#xff0c;从以下几个方面展开&#xff1a;1. 什么是结构思考力及其重要性&#xff1b;2. 为什么要…

数据治理创新路:建设数据集市,强化数据报送一致性新实践

随着信息化和数字化的飞速发展&#xff0c;数据已经成为企业运营和决策的核心要素。然而&#xff0c;数据治理的复杂性和多样性给企业带来了不小的挑战。为了更好地应对这些挑战&#xff0c;许多企业开始探索数据治理的创新路径&#xff0c;其中建设数据集市和强化数据报送一致…

Vue08-webpack使用

webpack使用 1、什么是Webpack 本质上&#xff0c; webpack是一个现代JavaScript应用程序的静态模块打包器(module bundler) 。当webpack处理应用程序时&#xff0c; 它会递归地构建一个依赖关系图(dependency graph) &#xff0c; 其中包含应用程序需要的每个模块&#xff0…

期货以旁观者心态关注市场,会更加理性

1.期货交易具备较高灵活度&#xff0c;相比于股票&#xff0c;期货盈利速度明显提升。针对普通投资者&#xff0c;适量参与中线投机更为合适。 2.选择期货品种需兼顾市场属性稳定与计划特点较弱两方面&#xff0c;以及波动剧烈、投机特征显著的品种。 3.若市场环境不利且缺乏机…

temu跨境选品师是怎么样的一个项目?

TEMU(特穆)跨境选品师项目&#xff0c;作为一项创新的全球商品采购和选品服务&#xff0c;正在逐步改变消费者对于跨境电商产品的认知和选择方式。这个项目不仅仅是一个简单的商品推荐平台&#xff0c;更是一种以数据驱动的精准选品策略的体现&#xff0c;为消费者提供了全新的…

【操作系统】操作系统课后作业-聊天程序

无名管道与有名管道的区别 无名管道&#xff1a; 它是半双工的&#xff0c;具有固定的读端和写端。 只能用于具有亲缘关系的进程之间的通信&#xff08;也是父子进程或者兄弟进程之间&#xff09;。 不是普通的文件&#xff0c;不属于其他任何文件系统&#xff0c;并且只存…

期望25K,我的React知识体系

面经哥只做互联网社招面试经历分享&#xff0c;关注我&#xff0c;每日推送精选面经&#xff0c;面试前&#xff0c;先找面经哥 我最终还是上岸了&#xff0c;花了3天总结了近万字的react知识体系思维导图&#xff0c;分享出来希望能帮助有缘人吧&#xff0c;以下只是部分截图&…

org.eclipse.milo opcua 库查看记录

1 Reference连接 在OPC UA Server中&#xff0c;所有Node之间都是使用Reference进行连接的。 读取时指定HierarchicalReferences就可以读取HierarchicalReferences及以下所有类型的节点。 2 nodeId读取 browse 默认读取了Method、Object、Variable类型节点&#xff0c;Refer…

CCS条形光源——HLDL3系列,长距离和宽范围照射应用的不二之选

机器视觉系统中&#xff0c;光源起着重要作用&#xff0c;不同类型的光源应用也不同&#xff0c;选择合适的光源成像效果非常明显。今天我们一起来看看CCS光源——工业用条形光源HLDL3系列。 高亮LED光源HLDL3系列 适用于长距离和宽范围照射的条形光源。 适用于各种检测案例&a…

Linux DNS配置文档

一、问题描述 1. 无法在浏览器通过域名访问百度&#xff1b; 2. 无法在终端 ping 通百度&#xff0c;例如&#xff1a;ping www.baidu.com 3. 可以 ping 通公网地址&#xff0c;例如&#xff1a;ping 114.114.114.114 或 ping 8.8.8.8 二、问题原因 域名解析 DNS 配置错误&am…

如何快速在一台新电脑上安装 Python 环境

一、下载miniconda 1.下载 我们可以在清华大学开源软件镜像站下载最新版本的miniconda。如&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py38_4.9.2-Windows-x86_64.exe 2.安装 双击exe文件安装&#xff0c;如果没有特殊的需求&#x…

Erlang程序设计[Part2 chapter5-chapter8]

两种数据容器&#xff1a;元组、列表 part 2 chapter5 记录与映射组 记录 记录其实就是元组的另一种形式。通过使用记录&#xff0c;可以给元组里的各个元素关联一个名称。 映射 映射组是键 值对的关联性集合。 通过记录命名元组里的项 记录的产生背景&#xff1a; 对于小型元…

线上课堂知识付费小程序源码系统 全面升级+完整的安装包+搭建部署教程

系统概述 随着互联网的发展&#xff0c;线上教育和知识付费市场呈现出爆发式增长。线上课堂知识付费小程序源码系统为教育机构、培训师、个人创作者等提供了一个便捷、高效的平台&#xff0c;让他们能够将自己的知识和技能转化为实际收益。 代码示例 系统特色功能一览 1.拓展…