C# 结合 JS 暴改腾讯 IM SDK Demo

 

目录

关于腾讯 IM SDK Demo 

范例运行环境

设计思路

服务端生成地址

IM 服务端接收

IM 客户端程序

小结


关于腾讯 IM SDK Demo 

腾讯云即时通信 IM SDK 提供了单聊、群聊、关系链、消息漫游、群组管理、资料管理、直播弹幕等功能,并提供完备的 App 接入及管理接口。目前的下载链接请参照如下:

https://cloud.tencent.com/document/product/269/36887

我们下载的是 Windows SDK Web 版本的源码,其结构如下:

下载后感觉目录里的文件有些随意,因此围绕打包编译后的目录 dist 展开研究,运行 index.html 似乎能够出来一些效果,但实际的使用中肯定与自己的需求有出入,由于本人比较懒,仅通过跟踪终端显示呈现效果,直接暴力修改混淆代码,主要解决如下一些问题:

1、结合已有系统,通过令牌机制验证对首页登录的访问

2、成功访问登录页后生成访问用户的 UserSig ,UserSig 是用户登录即时通信 IM 的密码,其本质是对 UserID 等信息加密后得到的密文,如何生成 UserSig 请参照我的文章《C# 生成腾讯云 IM 之 TLSSigAPIv2 UserSig》

3、修改 Toast.js 的信息提示程序

4、根据判断手机微信和PC不同终端进入不同的运行环境样式

5、重写左侧分页提示消息(如我的消息、我的通讯录)

6、重写获取好友列表

7、重写左侧操作面板样式

8、重写了更新个人资料的昵称和头像功能

9、增加获取成员信息的功能

10、增加了禁言用户和解禁用户的功能

11、重写了初始化左侧好友列表、消息状态及显示的功能

12、修改了视频通话只能显示帐户名,改为可以显示昵称的功能

13、增加了视频通话云端混录的功能

14、增加了群组管理员禁言用户及获取禁言用户列表的功能

15、增加对左侧控制面板的显示配置

16、增加聊天面板的选项配置

范例运行环境

操作系统: Windows Server 2019 DataCenter

.net版本: .netFramework4.0 或以上

开发工具:VS2019  C# 

设计思路

服务端生成地址

服务端设计一个登录页面用于如客服登录或普通登录。(也可以集成在应用中直接使用Session用户帐户登录),通过建立 IM 备份帐户表,检验登录 ,表大致设计如下:

序号字段名基础类型说明
1AppUIDnvarchar应用系统可能集成的用户帐户
2Accountnvarchar腾讯IM账户
3APWDnvarchar应用系统集成的加密密码
4avatarUrlnvarchar

应用系统集成的头像地址

5nickNamenvarchar应用系统集成的昵称
6sexnvarchar应用系统集成的性别
7AppClass     nvarcharApp平台名称
8AppName      nvarchar应用分类名称
9AppSubName  nvarchar应用二类分类名称
10AppIDNnvarchar账户类型(如客服、考生、个人、企业等等)

登录通过后根据用户生成 IM 用链接,地址为 /webim/dist/index.aspx,并传递相关参数值,见下表:

序号参数类型说明
1atstring传递的即时令牌值,接收端页面检验成功后即失效,用于页面安全访问
2scenestring

场景配置参数。配置参数形式如下:{0}_{1}_{2}_{3}

{0}:表示登录帐号

{1}:表示对方帐号(比如添加好友,这里可以默认为空)

{2}:左侧控制面板配置,用6个数字连接,依次表示为显示控制列表、会话、群组、好友、黑名单、默认进入类型的对应四个图标(1234),除最后一个数字为1到4的值外,其它均为1和0,1代表显示,0代表隐藏

如110102,代表显示控制列表,显示会话,隐藏群组,显示好友、隐藏黑名单、进入第二个图标

{3}:聊天面板配置,用4个数字连接,依次表示发送图片、视频、文件、视频通话。

如1110,则表示关闭视频通话功能,其它图标都显示

综上所述,生成的拼接地址如下示例:

/webim/dist/index.aspx?at=令牌值&scene=user1_user2_110102_1110

IM 服务端接收

IM 服务端接收,只要实现令牌值的合法校验,即是否可以访问本页,成功后进行客户端用的参数赋值,并生成 UserSig,示例代码如下:

<%@ Page Language="C#"  ResponseEncoding="utf-8"  ValidateRequest="false" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %><%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Web" %>
<%@ Import Namespace="System.Web.UI" %>
<%@ Import Namespace="System.Web.UI.WebControls" %><%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.Web.Services"%>
<%@ Import Namespace="System.Web.Script.Services"%>
<script language="C#" runat="server">protected void Page_Load(object sender, EventArgs e){if (Page.IsPostBack == true){return;}Security.CraneOfficeCloud cc = new Security.CraneOfficeCloud();ViewState["access_token"] = cc.getToken("");ViewState["apiurl"] = System.Configuration.ConfigurationManager.AppSettings["apiurl"];ViewState["userId"] = "";ViewState["reomteUserId"] = "";ViewState["cfg_showlist"] = "0";ViewState["cfg_clist"] = "0";ViewState["cfg_glist"] = "0";ViewState["cfg_flist"] = "0";ViewState["cfg_blist"] = "0";ViewState["cfg_dlist"] = "1";ViewState["cfg_spic"] = "0";ViewState["cfg_svideo"] = "0";ViewState["cfg_sfile"] = "0";ViewState["cfg_videocall"] = "0";ViewState["userSig"] ="";string _at = (Request.QueryString["at"] == null ? "" : Request.QueryString["at"].ToString());bool validresult = cc.validImToken(_at);if (validresult == false){Response.Redirect("end.aspx");return;}string reqPara = sec.CoDecode(Request.QueryString["scene"].ToString(), "michaeln");string[] paras = reqPara.Split('_');ViewState["userId"] = paras[0];ViewState["reomteUserId"] = paras[1];string cfg = paras[2];ViewState["cfg_showlist"] = cfg.Substring(0, 1);ViewState["cfg_clist"] = cfg.Substring(1, 1);ViewState["cfg_glist"] = cfg.Substring(2, 1);ViewState["cfg_flist"] = cfg.Substring(3, 1);ViewState["cfg_blist"] = cfg.Substring(4, 1);ViewState["cfg_dlist"] = cfg.Substring(5, 1);string cfg2 = paras[3];ViewState["cfg_spic"] = cfg2.Substring(0, 1);ViewState["cfg_svideo"] = cfg2.Substring(1, 1);ViewState["cfg_sfile"] = cfg2.Substring(2, 1);ViewState["cfg_videocall"] = cfg2.Substring(3, 1);TLSSigAPIv2 sig = new TLSSigAPIv2(1400,"6b7ec2a8fd");string _sig = sig.GenSig(ViewState["userId"].ToString());ViewState["userSig"] = _sig;}
</script>

IM 客户端程序

客户端程序主要用于接收服务端生成的参数,并通过 JS 外围控制与改变 IM SDK 的核心JS,客户端的示例代码如下:

<html>
<head>
<meta charset="utf-8"/><meta name="renderer" content="webkit"/><meta name="force-rendering" content="webkit"/><meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"/>
<title>craneoffice TIM</title>
<style type="text/css">.fbbtn{cursor:pointer;background-color:White;color:Gray;width:100px;-webkit-box-shadow:0 5px 10px 0 rgba(0,0,0,.5);box-shadow:0 5px 10px 0 rgba(0,0,0,.5);border-style:solid;border-width:1px;    }.fbbtn2{cursor:pointer;background-color:White;width:100px;color:Gray;-webkit-box-shadow:0 5px 10px 0 rgba(0,0,0,.5);box-shadow:0 5px 10px 0 rgba(0,0,0,.5);border-style:solid;border-width:1px;    }.fblist{width:120px;font-size:9pt;font-family:微软雅黑;}.rfbtn{width:35px;font-size:9pt;font-family:微软雅黑;}.friend-list-container{margin-top:80px;margin-left:10px;}.friend-item-container{cursor:pointer;margin-top:10px;}.friend-name{margin-top:10px;margin-left:0px;color:White;}
</style>
<script language="javascript" type="text/javascript">var app_apiurl = '<%=ViewState["apiurl"].ToString()%>';var app_at = '<%=ViewState["access_token"].ToString()%>';var app_userId = '<%=ViewState["userId"].ToString()%>';var app_remote_userId = '<%=ViewState["reomteUserId"].ToString()%>';var app_showlist = '<%=ViewState["cfg_showlist"].ToString()%>';var app_clist = '<%=ViewState["cfg_clist"].ToString()%>';var app_glist = '<%=ViewState["cfg_glist"].ToString()%>';var app_flist = '<%=ViewState["cfg_flist"].ToString()%>';var app_blist = '<%=ViewState["cfg_blist"].ToString()%>';var app_dlist = '<%=ViewState["cfg_dlist"].ToString()%>';var app_sig = '<%=ViewState["userSig"].ToString()%>';var app_spic = '<%=ViewState["cfg_spic"].ToString()%>';var app_svideo = '<%=ViewState["cfg_svideo"].ToString()%>';var app_sfile = '<%=ViewState["cfg_sfile"].ToString()%>';var app_videocall = '<%=ViewState["cfg_videocall"].ToString()%>';var app_roomid = '';var app_groupid = '';var app_groupMsgUserId = '';var app_groupMsgUserRole = '';var app_frameId = window.frameElement && window.frameElement.id || '';var app_e = null;var app_nickname = "";var app_faceurl = "";if (window.parent != null) {app_nickname=(window.parent.document.getElementById('imnickname').value);app_faceurl=(window.parent.document.getElementById('imfaceurl').value);}
</script>
<link rel="icon" href="favicon.ico" type="image/x-icon" />
<link href="css/chunk-vendors.c7922a7e.css?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>" rel="stylesheet" />
<link href="css/app.16310f51.css?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>" rel="Stylesheet" />
<link rel="stylesheet" href="css/toastify.min.css" /></head><body>
<div id="app"></div>
<script src="js/toastify.js"></script>
<script src="./debug/GenerateTestUserSig.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="./debug/lib-generate-test-usersig.min.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="js/chunk-vendors.f90981cb.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="js/app.430352d1.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="js/jquery-3.2.1.min.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="js/utils.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script><asp:Label ID="inittip" runat="server" Width="300px" Height="70px" Text="<br>正在配置请稍候..." style="text-align:center; display:none;position:absolute;left:100px;top:100px;-webkit-box-shadow:0 5px 10px 0 rgba(0,0,0,.9);box-shadow:0 5px 10px 0 rgba(0,0,0,.9)" ForeColor="white" ></asp:Label>
<asp:Label ID="exTitle" runat="server" Text="" style="position:absolute;left:100px;top:20px;" ForeColor="#a5b5c1" ></asp:Label><input type="button"  ID="rfbtn" runat="server" style="display:none"   onclick="getGroupShuttedList()" value="刷新" class="rfbtn" />
<select id="shlist" class="fblist" onchange="muteRefUser(this.value)" style="display:none"></select>
<input type="button"  ID="Button1" runat="server" style="display:none"   onclick="changeArea(1)" value="刷新" class="rfbtn" />
<input type="button"  ID="Button2" runat="server" style="display:none"   onclick="changeArea(2)" value="刷新" class="rfbtn" /></body>
</html>
<script  language="javascript" type="text/javascript">var app_groupmemberlist=null;function is_weixin(){var ua = navigator.userAgent.toLowerCase();  if(ua.match(/MicroMessenger/i)=="micromessenger") {  return true;  } else {  return false;  }  } var vtitle='';if(is_weixin()==true){vtitle='IM 微信版';document.getElementById('exTitle').style.display=vtitle;}else{vtitle='IM PC版';document.getElementById('exTitle').style.display=vtitle;}Toast.info('正在配置启动 CO '+vtitle+',请稍候...');function getmemberlist(){var promise = tim.getGroupMemberList({ groupID: app_groupid, count: 30, offset:0 }); // 从0开始拉取30个群成员promise.then(function(imResponse) {alert(JSON.stringify(imResponse.data.memberList)); // 群成员列表}).catch(function(imError) {alert(imError);});}
async function test() {await sleep(10000);
}function sleep(ms) {return new Promise(resolve => setTimeout(resolve, ms));
}
function setTitleEx(etype){var title='';if(etype==1){title='我的消息';}else  if(etype==2){title='我的通讯录';}document.getElementById('exTitle').innerHTML=title;
}app_gfl=new Array();function gfl(){var promise =tim.getFriendList();promise.then(function(imResponse) {for(var i=0;i<imResponse.data.length;i++){app_gfl.push(imResponse.data[i]);}}).catch(function(imError) {Toast.error(imError);});}function handleFriendClickEx(e){e.querySelector('.friend-name').click();}function changeArea(paneltype){var ol=30;if(is_weixin()==true){document.getElementById('exTitle').style.display='none';}if(paneltype==1){if(is_weixin()==true){document.querySelector(".bar-right").style.display = 'none';document.querySelector(".current-conversation-wrapper").style.display='';document.querySelector(".current-conversation-wrapper").style.width = (window.frameElement.offsetWidth-ol)+'px';document.querySelector(".current-conversation-wrapper").style.position = 'absolute';document.querySelector(".current-conversation-wrapper").style.left = ol+'px';}}else if(paneltype==2){document.getElementById('exTitle').style.display='';if(is_weixin()==true){document.querySelector(".current-conversation-wrapper").style.display='none';document.querySelector(".bar-right").style.display = '';document.querySelector(".bar-right").style.position = 'absolute';document.querySelector(".bar-right").style.left = ol+'px';document.querySelector(".bar-right").style.width = (window.frameElement.offsetWidth-ol)+'px';}}}function updateProfile(){if(app_nickname==""||app_faceurl==""){return;}let promise = tim.updateMyProfile({nick: app_nickname,avatar: app_faceurl});promise.then(function(imResponse) {}).catch(function(imError) {alert('updateMyProfile error:'+ imError); // 更新资料失败的相关信息});}function getNick(userid){for(var i=0;i<app_gfl.length;i++){if(app_gfl[i].profile.userID==userid){return app_gfl[i].profile.nick;}}return userid;}function getNick2(userid){let promise = tim.getUserProfile({userIDList: [userid] // 请注意:即使只拉取一个用户的资料,也需要用数组类型,例如:userIDList: ['user1']});promise.then(function(imResponse) {app_e=imResponse.data[0].nick;if(imResponse.data[0].nick!=undefined){return imResponse.data[0].nick;}}).catch(function(imError) {return userid; // 获取其他用户资料失败的相关信息});        var e=app_e;alert(e.$store);e.$store.dispatch("checkoutConversation","CC20210506102216154");}function getmemberinfo(){Toast.info('信息提取中,如某些选项未显示请重新点击再试...');if(app_groupMsgUserId==app_userId){app_groupMsgUserRole='';Toast.notify('提取用户信息完成');return;}var promise = tim.getGroupMemberProfile({groupID: app_groupid,userIDList: [app_userId]});promise.then(function(imResponse) {if(imResponse.data.memberList.length>0){var ml=imResponse.data.memberList[0];app_groupMsgUserRole=ml.role;Toast.notify('提取用户信息完成。');}}).catch(function(imError) {Toast.error(imError);});}function reposx(x){if(x+230+100>$(window).width()){x=$(window).width()-230-100;}return x;}function reposy(y){if(y+271+70>$(window).height()){y=$(window).height()-271-70;}return y;}function muteRefUser(userid){if(userid=='') return;if(confirm('是否解禁用户'+userid)==false){return;}app_groupMsgUserId=userid;muteUser(0);}function muteUser(seconds) {var promise = tim.setGroupMemberMuteTime({groupID: app_groupid,userID: app_groupMsgUserId,muteTime: seconds // 禁言10分钟;设为0,则表示取消禁言});promise.then(function(imResponse) {var tip=(seconds==0?"已取消禁言该用户":'用户'+app_groupMsgUserId+'已被禁言'+timetip(seconds));Toast.notify(tip);rfbtn.click();}).catch(function(imError) {Toast.error(imError);});}function timetip(off) {var x=parseInt(off/3600,10);var htip=x==0?"":x+'小时';off=off-x*3600;var z = parseInt(off / 60, 10);var y = off % 60;var mtip='';var stip='';if(z==0&&y!=0){stip=y+'秒';} else if (z != 0 && y == 0) {mtip = z +'分钟';} else if (z != 0 && y != 0) {mtip = z + '分';stip = y + '秒';}  return htip+mtip+stip;}function onl() {if (app_showlist == 1) {}window.setTimeout(async function () {document.getElementById('inittip').style.display = 'none';var f = false;var fi = 0;for (var i = 0; i < document.getElementsByTagName('div').length; i++) {if (document.getElementsByTagName('div')[i].getAttribute('class') == 'side-bar-wrapper') {
//                                        document.getElementsByTagName('div')[i].style.width = window.frameElement.offsetWidth+'px';}if (document.getElementsByTagName('div')[i].getAttribute('class') == 'bar-right') {
//                                        document.getElementsByTagName('div')[i].style.display = 'none';}if (document.getElementsByTagName('div')[i].getAttribute('class') == 'bar-left') {//                    document.getElementsByTagName('div')[i].style.display = 'none';}if (document.getElementsByTagName('div')[i].getAttribute('class') == 'current-conversation-wrapper' && app_showlist == 0) {if (app_frameId != "") {document.getElementsByTagName('div')[i].style.width = (window.frameElement.offsetWidth - 44) + 'px';document.getElementsByTagName('div')[i].style.height = '99vh';document.getElementsByTagName('div')[i].style.left = '31px';document.getElementsByTagName('div')[i].style.top = '0px';document.getElementsByTagName('div')[i].style.position = 'absolute';}}if (document.getElementsByTagName('div')[i].getAttribute('class') == 'content') {//                    alert(document.getElementsByTagName('div')[i].innerHTML);//                    document.getElementsByTagName('div')[i].style.width = window.frameElement.offsetWidth + 'px';//                    document.getElementsByTagName('div')[i].style.height = window.frameElement.offsetHeight + 'px';//                    document.getElementsByTagName('div')[i].style.position = 'absolute';}// group - listif (document.getElementsByTagName('div')[i].getAttribute('id') == 'group-list' && app_dlist == 2) {document.getElementsByTagName('div')[i].click();}if (document.getElementsByTagName('div')[i].getAttribute('class') == 'header-bar') {if (document.getElementsByTagName('div')[i].innerHTML.indexOf('创建群组') != -1) {document.getElementsByTagName('div')[i].innerHTML = '';shlist.style.display='none';rfbtn.style.display='none';document.getElementsByTagName('div')[i].appendChild(shlist);document.getElementsByTagName('div')[i].appendChild(rfbtn);}}if (document.getElementsByTagName('div')[i].getAttribute('class') == 'conversation-item-container' && app_dlist == 1) {f = true;fi = i;//                    break;}if (document.getElementsByTagName('div')[i].getAttribute('class') == 'group-item' && app_dlist == 2) {f = true;fi = i;//                    break;}}if (f == true) {document.getElementsByTagName('div')[fi].click();if(app_dlist==2){await sleep(1500);getmemberinfo();await sleep(1500);if(app_groupMsgUserRole=='Owner'||app_groupMsgUserRole=='Admin'){rfbtn.click();shlist.style.display='';rfbtn.style.display='';}}}updateProfile();document.getElementById('friend-list').click();await sleep(1000);gfl();document.getElementById('conversation-list').click();}, 3000);}function iconClick() {setTitleEx(1);window.setTimeout(async function () {var f = false;var fi = 0;for (var i = 0; i < document.getElementsByTagName('div').length; i++) {if (document.getElementsByTagName('div')[i].getAttribute('class') == 'conversation-item-container' ) {f = true;fi = i;break;}}if (f == true&&is_weixin()==false){document.getElementsByTagName('div')[fi].click();}window.parent.layer.closeAll();}, 1000);}window.onload = function () {if (document.getElementsByTagName('button').length == 1) {document.getElementsByTagName('button')[0].click();}}function setonline(_user1, _user2) {$.ajax({type: "Post",url: app_apiurl,contentType: "application/x-www-form-urlencoded;charset=utf-8",data: {gettype: 'getRoomIdForMixRecord',at: app_at,user1: encodeURIComponent(_user1),user2: encodeURIComponent(_user2)},dataType: "json",success: function (res) {//JSON.stringifyalert(res.roomid);if (res.roomid != "") {app_roomid = res.roomid;requestMixRecord("request", "turing", app_roomid, "ARP120102197701243273", "ARI20200401");}},error: function (err) {alert(JSON.stringify(err));}});}function requestMixRecord(_mixtype, _companyName, _roomid, _userid1, _userid2) {$.ajax({type: "Post",url: app_apiurl,contentType: "application/x-www-form-urlencoded;charset=utf-8",data: {gettype: 'MixRecord',at: app_at,mixtype: encodeURIComponent(_mixtype),companyName: encodeURIComponent(_companyName),roomid: encodeURIComponent(_roomid),userid1: encodeURIComponent(_userid1),userid2: encodeURIComponent(_userid2)},dataType: "json",success: function (res) {//返回的数据用data.d获取内容   if (res.code == '0') {//                    Toast.notify(_mixtype + ' record ok');} else {//                    Toast.notify(' record '+res.code);}
//               alert(JSON.stringify(res));},error: function (err) {Toast.error(err);}});} //mixrecordfunction delGroupMsg() {$.ajax({type: "Post",url: app_apiurl,contentType: "application/x-www-form-urlencoded;charset=utf-8",data: {gettype: 'im_deleteGroupMsg',at: app_at,groupid: encodeURIComponent(app_groupid),account: encodeURIComponent(app_groupMsgUserId)},dataType: "json",success: function (res) {//返回的数据用data.d获取内容   
//               alert(JSON.stringify(res));if(res.ErrorCode=='0'){Toast.notify('删除消息成功,缓存的消息可能还会显示。');}else{Toast.error('删除消息失败。');}},error: function (err) {Toast.error(JSON.stringify(err));}});} //mixrecordfunction getGroupShuttedList() {$.ajax({type: "Post",url: app_apiurl,contentType: "application/x-www-form-urlencoded;charset=utf-8",data: {gettype: 'im_getGroupShuttedList',at: app_at,groupid: encodeURIComponent(app_groupid)},dataType: "json",success: function (res) {if(res.ErrorCode=='0'){if(res.ShuttedUinList.length>0){Toast.notify('获取禁言列表成功,共'+res.ShuttedUinList.length+'个用户');shlist.length=0;shlist.options.add(new Option('选择取消禁言用户',''));for(var i=0;i<res.ShuttedUinList.length;i++){var userid=res.ShuttedUinList[i].Member_Account;shlist.options.add(new Option(userid,userid));}}else{shlist.length=0;shlist.options.add(new Option('没有被禁言的用户',''));}}else{
//                  Toast.error('获取禁言列表失败。');}},error: function (err) {alert('error'+JSON.stringify(err));//                Toast.notify(_mixtype + ' record fail');}});} //mixrecord</script>

小结

暴改的腾讯 IM SDK Demo 请下载我的资源:

https://download.csdn.net/download/michaelline/89356543

本文代码代码示例仅供您参考使用,示例中使用到了视频通话的云端混录功能,有关云端混录功能请参考我的文章《C# 实现腾讯云多路直播流的云端混合录制》,请根据实际的应用取舍,另外一些 WebAPI 如设置用户在线状态、群组管理,也可根据实际需要进行修改。

感谢您的阅读,希望本文能够对您有所帮助。

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

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

相关文章

小猪APP分发:一站式托管服务,轻松玩转应用市场

在当今移动应用爆炸式增长的时代&#xff0c;开发者们面临的挑战不再仅限于创意的火花和代码的实现&#xff0c;更在于如何让精心打造的应用快速触达广大用户。这正是小猪APP分发www.appzhu.net应运而生的背景——作为一个全面、高效的APP托管服务分发平台&#xff0c;它为开发…

用于时间序列概率预测的蒙特卡洛模拟

大家好&#xff0c;蒙特卡洛模拟是一种广泛应用于各个领域的计算技术&#xff0c;它通过从概率分布中随机抽取大量样本&#xff0c;并对结果进行统计分析&#xff0c;从而模拟复杂系统的行为。这种技术具有很强的适用性&#xff0c;在金融建模、工程设计、物理模拟、运筹优化以…

F.费用报销【蓝桥杯】/01背包

费用报销 01背包 思路&#xff1a;f[i][j]表示前i个票据在容量为j的背包中能占的最大值。 #include<iostream> #include<algorithm> using namespace std; int day[13]{0,31,28,31,30,31,30,31,31,30,31,30,31}; int dp[1005][5005]; int s[13]; int last[1005];…

Obsidian Git 多端同步

2023年6月&#xff0c;某云笔记限制了免费用户最多同时登录 2 台设备&#xff0c;想要增加设备数量需要付费开通会员。之后我一直想找一款合适的笔记本软件&#xff0c;年底尝试了Obsidian&#xff0c;断断续续摸索了好几天终于成功了。将那时的笔记拿来分享一下。 相关地址&am…

Golang单元测试

文章目录 传统测试方法基本介绍主要缺点 单元测试基本介绍测试函数基准测试示例函数 传统测试方法 基本介绍 基本介绍 代码测试是软件开发中的一项重要实践&#xff0c;用于验证代码的正确性、可靠性和预期行为。通过代码测试&#xff0c;开发者可以发现和修复潜在的错误、确保…

Elasticsearch集群搭建学习

Elasticsearch集群聚合、集群搭建 RestClient查询所有高亮算分控制 数据聚合DSL实现Bucket聚合DSL实现Metrics聚合RestAPI实现聚合 拼音分词器如何使用拼音分词器&#xff1f;如何自定义分词器&#xff1f;拼音分词器注意事项&#xff1f; 自动补全数据同步集群搭建ES集群结构创…

HarmonyOS鸿蒙应用开发——ArkTS的“内置组件 + 样式 + 循环和条件渲染”

一、内置组件是咩&#xff1f; 学过前端的都知道&#xff0c;一个组件就是由多个组件组成的&#xff0c;一个组件也可以是多个小组件组成的&#xff0c;组件就是一些什么导航栏、底部、按钮......啥的&#xff0c;但是组件分为【自定义组件】跟【内置组件】 【自定义组件】就…

java继承使用细节二

构造器 主类是无参构造器时会默认调用 public graduate() {// TODO Auto-generated constructor stub也就是说我这里要用构造器会直接调用父类。它是默认看不到的 &#xff0c;System.out.println("graduate");} 但当主类是有参构造器如 public father_(int s,doubl…

K8S集群中Yaml文件详解

目录 一、Yaml概述 二、Yaml基本语法 三、Yaml数据结构 四、K8S资源清单描述方法 五、api资源版本标签 六、Yaml文件示例详解 1.deployment.yaml文件详解 2.Pod yaml文件详解 3.Service yaml文件详解 七、Yaml文件相关操作 1.试运行 2.生成yaml格式 3.生成json格式…

超大Sql文件切分工具SQLDumpSplitter —— 筑梦之路

官网&#xff1a;PLB PLB - SQLSplitter 用于将大型MySQL转储拆分为可独立执行的小型SQL文件。 显示100%时并不是已经处理完了&#xff0c;而是才开始 优点 软件程序小巧&#xff0c;不需要安装&#xff0c;直接点击运行就可以最厉害的是SQLDumpSplitter可以自动将结构语句&…

JVM学习-执行引擎

执行引擎 执行引擎是Java虚拟机核心组成部分之一虚拟机是一个相对于物理机的概念&#xff0c;这两种机器都有代码执行能力&#xff0c;其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统层面上的&#xff0c;而虚拟机的执行引擎是由软件自行实现的&#xf…

近临算法(个人总结版)

背景 近邻算法&#xff08;Nearest Neighbor Algorithm&#xff09;是一种基本但非常有效的分类和回归方法。最早由Fix和Hodges在1951年提出&#xff0c;经过几十年的发展和改进&#xff0c;已成为数据挖掘、模式识别和机器学习领域的重要工具。近邻算法基于相似性原则&#x…

vue源码2

vue之mustache库的机理其实是将模板字符串转化为tokens 然后再将 tokens 转化为 dom字符串&#xff0c;如下图 对于一般的将模板字符串转化为dom字符串&#xff0c;这样不能实现复杂的功能 let data {name:小王,age:18 } let templateStr <h1>我叫{{name}},我今年{{ag…

git分支常用命令

最近在用git提交代码的时候&#xff0c;发现有些命令不是很会&#xff0c;先记录几个常用分支命令&#xff0c;后续再补充&#xff0c;在执行git push命令提交代码的时候遇到报错&#xff0c;一并记录下。 1.git常用命令 新建分支&#xff1a; git branch <分支名称> 比…

2025第十届美陈展

展位又遭疯抢&#xff01;2025第十届美陈展释放“无界之美” 美是全球通用的语言&#xff0c;人类对美的追求始终如一&#xff0c;大众审美在经历了时代的变迁后开始趋同&#xff0c;东方文明深处的美学经济开始崛起。 在如今商业迈入存量阶段&#xff0c;以品牌为突破口打造…

Ai自动贴图直播项目的趋势,智享自动直播GMV增加工具

在当今社会&#xff0c;直播行业正在悄然地改变着人们的生活方式。无论是在闲暇时光中放松身心&#xff0c;还是在临睡前享受休闲娱乐&#xff0c;观众们越来越习惯于通过刷短视频或者观看直播来消遣自己。根据统计数据显示&#xff0c;到2023年全球将有超过10.74亿网民&#x…

前端日志收集(monitor-report v1)

为什么 为什么自己封装而不是使用三方 类似 Sentry 这种比较全面的 因为 Sentry 很大我没安装成功&#xff0c;所有才自己去封装的 为什么使用 可以帮助你简单解决前端收集错误日志、收集当前页面访问量&#xff0c;网站日活跃&#xff0c;页面访问次数&#xff0c;用户行…

海外仓储管理系统:提升效率,标准化海外仓管理,科技赋能业务

海外仓作为跨境物流的关键一环&#xff0c;完全可以说海外仓的效率直接决定了后续物流的整体运作效率。 对于海外仓而言&#xff0c;一套高效&#xff0c;易用的海外仓储系统&#xff0c;无疑将成为提升企业竞争力的重要工具&#xff0c;帮助海外仓实现从野蛮生长到标准化管理…

pytorch-13_2 模型结构选择策略:层数、激活函数、神经元个数

一、拟合度概念 在所有的模型优化问题中&#xff0c;最基础的也是最核心的问题&#xff0c;就是关于模型拟合程度的探讨与优化。根据此前的讨论&#xff0c;模型如果能很好的捕捉总体规律&#xff0c;就能够有较好的未知数据的预测效果。但限制模型捕捉总体规律的原因主要有两点…

02_前端三大件HTML

文章目录 HTML用于网页结构搭建1. 标签2. 客户端服务器交互流程3. 专业词汇4. html语法细节5. 安装VSCODE安装插件6. Live Server插件使用7. 标题&段落&换行&列表8. 超链接标签使用9. 图片10. 表格的写法11. 表单标签*(重点)12. 下拉框13. 页面布局标签14. 块元素和…