CHANGELOG.md 21.7 KB

Changelog

本文档记录 Manulife WeApp项目的所有重要变更。 格式基于 Keep a Changelog


[2026-02-10] - 修复计划书弹窗按钮显示逻辑

修复

  • 未找到模板时的按钮逻辑
    • 未找到计划书模板时,底部只显示"关闭"按钮
    • 找到模板时,显示"取消"和"生成计划书"按钮
    • 通过 hasTemplate prop 控制按钮显示状态

详细信息

  • 影响文件: src/components/plan/PlanPopupNew.vue, src/components/plan/PlanFormContainer.vue
  • 技术栈: Vue 3, Composition API
  • 测试状态: 待验证
  • 备注: 改进用户体验,避免在无模板时显示无用的"生成计划书"按钮

[2026-02-10] - 升级依赖包到最新稳定版本

优化

  • NutUI 升级@nutui/nutui-taro 从 4.3.13 升级到 4.3.14

    • 包含 bug 修复和性能优化
    • 改进组件稳定性和兼容性
  • Taro 框架升级:所有 @tarojs/* 包从 4.1.9 升级到 4.1.11

    • 核心框架优化:@tarojs/taro, @tarojs/runtime, @tarojs/components
    • 插件更新:所有平台插件(weapp, h5, alipay, swan, tt, jd, qq)
    • 构建工具升级:@tarojs/cli, @tarojs/webpack5-runner
    • 新增依赖:@tarojs/service@4.1.11

改进

  • 更好的 TypeScript 支持
  • 小程序平台兼容性改进
  • 构建工具稳定性提升

详细信息

  • 影响文件: package.json, pnpm-lock.yaml
  • 技术栈: Taro 4.1.11, NutUI 4.3.14
  • 测试状态: 待验证(需测试核心功能和构建)
  • 备注: ⚠️ 建议在开发环境测试验证后再部署到生产环境

[2026-02-09] - 添加热卖产品 Mock 数据支持

新增

  • Mock 数据模块src/api/mock/):
    • 新增 hotProducts.js:包含 9 种产品的 Mock 数据
    • 覆盖所有计划书模板类型(人寿、重疾、储蓄)
    • 支持 form_sn 字段,对应不同的计划书模板
    • 包含完整的产品信息(名称、分类、标签、封面图)

优化

  • 首页 Mock 数据支持src/pages/index/index.vue):
    • 添加 USE_MOCK_DATA 开关控制数据来源
    • 开发环境使用 Mock 数据测试计划书功能
    • 生产环境调用真实 API(listAPI
    • 添加详细的 JSDoc 注释和使用说明

文档

  • CLAUDE.md 更新
    • 添加 Mock 数据工具使用指南
    • 说明支持的 Mock API 列表
    • 提供使用示例和注意事项

详细信息

  • 影响文件: src/api/mock/hotProducts.js, src/pages/index/index.vue, CLAUDE.md
  • 技术栈: Vue 3, Mock 数据
  • 测试状态: 开发环境已测试
  • 备注: ⚠️ 生产环境请设置 USE_MOCK_DATA = false

Changelog

本文档记录 Manulife WeApp项目的所有重要变更。 格式基于 Keep a Changelog


[2026-02-09] - 更新 API 集成日志和经验教训文档

文档

  • API 集成日志更新:
    • 完成 3 个待联调接口联调(addAPI, weekHotAPI, fileListAPI)
    • 新增"待联调接口快速清单"(便于快速定位待处理接口)
    • 新增 myPlanListAPI 接口定义(我的计划书列表)
    • 更新进度追踪:29个接口,82.8% 已完成
  • 经验教训文档更新:
    • 新增"复杂功能修改的系统性问题"章节(250+ 行)
    • 记录计划书模块开发中的系统性问题
    • 提供 5 步系统化修改流程解决方案
    • 包含反面案例和正面案例对比

详细信息

  • 影响文件: docs/api-docs/API 集成日志.md, docs/lessons-learned.md
  • 技术栈: 文档
  • 测试状态: N/A
  • 备注: 提升项目文档完整性,积累开发经验

[2026-02-09] - 升级 AmountKeyboard 组件 UI 为现代科技风(V3 - 清新毛玻璃)

优化

  • 视觉风格:切换为明亮的半透明磨砂玻璃风格(Light Glassmorphism)
    • 背景色调整为 bg-white/70,配合 backdrop-blur-2xl,通透且有质感
    • 装饰流光改为更柔和的蓝紫色 mix-blend-multiply 模式,避免过度抢眼
  • 色彩调整
    • 文字颜色回归深灰色系(Slate 800/500),保证极佳的可读性
    • 光标使用清新的天蓝色(Blue 500),带柔和发光效果
  • 细节打磨
    • 顶部标签增加白色半透明背景和微阴影,提升层次感
    • 底部高光条改为 Slate 色系,与整体色调融合

[2026-02-09] - 升级 AmountKeyboard 组件 UI 为现代科技风(V2)

优化

  • 背景升级:使用 bg-slate-900/90 配合 backdrop-blur-2xl 实现真正的磨砂玻璃质感,底部增加微弱的彩色流光
  • 布局重构:将币种符号调整至金额上方,形成垂直视觉流(Vertical Flow),突出金额数值的核心地位
  • 排版优化
    • 顶部标签改为极简的 INPUT AMOUNT,增加字间距(tracking-widest)
    • 金额数值字号增大至 100rpx,增强视觉冲击力
    • 光标高度和阴影调整,使其更加自然
  • 细节打磨
    • 移除多余的装饰性元素,保持界面干净
    • 底部增加渐变高光条,提升精致感

[2026-02-09] - 优化 AmountKeyboard 组件 UI 风格为极简专业风

优化

  • 移除 AmountKeyboard 的装饰性背景和渐变效果,回归极简设计
  • 采用白色背景 + 深灰色文字,提升专业感和可读性
  • 增加光标模拟动画,提升交互感知
  • 优化排版布局,强化金额数值的视觉层级
  • 移除多余的阴影和边框,保持界面干净整洁

[2026-02-09] - 优化 AmountKeyboard 组件 UI 显示

优化

  • 重构 AmountKeyboard 弹窗 UI,使用 Tailwind CSS 替代原有 LESS 样式
  • 优化弹窗视觉效果,增加渐变背景和磨砂质感
  • 移除冗余的 LESS 样式代码,遵循项目 CSS 规范
  • 优化数字显示排版,提升可读性

[2026-02-09] - 清理未使用的旧版本选择器组件

重构

  • 删除 AgePicker.vue(已被 AgePickerGlobal.vue 替代)
  • 删除 DatePicker.vue(已被 DatePickerGlobal.vue 替代)
  • 删除 SelectPicker.vue(已被 SelectPickerGlobal.vue 替代)

背景

  • 所有模板文件已统一使用 Global 版本组件
  • 旧版本组件无任何引用,造成代码冗余

收益

  • ✅ 减少代码冗余(删除 759 行未使用代码)
  • ✅ 避免开发时的混淆(不知道该用哪个版本)
  • ✅ 降低维护成本

验证

  • ✅ ESLint 检查通过
  • ✅ 全局搜索确认无引用
  • ✅ 所有模板使用 Global 版本

[2026-02-09] - 修复组件路径引用问题

修复

  • 修复 MaterialCard.vue 中 ListItemActions 的导入路径
  • 修复 DocumentPreview 相关的导入路径(3 个文件)
  • 修复 ListItemActions 的导入路径(3 个页面文件)
  • 修复 OfficeViewer.vue 中 utils 的导入路径
  • 修复 document-demo 和 document-preview 页面的导入路径

验证

  • ✅ pnpm build:weapp 编译成功(12.98s)
  • ✅ 所有组件路径引用已更新
  • ✅ 无编译错误

[2026-02-09] - 组件目录结构重组

重构

  • 创建分类目录:navigation, list, forms, cards, documents, plan, icons
  • 移动组件到对应分类目录
    • navigation: TabBar, NavHeader
    • list: SectionCard, SectionItem, ListItemActions, LoadMoreList
    • forms: FilterTabs, SearchBar
    • cards: MaterialCard, ProductCard
    • documents: DocumentPreview, PdfPreview, OfficeViewer
    • plan: PlanFormContainer, PlanPopupNew, PlanFields, PlanTemplates
    • icons: IconFont
  • 更新所有组件导入路径(38 个文件)

收益

  • ✅ 组件组织更清晰,按功能分类
  • ✅ 便于查找和维护
  • ✅ 符合项目架构原则
  • ✅ 为未来组件扩展预留空间

[2026-02-09] - 清理未使用的组件

删除

  • 删除 src/components/qrCode.vue(11KB,完全未使用)
  • 删除 src/components/FilterTabs.example.vue(示例文件)
  • 删除 src/components/PlanPopup/ 目录(已被 PlanPopupNew 替代)

优化

  • 减少代码库大小约 11KB
  • 提升组件目录清晰度
  • 清理冗余代码,降低维护负担

[2026-02-09] - 修复 AmountKeyboard 组件取消操作显示异常并优化输入体验

修复

  • 修复点击遮罩关闭后显示 "123." 等不完整值的问题
  • 在 watch(showKeyboard) 中添加逻辑,键盘关闭时清除临时输入值
  • 优化 displayValue 计算属性,确保始终显示格式化后的金额

优化

  • 添加输入限制的震动反馈(Taro.vibrateShort)
  • 添加 Toast 轻提示提示用户输入限制
  • 重复输入小数点时提示"只能输入一个小数点"
  • 超过2位小数时提示"最多只能输入2位小数"

[2026-02-09] - 新增 AmountKeyboard 数字键盘输入组件

新增

  • 创建 AmountKeyboard.vue 组件,替代 AmountInput 输入框
  • 实现数字键盘(nut-number-keyboard)点击触发
  • 新增金额显示弹窗(页面中间显示输入内容,渐变背景设计)
  • 集成 GlobalPopupManager 解决嵌套弹窗层级问题
  • 实现字符累加逻辑,支持连续录入(123)
  • 添加输入验证(1个小数点,2位小数)
  • 添加千分位分隔符显示
  • 实现 toFixed(2) 确保保存格式一致性
  • 防止点击遮罩关闭弹窗
  • 添加 watch(showKeyboard) 同步键盘和弹窗状态

功能特点

  • 点击输入框弹出数字键盘(右列模式,包含小数点)
  • 金额显示弹窗(渐变背景 + 装饰圆圈 + 大号字体)
  • 输入验证(限制1个小数点,2位小数)
  • 连续输入支持(字符累加,字符串类型安全)
  • 状态同步(键盘关闭时自动关闭金额弹窗)
  • 多币种支持(CNY、USD、HKD、EUR)

技术实现

  • 使用 nut-number-keyboard 的 @input 事件(单字符传递)
  • 字符累加:String(inputValue.value) + String(val)
  • 输入验证:split('.') 检查小数点和小数位数量
  • 初始化:空字符串(非"0.00")避免验证冲突
  • 保存:parseFloat(yuan.toFixed(2)) 确保格式
  • 单位转换:内部存储为分(整数),显示为元(带2位小数)

问题解决

  1. Vue渲染错误:使用正确的 kebab-case 组件名 nut-number-keyboard
  2. 键盘被底部按钮遮挡:使用 GlobalPopupManager 解决嵌套弹窗层级
  3. 单字符输入:实现字符累加逻辑
  4. 字符串相加变成数字相加(1+2=3):显式使用 String() 转换
  5. 输入验证阻塞:初始化为空字符串而非 "0.00"
  6. 保存格式问题:使用 toFixed(2) 确保 "12.00" 格式
  7. 自动关闭bug:添加时间判断过滤(500ms内)
  8. 状态同步:watch(showKeyboard) 同步关闭金额弹窗

影响文件

  • src/components/PlanFields/AmountKeyboard.vue(新增)
  • src/components/PlanTemplates/LifeInsuranceTemplate.vue(使用新组件)
  • src/components/PlanTemplates/CriticalIllnessTemplate.vue(使用新组件)
  • src/components/PlanTemplates/SavingsTemplate.vue(使用新组件)
  • docs/lessons-learned.md(添加经验教训记录)

详细信息

  • 影响文件: 见上文
  • 技术栈: Vue 3, Taro 4, NutUI, GlobalPopupManager
  • 测试状态: ✅ 已通过
  • 备注: 替代原有的 AmountInput 组件,老组件保留用于测试

[2026-02-08] - 实现全局弹窗管理器解决嵌套弹窗遮挡问题

新增

  • 创建 GlobalPopupManager 全局弹窗管理器
  • 实现 useParentPopup 和 useGlobalPopup 接口
  • 新增 PlanPopupNew 父弹窗组件(支持全局管理)
  • 新增 DatePickerGlobal 日期选择器(支持全局管理)
  • 新增 SelectPickerGlobal 下拉选择器(支持全局管理)
  • 新增 AgePickerGlobal 年龄选择器(支持全局管理)

优化

  • 子弹窗打开时自动隐藏父弹窗底部按钮
  • 所有子弹窗关闭时自动恢复底部按钮
  • 支持多个子弹窗同时打开
  • 支持多层弹窗嵌套(弹窗套弹窗)
  • 使用 watch 监听全局状态,解决组件挂载时序问题

问题原因

NutUI 嵌套弹窗的 z-index 层级问题

  • 父弹窗和子弹窗都是 position: fixed 定位
  • 即使子弹窗 z-index 更高,也无法遮挡父弹窗的非子元素(如底部按钮)
  • 底部按钮在 DOM 结构上与子弹窗同级,会覆盖子弹窗内容

解决方案

核心策略:全局弹窗管理器协调父弹窗和子弹窗状态

  1. 子弹窗注册:每个子弹窗组件挂载时注册,获得唯一 ID
  2. 激活/停用:子弹窗打开时激活,关闭时停用
  3. 状态同步:管理器通知父弹窗隐藏/显示底部按钮
  4. 响应式更新:父弹窗通过 watch 监听全局状态变化

迁移工作

  • 更新 PlanFormContainer 使用 PlanPopupNew
  • 更新所有计划模板(LifeInsuranceTemplate、CriticalIllnessTemplate、SavingsTemplate)使用 Global 版本字段组件

影响文件

  • src/components/PlanFormContainer.vue
  • src/components/PlanPopupNew.vue
  • src/components/PlanFields/GlobalPopupManager.js
  • src/components/PlanFields/DatePickerGlobal.vue
  • src/components/PlanFields/SelectPickerGlobal.vue
  • src/components/PlanFields/AgePickerGlobal.vue
  • src/components/PlanTemplates/LifeInsuranceTemplate.vue
  • src/components/PlanTemplates/CriticalIllnessTemplate.vue
  • src/components/PlanTemplates/SavingsTemplate.vue

[2026-02-08] - 修复计划书表单重置和数据同步问题

修复

  • 修复计划书表单关闭后再次打开数据依然存在的bug
  • 修复表单输入过程中数据意外丢失的问题
  • 修复第一次点击确认按钮没有值的问题

优化

  • 优化表单状态管理,区分"重置"和"正常更新"
  • 改进 v-model 双向绑定的数据同步逻辑

问题原因

Vue 3 v-model + reactive 的双向同步陷阱

  • v-model 每次更新都创建新对象
  • reactive(props.modelValue) 只在初始化时读取一次 props
  • 父子组件状态不同步

解决方案

核心策略:区分"重置"和"正常更新"

  • 重置判断:从有数据 → 空对象
  • 正常更新:只合并新字段,不删除已有字段
  • 避免使用引用判断(newVal !== previousModelValue),因为 v-model 每次都创建新对象

技术细节

关键改进

// ✅ 正确的 watch 策略
const isReset = previousModelValue &&
                Object.keys(previousModelValue).length > 0 &&
                Object.keys(newVal).length === 0

if (isReset) {
  // 重置:清空表单
  Object.keys(form).forEach(key => delete form[key])
} else {
  // 正常更新:只合并新字段
  Object.keys(newVal).forEach(key => {
    form[key] = newVal[key]
  })
}

避免的陷阱

  • ❌ 每次 props 变化都清空并复制(导致数据丢失)
  • ❌ 使用引用判断是否更新(v-model 每次创建新对象)
  • ❌ 使用 { deep: true } 监听 props(可能导致循环)

影响文件

  • src/components/PlanFormContainer.vue
  • src/components/PlanTemplates/LifeInsuranceTemplate.vue
  • src/components/PlanTemplates/CriticalIllnessTemplate.vue
  • src/components/PlanTemplates/SavingsTemplate.vue

测试验证

  • ✅ 填写表单 → 关闭弹窗 → 再次打开 → 表单为空
  • ✅ 第一次点击确认按钮 → 值能正常保存
  • ✅ 年龄和出生年月日双向联动正常

经验教训

详见 docs/lessons-learned.md 中的"Vue 3 响应式数据和表单状态管理"章节。


[2026-02-08] - 优化年龄与出生年月日联动逻辑

优化

  • 调整计划书模板字段顺序:年龄在前,出生年月日在后
  • 实现年龄 → 出生年月日自动计算(当前年份 - 年龄,默认1月1日)
  • 保留出生年月日 → 年龄双向联动(用户可手动调整出生日期)
  • 简化占位符文案,避免用户理解混乱
  • 修复 AgePicker 组件不触发 change 事件的问题

改进细节

  • AgePicker.vue: 添加 change 事件支持,确保父组件能监听年龄变化
  • LifeInsuranceTemplate.vue: 实现双向联动逻辑
  • CriticalIllnessTemplate.vue: 实现双向联动逻辑
  • SavingsTemplate.vue: 实现双向联动逻辑

用户体验改进

  • ✅ 用户先录入年龄(简单快捷)
  • ✅ 系统自动计算出生年月日(默认1月1日)
  • ✅ 用户仍可手动调整出生年月日(灵活性)
  • ✅ 简化文案,避免不必要的理解错误

影响文件

  • src/components/PlanFields/AgePicker.vue
  • src/components/PlanTemplates/LifeInsuranceTemplate.vue
  • src/components/PlanTemplates/CriticalIllnessTemplate.vue
  • src/components/PlanTemplates/SavingsTemplate.vue

[2026-02-08] - 修复 LoadMoreList 页面双重滚动问题

修复

  • 修复 4 个使用 LoadMoreList 组件的页面出现双重滚动问题
    • 页面级和 scroll-view 都可以滚动,导致用户体验混乱
    • src/pages/feedback-list/index.vue
    • src/pages/favorites/index.vue
    • src/pages/material-list/index.vue
    • src/pages/product-center/index.vue
  • 在页面容器添加 height: 100vhoverflow: hidden
    • TailwindCSS: h-screen overflow-hidden
    • Less: height: 100vh; overflow: hidden;

问题原因

  • 页面容器未设置固定高度(使用 min-height 或未设置)
  • 页面容器未禁用溢出(缺少 overflow: hidden
  • 导致页面级和组件级滚动同时生效

解决方案

  • 页面容器设置固定高度:height: 100vh(或 h-screen
  • 页面容器禁用溢出:overflow: hidden(或 overflow-hidden
  • 让 LoadMoreList 内部的 scroll-view 处理所有滚动
  • 固定元素(导航栏、搜索栏)放在 #header 插槽中

文档

  • docs/lessons-learned.md 中添加"LoadMoreList 页面的双重滚动问题"记录
    • 说明问题表现、原因分析、解决方案
    • 提供最佳实践和检查清单
    • 列出修复的 4 个页面和已正确的 3 个页面

收益

  • ✅ 消除双重滚动,提升用户体验
  • ✅ 固定元素(导航栏、搜索栏)始终可见
  • ✅ 统一 LoadMoreList 页面的滚动行为
  • ✅ 为所有使用 LoadMoreList 的页面提供标准模式

详细信息

  • 影响文件:
    • src/pages/feedback-list/index.vue(修复双重滚动)
    • src/pages/favorites/index.vue(修复双重滚动)
    • src/pages/material-list/index.vue(修复双重滚动)
    • src/pages/product-center/index.vue(修复双重滚动)
    • docs/lessons-learned.md(添加经验教训)
  • 技术栈: Vue 3, Taro 4, TailwindCSS, Less
  • 测试状态: ✅ 已通过
  • 备注: 共检查 7 个使用 LoadMoreList 的页面,修复 4 个,3 个已正确

[2026-02-08] - 修复 LoadMoreList 组件底部 padding 堆叠问题

修复

  • 修复 .load-more-content.scrollable 修饰符类与基础类 padding 堆叠问题
    • 基础类 padding: 32rpx 与修饰符类 padding-bottom 堆叠
    • 导致底部 padding ≈ 192rpx + safe-area(过高)
    • 修改为覆盖整个 padding 属性: padding: 32rpx 32rpx calc(160rpx + env(safe-area-inset-bottom))

优化

  • 简化搜索页 shouldEnableScrollLoad 逻辑(只要有数据就启用滚动)
  • 添加搜索页 disableScroll: true 配置(禁用页面级滚动)

文档

  • docs/lessons-learned.md 中添加 LESS 修饰符类样式堆叠坑的记录
    • 说明 LESS 嵌套选择器中修饰符类属性会与基础类堆叠
    • 提供解决方案:覆盖整个属性而不是只写子属性

详细信息

  • 影响文件:
    • src/components/LoadMoreList/index.vue(修复 padding 堆叠)
    • src/pages/search/index.config.js(添加 disableScroll)
    • src/pages/search/index.vue(简化滚动逻辑)
    • docs/lessons-learned.md(添加经验教训)
  • 技术栈: Vue 3, Taro 4, Less
  • 测试状态: ✅ 已通过
  • 备注: 所有使用 LoadMoreList 的 7 个页面都受益于这个修复

[2026-02-08] - 文档重组:全面中文化

文档

  • 将所有文档文件名改为中文命名(遵循全局规则)
    • guides/ 目录下的指南文档(API 使用指南、OpenAPI 转换等)
    • reports/ 目录下的报告文档(Apifox 配置总结、变更日志检查等)
    • mcp/ 目录下的 MCP 相关文档
    • plan/ 目录下的计划书文档
  • 删除已废弃的 docs/form-sn-mapping.json(配置已迁移到代码)
  • 更新 docs/README.md 以反映新的文档结构
  • 修复文档中的交叉引用链接

详细信息

  • 影响文件: docs/guides/.md, docs/reports/.md, docs/mcp/.md, docs/plan/.md, docs/README.md
  • 技术栈: 文档
  • 测试状态: N/A
  • 备注: 提升中文开发者体验,统一文档命名规范

[2026-02-08] - 整理文档结构并使用中文命名(首次)

文档

  • 重新组织 docs 文件夹结构,按功能分类
    • 组件文档 → guides/components/
    • 测试指南 → guides/testing/
    • API 规范 → api-specs/api-specs/数据文档/
    • 测试报告 → reports/测试报告/
  • 所有文档文件名使用中文命名(如 LoadMoreList 完整使用指南.md
  • 更新所有文档中的相对路径引用
  • 备份原始页面代码到 docs/backups/original-pages/
  • 将"文档命名使用中文"规则添加到全局规则(changelog-automation.md

[2026-02-08] - 迁移所有剩余页面到 LoadMoreList 组件

重构

  • 迁移 src/pages/message/index.vue 使用 LoadMoreList 组件
    • 添加下拉刷新功能
    • 简化分页加载逻辑
  • 迁移 src/pages/product-center/index.vue 使用 LoadMoreList 组件
    • 保留搜索、tabs、计划书弹窗功能
    • 统一分页加载逻辑
  • 迁移 src/pages/material-list/index.vue 使用 LoadMoreList 组件
    • 保留分类缓存、搜索防抖功能
    • 优化分页状态管理
  • 迁移 src/pages/search/index.vue 使用 LoadMoreList 组件
    • 保留双列表系统(products + files)
    • 保留自动 tab 选择逻辑
    • 保留三种显示状态(初始、空、有结果)

收益

  • 统一 5 个页面的分页加载逻辑
  • 减少重复代码约 700+ 行
  • 统一动画效果和加载状态
  • 提升代码可维护性