diff --git a/platform_web/components/ServerDeploymentWorkflow.tsx b/platform_web/components/ServerDeploymentWorkflow.tsx
index dcc8ae3..b922000 100644
--- a/platform_web/components/ServerDeploymentWorkflow.tsx
+++ b/platform_web/components/ServerDeploymentWorkflow.tsx
@@ -1,4 +1,4 @@
-import { CheckCircle2, CircleDashed, Compass, FolderCog, Rocket, ServerCog } from "lucide-react";
+import { CheckCircle2, CircleDashed, Compass, Download, FolderCog, HeartPulse, Rocket, ScanSearch, ServerCog, SlidersHorizontal } from "lucide-react";
import { type ChangeEvent, type FormEvent, useEffect, useMemo, useState } from "react";
import type { GamePluginResponse, RunEndpointResponse, ServerDeploymentResponse } from "../api/types";
@@ -108,6 +108,7 @@ export function ServerDeploymentWorkflow({ open, kind, plugins, endpoints, initi
)}
))}
+ {form.deploymentMode === "guided-install" && }
{form.deploymentMode === "existing-server" &&
接管只做预检与绑定不会执行安装命令,也不会把本页的默认游戏参数写进已有服务器。
}
{form.deploymentMode === "custom-command" && 高级启动设置
只有自定义启动器需要这些设置。执行目录留空时,节点以服务器目录执行。
}
{kind === "create" && bindingFields.length > 0 && 运行连接设置
用于插件声明的逻辑连接,不是服务器目录或游戏配置。
{bindingFields.map((field) => )}
}
@@ -119,3 +120,19 @@ export function ServerDeploymentWorkflow({ open, kind, plugins, endpoints, initi
}
function ModeOption({ active, title, copy, onClick }: { active: boolean; title: string; copy: string; onClick: () => void }) { return ; }
+
+function GuidedInstallPlan({ pluginName, isScum }: { pluginName: string; isScum: boolean }) {
+ const steps = isScum ? [
+ { icon: ScanSearch, title: "预检目录与端口", copy: "确认安装目录可用、节点兼容且端口可绑定。" },
+ { icon: Download, title: "下载 SCUM Server", copy: "通过 SteamCMD 安装 App 3792580 到该目录。" },
+ { icon: SlidersHorizontal, title: "写入游戏配置", copy: "把本页的名称、端口与人数写入 ServerSettings.ini。" },
+ { icon: HeartPulse, title: "启动并健康验证", copy: "检查可执行文件、版本、配置、端口和服务进程。" }
+ ] : [
+ { icon: ScanSearch, title: "预检目录与节点", copy: "确认安装目录、权限、端口与运行节点可用。" },
+ { icon: Download, title: "安装游戏服务端", copy: "按插件声明的推荐方案安装到该目录。" },
+ { icon: SlidersHorizontal, title: "写入游戏配置", copy: "将本页填写的游戏参数交给受控部署流程。" },
+ { icon: HeartPulse, title: "启动并健康验证", copy: "只有启动与插件要求的验证通过才会显示成功。" }
+ ];
+
+ return 确认后,{pluginName} 会这样安装“安装目录”就是游戏服务端、数据和配置将落地的位置;它不是命令执行目录,也不会在日志中回显。
{isScum ? "全部 4 步通过才算安装成功" : "节点按插件契约执行"}{steps.map(({ icon: Icon, title, copy }, index) => {index + 1}. {title}{copy}
)}
不会做:{isScum ? "不会跳过验证就标记成功;失败时不会暴露你的目录、命令或凭据。" : "不会把受保护的路径、命令或凭据回显给浏览器。"}
;
+}
diff --git a/platform_web/pages/ConsolePages.test.tsx b/platform_web/pages/ConsolePages.test.tsx
index 9215677..56d7d76 100644
--- a/platform_web/pages/ConsolePages.test.tsx
+++ b/platform_web/pages/ConsolePages.test.tsx
@@ -180,6 +180,10 @@ describe("first-party console pages", () => {
expect(serverDeploymentWorkflowSource).toContain("执行目录(可选)");
expect(serverDeploymentWorkflowSource).toContain("默认使用服务器目录");
expect(serverDeploymentWorkflowSource).toContain("安装目录{isScum ? \"(必填)\" : \"(可选)\"}");
+ expect(serverDeploymentWorkflowSource).toContain("新建并安装执行流程");
+ expect(serverDeploymentWorkflowSource).toContain("安装目录”就是游戏服务端、数据和配置将落地的位置");
+ expect(serverDeploymentWorkflowSource).toContain("通过 SteamCMD 安装 App 3792580 到该目录");
+ expect(serverDeploymentWorkflowSource).toContain("全部 4 步通过才算安装成功");
expect(serverDeploymentWorkflowSource).toContain("已有服务器目录");
expect(serverDeploymentWorkflowSource).toContain("不会重装或覆盖现有游戏配置");
expect(serverDeploymentWorkflowSource).toContain("运行连接设置");
diff --git a/platform_web/theme/base-css.test.js b/platform_web/theme/base-css.test.js
index 4afe6bb..14ce563 100644
--- a/platform_web/theme/base-css.test.js
+++ b/platform_web/theme/base-css.test.js
@@ -172,6 +172,14 @@ describe("platform web shared theme CSS", () => {
expect(css).toContain(".deployment-workflow-body.form-grid{align-content:start;align-items:start;grid-auto-rows:min-content}");
});
+ it("keeps the guided-install plan compact and responsive inside the deployment workflow", () => {
+ const css = compact(readThemeCss());
+
+ expect(css).toContain(".guided-install-plan{display:grid;gap:10px;padding:12px;border:1pxsolidcolor-mix(insrgb,var(--accent)42%,var(--line));border-radius:8px");
+ expect(css).toContain(".guided-install-planol{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px");
+ expect(css).toContain(".guided-install-planol,.maintenance-node-item");
+ });
+
it("keeps magical card decoration from becoming square background patches", () => {
const css = compact(readThemeCss());
diff --git a/platform_web/theme/base.css b/platform_web/theme/base.css
index 728d448..851092f 100644
--- a/platform_web/theme/base.css
+++ b/platform_web/theme/base.css
@@ -496,6 +496,7 @@ to{transform:translate(-50%,-50%) rotate(calc(var(--construct-drift) + 360deg))}
.management-dialog-panel .management-form{grid-template-columns:repeat(2,minmax(0,1fr))}
.management-dialog-panel .dialog-form .confirm-actions,.management-dialog-panel .dialog-form .role-selector{grid-column:1/-1}
.server-deployment-workflow{display:grid;gap:14px}.deployment-workflow-steps{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:0;padding:0;list-style:none}.deployment-workflow-steps li{display:flex;align-items:center;gap:6px;min-height:38px;padding:8px;border:1px solid var(--line);border-radius:8px;background:var(--control-surface);color:var(--ink-faint);font-size:12px}.deployment-workflow-steps li>span{display:inline-flex;align-items:center;justify-content:center;color:var(--ink-soft)}.deployment-workflow-steps strong{font-size:12px}.deployment-workflow-step-active{border-color:var(--accent)!important;background:var(--primary-command-surface)!important;color:#fff!important;box-shadow:0 0 16px var(--accent-soft)}.deployment-workflow-step-complete{border-color:color-mix(in srgb,var(--teal) 68%,var(--line));color:var(--ink)!important}.deployment-workflow-body{display:grid;align-content:start;gap:12px;min-height:0}.deployment-workflow-body .form-grid{align-content:start;align-items:start;grid-auto-rows:min-content}.deployment-workflow-body .form-grid>label{align-content:start}.deployment-draft-choice{grid-template-columns:auto minmax(0,1fr);align-items:start;padding:10px 12px;border:1px dashed var(--line-strong);border-radius:8px;background:color-mix(in srgb,var(--surface-solid) 62%,transparent)}.deployment-draft-choice input{width:auto!important;min-height:auto!important;margin-top:3px}.deployment-draft-choice span{display:grid;gap:3px}.deployment-draft-choice small{color:var(--ink-faint);font-weight:600;line-height:1.4}.deployment-mode-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}.deployment-mode-option{display:grid;align-content:start;gap:5px;min-height:130px;padding:14px;border:1px solid var(--line);border-radius:8px;background:var(--control-surface);color:var(--ink-soft);cursor:pointer;text-align:left}.deployment-mode-option strong{color:var(--ink);font-size:14px}.deployment-mode-option span{font-size:12px;line-height:1.45}.deployment-mode-option:hover,.deployment-mode-option:focus-visible,.deployment-mode-option-active{border-color:var(--accent);outline:0;box-shadow:inset 0 1px 0 var(--crystal-rim),0 0 0 2px var(--accent-soft);background:var(--menu-item-active-bg)}.deployment-review{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.deployment-review>div{display:grid;gap:3px;padding:10px;border:1px solid var(--line);border-radius:8px;background:color-mix(in srgb,var(--surface-solid) 64%,transparent)}.deployment-review span{color:var(--ink-faint);font-size:11.5px;font-weight:700}.deployment-review strong{color:var(--ink);font-size:13px;overflow-wrap:anywhere}
+.guided-install-plan{display:grid;gap:10px;padding:12px;border:1px solid color-mix(in srgb,var(--accent) 42%,var(--line));border-radius:8px;background:linear-gradient(135deg,color-mix(in srgb,var(--primary-command-surface) 46%,transparent),color-mix(in srgb,var(--surface-solid) 72%,transparent));box-shadow:inset 0 1px 0 var(--crystal-rim)}.guided-install-plan-heading{display:flex;align-items:start;justify-content:space-between;gap:12px}.guided-install-plan-heading>div{display:grid;gap:3px}.guided-install-plan-heading strong,.guided-install-plan li strong,.guided-install-plan p strong{color:var(--ink);font-size:13px}.guided-install-plan-heading span,.guided-install-plan small,.guided-install-plan p{color:var(--ink-soft);font-size:12px;line-height:1.45}.guided-install-plan-heading>small{flex:0 0 auto;padding:3px 6px;border:1px solid var(--line);border-radius:999px;color:var(--accent);font-weight:750}.guided-install-plan ol{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin:0;padding:0;list-style:none}.guided-install-plan li{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:7px;padding:8px;border:1px solid var(--line);border-radius:6px;background:color-mix(in srgb,var(--surface-solid) 62%,transparent)}.guided-install-plan li>span{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:1px solid color-mix(in srgb,var(--accent) 44%,var(--line));border-radius:50%;color:var(--accent);background:var(--control-surface)}.guided-install-plan li>div{display:grid;gap:2px}.guided-install-plan li small{font-size:11.5px}.guided-install-plan p{margin:0;padding-top:2px}
.management-dialog-panel .plugin-detail-panel,.management-dialog-panel .plugin-group{border:0;padding:0;background:0 0;box-shadow:none;clip-path:none}
.management-dialog-panel .plugin-group::after,.management-dialog-panel .plugin-group::before{content:none}
.plugin-detail-actions{align-items:stretch}
@@ -624,7 +625,7 @@ to{transform:translate(-50%,-50%) rotate(calc(var(--construct-drift) + 360deg))}
}
@media (max-width:760px){.auth-shell{padding:14px;place-items:stretch}
.auth-card{align-self:center}
-.access-list-row,.deployment-mode-grid,.deployment-review,.deployment-workflow-steps,.maintenance-node-item,.maintenance-triage-grid,.management-form,.profile-background-grid,.profile-palette-grid,.profile-settings-form-row,.profile-settings-grid,.profile-settings-hero,.provider-preset-grid,.runtime-task-stages,.user-management-item,.workflow-hint-grid{grid-template-columns:1fr}
+.access-list-row,.deployment-mode-grid,.deployment-review,.deployment-workflow-steps,.guided-install-plan ol,.maintenance-node-item,.maintenance-triage-grid,.management-form,.profile-background-grid,.profile-palette-grid,.profile-settings-form-row,.profile-settings-grid,.profile-settings-hero,.provider-preset-grid,.runtime-task-stages,.user-management-item,.workflow-hint-grid{grid-template-columns:1fr}.guided-install-plan-heading{display:grid}
.console-row-actions,.maintenance-actions,.profile-settings-actions,.user-actions{justify-content:flex-start}
.app-shell{display:block;grid-template-columns:1fr}
.app-sidebar{position:fixed;inset:0 auto 0 0;z-index:60;width:min(82vw,300px);min-width:0;height:100dvh;display:flex;flex-direction:column;gap:12px;align-items:stretch;padding:max(14px,env(safe-area-inset-top)) 12px max(14px,env(safe-area-inset-bottom));border-right:1px solid color-mix(in srgb,var(--line-strong) 74%,transparent);border-bottom:0;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;opacity:0;visibility:hidden;pointer-events:none;transform:translateX(calc(-100% - 18px));transition:transform .2s ease,opacity 160ms ease,visibility .2s step-end}