11月
30
数组
sort() 方法对数组的项目进行排序。
排序顺序可以是按字母或数字,也可以是升序(向上)或降序(向下)。
默认情况下,sort() 方法将按字母和升序将值作为字符串进行排序。
如:
let fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();
# 输出 ['Apple', 'Banana', 'Mango', 'Orange']
fruits.reverse();
# 输出 ['Orange', 'Mango', 'Banana', 'Apple']
不过基于数字的排序,是按字符串来排序的。比如 33 排序比 123 要后。 如果非要基于数字大小来排。可以通过传入函数的方式来解决。
比如:
let arr = [1, 123, 22,5, 32];
arr.sort((a,b)=>(a-b));
# 输出 1, 5, 22, 32, 123
# 这样就可以基于数字来排序了
如果是基于数组里的 object ,也可以通过这种方式来排序。
Object 呢
对 object 按键值排序,一般在做加密验证的时候会用到。
有了数组的排序,object 也一样可以。
let param = {
name: 'vini123',
gender: 1,
time: 1669796346
}
let sorted = {};
Object.keys(param).sort().forEach(key => {
sorted[key] = param[key];
});
11月
21
uniapp 打包 app 时,默认安全区域的颜色是白色。如果页面和安全区域接触的区域不是白色,就会出现色差,这个时候体验就真心不好啊。不过,可以设置去搞掉。
我也是在做聊天功能时才碰触到颜色的问题。
https://uniapp.dcloud.net.cn/collocation/manifest-app.html#full-manifest
在文档中,找到 safearea 配置,复制过去在 manifest.json 找到 app-plus 添加进去去配置。
"safearea": {
"bottom": {
"offset": "none"
}
},
可以这样设置。
参考
https://blog.csdn.net/CSDN877425287/article/details/107484287
11月
19
时间,日期相关的处理, carbon 的确是个好东西。感觉离不开呀。
Carbon 是对 PHP DateTime 模块的二次扩展;提供时间格式化,时间计算的功能;
官方主页:http://carbon.nesbot.com/;
github: https://github.com/briannesbitt/Carbon
参考
https://www.jianshu.com/p/7e45bc4d0006
https://www.php.cn/phpkj/laravel/484191.html
https://learnku.com/articles/62292
11月
19
在微信环境,通过分享方式(非用户搜索,非小程序盒子), 能打开目标小程序,进入目标页面的方式。除了扫小程序码还有小程序链接方式。生成小程序性链接的能力有各种控制,链接的作用和生命也各有控制。做一个体验好,效果好的分享,得细心和用心。还得处处找一切能突破微信自己的阻碍。
主要是小程序分享到朋友圈从来就没一个好的体验。可以通过海报的方式,但用户得长按海报。不是所有人都知道要长按,也不是所有人都愿意长按。其他途径,比如小程序链接。虽然用户可以点击进入,但每次都弹个窗让用户确认。从体验感来说是不好,从用户意愿度(广告)来讲,算是一次告知。可是,既然用户愿意点了,意愿度还是有的,何必弹个窗来恶心人呢。每个人都有每个人的考虑,人在屋檐下,不得不低头。
https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/url-scheme/queryScheme.html
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/url-scheme.html
开始
看了下边的各种说明,只想说在微信内,打开小程序的途径 scheme 码和 urllink 都不好。这种码 A 打开了,其他人就打不开了。怎么发朋友圈宣传。短链接看起来是最好的,可短链接不是谁都有权限生成的,只有特殊服务类目才可以。就像获取用户当前位置一样,需要特殊服务目录(这个还得去申请接口权限)才有资格用。说来说去,微信内朋友圈宣传只能短链接或海报了。只能去争取申请能获取该接口的服务了。
微信外打开小程序 scheme 码 ios 是直接可以,android 需要借助 h5。 urllink 必须都得先跳转到 h5。只是跳转到 h5,然后再跳转到小程序。不必在 h5 那边再点击再跳转。就是 scheme 码和 urllink 只能一个人打开就有点恶心。
其实还有一种方式,是可以的。就是使用微信开放标签。需要借助服务号(个人可以借助云开发的静态网站),需要额外调用 js。请看下边的链接。
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_Open_Tag.html#%E5%BC%80%E6%94%BE%E6%A0%87%E7%AD%BE%E8%AF%B4%E6%98%8E%E6%96%87%E6%A1%A3
https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/staticstorage/introduction.html
scheme 码
该接口用于获取小程序 scheme 码,适用于短信、邮件、外部网页、微信内等拉起小程序的业务场景。通过该接口,可以选择生成到期失效和永久有效的小程序码,有数量限制,目前仅针对国内非个人主体的小程序开放
# 重点说明
自 2022 年 4 月 11 日起,URL Scheme有效期最长 30 天,不再支持永久有效的URL Scheme、不再区分短期有效URL Scheme与长期有效URL Scheme。若在微信外打开,用户可以在浏览器页面点击进入小程序。每个独立的URL Scheme被用户访问后,仅此用户可以再次访问并打开对应小程序,其他用户无法再次通过相同URL Scheme打开该小程序。 在本次规则调整生效前已经生成的URL Scheme,如果有效期超过30天或长期会被降级为30天有效,只能被1个用户访问,开始时间从调整日期开始计算。
每天生成 URL Scheme 和 URL Link 总数量上限为50万
iOS系统支持识别 URL Scheme,可在短信等应用场景中直接通过 Scheme 跳转小程序。
Android系统不支持直接识别 URL Scheme,用户无法通过 Scheme 正常打开小程序,开发者需要使用 H5 页面中转,再跳转到 Scheme 实现打开小程序
urllink
获取小程序 URL Link,适用于短信、邮件、网页、微信内等拉起小程序的业务场景。通过该接口,可以选择生成到期失效和永久有效的小程序链接,有数量限制,目前仅针对国内非个人主体的小程序开放
# 重点说明
自 2022 年 4 月 11 日起,URL Link有效期最长 30 天,不再支持永久有效的URL Link、不再区分短期有效URL Link与长期有效URL Link。若在微信外打开,用户可以在浏览器页面点击进入小程序。每个独立的URL Link被用户访问后,仅此用户可以再次访问并打开对应小程序,其他用户无法再次通过相同URL Link打开该小程序。 在本次规则调整生效前已经生成的URL Link,如果有效期超过30天或长期会被降级为30天有效,只能被1个用户访问,开始时间从调整日期开始计算。
每天生成 URL Scheme 和 URL Link 总数量上限为50万
只能生成已发布的小程序的 URL Link。
在微信内或者安卓手机打开 URL Link 时,默认会先跳转官方 H5 中间页,如果需要定制 H5 内容,可以使用云开发静态网站。
short link
获取小程序 Short Link,适用于微信内拉起小程序的业务场景。目前只开放给电商类目(具体包含以下一级类目:电商平台、商家自营、跨境电商)。通过该接口,可以选择生成到期失效和永久有效的小程序短链
通过服务端接口可以获取打开小程序任意页面的 Short Link。适用于微信内拉起小程序的业务场景。
目前只开放给电商类目小程序,具体包含以下一级类目:电商平台、商家自营、跨境电商。
最终
说了好多啰嗦的话。微信内推广,宣传,短链接肯定是最好用的。可得去申请服务类目。官方说只对电商开放。不过,看到其他非电商类目的也可以(比如招聘)。
11月
15
11月
11
只要 websocket 服务。最简单化的 websocket 服务。不需要其他基于 swoole 的其他框架应用。仅仅 swoole 扩展 + php + nginx 完成 websocket 的服务。就是想最简单简洁的实现。
就像官方的实例一样 https://wiki.swoole.com/#/start/start_ws_server,就这么些代码。
$ws = new Swoole\WebSocket\Server('0.0.0.0', 9502);
//监听WebSocket连接打开事件
$ws->on('Open', function ($ws, $request) {
$ws->push($request->fd, "hello, welcome\n");
});
//监听WebSocket消息事件
$ws->on('Message', function ($ws, $frame) {
echo "Message: {$frame->data}\n";
$ws->push($frame->fd, "server: {$frame->data}");
});
//监听WebSocket连接关闭事件
$ws->on('Close', function ($ws, $fd) {
echo "client-{$fd} is closed\n";
});
$ws->start();
我们不喜欢用 ip 来连接,我们用域名。我们不喜欢用 http,我们用 https。我们不喜欢加端口号,我们用代理。这里我们用 nginx 来搞定。比如吧,我们自己的域名是: xx.com, nginx 就可以像下边这样配置:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server
{
listen 443 ssl http2;
server_name xx.com;
ssl_certificate /usr/local/server/nginx/conf/ssl/xx.com.pem;
ssl_certificate_key /usr/local/server/nginx/conf/ssl/xx.com.key;
charset utf-8;
index index.php index.html index.htm;
root /www/xx/xx.com/public;
location /wss {
# 代理到上边的自定义的地址
proxy_pass http://127.0.0.1:9502;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php($|/) {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
服务端的配置构建的重要部分就算好了。需要注意的是,创建 websocket 的时候,一定不要带上 ssl 相关的参数和证书。这样你 nginx 这边请求代理过去是 http 请求,就会出错。
websocket 这里没有心跳功能,可以手动模拟创建一个,去实现类似的业务。
还有,在服务端可以使用 swoole 自己的存储结构。 https://wiki.swoole.com/#/memory/table
旧的文章
https://blog.vini123.com/405
https://blog.vini123.com/482
https://blog.vini123.com/294
11月
10
要实现 app 内版本更新得走以下几个流程:
- 对系统的获取(android 或 ios)。
-
对系统当前 app 版本的获取(1.0.1 + '.' + 100)(版本名称 + 版本号控制)。
-
对服务端接口请求 app 版本信息(定义当前最新版本号)。比如 app 之前的版本是 1.0.1.100,返回给前端就是这个。后来你新提交了一个版本 1.0.2.100,并审核通过了。当审核通过时,你修改后端配置,将版本号改成 1.0.2.100,这个时候返回前端就是 1.0.2.100。
-
用当前 app 版本信息和服务端版本信息进行对比。如果不一样,则表示服务端有新的版本。应弹窗提示用户进行 app 更新。(版本可以定义两个,android 和 ios 各一个,每个系统同一时间可能会不一样)。
-
弹窗提示用户是否要更新。用户点击确定。如果是 ios 系统,则跳转到商店更新(亲自测试可行)。如果是 android 系统,则下载安装包更新(没亲测过),ios 是必须要走商店,且只有一个商店,比较好弄,也正规。android 打个包就可以装,上商店也很多家都可以。说它简单是只要个正常的包就可以装,说它不简单就是商店太多,审核太麻烦,还得要软著,太心累。一般不到万不得已,根本就不想上 android 商店。
上边这个流程是在客户端做判断,并去处理升级。感觉不太好,因为客户端一旦上架你短时间内很难修改和改变。如果把判断放在服务端,你可以随时随地的修改。以备异常情况。(也是文章写着写着,想法也就变了)
运行环境管理对象(获取版本信息等能力)
官方文章
App升级中心
虽然 uniapp 官方提供了套件,但还是个人用户实现的更自由些(套件的升级 ui 界面 好像不能任意自定义)。
代码操作
一定要使用条件编译,也就是 app 才需要这样。因为有些 api 只有 app 端才有的。
// #ifdef APP-PLUS
# 从服务端获取 app 版本信息
GetAppVersion().then(res => {
// 获取当前已安装的 app 的版本信息
let curVersion = plus.runtime.version + '.' + plus.runtime.versionCode;
let osName = uni.getSystemInfoSync().platform;
if (osName == 'ios') {
if (res.ios_version && res.ios_version != curVersion) {
// 弹提示是否要更新。如果更新,就跳转到苹果应用商店
uni.showModal({
title: '更新提示',
content: '发现新版本,是否要更新?',
cancelColor: '#383838',
confirmColor: '#ffc80b',
success(res) {
if (res.confirm) {
let appleId = 6443910575;
plus.runtime.launchApplication(
{
action: `itms-apps://itunes.apple.com/cn/app/id${appleId}?mt=8`
},
function(e) {
console.log(e.message);
}
);
}
}
});
}
} else if (osName == 'android') {
if (res.android_version && res.android_version != curVersion && res.downUrl) {
// 弹窗提示是否要更新。如果更新,跳转到特定商店更新或下载更新。(弹窗省略了,去商店也省了)
var downTask = plus.downloader.createDownload(url, {}, function(d, status) {
//d为下载的文件对象
if (status == 200) {
//下载成功,d.filename是文件在保存在本地的相对路径,使用下面的API可转为平台绝对路径
var fileSaveUrl = plus.io.convertLocalFileSystemURL(d.filename);
plus.runtime.openFile(d.filename); //选择软件打开文件
uni.showToast({
icon: 'none',
title: '更新成功'
})
} else {
//下载失败
plus.downloader.clear(); //清除下载任务
uni.showToast({
icon: 'none',
title: '更新失败'
})
}
})
//开始下载
downTask.start();
//监听下载进度
downTask.addEventListener('statechanged', (task) => {
let percentage = parseInt(
(parseFloat(task.downloadedSize) /
parseFloat(task.totalSize)) *
100
);
if (percentage == 100) {
// 更新完成
}
})
}
}
});
// #endif
上边仅供参考,实际情况需调试。后一个思路,由服务端判断是否要更新,并提供更新信息(下载地址,商店地址等)这种方式比较好。还有 android 这边如果自己做下载更新,还得做个好看的 ui 升级界面。有进度条显示那种。
11月
10
看过小红书的推送的朋友肯定会觉得这种推送很有个性。能够自由定义用户的头像作为推送的通知图标。下边这个文章有说明。
https://blog.csdn.net/mazy_ma/article/details/124785158
11月
09
app 接受到推送消息后,如果用户点击消息,一般是到达目标页面。这个时候解析消息并进行处理。
unipush 消息推送
操作流程
- 当用户点击消息栏的消息时,通过 uni.onPushMessage 方法来接受消息。
- 获取接受消息里边的 payload 数据。payload 里边可以传递一些自定义的参数过来。
- 我们可以将想跳转的页面和参数定义在 page 里。并对 page 进行判断,如果 page 是 tab 页的,就做 tab 页跳转,非 tab 页就做非 tab 页跳转。
- 对消息数目角标清零
plus.runtime.setBadgeNumber(0);
。
// #ifdef APP-PLUS
let goPage = (value) => {
let tabbars = ['pages/home/index', 'pages/pdd/index', 'pages/message/index', 'pages/mine/index'];
let isTab = false;
for(let tabbar of tabbars) {
if (value.indexOf(tabbar) >= 0) {
isTab = true;
break;
}
}
if (isTab) {
uni.switchTab({
url: value
});
} else {
uni.navigateTo({
url: value
});
}
}
// 通过推送消息进来的
uni.onPushMessage((res) => {
plus.runtime.setBadgeNumber(0);
if (res && res.data && res.data.payload && res.data.payload.page) {
goPage(res.data.payload.page)
}
});
// #endif
消息推送补充
消息推送那边,我们把 page 参数 放在 payload 里。
{
"appId": "__UNI__XXXX",
"push_clientid": "6eb119fabc0123f545086eexxxxxxxx",
"title": "小区宝来电",
"content": "人生若只如初见,何事秋风悲画扇。",
"payload": { "page": "pages/home/topic/detail?id=6" }
}