1+ ---
2+ interface Update {
3+ version: string ;
4+ date: string ;
5+ title: string ;
6+ buttonText: string ;
7+ buttonUrl: string ;
8+ updates: string [];
9+ }
10+
11+ interface Props {
12+ updates: Update [];
13+ }
14+
15+ const { updates } = Astro .props ;
16+
17+ // 定义不同类型的badge样式
18+ const badgeStyles = {
19+ ' 新增' : ' bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300' ,
20+ ' 升级' : ' bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300' ,
21+ ' 修复' : ' bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300' ,
22+ ' 优化' : ' bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300' ,
23+ ' 预告' : ' bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-300' ,
24+ ' 删除' : ' bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300' ,
25+ };
26+
27+ // 修改 parseUpdate 函数以确保正确匹配
28+ function parseUpdate(update : string ) {
29+ const match = update .match (/ 【(. *? )】(. * )/ );
30+ if (match ) {
31+ return {
32+ type: match [1 ],
33+ content: match [2 ].trim ()
34+ };
35+ }
36+ return {
37+ type: ' ' ,
38+ content: update
39+ };
40+ }
41+ ---
42+
43+ <div id =" updateModal" class =" fixed inset-0 z-50" >
44+ <!-- 背景遮罩 -->
45+ <div class =" absolute inset-0 bg-black bg-opacity-50" ></div >
46+
47+ <!-- 弹窗内容 -->
48+ <div class =" absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[90%] max-w-md bg-white dark:bg-gray-800 rounded-lg shadow-xl p-6" >
49+ <!-- 弹窗头部 -->
50+ <div class =" flex justify-between items-center mb-4" >
51+ <div class =" flex items-center gap-4" >
52+ <h3 class =" text-xl font-bold text-gray-900 dark:text-white" >
53+ 更新历史
54+ </h3 >
55+ <a
56+ href =" ./zero2hero"
57+ rel =" noopener noreferrer"
58+ class =" px-3 py-1 text-sm bg-rose-500 text-white rounded hover:bg-rose-600 transition-colors"
59+ >
60+ ➡ 文档/教程
61+ </a >
62+ </div >
63+ <button id =" closeModal" class =" text-gray-500 hover:text-gray-700 dark:hover:text-gray-300" >
64+ <svg class =" w-6 h-6" fill =" none" stroke =" currentColor" viewBox =" 0 0 24 24" >
65+ <path stroke-linecap =" round" stroke-linejoin =" round" stroke-width =" 2" d =" M6 18L18 6M6 6l12 12" ></path >
66+ </svg >
67+ </button >
68+ </div >
69+
70+ <!-- 修改可滚动的内容区域 -->
71+ <div class =" max-h-[400px] overflow-y-auto pr-2" >
72+ { updates .map ((update ) => (
73+ <div class = " mb-6 last:mb-0" >
74+ <div class = " flex justify-between items-center mb-2" >
75+ <div class = " flex items-center gap-4" >
76+ <h4 class = " text-lg font-semibold text-gray-900 dark:text-white" >
77+ { update .version } { update .title }
78+ </h4 >
79+ <p class = " text-sm text-gray-500 dark:text-gray-400" >{ update .date } </p >
80+ </div >
81+ </div >
82+
83+ <div class = " space-y-2" >
84+ <ul class = " space-y-2" >
85+ { update .updates .map (item => {
86+ const { type, content } = parseUpdate (item );
87+ return (
88+ <li class = " flex items-start gap-2" >
89+ { type && (
90+ <span class = { ` inline-flex items-center px-2 py-0.5 text-xs font-medium rounded ${badgeStyles [type ] || ' bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300' } ` } >
91+ { type }
92+ </span >
93+ )}
94+ <span class = " flex-1 text-gray-600 dark:text-gray-300" >{ content } </span >
95+ </li >
96+ );
97+ })}
98+ </ul >
99+ </div >
100+ </div >
101+ ))}
102+ </div >
103+ </div >
104+ </div >
105+
106+ <script >
107+ const modal = document.getElementById('updateModal');
108+ const closeBtn = document.getElementById('closeModal');
109+
110+ // 关闭弹窗
111+ function closeModal() {
112+ if (modal) {
113+ modal.style.display = 'none';
114+ }
115+ }
116+
117+ // 点击背景关闭弹窗
118+ function handleClickOutside(event: MouseEvent) {
119+ const target = event.target as HTMLElement;
120+ if (target === modal) {
121+ closeModal();
122+ }
123+ }
124+
125+ // 添加事件监听
126+ closeBtn?.addEventListener('click', closeModal);
127+ modal?.addEventListener('click', handleClickOutside);
128+
129+ // 添加键盘事件监听(ESC键关闭弹窗)
130+ document.addEventListener('keydown', (event) => {
131+ if (event.key === 'Escape') {
132+ closeModal();
133+ }
134+ });
135+ </script >
136+
137+ <style >
138+ #updateModal {
139+ animation: fadeIn 0.3s ease-in-out;
140+ }
141+
142+ @keyframes fadeIn {
143+ from {
144+ opacity: 0;
145+ }
146+ to {
147+ opacity: 1;
148+ }
149+ }
150+
151+ /* 自定义滚动条样式 */
152+ .overflow-y-auto {
153+ scrollbar-width: thin;
154+ scrollbar-color: rgba(156, 163, 175, 0.5) transparent;
155+ }
156+
157+ .overflow-y-auto::-webkit-scrollbar {
158+ width: 6px;
159+ }
160+
161+ .overflow-y-auto::-webkit-scrollbar-track {
162+ background: transparent;
163+ }
164+
165+ .overflow-y-auto::-webkit-scrollbar-thumb {
166+ background-color: rgba(156, 163, 175, 0.5);
167+ border-radius: 3px;
168+ }
169+ </style >
0 commit comments