diff --git a/.cursor/skills/kbone-miniprogram/README.md b/.cursor/skills/kbone-miniprogram/README.md index c8927a0a..9ab95464 100644 --- a/.cursor/skills/kbone-miniprogram/README.md +++ b/.cursor/skills/kbone-miniprogram/README.md @@ -22,11 +22,18 @@ - 开发流程和最佳实践 - 快速检查清单 +### reference.md +Next → 小程序转化参考(详细步骤),包含: +- 架构与 newpp 配置、适配层、功能控制一致 +- 底部菜单必须用自定义组件(不要用原生 tabBar) +- UI 来源策略、样式兼容、**安全区与标题/胶囊避让** +- 构建与合并流程、检查清单 + ### troubleshooting.md 详细的故障排查指南,包含: -- 编译问题(chunk 文件、Babel、依赖) +- 从 Next 迁移要点、编译问题(chunk 文件、Babel、依赖) - 运行时问题(URLSearchParams、localStorage、window/document) -- 样式问题(Grid、盒模型、Flexbox) +- 样式问题(Grid、盒模型、**标题/头部被胶囊或电池栏遮挡**、Flexbox) - 路由问题(导航、switchTab、动态路由) - 网络问题(API 请求、跨域) - 性能问题(加载慢、卡顿) @@ -46,9 +53,10 @@ Agent 应该在以下情况下自动应用此技能: - 需要配置 `webpack.mp.config.js` 2. **代码转换** - - 将 React Web 应用转换为小程序 + - 将 React Web 应用转换为小程序(含 Next 项目转化) - 需要创建跨平台适配层 - 处理 Web 和小程序的 API 差异 + - 底部菜单保留自定义组件(不要用原生 tabBar)、安全区与标题避让 3. **问题排查** - 编译错误(chunk 文件、Webpack 配置) @@ -129,10 +137,14 @@ function isMiniProgram() { | 问题 | 文档位置 | |------|---------| +| redirect 跳转异常(用了 home) | SKILL.md > 必记坑点 1 / troubleshooting.md > 配置问题 1 | +| Babel 报错(?. / ??) | SKILL.md > 必记坑点 2 / troubleshooting.md > 编译问题 2 | | chunk 文件缺失 | SKILL.md > 问题 2 | | URLSearchParams 错误 | SKILL.md > 问题 3 / troubleshooting.md > 运行时问题 1 | | CSS Grid 不生效 | SKILL.md > 问题 1 / troubleshooting.md > 样式问题 1 | -| 底部导航动态显示 | SKILL.md > 问题 4 | +| 底部菜单/导航(不要用原生 tabBar) | SKILL.md > 问题 4 / reference.md > 4.5 | +| 安全区/标题被胶囊或电池栏遮挡 | reference.md > 第 7 节 / troubleshooting.md > 样式问题 4 | +| 阅读页上下章/数据源 | SKILL.md > 必记坑点 3、4 | | 页面跳转失败 | troubleshooting.md > 路由问题 1 | | API 请求失败 | troubleshooting.md > 网络问题 1 | diff --git a/.cursor/skills/kbone-miniprogram/SKILL.md b/.cursor/skills/kbone-miniprogram/SKILL.md index 1160a06b..772a9cea 100644 --- a/.cursor/skills/kbone-miniprogram/SKILL.md +++ b/.cursor/skills/kbone-miniprogram/SKILL.md @@ -37,7 +37,7 @@ Kbone 是腾讯提供的 Web 与小程序同构解决方案,允许使用 React 2. **适配层(必须)** - `adapters/env.js`:`isMiniProgram()`(`typeof wx !== 'undefined' && wx.getSystemInfoSync`)。 - - `adapters/request.js`:Web 用 `fetch`,小程序用 `wx.request`,统一返回 Promise。 + - `adapters/request.js`:Web 用 `fetch`(相对路径同源);小程序用 `wx.request`,**必须带完整 baseUrl**。本项目线上 API 域名为 **`https://soul.quwanzhi.com`**(见开发文档 `开发文档/8、部署/当前项目部署到线上.md`)。转化时:小程序侧 `request(url)` 实际请求 `baseUrl + url`,`baseUrl` 来自 `getApp().globalData.baseUrl`,壳的 `app.js` 的 `onLaunch` 前应设置 `globalData.baseUrl = 'https://soul.quwanzhi.com'`(或从配置读),**不要写死为 your-domain.com**。 - `adapters/storage.js`:Web 用 `localStorage`,小程序用 `wx.getStorageSync`/`setStorageSync`。 - `adapters/router.js`:Web 用 `window.location` 或 Next `router`,小程序用 `wx.navigateTo`/`wx.reLaunch`;路径转小程序页面路径 `toMpPath(path)`。 - **功能控制一致**:与 Next 端相同,用同一套 API(如 `/api/db/config`)和条件渲染(如 `features.matchEnabled` 控制「找伙伴」入口),不写死开关。 @@ -48,21 +48,26 @@ Kbone 是腾讯提供的 Web 与小程序同构解决方案,允许使用 React 4. **miniprogram.config.js 要点** - `router`:每个页面单独 key,例如 `index`、`chapters`、`read`、`my`、`match`,对应 `entry` 与小程序页面路径。 - - 动态底部导航:不配置原生 `tabBar`,在 `appExtraConfig` 中不写 `tabBar`;底部栏用 React 组件 + `wx.reLaunch` 跳转。 + - **底部菜单(重要)**:Web 端多为**自定义底部菜单组件**,有显隐逻辑(如某页不显示、根据 API 动态显隐某项),原生 tabBar 丑且可操作性差。转化时**不要**改为小程序原生 tabBar,应保留「主页面引入统一菜单组件」的方式:在 `appExtraConfig` 中**不配置** `tabBar`,各主页面(首页、目录、我的、找伙伴等)继续引入同一底部菜单组件,由组件控制显隐、样式与跳转(小程序内用 `wx.reLaunch`),与 Web 行为一致。 5. **样式兼容(与 Next 视觉一致)** - Grid → Flex(含 `boxSizing: 'border-box'`、必要时 `lineHeight`)。 - `backdrop-filter` / `position: sticky` 等不支持则用占位或纯色/渐变替代,保证布局不错乱。 - 单位:小程序侧可用 rpx,与 Web 的 rem/px 按设计稿做一次换算或共用同一套换算规则。 -6. **构建与合并** +6. **安全区与标题避让(必须)** + - **顶部/电池栏**:使用 **`navBarHeight`**(状态栏 + 胶囊区域总高),不用固定 `statusBarHeight + 44`。在壳的 `app.js` 的 `onLaunch` 里用 `wx.getSystemInfoSync()` + `wx.getMenuButtonBoundingClientRect()` 计算并写入 `globalData.navBarHeight`、`globalData.statusBarHeight`;无菜单按钮时回退 `statusBarHeight + 44`。每页顶部占位条高度设为 `navBarHeight`,内容区 `padding-top` 用 `statusBarHeight`。 + - **底部安全区**:底部导航/固定底栏必须加 `padding-bottom: env(safe-area-inset-bottom)`,避免在有底部刘海的设备上被遮挡。 + - **标题右侧防遮挡**:小程序右上角胶囊会覆盖标题/按钮。所有带标题或右侧按钮的头部容器必须**右侧留白**:用 `globalData.capsulePaddingRight` 内联 `padding-right`,或在全局样式中定义 `.safe-header-right { padding-right: 200rpx; box-sizing: border-box; }`,避免标题、返回按钮与胶囊重叠或被遮挡。若出现标题被挡,优先检查是否加了该留白。 + +7. **构建与合并** - 在 newpp 执行 `NODE_ENV=production npm run build:mp`,将 `dist/mp/common/` 及 mp-plugin 生成的页面目录合并到 `miniprogram/`。 - 合并时保留 miniprogram 壳的 `app.js` 全局数据与生命周期,只覆盖/新增 Kbone 生成的页面与 common 资源。 ### 与 Kbone 规则的关系 - **router**:遵循本技能「核心配置规范」——每页单独配置、不用 `other`。 -- **底部导航**:遵循「问题 4:底部导航动态显示」——不配置原生 tabBar,用自定义组件 + `wx.reLaunch`。 +- **底部菜单**:遵循「问题 4:底部导航动态显示」——**不要用原生 tabBar**;保留 Web 的自定义底部菜单组件,主页面统一引入该组件,显隐与样式逻辑与 Web 一致,跳转用 `wx.reLaunch`。 - **API/兼容**:遵循「跨平台适配层」与「问题 3:URLSearchParams」——全部走适配层,避免 Web 独有 API。 - **样式**:遵循「问题 1:样式错位」与 troubleshooting 中的 Grid/Flex、box-sizing、lineHeight 等。 @@ -78,7 +83,7 @@ Kbone 是腾讯提供的 Web 与小程序同构解决方案,允许使用 React ```javascript module.exports = { - origin: 'https://your-domain.com', + origin: 'https://soul.quwanzhi.com', // 本项目线上域名,见开发文档 8、部署 entry: '/', // ✅ 正确:每个页面单独配置 @@ -95,6 +100,12 @@ module.exports = { // other: ['/chapters', '/read/:id', ...], // }, + // ✅ redirect 必须用 router 里存在的页面名(如 index),不能写不存在的 'home' + redirect: { + notFound: 'index', + accessDenied: 'index', + }, + // 全局配置 global: { rem: true, // 支持 rem 单位 @@ -182,6 +193,15 @@ module.exports = { --- +## 必记坑点(项目实践) + +1. **redirect 必须用 router 里存在的页面名**:`notFound` / `accessDenied` 填 router 的 key(如 `index`),不要填不存在的 `home`。 +2. **Babel 6 不支持 ?. 和 ??**:官方 React 模板是 Babel 6 + stage-3,用 `(x && x.y)` 替代 `x?.y`,用 `x != null ? x : default` 替代 `x ?? default`,否则 build:mp 报 `Unexpected token`。 +3. **阅读页内容与上下章用同一数据源**:用 `useChapterContent` + `useChapters` 的 getNextSection/getPrevSection,不要混用静态 bookData 与 API。 +4. **useChapters 需暴露 getNextSection / getPrevSection**:有阅读页且 API 驱动时,供上一章/下一章使用。 + +--- + ## 常见问题解决 ### 问题 1:样式错位 @@ -270,27 +290,30 @@ const queryString = buildQueryString({ key: 'value', page: 1 }) --- -### 问题 4:底部导航动态显示 +### 问题 4:底部导航动态显示(必须用自定义组件,不要用原生 tabBar) -**场景**:需要根据 API 配置动态显示/隐藏某些导航项 +**背景**:Web 端通常用**自定义底部菜单组件**,主页面统一引入,有显隐逻辑(如某路由不显示菜单、根据 API 动态显示/隐藏「找伙伴」等项);原生 tabBar 样式丑、可操作性差,且无法灵活控制显隐。 -**方案**:使用完全自定义的导航组件,不配置原生 tabBar +**要求**:转化时**不要**把 Web 的自定义底部菜单改成小程序原生 `tabBar`,应保留「统一菜单组件」方式。 + +**方案**: +- 在 `appExtraConfig` 中**不配置** `tabBar`。 +- 各主页面(首页、目录、我的、找伙伴等)继续引入**同一底部菜单组件**(如 BottomNav),由该组件负责:显隐(与 Web 一致,如文档/阅读页不显示)、菜单项动态显隐(如根据 `matchEnabled` 显示/隐藏「找伙伴」)、样式与跳转。 +- 跳转使用 `wx.reLaunch`(因未配置原生 tabBar,不能用 `wx.switchTab`)。 ```javascript // miniprogram.config.js appExtraConfig: { sitemapLocation: 'sitemap.json', - // ✅ 不配置 tabBar,使用完全自定义的导航组件 - // 原因:需要根据 API 配置动态显示/隐藏功能 + // ✅ 不配置 tabBar,保留 Web 的自定义底部菜单组件 + // 原因:显隐逻辑、样式与可操作性需与 Web 一致 }, ``` ```javascript -// router adapter +// router adapter(底部菜单点击时) export function switchTab(path) { if (isMiniProgram()) { - // ✅ 使用 wx.reLaunch 代替 wx.switchTab - // 原因:没有配置原生 tabBar wx.reLaunch({ url: toMpPath(path) }) } else { window.location.href = path === '/' ? 'index.html' : path.replace(/^\//, '') + '.html' @@ -321,12 +344,14 @@ export function navigateTo(path) { } } -// adapters/request.js +// adapters/request.js(小程序侧必须用完整 URL,baseUrl 见 globalData) export function request(url, options) { if (isMiniProgram()) { + const baseUrl = (typeof getApp === 'function' && getApp().globalData?.baseUrl) || 'https://soul.quwanzhi.com' + const fullUrl = url.startsWith('http') ? url : baseUrl + url return new Promise((resolve, reject) => { wx.request({ - url, + url: fullUrl, method: options.method || 'GET', data: options.body, success: res => resolve(res.data), @@ -464,13 +489,13 @@ appExtraConfig: { } ``` -**动态导航**:使用自定义组件 +**动态导航 / Web 自定义底部菜单**:必须用自定义组件,不要用原生 tabBar ```javascript appExtraConfig: { // 不配置 tabBar } -// 使用 React 组件实现导航 -// 使用 wx.reLaunch 进行跳转 +// Web 端多为统一底部菜单组件,主页面引入;转化时保留该方式: +// 各主页面引入同一 BottomNav 等组件,显隐/样式与 Web 一致,跳转用 wx.reLaunch ``` --- @@ -480,6 +505,7 @@ appExtraConfig: { ### 配置检查 - [ ] router 每个页面单独配置 +- [ ] **redirect.notFound / accessDenied 使用 router 中存在的页面名(如 index)** - [ ] pages 配置了所有页面标题 - [ ] global 启用了 rem 和 pageStyle - [ ] webpack mode 根据环境判断 @@ -489,6 +515,7 @@ appExtraConfig: { - [ ] 所有 CSS Grid 替换为 Flexbox - [ ] 添加了 boxSizing: 'border-box' +- [ ] **没有使用可选链 ?. 和空值合并 ??(Babel 6 不支持)** - [ ] 没有使用 URLSearchParams - [ ] 没有使用其他 Web 独有 API diff --git a/.cursor/skills/kbone-miniprogram/reference.md b/.cursor/skills/kbone-miniprogram/reference.md index 8822eb38..1d7dbd08 100644 --- a/.cursor/skills/kbone-miniprogram/reference.md +++ b/.cursor/skills/kbone-miniprogram/reference.md @@ -21,7 +21,8 @@ ### 2.1 miniprogram.config.js - `router`:每个页面单独 key,对应 Next 路由,**不要使用 `other` 数组**。 -- 动态底部导航:`appExtraConfig` 中**不配置** `tabBar`,用自定义 React 组件 + `wx.reLaunch`。 +- **`redirect`**:`notFound`、`accessDenied` 必须填 **router 里存在的页面名**(如 `index`),不要填不存在的 `home`。 +- **底部菜单**:`appExtraConfig` 中**不配置** `tabBar`。Web 端多为自定义底部菜单组件(主页面统一引入、有显隐逻辑),转化时**不要**改为小程序原生 tabBar,保留「统一菜单组件」+ `wx.reLaunch` 跳转。 - `global`:建议 `rem: true`、`pageStyle: true`。 - `pages`:为每个页面配置 `extra.navigationBarTitleText`。 @@ -56,12 +57,18 @@ appExtraConfig: { | 文件 | 职责 | |------|------| | `adapters/env.js` | `isMiniProgram()`:`typeof wx !== 'undefined' && wx.getSystemInfoSync` | -| `adapters/request.js` | Web:`fetch`;小程序:`wx.request`,统一返回 Promise | +| `adapters/request.js` | Web:`fetch`(相对路径);小程序:`wx.request`,**必须带完整 baseUrl**,本项目线上域名为 `https://soul.quwanzhi.com`(见开发文档 8、部署) | | `adapters/storage.js` | Web:`localStorage`;小程序:`wx.getStorageSync`/`setStorageSync` | | `adapters/router.js` | Web:`window.location` 或 Next Router;小程序:`wx.navigateTo`/`wx.reLaunch`,路径用 `toMpPath(path)` 转成小程序页面路径 | 业务代码**只**通过适配层访问请求、存储、路由,不直接使用 `window`、`document`、`localStorage`、`URLSearchParams` 等。 +**请求基地址(转化时必须处理)**:小程序端不能使用相对路径,需用完整 URL。本项目线上 API 域名为 **`https://soul.quwanzhi.com`**,见 `开发文档/8、部署/当前项目部署到线上.md`。转化时: + +- 在**壳**的 `miniprogram/app.js` 的 `globalData` 中设置 `baseUrl: 'https://soul.quwanzhi.com'`(或从环境/配置读取)。 +- 在 **adapters/request.js** 中,小程序分支:`url` 若不以 `http` 开头则拼上 `getApp().globalData.baseUrl`,再调用 `wx.request`。 +- 不要写死为 `your-domain.com` 或其它占位域名。 + --- ## 4. 功能控制一致 @@ -74,6 +81,18 @@ appExtraConfig: { --- +## 4.5 底部菜单:必须用自定义组件,不要用原生 tabBar + +- **原因**:Web 端底部菜单多为**自定义组件**(如 `BottomNav`),主页面统一引入,有「某页不显示菜单」「根据 API 显隐某项」等逻辑;原生 tabBar 样式与可操作性差,且无法等价实现上述逻辑。 +- **要求**:转化时**不要**把自定义底部菜单改成小程序原生 `tabBar`。 +- **做法**: + - `appExtraConfig` 中不配置 `tabBar`。 + - 各主页面(首页、目录、我的、找伙伴等)**继续引入同一底部菜单组件**,由该组件控制:是否在本页显示、各菜单项显隐(如 `matchEnabled` 控制「找伙伴」)、样式、点击跳转(小程序内用 `wx.reLaunch`)。 + - 与 Web 一致:阅读页、文档页、关于页等可不渲染该组件或由布局隐藏。 +- **检查**:若发现被改成了原生 tabBar,应回退为「主页面引入统一菜单组件」的方式。 + +--- + ## 5. UI 来源策略 - **复制适配**:从 Next 的 `app/**/page.tsx`、`components/**` 复制到 newpp,改为 JSX,用适配层替代 `Link`/`useRouter`/`usePathname`/`fetch`。 @@ -91,7 +110,40 @@ appExtraConfig: { --- -## 7. 构建与合并流程 +## 7. 安全区与标题/胶囊避让(必须) + +### 7.1 电池栏/顶部安全区 + +- **问题**:使用自定义导航栏(`navigationStyle: 'custom'`)时,状态栏(电池、时间)会与页面顶部重叠,若不做占位,标题会被挡。 +- **做法**: + - 在**壳**的 `app.js` 的 `onLaunch` 中**同步**获取系统信息并计算占位高度,写入 `globalData`: + - `statusBarHeight`:`wx.getSystemInfoSync().statusBarHeight || 44` + - `navBarHeight`:用 `wx.getMenuButtonBoundingClientRect()` 计算「状态栏 + 胶囊区域」总高,公式:`menuButton.bottom + menuButton.top - systemInfo.statusBarHeight`;无菜单按钮时回退 `statusBarHeight + 44` + - `capsulePaddingRight`:`systemInfo.windowWidth - menuButton.left + 10`,供标题右侧留白使用 + - 每个页面的**顶部占位条**高度设为 `navBarHeight`(px);占位条内部若需区分状态栏与导航内容,可用 `padding-top: {{ statusBarHeight || 44 }}px`。 + - 页面 `onLoad`/`onShow` 时从 `getApp().globalData` 取 `navBarHeight`、`statusBarHeight` 写入页面 `data`,供 WXML 内联样式使用。 + +### 7.2 底部安全区 + +- **问题**:有底部刘海的设备上,固定底栏(如 TabBar、底部导航)会贴边,内容被遮挡。 +- **做法**:底部导航容器加 `padding-bottom: env(safe-area-inset-bottom)`(WXSS 或内联均可),无需额外 JS。 + +### 7.3 标题右侧不被胶囊遮挡 + +- **问题**:小程序右上角有胶囊按钮(…、首页),若标题或返回按钮延伸到右侧,会被遮挡或误触。 +- **做法**: + - 所有带标题/返回/右侧按钮的**头部容器**必须预留右侧空白: + - **方式 A**:全局样式 `.safe-header-right { padding-right: 200rpx; box-sizing: border-box; }`,头部容器加该类。 + - **方式 B**:内联 `style="padding-right: {{ capsulePaddingRight }}px"`,`capsulePaddingRight` 来自 `getApp().globalData.capsulePaddingRight`(在 onLaunch 中已计算)。 + - 若出现「标题或按钮被挡」,优先检查该头部是否加了上述留白,并确认 `app.js` 中已正确写入 `capsulePaddingRight`。 + +### 7.4 统一占位模板(可选) + +- 无复杂导航的页面(如设置、关于、推广、购买记录等)建议使用**同一套**顶部安全区:占位条高度 `navBarHeight`,其内 `padding-top: statusBarHeight`,导航容器 `display: flex; flex-direction: column; justify-content: flex-end; box-sizing: border-box;`,并加 `.safe-header-right` 或 `capsulePaddingRight`,保证标题与返回按钮不被遮挡且右侧留白一致。 + +--- + +## 8. 构建与合并流程 1. 在 newpp 执行:`NODE_ENV=production npm run build:mp`。 2. 将 `newpp/dist/mp/` 下生成的页面目录及 `common/` 复制/合并到 `miniprogram/`。 @@ -100,11 +152,12 @@ appExtraConfig: { --- -## 8. 检查清单 +## 9. 检查清单 -- [ ] miniprogram.config.js:每页单独 router,无 `other`;未配置原生 tabBar。 +- [ ] miniprogram.config.js:每页单独 router,无 `other`;**未配置原生 tabBar**,底部菜单沿用 Web 的自定义组件(主页面统一引入,显隐与跳转逻辑一致)。 - [ ] webpack.mp.config.js:每页有 entry;isOptimize 按 NODE_ENV;中小型项目 splitChunks 为 false。 - [ ] 适配层:env、request、storage、router 已实现并在业务中统一使用。 - [ ] 功能开关与 Next 一致,来自同一 API。 - [ ] 样式:无 Grid,Flex 已加 boxSizing/lineHeight;不支持特性已替代。 +- [ ] **安全区**:app.js 的 onLaunch 中已计算并写入 `navBarHeight`、`statusBarHeight`、`capsulePaddingRight`;每页顶部占位用 `navBarHeight`;底部导航有 `padding-bottom: env(safe-area-inset-bottom)`;带标题的头部有 `.safe-header-right` 或 `capsulePaddingRight` 留白,标题/按钮未被胶囊遮挡。 - [ ] 合并后 app.js 未被错误覆盖,页面路径与 app.json 一致。 diff --git a/.cursor/skills/kbone-miniprogram/troubleshooting.md b/.cursor/skills/kbone-miniprogram/troubleshooting.md index 78ebb615..2ddc01b6 100644 --- a/.cursor/skills/kbone-miniprogram/troubleshooting.md +++ b/.cursor/skills/kbone-miniprogram/troubleshooting.md @@ -8,15 +8,66 @@ - 以 **newpp** 为 Kbone 构建源,**miniprogram** 为壳,构建后合并产物。 - 必须做 **适配层**:`env`、`request`、`storage`、`router`;功能开关与 Next 一致,用同一 API(如 `/api/db/config` 的 `features.matchEnabled`)。 - **UI**:在 newpp 内复制并适配 Next 的页面/组件,或通过 webpack alias 引用根目录共享组件(无 Next 专属 API)。 -- **配置**:`miniprogram.config.js` 每页单独 router、不配原生 tabBar;`webpack.mp.config.js` 中 `isOptimize = process.env.NODE_ENV === 'production'`,中小型项目建议 `splitChunks: false`。 +- **配置**:`miniprogram.config.js` 每页单独 router、**不配原生 tabBar**;`webpack.mp.config.js` 中 `isOptimize = process.env.NODE_ENV === 'production'`,中小型项目建议 `splitChunks: false`。 +- **底部菜单**:Web 端多为自定义底部菜单组件(主页面统一引入、有显隐逻辑),**不要**转为小程序原生 tabBar;保留「主页面引入统一菜单组件」,显隐与跳转与 Web 一致,跳转用 `wx.reLaunch`。 - **样式**:Grid 改 Flex,补 `boxSizing`/`lineHeight`;不支持特性用兼容写法或替代。 -遇到具体报错时,在下方「编译问题」「运行时问题」「样式问题」中按类型排查。 +遇到具体报错时,在下方「配置问题」「编译问题」「运行时问题」「样式问题」中按类型排查。 + +--- + +## 配置问题 + +### 1. redirect 用了不存在的页面名 + +**现象**:配置了 `redirect.notFound: 'home'`、`redirect.accessDenied: 'home'`,但 router 里没有名为 `home` 的页面。 + +**后果**:404 或无权时,Kbone 可能无法正确跳转到首页。 + +**解决**:redirect 必须使用 **router 里存在的 key**。首页通常是 `index`,不要写 `home`。 + +```javascript +// ❌ 错误 +redirect: { notFound: 'home', accessDenied: 'home' } + +// ✅ 正确 +redirect: { notFound: 'index', accessDenied: 'index' } +``` --- ## 编译问题 +### 0. Node 17+ OpenSSL 错误(ERR_OSSL_EVP_UNSUPPORTED) + +**错误信息**: +``` +Error: error:0308010C:digital envelope routines::unsupported + code: 'ERR_OSSL_EVP_UNSUPPORTED' +``` + +**原因**:Node.js 17+ 使用 OpenSSL 3.0,旧版 webpack(如 4.x)依赖的 MD4 等算法被移出默认提供,导致构建时报错。 + +**解决方案**: + +**方案 1:在 newpp 的 package.json 脚本中加 NODE_OPTIONS**(推荐) +```json +"scripts": { + "web": "cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=development webpack-dev-server ...", + "mp": "rimraf dist/mp/common && cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=development webpack ...", + "build:mp": "rimraf dist/mp/common && cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production webpack ..." +} +``` + +**方案 2:当前终端临时设置后再运行** +- Windows PowerShell:`$env:NODE_OPTIONS="--openssl-legacy-provider"; cd newpp; npm run web` +- Windows CMD:`set NODE_OPTIONS=--openssl-legacy-provider && cd newpp && npm run web` +- Linux/macOS:`NODE_OPTIONS=--openssl-legacy-provider npm run web` + +**方案 3**:使用 Node.js 16.x(LTS)运行 newpp 构建,避免 OpenSSL 3.0。 + +--- + ### 1. chunk 文件缺失错误 **错误信息**: @@ -74,15 +125,28 @@ optimization: { ``` SyntaxError: Unexpected token ... ``` +或具体到某列:`Unexpected token (45:64)`(多为可选链位置) **原因**: - Babel 配置不正确 -- 使用了小程序不支持的 ES6+ 语法 +- 使用了 Babel 6(stage-3)不支持的语法:**可选链 `?.`、空值合并 `??`**(属 ES2020) +- 其他小程序不支持的 ES6+ 语法 **解决方案**: +**若为可选链 / 空值合并**(最常见): +```javascript +// ❌ Babel 6 会报错 +res.content?.length +x ?? 'default' + +// ✅ 兼容写法 +(res.content && res.content.length) || 0 +x != null ? x : 'default' +``` + +**Babel 配置**(.babelrc 或 babel.config.js): ```javascript -// .babelrc 或 babel.config.js { "presets": [ ["env", { @@ -377,7 +441,26 @@ const styles = { --- -### 4. Flexbox 间距问题 +### 4. 标题/头部被胶囊或电池栏遮挡 + +**问题描述**:自定义导航栏时,标题、返回按钮被右上角胶囊或顶部状态栏遮挡。 + +**原因**:未预留顶部安全区高度和右侧胶囊留白。 + +**解决方案**: + +1. **顶部安全区**:在 `app.js` 的 `onLaunch` 中计算并写入 `globalData`: + - `statusBarHeight = wx.getSystemInfoSync().statusBarHeight || 44` + - `navBarHeight`:用 `wx.getMenuButtonBoundingClientRect()` 计算 `menuButton.bottom + menuButton.top - statusBarHeight`,无菜单时用 `statusBarHeight + 44` + - `capsulePaddingRight = systemInfo.windowWidth - menuButton.left + 10` +2. **页面占位**:顶部占位条高度设为 `{{ navBarHeight }}px`,内容区 `padding-top: {{ statusBarHeight }}px`;页面 `onLoad`/`onShow` 从 `getApp().globalData` 取上述值写入 `data`。 +3. **标题右侧留白**:头部容器加类 `.safe-header-right { padding-right: 200rpx; box-sizing: border-box; }`,或内联 `padding-right: {{ capsulePaddingRight }}px`,避免标题与胶囊重叠。 + +详见本目录 `reference.md` 第 7 节「安全区与标题/胶囊避让」。 + +--- + +### 5. Flexbox 间距问题 **问题描述**:Flexbox 子元素间距不均匀 @@ -528,7 +611,7 @@ request:fail url not in domain list ```javascript // miniprogram.config.js module.exports = { - origin: 'https://your-domain.com', // 使用已配置的域名 + origin: 'https://soul.quwanzhi.com', // 本项目线上域名,见开发文档 8、部署 } ``` @@ -563,7 +646,7 @@ devServer: { ```javascript // Express 示例 app.use(cors({ - origin: ['http://localhost:8080', 'https://your-domain.com'], + origin: ['http://localhost:8080', 'https://soul.quwanzhi.com'], credentials: true, })) ``` diff --git a/README-API接入完成.md b/README-API接入完成.md deleted file mode 100644 index c7a8484a..00000000 --- a/README-API接入完成.md +++ /dev/null @@ -1,392 +0,0 @@ -# API 接入完成报告 - -## 📋 修复概览 - -**修复时间**:2026-02-03 -**问题**: -1. URLSearchParams 在小程序环境不支持 -2. Webpack chunk 文件命名导致文件缺失 - -**状态**:✅ 已完成 - ---- - -## 🐛 问题详情 - -### 问题 1:URLSearchParams 不支持 - -**错误信息**: -``` -ReferenceError: URLSearchParams is not defined -``` - -**原因**: -- 小程序环境不支持 Web API `URLSearchParams` -- 代码中使用了 `new URLSearchParams()` 来构建查询字符串 - -**影响**: -- 无法从 API 加载数据 -- 页面显示"加载失败" - -### 问题 2:Webpack Chunk 文件缺失 - -**错误信息**: -``` -Error: ENOENT: no such file or directory, -open 'E:/Gongsi/Mycontent/newpp/dist/mp/common/default~chapters~index~my~read~search.js' -``` - -**原因**: -- Webpack `splitChunks` 配置中 `name: true` 导致自动生成 chunk 名称 -- 某些 chunk 在特定情况下不会生成,但代码引用了它们 - -**影响**: -- 微信开发者工具编译失败 -- 页面无法加载 - ---- - -## ✅ 解决方案 - -### 修复 1:自定义 buildQueryString 函数 - -**文件**:`newpp/src/api/index.js` - -#### Before(使用 URLSearchParams) - -```javascript -export async function getChapters(params = {}) { - const { partId, status = 'published', page = 1, pageSize = 100 } = params - const query = new URLSearchParams({ status, page: String(page), pageSize: String(pageSize) }) - if (partId) query.append('partId', partId) - - const res = await request(`/api/book/chapters?${query.toString()}`) - return res -} -``` - -#### After(自定义函数) - -```javascript -/** - * 构建查询字符串(兼容小程序) - * @param {object} params - 参数对象 - */ -function buildQueryString(params) { - const parts = [] - for (const [key, value] of Object.entries(params)) { - if (value !== undefined && value !== null) { - parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`) - } - } - return parts.join('&') -} - -export async function getChapters(params = {}) { - const { partId, status = 'published', page = 1, pageSize = 100 } = params - const queryParams = { status, page: String(page), pageSize: String(pageSize) } - if (partId) queryParams.partId = partId - - const query = buildQueryString(queryParams) - const res = await request(`/api/book/chapters?${query}`) - return res -} -``` - -**关键改动**: -1. ✅ 自定义 `buildQueryString` 函数 -2. ✅ 使用 `Object.entries()` 遍历参数 -3. ✅ 手动拼接查询字符串 -4. ✅ 兼容小程序和 Web 环境 - ---- - -### 修复 2:固定 Webpack Chunk 名称 - -**文件**:`newpp/build/webpack.mp.config.js` - -#### Before(自动命名) - -```javascript -optimization: { - runtimeChunk: false, - splitChunks: { - chunks: 'all', - minSize: 1000, - maxSize: 0, - minChunks: 1, - maxAsyncRequests: 100, - maxInitialRequests: 100, - automaticNameDelimiter: '~', - name: true, // ❌ 自动生成名称 - cacheGroups: { - vendors: { - test: /[\\/]node_modules[\\/]/, - priority: -10, - }, - default: { - minChunks: 2, - priority: -20, - reuseExistingChunk: true, - }, - }, - }, -} -``` - -#### After(固定名称) - -```javascript -optimization: { - runtimeChunk: false, - splitChunks: { - chunks: 'all', - minSize: 1000, - maxSize: 0, - minChunks: 1, - maxAsyncRequests: 100, - maxInitialRequests: 100, - automaticNameDelimiter: '~', - name: false, // ✅ 禁用自动命名 - cacheGroups: { - vendors: { - test: /[\\/]node_modules[\\/]/, - priority: -10, - name: 'vendors', // ✅ 固定名称 - }, - default: { - minChunks: 2, - priority: -20, - reuseExistingChunk: true, - name: 'common', // ✅ 固定名称 - }, - }, - }, -} -``` - -**关键改动**: -1. ✅ `name: true` → `name: false` -2. ✅ `vendors` 添加 `name: 'vendors'` -3. ✅ `default` 添加 `name: 'common'` - -**效果**: -- 生成固定的 chunk 文件:`vendors.js`、`common.js` -- 避免生成动态名称的 chunk -- 确保所有引用的文件都存在 - ---- - -## 📊 修复前后对比 - -| 问题 | 修复前 | 修复后 | -|------|--------|--------| -| URLSearchParams | ❌ 小程序不支持 | ✅ 使用自定义函数 | -| Chunk 文件命名 | ❌ 自动生成,可能缺失 | ✅ 固定名称,稳定 | -| API 数据加载 | ❌ 报错 | ✅ 正常加载 | -| 编译结果 | ❌ 失败 | ✅ 成功 | - ---- - -## 🎯 API 集成功能 - -### 已接入的 API - -| 功能 | API | 方法 | 状态 | -|------|-----|------|------| -| 章节列表 | `/api/book/chapters` | GET | ✅ | -| 章节详情 | `/api/book/chapter/[id]` | GET | ✅ | -| 用户信息 | `/api/user/profile` | GET/POST | ✅ | -| 系统配置 | `/api/db/config` | GET | ✅ | -| 找伙伴配置 | `/api/match/config` | GET | ✅ | -| 加入匹配池 | `/api/ckb/join` | POST | ✅ | -| 获取匹配用户 | `/api/match/users` | GET | ✅ | -| 推广数据 | `/api/referral/data` | GET | ✅ | -| 搜索章节 | `/api/search` | GET | ✅ | -| 创建订单 | `/api/payment/create-order` | POST | ✅ | -| 提现申请 | `/api/withdraw` | POST | ✅ | - -### 数据流程 - -``` -页面组件 - ↓ -useChapters Hook / useChapterContent Hook - ↓ -api/index.js (API 集成层) - ↓ -adapters/request.js (请求适配器) - ↓ -小程序: wx.request / Web: fetch - ↓ -后端 API -``` - -### 缓存策略 - -| 数据类型 | 缓存时长 | 存储位置 | -|---------|---------|---------| -| 章节列表 | 30 分钟 | wx.storage / localStorage | -| 章节内容 | 不缓存 | - | -| 用户信息 | 会话期间 | Zustand Store | - ---- - -## 🧪 测试清单 - -### 基础功能测试 - -- [x] 页面加载成功 -- [x] 不再报 URLSearchParams 错误 -- [x] 不再报文件缺失错误 -- [ ] 章节列表正常显示 -- [ ] 章节内容正常显示 -- [ ] 搜索功能正常 -- [ ] 缓存功能正常 - -### API 测试 - -- [ ] 章节列表 API 调用成功 -- [ ] 章节详情 API 调用成功 -- [ ] 用户信息 API 调用成功 -- [ ] 配置 API 调用成功 -- [ ] 错误处理正确 - -### 跨平台测试 - -- [ ] Web 环境正常 -- [ ] 小程序环境正常 -- [ ] 数据格式一致 - ---- - -## 📝 修改的文件 - -### 核心文件 - -1. **`newpp/src/api/index.js`** - - ✅ 添加 `buildQueryString` 函数 - - ✅ 修复 `getChapters` 函数 - - ✅ 修复 `getUserProfile` 函数 - -2. **`newpp/build/webpack.mp.config.js`** - - ✅ 修改 `splitChunks.name` 为 `false` - - ✅ 添加 `vendors` 固定名称 - - ✅ 添加 `common` 固定名称 - -### 页面文件(已更新) - -1. ✅ `newpp/src/pages/HomePage.jsx` - 使用 `useChapters` Hook -2. ⚠️ `newpp/src/pages/ChaptersPage.jsx` - 需要测试 -3. ⚠️ `newpp/src/pages/ReadPage.jsx` - 需要测试 -4. ⚠️ `newpp/src/pages/SearchPage.jsx` - 需要测试 - ---- - -## 📚 相关文档 - -1. [API 接入说明](./开发文档/8、部署/API接入说明.md) - 完整的 API 文档 -2. [自定义导航方案](./开发文档/8、部署/自定义导航组件方案.md) - 导航组件说明 -3. [小程序样式修复](./开发文档/8、部署/小程序样式修复说明.md) - 样式问题解决 - ---- - -## 🚀 下一步测试 - -### 1. 微信开发者工具测试 - -```bash -# 打开微信开发者工具 -# 导入 miniprogram/ 目录 -# 点击"编译" -``` - -**验证**: -- [ ] 编译成功,无错误 -- [ ] 首页正常显示 -- [ ] 章节列表正常显示 -- [ ] 点击章节可以查看内容 -- [ ] 搜索功能正常 - -### 2. 数据加载测试 - -**验证**: -- [ ] 首次加载从 API 获取数据 -- [ ] 第二次加载从缓存读取 -- [ ] Loading 状态正常显示 -- [ ] Error 状态正常显示 - -### 3. API 调用测试 - -**打开控制台,检查**: -- [ ] 网络请求正常(无 404) -- [ ] 返回数据格式正确 -- [ ] 数据渲染正常 - ---- - -## 🎯 核心改进 - -### 1. 小程序兼容性 - -**Before**: -- ❌ 使用 Web API `URLSearchParams` -- ❌ 小程序环境报错 - -**After**: -- ✅ 自定义 `buildQueryString` 函数 -- ✅ 完全兼容小程序和 Web - -### 2. Webpack 稳定性 - -**Before**: -- ❌ 自动生成 chunk 名称 -- ❌ 文件可能缺失 - -**After**: -- ✅ 固定 chunk 名称 -- ✅ 文件稳定存在 - -### 3. 代码质量 - -**改进**: -1. ✅ 更好的错误处理 -2. ✅ Loading 状态管理 -3. ✅ 缓存机制 -4. ✅ 数据转换逻辑 - ---- - -## ✅ 完成总结 - -### 核心成果 - -1. ✅ **修复 URLSearchParams 问题** - 自定义兼容函数 -2. ✅ **修复 Webpack Chunk 问题** - 固定文件名称 -3. ✅ **API 集成完成** - 11 个核心 API 接入 -4. ✅ **Hooks 创建完成** - useChapters、useChapterContent -5. ✅ **页面更新完成** - HomePage、ChaptersPage、ReadPage、SearchPage - -### 技术亮点 - -1. ✅ 跨平台兼容(小程序 + Web) -2. ✅ 数据缓存(30分钟有效期) -3. ✅ 错误处理(友好的错误提示) -4. ✅ Loading 状态(优化用户体验) -5. ✅ 代码分离(API 层、Hooks 层、页面层) - -### 待完成 - -1. ⏳ 微信开发者工具完整测试 -2. ⏳ 真机预览测试 -3. ⏳ API 性能优化 -4. ⏳ 更多页面接入 API(找伙伴、我的、推广等) - ---- - -**🎉 API 接入完成!现在可以在微信开发者工具中测试真实数据加载了。** - ---- - -**修复日期**:2026-02-03 -**文档版本**:v1.0 diff --git a/README-Kbone技能创建完成.md b/README-Kbone技能创建完成.md deleted file mode 100644 index b2cd380c..00000000 --- a/README-Kbone技能创建完成.md +++ /dev/null @@ -1,543 +0,0 @@ -# Kbone 技能创建完成报告 - -## 📋 创建概览 - -**创建时间**:2026-02-03 -**技能名称**:kbone-miniprogram -**技能路径**:`.cursor/skills/kbone-miniprogram/` -**状态**:✅ 已完成 - ---- - -## 🎯 技能用途 - -这个技能帮助 AI Agent 更好地处理使用 Kbone 框架将 React Web 应用转换为微信小程序的任务。 - -**触发场景**: -- 配置或优化 Kbone 项目 -- 解决小程序编译/运行时错误 -- 处理跨平台兼容性问题 -- Web 应用转小程序迁移 - ---- - -## 📁 文件结构 - -``` -.cursor/skills/kbone-miniprogram/ -├── SKILL.md # 主技能文档(核心配置、快速方案、最佳实践) -├── troubleshooting.md # 详细故障排查指南(50+ 常见问题) -└── README.md # 技能使用说明(使用指南、维护说明) -``` - ---- - -## 📝 文件内容 - -### 1. SKILL.md(主技能文档) - -**包含内容**: - -#### 核心配置规范 -- ✅ `miniprogram.config.js` 完整配置模板 - - router 配置(每个页面单独配置) - - global 配置(rem、pageStyle) - - pages 配置(navigationBarTitleText) - - app 配置(导航栏样式) - - optimization 配置(性能优化) - -- ✅ `webpack.mp.config.js` 完整配置模板 - - mode 和 isOptimize 环境判断 - - entry/output 配置 - - splitChunks 策略(中小型 vs 大型项目) - -#### 常见问题快速解决 -1. **样式错位** - Grid 改 Flexbox -2. **chunk 文件缺失** - 禁用代码分割 -3. **URLSearchParams 错误** - 自定义实现 -4. **底部导航动态显示** - 自定义组件方案 - -#### 跨平台适配层 -- 环境判断(`isMiniProgram()`) -- router 适配器(navigateTo、switchTab) -- request 适配器(wx.request vs fetch) -- storage 适配器(wx.storage vs localStorage) - -#### 开发流程 -- 初始化项目 -- 开发模式(Web + 小程序) -- 生产构建 -- 测试部署 - -#### 最佳实践 -- 配置规范 -- 代码分割策略 -- 样式约束 -- API 兼容性 -- 导航设计 - -#### 检查清单 -- [ ] 配置检查(router、pages、global、webpack) -- [ ] 兼容性检查(Grid、URLSearchParams、API) -- [ ] 构建检查(编译、运行) -- [ ] 功能检查(标题、导航、数据、样式) - ---- - -### 2. troubleshooting.md(详细排查指南) - -**包含内容**: - -#### 编译问题(3 个) -1. **chunk 文件缺失** - 方案 1(禁用)vs 方案 2(固定命名) -2. **Babel 编译错误** - .babelrc 配置 -3. **依赖包报错** - 检查、重装、resolve 配置 - -#### 运行时问题(4 个) -1. **URLSearchParams 未定义** - `buildQueryString` 实现 -2. **localStorage 未定义** - storage 适配器 -3. **window 对象未定义** - 环境判断和可选链 -4. **document 对象未定义** - React 特性 + wx API - -#### 样式问题(4 个) -1. **CSS Grid 不生效** - Flexbox 方案 -2. **盒模型计算错误** - `boxSizing: 'border-box'` -3. **文字垂直居中问题** - `lineHeight` 设置 -4. **Flexbox 间距问题** - 3 种解决方案 - -#### 路由问题(3 个) -1. **页面跳转无效** - router 配置、适配器、文件检查 -2. **switchTab 报错** - wx.reLaunch 方案 -3. **动态路由参数丢失** - 小程序 vs Web 获取方式 - -#### 网络问题(2 个) -1. **API 请求失败** - 域名白名单、开发调试、代理 -2. **跨域问题** - webpack proxy、后端 CORS - -#### 性能问题(2 个) -1. **首屏加载慢** - 包体积、代码压缩、代码分割 -2. **页面卡顿** - 虚拟列表、React.memo、useMemo - -#### 调试技巧 -- 查看小程序日志 -- 条件断点 -- 真机调试 - -#### 检查清单 -- [ ] 编译检查 -- [ ] 兼容性检查 -- [ ] 配置检查 -- [ ] 运行检查 - ---- - -### 3. README.md(使用说明) - -**包含内容**: - -#### 文件说明 -- SKILL.md - 核心配置和快速方案 -- troubleshooting.md - 详细排查指南 - -#### 技能使用指南 -- 何时使用此技能(4 类场景) -- 核心知识点(4 个要点) -- 快速参考表(问题速查、配置速查) - -#### 使用示例 -- 场景 1:配置新项目 -- 场景 2:修复编译错误 -- 场景 3:修复运行时错误 -- 场景 4:优化配置 - -#### 维护说明 -- 更新触发条件 -- 更新流程 - -#### 参考资源 -- 官方文档链接 -- 项目文档位置 - ---- - -## 🎯 技能特点 - -### 1. 结构清晰 - -``` -SKILL.md → 核心知识,快速查找 -troubleshooting.md → 详细方案,深度排查 -README.md → 使用指南,维护说明 -``` - -**符合 create-skill 最佳实践**: -- ✅ 主文档 < 500 行(SKILL.md 约 400 行) -- ✅ 渐进式披露(详细内容在 troubleshooting.md) -- ✅ 文件引用一层深度 - ---- - -### 2. 内容全面 - -**覆盖范围**: -- ✅ 配置规范(miniprogram.config.js + webpack.mp.config.js) -- ✅ 常见问题(18+ 问题和解决方案) -- ✅ 跨平台适配(4 个核心适配器) -- ✅ 开发流程(初始化到部署) -- ✅ 最佳实践(配置、代码、样式、性能) -- ✅ 检查清单(4 类检查项) -- ✅ 调试技巧(工具和方法) - ---- - -### 3. 实践导向 - -**基于真实项目经验**: -- ✅ 所有问题都是实际遇到的 -- ✅ 所有方案都经过验证 -- ✅ 包含具体的代码示例 -- ✅ 提供决策依据(中小型 vs 大型项目) - ---- - -### 4. 易于维护 - -**清晰的维护指南**: -- ✅ 何时更新(3 种触发条件) -- ✅ 如何更新(4 步流程) -- ✅ 在哪更新(文件对应关系) - ---- - -## 📊 技能对比 - -### Before(没有技能) - -Agent 处理 Kbone 问题时: -- ❌ 需要搜索官方文档 -- ❌ 可能配置不规范 -- ❌ 遇到问题缺少实践经验 -- ❌ 解决方案不稳定 - -### After(有技能) - -Agent 处理 Kbone 问题时: -- ✅ 直接应用经验和最佳实践 -- ✅ 配置完全符合官方规范 -- ✅ 快速定位和解决问题 -- ✅ 解决方案经过验证 - ---- - -## 🧪 技能验证 - -### 测试场景 1:配置新项目 - -**用户消息**: -> "帮我配置一个 kbone 项目,有首页、目录、阅读三个页面" - -**预期行为**: -1. ✅ 读取 SKILL.md -2. ✅ 创建规范的 `miniprogram.config.js` -3. ✅ 创建优化的 `webpack.mp.config.js` -4. ✅ 创建跨平台适配器 -5. ✅ 提供构建命令 - ---- - -### 测试场景 2:修复编译错误 - -**用户消息**: -> "编译报错:ENOENT: no such file or directory, open 'default~chapters.js'" - -**预期行为**: -1. ✅ 识别为 chunk 文件缺失问题 -2. ✅ 读取 SKILL.md > 问题 2 -3. ✅ 判断项目规模 -4. ✅ 修改 webpack 配置(禁用 splitChunks) -5. ✅ 重新构建并验证 - ---- - -### 测试场景 3:修复运行时错误 - -**用户消息**: -> "小程序报错:URLSearchParams is not defined" - -**预期行为**: -1. ✅ 识别为 API 兼容性问题 -2. ✅ 读取 SKILL.md > 问题 3 -3. ✅ 创建 `buildQueryString` 函数 -4. ✅ 替换所有使用 -5. ✅ 测试验证 - ---- - -### 测试场景 4:优化配置 - -**用户消息**: -> "根据 kbone 官方文档优化我的配置" - -**预期行为**: -1. ✅ 读取 SKILL.md > 核心配置规范 -2. ✅ 检查 router、pages、global -3. ✅ 检查 webpack mode 和 isOptimize -4. ✅ 优化不规范的配置 -5. ✅ 提供优化说明 - ---- - -## 📚 技能与项目文档的关系 - -### 项目文档(详细实践) - -位置:`开发文档/8、部署/` - -文档列表: -- Kbone配置优化说明.md -- 小程序样式修复说明.md -- 自定义导航组件方案.md -- API接入说明.md -- Webpack代码分割问题修复.md - -**特点**: -- ✅ 详细的问题分析 -- ✅ 完整的解决过程 -- ✅ 具体的代码变更 -- ✅ 优化前后对比 - ---- - -### 技能文档(提炼精华) - -位置:`.cursor/skills/kbone-miniprogram/` - -文档列表: -- SKILL.md -- troubleshooting.md -- README.md - -**特点**: -- ✅ 精炼的配置规范 -- ✅ 快速的解决方案 -- ✅ 通用的最佳实践 -- ✅ 易于查找和应用 - ---- - -### 关系说明 - -``` -项目文档(详细) - ↓ 提炼精华 -技能文档(精简) - ↓ Agent 应用 -快速解决问题 -``` - -**互补关系**: -- 项目文档:记录完整过程,供人类阅读 -- 技能文档:提炼核心知识,供 Agent 应用 - ---- - -## ✅ 符合 create-skill 规范检查 - -### 核心质量 ✅ - -- [x] Description 具体且包含关键词 -- [x] Description 包含 WHAT 和 WHEN -- [x] 使用第三人称描述 -- [x] SKILL.md < 500 行(约 400 行) -- [x] 术语一致(Kbone、小程序、配置) -- [x] 示例具体(代码示例、配置示例) - ---- - -### 结构 ✅ - -- [x] 文件引用一层深度(SKILL.md → troubleshooting.md) -- [x] 渐进式披露(核心在 SKILL.md,详细在 troubleshooting.md) -- [x] 工作流程清晰(开发流程 4 步) -- [x] 无时效性信息 - ---- - -### 内容 ✅ - -- [x] 简洁为主(挑战每个段落的必要性) -- [x] 假设 Agent 智能(只提供它不知道的) -- [x] 具体的触发条件(4 类场景) -- [x] 明确的检查清单(4 类检查) - ---- - -### 命名 ✅ - -- [x] 技能名称规范(`kbone-miniprogram`) -- [x] 描述性强(不是 helper、utils) -- [x] 小写 + 连字符 -- [x] 不超过 64 字符 - ---- - -## 📊 技能质量评估 - -| 维度 | 评分 | 说明 | -|------|------|------| -| **完整性** | 95% | 覆盖配置、问题、实践、调试 ✅ | -| **准确性** | 100% | 所有方案经过验证 ✅ | -| **易用性** | 90% | 清晰的结构和索引 ✅ | -| **可维护性** | 95% | 明确的维护指南 ✅ | -| **规范性** | 100% | 完全符合 create-skill 规范 ✅ | - -**总体评分**:96% ✅ 优秀 - ---- - -## 🎯 技能价值 - -### 1. 提升效率 - -**Before**: -- Agent 需要搜索文档:5-10 分钟 -- 配置可能不规范:需要迭代修复 -- 问题解决缺少经验:可能走弯路 - -**After**: -- Agent 直接应用技能:30 秒 -- 配置一次到位:符合规范 -- 问题快速解决:经验方案 - -**效率提升**:10-20 倍 ✅ - ---- - -### 2. 保证质量 - -**稳定性**: -- ✅ 所有方案经过验证 -- ✅ 配置符合官方规范 -- ✅ 避免已知的坑 - -**一致性**: -- ✅ 统一的配置风格 -- ✅ 统一的代码模式 -- ✅ 统一的术语 - ---- - -### 3. 积累知识 - -**知识沉淀**: -- ✅ 实践经验文档化 -- ✅ 问题和方案结构化 -- ✅ 最佳实践标准化 - -**持续改进**: -- ✅ 发现新问题 → 更新技能 -- ✅ 优化旧方案 → 更新技能 -- ✅ 技能越用越强 - ---- - -## 📋 后续计划 - -### 立即可用 ✅ - -技能已经完整且可用: -- [x] 配置规范完整 -- [x] 常见问题覆盖 -- [x] 最佳实践明确 -- [x] 使用说明清晰 - ---- - -### 持续优化 ⏳ - -根据使用情况持续改进: - -1. **收集新问题** - - 遇到新的兼容性问题 - - 发现新的最佳实践 - - 用户反馈的问题 - -2. **更新技能文档** - - 添加到 troubleshooting.md - - 更新 SKILL.md(常见问题) - - 更新 README.md(快速参考) - -3. **创建项目文档** - - 在 `开发文档/8、部署/` 创建详细文档 - - 记录完整的解决过程 - - 供人类阅读和学习 - ---- - -### 可能的扩展 💡 - -未来可以考虑: - -1. **增加更多平台** - - 支持 Vue + Kbone - - 支持其他跨平台方案 - -2. **增加工具脚本** - - 自动化配置生成 - - 代码检查脚本 - - 迁移辅助工具 - -3. **增加性能优化** - - 更多优化策略 - - 性能监控方案 - - 最佳实践更新 - ---- - -## 🎉 完成总结 - -### 核心成果 - -1. ✅ **创建了完整的 Kbone 技能** - 3 个文档文件 -2. ✅ **覆盖了主要场景** - 配置、问题、优化、调试 -3. ✅ **符合规范标准** - 完全符合 create-skill 规范 -4. ✅ **基于实践经验** - 所有方案经过验证 -5. ✅ **易于维护更新** - 清晰的维护指南 - ---- - -### 技能亮点 - -1. **结构清晰** - 主文档 + 详细指南 + 使用说明 -2. **内容全面** - 18+ 问题和解决方案 -3. **实践导向** - 基于真实项目经验 -4. **易于查找** - 快速参考表和索引 -5. **持续改进** - 明确的更新机制 - ---- - -### 使用指引 - -**Agent 自动应用场景**: -- ✅ 用户提到 "kbone"、"小程序" -- ✅ 配置 miniprogram.config.js -- ✅ 修复编译/运行时错误 -- ✅ 优化 Kbone 配置 - -**人类查阅场景**: -- ✅ 学习 Kbone 最佳实践 -- ✅ 排查具体问题 -- ✅ 了解跨平台适配方案 - ---- - -**🎊 Kbone 技能创建完成!Agent 现在可以更专业地处理 Kbone 项目了。** - ---- - -**参考**: -- [create-skill 规范](https://github.com/getcursor/cursor/blob/main/docs/skills/create-skill.md) -- [Kbone 官方文档](https://wechat-miniprogram.github.io/kbone/docs/) - -**创建日期**:2026-02-03 -**文档版本**:v1.0 diff --git a/README-Kbone迁移完成.md b/README-Kbone迁移完成.md deleted file mode 100644 index fa9c9e3f..00000000 --- a/README-Kbone迁移完成.md +++ /dev/null @@ -1,480 +0,0 @@ -# 🎉 Kbone 小程序迁移完成报告 - -## 项目概述 - -**项目名称**:Soul创业派对 - C端小程序迁移 -**技术方案**:Kbone 同构开发(React) -**完成日期**:2026年2月2日 -**迁移状态**:✅ **100% 完成** - ---- - -## 一、迁移成果 - -### 1.1 页面完成度 - -✅ **10/10 页面全部迁移** - -| 序号 | 页面 | Web 路由 | 小程序页面 | 状态 | -|------|------|----------|-----------|------| -| 1 | 首页 | `/` | pages/index/index | ✅ | -| 2 | 目录 | `/chapters` | pages/chapters/chapters | ✅ | -| 3 | 阅读 | `/read/[id]` | pages/read/read | ✅ | -| 4 | 我的 | `/my` | pages/my/my | ✅ | -| 5 | 推广中心 | `/my/referral` | pages/referral/referral | ✅ | -| 6 | 设置 | `/my/settings` | pages/settings/settings | ✅ | -| 7 | 购买记录 | `/my/purchases` | pages/purchases/purchases | ✅ | -| 8 | 关于 | `/about` | pages/about/about | ✅ | -| 9 | 找伙伴 | `/match` | pages/match/match | ✅ | -| 10 | 搜索 | `/search` | pages/search/search | ✅ | - -### 1.2 核心功能 - -✅ **阅读流程** -- 首页 → 精选推荐 → 阅读页 -- 目录 → 选择章节 → 阅读页 -- 阅读页:内容渲染、进度条、上下篇切换 - -✅ **用户中心** -- 我的:未登录态、已登录态 -- 用户卡片:统计、收益、Tab 切换 -- 推广中心:邀请码、收益、复制功能 -- 设置、购买记录、关于 - -✅ **找伙伴** -- 匹配类型选择 -- 匹配次数管理 -- 匹配结果展示 -- 加入匹配池 - -✅ **搜索** -- 实时搜索章节 -- 搜索结果展示 -- 点击跳转阅读 - -✅ **底部 TabBar** -- 4 个 Tab:首页、目录、找伙伴、我的 -- 激活态标识 -- 跨端路由切换 - ---- - -## 二、技术架构 - -### 2.1 技术栈 - -| 类型 | 技术 | -|------|------| -| 框架 | Kbone(React 16.14) | -| 状态管理 | Zustand + persist | -| 样式方案 | Inline Styles | -| 构建工具 | Webpack 4 + Babel 6 | -| 运行时 | 小程序基础库 2.x | - -### 2.2 适配层设计 - -``` -src/adapters/ -├── env.js # 环境检测 -├── router.js # 路由导航 -├── request.js # 网络请求 -├── storage.js # 本地存储 -└── index.js # 统一导出 -``` - -**核心功能**: -- ✅ 跨端环境检测(小程序 / Web) -- ✅ 统一路由 API(navigate、switchTab、back、getPageQuery) -- ✅ 统一请求 API(小程序 wx.request / Web fetch) -- ✅ 统一存储 API(小程序 wx.storage / Web localStorage) - -### 2.3 状态管理 - -```javascript -// src/store/index.js -- 用户状态:user、isLoggedIn、logout、setUser -- 购买逻辑:hasPurchased、addPurchase、purchaseFullBook -- 配置管理:settings、setSettings -- 持久化:集成 storage 适配层 -``` - -### 2.4 目录结构 - -``` -newpp/ -├── src/ -│ ├── adapters/ # 适配层 -│ ├── components/ # 公共组件 -│ ├── pages/ # 页面组件 -│ ├── data/ # 静态数据 -│ ├── store/ # 状态管理 -│ ├── index.jsx # 首页入口 -│ ├── chapters.jsx # 目录入口 -│ ├── read.jsx # 阅读入口 -│ └── ... # 其他入口 -├── build/ -│ ├── miniprogram.config.js # Kbone 配置 -│ └── webpack.mp.config.js # Webpack 配置 -└── dist/mp/ # 构建产物 -``` - ---- - -## 三、迁移过程(Phase 1-5) - -### Phase 1:搭架子(2h) -- ✅ 创建适配层(env、router、request、storage) -- ✅ 配置 Kbone(miniprogram.config.js) -- ✅ 创建首页、目录、阅读页占位 -- ✅ 配置 Webpack 构建 - -### Phase 2:核心页(3h) -- ✅ 实现首页(精选推荐、书籍介绍、序言) -- ✅ 实现目录页(章节列表、展开/折叠) -- ✅ 实现阅读页(接口对接、上下篇切换) -- ✅ 创建 ChapterContent 组件 -- ✅ 创建静态 bookData - -### Phase 3:我的与子页(2h) -- ✅ 创建 Zustand store 适配 -- ✅ 实现我的页(登录态、统计、收益) -- ✅ 实现推广页(邀请码、收益、规则) -- ✅ 实现设置、购买记录、关于页 - -### Phase 4:找伙伴与其余(2h) -- ✅ 实现找伙伴页(匹配类型、次数管理、结果展示) -- ✅ 实现搜索页(实时搜索、结果跳转) -- ✅ 创建 BottomNav 组件 -- ✅ 各页面集成 BottomNav -- ✅ 安全区适配 - -### Phase 5:收尾(3h) -- ✅ 创建自检清单 -- ✅ 修复 Babel 6 兼容性问题 -- ✅ 创建踩坑修复指南 -- ✅ 创建发布流程文档 -- ✅ 构建成功并合并到 miniprogram - -**总耗时**:~12小时 - ---- - -## 四、技术亮点 - -### 4.1 跨端适配层 - -**设计思路**: -- 抽象平台差异,提供统一 API -- 运行时自动检测环境 -- 无需修改业务代码 - -**示例**: -```javascript -// 业务代码 -import { navigate, request, storage } from '../adapters' - -// 路由跳转(自动适配小程序 wx.navigateTo / Web location.href) -navigate('/read/1.1') - -// 网络请求(自动适配小程序 wx.request / Web fetch) -const data = await request('/api/book/chapter/1.1') - -// 本地存储(自动适配小程序 wx.storage / Web localStorage) -storage.setItem('user', user) -``` - -### 4.2 状态持久化 - -**方案**:Zustand + persist 中间件 + storage 适配层 - -**优势**: -- 状态自动持久化到本地存储 -- 跨端统一(小程序 wx.storage / Web localStorage) -- 无需手动 get/set - -### 4.3 Inline Styles - -**方案**:使用 JavaScript 对象定义样式 - -**优势**: -- 无需转换 Tailwind CSS → WXSS -- 样式与组件强耦合,易维护 -- 支持动态样式(条件渲染、主题切换) - -**示例**: -```javascript -const styles = { - page: { minHeight: '100vh', background: '#000', color: '#fff' }, - card: { padding: 16, borderRadius: 12, background: '#1c1c1e' }, -} - -return