Java集成E签宝实现签署

完整代码:java-boot-highpin-background: 背调服务 (gitee.com)  【暂不开源】
1.在application.yml中配置appid、密钥信息,包含沙箱环境```javaesign:host: https://smlopenapi.esign.cnappId: your appIdappSecret: your secret```
2.实现电子签的主要流程在BaseAuthInfoServiceImpl里面1.根据模板生成word文件(word文件模板在resources里面)2.生成好的文件进行上传,上传分两步:具体实现看uploadMFile方法3.查询文件上传状态4.获取文件坐标5.创建签署流程,返回签署流程id6.最后返回页面签署路径url,返回给前端用于给用户访问签署的页面

3.代码实现:

package io.renren.modules.zhaopin.service.impl;import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import io.renren.common.esign.EsignFileBean;
import io.renren.common.esign.EsignHttpHelper;
import io.renren.common.esign.EsignHttpResponse;
import io.renren.common.esign.enums.EsignHeaderConstant;
import io.renren.common.esign.enums.EsignRequestType;
import io.renren.common.esign.exception.EsignDemoException;
import io.renren.common.utils.*;
import io.renren.modules.zhaopin.dao.BaseAuthInfoDao;
import io.renren.modules.zhaopin.entity.BackgroundCheckOrdersEntity;
import io.renren.modules.zhaopin.entity.BaseAuthInfoEntity;
import io.renren.modules.zhaopin.service.BackgroundCheckOrdersService;
import io.renren.modules.zhaopin.service.BaseAuthInfoService;
import io.renren.modules.zhaopin.util.HTTPHelper;
import io.renren.modules.zhaopin.util.IdWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;@Slf4j
@Service("baseAuthInfoService")
public class BaseAuthInfoServiceImpl extends ServiceImpl<BaseAuthInfoDao, BaseAuthInfoEntity> implements BaseAuthInfoService {@Value("${esign.host}")private String host;@Value("${esign.appId}")private String appId;@Value("${esign.appSecret}")private String appSecret;@Value("${esign.noticeUrl}")private String noticeUrl;@Autowiredprivate BackgroundCheckOrdersService backgroundCheckOrdersService;@Autowiredprivate BaseAuthInfoService baseAuthInfoService;@Autowiredprivate IdWorker idWorker;@Overridepublic PageUtils queryPage(Map<String, Object> params) {IPage<BaseAuthInfoEntity> page = this.page(new Query<BaseAuthInfoEntity>().getPage(params),new QueryWrapper<BaseAuthInfoEntity>());return new PageUtils(page);}/*** 生成word文件** @param reportId 报告id*/private void generateWordFile(String reportId) {LambdaQueryWrapper<BackgroundCheckOrdersEntity> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(BackgroundCheckOrdersEntity::getReportId, reportId);BackgroundCheckOrdersEntity checkOrders = backgroundCheckOrdersService.getOne(queryWrapper);try {File file = ResourceUtils.getFile("classpath:授权声明.docx");Map<String, Object> params = new HashMap<>();// 渲染文本params.put("company", checkOrders.getOrgName());params.put("id_card", checkOrders.getIdCard());params.put("date", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));String path = file.getPath();String fileDir = path.substring(0, path.lastIndexOf("授"));String templatePath = file.getPath(); // "D:\\zdd.docx";String fileName = "最终版授权声明";String wordPath = GeneratorWordUtils.createWord(templatePath, fileDir, fileName, params);System.out.println("生成文档路径:" + wordPath);} catch (FileNotFoundException e) {throw new RuntimeException(e);}}/*** 上传本地文件** @return*/private Map<String, Object> uploadMFile() {String contentType = "application/pdf";String postUrl = "/v3/files/file-upload-url";String postAllUrl = host + postUrl;try {File file = ResourceUtils.getFile("classpath:最终版授权声明.docx");String path = file.getPath();String contentMD5 = ESignUtils.getFileContentMD5(path);// 计算签名拼接的url// 构建请求Body体JSONObject reqBodyObj = new JSONObject();reqBodyObj.put("contentMd5", contentMD5);reqBodyObj.put("contentType", contentType);reqBodyObj.put("convertToPDF", true);reqBodyObj.put("fileName", "最终版授权声明.docx");reqBodyObj.put("fileSize", file.length() + "");Map<String, Object> resultMap = getStringObjectMapPost(reqBodyObj, postUrl, postAllUrl);Map<String, Object> dataMap = (Map<String, Object>) resultMap.get("data");String fileUploadUrl = (String) dataMap.get("fileUploadUrl");// 文件上传Gson gson = new Gson();EsignHttpResponse uploadFileResponse = ESignUtils.uploadFile(fileUploadUrl, path, contentMD5);JSONObject uploadFileResponseJsonObject = gson.fromJson(uploadFileResponse.getBody(), JSONObject.class);String code = uploadFileResponseJsonObject.get("errCode").toString();System.out.println("文件上传成功,状态码:" + code);return resultMap;} catch (Exception e) {e.printStackTrace();String msg = MessageFormat.format("请求签名鉴权方式调用接口出现异常: {0}", e.getMessage());System.out.println(msg);throw new RuntimeException(e);}}private Map<String, Object> getStringObjectMapPost(JSONObject reqBodyObj, String postUrl, String postAllUrl) throws Exception {// 请求Body体数据String reqBodyData = reqBodyObj.toString();// 对请求Body体内的数据计算ContentMD5String contentMD5 = ESignUtils.getBodyContentMD5(reqBodyData);System.out.println("请求body数据:" + reqBodyData);System.out.println("body的md5值:" + contentMD5);// 构建待签名字符串String method = "POST";String accept = "*/*";String contentType = "application/json; charset=UTF-8";String date = "";String headers = "";StringBuffer sb = new StringBuffer();sb.append(method).append("\n").append(accept).append("\n").append(contentMD5).append("\n").append(contentType).append("\n").append(date).append("\n");if ("".equals(headers)) {sb.append(headers).append(postUrl);} else {sb.append(headers).append("\n").append(postUrl);}// 构建参与请求签名计算的明文String plaintext = sb.toString();// 计算请求签名值String reqSignature = ESignUtils.doSignatureBase64(plaintext, appSecret);System.out.println("计算请求签名值:" + reqSignature);// 获取时间戳(精确到毫秒)long timeStamp = DateUtils.timeStamp();// 构建请求头LinkedHashMap<String, String> header = new LinkedHashMap<String, String>();header.put("X-Tsign-Open-App-Id", appId);header.put("X-Tsign-Open-Auth-Mode", "Signature");header.put("X-Tsign-Open-Ca-Timestamp", String.valueOf(timeStamp));header.put("Accept", accept);header.put("Content-Type", contentType);header.put("X-Tsign-Open-Ca-Signature", reqSignature);header.put("Content-MD5", contentMD5);System.out.println("header" + header);String result = HTTPHelper.sendPOST(postAllUrl, reqBodyData, header, "UTF-8");JSONObject resultObj = JSONObject.parseObject(result);// json转mapMap<String, Object> resultMap = (Map<String, Object>) JSONObject.toJavaObject(resultObj, Map.class);System.out.println("请求返回信息: " + resultObj.toString());System.out.println("请求返回信息: " + resultMap.toString());return resultMap;}/*** 创建签署流程发送请求API** @param reqBodyObj 请求体* @param postUrl    url* @param postAllUrl 全url* @return 返回数据* @throws Exception 异常处理*/private Map<String, Object> getCreatePostSign(JSONObject reqBodyObj, String postUrl, String postAllUrl) throws Exception {// 请求Body体数据String reqBodyData = reqBodyObj.toString();// 对请求Body体内的数据计算ContentMD5String contentMD5 = ESignUtils.getBodyContentMD5(reqBodyData);System.out.println("请求body数据:" + reqBodyData);System.out.println("body的md5值:" + contentMD5);// 构建待签名字符串String method = "POST";String accept = "*/*";String contentType = "application/json;charset=UTF-8";String date = "";String headers = "";StringBuffer sb = new StringBuffer();sb.append(method).append("\n").append(accept).append("\n").append(contentMD5).append("\n").append(contentType).append("\n").append(date).append("\n");if ("".equals(headers)) {sb.append(headers).append(postUrl);} else {sb.append(headers).append("\n").append(postUrl);}// 构建参与请求签名计算的明文String plaintext = sb.toString();// 计算请求签名值String reqSignature = ESignUtils.doSignatureBase64(plaintext, appSecret);System.out.println("计算请求签名值:" + reqSignature);// 获取时间戳(精确到毫秒)long timeStamp = DateUtils.timeStamp();// 构建请求头LinkedHashMap<String, String> header = new LinkedHashMap<String, String>();header.put("X-Tsign-Open-App-Id", appId);header.put("X-Tsign-Open-Auth-Mode", "Signature");header.put("X-Tsign-Open-Ca-Timestamp", String.valueOf(timeStamp));header.put("Accept", accept);header.put("Content-Type", contentType);header.put("X-Tsign-Open-Ca-Signature", reqSignature);header.put("Content-MD5", contentMD5);System.out.println("header" + header);String result = HTTPHelper.sendPOST(postAllUrl, reqBodyData, header, "UTF-8");JSONObject resultObj = JSONObject.parseObject(result);// json转mapMap<String, Object> resultMap = (Map<String, Object>) JSONObject.toJavaObject(resultObj, Map.class);int code = (int) resultMap.get("code");if (code == 0) {Map<String, Object> dataMap = (Map<String, Object>) resultMap.get("data");// 签署流程idString signFlowId = (String) dataMap.get("signFlowId");resultMap.put("signFlowId", signFlowId);}System.out.println("请求返回信息: " + resultObj.toString());return resultMap;}/*** 签署流程id 获取签署页面链接** @param signFlowId 签署流程id*/private String getSignUrl(String signFlowId) {String postAllUrl = host + "/v3/sign-flow/" + signFlowId + "/sign-url";String postUrl = "/v3/sign-flow/" + signFlowId + "/sign-url";Map<String, Object> operatorMap = new HashMap<>();operatorMap.put("psnAccount", "16619880853");JSONObject reqBodyObj = new JSONObject();reqBodyObj.put("clientType", "ALL");reqBodyObj.put("needLogin", false);reqBodyObj.put("urlType", 2);reqBodyObj.put("operator", operatorMap);Map<String, Object> redirectConfigMap = new HashMap<>();redirectConfigMap.put("redirectUrl", noticeUrl);reqBodyObj.put("redirectConfig", redirectConfigMap);System.out.println("reqBodyObj" + reqBodyObj);try {Map<String, Object> map = getStringObjectMapPost(reqBodyObj, postUrl, postAllUrl);System.out.println(map);int code = (int) map.get("code");if (code == 0) {Map<String, Object> dataMap = (Map<String, Object>) map.get("data");String shortUrl = (String) dataMap.get("shortUrl");return shortUrl;}} catch (Exception e) {e.printStackTrace();}return "";}/*** 查询文件上传状态** @param fileId 报告id* @return*/private Integer getFileStatus(String fileId) throws Exception {String getAllUrl = host + "/v3/files/" + fileId;String postUrl = "/v3/files/" + fileId;JSONObject reqBodyObj = new JSONObject();reqBodyObj.put("fileId", fileId);// GET请求时ContentMD5为""String contentMD5 = "";// 构建待签名字符串String method = "GET";String accept = "*/*";String contentType = "application/json; charset=UTF-8";String date = "";String headers = "";StringBuffer sb = new StringBuffer();sb.append(method).append("\n").append(accept).append("\n").append(contentMD5).append("\n").append(contentType).append("\n").append(date).append("\n");if ("".equals(headers)) {sb.append(headers).append(postUrl);} else {sb.append(headers).append("\n").append(postUrl);}// 构建参与请求签名计算的明文String plaintext = sb.toString();// 计算请求签名值String reqSignature = ESignUtils.doSignatureBase64(plaintext, appSecret);System.out.println("计算请求签名值:" + reqSignature);// 获取时间戳(精确到毫秒)long timeStamp = DateUtils.timeStamp();// 构建请求头LinkedHashMap<String, String> header = new LinkedHashMap<String, String>();header.put("X-Tsign-Open-App-Id", appId);header.put("X-Tsign-Open-Auth-Mode", "Signature");header.put("X-Tsign-Open-Ca-Timestamp", String.valueOf(timeStamp));header.put("Accept", accept);header.put("Content-Type", contentType);header.put("X-Tsign-Open-Ca-Signature", reqSignature);header.put("Content-MD5", contentMD5);HashMap<String, Object> query = new HashMap<String, Object>();// 发送POST请求String result = HTTPHelper.sendGet(getAllUrl, query, header, "UTF-8");JSONObject resultObj = JSONObject.parseObject(result);System.out.println("请求返回信息: " + resultObj.toString());Map<String, Object> resultMap = (Map<String, Object>) JSONObject.toJavaObject(resultObj, Map.class);System.out.println(resultMap);return (Integer) resultMap.get("code");}/*** 获取文件坐标*/private Map<String, Object> getPosition(String fileId) {try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}String postUrl = "/v3/files/" + fileId + "/keyword-positions";String postAllUrl = host + postUrl;JSONObject reqBodyObj = new JSONObject();reqBodyObj.put("fileId", fileId);List<String> keywords = new ArrayList<>();keywords.add("本人签名");reqBodyObj.put("keywords", keywords);try {Map<String, Object> map = getStringObjectMapPost(reqBodyObj, postUrl, postAllUrl);System.out.println(map);Map<String, Object> dataMap = (Map<String, Object>) map.get("data");if (dataMap == null) {throw new RuntimeException("解析失败");}List keywordPositions = (List) dataMap.get("keywordPositions");Map<String, Object> objectMap = (Map<String, Object>) keywordPositions.get(0);List positions = (List) objectMap.get("positions");Map<String, Object> positionMap = (Map<String, Object>) positions.get(0);List coordinates = (List) positionMap.get("coordinates");Integer pageNums = (Integer) positionMap.get("pageNum");Map<String, Object> position = (Map<String, Object>) coordinates.get(0);position.put("pageNums", pageNums);return position;} catch (Exception e) {throw new RuntimeException(e);}}/*** 签署** @param reportId* @return*/@Override@Transactional(rollbackFor = Exception.class)public R sign(String reportId) {try {String id = idWorker.nextId() + "";generateWordFile(reportId);Map<String, Object> resultMap = uploadMFile();Map<String, Object> dataMap = (Map<String, Object>) resultMap.get("data");String fileId = (String) dataMap.get("fileId");String fileUploadUrl = (String) dataMap.get("fileUploadUrl");System.out.println(resultMap);/*1. 查看所上传文件的当前状态(转换pdf/html文件状态)文件名称和下载链接。2. 当返回的文件状态status值为 2 或 5 时,此文件才可以被应用到签署流程中。*/Integer fileStatus = getFileStatus(fileId);if (fileStatus == 0) {Map<String, Object> position = getPosition(fileId);BigDecimal positionY = (BigDecimal) position.get("positionY");BigDecimal positionX = (BigDecimal) position.get("positionX");Integer pageNums = (Integer) position.get("pageNums");Map<String, Object> sign = createSign(fileId, reportId, positionX, positionY, pageNums);String signUrl = (String) sign.get("signUrl");String signFlowId = (String) sign.get("signFlowId");// 保存到数据库 fileUploadIdBaseAuthInfoEntity baseAuthInfoEntity = new BaseAuthInfoEntity();baseAuthInfoEntity.setId(id);baseAuthInfoEntity.setOrderId(reportId);baseAuthInfoEntity.setAuthFlowId(signFlowId);baseAuthInfoEntity.setAuthUrl(signUrl);baseAuthInfoEntity.setCreateTime(LocalDateTime.now());baseAuthInfoEntity.setUpdateTime(LocalDateTime.now());baseAuthInfoEntity.setFileId(fileId);baseAuthInfoEntity.setFileUploadUrl(fileUploadUrl);baseAuthInfoService.save(baseAuthInfoEntity);return R.ok(sign);}} catch (Exception e) {throw new RuntimeException(e);}return R.ok("签署流程失败");}/*** 创建签署流程*/public Map<String, Object> createSign(String fileId, String reportId, BigDecimal positionX, BigDecimal positionY, Integer pageNums) {LambdaQueryWrapper<BackgroundCheckOrdersEntity> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(BackgroundCheckOrdersEntity::getReportId, reportId);BackgroundCheckOrdersEntity checkOrders = backgroundCheckOrdersService.getOne(queryWrapper);Map<String, Object> paramsMap = new HashMap<>();Map<String, Object> docsMap = new HashMap<>();// 待签署文件IDdocsMap.put("fileName", "最终版授权声明.docx");docsMap.put("fileId", fileId);Map<String, Object> signFlowConfigMap = new HashMap<>();signFlowConfigMap.put("signFlowTitle", "企业合同签署");signFlowConfigMap.put("notifyUrl", "www.baidu.com");Map<String, Object> redirectConfigMap = new HashMap<>();redirectConfigMap.put("redirectUrl", "www.baidu.com");signFlowConfigMap.put("redirectConfig", redirectConfigMap);signFlowConfigMap.put("autoFinish", true);Map<String, Object> signersMap = new HashMap<>();Map<String, Object> signConfigMap = new HashMap<>();signConfigMap.put("forcedReadingTime", 5);/*签署方类型,0 - 个人,1 - 企业/机构,2 - 法定代表人,3 - 经办人若指定签署方为个人,则psnSignerInfo为必传项;若指定签署方为机构或法定代表人手动签署(autoSign参数为false)时,则orgSignerInfo为必传项;若指定签署方为经办人,在同级数组内必须还有机构类型存在,且orgSignerInfo为必传项,即:指定3 - 经办人签的前提是必须同时存在1 - 企业/机构,且经办人签属于企业合同,不在个人名下。*/signersMap.put("signerType", 0);signersMap.put("signConfig", signConfigMap);Map<String, Object> psnSignerInfoMap = new HashMap<>();// 企业/机构名称(账号标识)psnSignerInfoMap.put("psnAccount", checkOrders.getHrTel());signersMap.put("psnSignerInfo", psnSignerInfoMap);List<Object> docsList = new ArrayList<>();docsList.add(docsMap);paramsMap.put("docs", docsList);paramsMap.put("signFlowConfig", signFlowConfigMap);List<Object> signersList = new ArrayList<>();signersList.add(signersMap);// signersList.add(psnSignerInfoMap);// paramsMap.put("signers", signersList);List<Object> signFieldsList = new ArrayList<>();Map<String, Object> signFieldsMap = new HashMap<>();signFieldsMap.put("fileId", fileId);signFieldsMap.put("customBizNum", idWorker.nextId() + "");Map<String, Object> normalSignFieldConfigMap = new HashMap<>();// 1 - 单页签章,2 - 骑缝签章normalSignFieldConfigMap.put("signFieldStyle", 1);normalSignFieldConfigMap.put("freeMode", false);normalSignFieldConfigMap.put("autoSign", false);Map<String, Object> signFieldPositionMap = new HashMap<>();signFieldPositionMap.put("positionX", positionX);signFieldPositionMap.put("positionY", positionY);signFieldPositionMap.put("positionPage", pageNums);signFieldsMap.put("normalSignFieldConfig", normalSignFieldConfigMap);normalSignFieldConfigMap.put("signFieldPosition", signFieldPositionMap);signFieldsList.add(signFieldsMap);signersMap.put("signFields", signFieldsList);String postAllUrl = host + "/v3/sign-flow/create-by-file";String postUrl = "/v3/sign-flow/create-by-file";JSONObject reqBodyObj = new JSONObject();reqBodyObj.put("docs", docsList);reqBodyObj.put("signFlowConfig", signFlowConfigMap);reqBodyObj.put("signers", signersList);System.out.println("reqBodyObj:" + reqBodyObj);System.out.println("paramsMap:" + paramsMap);try {Map<String, Object> map = getCreatePostSign(reqBodyObj, postUrl, postAllUrl);String signFlowId = (String) map.get("signFlowId");// 签署流程id 获取签署页面链接String signUrl = getSignUrl(signFlowId);map.put("signUrl", signUrl);map.put("signFlowId", signFlowId);return map;} catch (Exception e) {throw new RuntimeException(e);}}}

工具类代码比较多,就不全部写出来了

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

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

相关文章

Centos7 elasticsearch-7.7.0 集群搭建,启用x-pack验证 Kibana7.4用户管理

前言 Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎&#xff0c;能够解决不断涌现出的各种用例。 作为 Elastic Stack 的核心&#xff0c;它集中存储您的数据&#xff0c;帮助您发现意料之中以及意料之外的情况。 环境准备 软件 …

kubernetes(K8S)学习(七):K8S之系统核心组件

K8S之系统核心组件 K8s系统核心组件1.1 Master和Node1.2 kubeadm1.3 先把核心组件总体过一遍1.4 Kubernetes源码查看方式1.5 kubectl1.6 API Server1.7 集群安全机制之API Server1.8 Scheduler1.9 kubelet1.10 kube-proxy K8s系统核心组件 1.1 Master和Node 官网 &#xff1a;…

원클릭으로 주류 전자상거래 플랫폼 상품 상세 데이터 수집 및 접속 시연 예제 (한국어판)

클릭 한 번으로 전자상거래 플랫폼 데이터를 캡처하는 것은 일반적으로 웹 페이지에서 정보를 자동으로 추출 할 수있는 네트워크 파충류 기술과 관련됩니다.그러나 모든 형태의 데이터 수집은 해당 웹 사이트의 사용 약관 및 개인 정보 보호 정책 및 현지 법률 및 규정을 준수…

【C++笔记】异常与智能指针

一、异常 1.1、C的异常的使用 其实在C语言阶段我们就接触过异常了&#xff0c;例如C语言中的assert断言判断程序错误以及errorno异常编号。 而C中把异常设计成了一个类&#xff0c;如果要使用C中的异常&#xff0c;就要引入exception这个头文件&#xff1a; 这个头文件中就是…

基于Web的社区医院管理服务系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读100套最新项目持续更新中..... 2024年计算机毕业论文&#xff08;设计&#xff09;学生选题参考合集推荐收藏&#xff08;包含Springboot、jsp、ssmvue等技术项目合集&#xff09; 1. 系统功能…

全套医院手术麻醉系统源码 人工智能麻醉系统源码 医疗管理系统源码

全套医院手术麻醉系统源码 人工智能麻醉系统源码 医疗管理系统源码 手术麻醉临床信息系统有着完善的临床业务功能&#xff0c;能够涵盖整个围术期的工作&#xff0c;能够采集、汇总、存储、处理、展现所有的临床诊疗资料。通过该系统的实施&#xff0c;能够规范麻醉科的工作流…

带你认识线程

线程的概念 前言&#xff1a; 一个程序运行起来&#xff0c;就会对应一个进程&#xff0c;例如&#xff0c;启动一个 Java 程序&#xff0c;就会创建一个 Java 进程。进程也被称为系统分配资源的基本单位。 一个进程可以包含一个线程&#xff0c;也可以包含多个线程&#xff…

C语言查找-----------BF算法KMP算法

1.问题引入 有一个主字符串&#xff0c;有一个子字符串&#xff0c;要求我们寻找子字符串在主字符串里面开始出现的位置&#xff1b; 2.BF算法 BF算法就是暴力算法&#xff0c;这个做法虽然效率不高&#xff0c;但是按照我们传统的思路依然能够得到结果&#xff0c;接下来我们…

HarmonyOS实战开发-实现Ability内页面间的跳转和数据传递。

介绍 本篇Codelab基于Stage模型下的Ability开发&#xff0c;实现Ability内页面间的跳转和数据传递。 最终效果图如下&#xff1a; 相关概念 页面路由&#xff1a;提供通过不同的url访问不同的页面&#xff0c;包括跳转到应用内的指定页面、用应用内的某个页面替换当前页面、…

通讯录改进———动态版本

在上一篇博客中讲完了动态内存分配&#xff0c;这时候我们就可以改进之前写的通讯录了&#xff0c;可以将其升级为动态内存的版本&#xff0c;既不用担心联系人满了&#xff0c;也不用担心内存浪费太大。 要将其改为动态版本主要是两件事&#xff0c;首先初始化的时候我们要动…

算法打卡day31|贪心算法篇05|Leetcode 435. 无重叠区间、763.划分字母区间、56. 合并区间

算法题 Leetcode 435. 无重叠区间 题目链接:435. 无重叠区间 大佬视频讲解&#xff1a;无重叠区间视频讲解 个人思路 和昨日的最少箭扎气球有些类似&#xff0c;先按照右边界排序&#xff0c;从左向右记录非交叉区间的个数。最后用区间总数减去非交叉区间的个数就是需要移除的…

Image-Adaptive YOLO for Object Detection in Adverse Weather Conditions(IA-YOLO)

1、总体概述 基于深度学习的目标检测在常规条件的数据集可以获得不错的结果&#xff0c;但是在环境、场景、天气、照度、雾霾等自然条件的综合干扰下&#xff0c;深度学习模型的适应程度变低&#xff0c;检测结果也随之下降&#xff0c;因此研究在复杂气象条件下的目标检测方法…