feat(brand): apply 森林AI identity
@@ -2,7 +2,7 @@
|
||||
|
||||
## 项目
|
||||
|
||||
本仓库包含 SenlinAI 项目工作台 MVP。
|
||||
本仓库包含森林AI项目工作台 MVP。
|
||||
|
||||
该产品是一个以项目为中心、面向私有化部署的工作台,服务于个人知识工作者、团队负责人和可信的内部用户。它用于组织项目任务、inbox 条目、Markdown 笔记、文件、AI 会话、项目内标签,以及轻量级任务分发。
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# SenlinAI Agent Workbench
|
||||
# 森林AI
|
||||
|
||||
SenlinAI Agent Workbench 是一个以项目为中心的私有化工作台 MVP。
|
||||
森林AI 是一个以项目为中心的私有化工作台 MVP。
|
||||
|
||||
## 本地开发
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
[package]
|
||||
name = "senlinai_workbench"
|
||||
version = "0.1.0"
|
||||
description = "SenlinAI project workbench desktop shell"
|
||||
authors = ["SenlinAI"]
|
||||
description = "森林AI 项目工作台桌面端"
|
||||
authors = ["森林AI"]
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
BIN
apps/desktop/src-tauri/icons/128x128.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
apps/desktop/src-tauri/icons/128x128@2x.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
apps/desktop/src-tauri/icons/32x32.png
Normal file
|
After Width: | Height: | Size: 926 B |
BIN
apps/desktop/src-tauri/icons/icon.icns
Normal file
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 13 KiB |
@@ -3,5 +3,5 @@ pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running SenlinAI Workbench");
|
||||
.expect("启动森林AI时发生错误");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "SenlinAI Workbench",
|
||||
"productName": "森林AI",
|
||||
"version": "0.1.0",
|
||||
"identifier": "ai.senlin.workbench",
|
||||
"build": {
|
||||
@@ -12,7 +12,7 @@
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "项目工作台",
|
||||
"title": "森林AI",
|
||||
"width": 1280,
|
||||
"height": 820
|
||||
}
|
||||
@@ -24,6 +24,12 @@
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"icon": ["icons/icon.ico"]
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# SenlinAI Acro React
|
||||
# 森林AI Web 客户端
|
||||
|
||||
SenlinAI primary web client built with React, TypeScript, Vite, and Arco Design.
|
||||
森林AI主 Web 客户端,使用 React、TypeScript、Vite 和 Arco Design 构建。
|
||||
|
||||
This app is the active web client under `apps/web_v1`.
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="icon" type="image/svg+xml" href="/senlinai-icon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>web_v1</title>
|
||||
<meta name="application-name" content="森林AI" />
|
||||
<meta name="description" content="森林AI 私有化项目工作台" />
|
||||
<title>森林AI</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 731 B |
10
apps/web_v1/public/senlinai-icon.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
|
||||
<title>森林AI 图标</title>
|
||||
<rect x="4" y="4" width="120" height="120" rx="28" fill="#165DFF"/>
|
||||
<path d="M64 23C43 23 27 40 27 61c0 13 7 24 17 30h40c10-6 17-17 17-30 0-21-16-38-37-38Z" fill="#F4F8FF"/>
|
||||
<path d="M64 99V65M64 76 47 61M64 82l18-16M64 68l12-13" fill="none" stroke="#F4F8FF" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"/>
|
||||
<path d="M42 58c6-15 29-22 45-7M39 69c12-11 38-13 50 2M48 78c9-5 24-6 33-1" fill="none" stroke="#165DFF" stroke-linecap="round" stroke-width="5"/>
|
||||
<circle cx="47" cy="61" r="6" fill="#14B8A6"/>
|
||||
<circle cx="76" cy="55" r="6" fill="#60A5FA"/>
|
||||
<circle cx="82" cy="66" r="6" fill="#A7F3D0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 731 B |
@@ -25,6 +25,23 @@ const requiredFiles = [
|
||||
|
||||
const failures = requiredFiles.filter((file) => !existsSync(file)).map((file) => `missing ${file}`)
|
||||
|
||||
const html = readFileSync('index.html', 'utf8')
|
||||
if (!html.includes('<html lang="zh-CN">')) failures.push('index language must be zh-CN')
|
||||
if (!html.includes('<title>森林AI</title>')) failures.push('document title must be 森林AI')
|
||||
if (!html.includes('href="/senlinai-icon.svg"')) failures.push('favicon must use /senlinai-icon.svg')
|
||||
if (!existsSync('public/senlinai-icon.svg')) failures.push('missing public/senlinai-icon.svg')
|
||||
|
||||
for (const file of ['src/pages/login.tsx', 'src/pages/projects/project-topbar.tsx', 'src/pages/projects/project-rail.tsx']) {
|
||||
const source = readFileSync(file, 'utf8')
|
||||
if (!source.includes('/senlinai-icon.svg')) failures.push(`${file} must use the brand icon`)
|
||||
}
|
||||
|
||||
for (const forbidden of ['森林Agent', 'SenlinAI Workbench']) {
|
||||
for (const file of requiredFiles.filter((name) => name.endsWith('.tsx'))) {
|
||||
if (readFileSync(file, 'utf8').includes(forbidden)) failures.push(`${file} contains legacy product name ${forbidden}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (existsSync('src/App.tsx')) {
|
||||
failures.push('legacy src/App.tsx should be removed after page split')
|
||||
}
|
||||
|
||||
@@ -113,23 +113,23 @@
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.brand-symbol {
|
||||
.brand-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
display: block;
|
||||
border-radius: 8px;
|
||||
background: var(--senlin-primary);
|
||||
color: white;
|
||||
font-weight: 800;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.brand-lockup.large .brand-symbol {
|
||||
.brand-lockup.large .brand-icon {
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
border-radius: 12px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.rail-brand-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.brand-name {
|
||||
|
||||
@@ -38,8 +38,8 @@ export function LoginPage({ onLogin }: { onLogin: (input: { server: string; emai
|
||||
<Card className="login-card" bordered>
|
||||
<div className="login-brand-panel">
|
||||
<div className="brand-lockup large">
|
||||
<span className="brand-symbol">S</span>
|
||||
<Title heading={2}>森林Agent</Title>
|
||||
<img className="brand-icon" src="/senlinai-icon.svg" alt="" aria-hidden="true" />
|
||||
<Title heading={2}>森林AI</Title>
|
||||
</div>
|
||||
<Text className="login-slogan">私有部署 · 安全可控的智能协作平台</Text>
|
||||
<Text type="secondary">知识沉淀 · 团队协作 · AI Agent</Text>
|
||||
@@ -51,7 +51,7 @@ export function LoginPage({ onLogin }: { onLogin: (input: { server: string; emai
|
||||
</div>
|
||||
|
||||
<div className="login-form-panel">
|
||||
<Title heading={4}>登录到您的 SenlinAI</Title>
|
||||
<Title heading={4}>登录到您的森林AI</Title>
|
||||
<Text type="secondary">连接私有工作台</Text>
|
||||
<Form layout="vertical" className="login-form">
|
||||
<Form.Item label="服务器地址(IP 或域名优先)">
|
||||
@@ -81,7 +81,7 @@ export function LoginPage({ onLogin }: { onLogin: (input: { server: string; emai
|
||||
<div className="login-value-panel">
|
||||
<Title heading={3}>安全 · 专注 · 高效</Title>
|
||||
<Paragraph>
|
||||
SenlinAI 是面向知识工作者与内部团队的私有部署工作台,帮助团队在统一空间中收集信息、整理知识、协同决策。
|
||||
森林AI 是面向知识工作者与内部团队的私有部署工作台,帮助团队在统一空间中收集信息、整理知识、协同决策。
|
||||
</Paragraph>
|
||||
<ValuePoint icon={<IconSafe />} title="私有部署,数据自有" desc="所有数据与模型运行在您的环境中,安全可控。" />
|
||||
<ValuePoint icon={<IconBook />} title="知识沉淀,结构清晰" desc="从收集到整理,形成可复用的团队知识库。" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { CSSProperties } from 'react'
|
||||
import { Badge, Button, Layout, Space } from '@arco-design/web-react'
|
||||
import { IconCompass, IconDashboard, IconPlus } from '@arco-design/web-react/icon'
|
||||
import { IconCompass, IconPlus } from '@arco-design/web-react/icon'
|
||||
import type { Project, WorkbenchView } from './project-types'
|
||||
|
||||
const { Sider } = Layout
|
||||
@@ -26,10 +26,10 @@ export function ProjectRail({
|
||||
<Sider className="project-rail" width={96}>
|
||||
<Button
|
||||
className={activeView === 'workspace' ? 'dashboard-button active' : 'dashboard-button'}
|
||||
icon={<IconDashboard />}
|
||||
icon={<img className="brand-icon rail-brand-icon" src="/senlinai-icon.svg" alt="" aria-hidden="true" />}
|
||||
onClick={onSelectWorkspace}
|
||||
aria-label="工作台"
|
||||
title="工作台"
|
||||
aria-label="森林AI 工作台"
|
||||
title="森林AI 工作台"
|
||||
/>
|
||||
<Button
|
||||
className={activeView === 'workspace-explore' ? 'dashboard-button active' : 'dashboard-button'}
|
||||
|
||||
@@ -11,8 +11,8 @@ export function ProjectTopbar({ theme, onToggleTheme }: { theme: Theme; onToggle
|
||||
return (
|
||||
<Header className="topbar">
|
||||
<div className="brand-lockup">
|
||||
<span className="brand-symbol">S</span>
|
||||
<Text className="brand-name">SenlinAI</Text>
|
||||
<img className="brand-icon" src="/senlinai-icon.svg" alt="" aria-hidden="true" />
|
||||
<Text className="brand-name">森林AI</Text>
|
||||
</div>
|
||||
<div className="global-search" role="search">
|
||||
<Input size="large" prefix={<IconSearch />} placeholder="搜索项目、频道、文档、任务、联系人..." />
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# SenlinAI UI Design Guide
|
||||
# 森林AI UI Design Guide
|
||||
|
||||
## Purpose
|
||||
|
||||
This file defines the shared visual direction for SenlinAI Workbench. It keeps future UI work consistent across the login page, project shell, channel pages, object inspector, and desktop wrapper.
|
||||
This file defines the shared visual direction for 森林AI. It keeps future UI work consistent across the login page, project shell, channel pages, object inspector, and desktop wrapper.
|
||||
|
||||
The visual reference is shadcn/ui: quiet, structured, component-driven, and practical. This is a visual reference only. The web app must remain Svelte and TypeScript, and must not add React or shadcn/ui as runtime dependencies.
|
||||
|
||||
## Product Feel
|
||||
|
||||
SenlinAI is a private project workbench for focused knowledge work. The UI should feel calm, precise, and durable rather than decorative. It should support long sessions, dense information, fast scanning, and frequent switching between projects and channels.
|
||||
森林AI is a private project workbench for focused knowledge work. The UI should feel calm, precise, and durable rather than decorative. It should support long sessions, dense information, fast scanning, and frequent switching between projects and channels.
|
||||
|
||||
Use a restrained desktop-app tone:
|
||||
|
||||
|
||||
10
docs/senlinai-icon.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
|
||||
<title>森林AI 图标</title>
|
||||
<rect x="4" y="4" width="120" height="120" rx="28" fill="#165DFF"/>
|
||||
<path d="M64 23C43 23 27 40 27 61c0 13 7 24 17 30h40c10-6 17-17 17-30 0-21-16-38-37-38Z" fill="#F4F8FF"/>
|
||||
<path d="M64 99V65M64 76 47 61M64 82l18-16M64 68l12-13" fill="none" stroke="#F4F8FF" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"/>
|
||||
<path d="M42 58c6-15 29-22 45-7M39 69c12-11 38-13 50 2M48 78c9-5 24-6 33-1" fill="none" stroke="#165DFF" stroke-linecap="round" stroke-width="5"/>
|
||||
<circle cx="47" cy="61" r="6" fill="#14B8A6"/>
|
||||
<circle cx="76" cy="55" r="6" fill="#60A5FA"/>
|
||||
<circle cx="82" cy="66" r="6" fill="#A7F3D0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 731 B |