Yuxi 品牌自定义指南:站点信息、登录协议与主题样式的完整配置方案
【免费下载链接】Yuxi可私有部署的多租户知识智能体平台:统一 RAG、知识图谱、多智能体、MCP/Skills、沙盒与权限管理。Self-hosted knowledge agent platform for RAG, knowledge graphs and multi-agent workflows.项目地址: https://gitcode.com/GitHub_Trending/yu/Yuxi
Yuxi 是支持私有部署的多租户知识智能体平台,其品牌信息分为后端读取的站点信息(名称、Logo、协议链接)与前端源码中的主题样式两个层面。本文基于 docs/advanced/branding.md 系统讲解如何通过 YAML 文件替换站点名称、Logo 与协议链接,如何启用登录协议勾选,以及如何调整主题色变量,并结合仓库源码说明底层加载逻辑与部署生效方式。读完本文,你将能够独立完成 Yuxi 从"品牌文案"到"主题皮肤"的完整定制。
品牌配置的整体架构
Yuxi 的品牌定制并不存在一个"一键换肤"的总开关,而是由三个相互独立的配置面组成:
| 配置面 | 载体 | 作用对象 | 生效方式 |
|---|---|---|---|
| 站点信息 | info.local.yaml(YAML) | 后端/api/system/info接口 | 重启 API / 重建容器 |
| 主题样式 | base.css、base.dark.css、theme.js | 前端资源 | Vite 热更新 / 重建 Web 镜像 |
| 协议页面 | web/public/protocols/*.template.html | 静态页面 | 随 Web 资源发布 |
修改其中任何一项都不会自动联动另一项,这一点在定制时需要特别留意。下面的章节将逐一展开。
配置站点信息(YAML)
第一步:创建本地配置文件
仓库为品牌信息提供了模板文件 info.template.yaml。在开发环境中,建议复制一份本地文件并在此基础上修改:
cp -n backend/package/yuxi/config/static/info.template.yaml \ backend/package/yuxi/config/static/info.local.yamlinfo.local.yaml通常是本地未跟踪文件(位于.gitignore之外、不会被提交);如果目标文件已经存在,-n参数会避免覆盖它,此时应直接编辑现有文件,或先备份再覆盖。
第二步:理解 YAML 字段结构
模板文件的完整结构如下,每一层都有明确职责:
# 组织信息 organization: name: "语析" # 完整组织名称 logo: "/favicon.svg" # Logo文件路径(放在 web/public 目录下) avatar: "/favicon.svg" # 头像文件路径(放在 web/public 目录下) login_bg: "/login-bg.jpg" # 登录背景图片路径(放在 web/public 目录下) # 项目信息 branding: name: "Yuxi" title: "让团队知识可连接,让智能体可行动" # 系统标题 subtitle: "知识库 × 知识图谱 × 智能体 Harness,开源且可私有部署" # 副标题(subtitles 为空时使用) subtitles: - "知识与智能体真正协同,每个回答都可溯源" - "从回答问题到交付任务,工具与沙盒一站完成" - "多租户、权限与模型治理,面向团队而非 Demo" - "Docker Compose 一键部署,数据不出你的内网" # 页脚信息 footer: copyright: "© 语析 2026 v{{YUXI_VERSION}}" user_agreement_url: "/protocols/user-agreement.template.html" privacy_policy_url: "/protocols/privacy-policy.template.html"各字段的取值说明:
organization.name:组织完整名称,会出现在首页、登录页和侧边栏。organization.logo/organization.avatar:Logo 与头像,分别用于首页展示(见 HomeView.vue)和布局侧边栏(见 AppLayout.vue)。organization.login_bg:登录页背景图,前端在 LoginView.vue 中读取,取不到时回退到/login-bg.jpg。branding.name:应用品牌名。前端展示逻辑中,若组织名与品牌名都存在且不同,则优先展示品牌名;否则取组织名或品牌名(见 LoginView.vue)。branding.title:首页大标题;branding.subtitle为副标题,仅当subtitles列表为空时用作回退;branding.subtitles支持多行轮换文案,首页会按列表逐条渲染(见 HomeView.vue)。footer.copyright:页脚版权文案,可直接嵌入{{YUXI_VERSION}}版本占位符。footer.user_agreement_url/footer.privacy_policy_url:用户协议与隐私政策页面地址,控制登录协议勾选的显隐(详见下文)。
第三步:放置静态资源并填写路径
图片与协议页面统一放在web/public目录下,YAML 中的路径从网站根目录开始书写,例如/logo.svg、/avatar.jpg、/login-bg.jpg。仓库自带的默认资源包括:
web/public/favicon.svgweb/public/avatar.jpgweb/public/login-bg.jpgweb/public/protocols/user-agreement.template.htmlweb/public/protocols/privacy-policy.template.html
前端 Pinia store 在 info.js 中对organization、branding、footer三组字段做了默认值兜底,即使接口返回缺字段也不会导致页面报错。
第四步:通过环境变量指定配置文件
API 侧通过YUXI_BRAND_FILE_PATH环境变量定位品牌文件,其加载逻辑在 system_router.py 的load_info_config()中实现:
- 读取环境变量
YUXI_BRAND_FILE_PATH,默认值为package/yuxi/config/static/info.local.yaml; - 若该路径不存在,则回退到
info.template.yaml; - 读取文件内容,将
{{YUXI_VERSION}}占位符替换为当前版本(get_version()定义于 yuxi/init.py); - 通过 YAML 解析后返回配置对象。
docker-compose 中 API 容器的工作目录是/app,因此默认配置路径可以写成:
YUXI_BRAND_FILE_PATH=package/yuxi/config/static/info.local.yaml也可以在.env中设置绝对路径,但文件必须挂载到 API 容器内。注意:路径不存在时 API 只回退到模板,不会把两个 YAML 文件合并——即你不能期望"模板中没写的字段从本地文件补充",本地文件必须自成完整配置。
第五步:让配置生效(重新加载)
开发环境:backend/package直接挂载进容器,修改 YAML 后重启 API 即可:
docker compose restart api生产环境:生产 Compose 不挂载仓库源码,品牌 YAML 会在构建 API 镜像时复制进镜像。修改backend/package/yuxi/config/static/info.local.yaml后,需要重新构建并重建 API/worker 容器:
docker compose --env-file .env.prod -f docker-compose.prod.yml \ up -d --build --force-recreate api worker如果使用仓库之外的品牌文件,需要在 Compose 覆盖配置中把它只读挂载到 API 容器,并让YUXI_BRAND_FILE_PATH指向容器内路径;修改该环境变量后同样需要--force-recreate重建容器。
第六步:验证站点信息接口
页面通过公开的/api/system/info接口读取站点信息,前端封装见 system_api.js 的brandApi.getInfoConfig(),由 info.js 的loadInfoConfig统一加载并合并并发请求。该接口无需登录即可访问,对应的集成测试在 test_system_router_api.py 中验证了其公开性。
此外,接口还提供了管理员专用的POST /api/system/info/reload(见 system_router.py),用于不重启进程地重新加载品牌配置,其权限与可用性同样有集成测试覆盖(见 test_system_router_api.py)。{{YUXI_VERSION}}占位符在加载时会被 API 替换为当前版本号。
登录协议:启用勾选与替换模板
当footer.user_agreement_url和footer.privacy_policy_url同时有值时,登录页和初始化页面会显示协议勾选项;任一链接为空,则不显示勾选项。前端判断逻辑在 LoginView.vue:
const userAgreementUrl = computed(() => { return infoStore.footer?.user_agreement_url?.trim() || '' }) const privacyPolicyUrl = computed(() => { return infoStore.footer?.privacy_policy_url?.trim() || '' }) const showAgreementConsent = computed(() => { return Boolean(userAgreementUrl.value && privacyPolicyUrl.value) })用户未勾选时,登录或初始化会被页面拦截并提示先同意协议(agreementAccepted状态控制提交)。因此,只配置其中一个链接并不会出现"只勾一个协议"的折中效果,而是直接不显示勾选项。
仓库提供两个可直接使用的协议模板:
web/public/protocols/user-agreement.template.htmlweb/public/protocols/privacy-policy.template.html
模板内置了三个占位符:{{ORG_NAME}}(适用组织)、{{PRODUCT_NAME}}(产品名称)、{{EFFECTIVE_DATE}}(生效日期),例如用户协议模板中的:
<div class="meta">适用组织:{{ORG_NAME}} | 生效日期:{{EFFECTIVE_DATE}}</div> <p>欢迎使用 {{PRODUCT_NAME}}。在使用本平台提供的服务前,请仔细阅读并充分理解本协议。</p>替换模板内容后记得同步处理占位符;也可以把 YAML 中的user_agreement_url/privacy_policy_url指向自定义的站内页面或站外合规页面。正式上线前,请务必让法务审核协议文本。
修改主题样式
主题文件与变量体系
主题样式涉及三个前端文件:
| 文件 | 作用 |
|---|---|
| web/src/assets/css/base.css | 浅色模式主题变量与全局样式 |
| web/src/assets/css/base.dark.css | 暗色模式主题变量覆盖 |
| web/src/stores/theme.js | 主题选择器的默认配置与 Ant Design 主题 Token |
Yuxi 采用 CSS 变量驱动的主题体系。以浅色模式 base.css 为例,主色是一个从深到浅的完整色阶:
:root { --main-1000: #01151f; --main-900: #023944; --main-800: #035065; --main-700: #046a82; --main-600: #24839a; --main-500: #3996ae; --main-400: #5faec2; --main-300: #82c3d6; --main-200: #a3d8e8; --main-100: #c4eaf5; --main-50: #e1f6fb; /* ... */ --main-color: var(--main-700); --main-bright: #0188a6; }暗色模式在 base.dark.css 中会对同一组变量做反相覆盖(例如--main-1000: #e1f6fb、--main-color: #4a9fb8),因此调整主色时浅色与暗色两套文件都要同步修改。
必须同步theme.js中的 colorPrimary
这是最容易踩坑的一步:Ant Design 组件使用设计 Token,而不是直接读取 CSS 变量。在 theme.js 的commonTheme.token中:
const commonTheme = { token: { fontFamily: "'HarmonyOS Sans SC', Inter, -apple-system, ...", colorPrimary: '#24839b', colorLink: 'var(--main-color)', colorLinkHover: 'var(--main-600)', colorLinkActive: 'var(--main-800)', borderRadius: 8, wireframe: false } }其中colorPrimary是 Ant Design 组件的主色值,与 CSS 变量各自独立存在。如果只修改 CSS 变量而不改colorPrimary,会出现"自定义组件已换色、Ant Design 组件仍是旧色"的颜色不一致问题。建议的做法是:先确定新的主色值,同步更新colorPrimary与--main-*色阶中对应的基准色。
对比度与状态色检查
新增颜色或调整主色时,要同时检查浅色、暗色、hover、focus、禁用和错误状态的对比度。Yuxi 的主题变量体系中还包含辅助暖金色系(--second-*,基准--second-500),交互状态色(如 hover 使用--main-600、active 使用--main-800)分布在各组件样式中,保证色阶完整才能让所有状态视觉协调。优先修改已有 CSS 变量,不要在组件中散落新的硬编码颜色。
生效方式
- 开发环境:Vite 会通过热更新(HMR)自动刷新样式,修改
base.css、base.dark.css或theme.js后无需重启。 - 生产环境:需要重新构建 Web 镜像:
docker compose -f docker-compose.prod.yml --env-file .env.prod \ up -d --build web主题选择器本身由theme.js管理:默认浅色,用户切换后写入localStorage的theme字段,并通过document.documentElement上的darkclass 切换暗色变量(见 theme.js)。
三个配置面的边界与最佳实践
最后再次强调 Yuxi 品牌定制的核心边界:品牌 YAML、主题颜色和图标/协议页面属于不同配置面——YAML 影响站点信息接口(/api/system/info),CSS 与theme.js影响前端资源,协议与图片属于静态资源。修改其中一项不会自动改动另一项,也不会互相回退。
一次完整的品牌定制通常按以下顺序推进:
- 复制
info.template.yaml为info.local.yaml,填写组织名、Logo、头像、登录背景与品牌文案; - 将 Logo、头像、背景图与协议页面放入
web/public,并把 YAML 路径改为根路径形式; - 按需替换协议模板内容与
{{ORG_NAME}}、{{PRODUCT_NAME}}、{{EFFECTIVE_DATE}}占位符; - 修改
base.css与base.dark.css的主色色阶,同时同步theme.js的colorPrimary; - 开发环境
docker compose restart api验证站点信息,生产环境分别重建 API/worker 与 web 镜像。
遵循这一流程,即可在不改任何业务代码的前提下,让 Yuxi 呈现完全属于自己团队的组织形象与视觉风格。
【免费下载链接】Yuxi可私有部署的多租户知识智能体平台:统一 RAG、知识图谱、多智能体、MCP/Skills、沙盒与权限管理。Self-hosted knowledge agent platform for RAG, knowledge graphs and multi-agent workflows.项目地址: https://gitcode.com/GitHub_Trending/yu/Yuxi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考