uni-app 经验分享,从入门到离职(年度实战总结:经验篇)——上传图片以及小程序隐私保护指引设置

文章目录

  • 🔥年度征文
  • 📋前言
    • ⏬关于专栏
  • 🎯关于上传图片需求
  • 🎯前置知识点和示例代码
    • 🧩uni.chooseImage()
    • 🧩uni.chooseMedia()
      • 📌uni.chooseImage() 与 uni.chooseMedia()
    • 🧩uni.chooseFile()
  • 🎯关于小程序隐私保护指引设置
    • 🧩解决方法
  • 📝最后


在这里插入图片描述

🔥年度征文

在这里插入图片描述
活动地址:年度征文|回顾 2023,赢专属铭牌等定制大奖

白马过隙,转瞬之间 23 年的进度条已经快达到 100%,在迎接 24 年到来的同时,我们不妨来回顾一下这充满许多值得回忆时刻的 23年。过去的一年里,我们都经历了很多事情,或许经历了许多重要的时刻和学习机会;或许扩展了自己的知识领域;或许提升了自己的技术水平等等。接下来我来分享一下我在 23 年的一些代码笔记以及实战项目笔记。
在这里插入图片描述


📋前言

这篇文章是本专栏 uni-app 的项目经验篇,该文章将为大家分享在 uni-app 开发中的项目实战经验,本篇文章的主题是关于小程序上传图片官方 API 的使用,以及一些版本问题等等。除此之外,还有前段时间新发布的小程序隐私保护指引设置的新内容,包括如何解决类似隐私问题和如何设置隐私保护指引。

⏬关于专栏

本专栏主要是分享和介绍从零到一学习和使用的 uni-app 的笔记和个人经验。通过个人的学习经验和工作经验来给大家分享关于 uni-app 开发的技巧,以及快速入门的诀窍等等。

专栏主页:uni-app_黛琳ghz的博客-CSDN博客


🎯关于上传图片需求

在小程序中上传图片是很常见的交互功能,也是软件开发中不可缺少的功能,无论是在浏览器还是小程序中,都有很多需要用户上传图片的操作,接下来我们一起来看下有哪些应用场景,然后具体分析下需求。
在这里插入图片描述
应用场景:注册审核,在注册的流程中可能涉及到上传图片的需求,比如说身份证审核,个人信息等等审核,这个时候就需要用户上传图片到后台,进行审核;修改头像,这个功能是最常见的一个上传图片应用场景,用户从相册上传一张图片作为用户头像;表单提交,这个也是经常可以见到的应用场景,比如说问卷调查中需要上传图片的模块,或者任务提交的上传图片和上传任务描述这种应用场景。

需求分析:这里以注册审核的应用场景为例子,我们来分析一下这个需求,比如说该小程序注册要走审核流程,需要上传图片进行审核,首先授权完手机号码,然后填写用户的个人资料,如地址信息等等,接下来是上传图片的模块,比如说审核身份证、银行卡、健康证、认证资料等等,这些步骤都涉及到上传图片的功能。

分析完应用场景和需求之后,我们一起来看看在 uni-app 中可以用哪些 API 来实现上传图片的功能。


🎯前置知识点和示例代码

🧩uni.chooseImage()

uni.chooseImage() 是 uniapp 框架提供的一个 API,用于从本地相册或相机选择图片。 使用该方法可以打开系统的图片选择界面,让用户选择一张或多张图片。选择完成后,可以获取到选择的图片的临时文件路径。

❗PS:App端如需要更丰富的相机拍照API(如直接调用前置摄像头),参考plus.camera。

关于该方法的参数说明:

参数名类型必填说明平台差异说明
countNumber最多可以选择的图片张数,默认9见下方说明
sizeTypeArray<String>original 原图,compressed 压缩图,默认二者都有App、微信小程序、支付宝小程序、百度小程序
extensionArray<String>根据文件拓展名过滤,每一项都不能是空字符串。默认不过滤。H5(HBuilder X2.9.9+)
sourceTypeArray<String>album 从相册选图,camera 使用相机,默认二者都有。如需直接开相机或直接选相册,请只使用一个选项
cropObject图像裁剪参数,设置后 sizeType 失效App 3.1.19+
successFunction成功则返回图片的本地文件路径列表 tempFilePaths
failFunction接口调用失败的回调函数小程序、App
completeFunction接口调用结束的回调函数(调用成功、失败都会执行)

下面是 uni.chooseImage() 方法的使用示例:

uni.chooseImage({count: 1, // 最多可以选择的图片张数,默认为9sizeType: ['original', 'compressed'], // 可以指定原图或压缩图,默认为['original', 'compressed']sourceType: ['album', 'camera'], // 可以指定图片来源是相册还是相机,默认为['album', 'camera']// 选择图片成功success: function (res) {// 关于 tempFilePaths 在下文会介绍其注意事项var tempFilePaths = res.tempFilePaths;// 在这里可以对选择的图片进行处理,比如显示、上传等操作console.log('选择的图片路径:', tempFilePaths);},// 选择图片失败fail: function (err) {console.log('选择图片失败:', err.errMsg);}
});

在上述代码中,通过调用 uni.chooseImage() 方法,可以打开图片选择界面。可以通过设置 count 来指定最多选择的图片张数,sizeType 来指定选择的图片类型(原图或压缩图),sourceType 来指定图片来源(相册或相机)。

选择成功后,success 回调函数会被调用,可以在回调函数中获取选择的图片的临时文件路径(tempFilePaths)。在回调函数中,可以对选择的图片进行进一步处理,比如显示到页面上、上传到服务器等操作。如果选择图片失败,fail 回调函数会被调用,可以在回调函数中处理错误信息。

❗注意:文件的临时路径,在应用本次启动期间可以正常使用,如需持久保存,需在主动调用 uni.saveFile,在应用下次启动时才能访问得到。success 返回参数说明:

参数名类型说明
tempFilePathsArray<String>图片的本地文件路径列表
tempFilesArray<Object>、Array<File>图片的本地文件列表,每一项是一个 File 对象

关于其他详细的知识点和使用方法可以到 uni-app 官网查看,比如说这个 Tips 还是非常有用,需要的读者到官网(https://uniapp.dcloud.net.cn/api/media/image.html#chooseimage)查阅。
在这里插入图片描述


🧩uni.chooseMedia()

uni.chooseMedia() 是 uniapp 框架提供的一个 API,用于从本地相册或相机选择图片或视频。 使用该方法可以打开系统的图片/视频选择界面,让用户选择一张或多张图片或一个视频。选择完成后,可以获取到选择的图片/视频的临时文件路径。(兼容性如下图)在这里插入图片描述
关于该方法的参数说明:

参数名类型默认值必填说明
countNumber9(注意:ios不可大于9)最多可以选择的文件个数
mediaTypeArray<string>[‘image’, ‘video’]文件类型
sourceTypeArray<string>[‘album’, ‘camera’]图片和视频选择的来源
maxDurationNumber10拍摄视频最长拍摄时间,单位秒。时间范围为 3s 至 30s 之间
sizeTypeArray<string>[‘original’, ‘compressed’]仅对 mediaType 为 image 时有效,是否压缩所选文件
cameraString‘back’仅在 sourceType 为 camera 时生效,使用前置或后置摄像头
successfunction接口调用成功的回调函数
failfunction接口调用失败的回调函数
completefunction接口调用结束的回调函数(调用成功、失败都会执行)

下面是 uni.chooseMedia() 方法的使用示例:

uni.chooseMedia({count: 1, // 最多可以选择的图片或视频数量,默认为9mediaType: ['image', 'video'], // 可以指定选择的媒体类型为图片或视频,默认为['image', 'video']sourceType: ['album', 'camera'], // 可以指定图片/视频来源是相册还是相机,默认为['album', 'camera']maxDuration: 10, // 指定选择的视频的最大时长,单位秒,默认为60秒success: function (res) {// 关于 tempFilePaths 跟上文的注意事项类似var tempFiles = res.tempFiles;// 在这里可以对选择的图片或视频进行处理,比如显示、上传等操作console.log('选择的图片/视频路径:', tempFiles);},fail: function (err) {console.log('选择图片/视频失败:', err.errMsg);}
});

在上述代码中,通过调用 uni.chooseMedia() 方法,可以打开图片/视频选择界面。可以通过设置 count 来指定最多选择的图片或视频数量,mediaType 来指定选择的媒体类型(图片或视频),sourceType 来指定图片/视频来源(相册或相机),maxDuration 来指定选择的视频的最大时长。(具体使用方法和参数可以移步到官网查询和学习使用)

选择成功后,success 回调函数会被调用,可以在回调函数中获取选择的图片/视频的临时文件路径(tempFiles)。在回调函数中,可以对选择的图片/视频进行进一步处理,比如显示到页面上、上传到服务器等操作。如果选择图片或视频失败,fail 回调函数会被调用,可以在回调函数中处理错误信息。

📌uni.chooseImage() 与 uni.chooseMedia()

注意看下面这个图的红框部分,在微信小程序基础库 2.21.0 版本开始, wx.chooseImage 停止维护了,因此在开发过程中,我们在选择上传图片的方法时,需要留意下停止维护是否会影响到项目的后期迭代更新。因此可以使用 uni.chooseMedia 代替,以获得更好的兼容性和功能支持。
在这里插入图片描述
二者区别:

  • 功能:uni.chooseImage() 只能选择图片文件,而 uni.chooseMedia() 可以选择图片和视频文件。
  • 参数:在使用 uni.chooseImage() 时,可以通过设置 count 来指定最多选择的图片数量,而在使用 uni.chooseMedia() 时,可以通过设置 count 来指定最多选择的图片或视频数量。(等等)
  • 此外,uni.chooseMedia() 还可以通过设置 mediaType 来指定选择的媒体类型(图片或视频),以及通过设置 maxDuration 来指定选择的视频的最大时长。

🧩uni.chooseFile()

除了上面两个方法,这里还有一个方法也可以做到上传图片,但是不建议优先考虑使用 uni.chooseFile() 这个方法来进行上传图片的操作。因为 uni.chooseFile() 是 uniapp 框架提供的一个 API(仅兼容 H5),用于从本地选择文件。 该 API 主要用于选择非媒体文件,如果选择的文件是媒体文件,则可以用另外的专用API(如图片选择、视频选择、多媒体文件选择,含图片视频)。(兼容性如下图)
在这里插入图片描述
关于该方法的参数说明:

参数名类型默认值必填说明平台差异说明
countNumber100最多可以选择的文件数量不同平台的最大值可能会有差异
typeString‘all’所选的文件的类型不同平台支持的文件类型可能会有差异
extensionArray<String>根据文件拓展名过滤,每一项都不能是空字符串。默认不过滤。不同平台可能对拓展名的支持有差异
sourceTypeArray<String>[‘album’,‘camera’](仅在type为image或video时可用)album 从相册选图,camera 使用相机,默认二者都有。如需直接开相机或直接选相册,请只使用一个选项不同平台可能对相册和相机的支持有差异
successFunction成功则返回图片的本地文件路径列表 tempFilePaths
failFunction接口调用失败的回调函数
completeFunction接口调用结束的回调函数(调用成功、失败都会执行)

下面是 uni.chooseFile() 方法的使用示例:

uni.chooseFile({count: 1, // 最多可以选择的文件数量,默认为1type: 'all', // 可以指定选择的文件类型,如:image/video/audio/file,也可以使用 all,表示所有文件类型都可以选择,默认为 allsuccess: function (res) {var tempFilePaths = res.tempFilePaths;// 在这里可以对选择的文件进行处理,比如上传等操作console.log('选择的文件路径:', tempFilePaths);},fail: function (err) {console.log('选择文件失败:', err.errMsg);}
});

在上述代码中,通过调用 uni.chooseFile() 方法,可以打开文件选择界面。可以通过设置 count 来指定最多选择的文件数量,type 来指定选择的文件类型。

选择成功后,success 回调函数会被调用,可以在回调函数中获取选择的文件的临时文件路径(tempFilePaths)。在回调函数中,可以对选择的文件进行进一步处理,比如上传到服务器等操作。如果选择文件失败,fail 回调函数会被调用,可以在回调函数中处理错误信息。


🎯关于小程序隐私保护指引设置

上面介绍完上传图片的功能和使用案例,我们可以接着思考,既然我们要上传图片到程序或后台,那么上传图片就要读取到用户的手机相册或电脑的文件夹(编译器调试情况下或 PC 端打开小程序),这里就涉及到了一个隐私的问题,因此接下来我们一起来看一下关于小程序隐私保护指引设置,首先通过我的实际例子来给大家分享一下我从出现问题到解决问题的过程。

说到这点,其实也算是对个人 23 年接手的这一个项目做一个技术总结和经验分享吧,在微信官方更新小程序隐私保护指引设置的这个公告之前,小程序中的上传图片功能是正常的,但是在某一天,客户反馈说在注册过程中无法上传图片,因此针对这个问题,提出了三个排查方向,第一是前端上传图片类型错误了,导致前端判断逻辑有误、第二是后端接口的问题,第三是 API 的问题。逐一排查后,发现都不是这个问题,于是重点排查了 API 的问题,我通过输出 API 上传失败的原因和 fail 函数的输出来看,发现无论是在真机调试还是编译器上传都会出现这个报错。报错为:chooseImage:fail api scope is not declared in the privacy agreement,意思就是隐私协议中未声明 fail-api 作用域。
在这里插入图片描述
在这里插入图片描述
接下来对症下药,针对这个报错找解决方案即可,通过资料搜索和官网查询,发现也有不少开发者也同时遇到了这个问题,说明不是无缘无故冒出来的 bug,因此断定为官网修改 API 或发布新规则所导致。到该小程序的后台消息一看,发现新发布了一条关于小程序隐私保护指引设置的公告,公告这样说到:“为规范开发者的用户个人信息处理行为,保障用户的合法权益,自2023年9月15日起,对于涉及处理用户个人信息的小程序开发者,微信要求,仅当开发者主动向平台同步用户已阅读并同意了小程序的隐私保护指引等信息处理规则后,方可调用微信提供的隐私接口。”
在这里插入图片描述

🧩解决方法

知道了问题所在和微信官方给出的公告说明之后,我们可以很快的针对性的去解决这个问题,接下来分享一下解决方法。

首先我要到该小程序的后台提交协议信息,步骤为:进入首页,点击左侧导航栏的设置 => 功能设置 => 用户隐私保护指引设置 => 去填写信息提交审核。具体如下图。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里我们可以勾选“选中的照片或视频”这个选项(上传图片所需),其他则根据实际项目需要勾选即可。只有在指引中声明所处理的用户个人信息,才可以调用平台提供的对应接口或组件。若未声明,对应接口或组件将无法调用成功。

除此之外还可以配置用户隐私授权弹窗,微信提供了 wx.onNeedPrivacyAuthorization(function callback) 接口,意为用户触发了一个微信侧未记录过同意的隐私接口调用,开发者可通过响应该事件选择提示用户的时机。此外,微信还提供了 wx.requirePrivacyAuthorize(Object object) 接口,可用于模拟触发 onNeedPrivacyAuthorization 事件。仅有在指引中声明所处理的用户个人信息,才可以调用平台提供的对应接口或组件。若未声明,对应接口或组件将直接禁用。
在这里插入图片描述
如要进行代码提审,开发者需先自行声明是否有采集用户隐私,如有,则需在提审页面-「用户隐私保护设置」选择“采集用户隐私”。
在这里插入图片描述
通过上面一系列的方法,我也是解决这次项目出现的问题了,亲测有效,审核通过之后,稍等片刻,项目重新编译就好了。这次发现问题解决问题的经验是非常宝贵的,通过这次项目的事故也让我在开发的过程中更加仔细了,除此之外我也会时刻关注微信官方发布的最新规则和公告等等,避免出现影响项目正常运行的情况,如果是迫不得已也要预留好解决方案和备用方案。


📝最后

到此就是本篇文章的全部内容了,这篇文章记录的主要内容是微信小程序的上传图片功能选择和使用对比以及小程序隐私保护指引设置。回顾 2023年,我开始接触了 uni-app 和微信小程序的开发,在开发和学习的过程中,我遇到了很多问题和挑战,同时也积累了很多实战技巧和经验,这篇文章是博主 uni-app 专栏第一篇年度实战总结的文章,后续还会不断的更新更多关于 uni-app 的干货、实战经验、学习经验,期待你的关注和留言。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5D动感影院新奇体验丰富环境特效7D互动影院

5D动感影院太火啦&#xff01;凭借真实互动感、全视景高清屏幕、立体环绕音效、D打造新颖沉浸式观影体验&#xff0c;成为年轻人/家长/小朋友的新晋打卡聚集地&#xff0c;时刻上演着精彩绝伦的视觉盛宴&#xff01; 1、5D动感影院【硬件组成】&#xff1a;动感平台、金属银幕、…

Alinx ZYNQ 7020 LED调试--in RAM

设置拨码开关为JTAG方式 烧写LED bit stream a. 点击“Program device”烧录程序到FPGA中&#xff08;重新上电程序就丢失了&#xff09; b. /01_led/led.runs/impl_1/led.bit 程序烧录到Flash中 ZYNQ与以往的直接烧录Flash不同&#xff0c;首先必须PS&#xff0c;然后烧…

PXE和kickstart无人值守安装

PXE高效批量网络装机 引言 1.系统装机的引导方式 启动 操作 系统 1.硬盘 2.光驱&#xff08;u盘&#xff09; 3.网络启动 pxe 重装系统&#xff1f; 在已有操作系统 新到货了一台服务器&#xff0c; 装操作系统 系统镜像 u盘 光盘 pe&#xff1a; 小型的 操作系统 在操…

HTTP/HTTPS代理IP在多线程爬虫项目中的实践

在多线程爬虫项目中&#xff0c;HTTP/HTTPS代理IP的实践主要包括以下几个关键步骤&#xff1a; 1. 收集代理IP资源&#xff1a; - 从免费或付费代理IP提供商、公开代理列表网站&#xff08;如西刺代理、无忧代理等&#xff09;抓取代理IP和端口信息。 - 存储这些IP到数据库或者…

统计学-R语言-5.3

文章目录 前言分位数统计量的标准误总结 前言 本篇文章即为概率与分布的最后一篇文章。 分位数 分位数函数是累积分布函数的反函数。 p-分位数是具有这样性质的一个值&#xff1a;小于或等于它的概率为p。 根据定义&#xff0c;中位数即50%分位数。 分位数通常用于置信区间的…

RT-Thread 15. list_timer与软定时器

1. 代码 void rt_thread_usr1_entry(void *parameter) {/* set LED2 pin mode to output */rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT);while (1){rt_pin_write(LED2_PIN, PIN_HIGH);rt_thread_mdelay(2000);rt_pin_write(LED2_PIN, PIN_LOW);rt_thread_mdelay(3000);} }int ma…

前端公共组件库优化

背景 前段时间入职了新公司后&#xff0c;做一些内部前端基建的工作&#xff0c;其中一个工作就是优化现有的frontend-common公共组件库。之前的组件库一直是以源码依赖的形式存在&#xff0c;即各个项目通过git submodule的方式将该仓库引入到各个项目中&#xff0c;作为一个…

【K8S 云原生】K8S的对外服务—ingress

目录 一、K8S的Service 1、Service的作用 2、Service类型&#xff1a; 二、ingress 1、ingress的组成&#xff1a; 2、ingress资源的定义项&#xff1a; 3、ingress暴露服务端的方式 3.1、DeploymentLoadBalancer模式&#xff1a; 1、工作流程图&#xff1a; 3.2、Dae…

PDF转PowerPoint - Java实现方法

通过编程实现PDF转PPT的功能&#xff0c;可以自动化转换过程&#xff0c;减少手动操作的工作量&#xff0c;并根据需要进行批量转换。将PDF文件转换为PPT文档后&#xff0c;可以利用PPT的丰富功能和动画效果&#xff0c;达到更好的演示效果。 在Java中&#xff0c;我们可以使用…

PyTorch损失函数(二)

损失函数 5、nn.L1Loss nn.L1Loss是一个用于计算输入和目标之间差异的损失函数&#xff0c;它计算输入和目标之间的绝对值差异。 主要参数&#xff1a; reduction&#xff1a;计算模式&#xff0c;可以是none、sum或mean。 none&#xff1a;逐个元素计算损失&#xff0c;返…

清晰光谱空间:全自动可调波长系统的高光谱成像优势

高光谱成像技术 高光谱成像技术是一种捕获和分析宽波长信息的技术&#xff0c;能够对材料和特征进行详细的光谱分析和识别。高光谱成像技术的实现通过高光谱相机&#xff0c;其工作原理是使用多个光学传感器或光学滤波器分离不同波长的光&#xff0c;并捕获每个波段的图像&…

Node+Express编写接口---服务端

开始&#xff1a; 个人兴趣爱好&#xff0c;欢迎大家多多指教&#xff01;(点击直达源码!) node_vue_admin: 第一个以node为后端,vue为前端的后台管理项目https://gitee.com/ah-ah-bao/node_vue_admin.git 第一步:安装 安装Node.js 点击直达Node.js (nodejs.org) 安装Navic…

点赞模块设计 - Redis缓存 + 定时写入数据库实现高性能点赞功能

点赞模块设计 - Redis缓存 定时写入数据库实现高性能点赞功能 源码地址&#xff1a;github.com/cachecats/c… 点赞是作为整个系统的一个小模块&#xff0c;代码在 user-service 用户服务下。 本文基于 SpringCloud, 用户发起点赞、取消点赞后先存入 Redis 中&#xff0c;再…

WordPress回收站自动清空时间?如何关闭回收站或设置自动清理天数?

我们在WordPress后台的文章、页面、评论等页面都可以看到有回收站&#xff0c;意思就是我们不能直接删除某篇文章、页面、评论&#xff0c;而是需要现将它们移至回收站&#xff0c;然后再到回收站永久删除&#xff0c;或等回收站自动清理。 如上图所示&#xff0c;WordPress 6.…

javacv和opencv对图文视频编辑-裸眼3D图片制作

通过斗鸡眼&#xff0c;将左右两张相似的图片叠加到一起看&#xff0c;就会有3D效果。 3D图片&#xff0c;3D眼镜&#xff0c;3D视频等原理类似&#xff0c;都是通过两眼视觉差引起脑补产生3D效果。 图片&#xff1a; 图片来源&#xff1a; 一些我拍摄的真*裸眼3D照片 - 哔哩…

Java21 + SpringBoot3集成Spring Data JPA

Java21 SpringBoot3集成Spring Data JPA 文章目录 Java21 SpringBoot3集成Spring Data JPA前言相关技术简介ORM&#xff08;Object-Relational Mapping&#xff0c;对象-关系映射&#xff09;JPA&#xff08;Java Persistence API&#xff0c;Java持久层API&#xff09;Hiber…

新版K8s:v1.28拉取Harbor仓库镜像以及本地镜像(docker弃用改用containerd,纯纯踩坑)

目录 一、项目概述二、环境三、项目样式Harborkuboard运行样式 四、核心点Harbor安装config.toml文件修改(containerd)ctr、nerdctl相关命令kuboard工作负载 五、总结 一、项目概述 使用Kuboard作为k8s集群的管理平台&#xff0c;Harbor作为镜像仓库&#xff0c;拉取Harbor镜像…

【kafka】记录用-----------1

主题&#xff08;topic&#xff09;&#xff1a;消息的第一次分类 根据人为的划分条件将消息分成不同的主题 主题的划分是人为的根据不同的任务情景去划分 比如&#xff0c;我们有两个主题&#xff0c;一个是"订单"&#xff0c;另一个是"库存"。每个主题代…

24号资源——程序:电力系统程序集合已提供下载资源

24号资源&#xff1a;程序集合包含17个程序&#xff08;经典电力系统经济调度程序&#xff1b;2解决带储&#xff1b;3智能微电网PSO优化算法&#xff1b;微电网调度等等见资源描述&#xff09;资源-CSDN文库https://download.csdn.net/download/LIANG674027206/88752141&#…

ruoyi-cloud—若依微服务打包部署

1. 前端端口修改 2. 后端端口修改 &#xff08;1&#xff09;修改ruoyi-gateway服务中的bootstrap.yml的port端口 &#xff08;2&#xff09;修改ruoyi-ui中的vue.confing.js的target中的端口 3. 后端部署 (1) 在本地电脑上代码界面上打包后端 在ruoyi项目的bin目录下执行pa…