15 KiB
15 KiB
纯客户端转型设计规格
日期: 2026-04-27 状态: 已批准 作者: Zhang Xiang
1. 概述
将 Everything Is Suitable 从 C/S 架构(UniApp + Java Spring Boot + PostgreSQL)转型为纯客户端 App,通过 App Store、Google Play、华为/OPPO/小米等应用商店进行买断制付费分发,完全移除服务端。
产品定位:中国传统文化研究工具。
2. 决策记录
| 决策项 | 选择 | 理由 |
|---|---|---|
| 架构方案 | UniApp 继续演进 | 复用现有 UI,跨平台覆盖最广,风险最低 |
| 目标平台 | iOS + Android (Google Play) + 国内安卓商店 | 最大化覆盖面 |
| 付费模式 | 买断制付费下载 | 纯客户端最简变现方式 |
| 功能范围 | 第一版包含全部核心功能 | 黄历+紫微+运势全部移植 |
| 后端处理 | 完全删除 | 不再需要服务端 |
| 数据存储 | 纯本地存储 + 可选 iCloud 同步 | 无服务端,数据在设备本地 |
| CI/CD | Jenkins | 团队现有基础设施 |
3. 整体架构
3.1 转型后架构
┌─────────────────────────────────────────────────────┐
│ 纯客户端 App (UniApp) │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 表现层 (Pages / Components) │ │
│ │ 黄历查询页 | 紫微排盘页 | 运势分析页 | 搜索页 │ │
│ └───────────────────┬──────────────────────────┘ │
│ │ │
│ ┌───────────────────▼──────────────────────────┐ │
│ │ 服务层 (Local Services) │ │
│ │ AlmanacService | ZiweiService | FortuneService│ │
│ │ SearchService | TemplateService │ │
│ └───────────────────┬──────────────────────────┘ │
│ │ │
│ ┌───────────────────▼──────────────────────────┐ │
│ │ 算法层 (Core Algorithms) │ │
│ │ lunar.ts | almanac.ts | ziwei.ts | fortune.ts│ │
│ │ sanFangSiZheng.ts | heavenlyStems.ts │ │
│ └───────────────────┬──────────────────────────┘ │
│ │ │
│ ┌───────────────────▼──────────────────────────┐ │
│ │ 基础设施层 (Infrastructure) │ │
│ │ LRUCache | PerformanceMonitor | Storage │ │
│ │ ExportImport | CloudSync(iCloud/GDrive) │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
3.2 核心模块映射 (Java → TypeScript)
| Java 模块 | TypeScript 目标 | 关键类/方法 |
|---|---|---|
AlmanacServiceImpl |
almanac.ts |
getAlmanacByDate, getAlmanacsByRange |
AlmanacSearchHandler |
searchService.ts (重写) |
search, searchByKeyword |
ZiweiChartServiceImpl |
ziwei.ts |
generateChart, getPalaceInfo |
ZiweiAlgorithmUtil (1025行) |
ziweiAlgorithm.ts |
排盘核心算法 |
SanFangSiZhengUtil (249行) |
sanFangSiZheng.ts |
三方四正计算 |
FortuneAnalysisServiceImpl |
fortune.ts |
daily/monthly/yearly/overall |
DailyFortuneStrategy (229行) |
fortuneStrategy.ts |
日运策略 |
MonthlyFortuneStrategy (404行) |
fortuneStrategy.ts |
月运策略 |
LunarCalendarServiceImpl |
已有 lunar.ts |
无需移植 |
CalendarServiceImpl |
calendar.ts |
日历相关 |
3.3 转型后目录结构
everything-is-suitable/
├── everything-is-suitable-uniapp/ # 唯一保留的项目
│ ├── src/
│ │ ├── algorithms/ # 新增:核心算法层
│ │ │ ├── almanac.ts
│ │ │ ├── ziwei.ts
│ │ │ ├── ziweiAlgorithm.ts
│ │ │ ├── sanFangSiZheng.ts
│ │ │ ├── fortune.ts
│ │ │ ├── fortuneStrategy.ts
│ │ │ ├── calendar.ts
│ │ │ └── types.ts # 算法层共享类型
│ │ ├── services/ # 重写:本地服务层
│ │ │ ├── almanacService.ts
│ │ │ ├── ziweiService.ts
│ │ │ ├── fortuneService.ts
│ │ │ ├── searchService.ts
│ │ │ └── templateService.ts
│ │ ├── utils/ # 保留+增强
│ │ │ ├── lunar.ts # 已有
│ │ │ ├── lruCache.ts # 已有
│ │ │ ├── searchOptimizer.ts # 已有
│ │ │ ├── performanceMonitor.ts # 已有
│ │ │ ├── storage.ts # 新增:统一本地存储
│ │ │ ├── exportImport.ts # 新增:数据导出导入
│ │ │ └── errorHandler.ts # 已有
│ │ ├── components/ # 保留
│ │ ├── pages/ # 保留+新增
│ │ │ ├── almanac-search/ # 已有
│ │ │ ├── ziwei/ # 新增:紫微排盘页
│ │ │ └── fortune/ # 新增:运势分析页
│ │ └── types/ # 保留+扩展
│ ├── package.json
│ ├── Jenkinsfile # 新增:Jenkins CI
│ └── ...
└── (其他目录全部删除)
4. 核心算法移植策略
4.1 移植原则
- 算法逻辑 1:1 移植:不重构算法,保持与 Java 代码逻辑一致,便于交叉验证
- 类型先行:先移植枚举和领域模型,再移植算法
- 测试驱动:每个算法移植后,用 Java 端的现有测试用例做交叉验证
4.2 移植分层顺序
Step 1: 枚举与常量 (Enums)
- HeavenlyStem (天干)
- EarthlyBranch (地支)
- MajorStar (主星)
- PalaceType (宫位类型)
- StarNature (星性)
- TransformationType (四化类型)
- FortuneType (运势类型)
- StarBrightness (星曜亮度)
Step 2: 领域模型 (Domain Models)
- BirthInfo (出生信息)
- ZiweiChart (命盘)
- Palace (宫位)
- StarInfo (星曜信息)
- DailyFortune (日运)
- MonthlyFortune (月运)
- Almanac (黄历)
- LunarDate (农历日期 - 已有)
Step 3: 核心算法 (Algorithms)
- ZiweiAlgorithmUtil → ziweiAlgorithm.ts (排盘核心)
- SanFangSiZhengUtil → sanFangSiZheng.ts (三方四正)
- FortuneStrategy → fortuneStrategy.ts (运势策略)
- AlmanacService → almanac.ts (黄历计算)
Step 4: 服务层 (Services)
- ZiweiChartService → ziweiService.ts
- FortuneAnalysisService → fortuneService.ts
- AlmanacService → almanacService.ts
- SearchService → searchService.ts (重写为本地搜索)
4.3 Java → TypeScript 关键差异处理
| Java 特性 | TypeScript 对应 | 注意事项 |
|---|---|---|
int 除法自动截断 |
Math.floor() |
必须显式处理 |
enum |
enum + 辅助方法 |
fromIndex/fromName 等 |
List<T> |
T[] |
数组操作 |
Map<K,V> |
Map<K,V> |
保持一致 |
| Caffeine Cache | LRUCache (已有) | 已有实现 |
Optional<T> |
T | null |
空值处理 |
record |
interface |
不可变用 readonly |
switch 表达式 |
switch 语句 |
无表达式形式 |
4.4 交叉验证策略
每个算法移植后,使用 Java 端现有测试用例生成黄金数据集:
- 从 Java 测试用例中提取输入/输出对
- 在 TypeScript 中用相同输入执行
- 比对输出,允许浮点误差 < 0.001
- 100% 通过才算移植成功
5. 后端依赖移除与本地服务替换
5.1 需要删除的目录和文件
| 目标 | 处理方式 |
|---|---|
everything-is-suitable-api/ |
整个目录删除 |
everything-is-suitable-admin/ |
整个目录删除 |
everything-is-suitable-test/ |
整个目录删除 |
docker-compose.yml |
删除 |
docker-compose.*.yml |
删除 |
Dockerfile* |
删除 |
.woodpecker.yml |
删除,替换为 Jenkinsfile |
DEPLOYMENT.md |
删除 |
WOODPECKER_CI.md |
删除 |
STARTUP_GUIDE.md |
删除 |
config/ (根目录) |
删除 |
5.2 需要从 UniApp 中移除的文件
| 文件 | 替代方案 |
|---|---|
src/utils/httpClient.ts |
删除,本地服务直接调用 |
src/utils/tokenManager.ts |
删除,无需认证 |
src/types/api.ts |
删除,无远程 API |
config/ (baseURL 等) |
删除,无远程端点 |
5.3 本地服务替换映射
| 远程 API 调用 | 本地服务调用 |
|---|---|
httpClient.get('/almanac/{date}') |
almanacService.getByDate(date) |
httpClient.get('/almanac/range') |
almanacService.getByRange(start, end) |
httpClient.post('/almanac/search') |
searchService.search(request) |
httpClient.post('/fortune/daily') |
fortuneService.getDaily(birthInfo, date) |
httpClient.post('/fortune/monthly') |
fortuneService.getMonthly(birthInfo, month) |
httpClient.post('/fortune/yearly') |
fortuneService.getYearly(birthInfo, year) |
httpClient.post('/fortune/overall') |
fortuneService.getOverall(birthInfo) |
httpClient.post('/ziwei/chart') |
ziweiService.generateChart(birthInfo) |
5.4 统一本地存储层
新增 utils/storage.ts,封装 uni.storage:
get<T>(key: string): T | nullset<T>(key: string, value: T): voidremove(key: string): voidclear(): voidenableCloudSync(): void(后续版本:iCloud/Google Drive)syncToCloud(): Promise<void>(后续版本)syncFromCloud(): Promise<void>(后续版本)
第一版仅实现纯本地存储,云同步功能在后续版本中添加。
6. 付费分发与商店适配
6.1 付费模式
买断制付费下载,一次性购买永久使用。
| 平台 | 实现方式 | 费用 |
|---|---|---|
| App Store | Paid Application | Apple Developer $99/年 |
| Google Play | Paid App | Google Play Developer $25 一次性 |
| 华为应用市场 | 付费下载 | 华为开发者账号 |
| OPPO/小米 | 付费下载 | 各自开发者账号 |
6.2 内容合规:传统文化定位策略
所有文案和 UI 必须遵循"传统文化研究工具"定位。
禁用词替换表:
| 禁用词 | 替代词 |
|---|---|
| 算命 | 命理研究 |
| 预测 | 参考分析 |
| 占卜 | 传统卜筮文化研究 |
| 运势 | 时令参考 |
| 吉凶 | 传统宜忌参考 |
| 风水 | 传统堪舆文化 |
App 描述模板:
本应用是一款中国传统文化研究工具,基于传统历法学、紫微斗数学等传统文化体系,提供黄历查询、命盘排布、时令参考等功能。所有内容仅供传统文化学术研究参考,不构成任何决策建议。
6.3 各平台审核要点
| 平台 | 关键审核点 | 应对策略 |
|---|---|---|
| App Store | 2.5.2 功能完整 | 确保离线可用、无空白页 |
| App Store | 命理类需标注"娱乐" | 描述中标注"传统文化研究,仅供学术参考" |
| Google Play | 无特殊命理限制 | 正常提交 |
| 华为 | 对"迷信"内容敏感 | 强调"传统文化""学术研究"定位 |
| OPPO/小米 | 类似华为 | 同上 + 提供免责声明 |
7. 测试策略与质量保障
7.1 分层测试策略
┌─────────────────────────────────────┐
│ E2E 测试 (Playwright) │ 关键用户流程
├─────────────────────────────────────┤
│ 集成测试 (Vitest) │ 服务层 + 算法层联动
├─────────────────────────────────────┤
│ 单元测试 (Vitest) │ 算法正确性
├─────────────────────────────────────┤
│ 交叉验证测试 (Vitest) │ Java vs TS 结果比对
└─────────────────────────────────────┘
7.2 交叉验证测试
从 Java 端测试用例中提取黄金数据,确保 TypeScript 移植结果与 Java 完全一致。
测试用例来源:
ZiweiAlgorithmUtilTest.java(494行)ComprehensiveAlmanacServiceTest.javaDailyFortuneTest.java(334行)AlmanacSearchHandlerTest.java(490行)
7.3 质量门禁
| 指标 | 标准 |
|---|---|
| 算法层单元测试覆盖率 | >= 90% |
| 服务层单元测试覆盖率 | >= 80% |
| 交叉验证通过率 | 100% |
| E2E 关键路径通过率 | 100% |
| Lint 错误 | 0 |
| TypeScript 严格模式 | 开启 |
8. CI/CD (Jenkins)
pipeline {
agent any
environment {
NODE_VERSION = '20'
PROJECT_DIR = 'everything-is-suitable-uniapp'
}
stages {
stage('Install') {
steps {
dir(env.PROJECT_DIR) { sh 'npm ci' }
}
}
stage('Lint') {
steps {
dir(env.PROJECT_DIR) { sh 'npm run lint' }
}
}
stage('Unit Test') {
steps {
dir(env.PROJECT_DIR) { sh 'npm run test' }
}
post {
always { junit "${env.PROJECT_DIR}/test-results/*.xml" }
}
}
stage('Build H5') {
steps {
dir(env.PROJECT_DIR) { sh 'npm run build:h5' }
}
}
stage('Build Android') {
when { branch 'main' }
steps {
dir(env.PROJECT_DIR) { sh 'npm run build:app-android' }
}
}
stage('Build iOS') {
when { branch 'main' }
steps {
dir(env.PROJECT_DIR) { sh 'npm run build:app-ios' }
}
}
}
}
9. ICP 备案说明
纯客户端 App(无后端服务)不需要 ICP 备案。这不是"绕过",而是法律上的"不适用"——ICP 备案规制的是"互联网信息服务提供者",纯客户端 App 没有服务端,不构成信息服务提供者。
国内应用商店(华为/OPPO/小米)可能要求声明"本应用为纯客户端应用,无后端服务,不涉及互联网信息服务"。
10. 风险与缓解
| 风险 | 影响 | 缓解措施 |
|---|---|---|
| 算法移植正确性 | 高 | 交叉验证测试 + 黄金数据集 |
| 命理类内容审核 | 高 | 传统文化定位 + 合规文案 |
| App 体积过大 | 中 | 按需加载 + 数据压缩 |
| 算法性能瓶颈 | 低 | Web Worker 隔离 + LRUCache |
| 越狱盗版 | 低 | 可接受风险,商店内购保护 |