uniapp使用wxml-to-canvas开发小程序保存canvas图片

微信小程序官方解决方案:wxml-to-canvas

使用wxml-to-canvas要知道一些前提条件
1、只能画view,text,image
2、每个元素必须要设置宽高
3、默认是flex布局,可以通过flexDirection: "column"来改变排列方式
4、文字 必须放在text中,放在view中无法显示,且text不支持字体加粗
5、如果你要设置背景颜色,请使用backgroundColor,而非background,border同理~
6、多个absolute元素时,因为没有z-index,template元素自上而下渲染,对应z-index依次增高
7、导出图片过大,可以通过canvasToTempFilePath({fileType, quality})配置里面的quality字段来减小
8、image只支持临时地址和网络地址,不支持base64和本地图片,可以通过writeFile 把base64转成临时地址
如下:
const fs = wx.getFileSystemManager();
let qrcodeBase64 = QRresult.data;
let qrcodeLink = `${wx.env.USER_DATA_PATH}/qrcodeLink.gif`;
fs.writeFile({
    filePath: qrcodeLink,
    data: qrcodeBase64,
    encoding: 'base64',
    success: res => {
        console.log(res)
        shopJson.qrcode = qrcodeLink;
        this.renderToCanvas();
    },
    fail(res) {
        console.error(res)
    }
})


9、Canvas 初始化问题:为了正确绘制图像,需要确保在调用 canvas.draw() 之前完成所有绘制操作。
10、不支持实时更新:一旦 Canvas 绘制完成,它将成为静态图像,无法实时更新。如果需要实时更新数据可视化图表,可以考虑
使用其他库或组件。
11、长按保存图片问题:wxml-to-canvas 组件默认无法通过长按保存图片功能保存 Canvas 图像。你可能需要自行实现该功能,
并适配不同平台的实现方式。
12、对低版本小程序的兼容性问题:某些较旧的微信小程序版本可能无法完全支持 wxml-to-canvas 组件。在开发之前,请确保目
标用户群体的微信小程序版本。
13、性能问题:复杂的数据可视化图表可能会影响性能,尤其是在绘制大量数据时。尽量优化绘制逻辑,以避免出现卡顿或延迟。
14、与其他组件的兼容性问题:wxml-to-canvas 组件可能与其他小程序组件存在一些兼容性问题,导致样式错乱或布局问题。建
议在使用时进行充分的测试和调试。
15、跨平台问题:wxml-to-canvas 组件目前主要针对微信小程序,可能无法直接适用于其他小程序平台或移动端框架。如果需要
在其他平台上实现类似的功能,可能需要另行寻找适合的解决方案。
16、Canvas 绘图能力限制:由于 Canvas 的绘图能力有限,某些高级的数据可视化需求可能无法直接通过 wxml-to-canvas 组
件实现。在确定方案之前,建议先了解 Canvas 绘图的限制和特性。
17、样式定制问题:某些样式属性或效果可能难以通过 wxml-to-canvas 组件实现,例如阴影、渐变色等。需要根据具体需求考虑
是否能够满足所需的样式效果。
18、开发者工具与真机表现差异:在进行调试和预览时,开发者工具上的表现可能与真机上存在一些差异。建议进行真机测试,以
确保数据可视化图表在不同设备上正常显示。

等等...其他未知问题...

一、安装

npm install --save wxml-to-canvas

二、在程序根目录下新建 wxcomponents 文件夹,将node_modules下的 widget-ui 和 wxml-to-canvas 两个文件夹复制进去。

注意:这里有的安装后生成的node_modules还不一样,可直接复制dist里面的即可(如下图)

 三、将/wxcomponents/wxml-to-canvas/index.js中的

module.exports = require("widget-ui");
//改为
module.exports = require("../widget-ui/index.js")

 四、配置pages.json (这样uni-app才会打包wxcomponents)

  • 1. 在需要用到的页面配置
"pages": [
    {
        "path": "pages/xxx",
        "style": {
            "usingComponents": {
              "wxml-to-canvas": "/wxcomponents/wxml-to-canvas/index"
            }
        }
    },
...
]
  • 2. 或者在globalStyle里面全局配置
"globalStyle": {
		"navigationBarTextStyle": "black",
		"navigationBarTitleText": "uni-app",
		"navigationBarBackgroundColor": "#F8F8F8",
		"backgroundColor": "#F8F8F8",
		"usingComponents": {
			"wxml-to-canvas": "/wxcomponents/wxml-to-canvas/index"
		}
},

五、重点来了,如何使用?

  •  页面配置

<!-- 测试页面,可复制使用 -->
<template>
  <view class="wrap">
    <!-- 保存canvas测试 -->
    <view class="share-page">
      <view class="share-page-box" id="box" v-if="show"
        :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }">
        <wxml-to-canvas class="widget" :width="canvasWidth" :height="canvasHeight"></wxml-to-canvas>
      </view>
      <view class="share-page-box msg-box" v-else :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }">
        {{ msg }}
      </view>
      <view class="share-page-btn" @tap="extraImage">
        <button class="btn-big" :style="getBtnStyle">保存图片</button>
      </view>
    </view>
  </view>
</template>

<script>
import { wxml, style } from './DomData';
export default {
  data() {
    return {
      show: false, // 是否显示canvas
      canvasWidth: 320, // 默认canvas宽高
      canvasHeight: 480,
      screenWidth: null, // 设备宽度
      screenHeight: null, // 设备高度
      // name: '',
      // pic: '',
      // chapter1: '',
      // chapter2: '',
      widget: null,
      msg: '加载中,请稍等...', // 提示语
      listData:[
        {
          type:'1',
          title:'标题一',
          auther: '张三  2024-01-10',
          imgsrc:'https://pic1.zhimg.com/80/v2-58fe538a59f870407b1435bfd45893ed_720w.jpeg',
          text:'本报讯(记者 杜晨薇)上海正在建设东方枢纽项目,浦东国际机场与沪通铁路将实现连通,枢纽周边临空产业、重点项目布局正在规划设计中。为落实上海市政府与中国东方航空集团有限公司(以下简称“中国东航”)合作协议要求,充分利用东方枢纽建设发展机遇期进一步深化合作发展,昨天下午,浦东新区政府与中国东航签署深化合作战略协议。'
        },
        {
          type: '2',
          title: '标题二',
          auther: '张三  2024-01-10',
          imgsrc: 'https://pic1.zhimg.com/80/v2-58fe538a59f870407b1435bfd45893ed_720w.jpeg',
          text: '本报讯(记者 杜晨薇)上海正在建设东方枢纽项目,浦东国际机场与沪通铁路将实现连通,枢纽周边临空产业、重点项目布局正在规划设计中。为落实上海市政府与中国东方航空集团有限公司(以下简称“中国东航”)合作协议要求,充分利用东方枢纽建设发展机遇期进一步深化合作发展,昨天下午,浦东新区政府与中国东航签署深化合作战略协议。'
        },
        {
          type: '3',
          title: '标题三',
          auther: '张三  2024-01-10',
          imgsrc: 'https://pic1.zhimg.com/80/v2-58fe538a59f870407b1435bfd45893ed_720w.jpeg',
          text: '本报讯(记者 杜晨薇)上海正在建设东方枢纽项目,浦东国际机场与沪通铁路将实现连通,枢纽周边临空产业、重点项目布局正在规划设计中。为落实上海市政府与中国东方航空集团有限公司(以下简称“中国东航”)合作协议要求,充分利用东方枢纽建设发展机遇期进一步深化合作发展,昨天下午,浦东新区政府与中国东航签署深化合作战略协议。'
        },
        {
          type: '4',
          title: '标题四',
          auther: '张三  2024-01-10',
          imgsrc: 'https://pic1.zhimg.com/80/v2-58fe538a59f870407b1435bfd45893ed_720w.jpeg',
          text: '本报讯(记者 杜晨薇)上海正在建设东方枢纽项目,浦东国际机场与沪通铁路将实现连通,枢纽周边临空产业、重点项目布局正在规划设计中。为落实上海市政府与中国东方航空集团有限公司(以下简称“中国东航”)合作协议要求,充分利用东方枢纽建设发展机遇期进一步深化合作发展,昨天下午,浦东新区政府与中国东航签署深化合作战略协议。'
        },
        {
          type: '5',
          title: '标题五',
          auther: '张三  2024-01-10',
          imgsrc: 'https://pic1.zhimg.com/80/v2-58fe538a59f870407b1435bfd45893ed_720w.jpeg',
          text: '本报讯(记者 杜晨薇)上海正在建设东方枢纽项目,浦东国际机场与沪通铁路将实现连通,枢纽周边临空产业、重点项目布局正在规划设计中。为落实上海市政府与中国东方航空集团有限公司(以下简称“中国东航”)合作协议要求,充分利用东方枢纽建设发展机遇期进一步深化合作发展,昨天下午,浦东新区政府与中国东航签署深化合作战略协议。'
        },
      ]
    }
  },

  methods: {
    // wxml 转 canvas
    renderToCanvas() {
      console.log('canvasStyle.widget', this.widget)
      const _wxml = wxml(this.listData);
      console.log('this.widget', _wxml)
      const _style = style(this.screenWidth, this.canvasWidth, this.canvasHeight) //this.canvasHeight
      const p1 = this.widget.renderToCanvas({ wxml: _wxml, style: _style })
      console.log('renderToCanvas', p1)
      p1.then((res) => {
        console.log('海报生成成功', res);
        wx.hideLoading()
      }).catch((err) => {
        console.log('生成失败', err)
      })
    },
    // 保存到朋友圈
    extraImage() {
      if (!this.show) {
        wx.showToast({ title: '海报生成失败,无法分享到朋友圈', icon: 'none' })
        return
      }
      wx.showLoading({ title: '海报生成中...' })
      const p2 = this.widget.canvasToTempFilePath({ fileType:'jpg', quality :0.5})
      let that = this;
      p2.then(result => {
        let path = result.tempFilePath
        wx.getSetting({
          success: res => {
            wx.hideLoading()
            // 非初始化且未授权的情况,需要再次弹窗提示授权
            if (res.authSetting['scope.writePhotosAlbum'] != undefined && res.authSetting['scope.writePhotosAlbum'] != true) {
              wx.showModal({
                title: '是否授权相册权限',
                content: '需要获取相册权限,请确认授权,否则无法使用相关功能',
                success: res => {
                  if (res.confirm) {
                    wx.openSetting({
                      success: dataAu => {
                        if (dataAu.authSetting["scope.writePhotosAlbum"] == true) {
                          wx.showToast({
                            title: '授权成功',
                            icon: 'none',
                            duration: 1000
                          });
                          that.saveIMg(path);
                        } else {
                          wx.showToast({
                            title: '授权失败',
                            icon: 'success',
                            duration: 1000
                          });
                        }
                      }
                    });
                  }
                }
              });
            } else {
              // 初始化且未授权,系统默认会弹窗提示授权
              // 非初始化且已授权,也会进入这里
              that.saveIMg(path);
            }
          }
        });
      })
    },
    // 保存到相册
    async saveIMg(tempFilePath) {
      wx.saveImageToPhotosAlbum({
        filePath: tempFilePath,
        success: async (res) => {
          wx.showModal({
            content: '图片已保存,分享给好友吧!',
            showCancel: false,
            confirmText: '好的',
            confirmColor: '#333',
            success: function (res) {
              wx.navigateBack({
                //返回
                delta: 1
              });
            },
            fail: function (res) {
              console.log('res', res);
            }
          });
        },

        fail: function (res) {
          wx.showToast({
            title: '您取消了授权',
            icon: 'none',
            duration: 2000
          })
        }
      });
    },
  },
  onLoad(options) {
    console.log('options', options);
    // 获取设备信息
    wx.getSystemInfo({
      success: (res) => {
        console.log('屏幕',res)
        this.screenWidth = res.screenWidth;
        this.canvasWidth = this.screenWidth;
        this.canvasHeight = this.screenWidth * 8.5;
        console.log('海报高度:', this.canvasHeight)

        this.show = true
        // 数字容器宽度 动态设置 
        setTimeout(() => {
          wx.showLoading({ title: '海报加载中...' })
          this.widget = this.selectComponent('.widget')
          this.renderToCanvas()
        }, 1000)
      }
    });
  },
}


</script>

<style lang="scss">
.share-page {
  background: #cc0202;
  position: relative;
  overflow: hidden;
  // padding: 10rpx;
//   min-height: 100vh;
  .msg-box {
    display: flex;
    align-items: center;
    text-align: center;
    justify-content: center;
  }
  .share-page-box {
    margin: 0 auto;
    position: relative;
    overflow: hidden;
	  box-shadow: 0rpx 6rpx 20rpx 6rpx rgba(0, 0, 0, 0.2);
  }
  .share-page-btn {
    margin: 0 10rpx 0 10rpx;
    img {
      width: 100%;
      height: 100%;
    }
  }
}
</style>

  • DomData.js

/**
 *
 * @param {*} listData  canvas数据
 */

export const wxml = (listData) => `
<view class="container">
  ${listData.map(item=>{
    return `
    <view class="contentWrap">
      <view >
        <image src="`+ item.imgsrc + `"  class="pic1"/>
        <text class="name">`+ item.title + `</text>
        <text class="subtitle">`+ item.auther + `</text>
      </view>
      <view class="bottomcss">
        <image src="`+ item.imgsrc + `"  class="imgbc"/>
        <view class="tapContent1">
          <text class="tapname">`+ item.text+`</text>
        </view>
      </view>
    </view>`
  }).join('')}
</view>
`
/**
 *
 *
 * @param {*} screenWidth 屏幕宽度
 * @param {*} canvasWidth  画布宽度
 * @param {*} canvasHeight  画布高度
 * @param {*} numberWidth  数字宽度,动态设置
 * @return {*} 
 */
 export const style = (screenWidth, canvasWidth, canvasHeight) => {
  return {
    "container": {
      width: canvasWidth,
      minHeight: canvasHeight,
      position:'relative',
      backgroundColor: '#ffffff',
      justifyContent: 'center',
      alignItems:'center',
      overflow: 'hidden'
    },
    "bottomcss":{
      marginTop: 0,
    },

    "contentWrap":{
      position: 'relative',
      width: canvasWidth * 0.99,
      marginBottom: 20,
      marginTop: 5,
      marginLeft: 1,
      borderRadius: 20,
      overflow:'hidden',
      backgroundColor: '#333333',
    },
    "imgbc":{
      justifyContent: 'center',
      alignItems: 'center',
      width: canvasWidth * 0.97,
      height: canvasWidth,
      marginBottom: 4,
      marginLeft: 4,
      marginTop: 10,
      borderRadius: 20,
      overflow: 'hidden',
    },
    "tapContent1":{
      position:'absolute',
      top: 0,
      left: 0,
    },
    "tapname":{
      fontSize: 18,
      color: '#fff',
      marginLeft: 15,
      marginTop: 50,
      overflow: 'hidden',
      width: canvasWidth * 0.92,
      height: 400,
      textAlign: 'left',
    },
    "name":{
      fontSize: 20,
      color: '#fff',
      marginLeft: canvasWidth * 0.08,
      width: canvasWidth * 0.84,
      height: 30,
			textAlign: 'center',
    },
    "subtitle":{
      fontSize: 14,
      color: '#9E9C9C',
      marginLeft: canvasWidth * 0.08,
      width: canvasWidth * 0.84,
      height: 20,
      textAlign: 'center',
    },
    "content": {
			fontSize: 14,
			color: '#333',
      width: canvasWidth * 0.84,
      height: screenWidth * 0.15,
			marginLeft: canvasWidth * 0.08,
    },
    "pic1": {
      width: canvasWidth * 0.3,
      height: screenWidth * 0.3,
      marginTop: canvasWidth * 0.1,
      marginLeft: canvasWidth * 0.35,
			marginBottom: canvasWidth * 0.05,
			borderRadius: screenWidth * 0.14,
			overflow: 'hidden',
    },
    "pic2": {
      width: canvasWidth ,
      height: canvasWidth ,
      marginTop:10,
    },
    "bottom":{
      width: canvasWidth,
      height: screenWidth * 0.2,
      flexDirection: 'row',
      justifyContent: 'self-start',
      alignItems: 'center',
			backgroundColor: '#fafafa',
      position: 'absolute',
      bottom: 0,
      left: 0,
    },
		"qr": {
		  width: canvasWidth * 0.14,
		  height: screenWidth * 0.14,
		  marginLeft: canvasWidth * 0.04,
			marginRight: canvasWidth * 0.04,
		},
    "msg": {
      fontSize: 14,
      color: '#a1a1a1',
      width: canvasWidth * 0.74,
			height: 14,
			textAlign: 'left'
    },
  }
}


 


六、生成的效果图

 


...... 全 剧 终 ......

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

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

相关文章

云服务器搭建GitLab

经验总结&#xff1a; 1、配置需求&#xff1a;云服务器内存最低4G 2、内存4G的云服务器&#xff0c;在运行容器后&#xff0c;会遇到云服务器操作卡顿问题&#xff0c;这里有解决方案 转载&#xff1a;服务器搭建Gitlab卡顿解决办法-CSDN博客 3、云服务器的操作系统会影响…

ROS建图之ROS标准REP-105(官方搬运翻译+个人理解)

REP-105 是一个由 Wim Meeussen 于 2010年10月27日 创建并维护的&#xff0c;名为 "Coordinate Frames for Mobile Platforms"&#xff08;移动平台的坐标系框架&#xff09;的 ROS Enhancement Proposal&#xff08;REP&#xff09;。ROS官方教程&#xff1a;REP 10…

Page 251~254 Win32 GUI项目

win32_gui 源代码&#xff1a; #if defined(UNICODE) && !defined(_UNICODE)#define _UNICODE #elif defined(_UNICODE) && !defined(UNICODE)#define UNICODE #endif#include <tchar.h> #include <windows.h>/* Declare Windows procedure */…

【Vue2】一个数组按时间分割为【今年】和【往年】俩个数组

一. 需求 后端返回一个数组&#xff0c;前端按时间维度将该数组的分割为【今年】和【往年】俩个数组后端返回的数组格式如下 timeList:[{id:1,billTime:"2024-01-10",createTime:"2024-01-10 00:00:00",status:0},{id:2,billTime:"2022-05-25"…

EVE-NG初次启动及WEB客户端访问来了

本章从虚拟机Eve模拟器启动、模拟器的启动配置、浏览器访问三个步骤讲解EVE-NG的首次启动。 1.启动模拟器 打开虚拟机环境&#xff0c;启动安装好的EVE-NG虚拟机&#xff0c;进入如下界面。 登录时输入社区版默认账户是root&#xff0c;密码是eve&#xff0c;完成登陆。 1.配置…

00后网文作家年入百万,跻身“十二天王”之列!

各位书友们&#xff0c;有没有觉得现在网文界越来越风起云涌&#xff1f;最近&#xff0c;2023年网络文学榜样作家“十二天王”出炉&#xff0c;其中一位00后作家季越人引起了广泛关注&#xff01;这位公共管理系的大四学生凭借他的第一部网文小说《玄鉴仙族》一鸣惊人&#xf…

Ubuntu系统中指定端口防火墙状态查询与操作

浏览器访问&#xff1a; 如果遇到如山图所示的情况&#xff0c;既有可能是防火墙的问题。具体解决方案参照如下&#xff1a; 1.指定端口的防火墙状态查询 &#xff08;1&#xff09;查询命令 sudo ufw status | grep 8081/tcp #其中8081为要查询的端口号 如果端口是打开的…

达梦数据库的使用

文章目录 一、安装程序介绍1.dm管理工具2.dm服务查看器3.数据迁移工具 二、达梦数据库联机备份与还原操作1.配置归档2.备份1.归档备份 3.备份还原 一、安装程序介绍 官网文档&#xff1a;https://eco.dameng.com/docs/zh-cn/faq/faq-import-export.html 达梦数据库安装成功后…

windows安装RabbitMq,修改数据保存位置

1、先安装Erlang&#xff0c; Erlang和RabbitMQ有版本对应关系。 官网RabbitMQ与Erlang版本对应RabbitMQ Erlang Version Requirements — RabbitMQ 2、安装RabbitMQ。 3、修改数据保存地址。找到安装目录下的sbin文件夹&#xff0c;找到rabbitmq-env.bat&#xff0c;编辑文件…

免费简单好用的 webshell 在线检测:支持 php、jsp、asp等多格式文件

话不多说&#xff0c;直接上图上链接&#xff1a;https://rivers.chaitin.cn/?share3d4f2e8aaec211eea5550242c0a8170c 还是比较好用的&#xff0c;支持 PHP、JSP 文件 webshell 检测&#xff0c;看官方解释文档&#xff0c;引擎使用静态文本特征、骨架哈希、静态语义分析、动…

广告投放场景中ABtest分析的评价、优化和决策建议

写在开头 在当今数字化的商业环境中&#xff0c;广告投放是企业获取客户和推动销售的重要手段。然而&#xff0c;随着市场竞争的加剧&#xff0c;制定有效的广告策略变得愈发复杂。在这个背景下&#xff0c;AB测试成为了广告主们不可或缺的工具之一。本文将深入探讨广告投放中…

TDengine 时序数据库 研究学习以及实战

下载地址&#xff1a;TDengine 发布历史及下载链接 | TDengine 文档 | 涛思数据 下载客户端和服务端 服务端和客户端的安装后 TDengine 客户端连接工具地址&#xff1a;Archive Files | DBeaver Community 添加驱动 新增 》 设置 选择驱动类后 设置里的类名就自动填写了&…

Vs2019安装教程

1、下载链接&#xff1a;Visual Studio 较旧的下载 - 2019、2017、2015 和以前的版本 (microsoft.com)https://visualstudio.microsoft.com/zh-hans/vs/older-downloads/2、下载 而后跟进安装&#xff1a;&#xff08;虽然这是2022的&#xff0c;但是和2022和2019基本差不多&am…

TS 36.331 V12.0.0-过程(2)-连接控制(2)-RRC连接重配

​本文的内容主要涉及TS 36.331&#xff0c;版本是C00&#xff0c;也就是V12.0.0。

基于实时Linux+FPGA实现NI CompactRIO系统详解

利用集成的软件工具链&#xff0c;结合信号调理I/O模块&#xff0c;轻松构建和部署实时应用程序。 什么是CompactRIO&#xff1f; CompactRIO系统提供了高处理性能、传感器专用I/O和紧密集成的软件工具&#xff0c;使其成为工业物联网、监测和控制应用的理想之选。实时处理器提…

YOLOv8优化策略:轻量化改进 | 华为Ghostnet,超越谷歌MobileNet | CVPR2020

🚀🚀🚀本文改进:Ghost bottleneck为堆叠Ghost模块 ,与YOLOV8建立轻量C2f_GhostBottleneck 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1.Ghostnet介绍 论文: https://arxiv.org/pdf/1911.11907.…

科技创新领航 ,安川运动控制器为工业自动化赋能助力

迈入工业4.0时代&#xff0c;工业自动化的不断发展&#xff0c;让高精度运动控制成为制造业高质量发展的重要技术手段。北京北成新控伺服技术有限公司作为一家集工业自动化产品销售、系统设计、开发、服务于一体的高新技术企业&#xff0c;其引进推出的运动控制产品一直以卓越的…

Hive分区表实战 - 单分区字段

文章目录 一、实战概述二、实战步骤&#xff08;一&#xff09;创建图书数据库&#xff08;二&#xff09;创建国别分区的图书表&#xff08;三&#xff09;在本地创建数据文件&#xff08;四&#xff09;按分区加载数据1、加载中文书籍数据到countrycn分区2、加载英文书籍数据…

分布式数据库原理及技术实验及个人思考

Hive的数据库及表的存储结构体系讨论&#xff1a; 1.显示hive所在数据库的位置 方法一&#xff1a;一次性临时存储 >hive set hive.cli.print.current.dbtrue 方法二&#xff1a;永久存储 在conf文件夹下修改hive-site.xml配置文件&#xff0c;添加 <property> …

医疗器械网络安全风险评定CVSS打分

为了完成医疗器械软件的网络安全风险评定相关文档&#xff0c;需要进行CVSS评分&#xff0c;这个评分对于第一次做的人来说感觉还是有些迷惑的&#xff0c;查了一些资料&#xff0c;留作参考。 CVSS 指的是 Common Vulnerability Scoring System&#xff0c;即通用漏洞评分系统…