WACATW commited on
Commit
032edec
·
verified ·
1 Parent(s): 4edbaaa

Rename static/deepseek_html_20260921_60b93d.html to index.html

Browse files
index.html ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>云学习平台</title>
6
+ <style>
7
+ body { font-family: system-ui, sans-serif; max-width: 900px; margin: 40px auto; padding: 0 16px; }
8
+ h1 { color: #2563eb; }
9
+ section { border: 1px solid #e5e7eb; border-radius: 12px; padding: 20px; margin-bottom: 20px; }
10
+ input, button { padding: 8px 12px; margin: 4px 0; font-size: 14px; }
11
+ button { background: #2563eb; color: #fff; border: none; border-radius: 6px; cursor: pointer; }
12
+ button:hover { background: #1d4ed8; }
13
+ pre { background: #f3f4f6; padding: 12px; border-radius: 8px; overflow-x: auto; }
14
+ .row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
15
+ </style>
16
+ </head>
17
+ <body>
18
+ <h1>📚 云学习平台</h1>
19
+
20
+ <section>
21
+ <h2>1. 注册 / 登录</h2>
22
+ <div class="row">
23
+ <input id="username" placeholder="用户名">
24
+ <input id="password" type="password" placeholder="密码">
25
+ <button onclick="register()">注册</button>
26
+ <button onclick="login()">登录</button>
27
+ <span id="authStatus"></span>
28
+ </div>
29
+ </section>
30
+
31
+ <section>
32
+ <h2>2. 上传学习资料</h2>
33
+ <div class="row">
34
+ <input type="file" id="uploadFile">
35
+ <button onclick="upload()">上传</button>
36
+ </div>
37
+ <pre id="uploadResult"></pre>
38
+ </section>
39
+
40
+ <section>
41
+ <h2>3. 我的资料库</h2>
42
+ <button onclick="listFiles()">刷新列表</button>
43
+ <pre id="fileList"></pre>
44
+ </section>
45
+
46
+ <section>
47
+ <h2>4. AI 识图搜索</h2>
48
+ <p>上传一张图片,AI 会识别内容并在你的资料库中查找相关文件。</p>
49
+ <div class="row">
50
+ <input type="file" id="searchImage" accept="image/*">
51
+ <button onclick="searchByImage()">识图搜索</button>
52
+ </div>
53
+ <pre id="searchResult"></pre>
54
+ </section>
55
+
56
+ <script>
57
+ let token = localStorage.getItem("token") || "";
58
+
59
+ function authHeaders() {
60
+ return token ? { "Authorization": "Bearer " + token } : {};
61
+ }
62
+
63
+ async function register() {
64
+ const fd = new FormData();
65
+ fd.append("username", document.getElementById("username").value);
66
+ fd.append("password", document.getElementById("password").value);
67
+ const r = await fetch("/auth/register", { method: "POST", body: fd });
68
+ const j = await r.json();
69
+ if (r.ok) {
70
+ token = j.access_token;
71
+ localStorage.setItem("token", token);
72
+ document.getElementById("authStatus").textContent = "✅ 注册成功";
73
+ } else {
74
+ document.getElementById("authStatus").textContent = "❌ " + (j.detail || "注册失败");
75
+ }
76
+ }
77
+
78
+ async function login() {
79
+ const fd = new FormData();
80
+ fd.append("username", document.getElementById("username").value);
81
+ fd.append("password", document.getElementById("password").value);
82
+ const r = await fetch("/auth/login", { method: "POST", body: fd });
83
+ const j = await r.json();
84
+ if (r.ok) {
85
+ token = j.access_token;
86
+ localStorage.setItem("token", token);
87
+ document.getElementById("authStatus").textContent = "✅ 登录成功";
88
+ } else {
89
+ document.getElementById("authStatus").textContent = "❌ " + (j.detail || "登录失败");
90
+ }
91
+ }
92
+
93
+ async function upload() {
94
+ const f = document.getElementById("uploadFile").files[0];
95
+ if (!f) return alert("请选择文件");
96
+ const fd = new FormData();
97
+ fd.append("file", f);
98
+ const r = await fetch("/files/upload", { method: "POST", headers: authHeaders(), body: fd });
99
+ document.getElementById("uploadResult").textContent = JSON.stringify(await r.json(), null, 2);
100
+ }
101
+
102
+ async function listFiles() {
103
+ const r = await fetch("/files/list", { headers: authHeaders() });
104
+ document.getElementById("fileList").textContent = JSON.stringify(await r.json(), null, 2);
105
+ }
106
+
107
+ async function searchByImage() {
108
+ const f = document.getElementById("searchImage").files[0];
109
+ if (!f) return alert("请选择图片");
110
+ const fd = new FormData();
111
+ fd.append("file", f);
112
+ document.getElementById("searchResult").textContent = "识别中...";
113
+ const r = await fetch("/ai/search-by-image", { method: "POST", headers: authHeaders(), body: fd });
114
+ document.getElementById("searchResult").textContent = JSON.stringify(await r.json(), null, 2);
115
+ }
116
+ </script>
117
+ </body>
118
+ </html>
static/deepseek_html_20260921_60b93d.html DELETED
@@ -1,307 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>HF 存储桶极速上传下载</title>
7
- <style>
8
- * { box-sizing: border-box; margin: 0; padding: 0; }
9
- body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0d1117; color: #c9d1d9; min-height: 100vh; display: flex; justify-content: center; padding: 30px 20px; }
10
- .container { max-width: 680px; width: 100%; }
11
- h1 { font-size: 1.4rem; margin-bottom: 6px; color: #f0f6fc; }
12
- .subtitle { font-size: 0.85rem; color: #8b949e; margin-bottom: 20px; }
13
- .card { background: #161b22; border: 1px solid #30363d; border-radius: 10px; padding: 20px; margin-bottom: 16px; }
14
- .card h2 { font-size: 0.95rem; margin-bottom: 14px; color: #f0f6fc; border-bottom: 1px solid #21262d; padding-bottom: 8px; }
15
- .field { margin-bottom: 12px; }
16
- label { display: block; font-size: 0.78rem; color: #8b949e; margin-bottom: 4px; }
17
- input[type="text"], input[type="password"] { width: 100%; padding: 8px 12px; background: #0d1117; border: 1px solid #30363d; border-radius: 6px; color: #c9d1d9; font-size: 0.85rem; outline: none; }
18
- input:focus { border-color: #58a6ff; }
19
- button { padding: 8px 16px; background: #238636; color: #fff; border: none; border-radius: 6px; font-size: 0.85rem; cursor: pointer; transition: background 0.2s; }
20
- button:hover { background: #2ea043; }
21
- button:disabled { background: #21262d; color: #484f58; cursor: not-allowed; }
22
- button.secondary { background: #21262d; border: 1px solid #30363d; }
23
- button.secondary:hover { background: #30363d; }
24
- .row { display: flex; gap: 10px; align-items: flex-end; margin-bottom: 10px; }
25
- .row .field { flex: 1; margin-bottom: 0; }
26
- .status { margin-top: 10px; padding: 8px 12px; border-radius: 6px; font-size: 0.8rem; display: none; word-break: break-all; }
27
- .status.success { display: block; background: #0d2818; border: 1px solid #238636; color: #3fb950; }
28
- .status.error { display: block; background: #2d0f0f; border: 1px solid #f85149; color: #f85149; }
29
- .status.info { display: block; background: #0d1f2d; border: 1px solid #1f6feb; color: #58a6ff; }
30
- .file-list { list-style: none; margin-top: 10px; max-height: 250px; overflow-y: auto; }
31
- .file-list li { display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; border-bottom: 1px solid #21262d; font-size: 0.8rem; }
32
- .file-list li:last-child { border-bottom: none; }
33
- .file-list button { padding: 3px 10px; font-size: 0.75rem; }
34
- .warning { background: #2d1f00; border: 1px solid #9e6a03; border-radius: 6px; padding: 10px 14px; font-size: 0.78rem; color: #d29922; margin-bottom: 16px; line-height: 1.4; }
35
- </style>
36
- </head>
37
- <body>
38
- <div class="container">
39
- <h1>🚀 Hugging Face 存储桶极速工具</h1>
40
- <p class="subtitle">本地双击直接运行 · 无需 HTTP 服务器</p>
41
-
42
- <div class="warning">
43
- ⚠️ <strong>安全提示:</strong>你的密钥已预填在页面中,<strong>绝对不要将此 HTML 文件发给别人或上传到公网!</strong>仅供本地个人使用。
44
- </div>
45
-
46
- <!-- 配置卡片 -->
47
- <div class="card">
48
- <h2>🔑 连接配置</h2>
49
- <button id="loadBtn" class="secondary" style="margin-bottom: 14px; width: 100%;">⚡ 一键加载你的密钥(已预填)</button>
50
- <div class="field">
51
- <label>AWS_ACCESS_KEY_ID</label>
52
- <input type="text" id="accessKey" />
53
- </div>
54
- <div class="field">
55
- <label>AWS_SECRET_ACCESS_KEY</label>
56
- <input type="password" id="secretKey" />
57
- </div>
58
- <div class="field">
59
- <label>端点 URL(Endpoint)</label>
60
- <input type="text" id="endpoint" />
61
- </div>
62
- <div class="field">
63
- <label>存储桶名称(Bucket,包含命名空间)</label>
64
- <input type="text" id="bucketName" />
65
- </div>
66
- <button id="connectBtn" class="secondary" style="width: 100%;">🔗 初始化连接</button>
67
- <div id="connectStatus" class="status"></div>
68
- </div>
69
-
70
- <!-- 上传卡片 -->
71
- <div class="card">
72
- <h2>📤 上传文件</h2>
73
- <div class="field">
74
- <input type="file" id="fileInput" multiple />
75
- </div>
76
- <button id="uploadBtn" disabled style="width: 100%;">上传到存储桶</button>
77
- <div id="uploadStatus" class="status"></div>
78
- </div>
79
-
80
- <!-- 下载与列表卡片 -->
81
- <div class="card">
82
- <h2>📥 下载文件 / 文件列表</h2>
83
- <div class="row">
84
- <div class="field">
85
- <label>文件路径(如 test.txt)</label>
86
- <input type="text" id="downloadPath" placeholder="test.txt" />
87
- </div>
88
- <button id="downloadBtn" disabled>下载</button>
89
- </div>
90
- <div id="downloadStatus" class="status"></div>
91
- <button id="listBtn" class="secondary" style="margin-top: 10px; width: 100%;" disabled>📋 列出存储桶中的所有文件</button>
92
- <ul class="file-list" id="fileList"></ul>
93
- </div>
94
- </div>
95
-
96
- <!-- 引入轻量级 AWS S3 签名库(更换了国内更稳定的 CDN) -->
97
- <script src="https://unpkg.com/aws4fetch@1.0.20/dist/aws4fetch.min.js"></script>
98
-
99
- <script>
100
- // ── DOM 引用 ──
101
- const loadBtn = document.getElementById('loadBtn');
102
- const accessKeyInput = document.getElementById('accessKey');
103
- const secretKeyInput = document.getElementById('secretKey');
104
- const endpointInput = document.getElementById('endpoint');
105
- const bucketInput = document.getElementById('bucketName');
106
- const connectBtn = document.getElementById('connectBtn');
107
- const connectStatus = document.getElementById('connectStatus');
108
-
109
- const fileInput = document.getElementById('fileInput');
110
- const uploadBtn = document.getElementById('uploadBtn');
111
- const uploadStatus = document.getElementById('uploadStatus');
112
-
113
- const downloadPath = document.getElementById('downloadPath');
114
- const downloadBtn = document.getElementById('downloadBtn');
115
- const downloadStatus = document.getElementById('downloadStatus');
116
-
117
- const listBtn = document.getElementById('listBtn');
118
- const fileList = document.getElementById('fileList');
119
-
120
- let awsClient = null;
121
- let currentBucket = '';
122
- let currentEndpoint = '';
123
-
124
- // ── 工具函数 ──
125
- function showStatus(el, msg, type = 'info') {
126
- el.textContent = msg;
127
- el.className = `status ${type}`;
128
- }
129
- function setButtonsEnabled(enabled) {
130
- uploadBtn.disabled = !enabled;
131
- downloadBtn.disabled = !enabled;
132
- listBtn.disabled = !enabled;
133
- }
134
-
135
- // ── 一键加载预填密钥 ──
136
- loadBtn.addEventListener('click', () => {
137
- accessKeyInput.value = 'HFAK0z5hUE3yQ7h0lPHMMF4gITYxkMP';
138
- secretKeyInput.value = '5a4d39a13b8fff06128fb4fa64c24258b1081b1437075ae16311de9f884b8271';
139
- endpointInput.value = 'https://s3.hf.co';
140
- bucketInput.value = 'WACATW/pan-storage';
141
- showStatus(connectStatus, '✅ 密钥已全部加载!请点击“初始化连接”。', 'success');
142
- });
143
-
144
- // ── 初始化 S3 客户端 ──
145
- connectBtn.addEventListener('click', () => {
146
- const accessKey = accessKeyInput.value.trim();
147
- const secretKey = secretKeyInput.value.trim();
148
- let endpoint = endpointInput.value.trim();
149
- const bucket = bucketInput.value.trim();
150
-
151
- if (!accessKey || !secretKey || !endpoint || !bucket) {
152
- showStatus(connectStatus, '请确保所有字段都已填写', 'error');
153
- return;
154
- }
155
-
156
- // 检查 CDN 是否加载成功
157
- if (typeof AwsClient === 'undefined') {
158
- showStatus(connectStatus, '❌ 依赖库加载失败!请检查网络是否能访问 unpkg.com,或按下方说明下载本地库。', 'error');
159
- return;
160
- }
161
-
162
- // 标准化端点 URL(去掉末尾斜杠)
163
- endpoint = endpoint.replace(/\/+$/, '');
164
- currentEndpoint = endpoint;
165
-
166
- try {
167
- awsClient = new AwsClient({
168
- accessKeyId: accessKey,
169
- secretAccessKey: secretKey,
170
- service: 's3',
171
- region: 'us-east-1'
172
- });
173
- currentBucket = bucket;
174
-
175
- showStatus(connectStatus, `✅ 客户端初始化成功!存储桶: ${bucket}`, 'success');
176
- setButtonsEnabled(true);
177
- } catch (err) {
178
- console.error(err);
179
- showStatus(connectStatus, '❌ 初始化失败:' + err.message, 'error');
180
- setButtonsEnabled(false);
181
- }
182
- });
183
-
184
- // 组装完整的 URL
185
- function buildUrl(path = '') {
186
- let url = `${currentEndpoint}/${currentBucket}`;
187
- if (path) url += `/${path}`;
188
- return url;
189
- }
190
-
191
- // ── 上传文件 ──
192
- uploadBtn.addEventListener('click', async () => {
193
- const files = fileInput.files;
194
- if (!files || files.length === 0) {
195
- showStatus(uploadStatus, '请先选择文件', 'error');
196
- return;
197
- }
198
- if (!awsClient) return;
199
-
200
- uploadBtn.disabled = true;
201
- let successCount = 0;
202
-
203
- for (let i = 0; i < files.length; i++) {
204
- const file = files[i];
205
- showStatus(uploadStatus, `正在上传 (${i+1}/${files.length}): ${file.name}...`, 'info');
206
- try {
207
- const response = await awsClient.fetch(buildUrl(file.name), {
208
- method: 'PUT',
209
- body: file
210
- });
211
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
212
- successCount++;
213
- } catch (err) {
214
- console.error(err);
215
- showStatus(uploadStatus, `❌ 上传 ${file.name} 失败: ${err.message}`, 'error');
216
- uploadBtn.disabled = false;
217
- return;
218
- }
219
- }
220
-
221
- showStatus(uploadStatus, `✅ 成功上传 ${successCount} 个文件`, 'success');
222
- fileInput.value = '';
223
- uploadBtn.disabled = false;
224
- });
225
-
226
- // ── 下载文件 ──
227
- downloadBtn.addEventListener('click', async () => {
228
- const path = downloadPath.value.trim();
229
- if (!path) {
230
- showStatus(downloadStatus, '请输入文件路径', 'error');
231
- return;
232
- }
233
- if (!awsClient) return;
234
-
235
- downloadBtn.disabled = true;
236
- showStatus(downloadStatus, `正在下载 ${path}...`, 'info');
237
-
238
- try {
239
- const response = await awsClient.fetch(buildUrl(path));
240
-
241
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
242
-
243
- const blob = await response.blob();
244
- const urlObj = URL.createObjectURL(blob);
245
- const a = document.createElement('a');
246
- a.href = urlObj;
247
- a.download = path.split('/').pop();
248
- document.body.appendChild(a);
249
- a.click();
250
- document.body.removeChild(a);
251
- URL.revokeObjectURL(urlObj);
252
-
253
- showStatus(downloadStatus, `✅ 已下载 ${path}`, 'success');
254
- } catch (err) {
255
- console.error(err);
256
- showStatus(downloadStatus, `❌ 下载失败: ${err.message}`, 'error');
257
- } finally {
258
- downloadBtn.disabled = false;
259
- }
260
- });
261
-
262
- // ── 列出文件 ──
263
- listBtn.addEventListener('click', async () => {
264
- if (!awsClient) return;
265
- listBtn.disabled = true;
266
- fileList.innerHTML = '';
267
- showStatus(downloadStatus, '正在获取文件列表...', 'info');
268
-
269
- try {
270
- const response = await awsClient.fetch(buildUrl() + '?list-type=2');
271
-
272
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
273
-
274
- const text = await response.text();
275
- const parser = new DOMParser();
276
- const xmlDoc = parser.parseFromString(text, 'text/xml');
277
- const contents = xmlDoc.getElementsByTagName('Contents');
278
-
279
- if (contents.length === 0) {
280
- fileList.innerHTML = '<li style="color:#8b949e;">存储桶为空</li>';
281
- } else {
282
- for (let i = 0; i < contents.length; i++) {
283
- const key = contents[i].getElementsByTagName('Key')[0]?.textContent || '未知文件';
284
- const li = document.createElement('li');
285
- li.innerHTML = `<span>${key}</span>`;
286
- const btn = document.createElement('button');
287
- btn.textContent = '⬇️';
288
- btn.title = '下载此文件';
289
- btn.addEventListener('click', () => {
290
- downloadPath.value = key;
291
- downloadBtn.click();
292
- });
293
- li.appendChild(btn);
294
- fileList.appendChild(li);
295
- }
296
- }
297
- showStatus(downloadStatus, `✅ 共 ${contents.length} 个文件`, 'success');
298
- } catch (err) {
299
- console.error(err);
300
- showStatus(downloadStatus, `❌ 获取列表失败: ${err.message}`, 'error');
301
- } finally {
302
- listBtn.disabled = false;
303
- }
304
- });
305
- </script>
306
- </body>
307
- </html>