当前位置: 首页 > news >正文

小程序canvas2d实现横版全屏和竖版逐字的签名组件(字帖式米字格签名组件)

文章标题

  • 01 功能说明
  • 02 效果预览
    • 2.1 横版
    • 2.2 竖版
  • 03 使用方式
  • 04 横向签名组件源码
    • 4.1 html 代码
    • 4.2 业务 Js
    • 4.3 样式 Css
  • 05 竖向签名组件源码
    • 5.1 布局 Html
    • 5.2 业务 Js
    • 5.3 样式 Css

01 功能说明

技术栈:uniapp、vue、canvas 2d

需求

  • 实现横版的全名字帖式米字格签名组件,竖版逐字的字帖式米字格签名组件;
  • 支持配置文字描述、画笔颜色、画笔大小等;
  • 提供 submit 事件,当点击提交按钮时触发,回调参数是canvas转化为图片的地址;

02 效果预览

2.1 横版

横版截图
在这里插入图片描述

2.2 竖版

竖版截图
在这里插入图片描述

03 使用方式

// 使用横向签名------------------------
<template><HorizontalSign signText="赵钱孙" @submit="handleSubmit" /> 
</template><script>
import HorizontalSign from '@/components/HorizontalSign.vue';export default {components: { HorizontalSign },methods: {handleSubmit(imagePath) {console.log('--image--', imagePath);},},
} 
<script> // 使用竖向签名------------------------
<template><VerticalSign signText="赵钱孙"  @submit="handleSubmit" />
</template><script>
import VerticalSign from '@/components/VerticalSign.vue';export default {components: { VerticalSign },methods: {handleSubmit(imagePath) {console.log('--image--', imagePath);},},
}  
<script> 

04 横向签名组件源码

4.1 html 代码

<template><view class="wrapping"><!-- header 定位后以左上角顺时针旋转 90° --><view class="header-title flex col-center"><!-- <text> 签名:</text> --><!-- 预览图片(图片本身是正向的,但由于父元素旋转了90°所以正好能横向观看) --><!-- <image :src="previewImage" mode="aspectFit" class="small-preview" /> --><text class="desc-text">{{ description }}</text></view><!-- 实际保持直立正向 canvas 容器 --><view class="canvas-wrapper"><!-- 只展示限制数量文字的米字格,超过配置数量文字则不展示 --><view class="char-group flex-col flex-center" v-if="signText && signText.length <= riceGridLimit"><view class="char-box" v-for="(item, index) in signText" :key="index">{{ item }}</view></view><canvasid="signatureCanvas"type="2d"class="signature-canvas"@touchstart="handleTouchStart"@touchmove="handleTouchMove"@touchend="handleTouchEnd"@touchcancel="handleTouchEnd"disable-scroll></canvas></view><!-- footer 定位后以右下角顺时针旋转 90° --><view class="footer-btn flex"><view class="action-btn" @click="resetCanvas">重签</view><view class="action-btn submit-btn" @click="handleSubmit">{{ submitText }}</view></view><!--用于绘制并生成旋转为正向签名图片的 canvas 容器--><canvas id="previewCanvas" type="2d" class="preview-canvas"></canvas></view>
</template>

4.2 业务 Js

<script>
export default {props: {description: {type: String,default: '请使用正楷字体,逐字签写', //  文字描述},submitText: {type: String,default: '提交', // 提交按钮文字},dotSize: {type: Number,default: 4, // 签名笔大小},penColor: {type: String,default: '#000000', // 签名笔颜色},signText: {type: String,default: '', // 签名文字},riceGridLimit: {type: Number,default: 3, // 米字格展示字数最大限制},},data() {return {mainCtx: null,mainCanvas: null,isDrawing: false,touchPoints: [],signIsMove: false,previewImage: '',canvasRatio: 1,};},mounted() {this.canvasRatio = uni.getWindowInfo().pixelRatio ?? 1;this.initCanvas();},methods: {initCanvas() {const domItem = uni.createSelectorQuery().in(this).select('#signatureCanvas');domItem.fields({ node: true, size: true }).exec((res) => {// Canvas 对象this.mainCanvas = res[0]?.node;// 渲染上下文this.mainCtx = this.mainCanvas.getContext('2d');// Canvas 画布的实际绘制宽高const width = res[0].width;const height = res[0].height;// 初始化画布大小this.mainCanvas.width = width * this.canvasRatio;this.mainCanvas.height = height * this.canvasRatio;this.mainCtx.scale(this.canvasRatio, this.canvasRatio);this.setPen();});},setPen() {this.mainCtx.strokeStyle = this.penColor;this.mainCtx.lineWidth = this.dotSize;this.mainCtx.lineCap = 'round';this.mainCtx.lineJoin = 'round';},handleTouchStart(e) {const point = {x: e.changedTouches[0].x,y: e.changedTouches[0].y,};this.touchPoints.push(point);this.isDrawing = true;},handleTouchMove(e) {if (!this.isDrawing) return;const point = {x: e.touches[0].x,y: e.touches[0].y,};this.touchPoints.push(point);const len = this.touchPoints.length;if (len >= 2) {const prevPoint = this.touchPoints[len - 2];const currentPoint = this.touchPoints[len - 1];this.mainCtx.beginPath();this.mainCtx.moveTo(prevPoint.x, prevPoint.y);this.mainCtx.lineTo(currentPoint.x, currentPoint.y);this.mainCtx.stroke();this.signIsMove = true;}},handleTouchEnd() {this.isDrawing = false;this.touchPoints = [];},resetCanvas() {if (!this.signIsMove) {return;}this.mainCtx.clearRect(0, 0, 1000, 1000);this.setPen();this.touchPoints = [];this.previewImage = '';this.signIsMove = false;},async handleSubmit() {if (!this.signIsMove) {uni.showToast({ title: '请先完成签名', icon: 'none' });return;}try {const _this = this;uni.canvasToTempFilePath({canvas: this.mainCanvas,quality: 1,fileType: 'png',success: (res) => {let path = res.tempFilePath;_this.handlePreviewImage(path);},fail: (res) => {uni.showToast({ title: '提交失败,请重新尝试', icon: 'none' });},});} catch (err) {uni.showToast({ title: '签名失败,请重试', icon: 'none' });} finally {uni.hideLoading();}},handlePreviewImage(imagePath) {const _this = this;const previewDom = uni.createSelectorQuery().in(_this).select('#previewCanvas');previewDom.fields({ node: true, size: true }).exec((res) => {// Canvas 对象const canvas = res[0]?.node;// 渲染上下文const previewCtx = canvas.getContext('2d');const image = canvas.createImage();image.src = imagePath;image.onload = () => {let { width, height } = image;// 获取图片的宽高初始画布,canvas交换宽高canvas.width = height;canvas.height = width;// 设置白色背景previewCtx.fillStyle = '#FFFFFF';previewCtx.fillRect(0, 0, height, width);// 图片逆时针旋转90度,且换为弧度previewCtx.rotate((-90 * Math.PI) / 180);// 旋转后调整绘制的位置下移一个宽度的距离previewCtx.drawImage(image, -width, 0);};// 最终导出setTimeout(() => {uni.canvasToTempFilePath({canvas,fileType: 'png', // 指定文件类型quality: 1, // 最高质量success: (res) => {_this.previewImage = res.tempFilePath;uni.previewImage({ urls: [res.tempFilePath], current: 0 });_this.$emit('submit', res.tempFilePath);},fail: (err) => {uni.showToast({ title: '合成失败,请重试', icon: 'none' });},},_this);}, 300); // 增加最终导出前的延迟});},},
};
</script>

4.3 样式 Css

<style scoped>
.wrapping {position: relative;padding: 20rpx;margin: 20rpx;background-color: #fff;box-sizing: border-box;
}.header-title {position: absolute;right: 20rpx;top: 20rpx;height: 50rpx;z-index: 1000;transform-origin: top left;transform: translateX(100%) rotate(90deg);font-size: 32rpx;color: #333;
}.desc-text {color: #969799;
}.small-preview {width: 100rpx;height: 50rpx;border-bottom: 1px solid #333;
}.canvas-wrapper {position: relative;margin: auto;width: 60%;height: 80vh;background: #f7f8fa;
}.char-group {position: absolute;top: 0px;left: 0px;width: 100%;height: 100%;pointer-events: none;user-select: none;z-index: 1;gap: 20rpx;
}.char-box {padding: 36rpx;width: 30vw;height: 30vw;transform: rotate(90deg);font-size: 30vw;line-height: 30vw;text-align: center;color: #eeeeee;/* 使用虚线边框框住字体 *//* border: 1px dashed #ccc; *//* 使用米字格照片当背景图 */background: url('https://img1.baidu.com/it/u=2622499137,3527900847&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500') no-repeat;background-size: 100%;text-shadow: 1px 1px black, -1px -1px black, 1px -1px black, -1px 1px black;
}.signature-canvas {position: relative;width: 100%;height: 100%;z-index: 2;
}.footer-btn {position: absolute;left: 20rpx;bottom: 20rpx;transform-origin: bottom right;transform: translateX(-100%) rotate(90deg);z-index: 1000;gap: 32rpx;
}.action-btn {text-align: center;width: 200rpx;height: 96rpx;border-radius: 100rpx;font-size: 32rpx;line-height: 96rpx;color: #3874f6;border: 2rpx solid #3874f6;background: #fff;
}.submit-btn {color: #fff;border: 2rpx solid #3874f6;background: #3874f6;
}.preview-canvas {visibility: hidden;position: fixed;/* 将画布移出展示区域 */top: 100vh;left: 100vw;opacity: 0;z-index: 0;
}
</style>

05 竖向签名组件源码

5.1 布局 Html

<template><view class="signature-container"><view class="desc-text">{{ description }}</view><view class="signature-area"><view class="canvas-wrapper"><!-- 逐字展示文字 --><view class="char-box" v-if="signText && currentCharIndex < signText.length">{{ signText[currentCharIndex] }}</view><canvasid="signatureCanvas"class="signature-canvas"type="2d"@touchstart="handleTouchStart"@touchmove="handleTouchMove"@touchend="handleTouchEnd"@touchcancel="handleTouchEnd"disable-scroll></canvas></view><view class="action-box"><view class="action-btn" v-if="currentCharIndex > 0" @click="prevChar">上一字</view><view class="action-btn" @click="resetCanvas">清空画板</view><view class="action-btn" v-if="currentCharIndex < signText.length" @click="nextChar">{{ currentCharIndex < signText.length - 1 ? '下一字' : '确认' }}</view></view></view><view class="preview-title">逐字预览</view><view class="preview-content"><image v-for="(img, index) in previewImages" :key="index" :src="img" mode="aspectFit" class="preview-char" /></view><view class="action-box"><view class="action-btn submit-btn" @click="resetAllRecord">全部重签</view><view class="action-btn submit-btn" @click="handleSubmit">{{ submitText }}</view></view><!--用于拼接合并为完整签名图片的 canvas 容器--><canvas id="previewCanvas" type="2d" class="preview-canvas"></canvas></view>
</template>

5.2 业务 Js

<script>
export default {props: {description: {type: String,default: '请使用正楷字体,逐字签写', // 文字描述},submitText: {type: String,default: '提交', // 提交按钮文字},dotSize: {type: Number,default: 4, // 签名笔大小},penColor: {type: String,default: '#000000', // 签名笔颜色},signText: {type: String,default: '', // 签名文字},},data() {return {mainCtx: null,mainCanvas: null,isDrawing: false,touchPoints: [],allTouchPoints: [],signIsMove: false,currentCharIndex: 0,canvasRatio: 1,previewImages: [],};},mounted() {this.canvasRatio = uni.getWindowInfo().pixelRatio ?? 1;this.initCanvas();},methods: {initCanvas() {const domItem = uni.createSelectorQuery().in(this).select('#signatureCanvas');domItem.fields({ node: true, size: true }).exec((res) => {// Canvas 对象this.mainCanvas = res[0]?.node;// 渲染上下文this.mainCtx = this.mainCanvas.getContext('2d');// Canvas 画布的实际绘制宽高const width = res[0].width;const height = res[0].height;// 初始化画布大小this.mainCanvas.width = width * this.canvasRatio;this.mainCanvas.height = height * this.canvasRatio;this.mainCtx.scale(this.canvasRatio, this.canvasRatio);this.setPen();});},setPen() {this.mainCtx.strokeStyle = this.penColor;this.mainCtx.lineWidth = this.dotSize;this.mainCtx.lineCap = 'round';this.mainCtx.lineJoin = 'round';},handleTouchStart(e) {const point = {x: e.changedTouches[0].x,y: e.changedTouches[0].y,};this.touchPoints.push(point);this.allTouchPoints.push(point);this.isDrawing = true;},handleTouchMove(e) {if (!this.isDrawing) return;const point = {x: e.touches[0].x,y: e.touches[0].y,};this.touchPoints.push(point);this.allTouchPoints.push(point);const len = this.touchPoints.length;if (len >= 2) {const prevPoint = this.touchPoints[len - 2];const currentPoint = this.touchPoints[len - 1];this.mainCtx.beginPath();this.mainCtx.moveTo(prevPoint.x, prevPoint.y);this.mainCtx.lineTo(currentPoint.x, currentPoint.y);this.mainCtx.stroke();this.signIsMove = true;}},handleTouchEnd() {this.isDrawing = false;this.touchPoints = [];},getRectangle(points) {// 计算每个字符的实际大小let minX = Number.POSITIVE_INFINITY;let minY = Number.POSITIVE_INFINITY;let maxX = Number.NEGATIVE_INFINITY;let maxY = Number.NEGATIVE_INFINITY;for (let point of points) {minX = Math.min(minX, point.x);minY = Math.min(minY, point.y);maxX = Math.max(maxX, point.x);maxY = Math.max(maxY, point.y);}return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };},prevChar() {if (this.previewImages.length > 0) {this.previewImages.pop();this.currentCharIndex--;this.resetCanvas();}},nextChar() {if (!this.signIsMove) {uni.showToast({ title: '请先完成签名', icon: 'none' });return;}try {const { x, y, width, height } = this.getRectangle(this.allTouchPoints);const offset = 10;const _this = this;uni.canvasToTempFilePath({canvas: this.mainCanvas,x: x - offset,y: y - offset,width: width + offset * 2,height: height + offset * 2,success: (res) => {_this.previewImages.push(res.tempFilePath);_this.currentCharIndex++;_this.resetCanvas();},fail: () => {uni.showToast({ title: '提交失败,请重新尝试', icon: 'none' });},},_this);} catch (err) {uni.showToast({ title: '保存失败,请重试', icon: 'none' });}},resetCanvas() {this.mainCtx.clearRect(0, 0, 1000, 1000);this.setPen();this.touchPoints = [];this.allTouchPoints = [];this.signIsMove = false;},resetAllRecord() {this.previewImages = [];this.currentCharIndex = 0;this.resetCanvas();},async handleSubmit() {if (this.previewImages.length <= 0) {uni.showToast({ title: '请至少签写一个字', icon: 'none' });return;}try {this.handlePreviewImage();} catch (err) {uni.showToast({ title: '合成失败,请重试', icon: 'none' });}},handlePreviewImage() {const _this = this;const previewDom = uni.createSelectorQuery().in(_this).select('#previewCanvas');previewDom.fields({ node: true, size: true }).exec((res) => {// Canvas 对象const canvas = res[0]?.node;// 渲染上下文const previewCtx = canvas.getContext('2d');// 计算总宽度和单个字的尺寸const charWidth = 300 / this.previewImages.length;const charHeight = 300 / this.previewImages.length;const totalWidth = charWidth * this.previewImages.length;// 设置白色背景previewCtx.fillStyle = '#FFFFFF';previewCtx.fillRect(0, 0, totalWidth, charHeight);// 按顺序绘制每个图片for (let i = 0; i < this.previewImages.length; i++) {const image = canvas.createImage();image.src = this.previewImages[i];image.onload = () => {const x = i * charWidth;// 绘制当前图片previewCtx.drawImage(image, x, 0, charWidth, charHeight);};}// 最终导出setTimeout(() => {uni.canvasToTempFilePath({canvas,x: 0,y: 0,width: totalWidth,height: charHeight,fileType: 'png', // 指定文件类型quality: 1, // 最高质量success: (res) => {uni.previewImage({ urls: [res.tempFilePath], current: 0 });_this.$emit('submit', res.tempFilePath);},fail: (err) => {uni.showToast({ title: '合成失败,请重试', icon: 'none' });},},_this);}, 300); // 增加最终导出前的延迟});},},
};
</script>

5.3 样式 Css

<style scoped>
.signature-container {padding: 0 20rpx 40rpx 20rpx;background-color: #f5f5f5;box-sizing: border-box;
}.signature-area {padding: 50rpx;background-color: #fff;box-sizing: border-box;
}.desc-text {padding: 20rpx 0;font-size: 32rpx;color: #333;text-align: center;box-sizing: border-box;
}.canvas-wrapper {position: relative;width: 100%;/* 保持宽高比 */aspect-ratio: 1;/* height: 600rpx; */background: #fff;/* 使用虚线边框框住字体 *//* border: 1px dashed #ccc; *//* 使用米字格照片当背景图 */background: url('https://img1.baidu.com/it/u=2622499137,3527900847&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500') no-repeat;background-size: 100%;
}.char-box {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);font-size: 400rpx;text-shadow: 1px 1px black, -1px -1px black, 1px -1px black, -1px 1px black;color: #eeeeee;pointer-events: none;user-select: none;z-index: 1;
}.signature-canvas {position: relative;width: 100%;height: 100%;z-index: 2;
}.action-box {display: flex;margin-top: 32rpx;gap: 20rpx;
}.action-btn {flex: 1;text-align: center;padding: 16rpx 30rpx;font-size: 28rpx;color: #3874f6;border: 2rpx solid #3874f6;border-radius: 80rpx;box-sizing: border-box;
}.submit-btn {background: #3874f6;color: #fff;
}.preview-title {margin-top: 32rpx;width: 100%;text-align: center;font-size: 28rpx;color: #666;
}.preview-content {display: flex;flex-wrap: wrap;margin-top: 20rpx;background-color: #fff;padding: 20rpx 20rpx 0 20rpx;min-height: 190rpx;box-sizing: border-box;
}.preview-char {width: 150rpx;height: 150rpx;margin-right: 19rpx;margin-bottom: 20rpx;
}.preview-canvas {position: fixed;left: -2000px;width: 300px;height: 300px;
}
</style>

相关文章:

小程序canvas2d实现横版全屏和竖版逐字的签名组件(字帖式米字格签名组件)

文章标题 01 功能说明02 效果预览2.1 横版2.2 竖版 03 使用方式04 横向签名组件源码4.1 html 代码4.2 业务 Js4.3 样式 Css 05 竖向签名组件源码5.1 布局 Html5.2 业务 Js5.3 样式 Css 01 功能说明 技术栈&#xff1a;uniapp、vue、canvas 2d 需求&#xff1a; 实现横版的全…...

haproxy详解笔记

一、概述 HAProxy&#xff08;High Availability Proxy&#xff09;是一款开源的高性能 TCP/HTTP 负载均衡器和代理服务器&#xff0c;用于将大量并发连接分发到多个服务器上&#xff0c;从而提高系统的可用性和负载能力。它支持多种负载均衡算法&#xff0c;能够根据服务器的…...

SpringCloud框架下的注册中心比较:Eureka与Consul的实战解析

摘要 在探讨SpringCloud框架中的两种注册中心之前&#xff0c;有必要回顾单体架构与分布式架构的特点。单体架构将所有业务功能集成在一个项目中&#xff0c;优点是架构简单、部署成本低&#xff0c;但耦合度高。分布式架构则根据业务功能对系统进行拆分&#xff0c;每个模块作…...

前端调用串口通信

项目录结构 node项目 1&#xff09; 安装serialport npm install serialport 2&#xff09;编写index.js 1 const SerialPort require(serialport); 2 var senddata [0x02];//串口索要发送的数据源 3 var port new SerialPort(COM3);//连接串口COM3 4 port.on(open, fun…...

23、深度学习-自学之路-激活函数relu、tanh、sigmoid、softmax函数的正向传播和反向梯度。

在使用这个非线性激活函数的时候&#xff0c;其实我们重点还是学习的是他们的正向怎么传播&#xff0c;以及反向怎么传递的。 如下图所示&#xff1a; 第一&#xff1a;relu函数的正向传播函数是&#xff1a;当输入值&#xff08;隐藏层&#xff09;值大于了&#xff0c;就输出…...

《8天入门Trustzone/TEE/安全架构》

CSDN学院课程连接&#xff1a;https://edu.csdn.net/course/detail/39573...

计算机视觉中图像的基础认知

一、图像/视频的基本属性 在计算机视觉中&#xff0c;图像和视频的本质是多维数值矩阵。图像或视频数据的一些基本属性。 宽度&#xff08;W&#xff09; 和 高度&#xff08;H&#xff09; 定义了图像的像素分辨率&#xff0c;单位通常是像素。例如&#xff0c;一张 1920x10…...

MYSQL的管理备份

一、系统数据库 mysql数据库安装完成后,自带了四个数据库,具体作用如下: mysql:存储MySQL服务器正常运行所需的各种信息(时区、主从、用户、权限等); information_schema:提供了访问数据库元数据的各种表和视图,包含数据库、表、字段类型及访问权限等; performanc…...

数据仓库与数据挖掘记录 三

数据仓库的数据存储和处理 数据的ETL过程 数据 ETL 是用来实现异构数据源的数据集成,即完成数据的抓取/抽取、清洗、转换 .加载与索引等数据调和工作,如图 2. 2 所示。 1&#xff09;数据提取&#xff08;Extract&#xff09; 从多个数据源中获取原始数据&#xff08;如数据…...

第12周:LSTM(火灾温度)

1.库以及数据的导入 1.1库的导入 import torch.nn.functional as F import numpy as np import pandas as pd import torch from torch import nn1.2数据集的导入 data pd.read_csv("woodpine2.csv")dataTimeTem1CO 1Soot 100.00025.00.0000000.00000010.22825.…...

MySQL的SQL执行流程

项目查询数据库的流程 用户通过Tomcat服务器发送请求到MySQL数据库的过程。 用户发起请求&#xff1a;用户通过浏览器或其他客户端向Tomcat服务器发送HTTP请求。 Tomcat服务器处理请求&#xff1a; Tomcat服务器接收用户的请求&#xff0c;并创建一个线程来处理这个请求。 线…...

Foundation CSS 可见性

Foundation CSS 可见性 引言 在网页设计中,CSS可见性是一个至关重要的概念。它决定了元素在网页上是否可见,以及如何显示。Foundation CSS 是一个流行的前端框架,它提供了丰富的工具和组件来帮助开发者构建响应式和可访问的网页。本文将深入探讨 Foundation CSS 中的可见性…...

7. Docker 容器数据卷的使用(超详细的讲解说明)

7. Docker 容器数据卷的使用(超详细的讲解说明) 文章目录 7. Docker 容器数据卷的使用(超详细的讲解说明)1. Docker容器数据卷概述2. Docker 容器数据卷的使用演示&#xff1a;2.1 宿主 和 容器之间映射添加容器卷2.2 容器数据卷 读写规则映射添加说明2.3 容器数据卷的继承和共…...

算法——结合实例了解广度优先搜索(BFS)搜索

一、广度优先搜索初印象 想象一下&#xff0c;你身处一座陌生的城市&#xff0c;想要从当前位置前往某个景点&#xff0c;你打开手机上的地图导航软件&#xff0c;输入目的地后&#xff0c;导航软件会迅速规划出一条最短路线。这背后&#xff0c;就可能运用到了广度优先搜索&am…...

qt QCommandLineOption 详解

1、概述 QCommandLineOption类是Qt框架中用于解析命令行参数的类。它提供了一种方便的方式来定义和解析命令行选项&#xff0c;并且可以与QCommandLineParser类一起使用&#xff0c;以便在应用程序中轻松处理命令行参数。通过QCommandLineOption类&#xff0c;开发者可以更便捷…...

Linux权限提升-内核溢出

一&#xff1a;Web到Linux-内核溢出Dcow 复现环境&#xff1a;https://www.vulnhub.com/entry/lampiao-1,249/ 1.信息收集&#xff1a;探测⽬标ip及开发端⼝ 2.Web漏洞利⽤&#xff1a; 查找drupal相关漏洞 search drupal # 进⾏漏洞利⽤ use exploit/unix/webapp/drupal_dr…...

【环境安装】重装Docker-26.0.2版本

【机器背景说明】Linux-Centos7&#xff1b;已有低版本的Docker 【目标环境说明】 卸载已有Docker&#xff0c;用docker-26.0.2.tgz安装包安装 1.Docker包下载 下载地址&#xff1a;Index of linux/static/stable/x86_64/ 2.卸载已有的Docker 卸载之前首先停掉服务 sudo…...

【云安全】云原生- K8S API Server 未授权访问

API Server 是 Kubernetes 集群的核心管理接口&#xff0c;所有资源请求和操作都通过 kube-apiserver 提供的 API 进行处理。默认情况下&#xff0c;API Server 会监听两个端口&#xff1a;8080 和 6443。如果配置不当&#xff0c;可能会导致未授权访问的安全风险。 8080 端口…...

笔记7——条件判断

条件判断 主要通过 if、elif 和 else 语句来实现 语法结构 # if 条件1: # 条件1为真时执行的代码 # elif 条件2&#xff1a; # 条件1为假、且条件2为真时执行的代码 # elif 条件3&#xff1a; # 条件1、2为假、且条件3为真时执行的代码 # ... # else: # 所…...

Word 公式转 CSDN 插件 发布

经过几个月的苦修&#xff0c;这款插件终于面世了。 从Word复制公式到CSDN粘贴&#xff0c;总是出现公式中的文字被单独提出来&#xff0c;而公式作为一个图片被粘贴的情况。公式多了的时候还会导致CSDN禁止进一步的上传公式。 经过对CSDN公式的研究&#xff0c;发现在粘贴公…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...