auto-save 2026-04-19 23:13 (~2)
This commit is contained in:
@@ -335,6 +335,13 @@
|
||||
"message": "auto-save 2026-04-19 23:02 (~1)",
|
||||
"hash": "84d1d75",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-04-19T23:08:15+08:00",
|
||||
"type": "commit",
|
||||
"message": "auto-save 2026-04-19 23:08 (~1)",
|
||||
"hash": "8c7a8e1",
|
||||
"files_changed": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -154,6 +154,20 @@ export const USER_VIEW_HTML = String.raw`<!DOCTYPE html>
|
||||
<template x-if="selectedType === 'image'">
|
||||
<div class="p-4"><img :src="selectedUrl" class="max-w-full rounded shadow-lg"/></div>
|
||||
</template>
|
||||
<template x-if="selectedType === 'html'">
|
||||
<div class="h-full flex flex-col">
|
||||
<div class="px-3 py-1.5 bg-[#0f1522] border-b border-gray-800 text-xs flex justify-between items-center">
|
||||
<span class="text-gray-500">🎮 HTML 实时预览(沙盒 iframe,JS 可跑)</span>
|
||||
<div class="flex gap-2">
|
||||
<button @click="htmlMode='preview'" :class="htmlMode==='preview'?'text-emerald-400':'text-gray-500'" class="hover:text-white">▶ 玩</button>
|
||||
<button @click="htmlMode='source'" :class="htmlMode==='source'?'text-emerald-400':'text-gray-500'" class="hover:text-white"><> 源码</button>
|
||||
<a :href="'data:text/html;charset=utf-8,' + encodeURIComponent(selectedContent)" target="_blank" class="text-gray-500 hover:text-white">↗ 新窗口</a>
|
||||
</div>
|
||||
</div>
|
||||
<iframe x-show="htmlMode==='preview'" :srcdoc="selectedContent" sandbox="allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-popups allow-modals" class="flex-1 bg-white" style="border:0"></iframe>
|
||||
<pre x-show="htmlMode==='source'" class="text-xs text-gray-300 p-4 whitespace-pre-wrap break-all flex-1 overflow-auto scrollbar" x-text="selectedContent"></pre>
|
||||
</div>
|
||||
</template>
|
||||
<template x-if="selectedType === 'text'">
|
||||
<pre class="text-xs text-gray-300 p-4 whitespace-pre-wrap break-all" x-text="selectedContent"></pre>
|
||||
</template>
|
||||
@@ -208,6 +222,7 @@ function userView() {
|
||||
selectedType: '',
|
||||
selectedContent: '',
|
||||
selectedUrl: '',
|
||||
htmlMode: 'preview',
|
||||
get sortedFiles() {
|
||||
return [...this.files].sort((a, b) => b.mtime - a.mtime);
|
||||
},
|
||||
@@ -260,19 +275,26 @@ function userView() {
|
||||
this.selectedSize = f.size;
|
||||
const ext = f.path.slice(f.path.lastIndexOf('.')).toLowerCase();
|
||||
const isImage = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg'].includes(ext);
|
||||
const isHtml = ['.html', '.htm'].includes(ext);
|
||||
const url = '../api/file?userId=' + encodeURIComponent(this.userId) + '&path=' + encodeURIComponent(f.path) + '&token=' + encodeURIComponent(this.token);
|
||||
if (isImage) {
|
||||
this.selectedType = 'image';
|
||||
this.selectedUrl = url;
|
||||
return;
|
||||
}
|
||||
const r = await fetch(url);
|
||||
if (!r.ok) {
|
||||
this.selectedType = 'error';
|
||||
this.selectedContent = '加载失败: ' + await r.text();
|
||||
return;
|
||||
}
|
||||
const content = await r.text();
|
||||
this.selectedContent = content;
|
||||
if (isHtml) {
|
||||
this.selectedType = 'html';
|
||||
this.htmlMode = 'preview';
|
||||
} else {
|
||||
const r = await fetch(url);
|
||||
if (r.ok) {
|
||||
this.selectedType = 'text';
|
||||
this.selectedContent = await r.text();
|
||||
} else {
|
||||
this.selectedType = 'error';
|
||||
this.selectedContent = '加载失败: ' + await r.text();
|
||||
}
|
||||
this.selectedType = 'text';
|
||||
}
|
||||
},
|
||||
iconFor(path) {
|
||||
@@ -282,7 +304,7 @@ function userView() {
|
||||
'.json': '{}', '.md': '📝', '.txt': '📄',
|
||||
'.csv': '📊', '.tsv': '📊', '.xlsx': '📊',
|
||||
'.png': '🖼', '.jpg': '🖼', '.jpeg': '🖼', '.gif': '🖼', '.webp': '🖼',
|
||||
'.html': '🌐', '.css': '🎨',
|
||||
'.html': '🎮', '.htm': '🎮', '.css': '🎨',
|
||||
'.pdf': '📕', '.zip': '📦',
|
||||
})[ext] ?? '📄';
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user