Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
782 lines (690 loc) · 78.1 KB
/
Copy pathindex.html
File metadata and controls
782 lines (690 loc) · 78.1 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
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
<!DOCTYPE html><html lang="zh-Hans" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>守株阁 - 一切都是守株待兔,如切如磋,如琢如磨。I am just joking.</title><meta name="author" content="magicliang"><meta name="copyright" content="magicliang"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="关于技术以及人生">
<meta property="og:type" content="website">
<meta property="og:title" content="守株阁">
<meta property="og:url" content="https://magicliang.github.io/index.html">
<meta property="og:site_name" content="守株阁">
<meta property="og:description" content="关于技术以及人生">
<meta property="og:locale">
<meta property="og:image" content="https://magicliang.github.io/img/rei.jpeg">
<meta property="article:author" content="magicliang">
<meta property="article:tag" content="计算机 文学">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://magicliang.github.io/img/rei.jpeg"><script type="application/ld+json">{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "守株阁",
"alternateName": [
"一切都是守株待兔,如切如磋,如琢如磨。I am just joking.",
"magicliang.github.io"
],
"url": "https://magicliang.github.io/"
}</script><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://magicliang.github.io/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css?v=5.7.0"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@7.3.1/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-snackbar@0.1.16/dist/snackbar.min.css" media="print" onload="this.media='all'"><script>
(() => {
const saveToLocal = {
set: (key, value, ttl) => {
const data = { value }
if (ttl != null) {
data.expiry = Date.now() + ttl * 86400000
}
localStorage.setItem(key, JSON.stringify(data))
},
get: key => {
const itemStr = localStorage.getItem(key)
if (!itemStr) return
try {
const data = JSON.parse(itemStr)
if (data.expiry && Date.now() > data.expiry) {
localStorage.removeItem(key)
return
}
return data.value
} catch {
localStorage.removeItem(key)
}
}
}
const scriptCache = new Map()
const cssCache = new Map()
window.btf = {
saveToLocal,
getScript: (url, attr = {}) => {
if (scriptCache.has(url)) {
return scriptCache.get(url)
}
const promise = new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.async = true
for (const key in attr) {
script.setAttribute(key, attr[key])
}
script.onload = resolve
script.onerror = reject
document.head.appendChild(script)
})
scriptCache.set(url, promise)
return promise
},
getCSS: (url, id) => {
if (cssCache.has(url)) {
return cssCache.get(url)
}
const promise = new Promise((resolve, reject) => {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = url
if (id) {
link.id = id
}
link.onload = resolve
link.onerror = reject
document.head.appendChild(link)
})
cssCache.set(url, promise)
return promise
},
addGlobalFn: (key, fn, name = false, parent = window) => {
if (!true && key.startsWith('pjax')) return
const globalFn = parent.globalFn || {}
globalFn[key] = globalFn[key] || {}
globalFn[key][name || Object.keys(globalFn[key]).length] = fn
parent.globalFn = globalFn
}
}
const metaThemeColor = document.querySelector('meta[name="theme-color"]')
const activateDarkMode = () => {
document.documentElement.dataset.theme = 'dark'
if (metaThemeColor !== null) {
metaThemeColor.setAttribute('content', 'undefined')
}
}
const activateLightMode = () => {
document.documentElement.dataset.theme = 'light'
if (metaThemeColor !== null) {
metaThemeColor.setAttribute('content', 'undefined')
}
}
btf.activateDarkMode = activateDarkMode
btf.activateLightMode = activateLightMode
const theme = saveToLocal.get('theme')
theme === 'dark' ? activateDarkMode() : theme === 'light' ? activateLightMode() : null
const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
document.documentElement.classList.toggle('hide-aside', asideStatus === 'hide')
}
const detectApple = () => {
if (/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)) {
document.documentElement.classList.add('apple')
}
}
detectApple()
})()
</script><script>const GLOBAL_CONFIG = {
root: '/',
algolia: undefined,
localSearch: {"path":"/search.json","preload":false,"top_n_per_article":1,"unescape":false,"pagination":{"enable":false,"hitsPerPage":8},"languages":{"hits_empty":"No results found for: ${query}","hits_stats":"${hits} articles found"}},
translate: {"defaultEncoding":1,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"簡"},
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false,"highlightFullpage":false,"highlightMacStyle":true},
copy: {
success: 'Copy Successful',
error: 'Copy Failed',
noSupport: 'Browser Not Supported'
},
relativeDate: {
homepage: true,
post: true
},
runtime: '',
dateSuffix: {
just: 'Just now',
min: 'minutes ago',
hour: 'hours ago',
day: 'days ago',
month: 'months ago'
},
copyright: {"limitCount":50,"languages":{"author":"Author: magicliang","link":"Link: ","source":"Source: 守株阁","info":"Copyright belongs to the author. For commercial use, please contact the author for authorization. For non-commercial use, please indicate the source."}},
lightbox: 'null',
Snackbar: {"chs_to_cht":"You have switched to Traditional Chinese","cht_to_chs":"You have switched to Simplified Chinese","day_to_night":"You have switched to Dark Mode","night_to_day":"You have switched to Light Mode","bgLight":"#49b1f5","bgDark":"#2d3035","position":"bottom-left"},
infinitegrid: {
js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid@4.13.0/dist/infinitegrid.min.js',
buttonText: 'Load More'
},
isPhotoFigcaption: true,
islazyloadPlugin: true,
isAnchor: false,
percent: {
toc: true,
rightside: true,
},
autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
title: '守株阁',
isHighlightShrink: false,
isToc: false,
pageType: 'home'
}</script><meta name="generator" content="Hexo 8.1.2"><link rel="alternate" href="/atom.xml" title="守株阁" type="application/atom+xml">
<link href="https://cdn.bootcss.com/KaTeX/0.11.1/katex.min.css" rel="stylesheet" /></head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><div class="spinner-box"><div class="configure-border-1"><div class="configure-core"></div></div><div class="configure-border-2"><div class="configure-core"></div></div><div class="loading-word">Loading...</div></div></div><script>(()=>{
const $loadingBox = document.getElementById('loading-box')
const $body = document.body
const preloader = {
endLoading: () => {
if ($loadingBox.classList.contains('loaded')) return
$body.style.overflow = ''
$loadingBox.classList.add('loaded')
},
initLoading: () => {
$body.style.overflow = 'hidden'
$loadingBox.classList.remove('loaded')
}
}
preloader.initLoading()
if (document.readyState === 'complete') {
preloader.endLoading()
} else {
window.addEventListener('load', preloader.endLoading)
document.addEventListener('DOMContentLoaded', preloader.endLoading)
// Add timeout protection: force end after 7 seconds
setTimeout(preloader.endLoading, 7000)
}
if (true) {
btf.addGlobalFn('pjaxSend', preloader.initLoading, 'preloader_init')
btf.addGlobalFn('pjaxComplete', preloader.endLoading, 'preloader_end')
}
})()</script><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img text-center"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/rei.jpeg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data text-center"><a href="/archives/"><div class="headline">Articles</div><div class="length-num">2143</div></a><a href="/tags/"><div class="headline">Tags</div><div class="length-num">2145</div></a><a href="/categories/"><div class="headline">Categories</div><div class="length-num">40</div></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> Home</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> Archives</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> Tags</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> Categories</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> About</span></a></div></div></div></div><div class="page" id="body-wrap"><header class="full_page" id="page-header" style="background-image: url(/img/eva-wallpaper.jpg);"><nav id="nav"><span id="blog-info"><a class="nav-site-title" href="/"><span class="site-name">守株阁</span></a></span><div id="menus"><div id="search-button"><span class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> Search</span></span></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> Home</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> Archives</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> Tags</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> Categories</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> About</span></a></div></div><div id="toggle-menu"><span class="site-page"><i class="fas fa-bars fa-fw"></i></span></div></div></nav><div id="site-info"><h1 id="site-title">守株阁</h1><div id="site-subtitle"><span id="subtitle"></span></div><div id="site_social_icons"><a class="social-icon" href="https://github.com/magicliang" target="_blank" title="Github"><i class="fab fa-github"></i></a><a class="social-icon" href="mailto:magicliang@qq.com" target="_blank" title="Email"><i class="fas fa-envelope"></i></a></div></div><div id="scroll-down"><i class="fas fa-angle-down scroll-down-effects"></i></div></header><main class="layout" id="content-inner"><div class="recent-posts nc" id="recent-posts"><div class="recent-post-items"><div class="recent-post-item"><div class="post_cover left"><a href="/east-europe-15/" title="东欧剧变 15:为什么旧秩序瓦解以后,欧洲仍未获得共同安全"><img class="post-bg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-35.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 15:为什么旧秩序瓦解以后,欧洲仍未获得共同安全"></a></div><div class="recent-post-info"><a class="article-title" href="/east-europe-15/" title="东欧剧变 15:为什么旧秩序瓦解以后,欧洲仍未获得共同安全">东欧剧变 15:为什么旧秩序瓦解以后,欧洲仍未获得共同安全</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time class="post-meta-date-created" datetime="2026-10-23T00:15:00.000Z" title="Created 2026-10-23 08:15:00">2026-10-23</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">Updated</span><time class="post-meta-date-updated" datetime="2026-10-26T06:36:44.934Z" title="Updated 2026-10-26 14:36:44">2026-10-26</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E5%8E%86%E5%8F%B2/">历史</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E5%8E%86%E5%8F%B2/">历史</a><span class="article-meta-link">•</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E4%B8%9C%E6%AC%A7%E5%89%A7%E5%8F%98/">东欧剧变</a></span></div><div class="content">系列目录 · 上一篇:普通人的转型十年 1989 年发生的不是一次由同一机关指挥、具有同一目标的革命。波兰的谈判、匈牙利的党内改革、东德的出走与示威、捷克斯洛伐克的群众动员、罗马尼亚的暴力决裂,改变政权的方式不同。苏联到 1991 年才终结,南斯拉夫则沿着另一套联邦危机进入战争。把这些变化统称为“东欧剧变”,有助于看见共同的时代条件,也容易把必须解释的差异提前抹去。 到 1999 年,旧集团体系已经消失,一些国家建立了能够轮替的政府,另一些地方仍由战争、贫困或行政权力决定政治竞争。欧洲出现了扩大中的制度共同体,也出现了未能进入这一共同体的安全焦虑。解释这一段历史,需要分别回答旧政权为什么失去维持能力、国家为什么解体、改革为什么产生不同分配结果,以及国际秩序为什么没有沿着一份共同认可的设计图重建。 经济困难提供压力,却没有规定政权更替的日期 经济解释的力量在于,它能说明为什么既有统治交易越来越难继续。以充分就业、物价稳定、住房和社会保障换取政治服从的制度,必须持续提供这些东西。短缺、外债、技术差距和增长放缓,使执政者既难增加消费,也难维持投资;改变价格和企业约束又会伤害依赖旧安排的...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/east-europe-14/" title="东欧剧变 14:普通人的转型十年,1989—1999"><img class="post-bg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-14.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 14:普通人的转型十年,1989—1999"></a></div><div class="recent-post-info"><a class="article-title" href="/east-europe-14/" title="东欧剧变 14:普通人的转型十年,1989—1999">东欧剧变 14:普通人的转型十年,1989—1999</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time class="post-meta-date-created" datetime="2026-10-23T00:14:00.000Z" title="Created 2026-10-23 08:14:00">2026-10-23</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">Updated</span><time class="post-meta-date-updated" datetime="2026-10-26T06:36:44.934Z" title="Updated 2026-10-26 14:36:44">2026-10-26</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E5%8E%86%E5%8F%B2/">历史</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E5%8E%86%E5%8F%B2/">历史</a><span class="article-meta-link">•</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E4%B8%9C%E6%AC%A7%E5%89%A7%E5%8F%98/">东欧剧变</a></span></div><div class="content">系列目录 · 上一篇:南斯拉夫的不同战区 · 下一篇:共同条件与国际后果 制度更替使许多人获得迁徙、表达、经营和选择政府的权利,也使另一些人失去稳定职业、积蓄和原有公共服务。两类变化经常发生在同一个家庭。一个人可以支持结束一党统治,同时反对所在工厂关闭;可以从商品供应改善中获益,同时无法承受住房和医疗支出。1989—1999 年的社会后果,应沿着家庭收入、财产、劳动、照护和政治权利分别观察。 转型的代价真实存在,但并非各国接受了同一套政策而得到同一种结果。国家是否继续存在、是否发生战争、旧产业如何组织、政府能否征税和支付、外国市场是否开放,都影响改革政策的作用。比较普通人的生活,首先需要防止把这些条件全部藏进“转型”这个词里。 货架丰富了,为什么生活仍可能更难 旧制度下,官方价格不一定代表取得商品的实际成本。排队、凭关系购买、配给、等待住房,以及质量和选择受限,都占用时间或限制生活。价格放开后,一些短缺迅速缓解,市场上可以买到更多商品,但这并不等于原来的购买者都买得起。此前以等待时间承担的成本,部分转为货币支出;拥有现金、外汇或稳定收入的人更容易适应。 因此,不能仅用商店照片判断...</div></div></div><div class="recent-post-item"><div class="post_cover left"><a href="/east-europe-13/" title="东欧剧变 13:南斯拉夫各战区为什么走向不同结局"><img class="post-bg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-38.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 13:南斯拉夫各战区为什么走向不同结局"></a></div><div class="recent-post-info"><a class="article-title" href="/east-europe-13/" title="东欧剧变 13:南斯拉夫各战区为什么走向不同结局">东欧剧变 13:南斯拉夫各战区为什么走向不同结局</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time class="post-meta-date-created" datetime="2026-10-23T00:13:00.000Z" title="Created 2026-10-23 08:13:00">2026-10-23</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">Updated</span><time class="post-meta-date-updated" datetime="2026-10-26T06:36:44.933Z" title="Updated 2026-10-26 14:36:44">2026-10-26</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E5%8E%86%E5%8F%B2/">历史</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E5%8E%86%E5%8F%B2/">历史</a><span class="article-meta-link">•</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E4%B8%9C%E6%AC%A7%E5%89%A7%E5%8F%98/">东欧剧变</a></span></div><div class="content">系列目录 · 上一篇:从联邦危机走向战争 · 下一篇:普通人的转型十年 1991—1995 年的南斯拉夫战争不能按一条战线叙述。斯洛文尼亚经历短期交战,克罗地亚经历持续数年的占领与反攻,波斯尼亚和黑塞哥维那经历围城、地方夺权、驱逐和大规模屠杀,马其顿则通过谈判脱离联邦。共同国家解体使政治归属成为争议,暴力程度却取决于另一组条件:谁要控制哪些土地,居民怎样混居,武装从哪里取得装备,边界之外的力量愿意支持多久。 这里的“民族清洗”指以暴力和恐吓迫使某群体离开特定地区的政策或实践,不是一个可以替代具体罪名的万能法律标签。驱逐、迫害、杀人、酷刑和种族灭绝有各自的构成要件。判断责任时,需要区分执行者、命令者、提供帮助者、负有制止义务者,以及不参与这些行动的普通居民。 斯洛文尼亚:有限目标使停战成为可能 1991 年 6 月 25 日斯洛文尼亚宣布独立,随后接管边境等国家职能。联邦当局试图恢复边境和海关控制,人民军从本地与克罗地亚境内驻地出动装甲部队。斯洛文尼亚政府依靠领土防御部队和警察阻截交通、包围营区、控制信息与补给。坦克在公路上出现并不等于掌握周围地区;道路障碍、地方地形和补给中断,使...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/east-europe-12/" title="东欧剧变 12:南斯拉夫怎样从联邦危机走向战争"><img class="post-bg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-21.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 12:南斯拉夫怎样从联邦危机走向战争"></a></div><div class="recent-post-info"><a class="article-title" href="/east-europe-12/" title="东欧剧变 12:南斯拉夫怎样从联邦危机走向战争">东欧剧变 12:南斯拉夫怎样从联邦危机走向战争</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time class="post-meta-date-created" datetime="2026-10-23T00:12:00.000Z" title="Created 2026-10-23 08:12:00">2026-10-23</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">Updated</span><time class="post-meta-date-updated" datetime="2026-10-26T06:36:44.931Z" title="Updated 2026-10-26 14:36:44">2026-10-26</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E5%8E%86%E5%8F%B2/">历史</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E5%8E%86%E5%8F%B2/">历史</a><span class="article-meta-link">•</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E4%B8%9C%E6%AC%A7%E5%89%A7%E5%8F%98/">东欧剧变</a></span></div><div class="content">系列目录 · 上一篇:苏联的最后几个月 · 下一篇:不同战区的战争与和平 1980 年铁托去世时,南斯拉夫仍有共同的政府、货币、军队和执政党。到 1991 年夏天,共和国已经各自决定政治前途,地方警察拒绝另一层政府的命令,原本保卫同一个国家的武装开始交战。十一年间,争执逐步改变了命令由谁执行、资金由谁筹集,以及居民向谁寻求保护。 经济危机降低了妥协收益,联邦制度使共和国能够组织不同方案,民族动员将分配争议变成了安全问题。但战争还需要更具体的一步:政治领导人建立或接管武装,以控制土地和人口来决定争议的结果。斯洛文尼亚短暂交战后脱离,克罗地亚却陷入持续战争,已经说明“多民族国家遇到经济危机”不足以解释结局。 一个不属于苏联集团的社会主义联邦 南斯拉夫社会主义联邦共和国由斯洛文尼亚、克罗地亚、波斯尼亚和黑塞哥维那、塞尔维亚、黑山、马其顿六个共和国组成。科索沃和伏伊伏丁那是塞尔维亚境内的自治省,在 1974 年宪制下又直接参与若干联邦机构。这里的“共和国”是具有议会、政府、党组织和行政系统的政治单位,并不意味着境内只有一种民族身份。尤其在波黑、克罗地亚和塞尔维亚,民族分布与共和国边界没有...</div></div></div><div class="recent-post-item"><div class="post_cover left"><a href="/east-europe-11/" title="东欧剧变 11:1991年最后几个月,从八月事件到苏联终结"><img class="post-bg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-62.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 11:1991年最后几个月,从八月事件到苏联终结"></a></div><div class="recent-post-info"><a class="article-title" href="/east-europe-11/" title="东欧剧变 11:1991年最后几个月,从八月事件到苏联终结">东欧剧变 11:1991年最后几个月,从八月事件到苏联终结</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time class="post-meta-date-created" datetime="2026-10-23T00:11:00.000Z" title="Created 2026-10-23 08:11:00">2026-10-23</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">Updated</span><time class="post-meta-date-updated" datetime="2026-10-26T06:36:44.931Z" title="Updated 2026-10-26 14:36:44">2026-10-26</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E5%8E%86%E5%8F%B2/">历史</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E5%8E%86%E5%8F%B2/">历史</a><span class="article-meta-link">•</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E8%8B%8F%E8%81%94/">苏联</a><span class="article-meta-link">•</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E4%B8%9C%E6%AC%A7%E5%89%A7%E5%8F%98/">东欧剧变</a></span></div><div class="content">系列导读 · 上一篇:苏联中央与共和国 · 下一篇:南斯拉夫的联邦危机 1991年8月,苏联的一批最高官员试图以紧急状态阻止中央权力继续流失。四个月以后,联盟总统辞职,联盟的议会机构确认苏联停止存在。两者之间不是一次军事行动失败后自动发生的连锁反应。俄罗斯接管联盟资源、各共和国独立、重建联盟的谈判、乌克兰公投和独联体协议,各自改变了下一轮选择的条件。 八月事件加速了解体,因为它同时破坏了两种信用:联盟中央无法保证改革不被军警机关推翻,强硬派也无法证明自己有能力恢复统一命令。共和国领导人既有理由摆脱这种风险,又拥有议会、政府、财政和本地干部来承接权力。但直到11月,保留共同国家的方案仍在讨论。解释苏联终结,必须追踪这些方案怎样失去参加者和执行资源,不能只寻找最后签字的三个人。 从保卫联盟的名义到隔离联盟总统 准备于8月20日开始签署的新联盟条约,将进一步限制原有中央机构的权限。对克格勃主席弗拉基米尔·克留奇科夫、国防部长德米特里·亚佐夫等人而言,国家分散、经济失序与自身机构的地位下降相互交织。不能把所有参与者的动机简化为保住职位;也不能因为他们公开声称保卫国家,就把其行动当作已经...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/east-europe-10/" title="东欧剧变 10:苏联中央与共和国,一个联盟怎样失去共同规则"><img class="post-bg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-174.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 10:苏联中央与共和国,一个联盟怎样失去共同规则"></a></div><div class="recent-post-info"><a class="article-title" href="/east-europe-10/" title="东欧剧变 10:苏联中央与共和国,一个联盟怎样失去共同规则">东欧剧变 10:苏联中央与共和国,一个联盟怎样失去共同规则</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time class="post-meta-date-created" datetime="2026-10-23T00:10:00.000Z" title="Created 2026-10-23 08:10:00">2026-10-23</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">Updated</span><time class="post-meta-date-updated" datetime="2026-10-26T06:36:44.929Z" title="Updated 2026-10-26 14:36:44">2026-10-26</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E5%8E%86%E5%8F%B2/">历史</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E5%8E%86%E5%8F%B2/">历史</a><span class="article-meta-link">•</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E8%8B%8F%E8%81%94/">苏联</a><span class="article-meta-link">•</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E4%B8%9C%E6%AC%A7%E5%89%A7%E5%8F%98/">东欧剧变</a></span></div><div class="content">系列导读 · 上一篇:保加利亚与阿尔巴尼亚 · 下一篇:1991年最后几个月 1988年至1991年夏,苏联的关键变化,是不同政治机构开始对同一批土地、企业、税款和居民提出互不相容的管辖要求。共和国宣布“主权”,有时意味着要求重新分配联盟内部的权力,有时意味着准备独立,还有些地方要求恢复被吞并以前的国家。只看宣言中的同一个词,会把不同的政治工程误当成同步发生的分离运动。 苏联最终解体,不能只用边缘地区反抗莫斯科解释。俄罗斯共和国也在莫斯科建立了与联盟总统竞争的权力中心。原来由苏共组织、中央计划和统一财政共同维持的等级关系逐渐失效,新的议会、总统和选举却同时提供了彼此竞争的授权。1991年八月以前,各方仍有重建联盟的真实谈判;它的困难在于,准备签约的人对共同国家应当拥有多少权力并没有同一种理解。 联邦宪法为什么既能维持统一,也能成为争权依据 1977年苏联宪法把苏联规定为统一的多民族联邦国家,同时保留加盟共和国自由退出的权利。第73条列举联盟层面的经济计划、预算、国防和边界等权限,第74条规定发生冲突时联盟法律优先;共和国则有自己的宪法、最高苏维埃和政府。第78条还规定,未经共和...</div></div></div><div class="recent-post-item"><div class="post_cover left"><a href="/east-europe-09/" title="东欧剧变 09:保加利亚与阿尔巴尼亚,两条迟缓而曲折的转型道路"><img class="post-bg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-155.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 09:保加利亚与阿尔巴尼亚,两条迟缓而曲折的转型道路"></a></div><div class="recent-post-info"><a class="article-title" href="/east-europe-09/" title="东欧剧变 09:保加利亚与阿尔巴尼亚,两条迟缓而曲折的转型道路">东欧剧变 09:保加利亚与阿尔巴尼亚,两条迟缓而曲折的转型道路</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time class="post-meta-date-created" datetime="2026-10-23T00:09:00.000Z" title="Created 2026-10-23 08:09:00">2026-10-23</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">Updated</span><time class="post-meta-date-updated" datetime="2026-10-26T06:36:44.928Z" title="Updated 2026-10-26 14:36:44">2026-10-26</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E5%8E%86%E5%8F%B2/">历史</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E5%8E%86%E5%8F%B2/">历史</a><span class="article-meta-link">•</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E4%B8%9C%E6%AC%A7%E5%89%A7%E5%8F%98/">东欧剧变</a></span></div><div class="content">系列目录 · 上一篇:罗马尼亚 · 下一篇:苏联中央与共和国 柏林墙开放的第二天,保加利亚共产党中央全会撤换了托多尔·日夫科夫。这个时间上的相邻,很容易给人一种错觉:德国边界一开,另一国政权便随之倒下。实际上,保加利亚发生的首先是执政党内部的领导权更替;多党竞争、制宪和反对派执政,还要经过两年的组织与冲突。 阿尔巴尼亚的转折更晚。其他东欧国家已经举行竞争性选举时,拉米兹·阿利雅仍试图把改革限制在劳动党主导的框架内。1990 年底允许独立政党成立,1991 年春劳动党却在首次多党选举中获胜,直到 1992 年民主党才取得执政权。允许竞争、旧党落选和民主制度稳定,显然不是同一个时刻。 两国可以放在一起比较,但不能用“巴尔干落后”代替解释。保加利亚的苏联联系、少数族群问题和党内改革条件,与阿尔巴尼亚长期孤立、宗教压制和极低开放程度不同。它们各自的转折,都需要从具体的政治行动与制度安排中理解。 保加利亚:危机先于日夫科夫下台 日夫科夫长期维持对苏联的密切依赖,利用党政干部体系管理工业、农业与社会组织。到八十年代后期,外债、经济效率和供给问题加重,戈尔巴乔夫改革又改变了原来可以依靠的政治环...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/east-europe-08/" title="东欧剧变 08:罗马尼亚,革命中的枪声与革命后的权力"><img class="post-bg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-157.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 08:罗马尼亚,革命中的枪声与革命后的权力"></a></div><div class="recent-post-info"><a class="article-title" href="/east-europe-08/" title="东欧剧变 08:罗马尼亚,革命中的枪声与革命后的权力">东欧剧变 08:罗马尼亚,革命中的枪声与革命后的权力</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time class="post-meta-date-created" datetime="2026-10-23T00:08:00.000Z" title="Created 2026-10-23 08:08:00">2026-10-23</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">Updated</span><time class="post-meta-date-updated" datetime="2026-10-26T06:36:44.928Z" title="Updated 2026-10-26 14:36:44">2026-10-26</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E5%8E%86%E5%8F%B2/">历史</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E5%8E%86%E5%8F%B2/">历史</a><span class="article-meta-link">•</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E4%B8%9C%E6%AC%A7%E5%89%A7%E5%8F%98/">东欧剧变</a></span></div><div class="content">系列目录 · 上一篇:捷克斯洛伐克 · 下一篇:保加利亚与阿尔巴尼亚 1989 年 12 月 22 日中午,齐奥塞斯库乘直升机离开布加勒斯特的党中央大楼。这个镜头通常被当作罗马尼亚革命的终点,但伤亡最难解释的一部分发生在他出逃以后。军队宣布站到人民一边,电视台播报革命胜利,同时又反复呼吁保卫革命、防御不明身份的“恐怖分子”。街头平民、临时武装人员和不同部队开始在彼此无法可靠辨识的情况下开火。 三天后,齐奥塞斯库夫妇经过仓促的军事审判被处决。个人统治已经结束,谁能够代表革命、怎样追究枪杀责任、旧干部能否以新组织继续执政,却都没有随之解决。理解这场转折,需要分别追踪地方抗议如何成为全国起义、军政机关怎样改变服从对象,以及救国阵线怎样把临时接管转化为选举与宪法中的权力。 紧缩政策把工厂中的不满推到了街头 罗马尼亚的危机并非突然产生于 1989 年冬天。齐奥塞斯库在外交上长期强调相对苏联的自主性,国内却建立了高度集中的个人统治。到了八十年代,偿还外债成为压倒其他目标的政策任务。出口、能源分配和进口压缩影响食品、取暖、照明与工业生产;国家宣称取得的经济成就,与居民排队和日常短缺之间形成尖锐...</div></div></div><div class="recent-post-item"><div class="post_cover left"><a href="/east-europe-07/" title="东欧剧变 07:捷克斯洛伐克,从政权更替到联邦分离"><img class="post-bg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-18.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 07:捷克斯洛伐克,从政权更替到联邦分离"></a></div><div class="recent-post-info"><a class="article-title" href="/east-europe-07/" title="东欧剧变 07:捷克斯洛伐克,从政权更替到联邦分离">东欧剧变 07:捷克斯洛伐克,从政权更替到联邦分离</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time class="post-meta-date-created" datetime="2026-10-23T00:07:00.000Z" title="Created 2026-10-23 08:07:00">2026-10-23</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">Updated</span><time class="post-meta-date-updated" datetime="2026-10-26T06:36:44.928Z" title="Updated 2026-10-26 14:36:44">2026-10-26</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E5%8E%86%E5%8F%B2/">历史</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E5%8E%86%E5%8F%B2/">历史</a><span class="article-meta-link">•</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E4%B8%9C%E6%AC%A7%E5%89%A7%E5%8F%98/">东欧剧变</a></span></div><div class="content">系列目录 · 上一篇:德国统一 · 下一篇:罗马尼亚 1989 年 11 月,捷克斯洛伐克的示威、罢工与谈判结束了共产党的政治垄断。1993 年 1 月 1 日,捷克共和国与斯洛伐克共和国成为两个独立国家。两件事之间隔着三年的选举、经济改革和宪制争议。共产党下台时,没有一份共同纲领要求国家必须解体;联邦最后终止,也不是一次全民公投的结果。 1989 年的变化建立了公开政治竞争,1968 年以后长期被统一党权压住的共和国关系由此进入真正的讨价还价。1992 年选举在两地分别产生了主张不同国家安排和经济政策的领先政治集团。主要执政精英最后接受分离,联邦议会通过宪法性法律完成程序。这条路径能够解释国家怎样和平分开,却不能证明所有居民都愿意分开,更不能把没有战争视为没有民主争议。 “正常化”之后的政治空间 1968 年华约入侵及随后“正常化”留下了两项不同的遗产。改革派被清除,社会组织受到压制,许多人退出公开政治;与此同时,捷克斯洛伐克自 1969 年起成为由捷克与斯洛伐克两个共和国组成的联邦。共和国议会和政府拥有法律形式,实际决策却仍受统一的共产党体系约束。名义上的联邦协商与实际上的...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/east-europe-06/" title="东欧剧变 06:从东德危机到德国统一"><img class="post-bg" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-34.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 06:从东德危机到德国统一"></a></div><div class="recent-post-info"><a class="article-title" href="/east-europe-06/" title="东欧剧变 06:从东德危机到德国统一">东欧剧变 06:从东德危机到德国统一</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">Created</span><time class="post-meta-date-created" datetime="2026-10-23T00:06:00.000Z" title="Created 2026-10-23 08:06:00">2026-10-23</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">Updated</span><time class="post-meta-date-updated" datetime="2026-10-26T06:36:44.928Z" title="Updated 2026-10-26 14:36:44">2026-10-26</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E5%8E%86%E5%8F%B2/">历史</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E5%8E%86%E5%8F%B2/">历史</a><span class="article-meta-link">•</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E4%B8%9C%E6%AC%A7%E5%89%A7%E5%8F%98/">东欧剧变</a></span></div><div class="content">系列目录 · 上一篇:匈牙利 · 下一篇:捷克斯洛伐克 1989 年 11 月 9 日柏林墙开放,改变了东德居民出行的可能性,却没有立即取消民主德国的政府、法律和国际地位。东德执政党失去垄断权力、举行自由选举,以及这个国家于 1990 年 10 月 3 日加入联邦德国,是相互推动而又需要分别解释的过程。把这十一个月压缩成一次“推倒柏林墙”,会漏掉统一真正具有决定性的社会选择、议会决定与国际谈判。 东德危机最特殊的条件,是边境另一侧已经存在一个富裕、说同一种语言、原则上承认东德居民德国人身份的国家。居民可以要求改变本国,也可以离开本国。这两种行动起初并不一致,却共同削弱了统一社会党继续按原有方式统治的能力。边境开放以后,后一种选择又改变了前一种选择的条件。 离开的人与留下的人 东德并非直到 1989 年才出现不满。旅行限制、秘密警察的监视、住房与消费品问题、污染和政治表达受限,早已进入居民生活。国家能够提供就业、教育与一部分社会保障,也确实拥有认同社会主义的支持者;问题在于这些支持无法通过自由竞争与公开纠错加以检验。政府仍以高度一致的选举数字显示合法性,居民却能经电视、亲属往来和...</div></div></div></div><nav id="pagination"><div class="pagination"><span class="page-number current">1</span><a class="page-number" href="/page/2/#content-inner">2</a><span class="space">…</span><a class="page-number" href="/page/215/#content-inner">215</a><a class="extend next" rel="next" href="/page/2/#content-inner"><i class="fas fa-chevron-right fa-fw"></i></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info text-center"><div class="avatar-img"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/rei.jpeg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info-name">magicliang</div><div class="author-info-description">关于技术以及人生</div><div class="site-data"><a href="/archives/"><div class="headline">Articles</div><div class="length-num">2143</div></a><a href="/tags/"><div class="headline">Tags</div><div class="length-num">2145</div></a><a href="/categories/"><div class="headline">Categories</div><div class="length-num">40</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/magicliang"><i class="fab fa-github"></i><span>Github</span></a><div class="card-info-social-icons"><a class="social-icon" href="https://github.com/magicliang" target="_blank" title="Github"><i class="fab fa-github"></i></a><a class="social-icon" href="mailto:magicliang@qq.com" target="_blank" title="Email"><i class="fas fa-envelope"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>Announcement</span></div><div class="announcement_content">人生只是,守株待兔</div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>Recent Posts</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/east-europe-15/" title="东欧剧变 15:为什么旧秩序瓦解以后,欧洲仍未获得共同安全"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-35.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 15:为什么旧秩序瓦解以后,欧洲仍未获得共同安全"/></a><div class="content"><a class="title" href="/east-europe-15/" title="东欧剧变 15:为什么旧秩序瓦解以后,欧洲仍未获得共同安全">东欧剧变 15:为什么旧秩序瓦解以后,欧洲仍未获得共同安全</a><time datetime="2026-10-23T00:15:00.000Z" title="Created 2026-10-23 08:15:00">2026-10-23</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/east-europe-14/" title="东欧剧变 14:普通人的转型十年,1989—1999"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-14.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 14:普通人的转型十年,1989—1999"/></a><div class="content"><a class="title" href="/east-europe-14/" title="东欧剧变 14:普通人的转型十年,1989—1999">东欧剧变 14:普通人的转型十年,1989—1999</a><time datetime="2026-10-23T00:14:00.000Z" title="Created 2026-10-23 08:14:00">2026-10-23</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/east-europe-13/" title="东欧剧变 13:南斯拉夫各战区为什么走向不同结局"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-38.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 13:南斯拉夫各战区为什么走向不同结局"/></a><div class="content"><a class="title" href="/east-europe-13/" title="东欧剧变 13:南斯拉夫各战区为什么走向不同结局">东欧剧变 13:南斯拉夫各战区为什么走向不同结局</a><time datetime="2026-10-23T00:13:00.000Z" title="Created 2026-10-23 08:13:00">2026-10-23</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/east-europe-12/" title="东欧剧变 12:南斯拉夫怎样从联邦危机走向战争"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-21.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 12:南斯拉夫怎样从联邦危机走向战争"/></a><div class="content"><a class="title" href="/east-europe-12/" title="东欧剧变 12:南斯拉夫怎样从联邦危机走向战争">东欧剧变 12:南斯拉夫怎样从联邦危机走向战争</a><time datetime="2026-10-23T00:12:00.000Z" title="Created 2026-10-23 08:12:00">2026-10-23</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/east-europe-11/" title="东欧剧变 11:1991年最后几个月,从八月事件到苏联终结"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-lazy-src="/img/wall-paper-62.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="东欧剧变 11:1991年最后几个月,从八月事件到苏联终结"/></a><div class="content"><a class="title" href="/east-europe-11/" title="东欧剧变 11:1991年最后几个月,从八月事件到苏联终结">东欧剧变 11:1991年最后几个月,从八月事件到苏联终结</a><time datetime="2026-10-23T00:11:00.000Z" title="Created 2026-10-23 08:11:00">2026-10-23</time></div></div></div></div><div class="card-widget card-categories"><div class="item-headline"><i class="fas fa-folder-open"></i><span>Categories</span><a class="card-more-btn" href="/categories/" title="View More">
<i class="fas fa-angle-right"></i></a></div>
<ul class="card-category-list" id="aside-cat-list">
<li class="card-category-list-item "><a class="card-category-list-link" href="/categories/AI/"><span class="card-category-list-name">AI</span><span class="card-category-list-count">80</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Java/"><span class="card-category-list-name">Java</span><span class="card-category-list-count">116</span></a><ul class="card-category-list child"><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Java/%E6%8C%81%E4%B9%85%E5%8C%96/"><span class="card-category-list-name">持久化</span><span class="card-category-list-count">2</span></a></li></ul></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Java-EE-%E4%BC%81%E4%B8%9A%E5%BA%94%E7%94%A8/"><span class="card-category-list-name">Java EE 企业应用</span><span class="card-category-list-count">24</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Kotlin-%E8%AF%AD%E8%A8%80%E4%B8%8E-JVM-%E5%B7%A5%E7%A8%8B/"><span class="card-category-list-name">Kotlin 语言与 JVM 工程</span><span class="card-category-list-count">48</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Perl/"><span class="card-category-list-name">Perl</span><span class="card-category-list-count">60</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Python-%E8%AF%AD%E8%A8%80%E4%B8%8E%E5%B7%A5%E7%A8%8B/"><span class="card-category-list-name">Python 语言与工程</span><span class="card-category-list-count">31</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Python%EF%BC%9A%E4%BB%8E%E5%AF%B9%E8%B1%A1%E6%A8%A1%E5%9E%8B%E5%88%B0%E5%B9%B6%E5%8F%91%E4%B8%8E%E5%B7%A5%E7%A8%8B%E5%AE%9E%E8%B7%B5/"><span class="card-category-list-name">Python:从对象模型到并发与工程实践</span><span class="card-category-list-count">17</span></a></li>
</ul></div><div class="card-widget card-tags"><div class="item-headline"><i class="fas fa-tags"></i><span>Tags</span></div><div class="card-tag-cloud"><a href="/tags/%E5%BD%B1%E8%AF%84/" style="font-size: 1.24em; color: rgb(50, 176, 136);">影评</a><a href="/tags/%E6%9D%A8%E5%B9%82/" style="font-size: 1.15em; color: rgb(50, 75, 140);">杨幂</a><a href="/tags/%E8%AF%BA%E5%85%B0/" style="font-size: 1.15em; color: rgb(190, 156, 50);">诺兰</a><a href="/tags/JVM/" style="font-size: 1.33em; color: rgb(50, 144, 125);">JVM</a><a href="/tags/Java/" style="font-size: 1.45em; color: rgb(58, 127, 171);">Java</a><a href="/tags/%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86/" style="font-size: 1.17em; color: rgb(184, 142, 50);">异常处理</a><a href="/tags/%E5%8C%BA%E5%9D%97%E9%93%BE/" style="font-size: 1.43em; color: rgb(194, 50, 50);">区块链</a><a href="/tags/Hyperledger/" style="font-size: 1.15em; color: rgb(122, 59, 122);">Hyperledger</a><a href="/tags/Corda/" style="font-size: 1.15em; color: rgb(57, 106, 65);">Corda</a><a href="/tags/%E7%A7%81%E6%9C%89%E9%93%BE/" style="font-size: 1.15em; color: rgb(61, 50, 89);">私有链</a><a href="/tags/%E8%81%94%E7%9B%9F%E9%93%BE/" style="font-size: 1.15em; color: rgb(152, 70, 187);">联盟链</a><a href="/tags/%E5%85%B1%E8%AF%86%E7%AE%97%E6%B3%95/" style="font-size: 1.17em; color: rgb(168, 142, 50);">共识算法</a><a href="/tags/javac/" style="font-size: 1.15em; color: rgb(91, 168, 168);">javac</a><a href="/tags/JIT/" style="font-size: 1.17em; color: rgb(90, 142, 65);">JIT</a><a href="/tags/%E5%AD%97%E8%8A%82%E7%A0%81/" style="font-size: 1.17em; color: rgb(79, 77, 50);">字节码</a><a href="/tags/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/" style="font-size: 1.17em; color: rgb(50, 50, 179);">性能优化</a><a href="/tags/%E7%A7%91%E5%B9%BB/" style="font-size: 1.15em; color: rgb(191, 175, 187);">科幻</a><a href="/tags/Docker/" style="font-size: 1.22em; color: rgb(168, 185, 151);">Docker</a><a href="/tags/Socket/" style="font-size: 1.2em; color: rgb(155, 186, 197);">Socket</a><a href="/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/" style="font-size: 1.29em; color: rgb(85, 68, 50);">数据库</a><a href="/tags/MySQL/" style="font-size: 1.27em; color: rgb(105, 62, 59);">MySQL</a><a href="/tags/MariaDB/" style="font-size: 1.15em; color: rgb(134, 96, 178);">MariaDB</a><a href="/tags/JavaScript/" style="font-size: 1.26em; color: rgb(62, 125, 50);">JavaScript</a><a href="/tags/KOA/" style="font-size: 1.15em; color: rgb(50, 97, 50);">KOA</a><a href="/tags/Linux/" style="font-size: 1.34em; color: rgb(50, 50, 169);">Linux</a><a href="/tags/%E8%99%9A%E6%8B%9F%E5%8C%96/" style="font-size: 1.19em; color: rgb(188, 50, 104);">虚拟化</a><a href="/tags/hypervisor/" style="font-size: 1.15em; color: rgb(57, 92, 130);">hypervisor</a><a href="/tags/github/" style="font-size: 1.15em; color: rgb(188, 50, 194);">github</a><a href="/tags/hexo/" style="font-size: 1.15em; color: rgb(93, 138, 65);">hexo</a><a href="/tags/%E4%BA%92%E8%81%94%E7%BD%91%E9%87%91%E8%9E%8D/" style="font-size: 1.15em; color: rgb(50, 114, 181);">互联网金融</a><a href="/tags/FinTech/" style="font-size: 1.17em; color: rgb(81, 137, 50);">FinTech</a><a href="/tags/Python/" style="font-size: 1.41em; color: rgb(66, 61, 184);">Python</a><a href="/tags/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/" style="font-size: 1.17em; color: rgb(50, 148, 52);">面向对象</a><a href="/tags/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/" style="font-size: 1.36em; color: rgb(50, 133, 166);">编程语言</a><a href="/tags/%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/" style="font-size: 1.15em; color: rgb(50, 152, 138);">编程范式</a><a href="/tags/tag/" style="font-size: 1.15em; color: rgb(174, 50, 79);">tag</a><a href="/tags/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/" style="font-size: 1.38em; color: rgb(50, 151, 179);">操作系统</a><a href="/tags/Go/" style="font-size: 1.4em; color: rgb(50, 50, 50);">Go</a><a href="/tags/%E5%A4%A7%E6%95%B0%E6%8D%AE/" style="font-size: 1.31em; color: rgb(92, 164, 50);">大数据</a><a href="/tags/%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84/" style="font-size: 1.19em; color: rgb(147, 69, 109);">体系结构</a></div></div><div class="card-widget card-archives">
<div class="item-headline"><i class="fas fa-archive"></i><span>Archives</span><a class="card-more-btn" href="/archives/"
title="View More">
<i class="fas fa-angle-right"></i>
</a></div>
<ul class="card-archive-list">
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/10/">
<span class="card-archive-list-date">
October 2026
</span>
<span class="card-archive-list-count">1237</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/09/">
<span class="card-archive-list-date">
September 2026
</span>
<span class="card-archive-list-count">244</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/08/">
<span class="card-archive-list-date">
August 2026
</span>
<span class="card-archive-list-count">100</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/07/">
<span class="card-archive-list-date">
July 2026
</span>
<span class="card-archive-list-count">54</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/06/">
<span class="card-archive-list-date">
June 2026
</span>
<span class="card-archive-list-count">80</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/05/">
<span class="card-archive-list-date">
May 2026
</span>
<span class="card-archive-list-count">90</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/04/">
<span class="card-archive-list-date">
April 2026
</span>
<span class="card-archive-list-count">19</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/03/">
<span class="card-archive-list-date">
March 2026
</span>
<span class="card-archive-list-count">14</span>
</a>
</li>
</ul>
</div><div class="card-widget card-webinfo"><div class="item-headline"><i class="fas fa-chart-line"></i><span>Website Info</span></div><div class="webinfo"><div class="webinfo-item"><div class="item-name">Article Count :</div><div class="item-count">2143</div></div><div class="webinfo-item"><div class="item-name">Total Word Count :</div><div class="item-count">7667.1k</div></div><div class="webinfo-item"><div class="item-name">Unique Visitors :</div><div class="item-count" id="busuanzi_value_site_uv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">Page Views :</div><div class="item-count" id="busuanzi_value_site_pv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">Last Update :</div><div class="item-count" id="last-push-date" data-lastPushDate="2026-10-26T06:37:36.609Z"><i class="fa-solid fa-spinner fa-spin"></i></div></div></div></div></div></div></main><footer id="footer"><div class="footer-other"><div class="footer-copyright"><span class="copyright">© 2017 - 2026 By magicliang</span><span class="framework-info"><span>Framework </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo 8.1.2</a><span class="footer-separator">|</span><span>Theme </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly 5.7.0</a></span></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="translateLink" type="button" title="Toggle Between Traditional and Simplified Chinese">簡</button><button id="darkmode" type="button" title="Toggle Between Light and Dark Mode"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="Toggle Between Single-column and Double-column"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="Settings"><i class="fas fa-cog fa-spin"></i></button><button id="go-up" type="button" title="Back to Top"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js?v=5.7.0"></script><script src="/js/main.js?v=5.7.0"></script><script src="/js/tw_cn.js?v=5.7.0"></script><script src="https://cdn.jsdelivr.net/npm/instant.page@5.2.0/instantpage.min.js" type="module"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@19.1.3/dist/lazyload.iife.min.js"></script><script src="https://cdn.jsdelivr.net/npm/node-snackbar@0.1.16/dist/snackbar.min.js"></script><div class="js-pjax"><script>window.typedJSFn = {
init: str => {
window.typed = new Typed('#subtitle', Object.assign({
strings: str,
startDelay: 300,
typeSpeed: 150,
loop: true,
backSpeed: 50,
}, null))
},
run: subtitleType => {
if (true) {
if (typeof Typed === 'function') {
subtitleType()
} else {
btf.getScript('https://cdn.jsdelivr.net/npm/typed.js@3.0.0/dist/typed.umd.min.js').then(subtitleType)
}
} else {
subtitleType()
}
},
processSubtitle: (content, extraContents = []) => {
if (true) {
const sub = ["一切都是守株待兔,如切如磋,如琢如磨。","I am just joking."].slice()
if (extraContents.length > 0) {
sub.unshift(...extraContents)
}
if (typeof content === 'string') {
sub.unshift(content)
} else if (Array.isArray(content)) {
sub.unshift(...content)
}
sub.length > 0 && typedJSFn.init(sub)
} else {
document.getElementById('subtitle').textContent = typeof content === 'string' ? content :
(Array.isArray(content) && content.length > 0 ? content[0] : '')
}
}
}
btf.addGlobalFn('pjaxSendOnce', () => { typed && typed.destroy() }, 'typedDestroy')
</script><script>function subtitleType () {
typedJSFn.processSubtitle(["一切都是守株待兔,如切如磋,如琢如磨。","I am just joking."])
}
typedJSFn.run(subtitleType)</script><script>(() => {
const parseViewBox = viewBox => {
if (!viewBox) return null
const parts = viewBox.trim().split(/[\s,]+/).map(n => Number(n))
if (parts.length !== 4 || parts.some(n => Number.isNaN(n))) return null
return parts
}
const getSvgViewBox = svg => {
const attr = parseViewBox(svg.getAttribute('viewBox'))
if (attr) return attr
// Fallback: use bbox to build a viewBox
try {
const bbox = svg.getBBox()
if (bbox && bbox.width && bbox.height) return [bbox.x, bbox.y, bbox.width, bbox.height]
} catch (e) {
// getBBox may fail on some edge cases; ignore
}
const w = Number(svg.getAttribute('width')) || 0
const h = Number(svg.getAttribute('height')) || 0
if (w > 0 && h > 0) return [0, 0, w, h]
return [0, 0, 100, 100]
}
const setSvgViewBox = (svg, vb) => {
svg.setAttribute('viewBox', `${vb[0]} ${vb[1]} ${vb[2]} ${vb[3]}`)
}
const clamp = (v, min, max) => Math.max(min, Math.min(max, v))
const openSvgInNewTab = ({ source, initViewBox }) => {
const getClonedSvg = () => {
if (typeof source === 'string') {
const template = document.createElement('template')
template.innerHTML = source.trim()
const svg = template.content.querySelector('svg')
return svg ? svg.cloneNode(true) : null
}
if (source && typeof source.cloneNode === 'function') {
return source.cloneNode(true)
}
return null
}
const clone = getClonedSvg()
if (!clone) return
if (initViewBox && initViewBox.length === 4) {
clone.setAttribute('viewBox', initViewBox.join(' '))
}
if (!clone.getAttribute('xmlns')) clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
if (!clone.getAttribute('xmlns:xlink') && clone.innerHTML.includes('xlink:')) {
clone.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink')
}
// inject background to match current theme
const isDark = document.documentElement.getAttribute('data-theme') === 'dark'
const bg = getComputedStyle(document.body).backgroundColor || (isDark ? '#1e1e1e' : '#ffffff')
if (!clone.style.background) clone.style.background = bg
const serializer = new XMLSerializer()
const svgSource = serializer.serializeToString(clone)
const htmlSource = `<!doctype html><html><head><meta charset="utf-8" />
<style>
html, body { width: 100%; height: 100%; margin: 0; display: flex; align-items: center; justify-content: center; background: ${bg}; }
svg { max-width: 100%; max-height: 100%; height: auto; width: auto; }
</style>
</head><body>${svgSource}</body></html>`
const blob = new Blob([htmlSource], { type: 'text/html;charset=utf-8' })
const url = URL.createObjectURL(blob)
window.open(url, '_blank', 'noopener')
setTimeout(() => URL.revokeObjectURL(url), 5000)
}
const attachMermaidViewerButton = wrap => {
let btn = wrap.querySelector('.mermaid-open-btn')
if (!btn) {
btn = document.createElement('button')
btn.type = 'button'
btn.className = 'mermaid-open-btn'
wrap.appendChild(btn)
}
btn.innerHTML = '<i class="fa fa-search fa-fw" aria-hidden="true"></i>'
if (!btn.__mermaidViewerBound) {
btn.addEventListener('click', e => {
e.preventDefault()
e.stopPropagation()
const svg = wrap.__mermaidOriginalSvg || wrap.querySelector('svg')
if (!svg) return
const initViewBox = wrap.__mermaidInitViewBox
openSvgInNewTab({ source: svg, initViewBox })
})
btn.__mermaidViewerBound = true
}
}
// Zoom around a point (px, py) in the SVG viewport (in viewBox coordinates)
const zoomAtPoint = (vb, factor, px, py) => {
const w = vb[2] * factor
const h = vb[3] * factor
const nx = px - (px - vb[0]) * factor
const ny = py - (py - vb[1]) * factor
return [nx, ny, w, h]
}
const initMermaidGestures = wrap => {
// Clean up previous event listeners and pending frames
if (wrap.__mermaidAbortController) {
wrap.__mermaidAbortController.abort()
if (wrap.__mermaidRafId) cancelAnimationFrame(wrap.__mermaidRafId)
}
const ac = new AbortController()
wrap.__mermaidAbortController = ac
const svg = wrap.querySelector('svg')
if (!svg) return
// Ensure viewBox exists so gestures always work
const initVb = getSvgViewBox(svg)
wrap.__mermaidInitViewBox = initVb
wrap.__mermaidCurViewBox = initVb.slice()
setSvgViewBox(svg, initVb)
// Disable default gestures to prevent scroll chaining and pinch-zoom penetration in Chrome
svg.style.touchAction = 'none'
// Cache BoundingClientRect, throttled on scroll to reduce reflow
let cachedRect = svg.getBoundingClientRect()
let rectDirty = false
const markRectDirty = () => { rectDirty = true }
window.addEventListener('resize', markRectDirty, { signal: ac.signal })
window.addEventListener('scroll', markRectDirty, { signal: ac.signal, capture: true })
const getRect = () => {
if (rectDirty) {
cachedRect = svg.getBoundingClientRect()
rectDirty = false
}
return cachedRect
}
// Precompute clamp bounds from initial viewBox
const minW = initVb[2] * 0.1
const maxW = initVb[2] * 10
const minH = initVb[3] * 0.1
const maxH = initVb[3] * 10
const clampVb = vb => {
const out = vb.slice()
out[2] = clamp(out[2], minW, maxW)
out[3] = clamp(out[3], minH, maxH)
return out
}
// Throttle DOM updates using requestAnimationFrame
let pendingVb = null
let rafId = null
const applyVb = () => {
if (pendingVb) {
wrap.__mermaidCurViewBox = pendingVb
setSvgViewBox(svg, pendingVb)
pendingVb = null
}
rafId = null
wrap.__mermaidRafId = null
}
const setCurVb = vb => {
pendingVb = clampVb(vb)
if (!rafId) {
rafId = requestAnimationFrame(applyVb)
wrap.__mermaidRafId = rafId
}
}
const state = {
pointers: new Map(),
startVb: null,
startDist: 0,
lastPointerX: 0,
lastPointerY: 0
}
const onPointerDown = e => {
if (e.pointerType === 'mouse' && e.button !== 0) return
svg.setPointerCapture(e.pointerId)
const curVb = wrap.__mermaidCurViewBox
state.pointers.set(e.pointerId, { x: e.clientX, y: e.clientY })
if (state.pointers.size === 1) {
state.startVb = curVb.slice()
state.lastPointerX = e.clientX
state.lastPointerY = e.clientY
} else if (state.pointers.size === 2) {
const pts = [...state.pointers.values()]
const dx = pts[0].x - pts[1].x
const dy = pts[0].y - pts[1].y
state.startDist = Math.hypot(dx, dy)
state.startVb = curVb.slice()
}
}
const onPointerMove = e => {
if (!state.pointers.has(e.pointerId)) return
state.pointers.set(e.pointerId, { x: e.clientX, y: e.clientY })
const curVb = wrap.__mermaidCurViewBox
const rect = getRect()
if (state.pointers.size === 1 && state.startVb) {
const p = state.pointers.values().next().value
const dxClient = p.x - state.lastPointerX
const dyClient = p.y - state.lastPointerY
state.lastPointerX = p.x
state.lastPointerY = p.y
const dx = dxClient * (curVb[2] / rect.width)
const dy = dyClient * (curVb[3] / rect.height)
setCurVb([curVb[0] - dx, curVb[1] - dy, curVb[2], curVb[3]])
return
}
if (state.pointers.size === 2 && state.startVb && state.startDist > 0) {
const pts = [...state.pointers.values()]
const dx = pts[0].x - pts[1].x
const dy = pts[0].y - pts[1].y
const dist = Math.hypot(dx, dy)
if (!dist) return
const factor = state.startDist / dist
const cx = (pts[0].x + pts[1].x) / 2
const cy = (pts[0].y + pts[1].y) / 2
const px = curVb[0] + (cx - rect.left) * (curVb[2] / rect.width)
const py = curVb[1] + (cy - rect.top) * (curVb[3] / rect.height)
setCurVb(zoomAtPoint(state.startVb, factor, px, py))
}
}
const onPointerUpOrCancel = e => {
// Release PointerCapture to avoid event capture anomalies
if (svg.hasPointerCapture && svg.hasPointerCapture(e.pointerId)) {
svg.releasePointerCapture(e.pointerId)
}
state.pointers.delete(e.pointerId)
if (state.pointers.size === 0) {
state.startVb = null
state.startDist = 0
} else if (state.pointers.size === 1) {
const p = state.pointers.values().next().value
state.lastPointerX = p.x
state.lastPointerY = p.y
}
}
const onWheel = e => {
// Prevent event bubbling from triggering external scroll
e.preventDefault()
e.stopPropagation()
// Normalize deltaY across deltaMode (Chrome uses pixels, Safari uses lines)
let delta = e.deltaY
if (e.deltaMode === 1) delta *= 16
else if (e.deltaMode === 2) delta *= 400
// Continuous zoom factor: smoother than fixed 1.1/0.9 steps
const zoomFactor = Math.pow(1.001, delta)
const curVb = wrap.__mermaidCurViewBox
const rect = getRect()
const px = curVb[0] + (e.clientX - rect.left) * (curVb[2] / rect.width)
const py = curVb[1] + (e.clientY - rect.top) * (curVb[3] / rect.height)
setCurVb(zoomAtPoint(curVb, zoomFactor, px, py))
}
const onDblClick = () => {
const init = wrap.__mermaidInitViewBox
if (init) setCurVb(init)
}
svg.addEventListener('pointerdown', onPointerDown, { signal: ac.signal })
svg.addEventListener('pointermove', onPointerMove, { signal: ac.signal })
svg.addEventListener('pointerup', onPointerUpOrCancel, { signal: ac.signal })
svg.addEventListener('pointercancel', onPointerUpOrCancel, { signal: ac.signal })
svg.addEventListener('wheel', onWheel, { passive: false, signal: ac.signal })
svg.addEventListener('dblclick', onDblClick, { signal: ac.signal })
}
const runMermaid = ele => {
window.loadMermaid = true
const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'default'
ele.forEach((item, index) => {
const mermaidSrc = item.firstElementChild
// Clean up event listeners before removing old SVG
if (item.__mermaidAbortController) {
item.__mermaidAbortController.abort()
}
const oldSvg = item.querySelector('svg')
if (oldSvg) oldSvg.remove()
let config = {}
try {
config = mermaidSrc.dataset.config ? JSON.parse(mermaidSrc.dataset.config) : {}
} catch (e) {
console.warn('[mermaid] failed to parse dataset.config:', e)
}
if (!config.theme) {
config.theme = theme
}
const mermaidThemeConfig = `%%{init: ${JSON.stringify(config)}}%%\n`
const mermaidID = `mermaid-${index}`
const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent
const renderMermaid = svg => {
mermaidSrc.insertAdjacentHTML('afterend', svg)
if (true) initMermaidGestures(item)
item.__mermaidOriginalSvg = svg
if (true) attachMermaidViewerButton(item)
}
const handleError = err => {
console.error(`[mermaid] render failed for block #${index}:`, err)
const errorEl = document.createElement('div')
errorEl.className = 'mermaid-error'
errorEl.textContent = `Mermaid render error: ${err.message || err}`
mermaidSrc.insertAdjacentElement('afterend', errorEl)
}
try {
const renderFn = mermaid.render(mermaidID, mermaidDefinition)
// mermaid v9 and v10 compatibility
if (typeof renderFn === 'string') {
renderMermaid(renderFn)
} else {
renderFn.then(({ svg }) => renderMermaid(svg)).catch(handleError)
}
} catch (err) {
handleError(err)
}
})
}
const codeToMermaid = $article => {
const codeMermaidEle = $article.querySelectorAll('pre > code.mermaid')
if (codeMermaidEle.length === 0) return
codeMermaidEle.forEach(ele => {
const preEle = document.createElement('pre')
preEle.className = 'mermaid-src'
preEle.hidden = true
preEle.textContent = ele.textContent
const newEle = document.createElement('div')
newEle.className = 'mermaid-wrap'
newEle.appendChild(preEle)
ele.parentNode.replaceWith(newEle)
})
}
const loadMermaid = () => {
const $article = document.getElementById('article-container')
if (!$article) return
if (true) codeToMermaid($article)
const $mermaid = $article.querySelectorAll('.mermaid-wrap')
if ($mermaid.length === 0) return
const runMermaidFn = () => runMermaid($mermaid)
btf.addGlobalFn('themeChange', runMermaidFn, 'mermaid')
window.loadMermaid ? runMermaidFn() : btf.getScript('https://cdn.jsdelivr.net/npm/mermaid@11.16.0/dist/mermaid.min.js').then(runMermaidFn)
}
btf.addGlobalFn('encrypt', loadMermaid, 'mermaid')
window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid)
})()</script></div><script defer="defer" id="fluttering_ribbon" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.6/dist/canvas-fluttering-ribbon.min.js"></script><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.6/dist/activate-power-mode.min.js"></script><script>POWERMODE.colorful = true;
POWERMODE.shake = false;
POWERMODE.mobile = false;
document.body.addEventListener('input', POWERMODE);
</script><script src="https://cdn.jsdelivr.net/npm/pjax@0.2.8/pjax.min.js" defer="defer"></script><script>document.addEventListener('DOMContentLoaded', () => {
const pjaxSelectors = ["head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"]
window.pjax = new Pjax({
elements: 'a:not([target="_blank"]):not([data-fancybox])',
selectors: pjaxSelectors,
cacheBust: false,
analytics: false,
scrollRestoration: false
})
const triggerPjaxFn = (val) => {
if (!val) return
Object.values(val).forEach(fn => {
try {
fn()
} catch (err) {
console.debug('Pjax callback failed:', err)
}
})
}
document.addEventListener('pjax:send', () => {
// removeEventListener
btf.removeGlobalFnEvent('pjaxSendOnce')
btf.removeGlobalFnEvent('themeChange')
// reset readmode
const $bodyClassList = document.body.classList
if ($bodyClassList.contains('read-mode')) $bodyClassList.remove('read-mode')
triggerPjaxFn(window.globalFn.pjaxSend)
})
document.addEventListener('pjax:complete', () => {
btf.removeGlobalFnEvent('pjaxCompleteOnce')
document.querySelectorAll('script[data-pjax]').forEach(item => {
if (!item.parentNode) return
const newScript = document.createElement('script')
const content = item.text || item.textContent || ''
Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
newScript.appendChild(document.createTextNode(content))
item.parentNode.replaceChild(newScript, item)
})
triggerPjaxFn(window.globalFn.pjaxComplete)
})
document.addEventListener('pjax:error', e => {
const responseURL = e.request && e.request.responseURL
if (e.request && e.request.status === 404) {
true
? pjax.loadUrl('/404.html')
: responseURL && (window.location.href = responseURL)
} else if (responseURL) {
window.location.href = responseURL
}
})
})</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">Search</span><i class="fas fa-spinner fa-pulse" id="loading-status" hidden="hidden"></i><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="text-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span> Loading Database</span></div><div class="local-search-input"><input placeholder="搜索文章..." type="text"/></div><hr/><div id="local-search-results"></div><div class="ais-Pagination" id="local-search-pagination" style="display:none;"><ul class="ais-Pagination-list"></ul></div><div id="local-search-stats"></div></div><div id="search-mask"></div><script src="/js/search/local-search.js?v=5.7.0"></script></div></div></body></html>