浦口龙虎巷扫街,记录人间真实
龙虎巷的高大梧桐树今年被政府砍断了,原本颇有老街风貌的街区瞬间失去了一些色彩,但这里依然还有很多魅力景物,昨天带上索尼 FE 35mm F1.8 去拍了几张照片,特此分享。
龙虎巷的高大梧桐树今年被政府砍断了,原本颇有老街风貌的街区瞬间失去了一些色彩,但这里依然还有很多魅力景物,昨天带上索尼 FE 35mm F1.8 去拍了几张照片,特此分享。
今天看B站动态当中的配图文件格式是 AVIF,瞬间起了兴趣。
然后才发现我的博客这么多图片我一直还在使用 MozJPEG 格式压缩的,虽然 MozJPEG 压缩率已经很高了,但看到更先进的算法不由得还是心动了,于是决定进行一些研究和寻求一些改变。
Squoosh 是 Google chrome labs 推出的,他支持压缩成 AVIF, MozJPEG, BrowserJPEG(就是标准JPEG), WebP 等格式,我一直用他压缩图片。他是开源的,源码在 https://github.com/GoogleChromeLabs/squoosh 支持这么多压缩算法
Squoosh各种压缩算法对比表
算法名称 | 核心技术 | 优势场景 | 劣势 | 兼容性 |
---|---|---|---|---|
AVIF | AV1视频编码 | 超高压缩率(50%+),支持HDR/广色域 | 编码速度慢,旧浏览器不支持 | 需现代浏览器 |
Browser JPEG | 传统JPEG | 快速压缩,广泛兼容 | 压缩率/画质均低于优化算法 | 全平台兼容 |
JPEG XL (beta) | 新一代JPEG | 渐进加载,兼容传统JPEG,超高画质保留 | 尚处beta阶段,生态未普及 | 实验性支持 |
MozJPEG | 优化版JPEG | 比传统JPEG节省20%-30%体积,兼容性好 | 无法突破JPEG格式限制 | 全平台兼容 |
WebP | Google VP8 | 比JPEG小30%+,支持透明通道 | 部分旧设备不支持,不支持渐进加载 | 主流浏览器支持 |
WebP v2 (unstable) | 升级版VP8 | 比WebP体积更小 | 不稳定,可能产生画质异常 | 实验性支持 |
(注:PNG相关算法未列入主推荐,因PNG格式不适合照片压缩)
我的目标是占用存储空间小(用户访问文章图片加载也会更快),画质能接受不能太差,所以最好的方案是 AVIF,但是兼容性差,图床支持也不行。
最佳选择是这样的 优先级排序:AVIF > WebP > MozJPEG
质量等级 65-75
,开启 色域保留
选项。质量等级 75-85
,勾选 自动滤镜优化
。质量等级 75-80
,开启 渐进加载
提升感知速度。下面实测我拍的一张南京长江大桥图片,分别使用 AVIF, MozJPEG, WebP 压缩,每种压缩算法均使用 Squoosh 默认压缩选项,来比比看吧
可以看出,MozJPEG -> WebP -> AVIF 压缩率逐步提升,文件体积不断减小,我看了一下画质均在可接受范围内,其中 WebP 我勾选了【Auto adjust filter strength 自动调整滤镜增强】(不会影响压缩率和文件体积,只会影响画质),一个表格来表达
算法名称 | 压缩率 | 压缩后文件体积 |
---|---|---|
MozJPEG | 88% | 1.09MB |
WebP | 91% | 812KB |
AVIF | 95% | 419KB |
从表格可以看出 AVIF 压缩率和新文件的文件体积都遥遥领先,这正是未来趋势。不过使用 AVIF 压缩时间很久,电脑风扇也会呼呼转,这也是代价。
我使用的图床是 Lsky Pro,不支持 avif,开源版本目前也不会迭代了,更不会增加新需求。综上,我今后将使用 WebP 作为图床图片的格式,虽然比 MozJPEG 也没有强多少,但是总归是要更好的。
我分享这个 flow 是因为我有分享视频中片段的需求,但是又不想用相机拍摄,相机拍摄效果可能也不好。下载下来再裁剪又太麻烦。尤其是我喜欢看车祸警示录,有时候看到某些事故非常搞笑,我就用这个手段录制下来,视频可能就10s,30s,然后再微信分享,就很 nice 了。如果是分享10min的完整视频那种,就不如直接贴链接,或者直接下载下来再分享,不需要使用本文方案进行录制。
你是否会因为难以下载 YouTube, X(Twitter), 小红书, Instagram, 微博 之类的网站上的视频而发愁呢……虽然下载这些网站的视频大多都有在线工具或者命令行工具,可以在 GitHub 寻找。
但是目前经过我的日常使用,小红书和微博上的视频资源不是很轻松就能下载下来,或者下载用时很久,还可能下载下来文件太大(比如下载时无法执行码率和分辨率),不利于再次分享。
我为了解决这个问题,一开始使用了 NVIDIA Geforce Experience,但是这个只能录制屏幕的完整内容,如果想要录制屏幕当中的某一块区域,英伟达这个软件就不行了。
于是转而使用 Obs Studio。下面这段介绍来自 DeepSeek V3
OBS Studio(Open Broadcaster Software)是一款免费开源的跨平台直播和录屏软件,广泛用于游戏直播、教学演示、视频创作等场景。以下是其核心特点:
官网下载:OBS Project
社区活跃,遇到问题可通过论坛或GitHub快速解决。适合追求高自由度、零成本的用户。
我在使用 Windows 11 电脑。安装好 Obs Studio 之后,打开软件,进行初始化配置,我不直播,所以只进行了 recording 录制相关的初始化,最后 apply settings,应用设置。
添加源。我拿录制B站车祸警示录的视频举例,使用 edge 浏览器播放B站视频,那么来源选择【窗口采集】,选中正在运行的 edge 那个窗口,标题前缀是 [msedge.exe]
,
如果不想录入当前电脑麦克风的声音,请将 Mic 给静音。
此时会录制整个窗口的画面,如果想录制视频播放区域,需要添加一个裁剪/填充
的【滤镜】,如下图,设置好距离左,顶部,右,底部的像素数量关闭即可。
在开始录制前确保输出的视频画面充满整个画布,勾选使用此源的尺寸作为输出分辨率 (重要重要!否则输出的视频可能有很多“留黑”空白区域)
最后再点击【开始录制】,同时播放 edge 浏览器窗口的视频,在视频结束时(或者你想截取的视频片段刚好结束)点击【停止录制】。
最终录制视频呈现的质量,设置项在 【设置】->【输出】->【录制】->【录像质量,录像格式,视频编码器,音频编码器,音轨】等配置。
建议录像格式使用MPEG-4,方便传播,比如微信就可以直接预览 mp4 视频。
使用了这个插件: https://github.com/zyuzhi/MarkdownKatex-typecho ,下载了 v1.0.1
,但是点击创建文章之后无法返回所有文章页面。另外博客首页也无法加载,禁用插件即恢复正常。懒的去追究原因了,索性不用插件改用其他方法。
我家里的一台机器也部署了 typecho,同样都是 docker compose 部署的,和当前 typecho 实例的区别大概就是
v1.2.0
vsv1.2.1
。家里机器上的 typecho 是 1.2.0,当前实例是 1.2.1,有可能是版本升级导致的原有插件失效,因为上述插件 GitHub 源代码是2018年左右最终打包到 release 发行的。
在 typecho v1.2.1
实例上测试如下方法可以为 typecho 博客添加 latex 支持。
方法参考: https://www.xrgzs.top/posts/typecho-use-mathjax-add-latex-support
将以下代码添加到 footer.php </body>
关闭标签之前。我这个主题这个文件在 components/footer.php
。我上面参考的博客将这段脚本引用放在了 index.php,可能会引起 DOM 渲染紊乱,比如图片被拉长,主页 footer 在页面中间渲染。放在 footer.php
的 </body>
前,此时 DOM 已解析完成,图片布局已稳定,脚本加载不再影响初始渲染
<script async type="text/javascript"
src="//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
将以下代码添加到 header.php 的适当位置。我这个主题这个文件在 components/header.php
。
<script async type="text/javascript"
src="//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
extensions: ["tex2jax.js"],
jax: ["input/TeX", "output/HTML-CSS"],
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
processEscapes: true
},
"HTML-CSS": { availableFonts: ["TeX"] }
});
</script>
物体所受合外力 $\mathbf{F}$ 与其加速度 $\mathbf{a}$ 满足:
$$ \mathbf{F} = m\mathbf{a} = \frac{d\mathbf{p}}{dt} $$
其中:
两个质点间的引力大小:
$$ F = G\frac{m_1 m_2}{r^2} $$
式中普适常量: $G \approx 6.674 \times 10^{-11}\, \mathrm{m^3 \cdot kg^{-1} \cdot s^{-2}}$
以下是我和DeepSeek R1的对话
新能源汽车使用7kW 交流慢充和外面的直流快充,哪个充电时损耗更高?7kW 交流慢充的电流大概30A,44度电池大概需要7个小时;使用外面直流快充桩,假如功率是70kW,充满需要1小时,但是充电电流最大180A左右。请计算一下哪种充电方式电损耗更多?
在比较新能源汽车使用7kW交流慢充和70kW直流快充的充电损耗时,需综合考虑线损和转换效率。以下是关键分析步骤:
在合理假设下,直流快充的总损耗更低(约3kWh),因其转换效率更高且充电时间短。但若按用户提供的错误数据(快充输入70kWh),则损耗更高,此情况不符合实际。实际使用中,快充是更高效的选择。
我给出的快充功率70kW,但实际充电功率并不是恒定70kW 呀,功率会随着电池soc的增高而降低的。所以快充充满一般都需要1小时。请再计算看看
在考虑快充功率动态变化的情况下,重新计算两种充电方式的损耗如下:
指标 | 直流快充(动态功率) | 交流慢充(7kW) |
---|---|---|
总损耗 | 约2.54kWh | 约5.55kWh |
损耗比例 | 5.8%(44kWh电池) | 12.6% |
核心原因 | 转换效率高(95%)、时间短、线损低 | 转换效率低(90%)、时间长、线损高 |
即使考虑快充功率随SOC动态下降的情况,直流快充的总损耗(约2.54kWh)仍显著低于交流慢充(约5.55kWh)。核心原因在于:
实际建议:若需减少充电损耗,优先选择直流快充;若考虑电池寿命,可适当使用慢充平衡。
21年8月我写过这篇:全国各省份 5A 级景区
时间到了2025年3月,全国5A变化挺大的,今天再来处理一下全部数据。数据来自文化和旅游部 at 2025-03-25 14:32:24
先上代码
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import java.util.Collections;
/**
* @author: hellodk
* @description AllProvince5ASpot
* @date: 3/25/2025 1:47 PM
*/
public class AllProvince5ASpot {
private static int globalCounter = 0;
public static void main(String[] args) {
AllProvince5ASpot spot = new AllProvince5ASpot();
spot.printAll5ASpot();
System.out.println("一共有多少个景区?" + globalCounter);
}
private void printAll5ASpot() {
final String baseUrl = "https://www.mct.gov.cn/tourism/api/content/getContentListByDirId";
int totalPage;
int totalItem = 0;
int currPage = 1;
JSONObject body = new JSONObject();
body.put("directoryId", "4");
body.put("searchList", Collections.emptyList());
body.put("size", 100);
body.put("page", currPage);
HttpResponse resp = HttpUtil.createPost(baseUrl)
.body(body.toJSONString(), ContentType.JSON.getValue())
.timeout(60000)
.execute();
if (!resp.isOk()) {
System.err.println("第一次就请求失败。现退出程序");
return;
}
JSONObject res = JSON.parseObject(resp.body());
// .data.contentList.totalPages
// totalElements
totalPage = res.getJSONObject("data").getJSONObject("contentList").getInteger("totalPages");
totalItem = res.getJSONObject("data").getJSONObject("contentList").getInteger("totalElements");
System.out.println("总的页数:" + totalPage);
System.out.println("总的景区数:" + totalItem);
JSONArray items = res.getJSONObject("data").getJSONObject("contentList").getJSONArray("content");
printSpot(items);
while (currPage <= totalPage) {
currPage++;
ThreadUtil.safeSleep(3000);
body.put("page", currPage);
resp = HttpUtil.createPost(baseUrl)
.body(body.toJSONString(), ContentType.JSON.getValue())
.timeout(60000)
.execute();
if (!resp.isOk()) {
System.err.println("第 " + currPage + " 次请求失败。现跳过当次,准备下一次请求");
continue;
}
res = JSON.parseObject(resp.body());
items = res.getJSONObject("data").getJSONObject("contentList").getJSONArray("content");
printSpot(items);
}
}
private void printSpot(JSONArray items) {
if (CollectionUtils.isNotEmpty(items)) {
System.out.println();
System.out.println("----");
for (Object item : items) {
globalCounter++;
JSONObject spot = (JSONObject) item;
System.out.print("景区名称:" + spot.getString("name") + " ");
System.out.print("地区:" + spot.getString("provinceName") + " ");
System.out.print("A级:" + spot.getString("gradesName") + " ");
System.out.print("评定年份:" + spot.getString("year"));
System.out.println();
}
System.out.println("----");
System.out.println();
}
}
}
输出如下:
总的页数:4
总的景区数:358
一共有多少个景区?358
注意这些只包含了5A
先说明一下,网上的一些教程已经过时,从MIUI各个版本迭代到如今 HyperOS 改了又改,很多方法失效了。通过拨号键盘输入 *#*#6485#*#*
现在已不展示 MF_05 和 MF_06 的值。
系统里的【电池保护】功能只使用通俗语言描述了电池健康度,没有显示剩余容量的百分比。
当前是2025年3月,我经过实践得知,通过拨号键盘输入 *#*#284#*#*
,手机会生成Bug检测报告,仔细查阅这份 txt 报告,能得到当前手机容量和循环次数。
生成bug检测报告大概率很慢,需要耐心等待,系统通知栏会有进度条。生成成功之后,zip 文件存在于 内部存储器/MIUI/debug_log/bugreport-2025-03-07-120503.zip
,我是把这个文件拷贝到了电脑上。然后解压缩此 zip 文件,得到 bugreport-Redmi K70-2025-03-07-121000.zip
,继续解压缩这个 redmi k70 的 zip 文件,得到 bugreport-vermeer-UKQ1.230804.001-2025-03-07-12-05-04.txt
这个文件。不同型号这个文件名不同,你需要查看的是 bugreport 开头的并且扩展名是 .txt 的文件。使用 vscode 或者其他文本编辑器搜索这个文件
1️⃣ 搜索 battery capacity
能够得到电池当前容量
2️⃣ 搜索 cycle count
能得到手机循环次数,实际上这里的 Full charge 的值也是现在手机电池的最大容量,4825000就是 4825毫安时,除以出厂时的典型容量5000毫安时可得,容量还剩 96.5%
我的 K70 是2023-12-02到手的,典型容量是5000毫安时。手机电池一般是三元锂软包,我的经过了402次循环还剩96.5%的容量,说明我的电池使用习惯还不错。
PS: 今天2025-03-07,距离2023-12-02已经过了461天,这段时间K70一直是我的主力机。
开始时间:2023年12月02日 00:00
结束时间:2025年03月07日 00:00
相差年数:2年
相差月数:15月
相差周数:65周余6天
相差天数:461天
相差小时:11064时
我的 seafile 安装在内网,服务地址是 http://10.10.10.5:8088
,然后我使用 frp 将其暴露在了公网 https://seafile.940304.xyz
。
正常情况下在任何联网设备上都可以通过域名 seafile.940304.xyz
访问,并且能够上传和下载。但是当我处于 10.10.10.0/24
家里的内网时,我发现上传文件走了公网(seafile.940304.xyz
所在服务器),所以数据包兜了个圈再回到我家,这样的表现就是上传下载文件都非常缓慢,最大速率刚好是我的公网机器的带宽。我发现这是 seafile 系统设置当中 FILE_SERVER_ROOT
这个变量定义成了 https://seafile.940304.xyz/seafhttp
导致的,于是寻求解决办法。
一个临时办法:
当我处于家庭内网时,如果需要上传大文件,我可以手动改一下系统配置,将 FILE_SERVER_ROOT 改成 http://10.10.10.5:8088/seafhttp
,这样可以临时解决上传速度慢的问题。
但是这样未免有点低效。我开始上网搜索解决办法,看到如下这些相似的帖子:
思索再三之后,配合 gpt-4o 对我的一些建议,我发现一个不错的解决办法,因为我的家庭网络使用了 openwrt 作为网关路由器,并且当时构建的镜像使用 nginx
替代了原本的 uhttpd
作为 web server,这样就更加接近我的目标了。简单说下实现思路
SERVICE_URL
保持公网地址 https://seafile.940304.xyz/
;FILE_SERVER_ROOT
的值保持公网地址 https://seafile.940304.xyz/seafhttp
。此时非内网的公网下访问、上传、下载都没有问题seafile.940304.xyz
域名直接映射到 10.10.10.1
,这是我的 openwrt 地址seafile.940304.xyz
的请求全都转发到 10.10.10.5:8088
以下是详细步骤。
填入公网的地址即可。SERVICE_URL
填入公网地址 https://seafile.940304.xyz/
;FILE_SERVER_ROOT
的值填入公网地址 https://seafile.940304.xyz/seafhttp
,然后保存。
打开 openwrt 后台管理页面,进入 网络
-> DHCP/DNS
-> 主机名映射
,添加一条记录,主机名 seafile.940304.xyz
,IP地址 10.10.10.1
然后保存。
这个操作是否生效了可以在本地局域网任何一台机器使用命令 nslookup seafile.940304.xyz
检查,返回结果是 10.10.10.1
则说明配置正常且生效了。否则可能还是域名对应的公网地址
nginx 配置如下,文件名 /etc/nginx/conf.d/seafile-on-pvedebian11.conf
,其中 ssl 证书和私钥 key 部分是我从我的公网机器上 copy 过来的。
server {
listen 443 ssl;
server_name seafile.940304.xyz;
ssl_certificate /etc/letsencrypt/live/940304.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/940304.xyz/privkey.pem;
access_log /var/log/nginx/seafile_access.log;
error_log /var/log/nginx/seafile_error.log;
location / {
proxy_pass http://10.10.10.5:8088;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /seafhttp {
proxy_pass http://10.10.10.5:8088/seafhttp;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
然后检查 nginx 配置是否正确和重载 nginx 服务即可。
在内网使用公网域名正常访问,并且是反向代理过的,访问、上传和下载速度都极快。可以通过 openwrt 上的 nginx 日志验证。
检查 openwrt 上 nginx 的日志文件 /var/log/nginx/seafile_access.log
[root@openwrt_ai_dk_20240831:11:54 AM /etc/nginx/conf.d] # tail -n 10 /var/log/nginx/seafile_access.log
10.10.10.108 - - [13/Oct/2024:11:03:55 +0800] "GET /api/v2.1/admin/web-settings/ HTTP/1.1" 200 1176 "https://seafile.940304.xyz/sys/web-settings/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
10.10.10.108 - - [13/Oct/2024:11:03:55 +0800] "GET /media/img/seafile-logo.png?t=1728788662258 HTTP/1.1" 200 12612 "https://seafile.940304.xyz/sys/web-settings/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
10.10.10.108 - - [13/Oct/2024:11:03:55 +0800] "GET /media/favicons/favicon.png?t=1728788662258 HTTP/1.1" 200 45439 "https://seafile.940304.xyz/sys/web-settings/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
10.10.10.108 - - [13/Oct/2024:11:03:55 +0800] "GET /media/custom/login-bg.jpg?t=1728788662258 HTTP/1.1" 200 338345 "https://seafile.940304.xyz/sys/web-settings/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
10.10.10.108 - - [13/Oct/2024:11:05:19 +0800] "GET / HTTP/1.1" 200 2227 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
10.10.10.108 - - [13/Oct/2024:11:05:20 +0800] "GET /api/v2.1/notifications/ HTTP/1.1" 200 689 "https://seafile.940304.xyz/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
10.10.10.108 - - [13/Oct/2024:11:05:20 +0800] "GET /api/v2.1/repos/?type=mine HTTP/1.1" 200 1394 "https://seafile.940304.xyz/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
10.10.10.108 - - [13/Oct/2024:11:24:32 +0800] "GET / HTTP/1.1" 200 2229 "https://seafile.940304.xyz/sys/web-settings/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
10.10.10.108 - - [13/Oct/2024:11:24:32 +0800] "GET /api/v2.1/notifications/ HTTP/1.1" 200 689 "https://seafile.940304.xyz/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
10.10.10.108 - - [13/Oct/2024:11:24:32 +0800] "GET /api/v2.1/repos/?type=mine HTTP/1.1" 200 1394 "https://seafile.940304.xyz/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
并且,在内网依然可以使用内网IP和端口访问,并且此时上传和下载还是走 https://seafile.940304.xyz/seafhttp
匹配到的 nginx 反向代理,即 http://10.10.10.5:8088/seafhttp
,所以还是走的内网,速度依然最佳。
于是这个问题通过设置公网地址+公网域名映射内网ip+nginx反向代理完美解决。
我发现一些论坛,还有 telegram,都支持文字 spoiler 效果,那什么是文本 spoiler?
在英文中,“spoiler”这个词原本的含义是指“破坏者”或“毁坏者”。在不同的上下文中,它可以指代能够破坏某种事情、情节、计划或体验的因素。
近年来,随着社交媒体和娱乐讨论的普及,“spoiler”一词常常用于指代剧透,特别是在讨论电影、电视剧、小说等作品时。
因此,虽然“spoiler”最初的意思是“破坏者”,但现代用法主要与“剧透”相关,体现了该词在流行文化中的演变。
在Telegram客户端中,文字的spoiler效果可以通过特定的格式来实现。用户可以将某些文本标记为spoiler,使其在聊天中不直接显示,而是被一个模糊的、可点击的框包裹。这种设计的作用主要有几个方面:
我想在typecho中实现这个效果。既然markdown不支持,那么我们就用原生css和html实现吧。
我考虑了一下,还是鼠标直接悬浮(当然也支持点击)就直接展示原文,这样更加简单直接。有一些论坛的实践(比如 linux.do )确实是需要点击后才显示原文。
登录typecho后台,进入博客的样式设置页面(控制台 -> 外观 -> 设置外观),url路由是 https://xxx.com/admin_path/options-theme.php
,其中 admin_path 默认是 admin,如果你像我一样想增强博客安全,可以更改一下这部分的路由,改成复杂字符串或者自己的名字之类的字符串,目的是为了不让别人轻易发现博客后台登录地址。
在全局css 样式中定义如下样式,这是我精心调试过的效果。效果演示放在后文。
.spoiler {
position: relative; /* 使得伪元素可以定位 */
background-color: rgba(200, 200, 200, 0.3); /* 浅灰色半透明背景 */
color: rgba(0, 0, 0, 0.5); /* 半透明黑色文字 */
user-select: none; /* 禁止选中文字 */
overflow: hidden; /* 隐藏溢出的内容 */
cursor: pointer; /* 鼠标悬停时光标变为手型 */
filter: blur(3px); /* 添加模糊效果 */
padding: 5px; /* 为文本添加内边距以增强效果 */
transition: filter 0.3s ease; /* 添加平滑过渡效果 */
}
.spoiler:hover {
background-color: inherit; /* 悬停时使用父元素的背景色 */
color: inherit; /* 悬停时显示原色 */
filter: blur(0); /* 悬停消除模糊效果 */
}
保存即可。后面就是写文章时直接引用该class即可。
我习惯使用 <span>
标签。比如原文是 我才知道周也的父亲是叫周秦快。
,如果你是写影评,为了避免剧透把周秦快
做spoiler效果,那就写如下内容
我才知道周也的父亲是叫<span class="spoiler">周秦快</span>。
我才知道周也的父亲是叫周秦快。
ok,这便是我想要的效果。
使用 Facile 主题已经有一年多了应该,首先感谢作者的开发,目前我使用得挺好。我最近刚由 2.1.12 切换到 2.2 版本,但是图片懒加载功能似乎一直没有生效?直到我最近写了一篇包含94张图片的文章,才发现浏览体验受到了很大的影响。
我也提了一个 issue,并给出了我的解决方法, https://github.com/changbin1997/Facile/issues/12
作者回复他那边没问题,那很可能是我这边什么插件导致了 replaceImgSrc
方法不起作用,或者其他兼容性问题,但最后好在我解决了,本文就分享一下我的解决方法,并且给出我做的其他小细节定制。
进入容器(或者你是宿主机直接安装就去宿主机找)找到文件 usr/themes/Facile/components/header.php
在 <head>
标签下引入脚本,详细如下
找到 <link rel="stylesheet"
这一行,以及 <!--自定义CSS-->
这一行,在其中插入 <script src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.2.2/lazysizes.min.js" async></script>
修改后如下
<link rel="stylesheet" href="<?php $this->options->themeUrl('assets/css/style-1722355012.css'); ?>" type="text/css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.2.2/lazysizes.min.js" async></script>
<!--自定义CSS-->
<?php if ($this->options->cssCode): ?>
找到 usr/themes/Facile/functions.php
文件,或者直接在 typecho 后台管理页修改,也就是 控制台
-> 外观
-> 编辑当前外观
-> functions.php
,具体修改如下,注释掉原本的代码,我修改的 replaceImgSrc
使用了一个 svg loading 图作为占位符(滚动可视区域内的图片尚未完全加载前的转圈圈效果)
// 把图片的 src 替换为 data-src,用于图片懒加载,这是Facile 2.1.12以及2.2 版本当中的代码
//function replaceImgSrc($content) {
// $pattern = '/<img(.*?)src(.*?)=(.*?)"(.*?)">/i';
// $replacement = '<img$1data-src$3="$4"$5 class="load-img">';
// return preg_replace($pattern, $replacement, $content);
// }
function replaceImgSrc($content) {
// SVG 数据URI
$loadingSVG = 'data:image/svg+xml;charset=UTF-8,' . rawurlencode('<svg version="1.1" id="L9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve"><path fill="#000" d="M73.438,49.25c0-13.025-10.634-23.562-23.75-23.562c-13.024,0-23.562,10.537-23.562,23.562h6.797 c0-9.276,7.489-16.765,16.765-16.765c9.276,0,16.765,7.489,16.765,16.765H73.438z"><animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="1s" from="0 50 50" to="360 50 50" repeatCount="indefinite" /></path></svg>');
$pattern = '/<img(.*?)src=["\'](.*?)["\'](.*?[^>])>/i';
$replacement = '<img$1src="' . $loadingSVG . '" data-src="$2"$3 class="lazyload"><noscript><img$1src="$2"$3></noscript>';
return preg_replace($pattern, $replacement, $content);
}
这个方法是在 usr/themes/Facile/post.php
的如下地方调用的,也就是主题设置中的图片懒加载功能需要打开
<?php echo $this->options->imagelazyloading == 'on'?replaceImgSrc($GLOBALS['post']['content']):$GLOBALS['post']['content']; ?>
最终我这边图片懒加载功能完美运行,你可以参考我这篇文章,一共94张图,可以很好地预览图片懒加载功能 2024年8月我的宜昌 - 重庆 - 川西小环线自驾旅行分享
在 usr/themes/Facile/functions.php
尾部追加代码,如下
// 添加文章字数统计,预计阅读用时方法
function art_count ($cid){
$db = Typecho_Db::get ();
$rs = $db->fetchRow ($db->select ('table.contents.text')->from ('table.contents')->where ('table.contents.cid=?',$cid)->order ('table.contents.cid',Typecho_Db::SORT_ASC)->limit (1));
$text = preg_replace("/[^\x{4e00}-\x{9fa5}]/u", "", $rs['text']);
$text_num = mb_strlen($text,'UTF-8');
$read_time = ceil($text_num/400);
$output = '本文共' . $text_num . '个字,预计阅读时间' . $read_time . '分钟';
return $output;
}
然后修改 usr/themes/Facile/post.php
文件,在适当位置调用 art_count 方法,修改后如下
<span class="ml-1" title="发布日期" data-toggle="tooltip" data-placement="top">
<i class="icon-calendar mr-2" aria-hidden="true"></i>
<?php $this->date('Y年m月d日'); ?>
</span>
<span class="ml-2" title="作者" data-toggle="tooltip" data-placement="top">
<i class="icon-user mr-2" aria-hidden="true"></i>
<a rel="author" href="<?php $this->author->permalink(); ?>" class="mr-2" title="作者:<?php $this->author(); ?>">
<?php $this->author(); ?>
</a>
</span>
<span class="ml-2" title="阅读量" data-toggle="tooltip" data-placement="top">
<i class="icon-eye mr-2" aria-hidden="true"></i>
<?php echo postViews($this); ?>
</span>
<span class="ml-2" title="文章字数和阅读预计用时" data-toggle="tooltip" data-placement="top">
<i class="icon-eye mr-2" aria-hidden="true"></i>
<?php _e(art_count($this->cid)); ?>
</span>
修改文件 usr/themes/Facile/components/footer.php
,我改成了如下
<footer>
<div class="container py-3">
<?php if ($this->options->icp): ?>
<nav class="text-center mb-1">
<?php $this->options->icp(); ?>
</nav>
<?php endif; ?>
<nav class="text-center">
<p>Copyright ©
<?php echo "2019 - " . date('Y'); ?> by hellodk.cn | Proudly Powered by <a href="http://www.typecho.org"
target="_blank">Typecho</a> &
<a href="https://hellodk.cn/" target="_blank"> ❤.</a>
Theme by
<a class="ml-1" href="https://github.com/changbin1997/Facile" target="_blank">Facile</a>.
</p>
<p>
<?php hasBeenRunningTime2(); ?>
</p>
</nav>
</div>
</footer>
其中调用了一个方法 hasBeenRunningTime2
,该方法定义如下,添加到 usr/themes/Facile/functions.php
尾部
// 计算网站已运行多长时间
function hasBeenRunningTime2()
{
// 设置时区
date_default_timezone_set('Asia/Shanghai');
// 在下面按格式输入本站创建的时间
$site_create_time = strtotime('2019-04-06 14:00:00'); //格式:年 月 日 时 分 秒
$time = time() - $site_create_time;
if (is_numeric($time)) {
$value = array(
"years" => 0, "days" => 0, "hours" => 0,
"minutes" => 0, "seconds" => 0,
);
if ($time >= 31556926) {
$value["years"] = floor($time / 31556926);
$time = ($time % 31556926);
}
if ($time >= 86400) {
$value["days"] = floor($time / 86400);
$time = ($time % 86400);
}
if ($time >= 3600) {
$value["hours"] = floor($time / 3600);
$time = ($time % 3600);
}
if ($time >= 60) {
$value["minutes"] = floor($time / 60);
$time = ($time % 60);
}
$value["seconds"] = floor($time);
echo 'Site has been running for ';
echo '<span class="btime">' . $value['years'] . ' years ' . $value['days'] . ' days ' . $value['hours'] . ' hours.</span>';
} else {
echo '';
}
}
在 usr/themes/Facile/functions.php
尾部追加方法,代码如下
//评论区简单算术验证,防止评论被滥用
function themeInit($comment){
$comment = spam_protection_pre($comment, $post, $result);
}
function spam_protection_math(){
$num1=rand(1,49);
//数字范围,自定义修改
$num2=rand(1,49);
echo "验证码:<input type=\"text\" name=\"sum\" class=\"text\" value=\"\" size=\"25\" tabindex=\"4\" style=\"width:100px\" placeholder=\"$num1 + $num2 = ?\">\n";
echo "<input type=\"hidden\" name=\"num1\" value=\"$num1\">\n";
echo "<input type=\"hidden\" name=\"num2\" value=\"$num2\">";
}
function spam_protection_pre($comment, $post, $result){
$sum=$_POST['sum'];
switch($sum){
case $_POST['num1']+$_POST['num2']:
break;
case null:
throw new Typecho_Widget_Exception(_t('对不起: 请输入验证码。<a href="javascript:history.back(-1)">返回上一页</a>','评论失败'));
break;
default:
throw new Typecho_Widget_Exception(_t('对不起: 验证码错误,请<a href="javascript:history.back(-1)">返回</a>重试 。','评论失败'));
}
return $comment;
}
然后需要修改 usr/themes/Facile/components/comment-input.php
文件,在适当位置添加对 spam_protection_math 方法的调用,修改后如下
<!--姓名输入-->
<div class="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
<label for="author" class="d-block">姓名</label>
<input type="text" class="form-control" placeholder="请输入您的姓名或昵称" name="author" id="author" value="<?php $this->remember('author'); ?>" required>
</div>
<!--邮箱地址输入-->
<div class="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
<label for="mail" class="d-block">电子邮件地址(不会公开)</label>
<input type="email" class="form-control" placeholder="请输入您的电子邮件地址" name="mail" id="mail" value="<?php $this->remember('mail'); ?>" <?php if ($this->options->commentsRequireMail): ?> required <?php endif; ?>>
</div>
<!--网站地址输入-->
<div class="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
<label for="url" class="d-block">网站(选填)</label>
<input type="url" class="form-control" placeholder="请输入您的网站或博客地址" name="url" id="url" value="<?php $this->remember('url'); ?>" <?php if ($this->options->commentsRequireURL): ?> required <?php endif; ?>>
</div>
<!--数字验证码-->
<div class="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
<?php spam_protection_math(); ?>
</div>
参考了这篇文章 Gravatar 头像镜像源收集 (2024年)
Facile 2.2 版本支持在主题设置中设置 gravatar 源,于是我参考上面文章,修改成了 https://cravatar.cn/avatar/
国内源,目前 gravatar 头像加载速度很快,解决的很完美。
顺便修改一下 Typecho 系统全局的 gravatar 源。比如在 manage-comments.php
评论管理页面就用上了这个地方定义的头像源。修改文件 config.inc.php
,改成如下
// 更换头像源
define('__TYPECHO_GRAVATAR_PREFIX__', 'https://cravatar.cn/avatar/');
改后建议重启 typecho 和数据库。
好了,目前我做的一些修改就是这些。其实之前 2.1.12版本时我还做了全站字数统计放在归档页面等小细节,但是目前就这样,先不改了。
本文是给自己做的修改的详细记录,也给广大网友提供了参考。如有问题,欢迎评论。
去年的这个时候,我一个人去了皖南川藏线和黄山徽州天路等地方旅行。今年早早的有所规划,写了一份还算详尽的计划书。计划着想去但一直没去的川西。至于怎么去最终还是决定和我哥俩人自驾着去,虽然劳累,但是最节省,尽管这样会浪费一些时间在路上。
现在是 2024-08-14 22:13:19,我在旅行归来后总结旅行。在经历过这次舟车劳顿的旅行体验之后,下一次这种去往很远的地方的旅行就再也不会纯自驾了——可能会托运汽车,也可能当地租车,反正都比我们从合肥开车过去要轻松。
这一次的旅行计划是从合肥开到宜昌,走走G348中国地质科普公路,看看三峡库区的雄伟壮丽。再去往重庆,看看美丽山城的夜景。后面就是从重庆直达川西小环线,看海螺沟,翻越折多山垭口,驻足欣赏贡嘎雪山,看看沿途美丽的高原风景……
具体的路线和计划在这篇文章就不写了,本文记录一下旅行当中我拍摄的照片,不过会大致描述一下每天的行程。
今天是假期第一天。我收拾好行李后开车去往合肥,走了国道因为想去看看巢湖……
当天温度有37度左右,但是我按耐不住拿出相机拍下这些田园风光……笔直的公路,绿油油的农田,是我印象中南方夏天的样子。
这就是在巢湖大道拍摄的照片。这一段巢湖的北岸与南岸的直线距离大概是15km左右,还是能看到对岸的山的。
中午到达合肥,下午和晚上继续收拾东西,购买部分补给,整装待发。
6点便洗好出门,怀着激动的心情开启我们的自驾之旅。
第一次到三峡库区,第一次踏上G348国道,一切都很新鲜,风景养眼,就是烈日当空,40度的天气,太劝退人了。本来这样的天气只适合在家吹空调的,但是看到路上也还有一些人在旅行,想想也的确没办法,普通打工人的假期不能自定义,只能硬着头皮上了。
从宜昌下高速,直达【听风谷观景台】。
在听风谷观景台远眺远方的城市宜昌。
宜昌G348。我是在小红书看到很多人推荐G348自驾,刚好我们的行程经过宜昌,于是今天的行程安排可以说相当合理了。
长江中的轮船,拖运的一般是什么?
这条风光大道,标识性的东西做得挺好的,非常多可让人打卡留恋的场景。
晚上准备夜宿【屈原故里】—— 秭归县,傍晚时分感受着江岸的城市,岁月静好,幽静自然,实在是太美好了。如果能不上班该多好啊😭️
山城就是有高低层次,对于长久生活在平原地区的人们来说一定是一道亮丽的风景。
晚上在秭归县街头走走逛逛,发现小县城真的好有活力,还有不错的商业,只是屈原故里等景点未能打卡,略有遗憾。以后有缘再会。
今天从宜昌秭归准备去往重庆市。一开始的打算还要经过一下恩施市,并且去看一下【恩施大峡谷】,但是开到高速口还耽误了很多时间,大峡谷门票200+,只玩一两个小时太亏了,也太贵了。后面只好放弃恩施的游玩计划,直驱重庆市。而且导航显示,到达重庆市也要傍晚6点了。这时候我的研究生同学汤工也顺利到达重庆,于是我们汇合,逛吃重庆,夜拍重庆。这样的安排就刚刚好。
早上出门走的国道/省道,拍摄的沿途的三峡景观。
听我宜昌的朋友说,前阵子刚泄过洪,所以江水看起来才是浑浊的。不然这段的江水,平时清澈得很。
傍晚到达重庆,我们坐了一个公交去往【山城步道】。在重庆坐公交和地铁都是有意思的。
透过公交车的玻璃拍摄,尽管玻璃表面不那么干净,但依然能感受到重庆山城的魅力。这段是乘坐的重庆市322路公交,在重庆长江大桥上。
山城山城,复杂的城市道路会有上上下下,起起伏伏的坡,于是很多视角都是平原城市所很难看到的。这也是在重庆拍照和拍影片容易出片的原因之一。
在山城步道观看远处的【南纪门轨道大桥】。
夜幕降临,我们打车来到重庆大剧院这边,欣赏重庆最具魅力的夜景打卡地。实际上我准备了很多地点都想去,但是迫于时间紧张,只能打卡一两个确实遗憾。重庆以后还会再来的。
重庆这里的夜景,在国内确实排得上前几的。现场人山人海,我们一度怀疑今天是不是什么假期,哪知道只是一个普通的周一晚上。
今天晚上夜宿重庆市南岸区,明天我们将驱车去往川西,我们此行真正的目的地。
6点钟,我们三人打起精神起床,准备直接前往海螺沟景区。重庆到成都段的高速实在是好开,路平车少,轻轻松松跑120~130。
中午我们在泸定县下高速,然后在一家餐馆吃了饱饱的午餐。转了转泸定桥,后面就继续赶路前往海螺沟了。因为景区最后一班车是15:00发车,景区要求15:00之前到达并检票,由于堵车我们差点没去成海螺沟。
检票后还需要坐很长一段时间的景区大巴车,一路上听着车里的介绍,海螺沟景区(5A)在上次地震受损后实现了重建,如今更上一层楼,几乎所有配置均得到了升级。可尽管如此,我们此行依然有所遗憾,他最上面的索道关停了,我们无法到达最高处近距离欣赏贡嘎雪山了。
一起来欣赏海螺沟里面的风景。
幸亏有腾龙28-200镜头,天涯镜名不虚传,出门旅游拍照实在是太方便了。这种大江大河的场景,能拍到比大光圈更加重要。
高原小湖泊,海螺沟景区里的小湖。
这水有点不太清澈,应该是上游有什么活动导致的。
看往景区上游的方向,可惜今天不能到达了。
到了川西和藏区,玛尼堆随处可见。在川西和藏区,玛尼堆是一种具有重要宗教和文化意义的石堆。它们通常由信徒在朝圣或旅行途中堆砌而成,象征着对佛教、特别是藏传佛教的敬仰。
天空美的我说不出话——奈何本人没啥文化,只能说一句美得像画。
这边的雪山融水是清澈的。使用慢快门拍出了流水“丝绸”般柔和、平滑的效果。
从景区下山后,我们开车走榆磨路去康定市区,今晚将夜宿康定。
虽然在海螺沟没有看到雪山,但是天空作美,我们在榆磨路路边看到了“拨开乌云见雪山”,甚至是日照金山!实在是有些激动。第一次看到日照金山的我被深深打动——人们为什么那么向往雪山,因为他就在那里。
今天下午乃至晚上的行程有些危险,全程有好几段路路况很差,我们只是一辆轿车。
然后出去觅食,我们吃到了味道极好的【牦牛肉面】。今晚夜宿康定。
今天从康定到新都桥,路程较少,但中途会有很多观景台可以停车打卡。
早上在康定情歌广场附近拍的。昨晚住在新城,康定情歌广场所处的位置在下游,比较老的城区里。
大渡河流经康定市,在此处水面翻涌,水流挺大。
康定情歌歌词本打卡。
出发去折多山垭口,途中观景台拍摄。
去折多山垭口一直在爬坡,居然这里也能拍到雪山!在川西一步一个风景,实在是惊喜,惊喜。
快要到垭口的地方,回望上山路,这视野真广阔。该碎碎念腾龙28-200广角端不够广了……
从垭口停车休息区开始爬山,因为第一次来海拔4000的高山,我必须慢慢爬,调整呼吸节奏,每一次深呼吸都是尽可能防止高反头痛的发生。在山腰上停留也拍到了远处的雪山。
牵着马下山的当地人和巨大的玛尼堆。
路过这个小伙子摊位前,我发挥出隐藏e人属性,勇敢的说我可以为你拍两张照片吗?他轻轻地点了点头,然后十分认真的看着我的镜头。我一共拍了三张,每一张他的眼睛都很干净和光亮。我好几个同学朋友说,“这有点像丁真了……”
这些雪山几乎都是200mm超长焦拍摄的,实际上雪山距离我们还是很远的。
俊俏的马儿,背景很美~
去往康定机场的路上。
在斯丁措拍摄。
斯丁措景点附近的牦牛,行走的牦牛肉干。
这是去往红海子的路上。
通过一些具有玛尼堆景物的前景,想表达一下远处高山的巍峨,表现力应该还可以吧。
这是在【进村路】上,一路的高山草甸,太美好了!如果不是高原的阳光太晒,我的感受还要加10分。
从【红海子】前往【新都桥镇】,汇入318国道之前会走这一段【进村路】,风景很好,属于旅行中的意外之喜。
傍晚我们驱车来到【新都桥镇 - 贡嘎雪山观景台】,观景台本身是免费的,爬上来时还是出现了一点高反的症状,不过为了在山顶看到贡嘎雪山,我也仍然坚持了下来。
看到几个小伙子自驾游,也驻足这里拍贡嘎。一个是富士xt5 150-300mm(可能不太对),这个等效全画幅焦距需要乘以1.5裁切因子;另一个是尼康Z5 全画幅,镜头好像是24-200。我们交流着如何拍到更具细节、分辨率更高的雪山山体。还调侃脖子上挂着诸多相机,却依然掏出手机拍照的一些网络名场面,哈哈哈
然后我真的拍到了贡嘎雪山的尖尖,虽然没有日照金山那般震撼,但这是贡嘎 7556m 的尖尖,能看到拍到依然非常兴奋。
夜晚汤工在新都桥镇住的民宿,我和我哥决定在呷八乡露营。我换上了SONY FE 35mm F1.8 镜头,架上了三脚架,尝试夜拍一下星空。于是拍到了下面几张照片。
璀璨的星河,真的美丽。
这一张,前景有草,中景有山,背景有银河星星。此行我最喜欢的照片之一。
由于偷懒没带睡袋,夜里在帐篷里通过几个毯子保暖还是不够,一夜蜷缩着双脚,艰难的度过了一晚。谁能知道这时候江浙沪晚上的户外还有34度,和这里比起来就是不开空调无法睡觉。来这里避暑果然还是有点先见的。
昨晚在呷八乡露营,今早有一个大妈牵着马过来问我们是否骑马,被我们婉言拒绝后她图穷匕见,向我们索要20元的露营费🏕️。🤣,没办法我们也只好给了。
今天的计划是打卡一下【塔公草原】、【墨石公园】、【木雅大寺】、【青绕神山】,然后折返直接走318去往泸定,并从泸定上高速回成都。
因为我们的计划是走川西小环线,但是从丹巴县到小金县的路被封了,由于地质灾害造成的道路中断,我们只能绕行北面的317国道,但是这样会增加7个小时的车程,迫于时间上的考量,我们直接放弃了环线后面的内容。真是遗憾,但后会有期。
不是很懂,塔公寺门口这个老人转着手里的这个东西…… 手持转经筒?感受到一种虔诚和坚定,有一点震撼我心。
塔公草原的某一侧。
塔公草原需要20元门票,不建议买票进去。附近太多出片的好地方,没必要花钱进去。
好多马儿,这是可以花钱坐上去然后骑到(被人牵着走)塔公草原景区里的山顶上的。
骏马1
骏马2,白色皮肤版,帅气呀
墨石公园打卡成功。我哥用无人机拍了一些场景,我们又节省了门票和时间。
两张墨石公园航拍。
墨石公园位于中国四川省甘孜藏族自治州道孚县,是一处独特的自然景观区。它因其独特的地质景观和丰富的文化底蕴而备受游客青睐。公园得名于其广泛分布的黑色岩石,这些岩石在阳光照射下泛着淡淡的金属光泽,像极了墨色的画卷。
墨石公园被誉为“中国的天然地质博物馆”,拥有多种地质遗迹和奇特的岩石形态,如石林、石柱、石峰等。它形成于大约1.4亿年前的侏罗纪时期,经历了长期的地质演化和风化作用,使得这一地区的岩石形状各异,充满了自然奇观。
此外,墨石公园还紧邻丰富的人文景观和多样的少数民族文化,您可以在这里欣赏到藏族、羌族和彝族等少数民族的传统文化和习俗。
总体而言,墨石公园结合了壮丽的自然风光和深厚的文化底蕴,是一个值得探索和体验的旅游胜地。
引用内容来自 GPT4
木雅大寺这边还是很震撼的,视野极度广阔,建筑也非常具备特色。
经典——藏民的摩托车,寺庙当中的年轻僧人。
我叫不上名字的雪山一隅。
来到青绕神山,拍到了这张拥有广阔视野的高山草原。
从青绕神山这边看到的雪山应该是雅拉雪山。
随后一直赶路,直到到达成都。晚上还和另外几名同事汇合,我们在成都吃了美美的一顿火锅。
今天计划在成都稍微转一转,下午就启程回合肥了。
准备在成都买一点大熊猫周边,哈哈
你在成都?记得带“熊猫”回来哈!
宽窄巷子附近好多特产店~嘿嘿这也是我第一次来成都🤣
买了三个熊猫周边。可爱捏
今天成都下了超级大的雨。把汤工送回酒店之后我和我哥踏上了归程。从成都收费站上高速。成都,以后再见了。
19:36 左右,路过重庆万州这边。
20:53分穿过隧道到达重庆第一县——云阳县,真是一坐极具三峡特色的县城,以后有空必须再来逛逛。
经过重庆万州的一些省道,路边的村民都拿着蒲扇,围在一起唠家常,我真是很久没有亲眼看到过这样的景象了,只觉得他们的生活非常惬意,虽然平淡但是尽享生活。我们都在城市当牛马,身边除了班味,很少能感受到这样的风土人情。
穿过隧道之后看到如此灯火通明的城市,一瞬间又让我有些感动。有一点绝处逢生的感觉——当你在逆境中待久了,重新回到人类文明集中的世界那种解脱感、安全感。也许最好的生活方式是城市和农村的结合,不能久处城市,更不能久处农村。
今晚夜宿重庆云阳县。
早上从云阳出发回合肥。随意瞥见的长江山城——重庆云阳。
早晨07:14的云阳街头。
吃一份重庆小面再出发。
在加油站旁边拍到的云阳景色。
不愧是重庆第一县城,从新城的建筑看还是蛮繁华的。
经过了白天的不懈赶路,我们在傍晚6点40到达了合肥新桥机场附近。
随后便是顺利抵达合肥,安全完成我们的宜昌 - 重庆 - 川西小环线之旅。虽有遗憾,但见到了许多未曾见识的风景,值也值也。
今天在合肥休息,下午走高速回南京。
全程一共走了4148公里,我用高德 web 制作了全程路书,和实际里程还是蛮吻合的。
本次旅程除了康定-新都桥那天,其余每天都在路上奔波,的确辛苦和疲惫,但就是痛并快乐着。以后类似的旅行,我得花更多的预算,以求一个更加舒服的旅行体验。
感谢阅读。有感兴趣的欢迎在评论区与我讨论。
重要提醒——本文是补档,因为原文 打卡南京市区人防工程纳凉点 访问经常出现问题,原因是所在服务器资源不足。
原视频中的是菠萝山人防工程(鼓楼区广州路229号),这个好像装修不错,具有桌椅还有 wifi。
还记得这个吗?2022-07-11 有个南京同城热搜。我今天去打卡一下南京市区的人防工程纳凉点。
【南京人防工程纳凉点开放至8月底】 同城热度5784 | @江苏新闻
https://s.hellodk.com/2qz3kis0
首条微博直链 https://m.weibo.cn/detail/4789784855450027
截图如下
今天我就试图体验打卡一番。
搜了各个地点,挑选了前两天决定前往。
先去了北极西村,事实上不太好找。
工作人员让我扫了场所码之后我就下阶梯,下了两段楼梯,好家伙,确实好凉快。
工作人员和我说里面有施工🚧️的。可是我没想到,我进去后居然只有我一个市民,其他的都是工人。😂️
等等,这么拉胯?和我在网上看到的不一样呀🤣。。而且这都8月1号了,你7月1号开始整的活,一个月了还是这个进度,有点对不起老百姓了啊。看来我在网上看到的是鸡鸣寺那里的那个,那个还有桌子,还有饮用水之类的,里面的装修也好很多。不过无可厚非,拿来宣传,肯定找最好的。
我放下书包,拿起米家温湿度计 Pro,一开始温度 35.4℃(图片中是35.0,并非一开始的温度),此时下午 4点18。
这里面是真的凉快啊,温度下降的也很快,还有两个工业用的风扇一直吹。4点24的时候温度已经下降到26.3℃了。我决定等到28分,看看十分钟后温度下降到多少。
下午4点28分,温度24.2℃,我已经感觉到冷冷的了😂️,29分时把温度计放回包里表显23.8℃,狠!我书包里还背了 MacBook Pro,我打算来这里上网的,因为网上说还有免费 wifi 🙃️。于是我就出发吧,去鸡鸣寺那个。
这两个人防工程离得不远,骑车不到2公里就到了。
骑车到了这边发现不给进了,写着服务到下午5点。这么热的天不给到9点嘛,你网上是咋宣传的呀,视频里也说的到9点呀,顿生强烈鄙视之感。这个时候不给服务到9点那是啥时候服务到9点。
然后也就没什么好看的了,回吧~~~
这么热的天,还有许多游客来玄武湖、鸡鸣寺游览也是真的勇士。
Allen Hua at 2022-08-01 17 : 55 : 22
第二天下午下了暴雨,但我没灰心,第三天下午又来了。下午的室外确实是无敌的炎热,我选定了菠萝山的人防工程,在高德地图上的 label name 只有 应急掩蔽场所 鼓楼区广州路229号。
骑车到虎踞关
和广州路
的丁字路口,找地方停车然后沿着坡道(广州路)往上走,在一处宾馆前面就能看到标识,进入即可。
进去是个宾馆,纳凉的地方还要继续往里走。扫场所码,老奶奶说没有口罩不给进,但我没带诶,老奶奶有点不情愿得给了我一个新的口罩😁️,谢谢她老人家。
里面确实要好很多哇,有免费的水、wifi、报刊、桌椅,这点有点像话甚至是非常不错了。里面的空间也比北极西村的要大很多。
里面除了我只有一个年轻人,偷看到屏幕好像是在浏览马蜂窝。
人防工程里都没有手机信号,这个有 wifi 真滴蛮不错,离得近的话不论老少皆宜,而且这个开放到晚上9点,给个大大好评💯️。
针不戳。
2024年7月27日,我顶着35度高温天气去拍红山的毛孩子们。
上一次来红山森林动物园是21年。当时有记录下来这样一篇: 南京红山森林动物园附近纪实照片分享
这几年红山动物园真是在网上大火呀,经营状况比起前些年大有改善。就在前天那么炎热的天气下,仍然有很多很多游客前来游玩。替红山森林动物园高兴!
这一次带着刚买不久的腾龙28-200mm 镜头,来试试小长焦拍小动物的效果。来时在小红书做了一下停车攻略,停哪里呢?我选择停在了「十字街」道路两侧,🈶️划车位,并且没有收费,美滋滋。千万不要开车去动物园北门,堵死。开车导航去 【碧玉苑】 或者 【御林山庄】 ,这两个小区门前都有设立道路停车位,费用不记得了,好像是一块钱一小时。
这么热的天气下大爷们在下棋,好一闲情雅致。
门票40元,美团和线下购买同价。
大狮子🦁️。
脑斧。🐅️
这叫什么来着,瘦猫还是啥来着,猫科王国看到的。
这是狐獴,也叫细尾獴。站起来时好有趣。这几张看起来长焦真的好啊,能拍到比画质好更重要,当然了,两者全都要也好,可惜要么价格贵,要么这样的产品还没有开发出来。
动物园内小火车的轨道。
猴山里的吗喽。🐒️😄️
这张好喜欢,抓拍到了,热得我满头大汗。
长颈鹿。🦒
大象。🐘️
国宝大熊猫。🐼️ 哈哈 抓拍了好多张。
吃竹子吃得贼hi
没看到小熊猫~ 天太热啦。
此时快6点了,将要闭园。我是4点进园的,暴走俩小时。什么鸟🦆不知道。
不认识的🦆。
碰到一个大哥,牛逼的很,适马sigma 600mm。忘了问他机身是啥……
可能是适马 SIGMA 150-600mm F5-6.3 DG OS HSM | Contemporary
官方页面: http://www.sigma-photo.com.cn/lenses/overview?id=40 看了一下京东价格,索尼E口是 8499 元,还不错~~~
我看他拍鸟这么有兴致,我也赶紧拉到200mm F5.6 试试看打鸟 🤣
热🥵热。我来得稍微有些晚,像是考拉🐨️馆,16:30就闭馆了。而且很多动物拍不到,因为他们的家都太大了[笑哭],而且有时候躲在人类看不到的角落[旺柴]。
红山对动物,是尊重,是保护,更是爱护。不是把动物放进一个铁笼子或者钢筋混凝土构成的空间,而是精心给他们创造了一个类似他们原本生活地方的家,感谢这么有爱的动物园~
我挑选第一颗变焦镜头有参考很多文章、帖子和视频,写了一篇文章记录挑选过程,2024年7月索尼A7C2的第一颗变焦镜头选择 .
过一两周有计划出门旅行,在综合了诸多方面:价格、焦段实用程度、画质表现、光圈大小、镜头发布年月、二手市场流通性/受欢迎程度等等因素,我还是决定先买腾龙 28-200,原厂的 20-70 F4是一开始的打算,但是在旅游一镜走天下方面,还是200mm 更香。
现在腾龙28-200 京东自营价格还是要 5490,综合考虑之后决定买一个靠谱二手。最后就收到了成色很好的腾龙28-200 ~ 🥳
卖家箱说全,这点很重要。买这种数码类产品,最好原始包装盒保留一下,考虑到未来出二手,会方便一些,也能有一些优势。买家一般优先选那些箱说全的。到货 check 一下……
看不出明显的使用痕迹,很不错了。
下面是我拿出去拍的一些照片。
对于这颗镜头的表现,初步给出印象分8分(满分10分)
这颗镜头官方介绍页 https://www.tamron.com.cn/cameralens/products/a071/index.shtml
总体体验不错,后面拍了新的片子会继续分享。
我现在都在用 squoosh 批量压缩照片。但是 squoosh 压缩出来的图片丢失了 exif 数据,不论是网页还是终端 squoosh-cli。关于使用终端 squoosh-cli 批量压缩图片,你可以阅读我写的 [可能是]最好的压缩图片程序,使用 squoosh-cli 批量压缩图片
关于在得到压缩后的图片不丢失exif元数据这个问题,我尝试了其他压缩工具,比如 tinypng.com 也一样无法实现目的。
tinypng.com 的 web,压缩后的图片无法得到元数据。然后我关注到了其 API,https://tinypng.com/developers/reference/java
我写了段Java代码试了一下,通过调用方法 source.preserve("copyright", "creation", "location");
可以保存元数据
System.out.println("start to tiny your images...");
try {
String path = "c:\\users\\dk\\downloads\\IMG_1989.jpg";
Source source = Tinify.fromFile(path);
String lowercasedPath = path.toLowerCase(Locale.ROOT);
Source sourceWithMetadata;
if (lowercasedPath.endsWith(".jpg") || lowercasedPath.endsWith(".jpeg")) {
//location
sourceWithMetadata = source.preserve("copyright", "creation", "location");
}
else {
sourceWithMetadata = source.preserve("copyright", "creation");
}
sourceWithMetadata.toFile("c:\\users\\dk\\downloads\\IMG_1989-dk-compressed.jpg");
}
catch (IOException e) {
throw new RuntimeException(e);
}
但是经过实践发现只保留下来了图片拍摄时间。我想要的相机信息,镜头信息,拍摄参数(比如快门时间、ISO大小、光圈大小)等还是丢失了。
经过一番研究,我最终转变了思路。 使用 exiftool 工具写入照片的原始exif metadata,我之前居然不知道 exiftool 这么好用的工具。
ExifTool 由 Phil Harvey 开发,是一款免费、跨平台的开源软件,用于读写和处理图像(主要)、音视频和PDF等文件的元数据(metadata)。ExifTool可以作为Perl库(Image::ExifTool)使用,也有功能齐全的命令行版本。ExifTool支持很多类型的元数据,包括Exif、IPTC、XMP、JFIF、GeoTIFF、ICC配置文件、Photoshop IRB、FlashPix、AFCP和ID3,以及众多品牌的数码相机的私有格式的元数据。
本段介绍source
我在 squoosh 容器当中继续操作。
squoosh 容器基于 alpine 镜像制作,所以使用 apk 安装 exiftool 即可。
# apk add exiftool
然后编写一段 shell 脚本。
2024-08-02 19:18:18 新增一些说明
dko0/squoosh:v1.12.0
镜像是支持amd64, arm64 and arm v7 arch这三个架构的,但是只有在 arm64 机器上运行的容器安装了vim之后才能正常运行。在amd64机器上pull了此镜像后启动一个容器然后通过apk安装vim会无法运行,都会报错Segmentation fault (core dumped)
。关于这个问题我检查了很多东西,发现可能是 alpine linux 和不同架构的相关依赖实现的问题/bin/ash
作为 default shell,而且内置的 vi 等命令都是来自 busybox,简体中文不太好支持。所以下面的 shell 我最终改用 /bin/bash
编写。我放在宿主机 debian 执行了apt-get update && apt-get install -y exiftool
安装 exiftool 工具#!/bin/bash
# 检查是否提供了必要的参数
if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: $0 <input_dir> <output_dir>"
exit 1
fi
# 从命令行参数中读取输入目录和输出目录
input_dir="$1"
output_dir="$2"
# 检查输入目录是否存在
if [ ! -d "$input_dir" ]; then
echo "Input directory '$input_dir' does not exist."
exit 1
fi
# 检查输出目录是否存在
if [ ! -d "$output_dir" ]; then
echo "Output directory '$output_dir' does not exist."
exit 1
fi
# 如果 output_dir 以 / 结尾,删除末尾的 /
if [ "${output_dir: -1}" = "/" ]; then
output_dir="${output_dir%/}"
fi
# 定义要处理的文件扩展名
exts=("jpg" "JPG" "jpeg" "JPEG")
# 遍历所有指定文件扩展名的图片文件
for ext in "${exts[@]}"; do
for input_file in "$input_dir"/*."$ext"; do
# 检查文件是否存在
if [ ! -f "$input_file" ]; then
continue
fi
# 提取文件名,不带路径
filename=$(basename "$input_file")
# 构建目标文件路径
output_file="${output_dir}/${filename%.*}-dk-compressed.jpg"
# 检查压缩后的文件是否存在,以防万一
if [ ! -f "$output_file" ]; then
echo "File $output_file does not exist, skipping..."
continue
fi
# 复制 EXIF 元数据
exiftool -TagsFromFile "$input_file" -all:all "$output_file"
echo "$output_file exif metadata write success."
# 删除生成的备份文件(-TagsFromFile 操作会创建一个备份文件)
rm "${output_file}_original"
done
done
将此 shell 文件保存为 /home/dk/copy_exif.sh
使用时的命令:~/copy_exif.sh . ./output/
解释说明:
chmod +x /home/dk/copy_exif.sh
经过 exiftool 写入exif元数据之后,文件会变大一丢丢。通过下面一个case 粗略估计文件体积会增大5%。
可以看到压缩后的照片也具有了元数据了,这对我将文件存放在 immich 里时可以有更好的读写性能,并且在浏览照片时也能看到照片 exif 信息,这对我很重要。
当然具备完整细节的原图还在SD卡/电脑里备份着。
易车销量排行榜页面是 https://car.yiche.com/newcar/salesrank/ ,由于易车 web 端没有提供一页展示多少条数据的功能,所以浏览这个排行榜时就得一页一页的翻,想查某一车型的销量数据很不方便。
但是易车手机app是可以一页展示的,而且也能搜索车型,不过碍于手机屏幕过小,我还是希望在 web 上查看,可以利用 Control + F 功能,更快速的寻找想要的数据。
https://car.yiche.com/newcar/salesrank/
https://car.yiche.com/newcar/salesrank/?page=xxx
当前时间是 2024-07-10 13:47:01,默认展示的是上一个月的数据,也就是2024年6月份的销量排行榜。
如果想抓取2024年5月的数据,请求地址是
https://car.yiche.com/newcar/salesrank/?date=2024-05-01
https://car.yiche.com/newcar/salesrank/?date=2024-05-01&page=xxx
其中 xxx 代表页码。
我抓取了 2024年6月的国内汽车销量数据,生成了一个静态页面。欢迎查阅:2024年6月国内汽车销量排行榜-按车型分
下面是源码
(async () => {
const totalPages = 62; // 一共62页
const fetchDataForPage = async (pageNum) => {
let pageUrl = `https://car.yiche.com/newcar/salesrank/?page=${pageNum}`;
const response = await fetch(pageUrl);
const text = await response.text();
const parser = new DOMParser();
const doc = parser.parseFromString(text, 'text/html');
// 返回整个 div.rk-list-box 元素
return doc.querySelector('div.rk-list-box');
};
// 定义睡眠函数
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
// 获取第一页的数据,并初始化页面
let mainListBox = document.querySelector('div.rk-list-box');
if (!mainListBox) {
console.error('初始化时无法找到 div.rk-list-box 元素');
return;
}
for (let i = 2; i <= totalPages; i++) {
console.log(`正在抓取第 ${i} 页的数据...`);
const pageListBox = await fetchDataForPage(i);
if (pageListBox) {
// 查找并更新所有懒加载图片
const lazyImages = pageListBox.querySelectorAll('.rk-img.lazyload');
lazyImages.forEach(img => {
if (img.dataset.original) {
img.src = img.dataset['original'];
}
});
// 将新页的数据追加到现有的列表中
mainListBox.append(...pageListBox.children);
} else {
console.error(`第 ${i} 页的数据抓取失败`);
}
// 每抓取一页后等待15秒
await sleep(15000); // 15秒
}
console.log('所有数据抓取完毕!');
})();
页面数据抓取完成之后,利用 chrome extension SingleFile
保存成一个 html 文件。
https://github.com/gildas-lormeau/SingleFile
https://chromewebstore.google.com/detail/singlefile/mpiodijhokgodhhofbcjdecpffjipkle
Web Extension for saving a faithful copy of a complete web page in a single HTML file
然后我将这个htm文件托管到了自己的服务器上,尽管这个文件有 44MB,但是加载好之后通过 Control + F 查找车型和销量数据实在是太方便了。
哔哩哔哩观看历史记录的页面地址是 https://www.bilibili.com/account/history
有时候我想分享最近观看的几个视频给朋友,尤其是在我使用关键字搜索之后的列表,会有好几个条目,一个一个打开并复制出一个干净的标题和干净的视频地址太麻烦了。于是我用js写了一段脚本快速获取页面上的视频标题和URL
源码如下
// 使用 querySelectorAll 选择符合路径的 div
const targetDiv = document.querySelector('#history_list');
// 检查 targetDiv 是否存在
if (targetDiv) {
// 在 targetDiv 内选择所有的 li 标签
const liTags = targetDiv.querySelectorAll('li');
let title_url = '';
// 遍历每一个 li 标签,获取其内容
liTags.forEach(liTag => {
const titleA = liTag.querySelector('a.title'); // 获取 class 名称是 title 的那个 a 标签
if (titleA) {
let url = titleA.getAttribute('href'); // 获取链接地址
let title = titleA.textContent;
if (url) {
let originStr = url.trim(); // 原始字符串
url = `https:${originStr.replace(/\?.*$/, '')}`; // 利用正则格式化,前面拼上 https: 顺便把半角问号和后面的字符串都remove掉
title_url += '- ' + title + ' ' + url + '\n'; // 拼接英文减号和空格,再拼上视频标题和空格,最后拼上视频地址
} else {
title_url += '- No title attribute\n'; // 如果没有 title 属性,添加提示
}
}
});
console.log(title_url)
} else {
console.log('无法找到目标 div');
}
Console
标签allow pasting
回车即可。不过B站的web是允许粘贴的举例,我使用富士搜索出如下视频
执行js代码之后快速获取了这些视频的标题和URL
刚好我顺手记录一下这些视频的地址。下面各二级标题就是我使用标题搜出来的结果(基于我最近观看的视频)。不太清楚,B站历史记录的最大条目好像是 1000?(有知道的朋友欢迎留言评论)
ok, that's all.
这几天很喜欢AI陶喆演唱的《泪桥》,陶比特泪目😭️,今天的文章我想用它作bgm,下面请收听
一些说明
https://space.bilibili.com/247308944
火鸡编曲的泪桥 https://www.bilibili.com/video/BV1P4421X79K/
最近长三角地区受副热带高压影响,都是晴好的天气,虽然巨热,但是天空晴朗,空气能见度高。17年毕业季班级出资送了我一个三脚架,但是弄丢了已经,今天自费买一个,哈哈。
依然是选择入门性价比的三脚架产品,不用来干活,不用来吃饭,个人用用玩玩就够了。
在预算100多的条件下,我只留下了两个候选:
优篮子整体设计和用料做工会更好一点,还有白色款,颜值真的高很多。但是现在价格298,查了一下历史低价,也看了B站一些视频的评论区,有些人实付款170就买到了……我现在原价购买就是大冤种。
也查了云腾 VCT-668的历史低价,100,现价118,于是果断入手。
周四晚上23点之前买的,希望周五下午就能到货,只有京东自营做得到了。
下了班之后我直奔蒋王庙,顾不上吃碳水,想着这大热天流汗还能燃脂……
35 36度的天,背着书包+三脚架爬山已经很难了。这些人为了赚点小钱,背着这么多矿泉水在山间各休息点卖,真是好不容易啊。
爬到山顶天完全黑了,为了早些到达山顶我还一路超人,导致周末肌肉酸痛[捂脸]
手持1.3s长曝光。
感觉晚上天空反而没有那么纯净。头陀岭这两个观景台,护栏太高了,人又很多,不太好找机位。凑合拍了几张,感觉还没有小米14 Ultra 拍得好呢。虽然 FE 35mm F1.8 有 F1.8 大光圈,但是手机摄影的夜拍实在是厉害,计算摄影不容小觑。
下面圆拱顶带灯的建筑是岗子村太阳宫,远处的湖是玄武湖,再远处的江是长江。A7C2全画幅 sensor 3300万像素的照片,原图解析力还是很不错的。
下山后我还去了一趟玄武湖,拍了几张,此时大腿和膝盖已经在疼了 [捂脸]
ISO手动指定到了100,画面纯净度没得说,比手机自动模式强。
树上的细节清晰可见,不错。
就拍了这么多,天气实在是太热了,后面天气合适时再战。
我们知道,Docker Desktop 在win上默认存储的路径是 %LOCALAPPDATA%\Docker
,实际存储路径:C:\Users\dk\AppData\Local\Docker
,dk
是你的用户名。
我的C盘还是出厂自带的512G固态,虽然我没有分区,将所有空间都给了C盘,但随着 docker 的使用,Windows创建vhdx后缀的磁盘镜像文件不断扩容,这个文件越来越大,当然还有其他大文件。
使用 WinDirStat 软件分析,我的 Docker 目录占用了 107.4GB,这对 512GB 固态来说有点吃力。很遗憾忘了截图,当时的C盘只剩34GB空闲空间,已经爆红了……
所以我打算 migrate Docker Desktop root storage path for windows...
使用 docker image prune -af
或者 docker system prune
这些方法只能释放一部分空间。
还看到使用压缩镜像的方式减小镜像文件体积的方法。
但使用符号软链接的方式是最优雅的,改动最小,实现起来也最简单,还最能释放空间。
看上图,整体思路
E:\docker_desktop_files
C:\Users\dk\AppData\Local\Docker
下面的所有文件到 E:\docker_desktop_files
C:\Users\dk\AppData\Local
Docker
文件夹为 Docker_bak
,这一举作用有二:让Docker客户端知道 C:\Users\dk\AppData\Local\Docker
路径已不存在;暂时只是重命名文件夹,相当于一个备份,如果后续迁移出现问题,比如无法打开 Docker Desktop,还能改回来mklink /j "C:\Users\dk\AppData\Local\Docker" "E:\docker_desktop_files"
Docker_bak
文件夹,释放了 C 盘很多空间。再次检查 C:\Users\dk\AppData\Local\
,发现生成了一个带有符号链接标志的 Docker
文件夹下面给出上面部分命令的解释
# 使用管理员权限打开一个 cmd 窗口,进入路径 `C:\Users\dk\AppData\Local`
cd C:\Users\dk\AppData\Local\
# 重命名 `Docker` 文件夹为 `Docker_bak`,使用 ren 命令重命名
ren Docker Docker_bak
# 创建符号链接,左边路径是 Docker Desktop 程序默认读取的路径,E:\docker_desktop_files 是软链接过去的路径
mklink /j "C:\Users\dk\AppData\Local\Docker" "E:\docker_desktop_files"
再次打开 Docker Desktop,发现程序和里面的镜像、容器等都正常。通过 rmdir /s /q Docker_bak
强制递归删除原本的 Docker 目录,释放了C盘空间。