From 1da52bfb962387a2fe685d92f0d7f7601b4844a5 Mon Sep 17 00:00:00 2001 From: Gloridust Date: Sun, 14 Jun 2026 18:19:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(v1.2.0):=20UI=20=E6=8C=89=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E7=B1=BB=E5=9E=8B=E6=B3=9B=E5=8C=96=EF=BC=88=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E5=88=B0=E5=A4=84=E5=86=99=E6=AD=BB=E3=80=8C=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E3=80=8D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 APP_PROFILES(label/needsInstall/enterHint/updateLabel)+ appProfile()。 - 实例卡片:状态副文案、"进入实例"提示、安装/更新按钮均按 appType 显示;Chromium 已烤进镜像 (needsInstall=false)故不显示"下载安装/更新",状态直接"已就绪"。 - 桌面页:连接提示语用 enterHint(微信=扫码登录,Chromium=直接使用);安装中/未安装提示、iframe 标题、文件传输/剪贴板/输入条文案改为应用名或通用"应用/桌面"。 - 列表区"微信实例"→"实例"、空状态泛化。 Co-Authored-By: Claude Opus 4.8 --- panel/web/src/api.ts | 18 ++++++++++++++ panel/web/src/pages/Admin.tsx | 22 +++++++++-------- panel/web/src/pages/Desktop.tsx | 44 +++++++++++++++++---------------- 3 files changed, 53 insertions(+), 31 deletions(-) diff --git a/panel/web/src/api.ts b/panel/web/src/api.ts index d8b0b3c..1e553cc 100644 --- a/panel/web/src/api.ts +++ b/panel/web/src/api.ts @@ -26,6 +26,24 @@ export const APP_LABELS: Record = { chromium: 'Chromium', custom: '自定义应用', }; + +// 各应用的 UI 画像,供卡片/桌面页按类型显示正确文案(避免到处写死「微信」)。 +// needsInstall: 是否需要运行时下载安装(微信/Telegram 是;Chromium 已烤进镜像、即创建即就绪)。 +// enterHint: 首次进入实例的提示。 +// updateLabel: 「管理」菜单里的更新按钮文案(needsInstall=false 时不显示)。 +export interface AppProfile { + label: string; + needsInstall: boolean; + enterHint: string; + updateLabel: string; +} +export const APP_PROFILES: Record = { + wechat: { label: '微信', needsInstall: true, enterHint: '首次进入请扫码登录微信', updateLabel: '更新微信' }, + telegram: { label: 'Telegram', needsInstall: true, enterHint: '首次进入请登录 Telegram', updateLabel: '更新 Telegram' }, + chromium: { label: 'Chromium', needsInstall: false, enterHint: '浏览器已就绪,直接使用即可', updateLabel: '' }, + custom: { label: '自定义应用', needsInstall: true, enterHint: '', updateLabel: '更新' }, +}; +export const appProfile = (t?: AppType): AppProfile => APP_PROFILES[t ?? 'wechat'] ?? APP_PROFILES.wechat; export interface PanelInstance { id: string; name: string; diff --git a/panel/web/src/pages/Admin.tsx b/panel/web/src/pages/Admin.tsx index 6247984..5d21c1b 100644 --- a/panel/web/src/pages/Admin.tsx +++ b/panel/web/src/pages/Admin.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { api, APP_LABELS, type PanelUser, type InstanceWithStatus, type VolEntry, type AppType } from '../api'; +import { api, APP_LABELS, appProfile, type PanelUser, type InstanceWithStatus, type VolEntry, type AppType } from '../api'; import { useUI, PasswordInput } from '../ui'; import { useAuth } from '../auth'; @@ -271,7 +271,7 @@ export default function Admin({ onOpenMenu, onChangePassword }: { onOpenMenu: () {isAdmin && ( <>
- 微信实例 + 实例 @@ -279,11 +279,11 @@ export default function Admin({ onOpenMenu, onChangePassword }: { onOpenMenu: () {instances.length === 0 ? ( setCreatingInst(true)}> - + 新建微信实例 + + 新建实例 } /> @@ -899,6 +899,8 @@ function InstanceAdminCard({ return () => document.removeEventListener('mousedown', onDocDown); }, [menuOpen]); + const profile = appProfile(inst.appType); + let badge: { text: string; cls: string }; if (acting) badge = { text: '处理中', cls: 'tag-busy' }; else if (offline) badge = { text: inst.runtime === 'missing' ? '未创建' : '已停止', cls: 'tag-off' }; @@ -911,8 +913,8 @@ function InstanceAdminCard({ else if (busy) sub = wx.percent >= 0 ? `${wx.message || '处理中'} ${wx.percent}%` : wx.message || '请稍候…'; else if (wx.phase === 'error') sub = wx.message || '操作失败,可重试'; else if (offline) sub = inst.runtime === 'missing' ? '容器尚未创建' : '容器已停止'; - else if (installed) sub = wx.version ? `微信 ${wx.version}` : '微信已安装'; - else sub = '微信尚未安装'; + else if (installed) sub = wx.version ? `${profile.label} ${wx.version}` : `${profile.label}已就绪`; + else sub = `${profile.label}尚未安装`; return (
@@ -943,7 +945,7 @@ function InstanceAdminCard({ {inst.runtime === 'missing' ? '创建并启动' : '启动实例'} ) : ( - )} @@ -960,9 +962,9 @@ function InstanceAdminCard({
运维
- {!offline && ( + {!offline && profile.needsInstall && ( )} ) : ( -
请联系管理员在「管理」中下载安装微信
+
请联系管理员在「管理」中下载安装{appLabel}
)} {isAdmin && ( -
也可直接把文件拖进来。下方为桌面(~/Desktop)里的文件,微信收到的文件另存到桌面即可在此下载。
+
也可直接把文件拖进来。下方为桌面(~/Desktop)里的文件,应用收到的文件另存到桌面即可在此下载。
{files.length === 0 && (
@@ -776,17 +778,17 @@ export default function InstanceView({ onOpenMenu }: { onOpenMenu: () => void }) className="clip-area" value={clipText} onChange={(e) => setClipText(e.target.value)} - placeholder="在此输入或粘贴文本,点「发送到微信」后到微信输入框按 Ctrl+V 粘贴" + placeholder="在此输入或粘贴文本,点「发送到剪贴板」后到应用输入框按 Ctrl+V 粘贴" rows={5} />
- 局域网 http 访问时浏览器会禁用系统级剪贴板同步,故用此框中转:文本→容器剪贴板,再在微信里 Ctrl+V。 + 局域网 http 访问时浏览器会禁用系统级剪贴板同步,故用此框中转:文本→容器剪贴板,再在应用里 Ctrl+V。
)} @@ -804,7 +806,7 @@ export default function InstanceView({ onOpenMenu }: { onOpenMenu: () => void }) sendImeText(); } }} - placeholder="中文输入这里 → 回车送进微信(先点好微信的输入框)。Shift+回车换行。" + placeholder="中文输入这里 → 回车送进应用(先点好应用的输入框)。Shift+回车换行。" rows={1} />