-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
282 lines (262 loc) · 15.6 KB
/
Copy pathindex.html
File metadata and controls
282 lines (262 loc) · 15.6 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
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SQLite Web Studio</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap"
rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
}
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background: #d1d5db;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #9ca3af;
}
</style>
</head>
<body class="bg-gray-50 text-gray-900 h-screen overflow-hidden">
<div class="flex flex-col h-full">
<!-- Header -->
<header class="bg-white border-b border-gray-200 px-6 py-3 flex items-center justify-between shadow-sm z-10">
<div class="flex items-center space-x-3">
<div class="bg-blue-600 w-10 h-10 rounded-lg flex items-center justify-center flex-shrink-0">
<i class="fas fa-database text-white text-xl"></i>
</div>
<div>
<h1 class="text-xl font-bold text-gray-800 tracking-tight">SQLite Web Studio</h1>
<p class="text-[10px] text-gray-500 font-semibold uppercase" id="dbNameHeader">准备加载数据库</p>
</div>
</div>
<div class="flex items-center space-x-3">
<label id="openFileLabel"
class="flex items-center px-4 py-2 bg-white border border-gray-300 rounded-lg text-sm font-semibold text-gray-700 hover:bg-gray-50 cursor-pointer transition shadow-sm"
style="display: none;">
<i class="fas fa-folder-open w-4 h-4 mr-2 text-blue-600"></i>
打开数据库
<input type="file" id="fileInput" class="hidden" accept=".db,.sqlite,.sqlite3" />
</label>
<button id="saveDbBtn"
class="flex items-center px-4 py-2 bg-emerald-600 text-white rounded-lg text-sm font-bold hover:bg-emerald-700 transition shadow-lg shadow-emerald-100"
style="display: none;">
<i class="fas fa-save w-4 h-4 mr-2"></i>
保存
</button>
<button id="exportDbBtn"
class="flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-bold hover:bg-blue-700 transition shadow-lg shadow-blue-100"
style="display: none;">
<i class="fas fa-download w-4 h-4 mr-2"></i>
导出数据库
</button>
</div>
</header>
<!-- Main Content Area -->
<main class="flex flex-1 overflow-hidden">
<!-- Sidebar -->
<aside class="w-72 bg-gray-50 border-r border-gray-200 flex flex-col" id="sidebar" style="display: none;">
<div class="p-4 border-b border-gray-200 bg-white">
<h2 class="text-xs font-bold text-gray-400 uppercase tracking-widest mb-3">数据库表</h2>
<div class="relative">
<i class="fas fa-search absolute left-3 top-2.5 w-4 h-4 text-gray-400"></i>
<input type="text" id="tableSearchInput" placeholder="搜索表..."
class="w-full pl-9 pr-4 py-2 bg-gray-100 border border-gray-200 rounded-md text-sm focus:ring-2 focus:ring-blue-500 focus:bg-white transition outline-none" />
</div>
</div>
<div class="flex-1 overflow-y-auto p-2 space-y-1" id="tableList">
<div class="flex flex-col items-center justify-center py-12 px-4 text-center">
<i class="fas fa-table w-12 h-12 text-gray-300 mb-3"></i>
<p class="text-xs text-gray-500 font-medium">尚未加载表</p>
</div>
</div>
</aside>
<!-- Content View -->
<section class="flex-1 flex flex-col bg-white overflow-hidden">
<!-- Welcome Screen -->
<div class="flex-1 flex flex-col items-center justify-center text-center p-12 bg-[radial-gradient(#e5e7eb_1px,transparent_1px)] [background-size:16px_16px]"
id="welcomeScreen">
<p class="text-gray-500 max-w-sm mx-auto text-sm leading-relaxed mb-6">
点击下方区域或拖拽文件加载 <code class="bg-gray-100 px-1 py-0.5 rounded">.db</code> 文件。所有操作都在浏览器本地进行。
</p>
<div class="border-2 border-dashed border-gray-300 rounded-2xl p-12 hover:border-blue-500 transition cursor-pointer"
id="dropZone">
<i class="fas fa-cloud-upload-alt text-5xl text-gray-400 mb-4"></i>
<p class="text-gray-600 font-medium">点击或拖拽数据库文件到此处</p>
<p class="text-xs text-gray-400 mt-2">支持 .db, .sqlite, .sqlite3 格式</p>
</div>
</div>
<!-- Table View -->
<div id="tableView" style="display: none;">
<!-- Toolbar -->
<div
class="bg-white border-b border-gray-200 px-6 py-4 flex items-center justify-between flex-shrink-0">
<div class="flex items-center space-x-6">
<h2 class="text-lg font-black text-gray-900 flex items-center tracking-tight"
id="currentTableName">
<button id="refreshTableBtn"
class="ml-2.5 p-1.5 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded-full transition"
title="刷新">
<i class="fas fa-sync-alt w-4 h-4"></i>
</button>
</h2>
<div class="flex p-1 bg-gray-100 rounded-xl">
<button id="dataTabBtn"
class="px-5 py-1.5 text-xs font-bold rounded-lg transition bg-white text-gray-900 shadow-sm">
浏览数据
</button>
<button id="structureTabBtn"
class="px-5 py-1.5 text-xs font-bold rounded-lg transition text-gray-500 hover:text-gray-700">
表结构
</button>
</div>
</div>
<div class="flex items-center space-x-4">
<div
class="flex items-center text-[10px] font-bold text-gray-400 uppercase tracking-wider mr-2">
<span class="mr-2">行数:</span>
<select id="limitSelect"
class="bg-gray-100 border-none rounded-md px-2 py-1 focus:ring-2 focus:ring-blue-500 text-gray-700">
<option value="100">100</option>
<option value="500">500</option>
<option value="1000">1000</option>
<option value="9999999">全部</option>
</select>
</div>
<button id="addRowBtn"
class="flex items-center px-4 py-2 bg-emerald-600 text-white rounded-lg text-xs font-bold hover:bg-emerald-700 transition shadow-md shadow-emerald-100">
<i class="fas fa-plus w-4 h-4 mr-1.5"></i>
插入行
</button>
</div>
</div>
<!-- Data View -->
<div class="flex-1 overflow-auto bg-gray-50/50 p-6">
<!-- Error Display -->
<div id="errorDisplay"
class="mb-6 bg-red-50 border border-red-200 rounded-xl p-4 flex items-start space-x-3 shadow-sm"
style="display: none;">
<i class="fas fa-exclamation-circle w-5 h-5 text-red-500 flex-shrink-0 mt-0.5"></i>
<p class="text-sm text-red-700 font-medium" id="errorMessage"></p>
</div>
<!-- Data Tab -->
<div id="dataTabContent" class="bg-white rounded-2xl shadow-sm border border-gray-200">
<div class="overflow-x-auto overflow-y-auto max-h-[calc(100vh-250px)]">
<table class="w-full text-left text-sm border-collapse">
<thead>
<tr class="bg-gray-50/80 border-b border-gray-200">
<th
class="px-4 py-4 text-[10px] font-black text-gray-400 uppercase tracking-widest text-center w-12">
#</th>
<th id="dataTableHead" colspan="100"></th>
<th
class="px-4 py-4 text-[10px] font-black text-gray-400 uppercase tracking-widest text-center w-28">
操作</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100" id="dataTableBody">
</tbody>
</table>
</div>
</div>
<!-- Structure Tab -->
<div id="structureTabContent" class="bg-white rounded-2xl shadow-sm border border-gray-200"
style="display: none;">
<div class="overflow-x-auto overflow-y-auto max-h-[calc(100vh-250px)]">
<table class="w-full text-left text-sm">
<thead>
<tr class="bg-gray-50/80 border-b border-gray-200">
<th class="px-8 py-5 font-bold text-gray-700">列名</th>
<th class="px-8 py-5 font-bold text-gray-700">数据类型</th>
<th class="px-8 py-5 font-bold text-gray-700 text-center">非空</th>
<th class="px-8 py-5 font-bold text-gray-700">默认值</th>
<th class="px-8 py-5 font-bold text-gray-700 text-center">主键</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100" id="structureBody">
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
</main>
<!-- Row Editor Modal -->
<div class="fixed inset-0 bg-gray-900/60 backdrop-blur-md z-50 flex items-center justify-center p-4"
id="editModal" style="display: none;">
<div class="bg-white rounded-3xl shadow-2xl w-full max-w-2xl max-h-[90vh] overflow-hidden flex flex-col">
<div class="p-7 border-b border-gray-100 flex items-center justify-between bg-white sticky top-0 z-10">
<div>
<h3 class="text-2xl font-black text-gray-900 tracking-tight" id="modalTitle">插入新记录</h3>
<p id="modalSubtitle"
class="text-[11px] text-blue-600 font-bold uppercase tracking-wider mt-1.5 flex items-center"
style="display: none;">
<i class="fas fa-info-circle w-3 h-3 mr-1"></i>
基于主键标识符更新
</p>
</div>
<button id="modalClose"
class="p-2.5 text-gray-400 hover:bg-gray-100 hover:text-gray-900 rounded-full transition-all">
<i class="fas fa-times w-6 h-6"></i>
</button>
</div>
<div class="p-8 overflow-y-auto flex-1 bg-gray-50/30" id="modalBody">
</div>
<div class="pt-6 pb-8 px-8 border-t border-gray-100 flex justify-end space-x-4">
<button id="modalCancel"
class="px-7 py-3 border border-gray-200 rounded-xl text-xs font-black uppercase tracking-widest text-gray-500 hover:bg-white hover:text-gray-900 transition-all">
取消
</button>
<button id="modalSave"
class="px-10 py-3 bg-gray-900 text-white rounded-xl text-xs font-black uppercase tracking-widest hover:bg-blue-600 transition-all shadow-xl shadow-gray-200 active:scale-95">
应用更改
</button>
</div>
</div>
</div>
<!-- Loading Overlay -->
<div class="fixed inset-0 bg-white/95 backdrop-blur-xl z-50 flex flex-col items-center justify-center"
id="loading" style="display: none;">
<div class="relative w-16 h-16">
<div class="absolute inset-0 border-4 border-blue-100 rounded-full"></div>
<div class="absolute inset-0 border-4 border-blue-600 border-t-transparent rounded-full animate-spin">
</div>
</div>
<p class="mt-6 text-sm font-black text-gray-900 uppercase tracking-[0.2em] animate-pulse">正在处理 SQL</p>
</div>
<!-- Toast Notification -->
<div class="fixed bottom-6 right-6 z-50" id="toast"></div>
<!-- Context Menu -->
<div id="contextMenu" class="fixed bg-white border border-gray-200 rounded-lg shadow-xl z-50 py-1 min-w-[150px]"
style="display: none;">
<button
class="context-menu-item w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-600 flex items-center">
<i class="fas fa-edit w-4 h-4 mr-2"></i>
编辑行
</button>
<button
class="context-menu-item w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-red-50 hover:text-red-600 flex items-center">
<i class="fas fa-trash w-4 h-4 mr-2"></i>
删除行
</button>
</div>
</div>
<!-- 引入 SQL.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.8.0/sql-wasm.js"></script>
<script src="app.js"></script>
</body>
</html>