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

news2025/1/11 20:46:55

微信小程序官方解决方案: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'
    },
  }
}


 


六、生成的效果图

 


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

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

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

相关文章

复试 || 就业day14(2024.01.10)算法篇

文章目录 前言字符串中第二大的数字字符串中不同整数的数目判断句子是否为全字母句长度为三且各字符不同的子字符串检查是否区域内所有整数都被覆盖*重新分配字符使所有字符串都相等可以输入的最大单词数检查是否所有字符出现次数相同差的绝对值为 K 的数对数目至少在两个数组中…

PHP开发日志 ━━ php8.3安装与使用组件Xdebug

今天开头写点历史&#xff1a; 二十年前流行asp&#xff0c;当时用vb整合常用函数库写了一个dll给asp调用&#xff0c;并在此基础上开发一套仿windows界面的后台管理系统&#xff1b;后来asp逐渐没落&#xff0c;于是在十多年前转投php&#xff0c;不久后用php写了一套mvc框架&…

压缩编码之变换的选择之离散余弦变换(DCT)和离散傅立叶变换(DFT)——数字图像处理

原理 变换的选择是一个关键的考量因素&#xff0c;它决定了数据是如何被压缩的。选择变换时考虑以下几个重要原则&#xff1a; 数据去关联性&#xff1a;变换的目的之一是减少数据中的相关性。例如&#xff0c;在图像压缩中&#xff0c;像素间往往高度相关。通过适当的变换&a…

Redis-Cluster 与 Redis 集群的技术大比拼

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 Redis-Cluster 与 Redis 集群的技术大比拼 前言概念与原理对比Redis-Cluster&#xff1a;基于哈希槽的分布式解决方案传统 Redis 集群&#xff1a;主从架构下的数据分片方式 搭建与配置的异同Redis-Cl…

跟着小德学C++之进程信息记录

嗨&#xff0c;大家好&#xff0c;我是出生在达纳苏斯的一名德鲁伊&#xff0c;我是要立志成为海贼王&#xff0c;啊不&#xff0c;是立志成为科学家的德鲁伊。最近&#xff0c;我发现我们所处的世界是一个虚拟的世界&#xff0c;并由此开始&#xff0c;我展开了对我们这个世界…

JS逆向之加密参数定位

文章目录 前言加密参数的处理步骤加密参数的定位方法搜索断点XHR断点DOM断点EVENT断点 hook 前言 当我们对网络请求进行抓包分析之后&#xff0c;需要用开发者工具对加密参数进行全局搜索。当搜索不到加密参数的时候&#xff0c;应该采取什么解决方法去定位。 还有一个应用场…

Tomcat-快速使用

关于Tomcat的概念及来由在Tomcat基本知识中进行了介绍&#xff0c;下面我们直接上手快速使用起来。 一、快速使用 &#xff08;1&#xff09;tomcat下载 &#xff08;2&#xff09;解压缩 &#xff08;3&#xff09;启动程序 &#xff08;4&#xff09;访问tomcat&#xff1a…

Windows和Linux中检查端口是否被占用

一、windows 1、查询端口占用情况 cmd > netstat -ano 2、查询8080端口是否被占用 cmd > netstat -ano|findstr 8080 3、查询哪个程序占用了端口 cmd > tasklist|findstr PID 4、终止该占用进程 cmd > ntsd -c q -p PID 二、Linux 1、查询8080端口是否被占用…

windows10 装docker和docker compose

一.windows环境准备 开启过程中的问题&#xff0c;进入bios修复 二.docker下载安装 1.下载 Docker Desktop: The #1 Containerization Tool for Developers | Docker 下载最新版有问题&#xff0c;下载老版本试试 Docker Desktop release notes | Docker Docs 2.安装 三.do…

GitHub pull request(傻瓜式入门版)

基础入门版 pull request一、fork项目二、clone代码到本地三、进入到克隆的项目目录下四、列出所有分支五、创建一个本地分支&#xff0c;并追踪远程项目分支六、查看当前分支七、与远程仓库建立连接八、与上游仓库建立连接八、同步最新代码九、修改代码并提交十、提交pr pull …

虚幻引擎:开创视觉与创意的新纪元

先看看据说虚幻5做出来的东西吧&#xff1a; 虚幻引擎5&#xff01;&#xff01;&#xff01;4K画质PS5实机演示&#xff01; 好了&#xff0c;用文字认识一下吧&#xff1a; 虚幻引擎5.3对UE5的核心工具集作了进一步优化&#xff0c;涉及渲染、世界构建、程序化内容生成&…

服务器执行rm命令时自动记录到审计日志中

目的 当在服务器上执行类似于 rm 命令时&#xff0c;自动记录该命令执行的时间&#xff0c;在哪里执行的&#xff0c;删除的什么文件&#xff0c;记录到审计日志中&#xff0c;能够查找到某些文件丢失原因 配置 # 需要root权限&#xff0c;sudo不行&#xff0c;这里假设执行…

麦芯(MachCore)开发教程1 --- 设备软件中间件

黄国强 2024/1/10 acloud163.com 对任何公司来说&#xff0c;在短时间内开发一款高质量设备专用软件&#xff0c;是一件不太容易做到的事情。麦芯是笔者发明的一款设备软件中间件产品。麦芯致力于给设备厂商提供一个开发工具和平台&#xff0c;让客户快速高效的开发自己的设备专…

PyQt5零基础入门(二)——QLabel控件

前言 QLabel控件可以视为是一个标签项&#xff0c;具有显示文本、图像的作用。在本篇文章中将介绍QLabel控件的常见用法。 例子 显示文本 import sys from PyQt5.QtWidgets import *if __name__ "__main__":app QApplication([])label QLabel(Hello world!)la…

了解结构体以及结构体数组

C语言的结构体你真的了解吗&#xff1f; 一起来看一下吧&#xff01;&#xff01;&#xff01; 1.结构体是啥&#xff1f; 结构体是多种数据类型的组合体 2.格式&#xff08;一般放在主函数前&#xff0c;也就是int main()前面 &#xff09; 关键字 结构体名字 {成员列表…

网络安全B模块(笔记详解)- Web信息收集

Web信息收集 1.通过Kali对服务器场景Linux进行Web扫描渗透测试(使用工具nikto,查看该命令的完整帮助文件),并将该操作使用命令中固定不变的字符串作为Flag提交; Flag:nikto -H 2.通过Kali对服务器场景Linux进行Web扫描渗透测试(使用工具nikto,扫描目标服务器8080端口,…

springCould中的Bus-从小白开始【11】

目录 &#x1f9c2;1.Bus是什么❤️❤️❤️ &#x1f32d;2.什么是总线❤️❤️❤️ &#x1f953;3.rabbitmq❤️❤️❤️ &#x1f95e;4.新建模块3366❤️❤️❤️ &#x1f373;5.设计思想 ❤️❤️❤️ &#x1f37f;6.添加消息总线的支持❤️❤️❤️ &#x1f9…

Redis不同环境缓存同一条数据,数据内部值不同

背景 现实中&#xff0c;本地环境&#xff08;dev&#xff09;和开发环境&#xff08;feature&#xff09;会共同使用相同的中间件&#xff08;本篇拿Redis举例&#xff09;&#xff0c;对于不同环境中的&#xff0c;图片、视频、语音等资源类型的预览地址url&#xff0c;需要配…

Ncast盈可视 高清智能录播系统 IPSetup.php信息泄露+RCE漏洞复现(CVE-2024-0305)

0x01 产品简介 Ncast盈可视 高清智能录播系统是广州盈可视电子科技有限公司一种先进的音视频录制和播放解决方案,旨在提供高质量、高清定制的录播体验。该系统采用先进的摄像和音频技术,结合强大的软件平台,可以实现高清视频录制、多路音频采集、实时切换和混音、定制视频分…

thinkphp学习07-数据库的数据查询

单数据查询 单条数据查询&#xff0c;一般是一维数组 Db::table()中 table 必须指定完整数据表&#xff08;包括前缀&#xff09;&#xff0c;如果配置了表前缀&#xff0c;Db::name()中可以忽略 如果希望只查询一条数据&#xff0c;可以使用 find()方法&#xff0c;需指定 wh…