MoreRSS

site iconiMaeGoo | 虹墨修改

95后前端开发者,居住郑州,擅长前端技术,分享个人学习记录。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

iMaeGoo | 虹墨的 RSS 预览

Android 14 APP 全屏代码实现

2024-11-21 21:08:00

新的 Android API 改变了应用全屏的方式,网上搜到的全屏代码都不管用了,甚至 谷歌自己的教程 都没有更新,看了 API 文档才研究明白最新代码怎么写。本篇讲述两种新的全屏方式,一种保留状态栏文字的全屏,一种隐藏状态栏的全屏。

保留状态栏,适配全面屏

默认情况下,应用界面不会延伸到系统状态栏、导航栏、导航条等区域,这会很丑,要想适配全面屏显示,在 Android 14 中,可以用一行代码简单实现。

1
2
3
// import androidx.activity.enableEdgeToEdg

enableEdgeToEdge()

隐藏状态栏,完全全屏

适配全面屏并不会隐藏系统状态栏、导航栏、导航条,如果想实现完全全屏,老办法一般是调用 setSystemUiVisibility(),然而这个方法在 14 中已经弃用了,获取 InsetsControllerViewCompat.getWindowInsetsController() 方法也被弃用了,最新的写法是:

1
2
3
4
5
6
7
8
9
// import androidx.core.view.WindowCompat
// import androidx.core.view.WindowInsetsCompat
// import androidx.core.view.WindowInsetsControllerCompat

val windowController = WindowCompat.getInsetsController(window, window.decorView)
// 应用全屏时,用户仍然可以从屏幕顶部下拉唤出状态栏,此行代码实现当用户唤出状态栏后,自动隐藏状态栏
windowController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
// 隐藏包括状态栏、导航栏、caption bar 在内的所有系统栏
windowController.hide(WindowInsetsCompat.Type.systemBars())

屠龙者终成恶龙

2024-11-14 18:00:00

赚了眼球丢了节操

前端人的 Python、Conda 环境搭建

2024-09-19 19:00:00

前言

许多 AI 相关的项目、游戏辅助工具都使用 Python 语言开发,迫使我开始接触 Python 的环境搭建。作为一个前端人,我已经对 Node.js、NVM、NPM 等工具再熟悉不过了,但搭建 Python 的过程中还是碰到了不少困难,在此记录一下,让和我一样的前端人能更快地理解 Python 的生态体系。

Python 生态

  • Python: Python 解释器和运行时环境,对应前端体系中的 Node.js,官网 www.python.org
  • Pip: Python 的包管理工具,对应前端体系中的 NPM,官网 pypi.org
  • Conda: 用于管理 Python 环境,对应前端体系中的 NVM,但又略有区别

NPM 在安装项目依赖时,会安装在项目的 node_modules 目录下,也就是局部安装,各个项目之间互相不影响,而 Pip 则是默认装在全局,这和前端的思维不一致。装在全局会造成多个项目的管理不便,各个项目之间依赖冲突、相同依赖的不同版本无法同时存在。

为了解决这个问题,Conda 就出现了,它可以创建完全隔离的多个不同的 Python 环境,每个环境可以指定不同的 Python 版本,每个环境所安装的依赖也相互隔离。

环境安装

为了搭建 Python 环境,新手往往会先想到安装 Python,但实际上 Conda 已经内置了 Python,我们 只需要安装一个 Conda,就完成环境安装了。

Conda 有三个发行的安装包,分别是 Anaconda、Miniconda、Miniforge,其中 Anaconda 最出名,它已经内置了数千个常用的科学计算依赖包,属于是开箱即用,但缺点是安装包体积达到了惊人的 912 MB。

Miniconda 就比较小巧了,它没有内置常用依赖,体积也降到了 85 MB,对于我这种需求不高的用户,显然更合适。

  1. 下载 Miniconda: https://docs.anaconda.com/miniconda/#latest-miniconda-installer-links
  2. 安装时有一步 Advanced Installation Options,建议选中 “Clear the package cache upon completion”,可以节省部分硬盘空间

修改软件源

和 NPM 一样,默认的国外软件源在国内是无法流畅使用的。我们需要在用户根目录(C:\Users\你的用户名)创建一个 .condarc 文件,输入以下内容来切换成国内源

1
2
3
4
5
6
7
8
channels:
- defaults
show_channel_urls: true
default_channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch

修改环境位置

如果你不想让以后安装的依赖占用 C 盘的空间,还需要提前修改环境位置,在上一步的 .condarc 文件中增加两行

1
2
envs_dirs:
- D:\dev\condaenvs

环境创建

在开始中搜索 “anaconda”,找到 “Anaconda Prompt (miniconda3)” 并打开,然后执行

1
conda create -n 环境名称 python=3.12 -y

替换命令中的环境名称为你定义的环境名称,替换命令中的 3.12 为你需要的 Python 版本

这样就完成环境的创建了,执行 conda env list 可以查看环境列表

环境切换

仍然是在 Anaconda Prompt 中执行

1
conda activate 环境名称

这样就切换到了对应的环境中

依赖安装

仍然是在 Anaconda Prompt 中执行

1
2
cd /d 项目目录
pip install -r requirements.txt

注意 -r 后跟项目依赖声明文件,有可能叫 requirements.txt,也有可能叫 requirements-prod.txt,之类的

安装好依赖后,就可以启动项目啦!具体如何启动可以参考项目的 README 文件。

在 bat 中切换 Conda 环境

有时候我们需要编写 bat 脚本来执行一些自动化任务(例如定时执行),这时我们会发现,由于脚本执行时没有切换到指定的 Conda 环境中,会报 Python 找不到的错误。怎样在 bat 脚本中切换 Conda 环境呢?

1
2
3
4
5
@echo off
cd /d 项目目录
call D:\dev\anaconda3\Scripts\activate.bat D:\dev\anaconda3
call conda activate 环境名称
python 项目主入口.py

替换命令中的 D:\dev\anaconda3 为你的 Conda 安装路径,替换最后一行命令为项目的启动命令

配置 PyCharm

如果你和我一样在用 PyCharm 开发工程,还需要在其中配置工程所使用的 Conda 环境

  1. 在 PyCharm 中打开工程
  2. 打开 文件-设置-项目-Python 解释器-添加解释器-添加本地解释器

  1. 选择 Conda 环境,选择 conda.exe 所在位置,然后选择刚才创建好的环境,然后确定

  1. 回到设置窗口选择刚刚添加好的解释器,大功告成

给 Parsec 设置代理,解决国内无法打开、无法登录、无法刷新的问题

2024-09-18 15:19:00

Parsec 一直是我用过的体验最好、最流畅的远程串流软件,它能实现几乎无感的远程体验,配置上也比 Sunshine + Moonlight + 内网穿透的方案要简单得多。Parsec 只需要一个软件就能实现点对点远程。同时它也是 macOS 上我用过的最好用的远程被控端。

但最近这个软件无法正常打开了,原因是国内无法访问 Parsec 的服务器。对此,我们可以寻找一台可以正常连接 Parsec 的代理服务器,这里以 127.0.0.1:7890 为例,让 Parsec 恢复正常使用。

为 Parsec 配置代理以后,Parsec 只会在启动、登录、刷新电脑列表、建立连接时使用代理服务器,实际串流仍然不经过代理服务器,而是使用点对点连接,所以不用担心代理服务器对串流性能造成影响!

  1. 打开 Parsec 的配置文件

如果是 Windows,配置文件可能在以下两个位置其中之一,按 Win + R 输入位置以后确定,找得到哪个就改哪个:

  1. %APPDATA%\Parse\config.json
  2. C:\ProgramData\Parsec\config.json

如果是 macOS,请打开 ~/.parsec/config.json(可以用 open -e ~/.parsec/config.json 命令直接打开)

  1. 在第一个花括号 { 后面增加这 9 行代理配置,注意加完以后整个文件必须是一个合法的 JSON,否则 Parsec 会重置配置
1
2
3
4
5
6
7
8
9
"app_proxy": {
"value": true
},
"app_proxy_address": {
"value": "127.0.0.1"
},
"app_proxy_port": {
"value": 7890
},

  1. 保存以后,打开任务管理器,结束所有 parsecd.exe 进程,然后再打开 Parsec,就可以正常使用了。

使用 HTTP API 从 WPS 在线表格中增删改查数据示例

2024-09-09 16:26:00

使用 HTTP API 从 WPS 在线表格中获取数据 中,我介绍了如何查询数据,本篇将介绍如何利用 AirScript 实现完整的增删改查。

首先还是在金山文档中创建一个智能表格,在智能表格中创建一个数据表,这里以 “汇率表” 为例。

点 “高级功能” - “高级开发” - “AirScript 脚本编辑器”,在文档共享脚本中,点击 + 号右边的下拉按钮,创建一个 AirScript 1.0 脚本。

AirScript 2.0 脚本暂时还不支持数据表

输入以下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/**
* WPS 智能表格数据表 AirScript 增删改查示例
* @author iMaeGoo <hello@imaegoo.com>
* @copyright iMaeGoo 2024
* @license MIT
*/

// 请求参数
const request = {
// 操作 ("create" | "read" | "update" | "delete")
action: Context.argv.action,
// 数据表名
sheet: Context.argv.sheet,
// 筛选条件,写法参考 https://airsheet.wps.cn/docs/api/excel/databook/%E9%99%84%E5%BD%95.html#%E9%99%84%E5%BD%95-3-%E7%AD%9B%E9%80%89%E6%9D%A1%E4%BB%B6%E8%AF%B4%E6%98%8E
filter: Context.argv.filter,
// 更新的字段信息
fields: Context.argv.fields,
};

// 响应参数
const response = {
success: false,
data: undefined,
message: "",
};

if (!request.action) {
response.message = "action 参数不能为空";
return response;
}

if (!request.sheet) {
response.message = "sheet 参数不能为空";
return response;
}

// 获取工作表
const sheet = Application.Sheets.Item(request.sheet);

switch (request.action) {
case "create":
response.data = create();
response.success = true;
response.message = "创建成功";
break;
case "read":
response.data = read();
response.success = true;
response.message = "查询成功";
break;
case "update":
response.data = update();
response.success = true;
response.message = "更新成功";
break;
case "delete":
response.data = del();
response.success = true;
response.message = "删除成功";
break;
default:
response.message =
'action 参数错误,应为 "create" | "read" | "update" | "delete"';
}

// 增
function create() {
return sheet.Record.CreateRecords({
Records: [
{
fields: request.fields,
},
],
});
}

// 查
function read() {
let all = [];
let offset = null;
while (all.length === 0 || offset) {
let records = sheet.Record.GetRecords({
Offset: offset,
Filter: request.filter,
});
offset = records.offset;
all = all.concat(records.records);
}
return all;
}

// 改
function update() {
const records = read();
const updateRecords = records.map((record) => {
return {
id: record.id,
fields: request.fields,
};
});
return sheet.Record.UpdateRecords({
Records: updateRecords,
});
}

// 删
function del() {
const records = read();
const deleteIds = records.map((record) => record.id);
return sheet.Record.DeleteRecords({
RecordIds: deleteIds,
});
}

return response;

按 Ctrl + S 保存脚本,然后点击工具栏上的 “脚本令牌” 按钮,生成一个脚本令牌,复制这个令牌保存(以后将无法再次查看),令牌有效期是半年,但放心,令牌可以随时延期,延期后令牌不变。

点击脚本名称旁边的菜单,点击 “复制脚本 webhook” 并保存。

接下来只需 POST 这个 webhook 地址,在请求头中带上 AirScript-Token: 脚本令牌,即可实现增删改查功能。

查询

查询美元的汇率

请求参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"Context": {
"argv": {
"action": "read",
"sheet": "汇率表",
"filter": {
"mode": "AND",
"criteria": [
{
"field": "货币名称",
"op": "Contains",
"values": [
"美元"
]
}
]
}
}
}
}

响应参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{
"data": {
"logs": [
{
"filename": "<system>",
"timestamp": "15:42:07.539",
"unix_time": 1725867727539,
"level": "info",
"args": [
"脚本环境(1.0)初始化..."
]
},
{
"filename": "<system>",
"timestamp": "15:42:07.544",
"unix_time": 1725867727544,
"level": "info",
"args": [
"已开始执行"
]
},
{
"filename": "<system>",
"timestamp": "15:42:07.678",
"unix_time": 1725867727678,
"level": "info",
"args": [
"执行完毕"
]
}
],
"result": {
"data": [
{
"fields": {
"中行折算价": 709.89,
"发布日期": "2024/09/09",
"发布时间": "15:25:28",
"现汇买入价": 710.11,
"现汇卖出价": 712.94,
"现钞买入价": 704.34,
"现钞卖出价": 712.94,
"货币名称": "美元"
},
"id": "VN"
}
],
"message": "查询成功",
"success": true
}
},
"error": "",
"status": "finished"
}

新增

创建一条 “萌币” 的汇率记录

请求参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"Context": {
"argv": {
"action": "create",
"sheet": "汇率表",
"filter": {},
"fields": {
"中行折算价": 26.05,
"发布日期": "2024/09/09",
"发布时间": "15:55:28",
"现汇买入价": 21.05,
"现汇卖出价": 22.05,
"现钞买入价": 23.05,
"现钞卖出价": 25.95,
"货币名称": "萌币"
}
}
}
}

响应参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{
"data": {
"logs": [
{
"filename": "<system>",
"timestamp": "15:56:57.857",
"unix_time": 1725868617857,
"level": "info",
"args": [
"脚本环境(1.0)初始化..."
]
},
{
"filename": "<system>",
"timestamp": "15:56:58.650",
"unix_time": 1725868618650,
"level": "info",
"args": [
"已开始执行"
]
},
{
"filename": "<system>",
"timestamp": "15:56:58.805",
"unix_time": 1725868618805,
"level": "info",
"args": [
"执行完毕"
]
}
],
"result": {
"data": [
{
"fields": {
"中行折算价": 26.05,
"发布日期": "2024/09/09",
"发布时间": "15:55:28",
"现汇买入价": 21.05,
"现汇卖出价": 22.05,
"现钞买入价": 23.05,
"现钞卖出价": 25.95,
"货币名称": "萌币"
},
"id": "VP"
}
],
"message": "创建成功",
"success": true
}
},
"error": "",
"status": "finished"
}

修改

修改 “萌币” 的备注

请求参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"Context": {
"argv": {
"action": "update",
"sheet": "汇率表",
"filter": {
"mode": "AND",
"criteria": [
{
"field": "货币名称",
"op": "Contains",
"values": [
"萌币"
]
}
]
},
"fields": {
"备注": "很萌但并不存在的货币"
}
}
}
}

响应参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
{
"data": {
"logs": [
{
"filename": "<system>",
"timestamp": "16:00:41.894",
"unix_time": 1725868841894,
"level": "info",
"args": [
"脚本环境(1.0)初始化..."
]
},
{
"filename": "<system>",
"timestamp": "16:00:42.683",
"unix_time": 1725868842683,
"level": "info",
"args": [
"已开始执行"
]
},
{
"filename": "<system>",
"timestamp": "16:00:42.955",
"unix_time": 1725868842955,
"level": "info",
"args": [
"执行完毕"
]
}
],
"result": {
"data": [
{
"fields": {
"中行折算价": 26.05,
"发布日期": "2024/09/09",
"发布时间": "15:55:28",
"备注": "很萌但并不存在的货币",
"现汇买入价": 21.05,
"现汇卖出价": 22.05,
"现钞买入价": 23.05,
"现钞卖出价": 25.95,
"货币名称": "萌币"
},
"id": "VP"
}
],
"message": "更新成功",
"success": true
}
},
"error": "",
"status": "finished"
}

删除

删除 “萌币” 记录

请求参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"Context": {
"argv": {
"action": "delete",
"sheet": "汇率表",
"filter": {
"mode": "AND",
"criteria": [
{
"field": "货币名称",
"op": "Contains",
"values": [
"萌币"
]
}
]
}
}
}
}

响应参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
"data": {
"logs": [
{
"filename": "<system>",
"timestamp": "16:01:47.265",
"unix_time": 1725868907265,
"level": "info",
"args": [
"脚本环境(1.0)初始化..."
]
},
{
"filename": "<system>",
"timestamp": "16:01:47.271",
"unix_time": 1725868907271,
"level": "info",
"args": [
"已开始执行"
]
},
{
"filename": "<system>",
"timestamp": "16:01:47.526",
"unix_time": 1725868907526,
"level": "info",
"args": [
"执行完毕"
]
}
],
"result": {
"data": [
{
"deleted": true,
"id": "VP"
}
],
"message": "删除成功",
"success": true
}
},
"error": "",
"status": "finished"
}

读速 7000 的 2T 固态只卖 599,当游戏盘真香

2024-08-27 21:31:00

简单测评一下新买的幻隐 HV3000 GR 2TB 固态硬盘。

测试环境

  1. 主板是 TUF GAMING B760M-PLUS WIFI,CPU 是 i5-13600KF
  2. 插在远离 CPU 的 PCIe 4.0 接口上,并安装主板标配的 M.2 散热马甲

测试截图

优点

  1. 速度快
  2. 价格低
  3. 五年质保
  4. 贴纸出厂时在纸盒里,没有贴在硬盘上,有利于散热
  5. 赠送螺丝、螺丝刀、金属散热片

缺点

  1. 包装简陋,没有塑封,也没有防拆贴
  2. 慧荣主控,两颗美光颗粒 B58R,这块我也不太懂,网上有反馈掉盘的情况,可能是品控问题,也可能是没做好散热,我没有遇到,只要当游戏盘,不要放重要的资料,就不必担心数据丢失了