From 6747ade9c478c2654af76e140fe60117e2b8fd41 Mon Sep 17 00:00:00 2001 From: yuming Date: Sun, 26 Oct 2025 19:29:30 +0800 Subject: [PATCH] Initial Commit --- .gitignore | 14 + PRD.md | 415 +++++++++++++++++++++ README.md | 225 +++++++++++ app.js | 27 ++ app.json | 46 +++ app.wxss | 101 +++++ images/.gitkeep | 7 + pages/add-anniversary/add-anniversary.js | 263 +++++++++++++ pages/add-anniversary/add-anniversary.wxml | 101 +++++ pages/add-anniversary/add-anniversary.wxss | 139 +++++++ pages/add-person/add-person.js | 136 +++++++ pages/add-person/add-person.wxml | 41 ++ pages/add-person/add-person.wxss | 115 ++++++ pages/calendar/calendar.js | 234 ++++++++++++ pages/calendar/calendar.wxml | 52 +++ pages/calendar/calendar.wxss | 215 +++++++++++ pages/index/index.js | 165 ++++++++ pages/index/index.wxml | 56 +++ pages/index/index.wxss | 193 ++++++++++ pages/person-detail/person-detail.js | 188 ++++++++++ pages/person-detail/person-detail.wxml | 63 ++++ pages/person-detail/person-detail.wxss | 273 ++++++++++++++ pages/settings/settings.js | 133 +++++++ pages/settings/settings.wxml | 46 +++ pages/settings/settings.wxss | 82 ++++ project.config.json | 43 +++ project.private.config.json | 23 ++ sitemap.json | 8 + utils/date.js | 117 ++++++ utils/lunar.js | 130 +++++++ utils/storage.js | 224 +++++++++++ 快速开始.md | 193 ++++++++++ 项目总结.md | 319 ++++++++++++++++ 33 files changed, 4387 insertions(+) create mode 100644 .gitignore create mode 100644 PRD.md create mode 100644 README.md create mode 100644 app.js create mode 100644 app.json create mode 100644 app.wxss create mode 100644 images/.gitkeep create mode 100644 pages/add-anniversary/add-anniversary.js create mode 100644 pages/add-anniversary/add-anniversary.wxml create mode 100644 pages/add-anniversary/add-anniversary.wxss create mode 100644 pages/add-person/add-person.js create mode 100644 pages/add-person/add-person.wxml create mode 100644 pages/add-person/add-person.wxss create mode 100644 pages/calendar/calendar.js create mode 100644 pages/calendar/calendar.wxml create mode 100644 pages/calendar/calendar.wxss create mode 100644 pages/index/index.js create mode 100644 pages/index/index.wxml create mode 100644 pages/index/index.wxss create mode 100644 pages/person-detail/person-detail.js create mode 100644 pages/person-detail/person-detail.wxml create mode 100644 pages/person-detail/person-detail.wxss create mode 100644 pages/settings/settings.js create mode 100644 pages/settings/settings.wxml create mode 100644 pages/settings/settings.wxss create mode 100644 project.config.json create mode 100644 project.private.config.json create mode 100644 sitemap.json create mode 100644 utils/date.js create mode 100644 utils/lunar.js create mode 100644 utils/storage.js create mode 100644 快速开始.md create mode 100644 项目总结.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..14ea590 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# Windows +[Dd]esktop.ini +Thumbs.db +$RECYCLE.BIN/ + +# macOS +.DS_Store +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes + +# Node.js +node_modules/ diff --git a/PRD.md b/PRD.md new file mode 100644 index 0000000..4a44daa --- /dev/null +++ b/PRD.md @@ -0,0 +1,415 @@ +# 生日提醒小程序产品需求文档 (PRD) + +## 1. 项目概述 + +### 1.1 项目名称 +生日提醒小程序 + +### 1.2 项目背景 +随着社交圈不断扩大,人们需要记住的生日和纪念日越来越多。人工记忆容易遗漏重要日期,需要一款智能提醒工具帮助用户管理所有重要的纪念日。 + +### 1.3 项目定位 +一款轻量级、易用的个人纪念日管理小程序,帮助用户记录和提醒重要的生日、节日和纪念日。 + +### 1.4 核心价值 +- **不遗漏任何重要日期**:智能提醒系统确保用户不会错过亲朋好友的生日 +- **支持农历生日**:满足中国传统习惯 +- **灵活定制**:支持多种纪念日类型,自定义提醒时间 +- **简单高效**:极简界面,快速添加和查看 + +--- + +## 2. 用户画像 + +### 2.1 目标用户 +- **年龄**: 20-45岁 +- **特征**: 重视人际关系,有较多社交圈子 +- **痛点**: + - 不记得朋友的生日日期 + - 农历生日难以记忆和转换 + - 错过重要的生日祝福 + - 无法提前准备礼物 + +### 2.2 使用场景 +1. 添加新朋友后,立即录入其生日信息 +2. 提前收到生日提醒,有时间准备礼物或祝福 +3. 查看近期即将到来的纪念日 +4. 回顾和添加各种纪念日(结婚、恋爱、重要事件等) + +--- + +## 3. 功能需求 + +### 3.1 核心功能(MVP) + +#### 3.1.1 人员信息管理 +**功能描述**: 用户可以添加、编辑、删除人员信息 + +**详细信息**: +- **人员信息字段**: + - 姓名(必填) + - 昵称(可选) + - 备注(可选) + - 头像(可选,可使用默认头像) + +- **操作功能**: + - 新增人员 + - 编辑人员信息 + - 删除人员(需二次确认) + - 搜索人员(按姓名搜索) + +**页面设计**: +- 人员列表页:卡片式布局,显示头像、姓名、最新生日信息 +- 人员详情页:显示完整信息及所有关联的纪念日 + +--- + +#### 3.1.2 纪念日管理 +**功能描述**: 为人员添加生日或其他纪念日 + +**纪念日信息字段**: +- 纪念日类型(必填): + - 公历生日 + - 农历生日 + - 结婚纪念日 + - 订婚纪念日 + - 其他纪念日(自定义名称) + +- 具体日期(必填) + - 公历:年-月-日 + - 农历:年-月-日(自动转换为公历计算下次提醒日期) + +- 重要程度(可选): + - 非常重要(红色标记) + - 重要(橙色标记) + - 一般(灰色标记) + +- 是否提醒(必填): + - 开启提醒/关闭提醒 + +- 提前提醒天数(必填,需开启提醒时): + - 提前3天 + - 提前7天 + - 提前14天 + - 提前30天 + - 自定义天数(1-365天) + +**操作功能**: +- 添加纪念日(关联到指定人员) +- 编辑纪念日信息 +- 删除纪念日(需二次确认) +- 标记已完成(当天查看后自动标记) + +--- + +#### 3.1.3 提醒功能 +**功能描述**: 智能提醒系统主动通知即将到来的纪念日 + +**提醒机制**: +- **推送提醒**: 在纪念日到达设定提前天数时推送通知 +- **每日提醒**: 每天早上8:00推送当天即将到来的纪念日 +- **提醒内容**: + - 人员姓名和头像 + - 纪念日类型 + - 距离具体日期的天数 + - 上次备注信息 + +**提醒设置**: +- 全局提醒开关 +- 单个纪念日提醒开关 +- 提醒时间设置(默认早上8:00) +- 提醒频率设置(仅提前提醒/每日提醒) + +--- + +#### 3.1.4 日历视图 +**功能描述**: 以日历形式展示所有纪念日 + +**视图模式**: +- **月视图**: 显示当月所有纪念日,按日期排序 +- **列表视图**: 按时间顺序显示即将到来的纪念日(最近1-3个月) +- **筛选功能**: 按纪念日类型、重要程度筛选 + +**交互功能**: +- 点击日期查看当天所有纪念日 +- 左右滑动切换月份 +- 回到今天按钮 + +--- + +### 3.2 高级功能(后续迭代) + +#### 3.2.1 统计功能 +- 年度统计:查看全年纪念日概览 +- 人员维度:查看某人所有纪念日 +- 类型统计:各类纪念日占比 + +#### 3.2.2 提醒历史 +- 查看历史提醒记录 +- 查看已完成的纪念日记录 +- 祝福记录(记录了哪些祝福内容) + +#### 3.2.3 导入导出 +- 支持批量导入人员信息(Excel/CSV) +- 导出数据备份 +- 导入数据恢复 + +#### 3.2.4 社交功能 +- 生日祝福模板 +- 礼物建议 +- 分享功能(分享生日提醒给家人朋友) + +--- + +## 4. 技术需求 + +### 4.1 平台选择 +**建议**: 微信小程序(初始版本) +- **优势**: + - 用户基数大,无需下载App + - 开发成本低 + - 支持推送通知 + - 跨平台兼容 +- **备选**: 也可以考虑开发移动App(React Native/Flutter) + +### 4.2 技术架构 + +#### 4.2.1 前端技术栈 +- **框架**: 微信小程序原生框架 / Taro / uni-app +- **UI组件**: ColorUI / Vant Weapp +- **状态管理**: MobX / Redux + +#### 4.2.2 后端技术栈(如需服务端) +- **方案一**: 纯客户端存储(轻量级,无需后端) + - 使用微信小程序的本地存储(localStorage) + - 最多存储10MB数据 + +- **方案二**: 云端存储(数据备份和同步) + - Node.js + Express + - 数据库: MySQL / MongoDB + - 云服务器: 腾讯云/阿里云 + +#### 4.2.3 农历计算 +- **核心功能**: 农历转公历、公历转农历 +- **技术方案**: 使用现成的农历计算库 + - JavaScript: `lunar-javascript` + - Python: `lunarcalendar` + - 小程序: `@lunar-js/calendar` + +--- + +### 4.3 数据模型设计 + +#### 4.3.1 人员表 (Person) +```javascript +{ + id: String, // 唯一标识 + name: String, // 姓名(必填) + nickname: String, // 昵称 + avatar: String, // 头像URL + remark: String, // 备注 + createTime: Date, // 创建时间 + updateTime: Date // 更新时间 +} +``` + +#### 4.3.2 纪念日表 (Anniversary) +```javascript +{ + id: String, // 唯一标识 + personId: String, // 关联人员ID + type: String, // 纪念日类型 + customTypeName: String, // 自定义类型名称(当type为"其他"时) + + // 日期信息 + isLunar: Boolean, // 是否农历(true=农历,false=公历) + lunarYear: Number, // 农历年份 + lunarMonth: Number, // 农历月份 + lunarDay: Number, // 农历日期 + solarYear: Number, // 公历年份 + solarMonth: Number, // 公历月份 + solarDay: Number, // 公历日期 + + // 提醒设置 + remindEnabled: Boolean, // 是否开启提醒 + remindDays: Number, // 提前提醒天数 + lastRemindTime: Date, // 上次提醒时间 + + // 其他信息 + importance: String, // 重要程度 + remark: String, // 备注 + createTime: Date, // 创建时间 + updateTime: Date // 更新时间 +} +``` + +#### 4.3.3 提醒记录表 (RemindHistory) +```javascript +{ + id: String, // 唯一标识 + anniversaryId: String, // 关联纪念日ID + remindDate: Date, // 提醒日期 + remindType: String, // 提醒类型(提前提醒/当日提醒) + isRead: Boolean, // 是否已读 + createTime: Date // 创建时间 +} +``` + +--- + +## 5. 非功能需求 + +### 5.1 性能需求 +- **加载速度**: 页面加载时间 < 1秒 +- **操作响应**: 用户操作响应时间 < 300ms +- **数据存储**: 支持存储至少1000条纪念日数据 + +### 5.2 可用性需求 +- **界面设计**: 简洁美观,符合主流UI设计规范 +- **操作流程**: 核心功能不超过3步完成 +- **错误提示**: 友好的错误提示和处理 + +### 5.3 可靠性需求 +- **数据安全**: 本地数据加密存储 +- **数据备份**: 支持导出备份,防止数据丢失 +- **异常处理**: 完善的异常捕获和处理机制 + +### 5.4 兼容性需求 +- **系统版本**: 支持微信小程序最低版本要求 +- **机型适配**: 适配主流手机屏幕尺寸 + +--- + +## 6. 交互流程 + +### 6.1 核心流程图 + +#### 流程1: 添加新人员及纪念日 +``` +首页 → 点击"+"按钮 → 选择"添加人员" → 填写人员信息 → 保存 → 自动进入添加纪念日页面 → 选择纪念日类型 → 选择日期(公历/农历) → 设置提醒 → 保存 → 返回列表 +``` + +#### 流程2: 查看即将到来的纪念日 +``` +首页 → 查看日历视图 / 列表视图 → 点击纪念日卡片 → 查看详情 → 可编辑/删除 +``` + +#### 流程3: 接收提醒 +``` +系统定时检查 → 发现即将到来的纪念日 → 发送推送通知 → 用户点击通知 → 跳转到详情页 → 查看信息 +``` + +--- + +### 6.2 页面结构 + +``` +├── 首页(人员列表) +│ ├── 顶部搜索栏 +│ ├── 筛选按钮(按类型/时间) +│ ├── 人员卡片列表 +│ └── 底部"+"添加按钮 +│ +├── 人员详情页 +│ ├── 人员基本信息 +│ ├── 纪念日列表 +│ └── 操作按钮(编辑/删除) +│ +├── 添加/编辑人员页 +│ ├── 姓名输入 +│ ├── 昵称输入 +│ ├── 头像选择 +│ └── 备注输入 +│ +├── 添加/编辑纪念日页 +│ ├── 关联人员选择 +│ ├── 纪念日类型选择 +│ ├── 日期选择器(公历/农历切换) +│ ├── 重要程度选择 +│ ├── 提醒开关 +│ └── 提前天数设置 +│ +├── 日历视图页 +│ ├── 日历头部 +│ ├── 日历网格 +│ ├── 当日纪念日列表 +│ └── 筛选选项 +│ +└── 设置页 + ├── 提醒设置 + ├── 数据备份 + ├── 关于 + └── 使用帮助 +``` + +--- + +## 7. 开发计划 + +### 7.1 第一阶段(MVP - 2周) +- [x] 项目初始化 +- [ ] 基础UI搭建 +- [ ] 人员信息管理(增删改查) +- [ ] 纪念日管理(增删改查) +- [ ] 农历日期计算 +- [ ] 本地数据存储 +- [ ] 基本的列表和详情展示 + +### 7.2 第二阶段(核心功能 - 2周) +- [ ] 日历视图实现 +- [ ] 提醒功能实现 +- [ ] 数据筛选和搜索 +- [ ] 导入导出功能 + +### 7.3 第三阶段(优化迭代 - 1周) +- [ ] UI美化 +- [ ] 性能优化 +- [ ] 用户体验优化 +- [ ] 测试和Bug修复 + +--- + +## 8. 风险评估 + +### 8.1 技术风险 +- **农历计算准确性**: 使用成熟的农历计算库 +- **数据存储限制**: 小程序本地存储10MB上限 +- **提醒功能实现**: 小程序后台限制 + +### 8.2 解决方案 +- 采用成熟的农历计算库 +- 定期提示用户导出数据备份 +- 使用云开发或后端服务支持提醒功能 + +--- + +## 9. 附录 + +### 9.1 参考资源 +- 微信小程序官方文档: https://developers.weixin.qq.com/miniprogram/dev/framework/ +- 农历计算库: https://github.com/lunar-js/lunar-calendar + +### 9.2 成功指标 +- **用户留存率**: 30日留存 > 40% +- **活跃度**: 每日打开率 > 50% +- **功能使用**: 80%用户成功添加至少5条纪念日 + +--- + +## 10. 总结 + +这是一款专注于用户核心需求、功能简洁实用的纪念日管理小程序。通过支持农历生日、灵活的提醒设置和简单的操作流程,为用户提供贴心的纪念日管理服务。 + +**核心亮点**: +✅ 支持农历生日(中国特色) +✅ 个性化提醒设置 +✅ 多种纪念日类型 +✅ 简洁美观的界面 +✅ 无需服务器(轻量级) + +--- + +**文档版本**: v1.0 +**创建日期**: 2024年 +**最后更新**: 2024年 + diff --git a/README.md b/README.md new file mode 100644 index 0000000..08c1b31 --- /dev/null +++ b/README.md @@ -0,0 +1,225 @@ +# 生日提醒小程序 + +一款轻量级、易用的个人纪念日管理小程序,帮助用户记录和提醒重要的生日、节日和纪念日。 + +## 📋 功能特性 + +### 核心功能 + +1. **人员信息管理** + - 添加、编辑、删除人员信息 + - 支持姓名、昵称、备注、头像 + - 快速搜索和筛选 + +2. **纪念日管理** + - 支持公历和农历生日 + - 多种纪念日类型(生日、结婚纪念日、订婚纪念日等) + - 自定义纪念日类型 + - 设置重要程度(非常重要/重要/一般) + +3. **智能提醒** + - 灵活设置提醒时间(提前3/7/14/30天或自定义) + - 支持开启/关闭提醒 + - 近期纪念日一目了然 + +4. **日历视图** + - 月历展示所有纪念日 + - 本月纪念日列表 + - 快速跳转到指定日期 + +5. **数据管理** + - 导出数据备份(复制到剪贴板) + - 导入数据恢复 + - 清空所有数据 + +## 🚀 快速开始 + +### 环境要求 + +- 微信开发者工具 +- Node.js(如果需要) + +### 安装步骤 + +1. **克隆或下载项目** + ```bash + git clone <项目地址> + cd 生日提醒小程序 + ``` + +2. **打开微信开发者工具** + - 打开微信开发者工具 + - 选择"导入项目" + - 选择项目目录 + - AppID填写:`touristappid`(测试号) + +3. **运行项目** + - 点击"编译"按钮 + - 在模拟器中查看效果 + +### 配置说明 + +#### app.json 配置 +- `pages`: 页面路径配置 +- `tabBar`: 底部导航栏配置 +- `window`: 窗口配置 + +#### project.config.json 配置 +- 根据实际开发需求修改 `appid` + +## 📁 项目结构 + +``` +生日提醒小程序/ +├── app.js # 小程序入口文件 +├── app.json # 全局配置 +├── app.wxss # 全局样式 +├── project.config.json # 项目配置 +├── sitemap.json # 站点地图 +├── pages/ # 页面目录 +│ ├── index/ # 首页(人员列表) +│ ├── person-detail/ # 人员详情 +│ ├── add-person/ # 添加/编辑人员 +│ ├── add-anniversary/ # 添加/编辑纪念日 +│ ├── calendar/ # 日历视图 +│ └── settings/ # 设置页面 +└── utils/ # 工具类 + ├── storage.js # 数据存储 + ├── lunar.js # 农历转换 + └── date.js # 日期工具 +``` + +## 🎨 页面功能说明 + +### 1. 首页(人员列表) +- 显示所有已添加的人员 +- 搜索和筛选功能 +- 显示最近的纪念日和倒计时 +- 浮动按钮快速添加 + +### 2. 人员详情页 +- 展示人员完整信息 +- 显示该人员的所有纪念日 +- 编辑和删除操作 + +### 3. 添加人员页 +- 输入姓名、昵称、备注 +- 上传头像 +- 保存到本地存储 + +### 4. 添加纪念日页 +- 选择关联人员 +- 选择纪念日类型 +- 选择日期(公历/农历) +- 设置重要程度 +- 配置提醒设置 + +### 5. 日历页 +- 月历视图 +- 标记有纪念日的日期 +- 本月纪念日列表 + +### 6. 设置页 +- 导出/导入数据 +- 清空数据 +- 关于信息 + +## 💾 数据存储 + +项目使用微信小程序的本地存储功能: +- `wx.getStorageSync()` - 同步读取数据 +- `wx.setStorageSync()` - 同步存储数据 +- 最大存储容量:10MB + +数据结构: +```javascript +// 人员数据 +{ + id: String, + name: String, + nickname: String, + avatar: String, + remark: String, + createTime: Number, + updateTime: Number +} + +// 纪念日数据 +{ + id: String, + personId: String, + type: String, + customTypeName: String, + isLunar: Boolean, + solarYear: Number, + solarMonth: Number, + solarDay: Number, + importance: String, + remindEnabled: Boolean, + remindDays: Number, + remark: String, + createTime: Number, + updateTime: Number +} +``` + +## ⚠️ 注意事项 + +1. **农历功能** + - 当前使用简化版的农历转换算法 + - 建议使用成熟的农历库(如 `lunar-javascript`)替换 + +2. **提醒功能** + - 小程序不支持后台定时任务 + - 需要在前台运行时才能触发提醒 + - 建议使用云开发或服务器来实现真正的推送通知 + +3. **数据备份** + - 导出功能会将数据复制到剪贴板 + - 建议定期导出备份,防止数据丢失 + - 导入时会覆盖现有数据 + +4. **头像上传** + - 当前使用本地临时路径 + - 如需持久化,需要上传到云存储或服务器 + +## 🔧 开发建议 + +### 功能扩展 + +1. **农历转换优化** + - 使用 `lunar-javascript` 库 + - 实现准确的农历转公历计算 + +2. **提醒功能增强** + - 使用云开发或后端服务 + - 实现真正的推送通知 + - 支持定时提醒 + +3. **数据同步** + - 添加云存储支持 + - 多设备数据同步 + - 数据加密 + +4. **UI优化** + - 添加更多的图标资源 + - 优化动画效果 + - 支持暗色模式 + +## 📄 许可证 + +MIT License + +## 🤝 贡献 + +欢迎提交 Issue 和 Pull Request! + +## 📞 联系方式 + +如有问题或建议,请提交 Issue。 + +--- + +**最后更新**: 2024年 +**版本**: v1.0.0 + diff --git a/app.js b/app.js new file mode 100644 index 0000000..c0460e7 --- /dev/null +++ b/app.js @@ -0,0 +1,27 @@ +App({ + onLaunch() { + // 展示本地存储能力 + const logs = wx.getStorageSync('logs') || [] + logs.unshift(Date.now()) + wx.setStorageSync('logs', logs) + + // 初始化数据 + this.initData() + }, + + // 初始化数据结构 + initData() { + // 检查是否有旧数据 + const persons = wx.getStorageSync('persons') || [] + const anniversaries = wx.getStorageSync('anniversaries') || [] + + if (persons.length === 0 && anniversaries.length === 0) { + console.log('初始化数据结构') + } + }, + + globalData: { + userInfo: null + } +}) + diff --git a/app.json b/app.json new file mode 100644 index 0000000..e8333a6 --- /dev/null +++ b/app.json @@ -0,0 +1,46 @@ +{ + "pages": [ + "pages/index/index", + "pages/person-detail/person-detail", + "pages/add-person/add-person", + "pages/add-anniversary/add-anniversary", + "pages/calendar/calendar", + "pages/settings/settings" + ], + "window": { + "backgroundTextStyle": "light", + "navigationBarBackgroundColor": "#fff", + "navigationBarTitleText": "生日提醒", + "navigationBarTextStyle": "black", + "backgroundColor": "#f5f5f5" + }, + "tabBar": { + "color": "#7A7E83", + "selectedColor": "#3cc51f", + "borderStyle": "black", + "backgroundColor": "#ffffff", + "list": [ + { + "pagePath": "pages/index/index", + "iconPath": "/images/home.png", + "selectedIconPath": "/images/home-active.png", + "text": "首页" + }, + { + "pagePath": "pages/calendar/calendar", + "iconPath": "/images/calendar.png", + "selectedIconPath": "/images/calendar-active.png", + "text": "日历" + }, + { + "pagePath": "pages/settings/settings", + "iconPath": "/images/settings.png", + "selectedIconPath": "/images/settings-active.png", + "text": "设置" + } + ] + }, + "style": "v2", + "sitemapLocation": "sitemap.json" +} + diff --git a/app.wxss b/app.wxss new file mode 100644 index 0000000..be0934b --- /dev/null +++ b/app.wxss @@ -0,0 +1,101 @@ +/**app.wxss**/ +.container { + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + padding: 200rpx 0; + box-sizing: border-box; +} + +/* 全局样式 */ +page { + background-color: #f5f5f5; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', + 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +/* 通用容器 */ +.content { + padding: 40rpx; +} + +/* 按钮样式 */ +.btn { + border-radius: 8rpx; + font-size: 32rpx; + padding: 24rpx 48rpx; +} + +.btn-primary { + background-color: #07c160; + color: #fff; +} + +.btn-secondary { + background-color: #fff; + color: #333; + border: 1px solid #ddd; +} + +/* 卡片样式 */ +.card { + background-color: #fff; + border-radius: 16rpx; + padding: 32rpx; + margin-bottom: 24rpx; + box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08); +} + +/* 输入框样式 */ +.input { + background-color: #fff; + padding: 24rpx; + border-radius: 8rpx; + border: 1px solid #e0e0e0; + font-size: 28rpx; +} + +/* 分割线 */ +.divider { + height: 1rpx; + background-color: #f0f0f0; + margin: 32rpx 0; +} + +/* 空状态 */ +.empty-state { + text-align: center; + padding: 120rpx 40rpx; + color: #999; +} + +.empty-state .icon { + font-size: 120rpx; + margin-bottom: 32rpx; +} + +.empty-state .text { + font-size: 28rpx; + color: #999; +} + +/* 浮动按钮 */ +.fab { + position: fixed; + bottom: 120rpx; + right: 40rpx; + width: 100rpx; + height: 100rpx; + border-radius: 50%; + background-color: #07c160; + color: #fff; + display: flex; + align-items: center; + justify-content: center; + font-size: 60rpx; + box-shadow: 0 8rpx 24rpx rgba(7, 193, 96, 0.3); + z-index: 100; +} + diff --git a/images/.gitkeep b/images/.gitkeep new file mode 100644 index 0000000..b465730 --- /dev/null +++ b/images/.gitkeep @@ -0,0 +1,7 @@ +# 图片资源目录 +# 请在此目录放置以下图片文件: +# - home.png / home-active.png (首页图标) +# - calendar.png / calendar-active.png (日历图标) +# - settings.png / settings-active.png (设置图标) +# - default-avatar.png (默认头像) + diff --git a/pages/add-anniversary/add-anniversary.js b/pages/add-anniversary/add-anniversary.js new file mode 100644 index 0000000..ffad185 --- /dev/null +++ b/pages/add-anniversary/add-anniversary.js @@ -0,0 +1,263 @@ +// add-anniversary.js +const storage = require('../../utils/storage') +const dateUtils = require('../../utils/date') + +Page({ + data: { + anniversaryId: null, + personId: null, + personList: [], + personIndex: 0, + selectedPerson: '', + typeList: ['公历生日', '农历生日', '结婚纪念日', '订婚纪念日', '其他纪念日'], + typeIndex: 0, + showCustomType: false, + dateValue: '', + remindDaysList: ['提前3天', '提前7天', '提前14天', '提前30天', '自定义'], + remindDaysIndex: 0, + formData: { + isLunar: false, + type: 'birthday', + customTypeName: '', + solarYear: '', + solarMonth: '', + solarDay: '', + lunarYear: '', + lunarMonth: '', + lunarDay: '', + importance: 'low', + remindEnabled: true, + remindDays: 7, + remark: '' + } + }, + + onLoad(options) { + // 获取人员列表 + const persons = storage.getPersons() + this.setData({ personList: persons }) + + if (options.personId) { + // 从人员详情页进入 + const index = persons.findIndex(p => p.id === options.personId) + if (index !== -1) { + this.setData({ + personIndex: index, + personId: options.personId, + selectedPerson: persons[index].name + }) + } + } + + if (options.id) { + // 编辑模式 + this.setData({ anniversaryId: options.id }) + this.loadAnniversary(options.id) + } else { + // 设置默认日期为今天 + const today = new Date() + this.setData({ + dateValue: dateUtils.formatDate(today, 'YYYY-MM-DD') + }) + } + }, + + /** + * 加载纪念日信息(编辑模式) + */ + loadAnniversary(id) { + const anniversaries = storage.getAnniversaries() + const anniversary = anniversaries.find(a => a.id === id) + + if (anniversary) { + const date = dateUtils.formatDate( + new Date(anniversary.solarYear, anniversary.solarMonth - 1, anniversary.solarDay), + 'YYYY-MM-DD' + ) + + // 设置类型 + const typeIndex = this.getTypeIndex(anniversary.type) + + this.setData({ + formData: anniversary, + dateValue: date, + typeIndex, + showCustomType: anniversary.type === 'other' + }) + + wx.setNavigationBarTitle({ title: '编辑纪念日' }) + } + }, + + /** + * 获取类型索引 + */ + getTypeIndex(type) { + const indexMap = { + birthday: 0, + lunar_birthday: 1, + wedding: 2, + engagement: 3, + other: 4 + } + return indexMap[type] || 0 + }, + + /** + * 选择人员 + */ + onPersonChange(e) { + const index = parseInt(e.detail.value) + const person = this.data.personList[index] + this.setData({ + personIndex: index, + personId: person.id, + selectedPerson: person.name + }) + }, + + /** + * 选择类型 + */ + onTypeChange(e) { + const index = parseInt(e.detail.value) + const types = ['birthday', 'lunar_birthday', 'wedding', 'engagement', 'other'] + const isOther = index === 4 + + this.setData({ + typeIndex: index, + showCustomType: isOther, + 'formData.type': types[index] + }) + }, + + /** + * 自定义类型输入 + */ + onCustomTypeInput(e) { + this.setData({ + 'formData.customTypeName': e.detail.value + }) + }, + + /** + * 日期类型改变 + */ + onDateTypeChange(e) { + const isLunar = e.detail.value === 'lunar' + this.setData({ + 'formData.isLunar': isLunar + }) + }, + + /** + * 日期改变 + */ + onDateChange(e) { + const dateStr = e.detail.value + const parts = dateStr.split('-') + + this.setData({ + dateValue: dateStr, + 'formData.solarYear': parseInt(parts[0]), + 'formData.solarMonth': parseInt(parts[1]), + 'formData.solarDay': parseInt(parts[2]) + }) + }, + + /** + * 重要程度改变 + */ + onImportanceChange(e) { + this.setData({ + 'formData.importance': e.detail.value + }) + }, + + /** + * 提醒开关改变 + */ + onRemindEnabledChange(e) { + this.setData({ + 'formData.remindEnabled': e.detail.value + }) + }, + + /** + * 提醒天数改变 + */ + onRemindDaysChange(e) { + const index = parseInt(e.detail.value) + const days = [3, 7, 14, 30, 7][index] + this.setData({ + remindDaysIndex: index, + 'formData.remindDays': days + }) + }, + + /** + * 备注改变 + */ + onRemarkChange(e) { + this.setData({ + 'formData.remark': e.detail.value + }) + }, + + /** + * 取消 + */ + onCancel() { + wx.navigateBack() + }, + + /** + * 提交 + */ + onSubmit() { + const { formData, personId, anniversaryId } = this.data + + // 验证关联人员 + if (!personId) { + wx.showToast({ title: '请选择关联人员', icon: 'none' }) + return + } + + // 验证日期 + if (!formData.solarYear || !formData.solarMonth || !formData.solarDay) { + wx.showToast({ title: '请选择日期', icon: 'none' }) + return + } + + // 验证自定义类型 + if (formData.type === 'other' && !formData.customTypeName) { + wx.showToast({ title: '请输入自定义类型', icon: 'none' }) + return + } + + if (anniversaryId) { + // 编辑模式 + const success = storage.updateAnniversary(anniversaryId, { + personId, + ...formData + }) + + if (success) { + wx.showToast({ title: '保存成功', icon: 'success' }) + setTimeout(() => wx.navigateBack(), 1500) + } + } else { + // 新增模式 + const newAnniversary = storage.addAnniversary({ + personId, + ...formData + }) + + if (newAnniversary) { + wx.showToast({ title: '添加成功', icon: 'success' }) + setTimeout(() => wx.navigateBack(), 1500) + } + } + } +}) + diff --git a/pages/add-anniversary/add-anniversary.wxml b/pages/add-anniversary/add-anniversary.wxml new file mode 100644 index 0000000..bd9dc9f --- /dev/null +++ b/pages/add-anniversary/add-anniversary.wxml @@ -0,0 +1,101 @@ + + + + + + 关联人员 + + + {{selectedPerson}} + 请选择关联人员 + + + + + + + + 纪念日类型 + + + {{typeList[typeIndex]}} + + + + + + + + + 日期类型 + + + + + + + + + 日期 + + + {{dateValue || '请选择日期'}} + + + + + + + + 重要程度 + + + + + + + + + + + 开启提醒 + + + + + + 提前{{formData.remindDays}}天提醒 + + + + + + + + 备注 +