# 纯客户端转型设计规格 > 日期: 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:1 移植**:不重构算法,保持与 Java 代码逻辑一致,便于交叉验证 2. **类型先行**:先移植枚举和领域模型,再移植算法 3. **测试驱动**:每个算法移植后,用 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[]` | 数组操作 | | `Map` | `Map` | 保持一致 | | Caffeine Cache | LRUCache (已有) | 已有实现 | | `Optional` | `T \| null` | 空值处理 | | `record` | `interface` | 不可变用 readonly | | `switch` 表达式 | `switch` 语句 | 无表达式形式 | ### 4.4 交叉验证策略 每个算法移植后,使用 Java 端现有测试用例生成黄金数据集: 1. 从 Java 测试用例中提取输入/输出对 2. 在 TypeScript 中用相同输入执行 3. 比对输出,允许浮点误差 < 0.001 4. 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(key: string): T | null` - `set(key: string, value: T): void` - `remove(key: string): void` - `clear(): void` - `enableCloudSync(): void` (后续版本:iCloud/Google Drive) - `syncToCloud(): Promise` (后续版本) - `syncFromCloud(): Promise` (后续版本) 第一版仅实现纯本地存储,云同步功能在后续版本中添加。 ## 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.java` - `DailyFortuneTest.java` (334行) - `AlmanacSearchHandlerTest.java` (490行) ### 7.3 质量门禁 | 指标 | 标准 | |------|------| | 算法层单元测试覆盖率 | >= 90% | | 服务层单元测试覆盖率 | >= 80% | | 交叉验证通过率 | 100% | | E2E 关键路径通过率 | 100% | | Lint 错误 | 0 | | TypeScript 严格模式 | 开启 | ## 8. CI/CD (Jenkins) ```groovy 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 | | 越狱盗版 | 低 | 可接受风险,商店内购保护 |