微信小程序手写签名

news2024/12/23 7:12:25

微信小程序手写签名组件

在这里插入图片描述
该组件基于signature_pad封装,signature_pad本身是web端的插件,此处将插件代码修改为小程序端可用。
signature_pad.js

/*!
 * Signature Pad v5.0.3 | https://github.com/szimek/signature_pad
 * (c) 2024 Szymon Nowak | Released under the MIT license
 */
!(function (t, e) {
  "object" == typeof exports && "undefined" != typeof module
    ? (module.exports = e())
    : "function" == typeof define && define.amd
    ? define(e)
    : ((t =
        "undefined" != typeof globalThis
          ? globalThis
          : t || self).SignaturePad = e());
})(this, function () {
  "use strict";
  class t {
    constructor(t, e, i, n) {
      if (isNaN(t) || isNaN(e))
        throw new Error(`Point is invalid: (${t}, ${e})`);
      (this.x = +t),
        (this.y = +e),
        (this.pressure = i || 0),
        (this.time = n || Date.now());
    }
    distanceTo(t) {
      return Math.sqrt(Math.pow(this.x - t.x, 2) + Math.pow(this.y - t.y, 2));
    }
    equals(t) {
      return (
        this.x === t.x &&
        this.y === t.y &&
        this.pressure === t.pressure &&
        this.time === t.time
      );
    }
    velocityFrom(t) {
      return this.time !== t.time
        ? this.distanceTo(t) / (this.time - t.time)
        : 0;
    }
  }
  class e {
    static fromPoints(t, i) {
      const n = this.calculateControlPoints(t[0], t[1], t[2]).c2,
        s = this.calculateControlPoints(t[1], t[2], t[3]).c1;
      return new e(t[1], n, s, t[2], i.start, i.end);
    }
    static calculateControlPoints(e, i, n) {
      const s = e.x - i.x,
        o = e.y - i.y,
        r = i.x - n.x,
        h = i.y - n.y,
        a = (e.x + i.x) / 2,
        c = (e.y + i.y) / 2,
        d = (i.x + n.x) / 2,
        l = (i.y + n.y) / 2,
        u = Math.sqrt(s * s + o * o),
        v = Math.sqrt(r * r + h * h),
        _ = u + v == 0 ? 0 : v / (u + v),
        p = d + (a - d) * _,
        m = l + (c - l) * _,
        g = i.x - p,
        w = i.y - m;
      return { c1: new t(a + g, c + w), c2: new t(d + g, l + w) };
    }
    constructor(t, e, i, n, s, o) {
      (this.startPoint = t),
        (this.control2 = e),
        (this.control1 = i),
        (this.endPoint = n),
        (this.startWidth = s),
        (this.endWidth = o);
    }
    length() {
      let t,
        e,
        i = 0;
      for (let n = 0; n <= 10; n += 1) {
        const s = n / 10,
          o = this.point(
            s,
            this.startPoint.x,
            this.control1.x,
            this.control2.x,
            this.endPoint.x
          ),
          r = this.point(
            s,
            this.startPoint.y,
            this.control1.y,
            this.control2.y,
            this.endPoint.y
          );
        if (n > 0) {
          const n = o - t,
            s = r - e;
          i += Math.sqrt(n * n + s * s);
        }
        (t = o), (e = r);
      }
      return i;
    }
    point(t, e, i, n, s) {
      return (
        e * (1 - t) * (1 - t) * (1 - t) +
        3 * i * (1 - t) * (1 - t) * t +
        3 * n * (1 - t) * t * t +
        s * t * t * t
      );
    }
  }
  class i {
    constructor() {
      try {
        this._et = new EventTarget();
      } catch (t) {
        this._et = document;
      }
    }
    dispatchEvent(t) {
      return this._et.dispatchEvent(t);
    }
  }
  class n extends i {
    constructor(t, e = {}) {
      var i, s, o;
      super(),
        (this.canvas = t),
        (this._drawingStroke = !1),
        (this._isEmpty = !0),
        (this._lastPoints = []),
        (this._data = []),
        (this._lastVelocity = 0),
        (this._lastWidth = 0),
        (this._handleMouseDown = (t) => {
          this._isLeftButtonPressed(t, !0) &&
            !this._drawingStroke &&
            this._strokeBegin(this._pointerEventToSignatureEvent(t));
        }),
        (this._handleMouseMove = (t) => {
          this._isLeftButtonPressed(t, !0) && this._drawingStroke
            ? this._strokeMoveUpdate(this._pointerEventToSignatureEvent(t))
            : this._strokeEnd(this._pointerEventToSignatureEvent(t), !1);
        }),
        (this._handleMouseUp = (t) => {
          this._isLeftButtonPressed(t) ||
            this._strokeEnd(this._pointerEventToSignatureEvent(t));
        }),
        (this._handleTouchStart = (t) => {
          1 !== t.touches.length ||
            this._drawingStroke ||
            (t.cancelable && t.preventDefault(),
            this._strokeBegin(this._touchEventToSignatureEvent(t)));
        }),
        (this._handleTouchMove = (t) => {
          1 === t.touches.length &&
            (t.cancelable && t.preventDefault(),
            this._drawingStroke
              ? this._strokeMoveUpdate(this._touchEventToSignatureEvent(t))
              : this._strokeEnd(this._touchEventToSignatureEvent(t), !1));
        }),
        (this._handleTouchEnd = (t) => {
          0 === t.touches.length &&
            (t.cancelable && t.preventDefault(),
            this._strokeEnd(this._touchEventToSignatureEvent(t)));
        }),
        (this._handlePointerDown = (t) => {
          this._isLeftButtonPressed(t) &&
            !this._drawingStroke &&
            (t.preventDefault(),
            this._strokeBegin(this._pointerEventToSignatureEvent(t)));
        }),
        (this._handlePointerMove = (t) => {
          this._isLeftButtonPressed(t, !0) && this._drawingStroke
            ? (t.preventDefault(),
              this._strokeMoveUpdate(this._pointerEventToSignatureEvent(t)))
            : this._strokeEnd(this._pointerEventToSignatureEvent(t), !1);
        }),
        (this._handlePointerUp = (t) => {
          this._isLeftButtonPressed(t) ||
            (t.preventDefault(),
            this._strokeEnd(this._pointerEventToSignatureEvent(t)));
        }),
        (this.velocityFilterWeight = e.velocityFilterWeight || 0.7),
        (this.minWidth = e.minWidth || 0.5),
        (this.maxWidth = e.maxWidth || 2.5),
        (this.throttle = null !== (i = e.throttle) && void 0 !== i ? i : 16),
        (this.minDistance =
          null !== (s = e.minDistance) && void 0 !== s ? s : 5),
        (this.dotSize = e.dotSize || 0),
        (this.penColor = e.penColor || "black"),
        (this.backgroundColor = e.backgroundColor || "rgba(0,0,0,0)"),
        (this.compositeOperation = e.compositeOperation || "source-over"),
        (this.canvasContextOptions =
          null !== (o = e.canvasContextOptions) && void 0 !== o ? o : {}),
        (this._strokeMoveUpdate = this.throttle
          ? (function (t, e = 250) {
              let i,
                n,
                s,
                o = 0,
                r = null;
              const h = () => {
                (o = Date.now()),
                  (r = null),
                  (i = t.apply(n, s)),
                  r || ((n = null), (s = []));
              };
              return function (...a) {
                const c = Date.now(),
                  d = e - (c - o);
                return (
                  (n = this),
                  (s = a),
                  d <= 0 || d > e
                    ? (r && (clearTimeout(r), (r = null)),
                      (o = c),
                      (i = t.apply(n, s)),
                      r || ((n = null), (s = [])))
                    : r || (r = setTimeout(h, d)),
                  i
                );
              };
            })(n.prototype._strokeUpdate, this.throttle)
          : n.prototype._strokeUpdate),
        (this._ctx = t.getContext("2d", this.canvasContextOptions)),
        this.clear();
    }
    clear() {
      const { _ctx: t, canvas: e } = this;
      (t.fillStyle = this.backgroundColor),
        t.clearRect(0, 0, e.width, e.height),
        t.fillRect(0, 0, e.width, e.height),
        (this._data = []),
        this._reset(this._getPointGroupOptions()),
        (this._isEmpty = !0);
    }
    fromDataURL(t, e = {}) {
      return new Promise((i, n) => {
        const s = new Image(),
          o = e.ratio || window.devicePixelRatio || 1,
          r = e.width || this.canvas.width / o,
          h = e.height || this.canvas.height / o,
          a = e.xOffset || 0,
          c = e.yOffset || 0;
        this._reset(this._getPointGroupOptions()),
          (s.onload = () => {
            this._ctx.drawImage(s, a, c, r, h), i();
          }),
          (s.onerror = (t) => {
            n(t);
          }),
          (s.crossOrigin = "anonymous"),
          (s.src = t),
          (this._isEmpty = !1);
      });
    }
    toDataURL(t = "image/png", e) {
      return ("number" != typeof e && (e = void 0), this.canvas.toDataURL(t, e));
    }
    isEmpty() {
      return this._isEmpty;
    }
    fromData(t, { clear: e = !0 } = {}) {
      e && this.clear(),
        this._fromData(t, this._drawCurve.bind(this), this._drawDot.bind(this)),
        (this._data = this._data.concat(t));
    }
    toData() {
      return this._data;
    }
    _isLeftButtonPressed(t, e) {
      return e ? 1 === t.buttons : !(1 & ~t.buttons);
    }
    _pointerEventToSignatureEvent(t) {
      return {
        event: t,
        type: t.type,
        x: t.x,
        y: t.y,
        pressure: "pressure" in t ? t.pressure : 0,
      };
    }
    _touchEventToSignatureEvent(t) {
      const e = t.changedTouches[0];
      return {
        event: t,
        type: t.type,
        x: e.x,
        y: e.y,
        pressure: e.force,
      };
    }
    _getPointGroupOptions(t) {
      return {
        penColor: t && "penColor" in t ? t.penColor : this.penColor,
        dotSize: t && "dotSize" in t ? t.dotSize : this.dotSize,
        minWidth: t && "minWidth" in t ? t.minWidth : this.minWidth,
        maxWidth: t && "maxWidth" in t ? t.maxWidth : this.maxWidth,
        velocityFilterWeight:
          t && "velocityFilterWeight" in t
            ? t.velocityFilterWeight
            : this.velocityFilterWeight,
        compositeOperation:
          t && "compositeOperation" in t
            ? t.compositeOperation
            : this.compositeOperation,
      };
    }
    _strokeBegin(event) {
      this._drawingStroke = !0;
			const i = this._getPointGroupOptions()
			const n = Object.assign(Object.assign({}, i), { points: [] })
			this._data.push(n);
			this._reset(i);
			this._strokeUpdate(event);
    }
    _strokeUpdate(t) {
      if (!this._drawingStroke) return;
      if (0 === this._data.length) return void this._strokeBegin(t);
      const e = this._createPoint(t.x, t.y, t.pressure),
        i = this._data[this._data.length - 1],
        n = i.points,
        s = n.length > 0 && n[n.length - 1],
        o = !!s && e.distanceTo(s) <= this.minDistance,
        r = this._getPointGroupOptions(i);
      if (!s || !s || !o) {
        const t = this._addPoint(e, r);
        s ? t && this._drawCurve(t, r) : this._drawDot(e, r),
          n.push({ time: e.time, x: e.x, y: e.y, pressure: e.pressure });
      }
    }
    _strokeEnd(t, e = !0) {
			this._drawingStroke &&
				(e && this._strokeUpdate(t),
				(this._drawingStroke = !1));
    }
    _reset(t) {
      (this._lastPoints = []),
        (this._lastVelocity = 0),
        (this._lastWidth = (t.minWidth + t.maxWidth) / 2),
        (this._ctx.fillStyle = t.penColor),
        (this._ctx.globalCompositeOperation = t.compositeOperation);
    }
    _createPoint(e, i, n) {
      return new t(e , i, n, new Date().getTime());
    }
    _addPoint(t, i) {
      const { _lastPoints: n } = this;
      if ((n.push(t), n.length > 2)) {
        3 === n.length && n.unshift(n[0]);
        const t = this._calculateCurveWidths(n[1], n[2], i),
          s = e.fromPoints(n, t);
        return n.shift(), s;
      }
      return null;
    }
    _calculateCurveWidths(t, e, i) {
      const n =
          i.velocityFilterWeight * e.velocityFrom(t) +
          (1 - i.velocityFilterWeight) * this._lastVelocity,
        s = this._strokeWidth(n, i),
        o = { end: s, start: this._lastWidth };
      return (this._lastVelocity = n), (this._lastWidth = s), o;
    }
    _strokeWidth(t, e) {
      return Math.max(e.maxWidth / (t + 1), e.minWidth);
    }
    _drawCurveSegment(t, e, i) {
      const n = this._ctx;
      n.moveTo(t, e), n.arc(t, e, i, 0, 2 * Math.PI, !1), (this._isEmpty = !1);
    }
    _drawCurve(t, e) {
      const i = this._ctx,
        n = t.endWidth - t.startWidth,
        s = 2 * Math.ceil(t.length());
      i.beginPath(), (i.fillStyle = e.penColor);
      for (let i = 0; i < s; i += 1) {
        const o = i / s,
          r = o * o,
          h = r * o,
          a = 1 - o,
          c = a * a,
          d = c * a;
        let l = d * t.startPoint.x;
        (l += 3 * c * o * t.control1.x),
          (l += 3 * a * r * t.control2.x),
          (l += h * t.endPoint.x);
        let u = d * t.startPoint.y;
        (u += 3 * c * o * t.control1.y),
          (u += 3 * a * r * t.control2.y),
          (u += h * t.endPoint.y);
        const v = Math.min(t.startWidth + h * n, e.maxWidth);
        this._drawCurveSegment(l, u, v);
      }
      i.closePath(), i.fill();
    }
    _drawDot(t, e) {
      const i = this._ctx,
        n = e.dotSize > 0 ? e.dotSize : (e.minWidth + e.maxWidth) / 2;
      i.beginPath(),
        this._drawCurveSegment(t.x, t.y, n),
        i.closePath(),
        (i.fillStyle = e.penColor),
        i.fill();
    }
    _fromData(e, i, n) {
      for (const s of e) {
        const { points: e } = s,
          o = this._getPointGroupOptions(s);
        if (e.length > 1)
          for (let n = 0; n < e.length; n += 1) {
            const s = e[n],
              r = new t(s.x, s.y, s.pressure, s.time);
            0 === n && this._reset(o);
            const h = this._addPoint(r, o);
            h && i(h, o);
          }
        else this._reset(o), n(e[0], o);
      }
    }
  }
  return n;
});
//# sourceMappingURL=signature_pad.umd.min.js.map

组件代码

这里封装展示的是横向签名,但其实画布是竖向,最后获取的是将画布旋转-90度的图片。
在这里插入图片描述
signature.wxml

<page-container show="{{show}}" position="right" bind:afterleave="pageLeave">
  <view hidden="{{!show}}" class="signature-wrap">
    <view class="actions-wrap">
      <view class="actions">
        <button type="default" class="sign-button" bindtap="tapUndo">撤销</button>
        <button type="warn" class="sign-button" bindtap="tapClear">清除</button>
        <button type="primary" class="sign-button" bindtap="tapConfirm">完成</button>
      </view>
    </view>
    <canvas
      type="2d"
      id="signature"
      class="signature"
      style="width:{{width}}px; height:{{height}}px;"
      disable-scroll="{{true}}"
      bindtouchstart="handleTouchStart"
      bindtouchmove="handleTouchMove"
      bindtouchend="handleTouchEnd"></canvas>
    <!-- 旋转图片canvas容器,不在页面上展示 -->
    <view class="offscreen">
      <canvas
        id="targetSignature"
        type="2d"
        style="width:{{height}}px; height:{{width}}px;"
      />
    </view>
  </view>
</page-container>

signature.js 这里需要注意,我的引用路径是'@/static/signature_pad',这种写法需要在app.json处配置resolveAlias自定义路径映射

import SignaturePad from '@/static/signature_pad'

Component({

  /**
   * 组件的属性列表
   */
  properties: {
    show: false
  },

  /**
   * 组件的初始数据
   */
  data: {
    signature: null,
    width: 0,
    height: 0,
    dpr: 1,
  },

  lifetimes: {
    ready() {
      try {
        const { windowWidth, windowHeight, pixelRatio } = wx.getWindowInfo();
        this.setData({
          width: windowWidth - 60, // 减去按钮区域
          height: windowHeight,
          dpr: Math.max(pixelRatio || 1, 2),
        })
      } catch (e) { }
      this.init()
    }
  },
  /**
   * 组件的方法列表
   */
  methods: {
    init() {
      this.createSelectorQuery().select('#signature').fields({ node: true, size: true }).exec((res) => {
        const { width, height, dpr } = this.data
        const canvas = res[0].node
        const ctx = canvas.getContext('2d')
        canvas.width = width * dpr
        canvas.height = height * dpr
        ctx.scale(dpr, dpr)
        const signature = new SignaturePad(canvas, {
          ratio: dpr,
          minWidth: 1,
          maxWidth: 4,
          backgroundColor: '#fff'
        });
        this.setData({
          signature
        })
      })
    },
    handleTouchStart(e) {
      this.data.signature._handleTouchStart(e)
    },
    handleTouchMove(e) {
      this.data.signature._handleTouchMove(e)
    },
    handleTouchEnd(e) {
      this.data.signature._handleTouchEnd(e)
    },
    tapClear() {
      this.data.signature.clear()
    },
    tapUndo() {
      let data = this.data.signature.toData()
      if (data) {
        data.pop()
        this.data.signature.fromData(data)
      }
    },
    async tapConfirm() {
      let isEmpty = this.data.signature.isEmpty()
      if (isEmpty) {
        return wx.showToast({
          title: '未签名',
          icon: 'none'
        })
      }
      const base64Url = this.data.signature.toDataURL()
      const targetSign = await this.getRotateImage(base64Url)
      this.triggerEvent('confirm', targetSign)
    },
    // 获取旋转后的图片
    getRotateImage(url) {
      return new Promise((resolve, reject) => {
        const query = this.createSelectorQuery()
        query.select('#targetSignature').node(res => {
          let canvas = res.node
          const { width, height } = this.data
          const ctx = canvas.getContext('2d')

          canvas.width = height
          canvas.height = width
          ctx.clearRect(0, 0, height, width)

          ctx.translate(0, width)
          ctx.rotate(-Math.PI / 2)

          const image = canvas.createImage()
          image.onload = () => {
            ctx.drawImage(image, 0, 0, width, height)
            // 如果只需要base64,只取这部分就可以
            const rotatedSign = canvas.toDataURL()
            ctx.clearRect(0, 0, height, width)
            resolve(rotatedSign)
            // 如果需要上传文件等相关处理,写到本地临时文件后做你自己的处理
            // wx.canvasToTempFilePath({
            //   canvas,
            //   success(res) {
            //     resolve(res.tempFilePath)
            //   }
            // })
          }
          image.src = url
        }).exec()
      })
    }
  }
})

signature.wxss

.signature-wrap {
  width: 100vw;
  height: 100vh;
  display: flex;
  z-index: 99;
  background-color: #fff;
  border-top: 2rpx solid #eee;
}
.actions-wrap {
  width: 60px;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  padding-bottom: 320rpx;
  border-right: 2rpx solid #eee;
}
.actions {
  white-space: nowrap;
  transform: rotate(90deg);
  display: flex;
}
.actions .sign-button {
  width: 160rpx;
  margin-left: 20rpx;
}
.offscreen {
  position: fixed;
  left: 9999px;
}

调用组件

index.wxml

<view class="row">
  <view class="label">签名</view>
  <view class="value" bind:tap="tapSignature">
    <image wx:if="{{signImg}}" class="sign-img" src="{{signImg}}" mode="heightFix" />
    <text wx:else class="input">请点击签名</text>
  </view>
</view>

<!-- 签名组件 -->
<signature wx:if="{{showSign}}" show="{{showSign}}" bindconfirm="confirmSign" bindcancel="cancelSign"></signature>

index.wxss

	.row {
  display: flex;
  align-items: center;
  padding: 16rpx 30rpx;
  border-bottom: 2rpx solid #f2f2f2;
}
.row .label {
  flex-shrink: 0;
}
.row .value {
  flex: 1;
  display: flex;
  justify-content: flex-end;
}
.row .value .input {
  color: #999;
}
.row .value .sign-img {
  height: 80rpx;
}

index.json

{
  "usingComponents": {
    "signature": "/components/signature/signature"
  }
}

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

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

相关文章

Windows10 安全加固之禁止光驱、U盘等自动播放

在使用Windows10系统的电脑中插入插入光盘或者U盘时,默认是自动播放的,这样会引入一些可能不安全的因素。因此,为了系统安全,有必要禁止光驱、U盘等自动播放。具体方法如下: 方法一:通过设置页面关闭 第1步:单击win10系统的“开始”菜单->“设置”,打开“windows设…

算法:区间dp

文章目录 一、适用场景二、基本思路步骤时间复杂度&#xff1a; 三、例题 区间动态规划&#xff08;Interval DP&#xff09;是一种用于解决某些需要处理区间或子段问题的动态规划方法&#xff0c;特别适合于问题的解可以通过子区间的解进行组合的情况。该方法的核心思想是在子…

pico手柄和人物模型手部旋转同步,实现手柄控制手臂手部位置移动、手部旋转和手指的操作了

这里的主要内容就是下述代码&#xff1b; // 获取左手控制器的旋转&#xff08;四元数表示&#xff09;Quaternion aRotationQuaternion leftHandController.rotation;// 计算旋转差值&#xff08;四元数表示&#xff09;Quaternion rotationDifference Quaternion.Euler(0, …

Qt创建项目及相关问题

文章目录 1. Qt项目创建2. 认识项目代码main.cppwidget.hwidget.cppwidget.ui.pro构建过程生成的中间文件 3. Hello World程序图形化方式创建代码方式创建内存泄漏问题编辑框方式创建按钮方式创建 4. 对象树引入对象树原因对象树自动释放对象实验演示 5. 乱码问题 1. Qt项目创建…

Databend 产品月报(2024年8月)

很高兴为您带来 Databend 2024 年 8 月的最新更新、新功能和改进&#xff01;我们希望这些增强功能对您有所帮助&#xff0c;并期待您的反馈。 Kafka Connect Sink Connector 插件 我们推出了一种将 Kafka 连接到 Databend 的新方式&#xff1a;databend-kafka-connect&#…

2023Idea版本无法下载通义灵码插件以及无法登录问题

进入下载插件处 在插件主页安装时&#xff0c;通常会根据当前自己访问的IDEA版本推荐合适的插件版本&#xff0c;所以最终会安装成功 idea中通义灵码插件无法登录问题

书客、松下、飞利浦护眼台灯怎么样?测评寻找护眼台灯天花板!

大家好&#xff0c;我是专注在护眼领域的一名评测师&#xff0c;长期以来&#xff0c;我致力于探索并体验各类能保护视力健康的护眼产品。今天&#xff0c;我来和大家分享我对护眼台灯的深入评测。护眼台灯作为日常学习生活的一部分&#xff0c;视觉体验的好坏往往取决于所选用…

Pygame中获取鼠标按键状态的方法

在《Pygame中获取鼠标位置的方法》中提到&#xff0c;可以通过鼠标事件和mouse模块中的函数获取鼠标位置&#xff0c;这两种方法同样适用于获取鼠标按键状态。 1 通过鼠标点击事件获取鼠标按键状态 通过鼠标点击事件获取鼠标按键状态的代码如图1所示。 图1 鼠标点击事件获取鼠…

HRGraph: 利用大型语言模型(LLMs)构建基于信息传播的HR数据知识图谱与职位推荐

知识图谱&#xff08;KGs&#xff09;作为语义网络&#xff0c;在管理不同领域复杂互联数据方面表现出极高的有效性&#xff0c;通过提供统一、上下文化和结构化的表示&#xff0c;具有灵活性&#xff0c;能够轻松适应不断发展的知识。在处理复杂的人力资源&#xff08;HR&…

RP2040 C SDK RTC功能使用

RP2040 C SDK RTC功能使用 &#x1f4cd;《RP2040 C SDK串口功能使用》&#x1f955;RP2040 RTC API官方文档说明&#xff1a;https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#group_hardware_rtc&#x1f955;官方例程参考&#xff1a;https://github.com/…

su root 提示 Permission denied

今天在某机器上新建了一个test账号&#xff0c;然后使用su root时&#xff0c;居然提示我没有权限&#xff0c;具体如下所示&#xff1a; [testlocalhost ~]$ su root Password: su: Permission denied [testlocalhost ~]$我确定密码是对的&#xff0c;试了好几次&#xff0c;…

彻底解决 node/npm, Electron下载失败相关问题, 从底层源码详解node electron 加速配置

最近玩了一下electron项目, 总是会遇到electron的下载失败问题, 于是看了一下node源码, 做一个记录. node/npm 加速配置 这个配置通过设置node配置里面的registry 这个配置项来完成加速. 配置方法 npm config set registry https://registry.npmmirror.com上面的命令就是将当…

day42-测试平台搭建之前端vue学习-基础1

一、Vue是什么 1.1.一套用于构建用户界面的渐进式JavaScript框架 1.2.渐进式 Vue可以自底向上逐层的应用 1).简单应用&#xff1a;只需一个轻量小巧的核心库 2).复杂应用&#xff1a;可以引ll入各式各样的Vue插件 二、Vue特点 2.1.采用组件化模式&#xff0c;提高代码复用率、…

翻译论文的关键部分 | Parallel Tiled QR Factorization for Multicore Architectures

SSRFB DTSQT2 DLARFB DGEQT2 1, 对角子矩阵分解 DGEQT2 这个例程被开发出来&#xff0c;用于针对对角Tile子矩阵&#xff1a; &#xff0c;执行不分块的QR分解。 这个运算产生&#xff1a; 一个上三角矩阵 一个酉下三角矩阵&#xff0c;这个矩阵包含 b 个 Householder 反光面…

跨平台打印模板转化pdf源码--SAAS本地化及未来之窗行业应用跨平台架构

一、跨平台打印转pdf渲染 pdf渲染模式可以支持国产化系统&#xff0c;和手机系统&#xff0c;安卓&#xff0c;苹果系统&#xff0c;qq浏览器&#xff0c;火狐&#xff0c;谷歌刘安祺 二、代码 /* ///cyberwin_offline_database_printtemp.js未来之窗打印模板解析技术 2024-…

maven的作用

一.什么是maven&#xff1f; maven是apache旗下的一个开源项目,是一款用于管理和构建java项目的工具。 关于Apache软件基金会,是目前世界最大的最受欢迎。 二.Maven的作用&#xff1f; 1.依赖管理 方便快捷的管理项目依赖的资源(jar包),避免版本冲突问题。 配置文件(pom.x…

Android UID 和 userID 以及 appID

我们知道Android 操作系统是基于Linux内核的&#xff0c;所以Android 的UID 是基于 Linux UID的。 Linux UID Linux 本身就是一个多用户操作系统&#xff0c;每一个用户都会有一个UID&#xff0c;不同UID 之间的资源访问是受限的。 其中&#xff0c;Linux的DAC权限模型&#…

mysql笔记2(安装配置与连接)

文章目录 1. 社区版两种安装包2. mysql是一个典型的C/S架构的软件3. 编写mysql代码的三个位置① cmd② mysql软件客户端③ 第三方软件Hyper 4. 常见的关系型数据库① myql② sql server③ oracle 5. 连接mysql① 为什么要连&#xff1f;② cmd里怎么连&#xff1f; 6. 清屏与退…

直线上最多的点数

优质博文&#xff1a;IT-BLOG-CN 题目 给你一个数组points&#xff0c;其中points[i] [xi, yi]表示X-Y平面上的一个点。求最多有多少个点在同一条直线上。 示例 1&#xff1a; 输入&#xff1a;points [[1,1],[2,2],[3,3]] 输出&#xff1a;3 示例 2&#xff1a; 输入&am…

中间件解析漏洞(附环境搭建教程)

⼀&#xff1a;IIS解析漏洞 环境资源&#xff1a; https://download.csdn.net/download/Nai_zui_jiang/89717504 环境安装 windows2003iis6 1.创建新的虚拟机 2.在下⼀步中选择我们的iso⽂件镜像 vm已主动识别到windows2003 3.产品密钥⽹上搜⼀个 密码自己设置一个简单的&…