一个以语音交互和自然语言理解为核心的 iOS 日历助手。
用户可以直接说出或输入一句话,让应用理解日程意图、读取苹果日历上下文、生成结构化计划,并在用户确认后安全地写入系统日历。完成任务后,应用会用薯条奖励记录每日进度:普通任务获得普通薯条,重要任务获得沾番茄酱的薯条。
本项目对应七牛云暑期实训营第二批次的题目一:语音版的日历工具。
题目要求开发一个以语音交互为核心的日历管理工具,帮助用户更准确、顺畅地通过语音添加、删除、查看事件和设置提醒。薯条日历在此基础上补充了多轮对话、日历上下文读取、确认后执行、任务完成统计和 AI 分享图片等能力。
传统日历适合精确录入,但用户在真实生活中更习惯用自然语言描述需求,例如:
明天上午 9 点到 10 点安排组会,下午 2 点到 4 点写论文,两个都提前 10 分钟提醒我。
如果仍然要求用户逐个选择日期、时间、提醒和重复规则,记录日程本身就会变成一项额外负担。薯条日历希望把这个过程缩短为一次自然表达,同时保留必要的确认步骤,避免大模型误操作苹果日历。
任务完成后的薯条奖励则把抽象的完成记录变成更直观的反馈。每天最多获得 5 根薯条,既保留轻量的成就感,也避免鼓励用户为了数量堆积琐碎任务。
【超级会员V5】通过百度网盘分享的文件:薯条日历-七牛云... 链接:https://pan.baidu.com/s/1OFxd51f3-dSeI9y-VRorhg?pwd=5hC7 复制这段内容打开「百度网盘APP 即可获取」
- 支持长按语音输入、实时转写、上滑取消和键盘输入
- 支持创建、修改、删除、完成和查询苹果日历事件
- 支持添加和移除日历提醒
- 支持重复日程,例如每周一、三、五固定跑步
- 支持普通问答、日程总结和基于真实日历数据的建议
- 从苹果日历读取今日真实任务和完成状态
- 每日最多获得 5 根薯条
- 普通任务使用普通薯条,重要任务使用番茄酱薯条
- 展示今日完成进度、任务状态、提醒和任务详情
- 支持系统分享入口
- 展示本周薯条、连续完成天数和重要任务数量
- 按周一到周日展示每日薯条盒记录
- AI 根据本周真实日程生成可横向切换的建议卡片
- 支持编辑头像和昵称,并同步到后端
- 支持深色模式
- 支持邮箱注册、登录和图片验证码
- 密码使用 bcrypt 哈希存储
- access token 保存在 iOS Keychain
- 大模型和生图服务默认通过后端代理调用,API Key 不会下发到 App
- 用户仍然可以在设置页切换到自己的模型服务和 API Key
- 读取今日真实任务、完成状态和薯条奖励
- 由大模型生成分享文案和生图提示词
- 通过后端代理调用生图服务生成分享图片
- 使用系统分享面板分享图片和文案
flowchart LR
A["语音或文字输入"] --> B["大模型判断是否读取日历"]
B --> C["EventKit 读取苹果日历上下文"]
C --> D["大模型生成结构化 JSON 计划"]
D --> E["App 展示确认卡片"]
E -->|用户确认| F["EventKit 写入苹果日历"]
E -->|取消或取消勾选| G["不执行对应操作"]
F --> H["今日任务、统计和薯条奖励更新"]
FriesCalendar/
├── FriesCalendar/ # SwiftUI iOS App
│ ├── App/ # App 入口、Tab 导航和根视图
│ ├── Features/ # 首页、日程、个人页、登录和设置
│ ├── Services/ # EventKit、语音、LLM、分享和账号服务
│ ├── Models/ # 日程协议、会话、账号和设置模型
│ ├── Components/ # 通用 SwiftUI 组件
│ └── DesignSystem/ # 颜色、间距、圆角和字体规范
├── backend/ # FastAPI + MySQL 后端
│ ├── app/api/ # 认证、资料、LLM 和生图代理接口
│ ├── app/core/ # 环境变量配置
│ ├── app/db/ # SQLAlchemy 数据库连接和迁移
│ ├── app/models/ # 数据库模型
│ └── app/services/ # 安全、验证码和头像存储
└── docs/images/ # README 实机截图
创建数据库和后端服务账号:
CREATE DATABASE fries_calendar CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'fries_calendar'@'localhost' IDENTIFIED BY 'replace_with_a_strong_password';
GRANT ALL PRIVILEGES ON fries_calendar.* TO 'fries_calendar'@'localhost';
FLUSH PRIVILEGES;如果 MySQL 与后端不在同一台机器,需要将 'localhost' 调整为实际允许访问的主机来源,并确保服务器防火墙只向可信来源开放 MySQL 端口。
cd backend
cp .env.example .env
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt编辑 backend/.env:
DATABASE_URL=mysql+aiomysql://fries_calendar:replace_with_password@127.0.0.1:3306/fries_calendar
JWT_SECRET_KEY=replace_with_a_random_secret_at_least_32_characters_long
LLM_BASE_URL=https://api.deepseek.com
LLM_API_KEY=replace_with_server_side_llm_key
LLM_DEFAULT_MODEL=deepseek-v4-flash
IMAGE_GENERATION_BASE_URL=https://api.siliconflow.cn/v1
IMAGE_GENERATION_API_KEY=replace_with_server_side_image_key
IMAGE_GENERATION_DEFAULT_MODEL=Tongyi-MAI/Z-Image-Turbo本地开发时可以使用热重载:
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000线上部署时不要使用 --reload,建议使用进程管理工具托管服务,例如:
uvicorn app.main:app --host 0.0.0.0 --port 8000如果需要长期运行,可以使用 systemd、supervisor 或容器平台管理进程,并在生产环境中设置 ENVIRONMENT=production。当前演示环境后端地址为:https://lzxz.xyz。
检查后端是否启动成功:
curl http://127.0.0.1:8000/health预期返回:
{"status":"ok"}更多后端接口说明见 backend/README.md。
- 使用 Xcode 打开
FriesCalendar.xcodeproj - 选择 iPhone 模拟器或已连接的 iPhone
- 点击 Run 运行项目
- 首次使用时按系统提示授权日历、麦克风和语音识别权限
App 默认连接线上后端服务:https://lzxz.xyz,可通过 https://lzxz.xyz/health 检查服务状态。如果需要连接本地开发后端,可以在登录页右上角打开服务器设置并修改服务地址;模拟器可使用 http://127.0.0.1:8000,真机需要使用电脑的局域网地址,例如 http://192.168.1.10:8000。
由于 iOS 应用分发需要有效的 Apple Developer 分发证书和对应的 provisioning profile,当前仓库暂不提供可直接安装的 IPA 包。如需体验项目,请使用 Xcode 编译运行。
查找电脑局域网地址:
ipconfig getifaddr en0| 依赖 | 用途 |
|---|---|
| Swift 5 | App 开发语言 |
| SwiftUI | 页面、组件和深色模式 |
| EventKit | 读取和写入苹果日历、日历提醒 |
| Speech | 语音识别和实时转写 |
| AVFoundation | 麦克风录音 |
| PhotosUI | 头像图片选择 |
| UIKit | 系统分享面板和图片处理 |
| Security | Keychain 安全存储 |
iOS App 目前仅使用苹果系统框架,没有额外的 Swift Package 依赖。
| 依赖 | 用途 |
|---|---|
| Python 3 | 后端开发语言 |
| FastAPI | HTTP API 服务 |
| Uvicorn | ASGI 服务启动 |
| SQLAlchemy | 数据库 ORM |
| aiomysql | MySQL 异步驱动 |
| pydantic-settings | 环境变量配置 |
| python-jose | JWT 签发和校验 |
| passlib + bcrypt | 密码哈希 |
| Pillow | 图片验证码和头像处理 |
| httpx | 大模型和生图服务代理请求 |
完整 Python 版本锁定见 backend/requirements.txt。
| 方法 | 路径 | 说明 |
|---|---|---|
GET |
/health |
健康检查 |
GET |
/api/auth/captcha |
获取一次性图片验证码 |
POST |
/api/auth/register |
注册账号 |
POST |
/api/auth/login |
登录账号 |
GET |
/api/auth/me |
获取当前用户 |
GET |
/api/profile/me |
获取头像和昵称 |
PATCH |
/api/profile/me |
修改头像和昵称 |
POST |
/api/llm/chat/completions |
登录用户调用后端大模型代理 |
POST |
/api/images/generations |
登录用户调用后端生图代理 |
- 不要将
backend/.env提交到 Git 仓库 - 不要将数据库密码、JWT 密钥、大模型 Key 或生图 Key 写入 App
- 后端代理接口要求登录用户携带 Bearer token
- App 将 token 和用户自定义 API Key 保存在系统 Keychain
- 日程写入前必须经过用户确认
xcodebuild -quiet \
-project FriesCalendar.xcodeproj \
-scheme FriesCalendar \
-destination "generic/platform=iOS Simulator" \
build



