From 12f248dc69506040ccdbb363814cb2873368fd14 Mon Sep 17 00:00:00 2001 From: WuYongJie Date: Mon, 1 Jun 2026 13:01:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=BA=E5=8C=96=E5=95=86=E4=B8=9A=E5=8C=96?= =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=A4=87=E4=BB=BD=E4=B8=8E=E6=9D=83=E9=99=90?= =?UTF-8?q?=20UI=20=E5=9C=B0=E5=9F=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 4 + README.md | 2 +- __tests__/production-build-hardening.test.ts | 1 + .../_components/AppearanceSettingsPanel.tsx | 66 ++--- .../template-manager/BuiltInTemplateGrid.tsx | 26 +- .../CustomTemplateSection.tsx | 74 ++--- .../TemplateManagerHeader.tsx | 6 +- .../editor/FieldConditionsConfig.tsx | 2 +- .../editor/FieldValidationConfig.tsx | 8 +- .../editor/TemplateFieldsEditor.tsx | 2 +- .../editor/TemplatePreviewPanel.tsx | 4 +- app/admin/page.tsx | 22 +- app/api/admin/upload-templates/[id]/route.ts | 158 ++++++++++- .../__tests__/template-crud.test.ts | 255 +++++++++++++++++- app/api/admin/upload-templates/route.ts | 6 +- .../__tests__/material-types-auth.test.ts | 59 ++++ app/api/material-types/route.ts | 37 +-- .../materials/asset/__tests__/route.test.ts | 123 +++++++++ app/api/materials/asset/route.ts | 63 +++-- .../materials/stats/__tests__/route.test.ts | 143 ++++++++++ app/api/materials/stats/route.ts | 72 ++++- .../system-settings/__tests__/route.test.ts | 25 +- app/api/system-settings/route.ts | 11 +- components/Header.tsx | 16 +- components/UploadModal.tsx | 10 +- deploy-registry.ps1 | 74 ++++- docs/deployment/部署说明.md | 15 +- .../__tests__/install-script.test.ts | 7 + flnxi-agent-go/install.sh | 4 +- lib/ui-styles-composer.ts | 8 +- lib/ui-styles.ts | 2 +- lib/ui-theme-colors-dark.ts | 12 +- lib/ui-theme-colors-light.ts | 12 +- lib/upload-template-save-validation.ts | 71 +++++ scripts/README.md | 6 +- .../__tests__/backup-restore-script.test.ts | 20 ++ .../__tests__/deploy-registry-script.test.ts | 15 ++ .../measure-image-size-script.test.ts | 27 ++ .../__tests__/smoke-install-script.test.ts | 4 + scripts/backup-restore.ps1 | 145 +++++++++- scripts/measure-image-size.ps1 | 46 +++- scripts/smoke-install.ps1 | 34 ++- 42 files changed, 1441 insertions(+), 256 deletions(-) create mode 100644 app/api/material-types/__tests__/material-types-auth.test.ts create mode 100644 app/api/materials/stats/__tests__/route.test.ts create mode 100644 scripts/__tests__/measure-image-size-script.test.ts diff --git a/Dockerfile b/Dockerfile index a98dc18..89d08fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -238,6 +238,10 @@ RUN addgroup --system --gid 1001 nodejs && \ COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static +# standalone 可能会把构建期的 prisma/engine-cache、dev.db 一起追踪进来; +# 运行镜像只保留 schema.prisma 和 migrations,避免客户每次升级重复拉无用缓存。 +RUN rm -rf ./prisma + # 复制必要的额外文件 # 1. public 目录(静态资源) COPY --from=builder --chown=nextjs:nodejs /app/public ./public diff --git a/README.md b/README.md index fde2101..2db4644 100644 --- a/README.md +++ b/README.md @@ -213,7 +213,7 @@ docker compose -f docker-compose.prod.yml up -d - `发布管理.ps1` - `license-server/deploy.ps1` -其中 `scripts/customer-install.ps1` 是客户首装分步骤入口,内部调用 `scripts/smoke-install.ps1` 做预检、启动和验收;`scripts/backup-restore.ps1` 用于客户环境备份、恢复和恢复后验收,`scripts/measure-image-size.ps1` 用于发布前记录镜像体积和分层。其它脚本执行前必须先读内容和参数,不应把内部固定服务器或固定镜像仓库当成客户默认交付配置。客户交付时要显式写入版本化 `APP_IMAGE` / `IMAGE_TAG`,`latest` 只保留给内部测试或兼容场景。当前新 Registry 发布脚本是主线,旧远程部署脚本只作历史或内部维护参考。AI、钉钉、内网穿透等可选能力依赖真实外部服务和密钥,不能只凭页面入口当成客户验收已完成。 +其中 `scripts/customer-install.ps1` 是客户首装分步骤入口,内部调用 `scripts/smoke-install.ps1` 做预检、启动和验收;`scripts/backup-restore.ps1` 用于客户环境备份、恢复和恢复后验收;`scripts/measure-image-size.ps1` 用于发布前记录镜像体积和分层,也可以设置体积/层数阈值,超限时阻止发布继续。其它脚本执行前必须先读内容和参数,不应把内部固定服务器或固定镜像仓库当成客户默认交付配置。客户交付时要显式写入版本化 `APP_IMAGE` / `IMAGE_TAG`,`latest` 只保留给内部测试或兼容场景。当前新 Registry 发布脚本是主线,旧远程部署脚本只作历史或内部维护参考。AI、钉钉、内网穿透等可选能力依赖真实外部服务和密钥,不能只凭页面入口当成客户验收已完成。 ## 10. 文档入口 diff --git a/__tests__/production-build-hardening.test.ts b/__tests__/production-build-hardening.test.ts index 3e3065c..9da5784 100644 --- a/__tests__/production-build-hardening.test.ts +++ b/__tests__/production-build-hardening.test.ts @@ -20,6 +20,7 @@ describe('production build hardening', () => { }) it('生产运行镜像只复制 Prisma 运行迁移所需文件', () => { + expect(dockerfile).toContain('RUN rm -rf ./prisma') expect(dockerfile).toContain('/app/prisma/schema.prisma ./prisma/schema.prisma') expect(dockerfile).toContain('/app/prisma/migrations ./prisma/migrations') expect(dockerfile).not.toContain('/app/prisma ./prisma') diff --git a/app/admin/_components/AppearanceSettingsPanel.tsx b/app/admin/_components/AppearanceSettingsPanel.tsx index b967197..752fa2b 100644 --- a/app/admin/_components/AppearanceSettingsPanel.tsx +++ b/app/admin/_components/AppearanceSettingsPanel.tsx @@ -274,23 +274,20 @@ export default function AppearanceSettingsPanel({ sessionUser, variant = 'embedd } return ( -
+
-
-
-

- 外观 -

-

品牌、标识与系统开关

-

- 这里集中处理品牌主题、LOGO、功能开关与对象存储。保存后会同步到后台界面与素材上传入口。 +

+
+

外观设置

+

+ 管理站点名称、LOGO、功能开关和对象存储配置。

{lastSavedAt && (

@@ -298,7 +295,7 @@ export default function AppearanceSettingsPanel({ sessionUser, variant = 'embedd

)}
-
+
{variant === 'standalone' && ( -
@@ -469,9 +432,16 @@ export default function AppearanceSettingsPanel({ sessionUser, variant = 'embedd onChange={(e) => setHeaderBgColor(e.target.value)} className={cn(styles.inputStyles.base, 'flex-1 text-sm font-mono')} /> +
- {['#1f2937', '#4f46e5', '#1e40af', '#7c3aed', '#0891b2', '#059669', '#dc2626', '#d97706'].map((color) => ( + {['#1f2937', '#334155', '#0f766e', '#166534', '#b45309', '#b91c1c'].map((color) => (
{hasDisabledTemplates && onEnableAll && ( @@ -54,32 +54,24 @@ export default function BuiltInTemplateGrid({ )}
-
+
{presets.map((preset) => { const fieldCount = preset.getFields().length return (
onPreview(preset.key)} > -
-
+
+

{preset.name}

{preset.description}

- - 预制 - -
-
-
- - - - {fieldCount} 个字段 -
-
+
+ + {fieldCount} 个字段 + {onToggleEnabled && (
{loading ? ( @@ -71,57 +88,26 @@ export default function CustomTemplateSection({ ) : error ? (
{error}
) : ( -
- - +
{templates.length === 0 ? ( -
暂无自定义模板,点击上方卡片开始创建。
+
暂无自定义模板。
) : filteredTemplates.length === 0 ? ( -
未找到匹配的模板名称,请调整搜索关键词。
+
未找到匹配的模板名称,请调整搜索关键词。
) : ( filteredTemplates.map((tpl) => (
onPreview(tpl)} - className={cn(styles.cardStyles.hover, 'group relative overflow-hidden cursor-pointer')} + className="group relative cursor-pointer rounded-lg border border-slate-200 bg-white px-4 py-3 transition-colors hover:border-slate-300 hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-900 dark:hover:border-slate-600 dark:hover:bg-slate-800/70" > -
-
+
+

{tpl.name}

{tpl.description && (

{tpl.description}

)}
-
+
{tpl.statusLabel} -
-
-
+ + {tpl.updatedLabel} · 版本 {tpl.version} + {tpl.status === 'active' ? ( - - {tpl.updatedLabel} · 版本 {tpl.version} -
+
)) )}
diff --git a/app/admin/_components/template-manager/TemplateManagerHeader.tsx b/app/admin/_components/template-manager/TemplateManagerHeader.tsx index ebad934..b021792 100644 --- a/app/admin/_components/template-manager/TemplateManagerHeader.tsx +++ b/app/admin/_components/template-manager/TemplateManagerHeader.tsx @@ -19,10 +19,10 @@ export default function TemplateManagerHeader({ return (
diff --git a/app/admin/_components/template-manager/editor/FieldConditionsConfig.tsx b/app/admin/_components/template-manager/editor/FieldConditionsConfig.tsx index 355aa3d..97600e1 100644 --- a/app/admin/_components/template-manager/editor/FieldConditionsConfig.tsx +++ b/app/admin/_components/template-manager/editor/FieldConditionsConfig.tsx @@ -164,7 +164,7 @@ export default function FieldConditionsConfig({ {index === 0 &&
} {/* 条件配置 */} -
+
{/* 字段选择 */} +
{typeof rules.minLength === 'number' && (
@@ -213,7 +213,7 @@ export default function FieldValidationConfig({ {/* 数值范围验证 - number */} {supportedValidations.includes('min') && ( -
+
+
{typeof rules.min === 'number' && (
diff --git a/app/admin/_components/template-manager/editor/TemplateFieldsEditor.tsx b/app/admin/_components/template-manager/editor/TemplateFieldsEditor.tsx index 93f7c8d..f176264 100644 --- a/app/admin/_components/template-manager/editor/TemplateFieldsEditor.tsx +++ b/app/admin/_components/template-manager/editor/TemplateFieldsEditor.tsx @@ -327,7 +327,7 @@ export default function TemplateFieldsEditor({
)} -
+