@posx/core 5.5.392 → 5.5.395
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +23 -23
- package/LICENSE +21 -21
- package/README.md +85 -85
- package/build/index.d.ts +6 -0
- package/build/index.js +1 -1
- package/jest.config.cjs +36 -36
- package/jest.setup.cjs +80 -80
- package/memo/technical-docs/01_ARCHITECTURE.md +147 -0
- package/memo/technical-docs/02_CORE_BUSINESS.md +292 -0
- package/memo/technical-docs/03_UI_COMPONENTS.md +59 -0
- package/memo/technical-docs/04_VIEWS.md +82 -0
- package/memo/technical-docs/05_DATA_LAYER.md +375 -0
- package/memo/technical-docs/06_CROSS_PLATFORM.md +246 -0
- package/memo/technical-docs/07_SIMILARITY_INDEX.md +195 -0
- package/memo/technical-docs/CHECKPOINT.md +46 -0
- package/memo/technical-docs/PROJECT_OVERVIEW.md +122 -0
- package/memo/technical-docs/TECHNICAL_DOCS_PLAN.md +77 -0
- package/package.json +1 -1
- package/package.publish.json +121 -120
- package/tsdown.config.ts +21 -21
- package/vite.config.ts +86 -86
- package/dev/.stfolder/syncthing-folder-9a95b7.txt +0 -5
- package/dev/98894488.xlsx +0 -0
- package/dev/HappyThaiSembawang.csv +0 -336
- package/dev/KB/create-new-model.md +0 -34
- package/dev/KB/markdown-lint.md +0 -14
- package/dev/KB/readmefirst.md +0 -6
- package/dev/Merchants/HappyThaiSembawang.csv +0 -400
- package/dev/Merchants/HappyThaiSembawang.xlsx +0 -0
- package/dev/Product_Import_Template.xlsx +0 -0
- package/dev/XPOS Invoice Module.pdf +0 -232
- package/dev/harbor-harness-deployment.md +0 -78
- package/dev/nginx-harbor-harness.conf +0 -84
- package/dev/test-logs/2026-02.md +0 -5
- package/dev//344/272/247/345/223/201/345/257/274/345/205/245/346/250/241/346/235/277.xlsx +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# 03 - UI 组件
|
|
2
|
+
|
|
3
|
+
> AI 上下文索引:核心库、非UI应用、类型定义、业务实体
|
|
4
|
+
|
|
5
|
+
## 重要说明
|
|
6
|
+
|
|
7
|
+
**本项目是核心服务库,不包含 UI 组件。**
|
|
8
|
+
|
|
9
|
+
`@posx/core` 是后端/核心库项目,提供业务逻辑服务,不是 UI 应用。因此没有 Vue/React 组件。
|
|
10
|
+
|
|
11
|
+
## 项目性质
|
|
12
|
+
|
|
13
|
+
- **类型:** TypeScript 核心库
|
|
14
|
+
- **用途:** 被其他 POS 前端应用消费
|
|
15
|
+
- **输出:** ESM bundle + 类型声明
|
|
16
|
+
|
|
17
|
+
## 提供的类型定义
|
|
18
|
+
|
|
19
|
+
虽然没有 UI 组件,但提供了完整的类型定义供 UI 层使用:
|
|
20
|
+
|
|
21
|
+
### 业务实体类型
|
|
22
|
+
|
|
23
|
+
| 文件 | 主要类型 | 用途 |
|
|
24
|
+
|------|---------|------|
|
|
25
|
+
| `invoice.type.ts` | IInvoice, IInvoiceLine | 发票数据结构 |
|
|
26
|
+
| `product.type.ts` | IItem, ICategory | 商品/分类 |
|
|
27
|
+
| `payment.type.ts` | IPayment, IPaymentMethod | 支付数据 |
|
|
28
|
+
| `employee.type.ts` | IEmployee | 员工信息 |
|
|
29
|
+
| `config.type.ts` | IAppConfig | 应用配置 |
|
|
30
|
+
| `printer.type.ts` | IPrinter, IPrintJob | 打印相关 |
|
|
31
|
+
| `shift.type.ts` | IShift, ITill | 班次/收银机 |
|
|
32
|
+
| `report.type.ts` | IAppReport | 报表数据 |
|
|
33
|
+
| `section.type.ts` | ISection, ISectionItem | 区域/桌位 |
|
|
34
|
+
|
|
35
|
+
### 枚举类型
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// 发票状态
|
|
39
|
+
enum InvoiceStatus { Open, OnHold, Paying, Paid, Void, PayAtCounter, Calibration }
|
|
40
|
+
|
|
41
|
+
// 打印机类型
|
|
42
|
+
enum PrinterType { Receipt, Kitchen, Kiosk, Label, Order, Check }
|
|
43
|
+
|
|
44
|
+
// 支付状态
|
|
45
|
+
enum PaymentStatus { payment_started, payment_completed, payment_failed, payment_cancelled }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## UI 应用位置
|
|
49
|
+
|
|
50
|
+
使用本库的 UI 应用可能位于:
|
|
51
|
+
- 单独的 `packages/app/` 目录 (monorepo 结构)
|
|
52
|
+
- 独立的前端仓库
|
|
53
|
+
- 消费 `@posx/core` 作为 npm 依赖
|
|
54
|
+
|
|
55
|
+
## 相关文档
|
|
56
|
+
|
|
57
|
+
- [PROJECT_OVERVIEW.md](./PROJECT_OVERVIEW.md) - 项目总览
|
|
58
|
+
- [02_CORE_BUSINESS.md](./02_CORE_BUSINESS.md) - 核心业务逻辑
|
|
59
|
+
- [05_DATA_LAYER.md](./05_DATA_LAYER.md) - 数据层
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# 04 - 页面实现
|
|
2
|
+
|
|
3
|
+
> AI 上下文索引:核心库、非UI应用、服务层、类型导出
|
|
4
|
+
|
|
5
|
+
## 重要说明
|
|
6
|
+
|
|
7
|
+
**本项目是核心服务库,不包含页面/视图。**
|
|
8
|
+
|
|
9
|
+
`@posx/core` 是 TypeScript 核心库,提供业务逻辑和数据服务,不是前端应用。因此没有 Vue/React 页面。
|
|
10
|
+
|
|
11
|
+
## 项目性质
|
|
12
|
+
|
|
13
|
+
- **类型:** 后端服务库
|
|
14
|
+
- **输出:** ESM bundle + 类型声明
|
|
15
|
+
- **用途:** 被 POS 前端应用消费
|
|
16
|
+
|
|
17
|
+
## 提供的服务
|
|
18
|
+
|
|
19
|
+
本库为 UI 层提供完整的业务服务:
|
|
20
|
+
|
|
21
|
+
### POS 相关服务
|
|
22
|
+
|
|
23
|
+
| 服务 | 功能 |
|
|
24
|
+
|------|------|
|
|
25
|
+
| SectionService | 区域管理 |
|
|
26
|
+
| SectionItemService | 桌位管理 |
|
|
27
|
+
| InvoiceService | 发票/订单处理 |
|
|
28
|
+
| ItemService | 商品查询 |
|
|
29
|
+
|
|
30
|
+
### 管理相关服务
|
|
31
|
+
|
|
32
|
+
| 服务 | 功能 |
|
|
33
|
+
|------|------|
|
|
34
|
+
| EmployeeService | 员工管理 |
|
|
35
|
+
| EmployeeRoleService | 角色权限 |
|
|
36
|
+
| ConfigService | 系统配置 |
|
|
37
|
+
| ReportService | 报表数据 |
|
|
38
|
+
|
|
39
|
+
### 设置相关服务
|
|
40
|
+
|
|
41
|
+
| 服务 | 功能 |
|
|
42
|
+
|------|------|
|
|
43
|
+
| PrinterService | 打印机配置 |
|
|
44
|
+
| PaymentMethodService | 支付方式 |
|
|
45
|
+
| CategoryService | 分类管理 |
|
|
46
|
+
| MenuService | 菜单配置 |
|
|
47
|
+
|
|
48
|
+
## UI 应用架构建议
|
|
49
|
+
|
|
50
|
+
使用本库的 UI 应用典型结构:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
app/
|
|
54
|
+
├── views/
|
|
55
|
+
│ ├── pos/ # POS 页面
|
|
56
|
+
│ ├── management/ # 管理页面
|
|
57
|
+
│ ├── settings/ # 设置页面
|
|
58
|
+
│ └── reporting/ # 报表页面
|
|
59
|
+
├── stores/ # 状态管理
|
|
60
|
+
└── services/ # 服务调用层
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 服务调用示例
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { ServiceFactory, InvoiceService } from '@posx/core';
|
|
67
|
+
|
|
68
|
+
// 初始化服务工厂
|
|
69
|
+
const factory = await ServiceFactory.init(options, window);
|
|
70
|
+
|
|
71
|
+
// 获取服务
|
|
72
|
+
const invoiceService = await factory.getServiceByName('Invoice');
|
|
73
|
+
|
|
74
|
+
// 使用服务
|
|
75
|
+
const invoice = await invoiceService.getOne(uid);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 相关文档
|
|
79
|
+
|
|
80
|
+
- [PROJECT_OVERVIEW.md](./PROJECT_OVERVIEW.md) - 项目总览
|
|
81
|
+
- [02_CORE_BUSINESS.md](./02_CORE_BUSINESS.md) - 核心业务逻辑
|
|
82
|
+
- [05_DATA_LAYER.md](./05_DATA_LAYER.md) - 数据层
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
# 05 - 数据层
|
|
2
|
+
|
|
3
|
+
> AI 上下文索引:Dexie、IndexedDB、服务工厂、HTTP客户端、类型系统、查询过滤
|
|
4
|
+
|
|
5
|
+
## 架构概述
|
|
6
|
+
|
|
7
|
+
采用 **混合数据架构**:本地 IndexedDB (Dexie) + 远程 API 同步
|
|
8
|
+
|
|
9
|
+
## 1. 数据库实现
|
|
10
|
+
|
|
11
|
+
### Dexie (IndexedDB 包装器)
|
|
12
|
+
|
|
13
|
+
**位置:** `src/service.factory.ts`
|
|
14
|
+
**版本:** Dexie v3.2.4
|
|
15
|
+
**Schema 版本:** v28
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// 初始化
|
|
19
|
+
public dataSource: Dexie;
|
|
20
|
+
public async initializeDatabase() {
|
|
21
|
+
this.dataSource = await new Dexie(this.options.database.name);
|
|
22
|
+
this.dataSource.version(28).stores(dbSchemas);
|
|
23
|
+
this.status = DbStatus.CONNECTED;
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 数据库表结构
|
|
28
|
+
|
|
29
|
+
**基础索引模式:**
|
|
30
|
+
```typescript
|
|
31
|
+
const baseSchema = 'uid, updated_at, created_at, deleted_at, _timestamp, id_in_server, created_at_timestamp';
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**完整表清单 (28 张):**
|
|
35
|
+
|
|
36
|
+
| 表名 | 额外索引 | 用途 |
|
|
37
|
+
|------|---------|------|
|
|
38
|
+
| items | name, barcode, codename, sequence | 商品 |
|
|
39
|
+
| sections | sequence | 区域 |
|
|
40
|
+
| section_items | sequence | 桌位 |
|
|
41
|
+
| categories | sequence | 分类 |
|
|
42
|
+
| invoices | type, status, table_uid | 发票 |
|
|
43
|
+
| employees | role_uid | 员工 |
|
|
44
|
+
| payment_methods | is_cash | 支付方式 |
|
|
45
|
+
| configs | - | 配置 |
|
|
46
|
+
| shifts | status | 班次 |
|
|
47
|
+
| tills | employee_uid | 收银机 |
|
|
48
|
+
| printers | - | 打印机 |
|
|
49
|
+
| print_jobs | status, printer_type, device_uid_to_print | 打印任务 |
|
|
50
|
+
| print_templates | type | 打印模板 |
|
|
51
|
+
| employee_roles | name, is_default | 角色 |
|
|
52
|
+
| order_displays | invoice_uid, status | 厨显 |
|
|
53
|
+
| storages | model | 通用存储 |
|
|
54
|
+
| menus | - | 菜单 |
|
|
55
|
+
| reports | - | 报表 |
|
|
56
|
+
|
|
57
|
+
### 数据库操作
|
|
58
|
+
|
|
59
|
+
**位置:** `src/services/abstract.service.ts`
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
// 创建/更新
|
|
63
|
+
async saveOne(item: T): Promise<T>
|
|
64
|
+
async saveMany(items: T[]): Promise<T[]>
|
|
65
|
+
|
|
66
|
+
// 读取
|
|
67
|
+
async getOne(uid: string): Promise<T>
|
|
68
|
+
async getOneByParams(params: Partial<T>): Promise<T | null>
|
|
69
|
+
async getAll(): Promise<T[]>
|
|
70
|
+
async getMany(params, options): Promise<GetManyResult<T>>
|
|
71
|
+
|
|
72
|
+
// 实时查询
|
|
73
|
+
public liveQuery<T>(expr: () => T): Observable<T>
|
|
74
|
+
|
|
75
|
+
// 清理
|
|
76
|
+
async clearTableData(tableName: string)
|
|
77
|
+
async dropDatabase()
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## 2. 存储工具
|
|
81
|
+
|
|
82
|
+
### 通用存储模型
|
|
83
|
+
|
|
84
|
+
**位置:** `src/types/storage.type.ts`
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
interface IStorage<T = Record<string, unknown> | unknown[]> extends IAppBaseModel {
|
|
88
|
+
uid: string;
|
|
89
|
+
model: 'discounts' | string;
|
|
90
|
+
data: T;
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**用途:** 存储折扣等复杂对象,通过 `storages` 表持久化。
|
|
95
|
+
|
|
96
|
+
## 3. API 服务
|
|
97
|
+
|
|
98
|
+
### HTTP 客户端工厂
|
|
99
|
+
|
|
100
|
+
**位置:** `src/utils/http.utils.ts`
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
export function createInstance(baseURL: string, uid: string, token: string) {
|
|
104
|
+
const instance = axios.create({
|
|
105
|
+
baseURL: baseURL,
|
|
106
|
+
timeout: 20000,
|
|
107
|
+
headers: {
|
|
108
|
+
'x-device-uid': uid,
|
|
109
|
+
'Authorization': `Bearer ${token}`
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
instance.interceptors.response.use(
|
|
114
|
+
(response) => response.data,
|
|
115
|
+
(error) => Promise.reject(error)
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
return instance;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 服务层架构
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
AppCoreService (基础 CRUD)
|
|
126
|
+
│
|
|
127
|
+
├── AppLocalService (本地,无远程)
|
|
128
|
+
│
|
|
129
|
+
└── AppRemoteService (CRUD + API 同步)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### API 端点模式
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
PUT /api/v5/merchants/{merchant_uid}/{module}/{method} # 创建
|
|
136
|
+
PATCH /api/v5/merchants/{merchant_uid}/{module}/{id} # 更新单个
|
|
137
|
+
PATCH /api/v5/merchants/{merchant_uid}/{module} # 批量更新
|
|
138
|
+
DELETE /api/v5/merchants/{merchant_uid}/{module}/{id} # 删除
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## 4. 服务工厂
|
|
142
|
+
|
|
143
|
+
**位置:** `src/service.factory.ts`
|
|
144
|
+
|
|
145
|
+
### 服务注册表 (18 个服务)
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
const serviceProvider = new Map([
|
|
149
|
+
['Item', ItemService],
|
|
150
|
+
['Section', SectionService],
|
|
151
|
+
['SectionItem', SectionItemService],
|
|
152
|
+
['Category', CategoryService],
|
|
153
|
+
['Config', ConfigService],
|
|
154
|
+
['Shift', ShiftService],
|
|
155
|
+
['Till', TillService],
|
|
156
|
+
['Employee', EmployeeService],
|
|
157
|
+
['PaymentMethod', PaymentMethodService],
|
|
158
|
+
['Invoice', InvoiceService],
|
|
159
|
+
['Report', AppReportService],
|
|
160
|
+
['Printer', PrinterService],
|
|
161
|
+
['PrintJob', PrintJobService],
|
|
162
|
+
['PrintTemplate', PrintTemplateService],
|
|
163
|
+
['EmployeeRole', EmployeeRoleService],
|
|
164
|
+
['OrderDisplay', OrderDisplayService],
|
|
165
|
+
['Storage', StorageService],
|
|
166
|
+
['Menu', MenuService]
|
|
167
|
+
]);
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### 服务获取方式
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// 按类引用
|
|
174
|
+
const invoiceService = await factory.getService<InvoiceService>(InvoiceService);
|
|
175
|
+
|
|
176
|
+
// 按名称
|
|
177
|
+
const itemService = await factory.getServiceByName('Item');
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### 运行模式
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
enum ServiceMode {
|
|
184
|
+
LOCAL = 'local', // 仅本地
|
|
185
|
+
CLOUD = 'cloud' // 远程同步
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
interface IServiceOptions {
|
|
189
|
+
mode: ServiceMode;
|
|
190
|
+
base_url: string;
|
|
191
|
+
device_uid: string;
|
|
192
|
+
merchant_uid: string;
|
|
193
|
+
token: string;
|
|
194
|
+
database: { version: number; name: string };
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## 5. 数据模型
|
|
199
|
+
|
|
200
|
+
### 模型层次
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
IAppCoreModel (核心接口)
|
|
204
|
+
│
|
|
205
|
+
└── AppCoreModel (抽象基类)
|
|
206
|
+
│
|
|
207
|
+
├── IAppBaseModel (+ name)
|
|
208
|
+
│ └── AppBaseModel
|
|
209
|
+
│ │
|
|
210
|
+
│ └── IAppExtraModel (+ description)
|
|
211
|
+
│ └── AppExtraModel
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### 核心字段
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
interface IAppCoreModel {
|
|
218
|
+
uid: string; // nanoid 主键
|
|
219
|
+
updated_at: Date;
|
|
220
|
+
created_at: Date;
|
|
221
|
+
created_at_timestamp: number;
|
|
222
|
+
deleted_at: Date | null; // 软删除标记
|
|
223
|
+
_timestamp: number; // 同步跟踪
|
|
224
|
+
id_in_server: number; // 远程 ID
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### UID 前缀
|
|
229
|
+
|
|
230
|
+
| 前缀 | 实体 |
|
|
231
|
+
|------|------|
|
|
232
|
+
| inv_ | Invoice |
|
|
233
|
+
| itm_ | Item |
|
|
234
|
+
| emp_ | Employee |
|
|
235
|
+
| cat_ | Category |
|
|
236
|
+
| sec_ | Section |
|
|
237
|
+
| sit_ | SectionItem |
|
|
238
|
+
|
|
239
|
+
### 类型定义文件
|
|
240
|
+
|
|
241
|
+
| 文件 | 主要类型 | 行数 |
|
|
242
|
+
|------|---------|------|
|
|
243
|
+
| invoice.type.ts | IInvoice, IInvoiceLine | ~540 |
|
|
244
|
+
| product.type.ts | IItem, ICategory | ~600 |
|
|
245
|
+
| config.type.ts | IAppConfig | ~760 |
|
|
246
|
+
| printer.type.ts | IPrinter, IPrintJob | ~350 |
|
|
247
|
+
| payment.type.ts | IPayment, IPaymentMethod | ~270 |
|
|
248
|
+
|
|
249
|
+
## 6. 查询过滤
|
|
250
|
+
|
|
251
|
+
**位置:** `src/libs/FindOptions.ts`
|
|
252
|
+
|
|
253
|
+
### 过滤函数
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
export const Include = (query?: string) =>
|
|
257
|
+
(val) => isEmpty(query) || val.includes(query);
|
|
258
|
+
|
|
259
|
+
export const In = (query?: never[]) =>
|
|
260
|
+
(val) => isEmpty(query) || query.includes(val);
|
|
261
|
+
|
|
262
|
+
export const Between = (begin: number, end: number) =>
|
|
263
|
+
(val) => val > begin && val < end;
|
|
264
|
+
|
|
265
|
+
export const Not = (query?: any) =>
|
|
266
|
+
(val) => val != query;
|
|
267
|
+
|
|
268
|
+
export const filterByParams = (params) =>
|
|
269
|
+
(values) => !values['deleted_at'] && Object.keys(params).every(...);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### 使用示例
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
// 按分类查询
|
|
276
|
+
await itemService.getMany(
|
|
277
|
+
{ category_uid: 'cat_123' },
|
|
278
|
+
{ page: 1, pageSize: 20 }
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
// 自定义过滤
|
|
282
|
+
await itemService.getMany(
|
|
283
|
+
{ price: Between(10, 50) },
|
|
284
|
+
{ pageSize: -1 }
|
|
285
|
+
);
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## 7. 同步与持久化
|
|
289
|
+
|
|
290
|
+
### 软删除
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// 标记删除
|
|
294
|
+
await itemService.deleteOne(item); // 设置 deleted_at
|
|
295
|
+
|
|
296
|
+
// 硬删除
|
|
297
|
+
await itemService.hardDeleteOne(item); // 从数据库移除
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### 时间戳跟踪
|
|
301
|
+
|
|
302
|
+
- `created_at` - ISO 日期
|
|
303
|
+
- `created_at_timestamp` - Unix 毫秒
|
|
304
|
+
- `updated_at` - 每次保存更新
|
|
305
|
+
- `_timestamp` - 冲突解决
|
|
306
|
+
|
|
307
|
+
### 实时更新
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
const itemsObservable = itemService.liveQuery(() =>
|
|
311
|
+
itemService.getAll()
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
itemsObservable.subscribe(items => {
|
|
315
|
+
// 数据库变更时自动更新
|
|
316
|
+
});
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## 8. 架构图
|
|
320
|
+
|
|
321
|
+
```
|
|
322
|
+
┌─────────────────────────────────────────┐
|
|
323
|
+
│ Application Layer │
|
|
324
|
+
└──────────────────┬──────────────────────┘
|
|
325
|
+
│
|
|
326
|
+
┌──────────────────▼──────────────────────┐
|
|
327
|
+
│ ServiceFactory (DI) │
|
|
328
|
+
│ • 初始化 Dexie 数据库 │
|
|
329
|
+
│ • 管理 HTTP 客户端 │
|
|
330
|
+
│ • 按需实例化服务 │
|
|
331
|
+
└──────────────────┬──────────────────────┘
|
|
332
|
+
│
|
|
333
|
+
┌──────────┴──────────┐
|
|
334
|
+
│ │
|
|
335
|
+
▼ ▼
|
|
336
|
+
┌──────────────────┐ ┌──────────────────┐
|
|
337
|
+
│ HTTP Client │ │ IndexedDB │
|
|
338
|
+
│ (Axios) │ │ (Dexie) │
|
|
339
|
+
└────────┬─────────┘ └────────┬─────────┘
|
|
340
|
+
│ │
|
|
341
|
+
▼ ▼
|
|
342
|
+
┌──────────────────────────────────────┐
|
|
343
|
+
│ AppRemoteService (Abstract) │
|
|
344
|
+
│ CRUD + API 同步 + liveQuery │
|
|
345
|
+
└────────────┬─────────────────────────┘
|
|
346
|
+
│
|
|
347
|
+
┌────────────┴──────────────────────────┐
|
|
348
|
+
│ Domain Services (18) │
|
|
349
|
+
│ Invoice, Item, Printer, Config... │
|
|
350
|
+
└───────────────────────────────────────┘
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## 文件结构
|
|
354
|
+
|
|
355
|
+
```
|
|
356
|
+
src/
|
|
357
|
+
├── service.factory.ts # DI 容器 & Schema
|
|
358
|
+
├── services/
|
|
359
|
+
│ ├── abstract.service.ts # 基础 CRUD
|
|
360
|
+
│ ├── app.service.ts # 16 个领域服务
|
|
361
|
+
│ ├── invoice.service.ts # 发票计算
|
|
362
|
+
│ ├── printer.service.ts # 打印管理
|
|
363
|
+
│ └── ods.service.ts # 厨显系统
|
|
364
|
+
├── types/ # 12+ 类型文件
|
|
365
|
+
├── libs/
|
|
366
|
+
│ └── FindOptions.ts # 查询过滤
|
|
367
|
+
└── utils/
|
|
368
|
+
└── http.utils.ts # Axios 工厂
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## 相关文档
|
|
372
|
+
|
|
373
|
+
- [01_ARCHITECTURE.md](./01_ARCHITECTURE.md) - 整体架构
|
|
374
|
+
- [02_CORE_BUSINESS.md](./02_CORE_BUSINESS.md) - 核心业务
|
|
375
|
+
- [06_CROSS_PLATFORM.md](./06_CROSS_PLATFORM.md) - 跨平台
|