@posx/core 5.5.393 → 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.
Files changed (34) hide show
  1. package/CLAUDE.md +23 -23
  2. package/LICENSE +21 -21
  3. package/README.md +85 -85
  4. package/build/index.d.ts +6 -0
  5. package/jest.config.cjs +36 -36
  6. package/jest.setup.cjs +80 -80
  7. package/memo/technical-docs/01_ARCHITECTURE.md +147 -0
  8. package/memo/technical-docs/02_CORE_BUSINESS.md +292 -0
  9. package/memo/technical-docs/03_UI_COMPONENTS.md +59 -0
  10. package/memo/technical-docs/04_VIEWS.md +82 -0
  11. package/memo/technical-docs/05_DATA_LAYER.md +375 -0
  12. package/memo/technical-docs/06_CROSS_PLATFORM.md +246 -0
  13. package/memo/technical-docs/07_SIMILARITY_INDEX.md +195 -0
  14. package/memo/technical-docs/CHECKPOINT.md +46 -0
  15. package/memo/technical-docs/PROJECT_OVERVIEW.md +122 -0
  16. package/memo/technical-docs/TECHNICAL_DOCS_PLAN.md +77 -0
  17. package/package.json +1 -1
  18. package/package.publish.json +121 -120
  19. package/tsdown.config.ts +21 -21
  20. package/vite.config.ts +86 -86
  21. package/dev/.stfolder/syncthing-folder-9a95b7.txt +0 -5
  22. package/dev/98894488.xlsx +0 -0
  23. package/dev/HappyThaiSembawang.csv +0 -336
  24. package/dev/KB/create-new-model.md +0 -34
  25. package/dev/KB/markdown-lint.md +0 -14
  26. package/dev/KB/readmefirst.md +0 -6
  27. package/dev/Merchants/HappyThaiSembawang.csv +0 -400
  28. package/dev/Merchants/HappyThaiSembawang.xlsx +0 -0
  29. package/dev/Product_Import_Template.xlsx +0 -0
  30. package/dev/XPOS Invoice Module.pdf +0 -232
  31. package/dev/harbor-harness-deployment.md +0 -78
  32. package/dev/nginx-harbor-harness.conf +0 -84
  33. package/dev/test-logs/2026-02.md +0 -5
  34. 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,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) - 跨平台
@@ -0,0 +1,246 @@
1
+ # 06 - 跨平台能力
2
+
3
+ > AI 上下文索引:Capacitor、Electron、ESC/POS、打印机、Socket、字符编码
4
+
5
+ ## 跨平台概述
6
+
7
+ 本库支持多平台运行:Web、Electron、Capacitor (iOS/Android)
8
+
9
+ ## 1. Capacitor 插件
10
+
11
+ **依赖:** `@capacitor/core@5.4.2`, `@awesome-cordova-plugins/network-interface@6.6.0`
12
+
13
+ ### 网络接口
14
+
15
+ **位置:** `src/services/printer.service.ts`
16
+
17
+ ```typescript
18
+ import { NetworkInterface } from '@awesome-cordova-plugins/network-interface';
19
+
20
+ // 获取 WiFi IP 地址
21
+ const ipAddress: NetworkInfo = await NetworkInterface.getWiFiIPAddress();
22
+ ```
23
+
24
+ **用途:**
25
+ - 检测设备 WiFi IP
26
+ - 计算子网掩码
27
+ - 扫描子网发现打印机
28
+
29
+ ## 2. Electron 集成
30
+
31
+ ### 类型定义
32
+
33
+ **位置:** `src/libs/electron.d.ts`
34
+
35
+ ```typescript
36
+ interface Window {
37
+ electronSocket: {
38
+ open: (host: string, port: number) => Promise<boolean>;
39
+ write: (data: number[]) => Promise<boolean>;
40
+ close: () => Promise<boolean>;
41
+ shutdownWrite: () => Promise<boolean>;
42
+ onData: (callback) => void;
43
+ onClose: (callback) => void;
44
+ onError: (callback) => void;
45
+ onEvent: (callback) => () => void;
46
+ };
47
+ }
48
+ ```
49
+
50
+ ### Socket 桥接
51
+
52
+ **位置:** `src/libs/electron.socket.ts`
53
+
54
+ **状态机:**
55
+ ```
56
+ CLOSED (0) → OPENING (1) → OPENED (2) → CLOSING (3)
57
+ ```
58
+
59
+ **回调系统:**
60
+ ```typescript
61
+ public onData: ((data: Uint8Array) => void) | null = null;
62
+ public onClose: ((hadError: boolean) => void) | null = null;
63
+ public onError: ((error: string) => void) | null = null;
64
+ ```
65
+
66
+ **方法:**
67
+ - `open(host, port, success?, error?)` - 建立连接
68
+ - `write(data, success?, error?)` - 发送数据
69
+ - `close(success?, error?)` - 关闭连接
70
+
71
+ **初始化:**
72
+ ```typescript
73
+ // service.factory.ts
74
+ ElectronSocket.setWindow(win);
75
+ ```
76
+
77
+ ## 3. 打印机硬件
78
+
79
+ ### ESC/POS 实现
80
+
81
+ **位置:** `src/libs/escpos.printer.ts`
82
+
83
+ **Socket 抽象:**
84
+ ```typescript
85
+ function getSocket(): any {
86
+ return typeof Socket === 'undefined' ? new ElectronSocket() : new Socket();
87
+ }
88
+ ```
89
+
90
+ ### 连接类型
91
+
92
+ ```typescript
93
+ enum PrinterConnections {
94
+ USB,
95
+ WINDOWS_DRIVER,
96
+ ETHERNET, // 主要用于网络打印机
97
+ BLUETOOTH,
98
+ BUILTIN
99
+ }
100
+ ```
101
+
102
+ ### 打印协议
103
+
104
+ ```typescript
105
+ enum PrinterProtocols {
106
+ ESCPOS, // 收据打印机、厨显
107
+ TSPL // 标签打印机
108
+ }
109
+ ```
110
+
111
+ ### 打印操作
112
+
113
+ | 方法 | 功能 |
114
+ |------|------|
115
+ | `testPrint(template)` | 测试打印 |
116
+ | `connect(ip, port, timeout)` | TCP 连接 |
117
+ | `write(resultByte, timeout)` | 发送命令 |
118
+ | `interpret(template)` | 编码打印命令 |
119
+
120
+ ### 高级打印功能
121
+
122
+ - 自定义字体大小
123
+ - 表格 (列宽计算)
124
+ - QR 码 & 条形码
125
+ - 图片 (多种抖动算法)
126
+ - 钱箱控制
127
+ - 文本换行
128
+
129
+ ### 字符编码支持
130
+
131
+ **位置:** `src/libs/viscii.encoding.ts`
132
+
133
+ ```typescript
134
+ enum Codepages {
135
+ SimplifiedChinese = 'cp936',
136
+ TraditionalChinese = 'cp950',
137
+ Japanese = 'shiftjis',
138
+ Vietnamese = 'windows1258',
139
+ // ... 20+ 国际编码
140
+ }
141
+ ```
142
+
143
+ **越南语 VISCII:**
144
+ - UTF-8 到 VISCII 转换
145
+ - 100+ 越南语字符映射
146
+ - 不支持字符回退到 ASCII
147
+
148
+ ## 4. 打印机服务
149
+
150
+ **位置:** `src/services/printer.service.ts`
151
+
152
+ ### 网络发现
153
+
154
+ ```typescript
155
+ searchPrinters(refresh: boolean, port: number): Promise<string[]>
156
+ ```
157
+
158
+ **流程:**
159
+ 1. 获取设备 WiFi IP
160
+ 2. 计算子网掩码
161
+ 3. TCP 扫描端口 1-254
162
+ 4. 缓存结果到本地数据库
163
+
164
+ ### 设备管理
165
+
166
+ - `getPhysicalPrintersFromNode()` - 查询连接的打印机
167
+ - `getUnpairedNode()` - 发现未配对节点
168
+ - `pairNode(nodeUid)` - 配对设备
169
+
170
+ ### 打印机配置
171
+
172
+ ```typescript
173
+ interface IPrinter {
174
+ device_uid: string;
175
+ type: PrinterType; // Receipt, Kitchen, Kiosk, Label
176
+ protocol: PrinterProtocols; // ESCPOS, TSPL
177
+ connection_type: PrinterConnections;
178
+ driver_printer_name: string;
179
+ ip_address?: string;
180
+ print_sequence?: number;
181
+ retries: number;
182
+ print_times: number;
183
+ }
184
+ ```
185
+
186
+ ### 打印任务队列
187
+
188
+ ```typescript
189
+ interface IPrintJob {
190
+ printer_uid: string;
191
+ connection_type: PrinterConnections;
192
+ protocol: PrinterProtocols;
193
+ device_uid_to_print: string;
194
+ save_only: boolean;
195
+ status: PrintJobStatus; // queued, printed, failed, expired
196
+ }
197
+ ```
198
+
199
+ ## 5. 离线支持
200
+
201
+ ### Dexie 集成
202
+
203
+ - **离线优先架构** 使用 IndexedDB
204
+ - 28 个数据库版本,自动迁移
205
+ - 打印机、打印任务、配置等表
206
+ - 离线时支持打印队列
207
+
208
+ ## 6. 未实现功能
209
+
210
+ | 功能 | 状态 |
211
+ |------|------|
212
+ | CodePush | 未实现 |
213
+ | 热更新 | 未实现 |
214
+ | 动态 Bundle 加载 | 未实现 |
215
+
216
+ 更新通过标准应用商店渠道处理。
217
+
218
+ ## 能力汇总
219
+
220
+ | 能力 | 实现 | 状态 |
221
+ |------|------|------|
222
+ | Capacitor | v5.4.2 - 网络插件 | ✅ 活跃 |
223
+ | Electron | IPC Socket 桥接 | ✅ 活跃 |
224
+ | 原生桥接 | ElectronSocket 抽象 | ✅ 活跃 |
225
+ | 打印协议 | ESC/POS, TSPL | ✅ 活跃 |
226
+ | 设备检测 | Cordova NetworkInterface | ✅ 活跃 |
227
+ | 字符编码 | VISCII, UTF-8, 20+ 编码 | ✅ 活跃 |
228
+ | 离线支持 | Dexie IndexedDB | ✅ 活跃 |
229
+ | CodePush | - | ❌ 未实现 |
230
+
231
+ ## 关键文件
232
+
233
+ | 文件 | 行数 | 职责 |
234
+ |------|------|------|
235
+ | `src/libs/electron.socket.ts` | 93 | 跨平台核心 |
236
+ | `src/libs/escpos.printer.ts` | 563 | 打印机硬件 |
237
+ | `src/services/printer.service.ts` | 200+ | 网络检测 |
238
+ | `src/types/printer.type.ts` | 325+ | 配置类型 |
239
+ | `src/libs/viscii.encoding.ts` | 55 | 编码支持 |
240
+ | `src/service.factory.ts` | 175 | 服务设置 |
241
+
242
+ ## 相关文档
243
+
244
+ - [01_ARCHITECTURE.md](./01_ARCHITECTURE.md) - 整体架构
245
+ - [02_CORE_BUSINESS.md](./02_CORE_BUSINESS.md) - 核心业务 (打印部分)
246
+ - [05_DATA_LAYER.md](./05_DATA_LAYER.md) - 数据层