-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathatom.xml
More file actions
559 lines (535 loc) · 34.9 KB
/
atom.xml
File metadata and controls
559 lines (535 loc) · 34.9 KB
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<id>https://ambeta.github.io</id>
<title>三土 | AmBeta</title>
<updated>2022-07-21T10:11:56.202Z</updated>
<generator>https://github.com/jpmonette/feed</generator>
<link rel="alternate" href="https://ambeta.github.io"/>
<link rel="self" href="https://ambeta.github.io/atom.xml"/>
<subtitle>一个伪程序猿的自我拉扯</subtitle>
<logo>https://ambeta.github.io/images/avatar.png</logo>
<icon>https://ambeta.github.io/favicon.ico</icon>
<rights>All rights reserved 2022, 三土 | AmBeta</rights>
<entry>
<title type="html"><![CDATA[使用 ZeroTier 实现异地组网]]></title>
<id>https://ambeta.github.io/post/shi-yong-zerotier-shi-xian-yi-di-zu-wang/</id>
<link href="https://ambeta.github.io/post/shi-yong-zerotier-shi-xian-yi-di-zu-wang/">
</link>
<updated>2022-07-21T08:33:47.000Z</updated>
<content type="html"><![CDATA[<p>对于家宽没有公网 IP 的情况,想要访问家里的 NAS 等设备就需要进行内网穿透。开源的 frp、nps 等工具可以方便地实现内网穿透,但目前这些工具的 P2P 穿透能力较差,强烈依赖于服务端的进出口带宽,而 ZeroTier 可以实现内网穿透,由官方提供通讯服务器,并且他对 P2P 穿透的支持性比较强。</p>
<p>关于 ZeroTier 的注册方法网上已经有很多教程,这里不再赘述。</p>
<h1 id="安装-zerotier">安装 ZeroTier</h1>
<p><a href="https://www.zerotier.com/download/">ZeroTier 官网</a>提供了多种平台的客户端下载,可自行下载安装。</p>
<h2 id="路由器-padavanopenwrt">路由器 (Padavan/OpenWRT)</h2>
<p>官网暂时没有提供对应平台的版本,需要使用 opkg 从 Entware 源下载。<br>
最新的软件包可能会有兼容性问题,如果启动时出现如下的警告信息:</p>
<pre><code class="language-shell">WARNING: ioctl() failed setting up Linux tap device (set MAC)
</code></pre>
<p>建议使用 1.4.6 版本,安装脚本如下:</p>
<pre><code class="language-shell">$ opkg install "http://bin.entware.net/mipselsf-k3.4/archive/zerotier_1.4.6-5_mipsel-3.4.ipk"
</code></pre>
<h1 id="启动-zerotier">启动 ZeroTier</h1>
<h2 id="路由器-padavanopenwrt-2">路由器 (Padavan/OpenWRT)</h2>
<pre><code class="language-shell">$ zerotier-one -d
$ zerotier-cli join <YOUER NETWORK ID>
</code></pre>
<h1 id="配置-zerotier-路由">配置 ZeroTier 路由</h1>
<p>在 ZeroTier 创建的网络中添加一条路由记录:</p>
<figure data-type="image" tabindex="1"><img src="https://ambeta.github.io/post-images/1658397826520.png" alt="ZeroTier 路由配置" loading="lazy"></figure>
<p>即将所有对内网网段的访问全部代理到路由器的虚拟网卡上。</p>
<p>设置路由器支持桥接模式:</p>
<figure data-type="image" tabindex="2"><img src="https://ambeta.github.io/post-images/1658398192061.png" alt="开启路由器桥接" loading="lazy"></figure>
<h1 id="配置路由器防火墙规则">配置路由器防火墙规则</h1>
<p>配置防火墙让 ZeroTier 创建的虚拟网卡的流量进入内网,并设置转发规则,从而可以访问内网中的其他机器。<br>
首先查看虚拟网卡的名称:</p>
<pre><code class="language-shell">$ ifconfig
ztklhznki4 Link encap:Ethernet HWaddr 66:BB:BD:04:7C:62
inet addr:10.147.19.163 Bcast:10.147.19.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:2800 Metric:1
RX packets:4659 errors:0 dropped:0 overruns:0 frame:0
TX packets:3150 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:601999 (587.8 KiB) TX bytes:2428690 (2.3 MiB)
</code></pre>
<p>我的虚拟网卡名称为:<code>ztklhznki4</code></p>
<p>配置防火墙规则:</p>
<pre><code class="language-shell">$ iptables -A INPUT -i ztklhznki4 -j ACCEPT
$ iptables -A FORWARD -i ztklhznki4 -j ACCEPT
$ iptables -A FORWARD -o ztklhznki4 -j ACCEPT
$ iptables -t nat -A POSTROUTING -o ztklhznki4 -j MASQUERADE
</code></pre>
<h1 id="reference">Reference</h1>
<ul>
<li><a href="https://www.cnblogs.com/wzcsxjl/p/14883792.html">Padavan安装使用ZeroTier实现组建虚拟局域网的方法 </a></li>
<li><a href="https://www.cnblogs.com/jonnyan/p/14175136.html">zerotier充当网关实现内网互联,访问其它节点内网 </a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[京东无线宝一代64G刷机]]></title>
<id>https://ambeta.github.io/post/jing-dong-wu-xian-bao-yi-dai-64g-shua-ji/</id>
<link href="https://ambeta.github.io/post/jing-dong-wu-xian-bao-yi-dai-64g-shua-ji/">
</link>
<updated>2022-07-08T08:53:06.000Z</updated>
<content type="html"><![CDATA[<h1 id="刷机步骤">刷机步骤</h1>
<ol>
<li>
<p>确认型号为:RE-SP-01B;</p>
</li>
<li>
<p>倒置,撕开2个半周的粘合的胶圈,拧下三颗螺丝,位置:顶部中间,左右稍中下部;</p>
</li>
<li>
<p>上下左右,各有2个卡扣,用硬物撬开或者电吹风吹软弄开;</p>
</li>
<li>
<p>CH341A 或者 Minpro 或者 其它编程器,接入16口的夹具(SOP16转DIP8夹子),找到路由线路板上winbond字样flash;</p>
</li>
<li>
<p>flash上从左到右,左上角为16、15,右上角为10、9,左下角为1、2,右下角为7、8;</p>
</li>
<li>
<p>编程器1、2、3、4、5、6、7、8分别对应:7、8、9、10、15、16、1、2夹好连接好夹具;</p>
</li>
<li>
<p>连接好电脑,识别出编程器,点编程器软件“检测”,识别到芯片为W25Q256,为FFF的是没弄好;(ch341a用1.4最新版的软件)</p>
</li>
<li>
<p>编程器读取,并保存备份原厂编程器固件;</p>
</li>
<li>
<p>编程器打开:breed-mt7621-jd-cloud-1.bin,分别依次点“擦除、写入、检验”。或者直接点“自动”。</p>
</li>
<li>
<p>完成后。拨掉夹具,接入路由电源,路由灯应该亮且不是红包,网线接入路由连接到电脑,访问192.168.1.1;</p>
</li>
<li>
<p>进入breed, <strong>开启环境变量</strong>,位置为“内部”,保存重启。<strong>开启breed保护</strong>,保存重启。(<strong>特别重要</strong>,防止后面格式化64g变砖)</p>
</li>
<li>
<p>刷入固件 JDC-1_3.4.3.9-099.trx</p>
</li>
<li>
<p>进入padavan后,点击服务,启用 Telnet 服务,启用 SSH 服务:</p>
</li>
<li>
<p>操作台 输入fdisk -l 查看分区状况,有个58GB的mmcblk0,如下:<br>
Disk /dev/mtdblock6 doesn't contain a valid partition table<br>
Disk /dev/mmcblk0: 58 GB, 61865984000 bytes, 120832000 sectors<br>
1888000 cylinders, 4 heads, 16 sectors/track<br>
Units: sectors of 1 * 512 = 512 bytes</p>
</li>
<li>
<p>操作台 输入mkfs.ext4/dev/mmcblk0 稍等一会重新刷新,sd状态重新刷新下就出来了</p>
</li>
<li>
<p>如果mac丢失信号很差,就刷eeprom.bin和full.bin</p>
</li>
</ol>
<figure data-type="image" tabindex="1"><img src="https://ambeta.github.io/post-images/1658391934401.jpeg" alt="转换器接线" loading="lazy"></figure>
<figure data-type="image" tabindex="2"><img src="https://ambeta.github.io/post-images/1658391914689.jpeg" alt="连接到电脑" loading="lazy"></figure>
<h1 id="reference">Reference</h1>
<ul>
<li><a href="https://www.right.com.cn/forum/thread-8221140-1-2.html">京东无线宝一代64G拆机编程器刷机并挂载内置64G经验分享,mac地址不丢失</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[在 docker 中使用 puppeteer 生成网页截图 PDF 文档]]></title>
<id>https://ambeta.github.io/post/zai-docker-zhong-shi-yong-puppeteer-sheng-cheng-wang-ye-jie-tu-pdf-wen-dang/</id>
<link href="https://ambeta.github.io/post/zai-docker-zhong-shi-yong-puppeteer-sheng-cheng-wang-ye-jie-tu-pdf-wen-dang/">
</link>
<updated>2022-05-29T06:13:02.000Z</updated>
<content type="html"><![CDATA[<p>之前的网页截图生成 PDF 项目使用的是 <a href="https://github.com/ariya/phantomjs">PhantomJS</a>,由于其目前已停止开发,故切换到 <a href="https://github.com/puppeteer/puppeteer">puppeteer</a>。</p>
<h1 id="运行环境准备">运行环境准备</h1>
<p>关于如何在 docker 中运行 puppeteer,官方文档中有详细说明(@Reference 1),这里仅以在 alpine 环境中运行举例。</p>
<pre><code class="language-dockerfile">FROM alpine
# Replace apk install source for Chinese users.
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
# Installs latest Chromium (100) package.
RUN apk add --no-cache \
chromium \
nss \
freetype \
harfbuzz \
ca-certificates \
ttf-dejavu \
fontconfig \
nodejs \
npm
# Tell Puppeteer to skip installing Chrome. We'll be using the installed package.
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
# Puppeteer v13.5.0 works with Chromium 100.
RUN yarn add puppeteer@13.5.0
# Add user so we don't need --no-sandbox.
RUN addgroup -S pptruser && adduser -S -G pptruser pptruser \
&& mkdir -p /home/pptruser/Downloads /app \
&& chown -R pptruser:pptruser /home/pptruser \
&& chown -R pptruser:pptruser /app
# Run everything after as non-privileged user.
USER pptruser
</code></pre>
<p>这里需要 <strong>注意</strong> 的点:</p>
<ol>
<li>只能够使用 apk 安装的 chromium,puppeteer 内置的脚本安装的 chromium 会有动态链接库不兼容的问题,因此一定要配置好 npm 安装依赖时的环境变量 <code>PUPPETEER_SKIP_CHROMIUM_DOWNLOAD</code> 和运行时的环境变量 <code>PUPPETEER_EXECUTABLE_PATH</code>。</li>
<li>目前通过 apk 安装的 chromium 只支持在 puppeteer@13.5.0 下运行,因此需要检查好安装的 puppeteer 版本。</li>
<li>由于 alpine 中不含字体库,会导致 puppeteer 无法正常渲染文字,故添加 <code>fontconfig</code> 用于安装字体,需要将字体文件放置在 <code>/usr/share/fonts/</code> 目录下。</li>
<li>国内用户使用 apk 安装库时可能会遇到网络问题,故可以切换 apk 源到国内镜像。</li>
</ol>
<h1 id="生成-pdf-示例代码">生成 PDF 示例代码</h1>
<pre><code class="language-typescript">import puppeteer from 'puppeteer';
type Options = puppeteer.PDFOptions & {};
async function genPDF(content: string, options: Options) {
const browser = await puppeteer.launch({
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
// https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#tips
'--disable-dev-shm-usage',
],
});
const page = await browser.newPage();
await page.setContent(content);
const pdfBuffer = await page.pdf(options);
await browser.close();
return pdfBuffer;
}
</code></pre>
<h1 id="reference">Reference</h1>
<ol>
<li><a href="https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-puppeteer-in-docker">running-puppeteer-in-docker</a></li>
<li><a href="https://pptr.dev/#?product=Puppeteer&version=v14.1.1&show=api-pagepdfoptions">puppeteer API reference</a></li>
<li><a href="https://furthergazer.top/article/2020/3/9/7.html">alpine linux 使用国内镜像源进行加速</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/357870388">Alpine镜像的中文支持和字体对比(puppeteer自动截图)</a></li>
<li><a href="https://www.cxyzjd.com/article/zimou5581/101368129">如何给dcoker容器里的alpine系统安装中文字体</a></li>
</ol>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[使用 Time Slice 解决 Long Task 问题]]></title>
<id>https://ambeta.github.io/post/shi-yong-time-slice-jie-jue-long-task-wen-ti/</id>
<link href="https://ambeta.github.io/post/shi-yong-time-slice-jie-jue-long-task-wen-ti/">
</link>
<updated>2021-04-13T09:00:28.000Z</updated>
<content type="html"><![CDATA[<p>前端处理大量数据时经常会遇到页面假死的问题,无法响应任何页面交互,严重影响用户体验。</p>
<p>这是因为 js 是单线程执行的,而浏览器的页面渲染和 js 执行共享同一个主线程,因此一个执行时间过长的 js task 会阻塞主线程,导致页面无法响应。<br>
使用 Chrome devtools 提供的 Performance 工具可以看到相关的提示:</p>
<figure data-type="image" tabindex="1"><img src="https://ambeta.github.io/post-images/1618305639006.png" alt="Long Task - Performance devtool" loading="lazy"></figure>
<p>我们可以通过将一个 long task 切分为多个 short task 的方式,交出主线程的执行权,这种方式也常被称为时间切片(<a href="https://en.wikipedia.org/wiki/Preemption_(computing)#Time_slice">Time Slice</a>)。</p>
<h1 id="demo">Demo</h1>
<pre><code class="language-javascript">const DATA = new Array(5000).fill();
const COSTLY_FUNC = () => {
for (let i = 0; i < 1000; i++) {
document.querySelector('div');
}
};
/**
* @param {function} runFn An iteratee function to be wrapped
* @param {function} cbFn A callback function when all iteratees are called
* @param {number} size Size of each short task
* @return {function} Wrapped iteratee function
*/
function timeSlice(runFn, cbFn, size = 10) {
const self = this;
const nextTick = window.setTimeout;
const queue = [];
const results = [];
let timer = 0;
const run = async () => {
let count = size;
while (count-- && queue.length) {
const args = queue.shift();
results.push(runFn.call(self, ...args));
}
if (queue.length > 0) {
timer = nextTick(run);
} else {
timer = 0;
await Promise.all(results);
cbFn();
}
};
const add = (...args) => {
queue.push([...args]);
if (timer === 0) {
timer = nextTick(run);
}
};
return add;
}
function loop() {
const start = performance.now();
DATA.forEach(() => {
COSTLY_FUNC();
});
console.log(performance.now() - start);
}
function loopWithTimeSlice() {
const start = performance.now();
await new Promise(resolve =>
DATA.forEach(timeSlice(() => {
COSTLY_FUNC();
}, resolve))
);
console.log(performance.now() - start);
}
</code></pre>
<p>如上所示,<code>timeSlice</code> 函数将一个迭代回调包装为一个支持 time slice 的函数,调用该迭代回调时将不再立即调用,而是将其推入调用队列中,并通过 <code>setTimeout</code> 在后续的 task 中依次调用。</p>
<p>使用 Performance 工具 debug 上述 <code>loop</code> 和 <code>loopWithTimeSlice</code> 函数,可以看到 long task 已经被拆分为了多个 task:</p>
<figure data-type="image" tabindex="2"><img src="https://ambeta.github.io/post-images/1618307521553.png" alt="Time Slice" loading="lazy"></figure>
<h1 id="procon">Pro/Con</h1>
<p>使用 Time Slice 的方式可以有效解决页面无响应的问题,但是由于执行权的释放让任务总体的执行时间也变得更长了。上述示例代码中使用 <code>setTimeout</code> 拆分任务,也可以替换使用 <code>requestIdleCallback</code> 进一步降权,但这也会拉长任务的总执行时间。<br>
此外,子任务的大小也是一个需要调优的参数,根据一次迭代的执行时间长短相应地缩小或者扩大子任务中迭代执行的次数(即 <code>timeSlice</code> 函数中的 size 参数)。</p>
<h1 id="conclusion">Conclusion</h1>
<p>Time Slice 并不是唯一的解决方案,也可以使用 Web Worker 将大量计算放在子线程中进行。<br>
Time Slice 也不是通用的解决方案,需要根据情况选用,每种解决方案都有各自的额外开销,需要根据迭代选用适合的方案。</p>
<h1 id="reference">Reference</h1>
<ul>
<li><a href="https://github.com/berwin/time-slicing">berwin/time-slicing</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[从豆丁网下载无水印文档]]></title>
<id>https://ambeta.github.io/post/cong-dou-ding-wang-xia-zai-wu-shui-yin-wen-dang/</id>
<link href="https://ambeta.github.io/post/cong-dou-ding-wang-xia-zai-wu-shui-yin-wen-dang/">
</link>
<updated>2021-03-22T07:44:04.000Z</updated>
<content type="html"><![CDATA[<p>为了找一个基建项目的环评公示,翻遍了各个环保局网站都没有找到,最后只在豆丁网看到了一份,但是下载需要 11RMB,这种本应免费提供的文档需要花钱下载感觉不值,于是就想着破解一下。</p>
<p>通过网页元素检查发现文档预览使用的是 canvas,通过 canvas 转图片可以很方便地导出,但是文档有水印,通过 debug 代码发现水印是通过前端传参控制显隐的,利用 devtools 的 log breakpoint 可以修改运行时代码这一点,将水印显示的参数调整为关闭,文档预览便不再有水印了:></p>
<h1 id="how">How</h1>
<h2 id="step1-修改-js-文件">Step1: 修改 js 文件</h2>
<p>从 <code>Sources</code> 面板打开 <code>js/canvas/jgcw20201019/jgcw-page.js</code> 文件,格式化一下。</p>
<p>跳转到 <code>L1931</code> 行,并添加 log breakpoint 输入 <code>e.watermark = false</code>。</p>
<figure data-type="image" tabindex="1"><img src="https://ambeta.github.io/post-images/1616400763020.png" alt="文件修改-1" loading="lazy"></figure>
<p>继续跳转到 <code>L3993</code> 行,并添加 log breakpoint 输入 <code>Object.assign(this.currentArgs, e)</code>。(这个函数会检查参数是否一致,如果不一致则会触发重新加载进入死循环。)</p>
<figure data-type="image" tabindex="2"><img src="https://ambeta.github.io/post-images/1616400835251.png" alt="文件修改-2" loading="lazy"></figure>
<h2 id="step2-预览文档">Step2: 预览文档</h2>
<p>重新刷新页面会发现预览文档时的水印已经没有了(首页还是有水印,可能首页走的是其他函数渲染的,没有大碍就没管了)。<br>
预览到文档最后一页,使得每一页都渲染出来。</p>
<h2 id="step3-导出文档">Step3: 导出文档</h2>
<p>导出就使用 canvas 转图片保存的方式,需要的话可以再合并为 pdf 文件。<br>
在 <code>Console</code> 面板输入下面的代码,然后就不停地点击保存就可以了:<</p>
<pre><code class="language-js">function downloadImage(data, filename) {
const a = document.createElement('a');
a.href = data;
a.download = filename;
document.body.appendChild(a);
a.click();
}
document.querySelectAll('canvas').forEach((node, index) => {
// if you dont replace you will get a DOM 18 exception.
const data = node..toDataURL("image/png").replace("image/png", "image/octet-stream");
downloadImage(data, `${index}.png`);
});
</code></pre>
<h1 id="blabla">Blabla...</h1>
<p>破解的主要突破口还是预览时是否显示水印是通过前端参数控制,如果是通过调用不同的接口在服务端控制就比较麻烦了。<br>
另外通过 debug 代码发现豆丁网已经用上了 wasm,在代码混淆方面效果还是挺不错的,如果全部都用 wasm 写估计就很难通过 debug 源码的方式发现破绽了。</p>
<h1 id="reference">Reference</h1>
<ul>
<li><a href="https://stackoverflow.com/questions/10673122/how-to-save-canvas-as-an-image-with-canvas-todataurl">Save Canvas As An Image</a></li>
<li><a href="https://apple.stackexchange.com/questions/11163/how-do-i-combine-two-or-more-images-to-get-a-single-pdf-file">How to combine images to a single pdf</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[《武汉日记》方方]]></title>
<id>https://ambeta.github.io/post/lesslesswu-han-ri-ji-greatergreater-fang-fang/</id>
<link href="https://ambeta.github.io/post/lesslesswu-han-ri-ji-greatergreater-fang-fang/">
</link>
<updated>2020-08-03T14:36:21.000Z</updated>
<content type="html"><![CDATA[<p>最近读了疫情期间在网络上吵得很凶的“方方日记”,通篇看下来,觉得文字朴实无华,也清晰真实地记录了武汉疫情封城期间的点滴。日记里面有很多对政府工作的批评,但也充分表达了对官方的信任,都是正常百姓心中所想。</p>
<p>作为一个在当代敢于写文字批评政府的作家,委实感到敬佩。而她六十多岁高龄还受到网络暴力,实在表示心疼,希望她不要过于在意网络上的评论。</p>
<blockquote>
<p>究竟有什么事让他们对一个素未谋面的人、一个他们毫无了解的人有这样意欲大卸八块的刻骨之恨呢?难道他们自小接受的教育不是真与善而是仇与恨?</p>
</blockquote>
<blockquote>
<p>这让人实在无法理解是什么样的动力让他们有这么多仇恨。好像,他们一生都在咬牙切齿。仇恨很多人,仇恨很多事。</p>
</blockquote>
<blockquote>
<p>像隔离病毒一样,与会咬人的群狗隔离,这就是常识。</p>
</blockquote>
<blockquote>
<p>记得我曾经跟某部门的一位负责人说:你们怎么可以让这样一些人去指导学生呢?他们中有的人就是流氓呀。可惜,对方没有听。现在,当年的那些被号召上网展示正能量的人,被指导成今天的他们。</p>
</blockquote>
<p>方方给网络上一个16岁孩子来信的回复:</p>
<blockquote>
<p>我要说,孩子,你写得不错,充满着你那个年龄人的疑惑。你的想法很适合你,你的疑惑是教育你的人给的。但是,我要跟你说的是:我无法解答你的疑惑。<br>
看到你的文字,倒让我想起很多年前我读过的一首诗。这首诗是白桦写的,不知道你有没有听说过他:一个才华横溢的诗人和剧作家哦。<br>
我读这首诗的年龄大约是12岁,这是在1967年的“文革”中。那时,整个武汉的夏天,都在武斗。就在这年,我这个小学五年级学生,得到了白桦的一本诗集,诗集名为:《迎着铁矛散发的传单》。其中第一首诗是《我也有过你们这样的青春》。诗的第一句:“我也有过你们这样的青春,那时的我们就像今天的你们。”我读这首诗时,非常激动,并且永远记下了。<br>
孩子,你说你16岁。我16岁时,是1971年。那时候,如果有人跟我说:“文化大革命是一场浩劫”,我一定会豁出去跟他争个头破血流,而且他就是说三天三夜道理也说服不了我。因为我从11岁起,接受的就是“文化大革命就是好”的教育,到我16岁时,这教育已经进行了五年。用三天三夜的道理来说服我,远远不够。同理,我也不可能解答你的疑惑。我就是说三年,写八本书,恐怕你也不会相信,因为你也有至少像我当年一样的五年。<br>
但是我要告诉你,孩子,你的疑惑迟早会得到解答。而那个答案,是你自己给自己的。十年,或是二十年后,有一天,你会想起来,哦,我那时好幼稚下作呀。因为那时的你,可能已是一个全新的你。当然,如果你走的是一帮极左人士指引的路,你或许就永远没有答案,并且终身挣扎在人生的深渊。<br>
孩子,我还要告诉你:我的16岁时代,比你差远了。我连“独立思考”这样的词都没有听说过。我从来不知道一个人需要独立思考,我的老师说什么就是什么,报纸说什么就是什么,收音机说什么就是什么。11岁开始“文革”,到21岁“文革”结束,这十年,我就是这样成长起来的。我从来没有过自己。因我从来就不是一个独立的人,只是一台机器上的螺丝钉。随着机器运转,机器停,我停,机器动,我动。这状态,大约也像今天的你(而不是你们,因为现今16岁孩子中很多人相当有独立思考能力)。<br>
幸运的是,我的父亲说:他一生最大的理想,就是希望自己的孩子全都能上大学。父亲说那番话的样子我还记得。所以我在当搬运工的时候,一心想实现父亲的遗愿,于是我考上了大学:中国最美丽的武汉大学。<br>
孩子,我经常为自己感到庆幸。虽然我的少年时代接受的尽是愚蠢的教育,但我却在青年时代得以进入大学。我在那里,如饥似渴地学习和阅读,与同学们一起讨论非常有意义的话题,并且开始了我的写作,终于有一天我知道了要独立思考。我还有幸地遇上了改革开放,更有幸参与了整个改革开放的全程。我看到结束“文革”浩劫的中国,从那样落后的状态,一步步强大。可以说,没有改革开放,几乎就没有今天的一切,包括我写这份公开的日记以及你给我写这封公开信的权利。这一点,我们都要庆幸。<br>
孩子,你知道吗?改革开放的前十年,几乎是我自己和自己斗争的十年。我要把过去挤压进我脑子里的垃圾和毒素一点点清理出去。我要装入新的东西,我要尝试用自己的眼光看世界,我要学会用自己的脑子思考问题。当然,学会这些,是建立在自己的成长经历、阅读、观察和努力的基础上。<br>
孩子,我一直以为这种自己与自己的斗争,自己给自己清除垃圾和毒素的事,只会在我这一代人中进行。意想不到的是:你和你的一些同伴,将来也会有这样的日子。那就是,自己与自己斗争,吧少年时代脑子里被灌入的垃圾和毒素,清理出去。这个过程,倒是不痛苦,每清理一次,就是一次解放。一次次的解放,会把一个僵化麻木带着锈迹的螺丝钉,变成一个真正的人。<br>
孩子,你听的懂吗?现在,我要把这一句诗送给你:“我也有过你们这样的青春,那时的我们就像今天的你们。”</p>
</blockquote>
<p><em>文章摘抄自原文,如有侵权请联系删除。</em></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[uni-app 小程序换肤方案]]></title>
<id>https://ambeta.github.io/post/wei-xin-xiao-cheng-xu-huan-fu-fang-an/</id>
<link href="https://ambeta.github.io/post/wei-xin-xiao-cheng-xu-huan-fu-fang-an/">
</link>
<updated>2020-08-03T03:02:53.000Z</updated>
<content type="html"><![CDATA[<p>由于小程序支持 <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/var()">CSS 变量</a>,可以比较方便地实现换肤功能。页面中的动态颜色使用 CSS 变量取值,通过 js 控制内联样式(inlined styles)或切换不同的样式类(css classes),实现 CSS 变量的动态切换,从而达到换肤的目的。</p>
<h1 id="方案实现">方案实现</h1>
<h2 id="step-1-定义-css-变量">Step 1: 定义 CSS 变量</h2>
<p>将 CSS 变量定义在主题的样式类中,并在入口文件中引入:</p>
<pre><code class="language-css">// theme.css
.theme-1 {
--color-primary: red;
}
.theme-2 {
--color-primary: blue;
}
</code></pre>
<h2 id="step-2-引入-css-变量">Step 2: 引入 CSS 变量</h2>
<p>这里使用 i18n 的思路,将每个主题样式类定义为 i18n 中的一个 locale,再引入到每个页面中。</p>
<pre><code class="language-js">// i18n.js
import Vue from 'vue';
import VueI18n from 'vue-i18n';
Vue.use(VueI18n);
const i18n = new VueI18n({
locale: 'vendorA',
messages: {
vendorA: {
theme: {
css: 'theme-1',
},
},
vendorB: {
theme: {
css: 'theme-2',
},
},
},
});
Vue.prototype._i18n = i18n;
export default i18n;
</code></pre>
<pre><code class="language-html"><template>
<view :class="[theme.css, 'page-test']">
</view>
</template>
<script>
export default {
computed: {
theme() {
return this.$t('theme');
},
},
};
</script>
<style>
.page-test {
background-color: var(--color-primary, white);
}
</style>
</code></pre>
<pre><code class="language-js">// main.js
import Vue from 'vue';
import App from './App';
import i18n from './i18n.js';
const app = new Vue({
i18n,
...App,
});
app.$mount();
</code></pre>
<h2 id="step-3-切换-css-变量">Step 3: 切换 CSS 变量</h2>
<p>通过切换 i18n 中定义的不同的 locale 来达到切换皮肤的目的。</p>
<pre><code class="language-html"><template>
<view>
<button @click="handleClick">Click to change!</button>
</view>
</template>
<script>
export default {
method: {
handleClick() {
this._i18n.locale = 'vendorB';
},
},
};
</script>
</code></pre>
<h1 id="参考文档">参考文档</h1>
<ul>
<li><a href="https://segmentfault.com/a/1190000021922132">小程序中使用css var变量,使js可以动态设置css样式属性</a></li>
<li><a href="https://ask.dcloud.net.cn/article/35102">uniapp与vue-i18n实现国际化多语言</a></li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[《道连·葛雷的画像》 上海译文出版社]]></title>
<id>https://ambeta.github.io/post/lesslessdao-lian-ge-lei-de-hua-xiang-greatergreater-shang-hai-yi-wen-chu-ban-she/</id>
<link href="https://ambeta.github.io/post/lesslessdao-lian-ge-lei-de-hua-xiang-greatergreater-shang-hai-yi-wen-chu-ban-she/">
</link>
<updated>2020-07-07T02:51:22.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>你好像忘了我是个已经结婚的人,而结婚的唯一美妙之处,就是双方都绝对需要靠撒谎过日子。</p>
</blockquote>
<blockquote>
<p>女人是一种装饰用的性别。她们从来没有什么要讲的,可讲起来就是娓娓动听。女人代表着物质对精神的胜利,正像男人代表着精神对道德的胜利一样。</p>
</blockquote>
<blockquote>
<p>其实,每一种乐趣和快感可能都含有幸灾乐祸的成分,几乎没有例外。</p>
</blockquote>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[书影随感-序]]></title>
<id>https://ambeta.github.io/post/shu-ying-sui-gan-xu/</id>
<link href="https://ambeta.github.io/post/shu-ying-sui-gan-xu/">
</link>
<updated>2020-07-07T02:09:34.000Z</updated>
<content type="html"><![CDATA[<p>自从开始了每天地铁通勤三小时的生活,我又把八岁高龄的泡面盖 kindle paperwhite 掏了出来,每天上下班路上看看书让痛苦的通勤时间多了一种享受(苦中作乐技能 MAX)。</p>
<p>消遣书籍中,我最爱看的还是偏向于纪实类的小说,就像我喜欢看剧情片一样,贴近现实让我比较能够构想出画面,而合乎情理的戏剧冲突又让我感受到现实生活中没有的魅力。我看书很慢,逐字逐句,在脑中勾画出一帧帧画面,进而组成一个个电影片段。这也是读书吸引我的一个地方,我感觉自己就是一个电影导演。</p>
<p>我很容易沉浸在小说或者电影的世界中,甚至故事结束之后我好些天都无法从那个世界出来,这样我也没办法紧接着去读下一本书或看下一部电影。这样在虚拟世界的弥留之际,不妨把自己的感想记录下来,也算是对那个世界做一个正式的告别,让我更快地可以进入下一个世界。</p>
<p>附图:八岁老 kindle<br>
<img src="https://ambeta.github.io/post-images/1594089890434.jpeg" alt="kindle paperwhite" loading="lazy"></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[4.4全国哀悼日——全(局域)网五十度灰]]></title>
<id>https://ambeta.github.io/post/4-yue-4-ri-quan-guo-ai-dao-ri-quan-wang-wu-shi-du-hui/</id>
<link href="https://ambeta.github.io/post/4-yue-4-ri-quan-guo-ai-dao-ri-quan-wang-wu-shi-du-hui/">
</link>
<updated>2020-04-04T11:55:03.000Z</updated>
<content type="html"><![CDATA[<p>国务院紧急通知清明节当天全国哀悼,各个网站也赶紧实现了全站灰度呈现,一起来看看各大厂都是怎么干的。</p>
<h2 id="淘宝taobaocom">淘宝(taobao.com)</h2>
<figure data-type="image" tabindex="1"><img src="https://ambeta.github.io/post-images/1586001637288.png" alt="50度灰淘宝" loading="lazy"></figure>
<p>淘宝比较直接,直接在 <code>html</code> 根元素上添加了 <code>filter</code> 样式,同时也有对 IE6 的支持:</p>
<pre><code class="language-css">html {
-webkit-filter: grayscale(100%);
filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
}
</code></pre>
<h2 id="百度baiducom">百度(baidu.com)</h2>
<figure data-type="image" tabindex="2"><img src="https://ambeta.github.io/post-images/1586001911862.png" alt="50度灰百度" loading="lazy"></figure>
<p>百度做得更细致一些,直接精确到了对应的 DOM 元素,可以看到网站左上角的空气质量显示仍保留有颜色。<br>
技术实现上也是使用 <code>filter</code> 同时添加了对 IE6 的支持,但用了 postCSS 或类似的 CSS 预处理器,相比于淘宝的实现多了很多的 browser vendor prefix。</p>
<h2 id="腾讯qqcom">腾讯(qq.com)</h2>
<figure data-type="image" tabindex="3"><img src="https://ambeta.github.io/post-images/1586002406191.png" alt="50度灰腾讯" loading="lazy"></figure>
<p>腾讯网在 <code>body</code> 元素上添加了一个 css 样式类 <code>garyBody</code>(grayBody???),同样使用 <code>filter</code> 属性实现灰度变化,但是缺少了对 IE6 的支持。<br>
另一个值得注意的是,body 上的这个样式类是通过 js 动态插入的,所以在网站打开时会有一个从彩色切换到灰色的跳变,并且如果禁用了浏览器脚本执行的话,网站就无法切换到灰色模式了。</p>
<h2 id="京东jdcom">京东(jd.com)</h2>
<figure data-type="image" tabindex="4"><img src="https://ambeta.github.io/post-images/1586002807113.png" alt="50度灰京东" loading="lazy"></figure>
<p>京东也是直接在 <code>html</code> 根元素上添加了相应的样式,所使用的 css 属性与淘宝一致,不过使用的是类名选择器而不是标签选择器。<br>
另外,京东的整个网站是一个单页面应用,并且没有做首屏服务端渲染,所以禁用浏览器脚本的话网站基本无法使用,当然也没法切换到灰度模式:</p>
<figure data-type="image" tabindex="5"><img src="https://ambeta.github.io/post-images/1586003024944.png" alt="禁用脚本后的京东" loading="lazy"></figure>
<h2 id="总结吐槽">总结(吐槽)</h2>
<blockquote>
<p>腾讯的哥们最粗(单词拼错?缺乏IE6支持?)<br>
百度的哥们最细(精确到元素,可能网站结构比较简单吧:))</p>
</blockquote>
<p>花了半个小时的时间写了一篇这么无聊的文章,了解了一个全站变灰的方式以及可能的坑,当然也不希望以后会用到这个技术吧。</p>
]]></content>
</entry>
</feed>