@code2rich/jpage 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +68 -0
- package/.dockerignore +8 -0
- package/.env.example +56 -0
- package/.github/workflows/ci.yml +43 -0
- package/CLAUDE.md +280 -0
- package/Dockerfile +44 -0
- package/LICENSE +21 -0
- package/README.md +433 -0
- package/README_EN.md +399 -0
- package/bin/args.js +64 -0
- package/bin/client.js +93 -0
- package/bin/commands/_shared.js +54 -0
- package/bin/commands/cat.js +23 -0
- package/bin/commands/ls.js +44 -0
- package/bin/commands/mv.js +20 -0
- package/bin/commands/rm.js +22 -0
- package/bin/commands/skills.js +70 -0
- package/bin/commands/star.js +23 -0
- package/bin/commands/tags.js +97 -0
- package/bin/commands/upload.js +84 -0
- package/bin/commands/url.js +25 -0
- package/bin/commands/whoami.js +29 -0
- package/bin/config.js +85 -0
- package/bin/jpage.js +168 -0
- package/build.js +112 -0
- package/docker-compose.yml +26 -0
- package/docs/api.md +438 -0
- package/docs/design/005-custom-modal.md +296 -0
- package/docs/design/013-file-version-history.md +324 -0
- package/docs/design/billing-system.md +600 -0
- package/docs/design/db-index-and-healthcheck.md +176 -0
- package/docs/design/loading-states.md +209 -0
- package/docs/virtual-hosting-feasibility.md +453 -0
- package/eslint.config.mjs +172 -0
- package/lib/auth-state.js +15 -0
- package/lib/categories.js +20 -0
- package/lib/crypto.js +85 -0
- package/lib/csp.js +66 -0
- package/lib/db.js +53 -0
- package/lib/dispatch.js +103 -0
- package/lib/fts.js +81 -0
- package/lib/middleware/auth.js +114 -0
- package/lib/middleware/files.js +42 -0
- package/lib/paths.js +9 -0
- package/lib/render-cache.js +48 -0
- package/lib/render.js +157 -0
- package/lib/templates.js +149 -0
- package/lib/util.js +66 -0
- package/lib/view-counts.js +59 -0
- package/lib/zip.js +192 -0
- package/logger.js +16 -0
- package/mailer.js +34 -0
- package/mcp/constants.js +16 -0
- package/mcp/resources.js +74 -0
- package/mcp/server.js +43 -0
- package/mcp/tools-categories.js +56 -0
- package/mcp/tools-content-templates.js +59 -0
- package/mcp/tools-files.js +245 -0
- package/mcp/tools-tags.js +41 -0
- package/mcp/tools-versions.js +57 -0
- package/mcp/transport.js +183 -0
- package/mcp/util.js +63 -0
- package/mcp-server.js +20 -0
- package/migrations/001_init_schema.js +25 -0
- package/migrations/002_add_share_key.js +33 -0
- package/migrations/003_add_roles_and_tokens.js +28 -0
- package/migrations/004_add_version_history.js +32 -0
- package/migrations/005_tags_starred_categories.js +49 -0
- package/migrations/006_zip_bundle.js +17 -0
- package/migrations/007_add_file_type_uploaded_by_indexes.js +7 -0
- package/migrations/008_add_fts5.js +6 -0
- package/migrations/009_add_link_visits.js +20 -0
- package/migrations/010_add_templates_system.js +34 -0
- package/migrations/011_content_templates.js +233 -0
- package/migrations/012_add_email_and_verification.js +35 -0
- package/migrations/013_add_token_encrypted.js +14 -0
- package/migrations.js +65 -0
- package/package.json +63 -0
- package/public/css/style.css +2915 -0
- package/public/index.html +855 -0
- package/public/js/api.js +22 -0
- package/public/js/app.js +94 -0
- package/public/js/components/dialog.js +106 -0
- package/public/js/components/toast.js +13 -0
- package/public/js/pages/content-templates.js +330 -0
- package/public/js/pages/home.js +1903 -0
- package/public/js/pages/landing.js +158 -0
- package/public/js/pages/login.js +175 -0
- package/public/js/pages/preview.js +713 -0
- package/public/js/theme.js +44 -0
- package/public/js/utils.js +67 -0
- package/routes/admin.js +136 -0
- package/routes/auth.js +365 -0
- package/routes/categories.js +90 -0
- package/routes/content-templates.js +215 -0
- package/routes/files/_shared.js +112 -0
- package/routes/files/associations.js +94 -0
- package/routes/files/crud.js +139 -0
- package/routes/files/detail-serve.js +178 -0
- package/routes/files/index.js +38 -0
- package/routes/files/list.js +200 -0
- package/routes/files/overwrite.js +114 -0
- package/routes/files/upload.js +204 -0
- package/routes/files/versions.js +166 -0
- package/routes/files.js +16 -0
- package/routes/skills.js +93 -0
- package/routes/tags.js +65 -0
- package/routes/tokens.js +110 -0
- package/routes/users.js +120 -0
- package/server.js +372 -0
- package/skills/jpage-content-template/SKILL.md +98 -0
- package/skills/jpage-upload/SKILL.md +247 -0
- package/skills-registry.js +135 -0
- package/templates/academic.html +41 -0
- package/templates/dark-pro.html +41 -0
- package/templates/default.html +56 -0
- package/templates/github.html +67 -0
- package/test/browser-harness.js +125 -0
- package/test/dispatch-bench.js +74 -0
- package/test/helpers/setup.js +45 -0
- package/test/integration/admin.test.js +108 -0
- package/test/integration/auth.test.js +93 -0
- package/test/integration/categories.test.js +103 -0
- package/test/integration/cli.test.js +310 -0
- package/test/integration/content-templates.test.js +147 -0
- package/test/integration/files-security.test.js +248 -0
- package/test/integration/files.test.js +139 -0
- package/test/integration/share.test.js +79 -0
- package/test/integration/skills.test.js +104 -0
- package/test/integration/tags.test.js +84 -0
- package/test/integration/tokens.test.js +89 -0
- package/test/integration/users.test.js +138 -0
- package/test/mcp-harness.js +152 -0
- package/test/perf-bench.js +108 -0
- package/test/perf-harness.js +198 -0
- package/test/run-server.sh +15 -0
- package/test/unit/cli-args.test.js +88 -0
- package/test/unit/cli-config.test.js +89 -0
- package/test/unit/crypto.test.js +100 -0
- package/test/unit/fts.test.js +52 -0
- package/test/unit/render-cache.test.js +76 -0
- package/test/unit/util.test.js +81 -0
- package/test/unit/zip.test.js +164 -0
|
@@ -0,0 +1,855 @@
|
|
|
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
|
+
<meta name="description" content="即页,拖入 HTML 或 Markdown 文件,即刻获得在线预览页面。">
|
|
7
|
+
<title>即页 — 拖入文件,即刻成页</title>
|
|
8
|
+
<link rel="stylesheet" href="/css/style.css?v=1.5.0">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="app"></div>
|
|
12
|
+
|
|
13
|
+
<!-- 落地页模板 -->
|
|
14
|
+
<template id="landing-template">
|
|
15
|
+
<div class="landing-page">
|
|
16
|
+
<!-- 导航栏 -->
|
|
17
|
+
<nav class="landing-nav">
|
|
18
|
+
<div class="landing-nav-inner">
|
|
19
|
+
<div class="landing-nav-brand">
|
|
20
|
+
<div class="brand-mark" aria-hidden="true">即</div>
|
|
21
|
+
<span class="landing-nav-title">即页</span>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="landing-nav-actions">
|
|
24
|
+
<button class="theme-toggle" aria-label="切换主题">
|
|
25
|
+
<svg class="icon-moon" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/></svg>
|
|
26
|
+
<svg class="icon-sun" viewBox="0 0 24 24"><path d="M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41M12 6a6 6 0 100 12 6 6 0 000-12z"/></svg>
|
|
27
|
+
</button>
|
|
28
|
+
<a class="btn btn-primary" href="#/login">登录</a>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</nav>
|
|
32
|
+
|
|
33
|
+
<!-- Hero 区域 -->
|
|
34
|
+
<section class="landing-hero">
|
|
35
|
+
<p class="landing-hero-eyebrow"><span></span>HTML · Markdown · 即时预览分享</p>
|
|
36
|
+
<h1 class="landing-hero-title"><em>即页</em> <small>jpage</small></h1>
|
|
37
|
+
<p class="landing-hero-sub">零 配 置 · 即 写 即 览 即 分 享</p>
|
|
38
|
+
<p class="landing-hero-slogan">拖入文件,即刻成页。AI 工具直连,一键分享。</p>
|
|
39
|
+
<div class="landing-hero-actions">
|
|
40
|
+
<a class="btn btn-primary btn-lg" href="#/login">开始使用</a>
|
|
41
|
+
</div>
|
|
42
|
+
<div class="landing-hero-tags">
|
|
43
|
+
<span class="landing-tag">Express</span>
|
|
44
|
+
<span class="landing-tag">SQLite</span>
|
|
45
|
+
<span class="landing-tag">Vanilla JS</span>
|
|
46
|
+
<span class="landing-tag">MCP</span>
|
|
47
|
+
<span class="landing-tag">Docker</span>
|
|
48
|
+
</div>
|
|
49
|
+
</section>
|
|
50
|
+
|
|
51
|
+
<!-- 四次进化 -->
|
|
52
|
+
<section class="landing-sec" id="versions">
|
|
53
|
+
<div class="landing-sec-inner">
|
|
54
|
+
<div class="landing-sec-tag">Version History</div>
|
|
55
|
+
<h2 class="landing-sec-title">四次进化,四个问题的答案</h2>
|
|
56
|
+
<div class="landing-versions">
|
|
57
|
+
<div class="ver">
|
|
58
|
+
<div class="ver-dot"></div>
|
|
59
|
+
<div class="ver-card">
|
|
60
|
+
<div class="ver-head">
|
|
61
|
+
<span class="ver-num">V1.0 / V1.1</span>
|
|
62
|
+
<span class="ver-date">2026-05-13</span>
|
|
63
|
+
<span class="ver-title">诞生:从第一行代码到品牌确立</span>
|
|
64
|
+
<span class="ver-theme">「能不能分享」</span>
|
|
65
|
+
</div>
|
|
66
|
+
<p class="ver-desc">AI 生成的 HTML 不再沦为截图或附件。拖拽上传,秒级预览,短链接即分享——即页的第一个版本,只做一件事:让内容被完整地看见。正式命名「即页 jpage」,端口 8858,Docker 一行部署。</p>
|
|
67
|
+
<div class="ver-highlights">
|
|
68
|
+
<div class="hl"><span class="hl-icon">📄</span>HTML/Markdown 拖拽上传秒级预览</div>
|
|
69
|
+
<div class="hl"><span class="hl-icon">🔄</span>渲染/源码双模式切换</div>
|
|
70
|
+
<div class="hl"><span class="hl-icon">🐳</span>Docker 一行部署,SQLite 零配置</div>
|
|
71
|
+
<div class="hl"><span class="hl-icon">🏷️</span>重命名、删除、下载</div>
|
|
72
|
+
<div class="hl"><span class="hl-icon">🎨</span>品牌视觉确立,端口 8858</div>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
<div class="ver">
|
|
77
|
+
<div class="ver-dot"></div>
|
|
78
|
+
<div class="ver-card">
|
|
79
|
+
<div class="ver-head">
|
|
80
|
+
<span class="ver-num">V1.2</span>
|
|
81
|
+
<span class="ver-date">2026-06-07</span>
|
|
82
|
+
<span class="ver-title">渲染增强 + MCP 协议</span>
|
|
83
|
+
<span class="ver-theme">「分享得好不好看」</span>
|
|
84
|
+
</div>
|
|
85
|
+
<p class="ver-desc">公式、图表、代码完整渲染。同时接入 MCP 协议,Claude Code 直连即页——AI 生成到发布全自动化。Skills 管理、文件隐私控制、API 全面开放,产品能力质的飞跃。</p>
|
|
86
|
+
<div class="ver-highlights">
|
|
87
|
+
<div class="hl"><span class="hl-icon">✨</span>highlight.js 代码高亮(180+ 语言)</div>
|
|
88
|
+
<div class="hl"><span class="hl-icon">📐</span>KaTeX 数学公式(行内 + 块级)</div>
|
|
89
|
+
<div class="hl"><span class="hl-icon">📊</span>Mermaid 图表(深/浅色主题)</div>
|
|
90
|
+
<div class="hl"><span class="hl-icon">🔗</span>MCP Server(6 Tools + 2 Resources)</div>
|
|
91
|
+
<div class="hl"><span class="hl-icon">🔒</span>文件公开/私有切换</div>
|
|
92
|
+
<div class="hl"><span class="hl-icon">📦</span>Skills 管理 + ZIP 打包</div>
|
|
93
|
+
<div class="hl"><span class="hl-icon">🔌</span>JSON 直传 + Bearer 认证</div>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
<div class="ver">
|
|
98
|
+
<div class="ver-dot"></div>
|
|
99
|
+
<div class="ver-card">
|
|
100
|
+
<div class="ver-head">
|
|
101
|
+
<span class="ver-num">V1.3</span>
|
|
102
|
+
<span class="ver-date">2026-06-08</span>
|
|
103
|
+
<span class="ver-title">管理体系:从分享到管理</span>
|
|
104
|
+
<span class="ver-theme">「分享之后怎么管理」</span>
|
|
105
|
+
</div>
|
|
106
|
+
<p class="ver-desc">短链接一键分享、ZIP 网站包上传、完整版本历史、三维文件组织、多用户管理——从「能分享」进化到「好管理」。MCP 工具从 6 个扩展到 15 个,安全全面加固。</p>
|
|
107
|
+
<div class="ver-highlights">
|
|
108
|
+
<div class="hl"><span class="hl-icon">🔗</span>短链接 /s/:key 即时分享</div>
|
|
109
|
+
<div class="hl"><span class="hl-icon">📁</span>ZIP 网站包 + 批量上传</div>
|
|
110
|
+
<div class="hl"><span class="hl-icon">📋</span>版本历史(备份/恢复/清理)</div>
|
|
111
|
+
<div class="hl"><span class="hl-icon">🏷️</span>标签 / 收藏 / 分类三维组织</div>
|
|
112
|
+
<div class="hl"><span class="hl-icon">👥</span>多用户管理 + API Token</div>
|
|
113
|
+
<div class="hl"><span class="hl-icon">🛡️</span>CSP + iframe Sandbox 加固</div>
|
|
114
|
+
<div class="hl"><span class="hl-icon">📱</span>UI/UX 全面升级 + 移动端优化</div>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
<div class="ver">
|
|
119
|
+
<div class="ver-dot"></div>
|
|
120
|
+
<div class="ver-card">
|
|
121
|
+
<div class="ver-head">
|
|
122
|
+
<span class="ver-num">V1.4</span>
|
|
123
|
+
<span class="ver-date">2026-06-09</span>
|
|
124
|
+
<span class="ver-title">风格化:AI 内容的审美革命</span>
|
|
125
|
+
<span class="ver-theme">「AI 生成的内容怎么有风格」</span>
|
|
126
|
+
</div>
|
|
127
|
+
<p class="ver-desc">内容模板市场让 AI 学会风格参考——不是模板套用,是风格学习。4 种 Markdown 渲染模板、全文搜索、链接访问统计。MCP 扩展到 17 个工具。</p>
|
|
128
|
+
<div class="ver-highlights">
|
|
129
|
+
<div class="hl"><span class="hl-icon">🏪</span>内容模板市场(9 场景 · 3 内置)</div>
|
|
130
|
+
<div class="hl"><span class="hl-icon">🎨</span>4 种 Markdown 渲染模板</div>
|
|
131
|
+
<div class="hl"><span class="hl-icon">🔍</span>FTS5 全文搜索</div>
|
|
132
|
+
<div class="hl"><span class="hl-icon">📈</span>链接访问统计</div>
|
|
133
|
+
<div class="hl"><span class="hl-icon">📐</span>app.js → 8 个 ES Modules</div>
|
|
134
|
+
<div class="hl"><span class="hl-icon">🤖</span>MCP 17 Tools + 模板集成</div>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
</section>
|
|
141
|
+
|
|
142
|
+
<!-- 设计理念 -->
|
|
143
|
+
<section class="landing-sec" id="philosophy">
|
|
144
|
+
<div class="landing-sec-inner">
|
|
145
|
+
<div class="landing-sec-tag">Design Philosophy</div>
|
|
146
|
+
<h2 class="landing-sec-title">设计理念</h2>
|
|
147
|
+
<div class="landing-philos">
|
|
148
|
+
<div class="phi"><div class="phi-ico">⚡</div><h3>零配置哲学</h3><p>docker-compose up — 三秒启动,五秒上传,八秒分享。开发者的内容工具应该像呼吸一样自然,不折腾配置,只专注内容。</p></div>
|
|
149
|
+
<div class="phi"><div class="phi-ico">🤖</div><h3>AI-Native</h3><p>不是给产品加 AI 功能,而是以 AI 为中心重新设计内容发布流程。MCP 工具让 Claude 成为内容助手,一句话生成、一键发布。</p></div>
|
|
150
|
+
<div class="phi"><div class="phi-ico">✂️</div><h3>极简主义</h3><p>无框架前端、无构建工具、无 npm script 魔法。Vanilla JS 写出的代码,十年后还能读懂。复杂度是敌人,简洁是美德。</p></div>
|
|
151
|
+
<div class="phi"><div class="phi-ico">🌱</div><h3>渐进增强</h3><p>从文件预览器到模板市场。版本管理、标签分类、全文搜索——每个功能都是自然生长的结果,不是预先设计的冗余。</p></div>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
</section>
|
|
155
|
+
|
|
156
|
+
<!-- 页脚 -->
|
|
157
|
+
<footer class="landing-footer">
|
|
158
|
+
<p>© 2026 即页 · <a href="https://github.com/code2rich/jpage" target="_blank">GitHub</a> · <a href="mailto:code2rich@qq.com">联系</a></p>
|
|
159
|
+
</footer>
|
|
160
|
+
|
|
161
|
+
<!-- 模板预览弹窗 -->
|
|
162
|
+
<div class="modal-backdrop" id="template-preview-modal" hidden>
|
|
163
|
+
<div class="modal-panel modal-panel-lg">
|
|
164
|
+
<button class="btn btn-small modal-close" id="template-preview-close" aria-label="关闭">×</button>
|
|
165
|
+
<div class="template-preview-header">
|
|
166
|
+
<h3 id="template-preview-title"></h3>
|
|
167
|
+
<div class="template-preview-meta" id="template-preview-meta"></div>
|
|
168
|
+
</div>
|
|
169
|
+
<div class="template-preview-body">
|
|
170
|
+
<iframe id="template-preview-iframe" sandbox="allow-scripts"></iframe>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
</template>
|
|
176
|
+
|
|
177
|
+
<!-- 登录/注册模板 -->
|
|
178
|
+
<template id="login-template">
|
|
179
|
+
<div class="layout login-layout">
|
|
180
|
+
<button class="theme-toggle" aria-label="切换主题" style="position:fixed;top:20px;right:20px;z-index:200">
|
|
181
|
+
<svg class="icon-moon" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/></svg>
|
|
182
|
+
<svg class="icon-sun" viewBox="0 0 24 24"><path d="M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41M12 6a6 6 0 100 12 6 6 0 000-12z"/></svg>
|
|
183
|
+
</button>
|
|
184
|
+
<main class="login-main">
|
|
185
|
+
<div class="login-brand">
|
|
186
|
+
<div class="brand-mark" aria-hidden="true">即</div>
|
|
187
|
+
<h1 class="login-title">即页</h1>
|
|
188
|
+
<p class="login-subtitle">拖入文件,即刻成页</p>
|
|
189
|
+
</div>
|
|
190
|
+
<div class="auth-tabs">
|
|
191
|
+
<button class="auth-tab active" data-tab="login">登录</button>
|
|
192
|
+
<button class="auth-tab" data-tab="register">注册</button>
|
|
193
|
+
</div>
|
|
194
|
+
<form class="login-form auth-panel active" id="login-form" autocomplete="on">
|
|
195
|
+
<label class="login-field">
|
|
196
|
+
<span>用户名或邮箱</span>
|
|
197
|
+
<input type="text" name="username" id="login-username" required autocomplete="username" autofocus>
|
|
198
|
+
</label>
|
|
199
|
+
<label class="login-field">
|
|
200
|
+
<span>密码</span>
|
|
201
|
+
<input type="password" name="password" id="login-password" required autocomplete="current-password">
|
|
202
|
+
</label>
|
|
203
|
+
<div class="login-error" id="login-error" role="alert" hidden></div>
|
|
204
|
+
<button type="submit" class="btn btn-primary login-submit" id="login-submit">登录</button>
|
|
205
|
+
</form>
|
|
206
|
+
<form class="login-form auth-panel" id="register-form" autocomplete="on">
|
|
207
|
+
<label class="login-field">
|
|
208
|
+
<span>邮箱</span>
|
|
209
|
+
<input type="email" name="email" id="register-email" autocomplete="email" required placeholder="用于接收验证码">
|
|
210
|
+
</label>
|
|
211
|
+
<div class="register-code-row">
|
|
212
|
+
<input type="text" id="register-code" placeholder="6 位验证码" maxlength="6" inputmode="numeric" pattern="\d{6}" required autocomplete="one-time-code">
|
|
213
|
+
<button type="button" class="btn btn-small" id="btn-send-code">发送验证码</button>
|
|
214
|
+
</div>
|
|
215
|
+
<div class="register-code-tip" id="register-code-tip" hidden></div>
|
|
216
|
+
<label class="login-field">
|
|
217
|
+
<span>用户名 <small>(可选)</small></span>
|
|
218
|
+
<input type="text" name="username" id="register-username" autocomplete="username" placeholder="字母、数字、下划线,2-30 位" pattern="[a-zA-Z0-9_]{2,30}" minlength="2" maxlength="30" title="只能包含字母、数字和下划线,2-30 位">
|
|
219
|
+
<div class="register-username-hint" id="register-username-hint" hidden></div>
|
|
220
|
+
</label>
|
|
221
|
+
<label class="login-field">
|
|
222
|
+
<span>密码</span>
|
|
223
|
+
<input type="password" name="password" id="register-password" required minlength="8" autocomplete="new-password" placeholder="至少 8 位">
|
|
224
|
+
</label>
|
|
225
|
+
<label class="login-field">
|
|
226
|
+
<span>确认密码</span>
|
|
227
|
+
<input type="password" name="confirmPassword" id="register-confirm" required minlength="8" autocomplete="new-password">
|
|
228
|
+
</label>
|
|
229
|
+
<div class="login-error" id="register-error" role="alert" hidden></div>
|
|
230
|
+
<button type="submit" class="btn btn-primary login-submit" id="register-submit">注册</button>
|
|
231
|
+
</form>
|
|
232
|
+
</main>
|
|
233
|
+
</div>
|
|
234
|
+
</template>
|
|
235
|
+
|
|
236
|
+
<!-- 文件管理模板 -->
|
|
237
|
+
<template id="home-template">
|
|
238
|
+
<div class="layout">
|
|
239
|
+
<header class="header">
|
|
240
|
+
<div class="header-left">
|
|
241
|
+
<div class="brand-mark" aria-hidden="true">即</div>
|
|
242
|
+
<div class="brand-text">
|
|
243
|
+
<h1>即页</h1>
|
|
244
|
+
<p class="header-tagline">拖入文件,即刻成页</p>
|
|
245
|
+
</div>
|
|
246
|
+
</div>
|
|
247
|
+
<div class="header-right">
|
|
248
|
+
<button class="theme-toggle" aria-label="切换主题">
|
|
249
|
+
<svg class="icon-moon" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/></svg>
|
|
250
|
+
<svg class="icon-sun" viewBox="0 0 24 24"><path d="M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41M12 6a6 6 0 100 12 6 6 0 000-12z"/></svg>
|
|
251
|
+
</button>
|
|
252
|
+
<span class="header-user" id="header-user"></span>
|
|
253
|
+
<div class="settings-dropdown" id="settings-dropdown">
|
|
254
|
+
<button type="button" class="btn btn-small btn-settings" id="btn-settings" aria-label="设置" aria-haspopup="true" aria-expanded="false">
|
|
255
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
|
|
256
|
+
<span>设置</span>
|
|
257
|
+
</button>
|
|
258
|
+
<div class="settings-menu" id="settings-menu" role="menu">
|
|
259
|
+
<div class="settings-menu-label">AI 集成</div>
|
|
260
|
+
<button type="button" class="settings-menu-item" role="menuitem" id="menu-item-skills">
|
|
261
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M12 2L2 7l10 5 10-5-10-5z"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg>
|
|
262
|
+
Skills 管理
|
|
263
|
+
</button>
|
|
264
|
+
<button type="button" class="settings-menu-item" role="menuitem" id="menu-item-content-templates">
|
|
265
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
|
|
266
|
+
内容模板
|
|
267
|
+
</button>
|
|
268
|
+
<button type="button" class="settings-menu-item" role="menuitem" id="menu-item-mcp">
|
|
269
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
|
|
270
|
+
MCP 配置
|
|
271
|
+
</button>
|
|
272
|
+
<div class="settings-menu-divider" role="separator"></div>
|
|
273
|
+
<button type="button" class="settings-menu-item" role="menuitem" id="menu-item-tokens">
|
|
274
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
|
|
275
|
+
API 令牌
|
|
276
|
+
</button>
|
|
277
|
+
<button type="button" class="settings-menu-item" role="menuitem" id="menu-item-password">
|
|
278
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
|
|
279
|
+
修改密码
|
|
280
|
+
</button>
|
|
281
|
+
<button type="button" class="settings-menu-item" role="menuitem" id="menu-item-profile">
|
|
282
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
|
283
|
+
个人资料
|
|
284
|
+
</button>
|
|
285
|
+
<div class="settings-menu-divider admin-only" role="separator"></div>
|
|
286
|
+
<button type="button" class="settings-menu-item admin-only" role="menuitem" id="menu-item-users">
|
|
287
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
|
|
288
|
+
用户管理
|
|
289
|
+
</button>
|
|
290
|
+
<button type="button" class="settings-menu-item admin-only" role="menuitem" id="menu-item-backup">
|
|
291
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
|
292
|
+
数据管理
|
|
293
|
+
</button>
|
|
294
|
+
</div>
|
|
295
|
+
</div>
|
|
296
|
+
<button type="button" class="btn btn-small" id="btn-logout" aria-label="退出登录">退出</button>
|
|
297
|
+
</div>
|
|
298
|
+
</header>
|
|
299
|
+
<div class="email-verify-banner" id="email-verify-banner" hidden>
|
|
300
|
+
<span>请验证你的邮箱地址</span>
|
|
301
|
+
<button type="button" class="btn btn-small" id="btn-resend-verify">重新发送验证邮件</button>
|
|
302
|
+
</div>
|
|
303
|
+
<main class="main">
|
|
304
|
+
<div class="toolbar">
|
|
305
|
+
<div class="upload-area" id="upload-area" role="button" tabindex="0" aria-label="选择或拖入 HTML、Markdown 文件上传">
|
|
306
|
+
<input type="file" id="file-input" accept=".html,.htm,.md,.markdown,.zip" hidden aria-label="选择要上传的文件">
|
|
307
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg>
|
|
308
|
+
<p class="upload-title">点击或拖拽上传</p>
|
|
309
|
+
<span class="upload-hint">支持 .html .htm .md .markdown .zip,单文件最大 50MB</span>
|
|
310
|
+
</div>
|
|
311
|
+
<label class="upload-privacy">
|
|
312
|
+
<input type="checkbox" id="upload-is-public" checked>
|
|
313
|
+
<span>公开访问(未勾选则仅自己可访问)</span>
|
|
314
|
+
</label>
|
|
315
|
+
<div class="upload-progress" id="upload-progress" style="display:none">
|
|
316
|
+
<div class="upload-progress-bar" id="upload-progress-bar"></div>
|
|
317
|
+
<span class="upload-progress-text" id="upload-progress-text">0%</span>
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
<div class="file-list-header">
|
|
321
|
+
<label class="file-checkbox-wrap select-all-wrap">
|
|
322
|
+
<input type="checkbox" id="select-all-checkbox" aria-label="全选">
|
|
323
|
+
<span class="file-checkbox-visual"></span>
|
|
324
|
+
</label>
|
|
325
|
+
<h2>文件列表</h2>
|
|
326
|
+
<span class="file-count" id="file-count" aria-live="polite"></span>
|
|
327
|
+
</div>
|
|
328
|
+
<div class="file-filter-bar">
|
|
329
|
+
<div class="search-input-wrap">
|
|
330
|
+
<svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
|
|
331
|
+
<input type="text" id="search-input" placeholder="搜索文件名和内容… (/)" autocomplete="off">
|
|
332
|
+
<button type="button" class="search-clear" id="search-clear" hidden aria-label="清除搜索">×</button>
|
|
333
|
+
<span class="search-kbd" id="search-kbd">/</span>
|
|
334
|
+
</div>
|
|
335
|
+
<div class="filter-chips">
|
|
336
|
+
<button type="button" class="filter-chip active" data-filter="all">全部</button>
|
|
337
|
+
<button type="button" class="filter-chip" data-filter="html">HTML</button>
|
|
338
|
+
<button type="button" class="filter-chip" data-filter="markdown">Markdown</button>
|
|
339
|
+
<span class="filter-divider" aria-hidden="true"></span>
|
|
340
|
+
<button type="button" class="filter-chip" data-filter="public">公开</button>
|
|
341
|
+
<button type="button" class="filter-chip" data-filter="private">私有</button>
|
|
342
|
+
<span class="filter-divider" aria-hidden="true"></span>
|
|
343
|
+
<button type="button" class="filter-chip" data-filter="starred">☆ 收藏</button>
|
|
344
|
+
<div class="filter-dropdown" id="tag-filter-dropdown">
|
|
345
|
+
<button type="button" class="filter-chip filter-dropdown-trigger">标签 ▾</button>
|
|
346
|
+
<div class="filter-dropdown-menu" id="tag-filter-menu"></div>
|
|
347
|
+
</div>
|
|
348
|
+
<div class="filter-dropdown" id="category-filter-dropdown">
|
|
349
|
+
<button type="button" class="filter-chip filter-dropdown-trigger">分类 ▾</button>
|
|
350
|
+
<div class="filter-dropdown-menu" id="category-filter-menu"></div>
|
|
351
|
+
</div>
|
|
352
|
+
</div>
|
|
353
|
+
</div>
|
|
354
|
+
<div class="file-list" id="file-list" aria-busy="false"></div>
|
|
355
|
+
<div class="empty-state" id="empty-state" style="display:none">
|
|
356
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
|
|
357
|
+
<p>暂无文件,请上传</p>
|
|
358
|
+
<button type="button" class="empty-state-cta" id="empty-state-cta"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg>上传文件</button>
|
|
359
|
+
</div>
|
|
360
|
+
<!-- Batch Toolbar -->
|
|
361
|
+
<div class="batch-toolbar" id="batch-toolbar" hidden>
|
|
362
|
+
<button type="button" class="btn btn-small btn-danger" id="batch-delete">删除</button>
|
|
363
|
+
<button type="button" class="btn btn-small" id="batch-set-public">设为公开</button>
|
|
364
|
+
<button type="button" class="btn btn-small" id="batch-set-private">设为私有</button>
|
|
365
|
+
<div class="batch-category-wrap">
|
|
366
|
+
<select id="batch-category-select" class="batch-category-select">
|
|
367
|
+
<option value="">移动到分类…</option>
|
|
368
|
+
<option value="">未分类</option>
|
|
369
|
+
</select>
|
|
370
|
+
</div>
|
|
371
|
+
<button type="button" class="btn btn-small" id="batch-cancel">取消选择</button>
|
|
372
|
+
</div>
|
|
373
|
+
</main>
|
|
374
|
+
</div>
|
|
375
|
+
</template>
|
|
376
|
+
|
|
377
|
+
<!-- 文件预览模板 -->
|
|
378
|
+
<template id="preview-template">
|
|
379
|
+
<div class="layout preview-layout" id="preview-layout-root">
|
|
380
|
+
<header class="header header-preview" id="preview-header">
|
|
381
|
+
<div class="preview-topbar">
|
|
382
|
+
<button type="button" class="preview-title-strip" id="preview-title-expand" aria-controls="preview-toolbar-expanded" aria-expanded="true">
|
|
383
|
+
<span id="preview-title" class="preview-title-text">加载中…</span>
|
|
384
|
+
<svg class="preview-title-strip-hint" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="6 9 12 15 18 9"></polyline></svg>
|
|
385
|
+
</button>
|
|
386
|
+
<div class="preview-toolbar-expanded" id="preview-toolbar-expanded" role="region" aria-label="预览工具栏">
|
|
387
|
+
<div class="preview-expanded-row">
|
|
388
|
+
<div class="preview-expanded-left">
|
|
389
|
+
<button type="button" class="btn btn-small" id="btn-back" aria-label="返回文件列表">
|
|
390
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="15 18 9 12 15 6"></polyline></svg>
|
|
391
|
+
<span class="btn-back-label">返回</span>
|
|
392
|
+
</button>
|
|
393
|
+
<h2 id="preview-heading" class="preview-heading-truncate"></h2>
|
|
394
|
+
</div>
|
|
395
|
+
<div class="preview-expanded-right">
|
|
396
|
+
<div class="view-toggle" role="group" aria-label="预览模式">
|
|
397
|
+
<button type="button" class="btn btn-small active" data-mode="render">渲染</button>
|
|
398
|
+
<button type="button" class="btn btn-small" data-mode="source">源码</button>
|
|
399
|
+
<button type="button" class="btn btn-small" data-mode="edit" id="btn-edit" hidden>编辑</button>
|
|
400
|
+
</div>
|
|
401
|
+
<div class="preview-more-dropdown" id="preview-more-dropdown">
|
|
402
|
+
<button type="button" class="btn btn-small preview-more-trigger" id="btn-preview-more" aria-label="更多操作" aria-haspopup="true" aria-expanded="false">
|
|
403
|
+
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" style="width:16px;height:16px"><circle cx="12" cy="5" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="19" r="2"/></svg>
|
|
404
|
+
</button>
|
|
405
|
+
<div class="preview-more-menu" id="preview-more-menu">
|
|
406
|
+
<button type="button" class="settings-menu-item" id="menu-download">
|
|
407
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
|
408
|
+
下载
|
|
409
|
+
</button>
|
|
410
|
+
<button type="button" class="settings-menu-item" id="menu-upload-version">
|
|
411
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
|
|
412
|
+
上传新版本
|
|
413
|
+
</button>
|
|
414
|
+
<button type="button" class="settings-menu-item" id="menu-version-history">
|
|
415
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
|
416
|
+
历史
|
|
417
|
+
</button>
|
|
418
|
+
<button type="button" class="settings-menu-item" id="menu-template" hidden>
|
|
419
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="3" y1="9" x2="21" y2="9"/><line x1="9" y1="21" x2="9" y2="9"/></svg>
|
|
420
|
+
模板
|
|
421
|
+
</button>
|
|
422
|
+
<button type="button" class="settings-menu-item" id="menu-stats" hidden>
|
|
423
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M18 20V10"/><path d="M12 20V4"/><path d="M6 20v-6"/></svg>
|
|
424
|
+
统计
|
|
425
|
+
</button>
|
|
426
|
+
<button type="button" class="settings-menu-item theme-toggle" id="menu-theme-toggle" aria-label="切换主题">
|
|
427
|
+
<svg class="icon-moon" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/></svg>
|
|
428
|
+
切换主题
|
|
429
|
+
</button>
|
|
430
|
+
</div>
|
|
431
|
+
</div>
|
|
432
|
+
<button type="button" class="btn btn-small btn-primary" id="btn-editor-save" hidden>保存</button>
|
|
433
|
+
<button type="button" class="btn btn-small" id="btn-editor-cancel" hidden>取消</button>
|
|
434
|
+
<button type="button" class="btn btn-small btn-header-fold" id="btn-toggle-preview-header" aria-expanded="true" aria-controls="preview-header" aria-label="收起顶栏" title="收起顶栏">
|
|
435
|
+
<svg class="icon-fold-chevron icon-fold-chevron--up" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="18 15 12 9 6 15"></polyline></svg>
|
|
436
|
+
<svg class="icon-fold-chevron icon-fold-chevron--down" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="6 9 12 15 18 9"></polyline></svg>
|
|
437
|
+
</button>
|
|
438
|
+
</div>
|
|
439
|
+
</div>
|
|
440
|
+
</div>
|
|
441
|
+
</div>
|
|
442
|
+
</header>
|
|
443
|
+
<button type="button" class="preview-expand-floating" id="btn-preview-expand-floating" aria-label="展开顶栏" title="展开顶栏">
|
|
444
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="6 9 12 15 18 9"></polyline></svg>
|
|
445
|
+
</button>
|
|
446
|
+
<input type="file" id="version-file-input" accept=".html,.htm,.md,.markdown" hidden aria-label="选择要上传的新版本文件">
|
|
447
|
+
<div class="preview-container">
|
|
448
|
+
<div class="version-panel" id="version-panel" hidden>
|
|
449
|
+
<div class="version-panel-header">
|
|
450
|
+
<h3>版本历史</h3>
|
|
451
|
+
<button type="button" class="btn btn-small" id="btn-close-version-panel" aria-label="关闭">✕</button>
|
|
452
|
+
</div>
|
|
453
|
+
<div class="version-panel-body" id="version-panel-body"></div>
|
|
454
|
+
</div>
|
|
455
|
+
<div class="preview-spinner" id="preview-spinner">
|
|
456
|
+
<div class="spinner"></div>
|
|
457
|
+
<span>加载中…</span>
|
|
458
|
+
</div>
|
|
459
|
+
<iframe id="preview-iframe" sandbox="allow-scripts"></iframe>
|
|
460
|
+
<div id="source-wrap" class="source-wrap">
|
|
461
|
+
<aside id="bundle-tree" class="bundle-tree" hidden aria-label="网站包文件">
|
|
462
|
+
<div class="bundle-tree-header">
|
|
463
|
+
<span class="bundle-tree-title">文件</span>
|
|
464
|
+
<span class="bundle-tree-count" id="bundle-tree-count"></span>
|
|
465
|
+
</div>
|
|
466
|
+
<div class="bundle-tree-body" id="bundle-tree-body"></div>
|
|
467
|
+
</aside>
|
|
468
|
+
<pre id="preview-source" class="source-view"><code id="source-code"></code></pre>
|
|
469
|
+
</div>
|
|
470
|
+
<div class="editor-container" id="editor-container" hidden>
|
|
471
|
+
<div class="editor-wrap">
|
|
472
|
+
<div class="editor-gutter" id="editor-gutter" aria-hidden="true"></div>
|
|
473
|
+
<textarea class="editor-textarea" id="editor-textarea" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off"></textarea>
|
|
474
|
+
</div>
|
|
475
|
+
<div class="editor-statusbar" id="editor-statusbar"></div>
|
|
476
|
+
</div>
|
|
477
|
+
</div>
|
|
478
|
+
</div>
|
|
479
|
+
</template>
|
|
480
|
+
|
|
481
|
+
<!-- Skill 详情弹窗 -->
|
|
482
|
+
<div class="modal-backdrop" id="skill-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="skill-modal-title">
|
|
483
|
+
<div class="modal-panel">
|
|
484
|
+
<div class="modal-header">
|
|
485
|
+
<h2 id="skill-modal-title">Skill 详情</h2>
|
|
486
|
+
<button type="button" class="btn btn-small modal-close" id="skill-modal-close" aria-label="关闭">×</button>
|
|
487
|
+
</div>
|
|
488
|
+
<div class="modal-body">
|
|
489
|
+
<div class="skill-modal-meta" id="skill-modal-meta"></div>
|
|
490
|
+
<h3>文件清单</h3>
|
|
491
|
+
<ul class="skill-file-tree" id="skill-modal-files"></ul>
|
|
492
|
+
<h3>SKILL.md 全文(Claude 读到的内容)</h3>
|
|
493
|
+
<pre class="skill-modal-source"><code id="skill-modal-source"></code></pre>
|
|
494
|
+
<h3 id="skill-install-heading" style="display:none">安装指引(人类看的)</h3>
|
|
495
|
+
<div class="skill-install-rendered" id="skill-install-rendered"></div>
|
|
496
|
+
</div>
|
|
497
|
+
<div class="modal-footer">
|
|
498
|
+
<button type="button" class="btn" id="skill-modal-download">下载 .zip</button>
|
|
499
|
+
<button type="button" class="btn btn-small" id="skill-modal-dismiss">关闭</button>
|
|
500
|
+
</div>
|
|
501
|
+
</div>
|
|
502
|
+
</div>
|
|
503
|
+
|
|
504
|
+
<!-- MCP 配置弹窗 -->
|
|
505
|
+
<div class="modal-backdrop" id="mcp-config-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="mcp-config-title">
|
|
506
|
+
<div class="modal-panel">
|
|
507
|
+
<div class="modal-header">
|
|
508
|
+
<h2 id="mcp-config-title">MCP 配置</h2>
|
|
509
|
+
<button type="button" class="btn btn-small modal-close" id="mcp-config-close" aria-label="关闭">×</button>
|
|
510
|
+
</div>
|
|
511
|
+
<div class="modal-body">
|
|
512
|
+
<div class="mcp-status" id="mcp-status"></div>
|
|
513
|
+
<div class="mcp-detail" id="mcp-detail"></div>
|
|
514
|
+
</div>
|
|
515
|
+
<div class="modal-footer">
|
|
516
|
+
<button type="button" class="btn btn-small" id="mcp-config-dismiss">关闭</button>
|
|
517
|
+
</div>
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
520
|
+
|
|
521
|
+
<!-- Skills 列表弹窗 -->
|
|
522
|
+
<div class="modal-backdrop" id="skills-list-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="skills-list-title">
|
|
523
|
+
<div class="modal-panel modal-panel-wide">
|
|
524
|
+
<div class="modal-header">
|
|
525
|
+
<h2 id="skills-list-title">AI 技能 (Skills)</h2>
|
|
526
|
+
<button type="button" class="btn btn-small modal-close" id="skills-list-close" aria-label="关闭">×</button>
|
|
527
|
+
</div>
|
|
528
|
+
<div class="modal-body">
|
|
529
|
+
<p class="skills-hint">MCP 已启用后,可下载 Skill 包并安装到 Claude Code / Claude Desktop,让 AI 直接上传文件到即页。</p>
|
|
530
|
+
<div class="skills-list" id="skills-list" aria-busy="false"></div>
|
|
531
|
+
<div class="empty-state empty-state-sm" id="skills-empty" style="display:none">
|
|
532
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M12 2L2 7l10 5 10-5-10-5z"></path><polyline points="2 17 12 22 22 17"></polyline><polyline points="2 12 12 17 22 12"></polyline></svg>
|
|
533
|
+
<p>暂无可用 Skill</p>
|
|
534
|
+
</div>
|
|
535
|
+
</div>
|
|
536
|
+
<div class="modal-footer">
|
|
537
|
+
<button type="button" class="btn btn-small" id="skills-list-dismiss">关闭</button>
|
|
538
|
+
</div>
|
|
539
|
+
</div>
|
|
540
|
+
</div>
|
|
541
|
+
|
|
542
|
+
<!-- 通用交互 Modal (prompt / confirm / alert) -->
|
|
543
|
+
|
|
544
|
+
<!-- 用户管理弹窗(仅 admin) -->
|
|
545
|
+
<div class="modal-backdrop" id="users-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="users-modal-title">
|
|
546
|
+
<div class="modal-panel modal-panel-wide">
|
|
547
|
+
<div class="modal-header">
|
|
548
|
+
<h2 id="users-modal-title">用户管理</h2>
|
|
549
|
+
<button type="button" class="btn btn-small modal-close" id="users-modal-close" aria-label="关闭">×</button>
|
|
550
|
+
</div>
|
|
551
|
+
<div class="modal-body">
|
|
552
|
+
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px">
|
|
553
|
+
<p class="modal-hint">管理用户账户和角色分配</p>
|
|
554
|
+
<button type="button" class="btn btn-primary btn-small" id="btn-create-user">+ 创建用户</button>
|
|
555
|
+
</div>
|
|
556
|
+
<div class="users-table-wrap" id="users-table-wrap"></div>
|
|
557
|
+
</div>
|
|
558
|
+
<div class="modal-footer">
|
|
559
|
+
<button type="button" class="btn btn-small" id="users-modal-dismiss">关闭</button>
|
|
560
|
+
</div>
|
|
561
|
+
</div>
|
|
562
|
+
</div>
|
|
563
|
+
|
|
564
|
+
<!-- API 令牌管理弹窗 -->
|
|
565
|
+
<div class="modal-backdrop" id="tokens-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="tokens-modal-title">
|
|
566
|
+
<div class="modal-panel modal-panel-wide">
|
|
567
|
+
<div class="modal-header">
|
|
568
|
+
<h2 id="tokens-modal-title">API 令牌</h2>
|
|
569
|
+
<button type="button" class="btn btn-small modal-close" id="tokens-modal-close" aria-label="关闭">×</button>
|
|
570
|
+
</div>
|
|
571
|
+
<div class="modal-body">
|
|
572
|
+
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px">
|
|
573
|
+
<p class="modal-hint">令牌用于 MCP 端点或 API 调用鉴权。可在列表中随时查看并复制。</p>
|
|
574
|
+
<button type="button" class="btn btn-primary btn-small" id="btn-create-token">+ 创建令牌</button>
|
|
575
|
+
</div>
|
|
576
|
+
<div class="tokens-list" id="tokens-list"></div>
|
|
577
|
+
</div>
|
|
578
|
+
<div class="modal-footer">
|
|
579
|
+
<button type="button" class="btn btn-small" id="tokens-modal-dismiss">关闭</button>
|
|
580
|
+
</div>
|
|
581
|
+
</div>
|
|
582
|
+
</div>
|
|
583
|
+
|
|
584
|
+
<!-- 令牌明文查看弹窗 -->
|
|
585
|
+
<div class="modal-backdrop" id="token-reveal-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="token-reveal-modal-title">
|
|
586
|
+
<div class="modal-panel modal-panel-sm">
|
|
587
|
+
<div class="modal-header">
|
|
588
|
+
<h2 id="token-reveal-modal-title">查看令牌</h2>
|
|
589
|
+
<button type="button" class="btn btn-small modal-close" id="token-reveal-modal-close" aria-label="关闭">×</button>
|
|
590
|
+
</div>
|
|
591
|
+
<div class="modal-body">
|
|
592
|
+
<p class="modal-hint" id="token-reveal-modal-name" style="margin-bottom:8px"></p>
|
|
593
|
+
<input type="text" id="token-reveal-modal-input" class="token-reveal-input" readonly autocomplete="off">
|
|
594
|
+
</div>
|
|
595
|
+
<div class="modal-footer">
|
|
596
|
+
<button type="button" class="btn btn-primary btn-small" id="token-reveal-modal-copy">复制</button>
|
|
597
|
+
<button type="button" class="btn btn-small" id="token-reveal-modal-dismiss">关闭</button>
|
|
598
|
+
</div>
|
|
599
|
+
</div>
|
|
600
|
+
</div>
|
|
601
|
+
|
|
602
|
+
<!-- 修改密码弹窗 -->
|
|
603
|
+
<div class="modal-backdrop" id="password-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="password-modal-title">
|
|
604
|
+
<div class="modal-panel modal-panel-sm">
|
|
605
|
+
<div class="modal-header">
|
|
606
|
+
<h2 id="password-modal-title">修改密码</h2>
|
|
607
|
+
<button type="button" class="btn btn-small modal-close" id="password-modal-close" aria-label="关闭">×</button>
|
|
608
|
+
</div>
|
|
609
|
+
<div class="modal-body">
|
|
610
|
+
<label class="login-field">
|
|
611
|
+
<span>当前密码</span>
|
|
612
|
+
<input type="password" id="current-password" autocomplete="current-password">
|
|
613
|
+
</label>
|
|
614
|
+
<label class="login-field">
|
|
615
|
+
<span>新密码(至少 8 位)</span>
|
|
616
|
+
<input type="password" id="new-password" autocomplete="new-password">
|
|
617
|
+
</label>
|
|
618
|
+
<label class="login-field">
|
|
619
|
+
<span>确认新密码</span>
|
|
620
|
+
<input type="password" id="confirm-password" autocomplete="new-password">
|
|
621
|
+
</label>
|
|
622
|
+
<div class="login-error" id="password-error" role="alert" hidden></div>
|
|
623
|
+
</div>
|
|
624
|
+
<div class="modal-footer">
|
|
625
|
+
<button type="button" class="btn btn-small" id="password-modal-cancel">取消</button>
|
|
626
|
+
<button type="button" class="btn btn-primary" id="password-modal-submit">修改密码</button>
|
|
627
|
+
</div>
|
|
628
|
+
</div>
|
|
629
|
+
</div>
|
|
630
|
+
|
|
631
|
+
<!-- 个人资料弹窗 -->
|
|
632
|
+
<div class="modal-backdrop" id="profile-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="profile-modal-title">
|
|
633
|
+
<div class="modal-panel modal-panel-sm">
|
|
634
|
+
<div class="modal-header">
|
|
635
|
+
<h2 id="profile-modal-title">个人资料</h2>
|
|
636
|
+
<button type="button" class="btn btn-small modal-close" id="profile-modal-close" aria-label="关闭">×</button>
|
|
637
|
+
</div>
|
|
638
|
+
<div class="modal-body">
|
|
639
|
+
<label class="login-field">
|
|
640
|
+
<span>用户名</span>
|
|
641
|
+
<input type="text" id="profile-username" autocomplete="username" placeholder="字母、数字、下划线,2-30 位">
|
|
642
|
+
</label>
|
|
643
|
+
<label class="login-field">
|
|
644
|
+
<span>邮箱</span>
|
|
645
|
+
<input type="email" id="profile-email" autocomplete="email" placeholder="可选">
|
|
646
|
+
</label>
|
|
647
|
+
<div class="login-error" id="profile-error" role="alert" hidden></div>
|
|
648
|
+
</div>
|
|
649
|
+
<div class="modal-footer">
|
|
650
|
+
<button type="button" class="btn btn-small" id="profile-modal-cancel">取消</button>
|
|
651
|
+
<button type="button" class="btn btn-primary" id="profile-modal-submit">保存</button>
|
|
652
|
+
</div>
|
|
653
|
+
</div>
|
|
654
|
+
</div>
|
|
655
|
+
|
|
656
|
+
<!-- 数据管理弹窗 -->
|
|
657
|
+
<div class="modal-backdrop" id="backup-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="backup-modal-title">
|
|
658
|
+
<div class="modal-panel modal-panel-sm">
|
|
659
|
+
<div class="modal-header">
|
|
660
|
+
<h2 id="backup-modal-title">数据管理</h2>
|
|
661
|
+
<button type="button" class="btn btn-small modal-close" id="backup-modal-close" aria-label="关闭">×</button>
|
|
662
|
+
</div>
|
|
663
|
+
<div class="modal-body">
|
|
664
|
+
<div id="backup-stats" style="margin-bottom:16px"></div>
|
|
665
|
+
<div style="display:flex;gap:10px;flex-wrap:wrap">
|
|
666
|
+
<button type="button" class="btn btn-primary btn-small" id="btn-export-backup">导出备份</button>
|
|
667
|
+
<button type="button" class="btn btn-small" id="btn-import-backup">导入恢复</button>
|
|
668
|
+
</div>
|
|
669
|
+
<input type="file" id="import-file-input" accept=".zip" style="display:none">
|
|
670
|
+
</div>
|
|
671
|
+
<div class="modal-footer">
|
|
672
|
+
<button type="button" class="btn btn-small" id="backup-modal-dismiss">关闭</button>
|
|
673
|
+
</div>
|
|
674
|
+
</div>
|
|
675
|
+
</div>
|
|
676
|
+
|
|
677
|
+
<div class="modal-backdrop" id="dialog-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="dialog-modal-title">
|
|
678
|
+
<div class="modal-panel modal-panel-sm">
|
|
679
|
+
<div class="modal-header">
|
|
680
|
+
<h2 id="dialog-modal-title"></h2>
|
|
681
|
+
<button type="button" class="btn btn-small modal-close" id="dialog-modal-close" aria-label="关闭">×</button>
|
|
682
|
+
</div>
|
|
683
|
+
<div class="modal-body">
|
|
684
|
+
<div class="dialog-message" id="dialog-modal-message"></div>
|
|
685
|
+
<label class="login-field dialog-field" id="dialog-modal-field" hidden>
|
|
686
|
+
<span id="dialog-modal-label"></span>
|
|
687
|
+
<input type="text" id="dialog-modal-input" autocomplete="off">
|
|
688
|
+
</label>
|
|
689
|
+
<div class="login-error" id="dialog-modal-error" role="alert" hidden></div>
|
|
690
|
+
</div>
|
|
691
|
+
<div class="modal-footer">
|
|
692
|
+
<button type="button" class="btn btn-small" id="dialog-modal-cancel">取消</button>
|
|
693
|
+
<button type="button" class="btn btn-primary" id="dialog-modal-confirm">确认</button>
|
|
694
|
+
</div>
|
|
695
|
+
</div>
|
|
696
|
+
</div>
|
|
697
|
+
|
|
698
|
+
<!-- 标签编辑器弹窗 -->
|
|
699
|
+
<div class="modal-backdrop" id="tag-editor-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="tag-editor-title">
|
|
700
|
+
<div class="modal-panel modal-panel-sm">
|
|
701
|
+
<div class="modal-header">
|
|
702
|
+
<h2 id="tag-editor-title">编辑标签</h2>
|
|
703
|
+
<button type="button" class="btn btn-small modal-close" id="tag-editor-close" aria-label="关闭">×</button>
|
|
704
|
+
</div>
|
|
705
|
+
<div class="modal-body">
|
|
706
|
+
<div class="tag-editor-selected" id="tag-editor-selected"></div>
|
|
707
|
+
<div class="tag-editor-input-wrap">
|
|
708
|
+
<input type="text" id="tag-editor-input" placeholder="输入标签名,回车添加…" autocomplete="off">
|
|
709
|
+
<ul class="tag-editor-suggestions" id="tag-editor-suggestions"></ul>
|
|
710
|
+
</div>
|
|
711
|
+
</div>
|
|
712
|
+
<div class="modal-footer">
|
|
713
|
+
<button type="button" class="btn btn-small" id="tag-editor-cancel">取消</button>
|
|
714
|
+
<button type="button" class="btn btn-primary" id="tag-editor-save">保存</button>
|
|
715
|
+
</div>
|
|
716
|
+
</div>
|
|
717
|
+
</div>
|
|
718
|
+
|
|
719
|
+
<!-- 分类选择弹窗 -->
|
|
720
|
+
<div class="modal-backdrop" id="category-select-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="category-select-title">
|
|
721
|
+
<div class="modal-panel modal-panel-sm">
|
|
722
|
+
<div class="modal-header">
|
|
723
|
+
<h2 id="category-select-title">选择分类</h2>
|
|
724
|
+
<div style="display:flex;gap:6px">
|
|
725
|
+
<button type="button" class="btn btn-small btn-primary" id="category-select-create">新建</button>
|
|
726
|
+
<button type="button" class="btn btn-small modal-close" id="category-select-close" aria-label="关闭">×</button>
|
|
727
|
+
</div>
|
|
728
|
+
</div>
|
|
729
|
+
<div class="modal-body">
|
|
730
|
+
<div id="category-select-list"></div>
|
|
731
|
+
</div>
|
|
732
|
+
<div class="modal-footer">
|
|
733
|
+
<button type="button" class="btn btn-small" id="category-select-cancel">取消</button>
|
|
734
|
+
</div>
|
|
735
|
+
</div>
|
|
736
|
+
</div>
|
|
737
|
+
|
|
738
|
+
<!-- 模板选择弹窗 -->
|
|
739
|
+
<div class="modal-backdrop" id="template-select-modal" hidden aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="template-select-title">
|
|
740
|
+
<div class="modal-panel modal-panel-sm">
|
|
741
|
+
<div class="modal-header">
|
|
742
|
+
<h2 id="template-select-title">渲染模板</h2>
|
|
743
|
+
<button type="button" class="btn btn-small modal-close" id="template-select-close" aria-label="关闭">×</button>
|
|
744
|
+
</div>
|
|
745
|
+
<div class="modal-body">
|
|
746
|
+
<div id="template-select-list"></div>
|
|
747
|
+
</div>
|
|
748
|
+
<div class="modal-footer">
|
|
749
|
+
<button type="button" class="btn btn-small" id="template-select-cancel">取消</button>
|
|
750
|
+
</div>
|
|
751
|
+
</div>
|
|
752
|
+
</div>
|
|
753
|
+
|
|
754
|
+
<!-- 内容模板市场弹窗 -->
|
|
755
|
+
<div class="modal-backdrop" id="ct-market-modal" hidden aria-hidden="true" role="dialog" aria-modal="true">
|
|
756
|
+
<div class="modal-panel modal-panel-wide">
|
|
757
|
+
<div class="modal-header">
|
|
758
|
+
<h2>内容模板市场</h2>
|
|
759
|
+
<div style="display:flex;gap:6px">
|
|
760
|
+
<button type="button" class="btn btn-small btn-primary" id="ct-market-upload">+ 上传模板</button>
|
|
761
|
+
<button type="button" class="btn btn-small modal-close" id="ct-market-close" aria-label="关闭">×</button>
|
|
762
|
+
</div>
|
|
763
|
+
</div>
|
|
764
|
+
<div class="modal-body">
|
|
765
|
+
<div class="ct-filter-bar">
|
|
766
|
+
<div class="search-input-wrap"><input type="text" id="ct-search" placeholder="搜索模板..."></div>
|
|
767
|
+
<div class="filter-chips" id="ct-scene-chips">
|
|
768
|
+
<button class="filter-chip active" data-scene="">全部</button>
|
|
769
|
+
<button class="filter-chip" data-scene="dashboard">仪表板</button>
|
|
770
|
+
<button class="filter-chip" data-scene="report">报告</button>
|
|
771
|
+
<button class="filter-chip" data-scene="resume">简历</button>
|
|
772
|
+
<button class="filter-chip" data-scene="landing">落地页</button>
|
|
773
|
+
<button class="filter-chip" data-scene="note">笔记</button>
|
|
774
|
+
<button class="filter-chip" data-scene="presentation">演示</button>
|
|
775
|
+
<button class="filter-chip" data-scene="card">卡片</button>
|
|
776
|
+
<button class="filter-chip" data-scene="email">邮件</button>
|
|
777
|
+
<button class="filter-chip" data-scene="other">其他</button>
|
|
778
|
+
</div>
|
|
779
|
+
</div>
|
|
780
|
+
<div class="ct-grid" id="ct-grid"></div>
|
|
781
|
+
</div>
|
|
782
|
+
<div class="modal-footer">
|
|
783
|
+
<button type="button" class="btn btn-small" id="ct-market-dismiss">关闭</button>
|
|
784
|
+
</div>
|
|
785
|
+
</div>
|
|
786
|
+
</div>
|
|
787
|
+
|
|
788
|
+
<!-- 内容模板上传弹窗 -->
|
|
789
|
+
<div class="modal-backdrop" id="ct-upload-modal" hidden aria-hidden="true" role="dialog" aria-modal="true">
|
|
790
|
+
<div class="modal-panel modal-panel-wide">
|
|
791
|
+
<div class="modal-header">
|
|
792
|
+
<h2>上传内容模板</h2>
|
|
793
|
+
<button type="button" class="btn btn-small modal-close" id="ct-upload-close" aria-label="关闭">×</button>
|
|
794
|
+
</div>
|
|
795
|
+
<div class="modal-body" style="display:flex;flex-direction:column;gap:16px">
|
|
796
|
+
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px 16px">
|
|
797
|
+
<label class="login-field"><span>模板标题 *</span><input type="text" id="ct-upload-title" placeholder="如:暗色数据仪表板"></label>
|
|
798
|
+
<label class="login-field"><span>文件类型</span>
|
|
799
|
+
<select id="ct-upload-filetype">
|
|
800
|
+
<option value="html">HTML</option>
|
|
801
|
+
<option value="markdown">Markdown</option>
|
|
802
|
+
</select>
|
|
803
|
+
</label>
|
|
804
|
+
</div>
|
|
805
|
+
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px 16px">
|
|
806
|
+
<label class="login-field"><span>使用场景</span>
|
|
807
|
+
<select id="ct-upload-scene">
|
|
808
|
+
<option value="">不指定</option>
|
|
809
|
+
<option value="dashboard">数据仪表板</option>
|
|
810
|
+
<option value="report">报告</option>
|
|
811
|
+
<option value="resume">简历/名片</option>
|
|
812
|
+
<option value="landing">落地页</option>
|
|
813
|
+
<option value="note">笔记/文档</option>
|
|
814
|
+
<option value="presentation">演示/幻灯片</option>
|
|
815
|
+
<option value="card">卡片/海报</option>
|
|
816
|
+
<option value="email">邮件</option>
|
|
817
|
+
<option value="other">其他</option>
|
|
818
|
+
</select>
|
|
819
|
+
</label>
|
|
820
|
+
<label class="login-field"><span>风格描述</span><input type="text" id="ct-upload-desc" placeholder="如:深色主题,CSS Grid 展示"></label>
|
|
821
|
+
<label class="login-field"><span>风格标签</span><input type="text" id="ct-upload-tags" placeholder="如:dark, minimal"></label>
|
|
822
|
+
</div>
|
|
823
|
+
<label class="login-field" style="flex:1"><span>样例内容 *</span><textarea id="ct-upload-content" rows="12" placeholder="粘贴完整的 HTML 或 Markdown 样例内容" style="font-family:monospace;font-size:13px;min-height:200px;resize:vertical"></textarea></label>
|
|
824
|
+
<label class="login-field" style="flex-direction:row;gap:6px;align-items:center"><input type="checkbox" id="ct-upload-public" checked><span style="font-size:14px;color:var(--text-secondary)">公开(其他用户可见)</span></label>
|
|
825
|
+
</div>
|
|
826
|
+
<div class="modal-footer">
|
|
827
|
+
<button type="button" class="btn btn-small" id="ct-upload-cancel">取消</button>
|
|
828
|
+
<button type="button" class="btn btn-primary btn-small" id="ct-upload-submit">上传</button>
|
|
829
|
+
</div>
|
|
830
|
+
</div>
|
|
831
|
+
</div>
|
|
832
|
+
|
|
833
|
+
<!-- 内容模板详情弹窗 -->
|
|
834
|
+
<div class="modal-backdrop" id="ct-detail-modal" hidden aria-hidden="true" role="dialog" aria-modal="true">
|
|
835
|
+
<div class="modal-panel modal-panel-wide">
|
|
836
|
+
<div class="modal-header">
|
|
837
|
+
<h2 id="ct-detail-title">模板详情</h2>
|
|
838
|
+
<button type="button" class="btn btn-small modal-close" id="ct-detail-close" aria-label="关闭">×</button>
|
|
839
|
+
</div>
|
|
840
|
+
<div class="modal-body">
|
|
841
|
+
<div class="ct-detail-meta" id="ct-detail-meta"></div>
|
|
842
|
+
<div class="ct-detail-preview"><iframe id="ct-detail-iframe" sandbox="allow-scripts" style="width:100%;min-height:400px;border:1px solid var(--border);border-radius:8px"></iframe></div>
|
|
843
|
+
</div>
|
|
844
|
+
<div class="modal-footer">
|
|
845
|
+
<button type="button" class="btn btn-small" id="ct-detail-copy">复制内容</button>
|
|
846
|
+
<button type="button" class="btn btn-small" id="ct-detail-edit">编辑</button>
|
|
847
|
+
<button type="button" class="btn btn-small btn-danger" id="ct-detail-delete">删除</button>
|
|
848
|
+
<button type="button" class="btn btn-small" id="ct-detail-dismiss">关闭</button>
|
|
849
|
+
</div>
|
|
850
|
+
</div>
|
|
851
|
+
</div>
|
|
852
|
+
|
|
853
|
+
<script type="module" src="/js/app.js?v=1.4.1"></script>
|
|
854
|
+
</body>
|
|
855
|
+
</html>
|