403 lines
8.1 KiB
Markdown
403 lines
8.1 KiB
Markdown
|
|
# Services 模块文档
|
|||
|
|
|
|||
|
|
## 模块概述
|
|||
|
|
|
|||
|
|
| 项目 | 内容 |
|
|||
|
|
|------|------|
|
|||
|
|
| **模块名** | services |
|
|||
|
|
| **职责** | 提供全局状态管理服务:国际化和主题系统 |
|
|||
|
|
| **公开 API** | 2 个管理器类 + 辅助函数 |
|
|||
|
|
| **状态** | ✅ 稳定 |
|
|||
|
|
|
|||
|
|
## 代码地图
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
src/
|
|||
|
|
├── services/
|
|||
|
|
│ ├── locale.ts # 国际化服务
|
|||
|
|
│ └── theme.ts # 主题服务
|
|||
|
|
├── locales/
|
|||
|
|
│ ├── types.ts # 翻译类型定义
|
|||
|
|
│ ├── zh-CN.ts # 中文翻译
|
|||
|
|
│ └── en-US.ts # 英文翻译
|
|||
|
|
└── themes/
|
|||
|
|
├── types.ts # 主题类型定义
|
|||
|
|
└── presets.ts # 内置主题预设
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## LocaleManager(国际化服务)
|
|||
|
|
|
|||
|
|
### 概述
|
|||
|
|
|
|||
|
|
管理应用语言、翻译文本,支持实时订阅。
|
|||
|
|
|
|||
|
|
### API
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
class LocaleManager {
|
|||
|
|
getLocale(): LocaleType;
|
|||
|
|
setLocale(locale: LocaleType): void;
|
|||
|
|
t(key: string): string;
|
|||
|
|
subscribe(listener: (locale: LocaleType) => void): () => void;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type LocaleType = 'zh-CN' | 'en-US';
|
|||
|
|
|
|||
|
|
// 单例导出
|
|||
|
|
export const localeManager: LocaleManager;
|
|||
|
|
|
|||
|
|
// 便捷函数
|
|||
|
|
export function t(key: string): string;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 使用示例
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { localeManager, t } from 'iflow-engine';
|
|||
|
|
|
|||
|
|
// 获取当前语言
|
|||
|
|
const locale = localeManager.getLocale(); // 'zh-CN'
|
|||
|
|
|
|||
|
|
// 切换语言
|
|||
|
|
localeManager.setLocale('en-US');
|
|||
|
|
|
|||
|
|
// 翻译
|
|||
|
|
console.log(t('toolbar.home')); // 'Home'
|
|||
|
|
console.log(t('measure.modes.distance')); // 'Distance'
|
|||
|
|
|
|||
|
|
// 订阅语言变更
|
|||
|
|
const unsubscribe = localeManager.subscribe((locale) => {
|
|||
|
|
console.log('Language changed:', locale);
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 翻译键结构
|
|||
|
|
|
|||
|
|
| 域 | 说明 | 示例 |
|
|||
|
|
|---|------|------|
|
|||
|
|
| `common` | 通用文本 | `common.title` |
|
|||
|
|
| `toolbar` | 工具栏按钮 | `toolbar.home`, `toolbar.measure` |
|
|||
|
|
| `dialog` | 对话框 | `dialog.testTitle` |
|
|||
|
|
| `menu` | 菜单项 | `menu.info` |
|
|||
|
|
| `tree` | 树形控件 | `tree.searchPlaceholder` |
|
|||
|
|
| `measure` | 测量工具 | `measure.modes.distance`, `measure.units.m` |
|
|||
|
|
| `sectionPlane` | 平面剖切 | `sectionPlane.dialogTitle` |
|
|||
|
|
| `sectionAxis` | 轴向剖切 | `sectionAxis.dialogTitle` |
|
|||
|
|
| `sectionBox` | 剖切盒 | `sectionBox.dialogTitle` |
|
|||
|
|
| `walkControl` | 漫游控制 | `walkControl.speed` |
|
|||
|
|
| `map` | 地图 | `map.dialogTitle` |
|
|||
|
|
|
|||
|
|
### 扩展新语言
|
|||
|
|
|
|||
|
|
1. 创建翻译文件 `src/locales/ja-JP.ts`
|
|||
|
|
2. 更新类型 `src/locales/types.ts`
|
|||
|
|
3. 注册到 LocaleManager
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// src/locales/ja-JP.ts
|
|||
|
|
export const jaJP: TranslationDictionary = {
|
|||
|
|
common: { title: 'BimEngine' },
|
|||
|
|
toolbar: { home: 'ホーム', measure: '測定' },
|
|||
|
|
// ...
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ThemeManager(主题服务)
|
|||
|
|
|
|||
|
|
### 概述
|
|||
|
|
|
|||
|
|
管理应用主题、颜色方案,支持实时订阅。
|
|||
|
|
|
|||
|
|
### API
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
class ThemeManager {
|
|||
|
|
getTheme(): ThemeConfig;
|
|||
|
|
setTheme(themeName: 'dark' | 'light'): void;
|
|||
|
|
setCustomTheme(theme: ThemeConfig): void;
|
|||
|
|
subscribe(listener: (theme: ThemeConfig) => void): () => void;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 单例导出
|
|||
|
|
export const themeManager: ThemeManager;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 使用示例
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { themeManager } from 'iflow-engine';
|
|||
|
|
|
|||
|
|
// 获取当前主题
|
|||
|
|
const theme = themeManager.getTheme();
|
|||
|
|
console.log(theme.primary); // '#2563eb'
|
|||
|
|
|
|||
|
|
// 切换预设主题
|
|||
|
|
themeManager.setTheme('dark');
|
|||
|
|
|
|||
|
|
// 自定义主题
|
|||
|
|
themeManager.setCustomTheme({
|
|||
|
|
name: 'custom',
|
|||
|
|
primary: '#ff6b6b',
|
|||
|
|
// ...
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 订阅主题变更
|
|||
|
|
const unsubscribe = themeManager.subscribe((theme) => {
|
|||
|
|
console.log('Theme changed:', theme.name);
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 预设主题
|
|||
|
|
|
|||
|
|
#### 亮色主题 (`lightTheme`)
|
|||
|
|
|
|||
|
|
| 属性 | 值 | 说明 |
|
|||
|
|
|------|-----|------|
|
|||
|
|
| `primary` | `#2563eb` | 主色 |
|
|||
|
|
| `bgBase` | `#f8fafc` | 页面背景 |
|
|||
|
|
| `bgElevated` | `#ffffff` | 卡片背景 |
|
|||
|
|
| `textPrimary` | `#0f172a` | 主文本 |
|
|||
|
|
| `textSecondary` | `#475569` | 次要文本 |
|
|||
|
|
|
|||
|
|
#### 暗色主题 (`darkTheme`)
|
|||
|
|
|
|||
|
|
| 属性 | 值 | 说明 |
|
|||
|
|
|------|-----|------|
|
|||
|
|
| `primary` | `#3b82f6` | 主色 |
|
|||
|
|
| `bgBase` | `#152232` | 页面背景 |
|
|||
|
|
| `bgElevated` | `#1f2d3e` | 卡片背景 |
|
|||
|
|
| `textPrimary` | `#ffffff` | 主文本 |
|
|||
|
|
| `textSecondary` | `#94a3b8` | 次要文本 |
|
|||
|
|
|
|||
|
|
### ThemeConfig 结构
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
interface ThemeConfig {
|
|||
|
|
name: string;
|
|||
|
|
|
|||
|
|
// 品牌色
|
|||
|
|
primary: string;
|
|||
|
|
primaryHover: string;
|
|||
|
|
primaryActive: string;
|
|||
|
|
primarySubtle: string;
|
|||
|
|
|
|||
|
|
// 状态色
|
|||
|
|
success: string;
|
|||
|
|
warning: string;
|
|||
|
|
danger: string;
|
|||
|
|
info: string;
|
|||
|
|
|
|||
|
|
// 背景色
|
|||
|
|
bgBase: string;
|
|||
|
|
bgElevated: string;
|
|||
|
|
bgOverlay: string;
|
|||
|
|
bgInset: string;
|
|||
|
|
bgGlass: string;
|
|||
|
|
bgGlassBlur: string;
|
|||
|
|
|
|||
|
|
// 文字色
|
|||
|
|
textPrimary: string;
|
|||
|
|
textSecondary: string;
|
|||
|
|
textTertiary: string;
|
|||
|
|
textDisabled: string;
|
|||
|
|
textInverse: string;
|
|||
|
|
textLink: string;
|
|||
|
|
|
|||
|
|
// 图标色
|
|||
|
|
iconDefault: string;
|
|||
|
|
iconHover: string;
|
|||
|
|
iconActive: string;
|
|||
|
|
iconDisabled: string;
|
|||
|
|
|
|||
|
|
// 边框色
|
|||
|
|
borderDefault: string;
|
|||
|
|
borderSubtle: string;
|
|||
|
|
borderStrong: string;
|
|||
|
|
divider: string;
|
|||
|
|
|
|||
|
|
// 组件状态
|
|||
|
|
componentBg: string;
|
|||
|
|
componentBgHover: string;
|
|||
|
|
componentBgActive: string;
|
|||
|
|
componentBgSelected: string;
|
|||
|
|
|
|||
|
|
// 焦点
|
|||
|
|
focusRing: string;
|
|||
|
|
selectionBg: string;
|
|||
|
|
|
|||
|
|
// 阴影
|
|||
|
|
shadowSm: string;
|
|||
|
|
shadowMd: string;
|
|||
|
|
shadowLg: string;
|
|||
|
|
shadowGlow: string;
|
|||
|
|
|
|||
|
|
// 浮动层
|
|||
|
|
floatingBg: string;
|
|||
|
|
floatingBorder: string;
|
|||
|
|
floatingBtnBg: string;
|
|||
|
|
floatingBtnBgHover: string;
|
|||
|
|
floatingIconColor: string;
|
|||
|
|
|
|||
|
|
// 面板
|
|||
|
|
panelBg: string;
|
|||
|
|
panelBorder: string;
|
|||
|
|
panelHeaderBg: string;
|
|||
|
|
panelRadius: string;
|
|||
|
|
|
|||
|
|
// 选项卡
|
|||
|
|
tabBg: string;
|
|||
|
|
tabItemBg: string;
|
|||
|
|
tabItemBgActive: string;
|
|||
|
|
tabItemTextActive: string;
|
|||
|
|
|
|||
|
|
// 组件覆盖(可选)
|
|||
|
|
overrides?: {
|
|||
|
|
dialog?: { headerBg?: string };
|
|||
|
|
toolbar?: { bg?: string; buttonBg?: string };
|
|||
|
|
input?: { bg?: string; placeholder?: string };
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 创建自定义主题
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { createThemeFromPartial, lightTheme } from 'iflow-engine';
|
|||
|
|
|
|||
|
|
// 基于预设创建(推荐)
|
|||
|
|
const customTheme = createThemeFromPartial(lightTheme, {
|
|||
|
|
name: 'coral',
|
|||
|
|
primary: '#ff6b6b',
|
|||
|
|
primaryHover: '#ff5252',
|
|||
|
|
primaryActive: '#ff4757',
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
themeManager.setCustomTheme(customTheme);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### CSS 变量映射
|
|||
|
|
|
|||
|
|
主题颜色自动映射到 CSS 变量:
|
|||
|
|
|
|||
|
|
```css
|
|||
|
|
.my-component {
|
|||
|
|
background-color: var(--bim-bg-elevated);
|
|||
|
|
color: var(--bim-text-primary);
|
|||
|
|
border: 1px solid var(--bim-border-default);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.my-button {
|
|||
|
|
background-color: var(--bim-primary);
|
|||
|
|
color: var(--bim-text-inverse);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.my-button:hover {
|
|||
|
|
background-color: var(--bim-primary-hover);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
常用 CSS 变量:
|
|||
|
|
|
|||
|
|
| 变量 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| `--bim-primary` | 主色 |
|
|||
|
|
| `--bim-bg-base` | 页面背景 |
|
|||
|
|
| `--bim-bg-elevated` | 卡片背景 |
|
|||
|
|
| `--bim-text-primary` | 主文本 |
|
|||
|
|
| `--bim-border-default` | 边框 |
|
|||
|
|
| `--bim-shadow-sm` | 小阴影 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## React 集成
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
import { useEffect, useState } from 'react';
|
|||
|
|
import { localeManager, themeManager } from 'iflow-engine';
|
|||
|
|
|
|||
|
|
// 语言 Hook
|
|||
|
|
export function useLocale() {
|
|||
|
|
const [locale, setLocale] = useState(() => localeManager.getLocale());
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
return localeManager.subscribe(setLocale);
|
|||
|
|
}, []);
|
|||
|
|
|
|||
|
|
return { locale, setLocale: localeManager.setLocale.bind(localeManager) };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 主题 Hook
|
|||
|
|
export function useTheme() {
|
|||
|
|
const [theme, setTheme] = useState(() => themeManager.getTheme());
|
|||
|
|
|
|||
|
|
useEffect(() => {
|
|||
|
|
return themeManager.subscribe(setTheme);
|
|||
|
|
}, []);
|
|||
|
|
|
|||
|
|
return { theme, setTheme: themeManager.setTheme.bind(themeManager) };
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 架构设计
|
|||
|
|
|
|||
|
|
### 单例模式
|
|||
|
|
|
|||
|
|
两个服务都采用单例模式:
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
export const localeManager = new LocaleManager();
|
|||
|
|
export const themeManager = new ThemeManager();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 观察者模式
|
|||
|
|
|
|||
|
|
支持订阅状态变更:
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 订阅
|
|||
|
|
const unsubscribe = themeManager.subscribe((theme) => {
|
|||
|
|
// 更新 UI
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 取消订阅
|
|||
|
|
unsubscribe();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 与 BimEngine 集成
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
const engine = new BimEngine('container', {
|
|||
|
|
locale: 'zh-CN',
|
|||
|
|
theme: 'dark'
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 动态切换
|
|||
|
|
engine.setLocale('en-US');
|
|||
|
|
engine.setTheme('light');
|
|||
|
|
engine.setCustomTheme(customTheme);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 依赖关系
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
BimEngine
|
|||
|
|
↓
|
|||
|
|
LocaleManager ←→ locales/*.ts
|
|||
|
|
↓
|
|||
|
|
ThemeManager ←→ themes/*.ts
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Services 模块无外部依赖,完全自包含。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**文档生成时间**: 2026-01-23
|