uni-app中web-view的使用

1. uni-app中web-view的使用

  uni-app中的web-view是一个 web 浏览器组件,可以用来承载网页的容器,uni-app开发的app与web-view实现交互的方式相关简单,应用通过属性@message绑定触发事件,然后在web-view的网页向应用 postMessage 触发并收到消息即可,详细请参考官网:web-view | uni-app官网 (https://uniapp.dcloud.net.cn/component/web-view.html#)主要实现代码参考下图所示。

1.1. uni-app中web-view的使用

1.1.1. app页面

<template><web-view :src="url" @message="handleMessage"></web-view>
</template><script>
export default {data() {return {url: null  //要打开的外部链接};},methods: {//通过 @message 事件接收外部链接传过来的内容handleMessage(event) {if (event.detail.data[0].isClose) {uni.reLaunch({url: '/main/main'});}}}
};
</script>

1.1.2.外部链接H5

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>我是在app里打开的页面</title><script src="./jquery-3.4.1.js" type="text/javascript" charset="utf-8"></script><!-- 微信JS-SDK 兼容微信小程序 引入此文件 --><script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script><!-- uni-app SDK --><script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script></head><body><div style="width: 100%;height: 100%;position: absolute;left: 0;top: 0;right: 0;bottom: 0;"><button id="btn">按钮</button></div></body><script>document.addEventListener('UniAppJSBridgeReady', function() {console.log("加载完成,可以使用uni相关接口");});$("#btn").click(function() {uni.postMessage({data: {isClose: true}})uni.navigateBack();})</script>
</html>

1.1.3.问题

  但是,以上方法只适合于APP,在H5环境中是不支持的,官方说明如下:
在这里插入图片描述
  那么,在uni-app如何实现在H5环境中与web-view中的网页交互通讯呢,按照官方的说法,使用window.postMessage方式实现!

1.2. window.postMessage

  关于window.postMessage的通讯原理,请参考官方档window.postMessage - Web API 接口参考 | MDN(https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage)

1.2.1. 应用端代码

onLoad: function() {window.addEventListener('message', function(e) { // 监听 message 事件console.log(e.origin);console.log("从" + e.origin + "收到消息: " + e.data);});
}

1.2.2. 网页端代码(H5)

//向uniapp发送信息
function sendMsgToUniapp(value) {parent.postMessage(value, "*");
}

  说明:uni-app的web-view,在H5环境中其实就是通过iframe来实现的,因此在iframe中的页面可直接通过jquery中的parent来获取父页面对象,并通过parent.postMessage的方式传递消息。

1.3. 完整代码

在这里插入图片描述

1.3.1. pageWeb.vue(uiapp)

<template><view><web-view @message="message":src="webViewUrl"></web-view></view>
</template><script>import pageUtil from '../../../utils/pageUtil.js';export default {data() {return {webViewUrl: '/hybrid/html/html/pageUniWeb.html?data=您好',//webViewUrl: 'http://120.224.9.76:18080/app/news/html/pageUniWeb.html?data=efhejr',wv: ''}},onReady() {pageUtil.setTitleBar('业务协同')},onLoad() {var that = this;// #ifdef APP-PLUS//此对象相当于html5plus里的plus.webview.currentWebview()。// 在uni-app里vue页面直接使用plus.webview.currentWebview()无效let currentWebview = this.$scope.$getAppWebview()setTimeout(() => {this.wv = currentWebview.children()[0]}, 300)// #endiftry {//信息交互(H5浏览器使用),监听 message 事件window.addEventListener('message',function (e) {console.log("从" + e.origin, "收到消息: ", e);var resData = e.data.data.arg;if (resData.myType) {uni.showToast({icon: 'none',title: "uniap获取H5发送数据:" + JSON.stringify(resData)});}});} catch (e) {}},methods: {//信息交互(app真机使用)message(e) {var that = thisvar resData = e.detail.data;console.log("uniap获取H5发送数据:", e)uni.showToast({icon: 'none',title: "uniap获取H5发送数据:" + JSON.stringify(resData)});var myObj = {}myObj.msg="我是uniapp"//这里必须序列化!!!myObj = JSON.stringify(myObj)this.wv.evalJS(`postJS(${myObj})`);},}}
</script>
<style>
</style>

1.3.2. pageUniWeb.html(H5)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>web-view</title><script type="text/javascript" src="../static/js/init-rem.js"></script><script type="text/javascript" src="../static/js/jquery-3.1.1.min.js"></script><script type="text/javascript" src="../static/helper/init-helper.js"></script><!--    <script src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"--><!--            type="text/javascript" charset="utf-8"></script>--><script type="text/javascript" src="../static/helper/web-view-custom.js"></script><script type="text/javascript" src="../static/js/vconsole.min.js"></script><script type="text/javascript">var vc = new VConsole()</script><style>.btn-layout {display: flex;flex-direction: column;align-items: center;}.btn-item {display: inline;font-size: 0.32rem;color: white;text-align: center;padding: 0.2rem 0.5rem;border-radius: 0.3rem;margin-top: 0.5rem;background-color: #1AAD19;}.content {display: inline;font-size: 0.32rem;color: black;text-align: center;padding: 0.2rem 0.5rem;border-radius: 0.3rem;margin-top: 0.5rem;}</style>
</head>
<body>
<div class="btn-layout"><span id="h5ToUniappId" class="btn-item">H5发送数据到uniapp</span><div id="contentId" class="content"></div><div id="content2Id" class="content"></div>
</div></body>
<script type="text/javascript">var itemData = getParamByKey('data');console.log("获取uniapp链接传递数据:", itemData)$(function () {$('#contentId').html("获取uniapp链接传递数据:"+itemData)});/*** 获取uniapp传递数据方法一* 定义全局方法,接收来自应用的信息*/// window.postJS = (msg) => {//     console.log('来自应用的消息', msg)// }/*** 获取uniapp传递数据方法二*/function postJS(e) {console.log("获取uniapp传递数据:", e)$('#content2Id').html("获取uniapp传递数据:"+JSON.stringify(e))}document.addEventListener('UniAppJSBridgeReady',function () {webUni.webView.getEnv(function (res) {console.log('当前环境:' + JSON.stringify(res));});document.querySelector('#h5ToUniappId').addEventListener('click', function (evt) {// webUni.webView.navigateBack();//向uniapp传值//方法一//window.parent.postMessage("", '*')//parent.postMessage("sdcec", "*");//方法二webUni.postMessage({data: {action: 'message',msg: '我是H5',myType: 'typeH5',}});});});
</script>
</html>

1.3.3. web-view-custom.js

!function (e, n) {"object" == typeof exports && "undefined" != typeof module ? module.exports = n() : "function" == typeof define && define.amd ? define(n) : (e = e || self).webUni = n()
}(this, (function () {"use strict";try {var e = {};Object.defineProperty(e, "passive", {get: function () {!0}}), window.addEventListener("test-passive", null, e)} catch (e) {}var n = Object.prototype.hasOwnProperty;function t(e, t) {return n.call(e, t)}var i = [], a = function (e, n) {var t = {options: {timestamp: +new Date}, name: e, arg: n};if (window.__dcloud_weex_postMessage || window.__dcloud_weex_) {if ("postMessage" === e) {var a = {data: [n]};return window.__dcloud_weex_postMessage ? window.__dcloud_weex_postMessage(a) : window.__dcloud_weex_.postMessage(JSON.stringify(a))}var o = {type: "WEB_INVOKE_APPSERVICE", args: {data: t, webviewIds: i}};window.__dcloud_weex_postMessage ? window.__dcloud_weex_postMessageToService(o) : window.__dcloud_weex_.postMessageToService(JSON.stringify(o))}if (!window.plus) return window.parent.postMessage({type: "WEB_INVOKE_APPSERVICE", data: t, pageId: ""}, "*");if (0 === i.length) {var r = plus.webview.currentWebview();if (!r) throw new Error("plus.webview.currentWebview() is undefined");var d = r.parent(), s = "";s = d ? d.id : r.id, i.push(s)}if (plus.webview.getWebviewById("__uniapp__service")) plus.webview.postMessageToUniNView({type: "WEB_INVOKE_APPSERVICE",args: {data: t, webviewIds: i}}, "__uniapp__service"); else {var w = JSON.stringify(t);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE", '",').concat(w, ",").concat(JSON.stringify(i), ");"))}}, o = {navigateTo: function () {var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, n = e.url;a("navigateTo", {url: encodeURI(n)})}, navigateBack: function () {var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, n = e.delta;a("navigateBack", {delta: parseInt(n) || 1})}, switchTab: function () {var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, n = e.url;a("switchTab", {url: encodeURI(n)})}, reLaunch: function () {var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, n = e.url;a("reLaunch", {url: encodeURI(n)})}, redirectTo: function () {var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, n = e.url;a("redirectTo", {url: encodeURI(n)})}, getEnv: function (e) {window.plus ? e({plus: !0}) : e({h5: !0})}, postMessage: function () {var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};a("postMessage", e.data || {})}}, r = /uni-app/i.test(navigator.userAgent), d = /Html5Plus/i.test(navigator.userAgent),s = /complete|loaded|interactive/;var w = window.my && navigator.userAgent.indexOf("AlipayClient") > -1;var u = window.swan && window.swan.webView && /swan/i.test(navigator.userAgent);var c = window.qq && window.qq.miniProgram && /QQ/i.test(navigator.userAgent) && /miniProgram/i.test(navigator.userAgent);var g = window.tt && window.tt.miniProgram && /toutiaomicroapp/i.test(navigator.userAgent);var v = window.wx && window.wx.miniProgram && /micromessenger/i.test(navigator.userAgent) && /miniProgram/i.test(navigator.userAgent);var p = window.qa && /quickapp/i.test(navigator.userAgent);for (var l, _ = function () {window.UniAppJSBridge = !0, document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady", {bubbles: !0,cancelable: !0}))}, f = [function (e) {if (r || d) return window.__dcloud_weex_postMessage || window.__dcloud_weex_ ? document.addEventListener("DOMContentLoaded", e) : window.plus && s.test(document.readyState) ? setTimeout(e, 0) : document.addEventListener("plusready", e), o}, function (e) {if (v) return window.WeixinJSBridge && window.WeixinJSBridge.invoke ? setTimeout(e, 0) : document.addEventListener("WeixinJSBridgeReady", e), window.wx.miniProgram}, function (e) {if (c) return window.QQJSBridge && window.QQJSBridge.invoke ? setTimeout(e, 0) : document.addEventListener("QQJSBridgeReady", e), window.qq.miniProgram}, function (e) {if (w) {document.addEventListener("DOMContentLoaded", e);var n = window.my;return {navigateTo: n.navigateTo,navigateBack: n.navigateBack,switchTab: n.switchTab,reLaunch: n.reLaunch,redirectTo: n.redirectTo,postMessage: n.postMessage,getEnv: n.getEnv}}}, function (e) {if (u) return document.addEventListener("DOMContentLoaded", e), window.swan.webView}, function (e) {if (g) return document.addEventListener("DOMContentLoaded", e), window.tt.miniProgram}, function (e) {if (p) {window.QaJSBridge && window.QaJSBridge.invoke ? setTimeout(e, 0) : document.addEventListener("QaJSBridgeReady", e);var n = window.qa;return {navigateTo: n.navigateTo,navigateBack: n.navigateBack,switchTab: n.switchTab,reLaunch: n.reLaunch,redirectTo: n.redirectTo,postMessage: n.postMessage,getEnv: n.getEnv}}}, function (e) {return document.addEventListener("DOMContentLoaded", e), o}], m = 0; m < f.length && !(l = f[m](_)); m++) ;l || (l = {});var E = "undefined" != typeof webUni ? webUni : {};if (!E.navigateTo) for (var b in l) t(l, b) && (E[b] = l[b]);return E.webView = l, E
}));

1.3.4. init-helper.js

var u = navigator.userAgent;
// 是否为ios设备
var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
// 是否为PC端
var isPC = typeof window.orientation === 'undefined';
// 是否为android端
var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1;
// 是否为微信端,此处不能为===,因为match的结果可能是null或数组
var isWx = u.toLowerCase().match(/MicroMessenger/i) == 'micromessenger';
var strConstant = {/*** 业务协同*///待办eventWaitDeal: '我的待办',//已办eventHasDeal: '我的已办',//考勤打卡workCheckSign: '考勤打卡',//添加pageTypeAdd: 'add',//编辑pageTypeEdit: 'edit',/*** 跳转类型*/jumpTypeMapLoc: 'jumpTypeMapLoc',
}/*** @desc 返回上一页*/
function backPage() {//单击Android左上角返回键执行该方法history.pushState(null, null, location.href);window.addEventListener('popstate',function (event) {if (isAndroid) {if (window.androidJsHook) {history.pushState(null, null, location.href);window.androidJsHook.htmlFinish();} else {history.go(-1)}} else if (isiOS) {if (window.webkit) {history.pushState(null, null, location.href);window.webkit.postMessage(null);} else {history.go(-1)}} else {history.go(-1)}});
};/*** 跳换页面*/
function openPage(webUrl, webTitle, webParams) {if (window.androidJsHook) {window.androidJsHook.startForResult(webUrl, webTitle, webParams);} else {mui.openWindow({url: webUrl + webParams,id: webUrl,styles: {top: '0px',bottom: '0px'},waiting: {autoShow: false, //自动显示等待框,默认为true}});}
}/*** @description 通过传入key值,得到页面key的初始化传值* plus情况为plus.webview.currentWebview.**** h5情况为 window.location.href 中的参数的值* @param {String} key*/
function getParamByKey(key) {if (!key) {return null;}return GetQueryString(key) || getExtraDataByKey(key);
};function GetQueryString(name) {//  var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");//  var r = window.location.search.substr(1).match(reg);//  if (r != null) return unescape(r[2]); return null;/*中文不乱码*/return decodeURIComponent((new RegExp('[?|&]' + name+ '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [, ""])[1].replace(/\+/g, '%20')) || null;
}/*** @description 通过传入key值,得到页面key的初始化传值* plus情况为plus.webview.currentWebview.**** h5情况为 window.location.href 中的参数的值* @param {String} key*/
function getExtraDataByKey(key) {if (!key) {return null;}var value = null;//h5value = getUrlParamsValue(window.location.href, key);if (value === 'undefined') {value = null;}return value;
};/*** 删掉遮罩*/
function removeDrop() {$('.mui-popup-backdrop').remove();
}/*** 合并json对象* @param {Object} target 第一个json对象,同时也是合并后的json对象* @param {Object} source 第二个json对象*/
function extend(target, source) {for (var obj in source) {target[obj] = source[obj];}return target;
}/*** 转为json数据格式* @param {Object} idStr form表单的id*/
function transformToJson(idStr) {var formData = $("#" + idStr).serializeArray();var obj = {};var j = 1;for (var i in formData) {obj[formData[i].name] = formData[i]['value'];//伪数组length字段,用于遍历改造json对象obj['length'] = j;j++}return obj;
}/*** 通用方法封装处理* commonUtils.isEmpty(jsonParam.countyLabel*/
var commonUtils = {// 判断字符串是否为空isEmpty: function (value) {if (value == null || this.trim(value) == "" || value == undefined) {return true;}return false;},// 判断一个字符串是否为非空串isNotEmpty: function (value) {return !commonUtils.isEmpty(value);},// 空格截取trim: function (value) {if (value == null) {return "";}return value.toString().replace(/(^\s*)|(\s*$)|\r|\n/g, "");},// 判断字符串是否是以start开头startWith: function (value, start) {var reg = new RegExp("^" + start);return reg.test(value)}
};/*** 重置form表单*/
function resetForm(resetArr) {var textInputArr = $("input[type='text']")var numberInput = $("input[type='number']")var domId = nullfor (var i = 0; i < textInputArr.length; i++) {domId = $(textInputArr[i]).attr('id')var isContain = falseresetArr.forEach(function (item, index) {if (domId == item) {isContain = true}})if (!isContain) {$(textInputArr[i]).val("")}}for (var i = 0; i < numberInput.length; i++) {domId = $(numberInput[i]).attr('id')var isContain = falseresetArr.forEach(function (item, index) {if (domId == item) {isContain = true}})if (!isContain) {$(numberInput[i]).val("")}}
}/*** 更新三级联动字典* @param {Object} name* @param {Object} nameMS* @author zzs*/
function updateDictLevel3(name, nameMsArr, urlStr) {var queryParam = {};if (isNotNull(name)) {queryParam.name = name;}getNetData(urlStr, queryParam, function (result) {if (result.code == '200') {var nameA = [];if (result.data && result.data.length == 0) {nameA = [{"id": "","value": "请选择"}];} else {$.each(result.data, function (i, item) {var flag = {};flag.id = item.value;flag.value = item.label;//二级var childsA = [];if (item.children && item.children.length > 0) {$.each(item.children, function (j, childsItem) {var childsFlag = {};childsFlag.id = childsItem.value;childsFlag.value = childsItem.label;//三级var childsB = [];if (childsItem.children && childsItem.children.length > 0) {$.each(childsItem.children, function (k, grandsonItem) {var grandsonFlag = {};grandsonFlag.id = grandsonItem.value;grandsonFlag.value = grandsonItem.label;childsB.push(grandsonFlag);});}childsFlag.childs = childsB;childsA.push(childsFlag);});}flag.childs = childsA;nameA.push(flag);});}if (nameMsArr != null && nameMsArr.length > 0) {nameMsArr.forEach(function (nameMs, index) {nameMs.updateWheels(nameA);})}}})
}

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

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

相关文章

遥感卫星影像质量评价指标汇总

1. 主观评价方法 以人为图像的评价者&#xff0c;根据自己的评价尺度和经验对图像质量进行评价。 2. 客观评价方法 1)均方差 2)信噪比 主要用来评价影像经压缩、传输、增强等处理前后的质量变化情况&#xff0c;其本质与均方差类似。 3)方差 反映了图像各个像元灰度相对…

18.字面量

文章目录 一、字面量二、区分技巧三、扩展&#xff1a; /t 制表符 一、字面量 在有些资料&#xff0c;会把字面量说成常量、字面值常量&#xff0c;这种叫法都不是很正确&#xff0c;最正确的叫法还是叫做&#xff1a;字面量。 作用&#xff1a;告诉程序员&#xff0c;数据在…

itextPdf生成pdf简单示例

文章环境 jdk1.8&#xff0c;springboot2.6.13 POM依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version></dependency><dependency><groupId>com.ite…

小米还涉足了哪些领域

小米作为一家全球性的移动互联网企业&#xff0c;其业务领域相当广泛&#xff0c;除了核心的智能手机业务外&#xff0c;还涉足了许多其他领域。以下是对小米涉足领域的简要介绍&#xff1a; 智能硬件与IoT平台&#xff1a;小米是全球领先的智能硬件和IoT平台公司&#xff0c;致…

iOS网络抓包工具全解析

摘要 本文将深入探讨iOS平台上常用的网络抓包工具&#xff0c;包括Charles、克魔助手、Thor和Http Catcher&#xff0c;以及通过SSH连接进行抓包的方法。此外&#xff0c;还介绍了克魔开发助手作为iOS应用开发的辅助工具&#xff0c;提供的全方面性能监控和调试功能。 在iOS应…

Dubbo启动流程

Java面试题 Dubbo启动流程 1.服务提供者将服务实例化后注册到注册中心。 2.服务消费者向注册中心订阅所需的服务。 3.注册中心将服务提供者注册的服务地址推送给服务消费者&#xff0c;同时基于长链接推送变更。 4.服务消费者通过代理对象&#xff08;Proxy&#xff09;发起远…

【正版特惠】IDM 永久授权 优惠低至109元!

尽管小编有修改版IDM&#xff0c;但是由于软件太好用了&#xff0c;很多同学干脆就直接购买了正版&#xff0c;现在正版也不贵&#xff0c;并且授权码绑定自己的邮箱&#xff0c;直接官方下载激活&#xff0c;无需其他的绿化修改之类的操作&#xff0c;不喜欢那么麻烦的&#x…

【概率论与数理统计】Chapter2 随机变量及其分布

随机变量与分布函数 随机变量 随机变量&#xff1a;一个随机变量是对随机现象可能的结果的一种数学抽象 分布函数 分布函数&#xff1a; X为随机变量&#xff0c; F ( x ) F(x) F(x)定义为&#xff1a; F ( x ) P ( X ≤ x ) F(x) P(X \leq x) F(x)P(X≤x) 定义域&#…

基于Python实现多功能翻译助手(下)

为了将上述步骤中的功能增强与扩展具体化为代码&#xff0c;我们将实现翻译历史记录功能、翻译选项配置以及UI的改进。 翻译历史记录功能 import json # 假设有一个用于存储历史记录的json文件 HISTORY_FILE translation_history.json # 初始化历史记录列表 translati…

OpenHarmony实战开发-List组件的使用之设置项

介绍 在本篇CodeLab中&#xff0c;我们将使用List组件、Toggle组件以及Router接口&#xff0c;实现一个简单的设置页&#xff0c;点击将跳转到对应的详细设置页面。效果图如下&#xff1a; 相关概念 CustomDialog&#xff1a;CustomDialog装饰器用于装饰自定义弹窗。List&…

C++从入门到精通——命名空间

命名空间 前言一、命名空间引例什么是命名空间 二、命名空间定义正常的命名空间定义嵌套的命名空间多个相同名称的命名空间 三、命名空间使用加命名空间名称及作用域限定符使用using将命名空间中某个成员引入使用using namespace 命名空间名称引用引用命名空间和引用头文件有什…

Unity PS5开发 天坑篇 之 URP管线与HDRP管线部署流程以及出包介绍04

目录 一, URP管线、HDRP管线下的Unity项目部署 1. PS5开发论坛关于Unity可支持的版本说明: 2. URP管线下的项目与部署 2.1 Build PS5 URP Project 2.2 运行画面 3. HDRP管线下的项目与部署 3.1 附上可以运行的画面: 4. PS5打包方式介绍 4.1 PC串流调试模式: Build Typ…

安装mysql8.0.36遇到的问题没有developer default 选项问题

安装mysql8.0.36的话没有developer default选项&#xff0c;直接选择customer就好了&#xff0c;点击next之后通过点击左边Available Products里面的号和中间一列的右箭头添加要安装的产品&#xff0c;最后会剩下6个 安装完成后默认是启动了&#xff0c;并且在电脑注册表注册了…

【Leetcode】单链表常见题

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;Leetcode刷题 本节内容我们来讲解常见的几道单链表的题型&#xff0c;文末会赋上单链表增删查&#xff0c;初始化等代码 目录 1.移除链表元素2.链表的中间节点3.返回倒数第K个节点&#xff1a;4.环…

华为云使用指南02

5.​​使用GitLab进行团队及项目管理​​ GitLab旨在帮助团队进行项目开发协作&#xff0c;为软件开发和运营生命周期提供了一个完整的DevOps方案。GitLab功能包括&#xff1a;项目源码的管理、计划、创建、验证、集成、发布、配置、监视和保护应用程序等。该镜像基于CentOS操…

【TB作品】MSP430G2553,超声波倒车雷达PCB,单片机,超声波SR04,键盘,oled,

题目 硬件&#xff1a;MSP430G2553、 SR04超声波传感器 、3*4键盘、 无源蜂鸣器、oled显示屏 软件 1 、实时显示测量得到的距离 2、按键设置一个报警门限数值&#xff0c;直接输入数值后确认 3、低于报警门限数值就开始报警&#xff0c;而且距离越近蜂鸣器的鸣叫频率越高 程序…

【踩坑】使用CenterNet训练自己的数据时的环境配置与踩坑

环境配置 系统&#xff1a;Ubuntu22.04 Python&#xff1a;3.8 CUDA&#xff1a;11.7 pytorch&#xff1a;2.2.1 因为种种原因没有使用原工程的老版本python和pytorch……但总之也跑通了&#xff0c;可喜可贺&#xff0c;可喜可贺。 新建conda环境&#xff1a; conda create -…

JavaEE之网络初识(网络中的一些基本概念)详解

&#x1f63d;博主CSDN主页: 小源_&#x1f63d; &#x1f58b;️个人专栏: JavaEE &#x1f600;努力追逐大佬们的步伐~ 目录 1. 前言 2. 网络中的一些基本概念 2.1 IP地址 2.2 端口号 2.3 网络协议 2.4 协议分层 2.5 封装 2.6 分用 (封装的逆向过程) 2.7 客户端 vs …

JUC并发编程之常用方法

sleep() public void testSleepAndYield() {Thread t1 new Thread(() -> {try {log.debug("t1-sleep...");Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}}, "t1");log.debug("t1 start 前的状态&#…

Appium设备交互API

设备交互API指的是操作设备系统中的一些固有功能&#xff0c;而非被测程序的功能&#xff0c;例如模拟来电&#xff0c;模拟发送短信&#xff0c;设置网络&#xff0c;切换横竖屏&#xff0c;APP操作&#xff0c;打开通知栏&#xff0c;录屏等。 模拟来电 make_gsm_call(phon…