news 2026/10/1 18:10:52

【AI实战篇】使用Codex制作读取iPhone日历到window桌面的事务展示工具(一)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【AI实战篇】使用Codex制作读取iPhone日历到window桌面的事务展示工具(一)

我目前还只是一名学生,为了追求更好的性能,电脑选择了游戏本,手机则买了 iPhone。我发现苹果自带的日历软件特别好用,无论是界面设计还是各项功能,用起来都极其舒适。因此,我希望电脑上也能拥有类似的能力——既能同步手机的日历数据,又能更方便地管理日程,实现手机端难以完成的操作。接下来,我将尝试用 Codex + DeepSeek 打造这样一个应用。

前情提要:苹果日历的ui和功能还是太好用了


这个日历程序,无论是我上课使用,还是登记一些重要的事件,都很有用。而且界面十分清晰明了,还能顺手标注上课地点,这对于上了一个学期还不知道课室在哪的人简直是福音。

很快我就发现了一个问题:每学期开学时,我都需要把日期一个个手动输入进去,还要设置重复时间、地址以及其他信息,整个过程繁琐且缺乏更优雅的添加方式。此外,我也无法在电脑上方便快捷地查看或修改我的日历项目(Windows 网页版 iCloud 的逻辑性太差了,每次想右键添加内容都不行)。我还希望能有一个悬浮窗口固定在桌面最底层,让我随时打开就能看到日历。

心中有许多想法,接下来我将尝试通过 AI 编程的方式来实现上述功能。

尝试建立AGENTS.md,规范ai行为以及输出内容

在之前尝试使用AI编程的时候,经常遇到ai自顾自的行动导致文件损坏,当时又没有使用git的习惯只能用更多的时间尝试让代码退化到前一个阶段,浪费了许多时间。
现在我使用一个AGENTS.md,用这个文件链接到codex中,让他始终遵守我给他指定的规则。

我将会在后面的编写过程中不断补充这个文档。

将AGENTS放到文件夹中,并让ai根据规则生成初步功能

先尝试能不能实现电脑链接到iCloud获取日历信息

登入apple账号->获取专属key->设置环境变量->安装caldav库

首先让他做了一个程序,保证了确实能够读取我日历里的信息并展示给我,我才让他做后续的动作

我的想法是先初步做一个简易的网页,实现我最初想要的在电脑上便捷阅读日历的功能(其实提示词也是按照我的想法让ds扩充的)

给 Codex 的后续任务提示词 当前状态确认 Python 脚本 icloud_calendar_probe.py 已验证成功: - 能通过 CalDAV 连上 iCloud 日历 - 能列出所有日历名称 - 能拉取并打印未来 7 天的事件 - 认证信息从环境变量读取,无硬编码 技术验证阶段结束。 本次任务:制作网页版 目标 做一个最简单的网页,在浏览器里展示 iCloud 日历未来 7 天的事件。 不需要复杂功能,只需要“打开网页就能看到日程”。 具体需求 1. 技术方案 - 推荐:Python 后端(Flask/FastAPI)+ 简单前端 HTML - 后端复用已验证的 CalDAV 逻辑,提供 JSON API - 前端用原生 HTML/JS,不引入框架 2. 后端要求 - 提供一个 API 接口,返回未来 7 天事件(JSON 格式) - 复用现有 icloud_calendar_probe.py 中的 CalDAV 连接逻辑 - 认证信息继续从环境变量读取 - 字段包含:日历名、事件标题、开始时间、结束时间 3. 前端要求 - 一个 HTML 页面,按日期分组展示事件 - 样式参考文件夹内的苹果设计的md 按照那个样式制作 - 打开页面自动加载数据,不需要手动点击按钮 4. 部署准备 - 代码结构要能直接部署到 Cloudflare Pages 或类似平台 - 说明本地怎么运行(装依赖、启动命令) 必须遵守(Always) - 认证信息从环境变量读取,绝不硬编码 - 先给出完整可运行的代码,再解释关键部分 - 后端代码复用已有的 CalDAV 逻辑,不重复造轮子 先问再做(Ask First) - 引入除 Flask/FastAPI 之外的新依赖 - 改变数据返回格式 - 添加超出“展示未来 7 天事件”范围的功能 绝不越界(Never) - 写复杂 UI 或引入前端框架 - 设计数据库 - 添加用户登录系统 - 添加超出本次任务范围的功能 - 把 Apple ID、App 专用密码写进代码 输出格式 1. 项目文件结构(列出要创建哪些文件) 2. 完整代码(后端 + 前端) 3. 本地运行步骤(装依赖、设环境变量、启动命令) 4. 后续部署到 Cloudflare Pages 的简要说明 完成标准 - 本地运行后,浏览器打开能看到未来 7 天的事件 - 事件按日期分组,显示标题和时间 - 所有敏感信息来自环境变量 - 代码结构清晰,方便后续部署

按照提示词成功生成出了第一版结果

很失望啊,没有想象中的完美,功能也不是按照我想法走。
我到这就理解了,为什么网上的人都在讲要给ai如此详细的提示词,还有网上的提示词工程教学的意义。

## 当前版本 - 版本:v3.0 日历功能升级版 - 状态:已完成两个月缓存、10 分钟后台增量同步、手动刷新、字体设置、超长全天日程压缩和事件编辑。 - 验证:Python、JavaScript 和 HTML 检查通过;缓存首次同步、缓存命中、增量更新、删除、令牌失效回退、POST 新增和 PUT 编辑均已使用模拟 CalDAV 验证。 ## 项目背景 - 通过 CalDAV 读取 iCloud 日历,并在网页中展示。 - 运行环境:Windows 本地开发。 - 后端入口:`app.py`。 - 前端入口:`index.html`,使用原生 HTML、CSS 和 JavaScript。 ## 当前结构 - `icloud_calendar_probe.py`:已验证的 CalDAV 连接和事件解析逻辑。 - `app.py`:Flask 服务,提供 `/api/events` 并托管前端。 - `index.html`:日、周、月三种日历视图。 - `requirements.txt`:Flask 和 caldav 依赖。 - `APPLE_DESIGN.md`:页面视觉设计参考。 ## 必须遵守(Always) - CalDAV 认证使用 App 专用密码,从环境变量读取,绝不硬编码。 - 每次改动后代码必须能直接运行,无语法错误。 - 前端继续使用原生 HTML、CSS 和 JavaScript,不引入前端框架。 - 后端继续复用 `icloud_calendar_probe.py` 的 CalDAV 查询和解析逻辑。 - API 保持 `{ "events": [...] }` 结构;事件字段为 `calendar`、`title`、`start`、`end`、可选 `location` 和 `uid`。 - `GET /api/events` 支持可选 `start`、`end` 参数,格式为 `YYYY-MM-DD`;默认范围是今天前后各 30 天。 - `POST /api/events` 只用于新增日程,通过 CalDAV 写入 iCloud。 - `PUT /api/events/<uid>` 只用于编辑非循环日程;循环事件暂时不支持编辑。 - `POST /api/refresh` 手动触发缓存增量刷新。 ## 先问再做(Ask First) - 引入任何新的第三方依赖。 - 修改 CalDAV 查询的时间范围。 - 修改 `/api/events` 的返回结构或字段含义。 - 添加事件删除、登录、数据库或其他超出上述功能范围的功能。 ## 绝不越界(Never) - 把 Apple ID、App 专用密码、Token 写进代码或提交到 Git。 - 使用 eventkit-js 等只能在 macOS 运行的库。 - 一次修改超过 3 个文件。 - 实现事件删除功能。 - 提交 `.venv`、`__pycache__`、本地缓存或任何敏感配置。 ## 当前功能边界 - `/api/events` 默认查询今天前后各 30 天;前端离开已加载范围时会按视图范围重新请求。 - 日、周、月视图共用同一份事件数据;视图范围超出缓存时自动请求新范围。 - 月视图按周日至周六排列,支持跨天事件横条。 - 周视图和日视图显示 00:00 至 24:00 的可滚动时间轴;全天事件单独显示。 - 时间重叠事件使用嵌套偏移展示,不再左右分列。 - 日历筛选由左侧复选框控制,不影响后端数据。 - 「计划」与「计划/作业」统一显示为「计划/作业」。 - 事件支持双击编辑非循环日程,不支持删除。 - `events_cache.json` 和 `sync_token.json` 是本地缓存,必须保持在 `.gitignore` 中。 - 字体大小与连续日程压缩阈值保存在浏览器 localStorage。 - 日历颜色内置映射:个人为绿色、家庭为黄色、课程为红色/粉色、课外为橙色、计划/作业为紫色,其他日历使用稳定的备用颜色。 ## 本地运行

这份是截稿时的AGENTS.md文件,设置的功能边界有ai一遍遍加进去的,也有我手动修订思考的

后面我们在配置日历信息的时候,发现需要配置iCloud密钥。
我是要将信息上传到GitHub上,密钥这种东西泄露怎么想都不像什么好事。
发现有上传到环境变量的操作,可以让重要的信息例如密码之类的不会直接出现在程序中,但也能让电脑读取到。
接下来就去研究环境变量…

设置环境变量

首先要知道环境变量是什么,为什么会有这个东西存在

简单来说,环境变量是操作系统或程序用来存储“配置信息”的一组“键值对”。你可以把它理解成电脑里的“公共便签”或“全局备忘录”。

它由变量名和变量值组成,比如:

  • 变量名:PATH
  • 变量值:C:\Windows\System32;C:\Program Files\...

它有什么用?

它的核心作用是告诉系统和程序一些关键信息,让它们知道去哪里找东西、或者当前处于什么状态。常见用途包括:

  • 告诉系统去哪里找可执行程序:这是最常用的功能。比如你在命令行输入java,系统就是靠PATH这个环境变量,去它记录的各个目录里挨个找java.exe。
  • 传递配置信息:比如TEMP变量告诉程序临时文件该放哪;JAVA_HOME告诉其他软件 Java 装在哪。
  • 区分运行环境:比如设置ENV=development或ENV=production,程序读到后就知道该连接测试数据库还是正式数据库。

在 Windows 上怎么查看和修改?

  1. 查看:按Win + R,输入cmd打开命令提示符,输入set回车,就能看到当前所有环境变量。
  2. 图形化修改:右键"此电脑" → “属性” → “高级系统设置” → “环境变量”。这里会看到用户变量(只对当前用户生效)和系统变量(对所有用户生效)。
  3. 命令行修改(临时):在 cmd 里输入set 变量名=值,但关掉窗口就失效了。

一个关键区别:用户变量 vs 系统变量

  • 用户变量:只对你当前登录的账户有效。比如你给自己配的 Python 路径。
  • 系统变量:对电脑上所有用户都有效。通常需要管理员权限才能修改。

上传信息的脚本

# 读取 Apple ID $appleId = Read-Host "请输入 Apple ID" # 隐藏输入 App 专用密码 $securePassword = Read-Host "请输入 App 专用密码" -AsSecureString # 将安全字符串临时转换为设置环境变量所需的值 $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($securePassword) $appPassword = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) # 写入当前 Windows 用户的永久环境变量 [Environment]::SetEnvironmentVariable("ICLOUD_APPLE_ID", $appleId, "User") [Environment]::SetEnvironmentVariable("ICLOUD_APP_PASSWORD", $appPassword, "User") # 清理当前 PowerShell 进程中的临时变量 Remove-Variable appleId, securePassword, appPassword, bstr

运行过程中说我缺少重要库/依赖

运行的时候出现的问题在Jupyter 中运行 app.py 报错,提示找不到 caldav 等依赖。

原因

Jupyter 使用的是系统 Python(例如 D:\Python314\python.exe),
这个解释器没有安装项目依赖。

而项目依赖实际安装在项目的虚拟环境中:
<项目目录>.venv\Scripts\python.exe

该虚拟环境里已安装:

  • caldav
  • Flask

结论

不要把 app.py 粘贴到 Jupyter Cell 里运行。
Flask 服务应该在独立终端中启动。

直接使用虚拟环境的python

cd"<项目目录>"&".\.venv\Scripts\python.exe"".\app.py"

直接双击py文件启动的前提是,系统python环境里安装好了所有的依赖,而且环境变量恰好能读到。一旦有一项不满足就会报错。

命令行启动的核心价值就是能明确指定用哪个python和带什么环境变量,相对可控。

另外,Flask是一个长期运行的程序,启动之后不会自动退出,会在终端中实时打印每个请求,也就是清楚看到有人访问了什么,返回了什么信息。

为什么要使用虚拟环境

  1. 隔离每一个项目的依赖,防止会有某些冲突产生bug,或者有不同版本的库
  2. 系统的Python是操作系统的一部分,乱撞库可能会影响其他程序
  3. 方便迁移,.venv文件夹中存放了所有的依赖,切换环境的时候可以直接读取到,或者使用requirement存放每个库名字和版本,方便复查

我想要某种样式,但是我不会描述给ai怎么办

这个时候就不得不给出skill这一利器。

这里有几乎全球的设计文字稿,能描述出某个品牌平面设计的特点,讲述给ai让他做出类似的效果
https://github.com/VoltAgent/awesome-design-md

或者将大致的效果图给ai,让他生成提示词丢回去给管项目的ai。

可能还是达不到更加具体的效果,但是可以有初步的第一版给出来,后面再按照需求修改。

最后成果

搭好了整体的网站框架,弄懂大致的架构也初步实现了想要的功能(对iCloud日历内容进行增删查改)
也弄清楚了项目内提示词管理,需要给出具体的行为而不是让ai自己想办法解决(可以先去问ai有什么方案,再去做修改)
一共提交了两版git文件,都是通过ai上传的
搞清楚了环境变量的作用,还有为什么每个项目都单独创立虚拟环境运行。
接下来的博客会根据后面项目推进编写,记录我这次的ai编程经历。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 18:10:01

Kubernetes CrashLoopBackOff 排障实战:日志、退出码与根因定位

开年在群里帮一个朋友排查容器反复重启的问题&#xff0c;从下午两点一直弄到晚上八点&#xff0c;最后发现根因居然是镜像里的一个环境变量写错了。这种场景在 Kubernetes 排障里太常见了——Pod 状态卡在 CrashLoopBackOff&#xff0c;日志却往往被截断或者压根没输出&#x…

作者头像 李华
网站建设 2026/10/1 18:08:09

YOLOv8轻量化改进:坐标注意力与EfficientNet结合的车辆检测方案

一、为什么YOLOv8在边缘端“跑不动”? 车辆检测是智能交通系统的核心任务,但把检测模型塞进边缘设备时,开发者往往会遇到一个尴尬的局面:YOLOv8精度够用,但计算开销压不下去。 根据Ultralytics官方文档的基准数据,YOLOv8n的参数量约为3.0M,GFLOPs约为8.1,在桌面GPU上…

作者头像 李华
网站建设 2026/10/1 18:07:51

AI Engineering from Scratch:构建可追溯、可验证的AI系统流水线

1. 这不是“搭积木”&#xff0c;而是亲手锻造AI系统的完整流水线“AI Engineering from Scratch”——这个标题乍看像一句技术宣言&#xff0c;实则是一份沉甸甸的工程契约。它不指代调用几个API、微调一个LoRA权重&#xff0c;更不是在Colab里跑通一段Hugging Face示例代码就…

作者头像 李华
网站建设 2026/10/1 18:07:48

uv:用Rust重写的下一代Python包管理器,从入门到实战

上个月帮朋友清理一台 Windows 上的 Python 环境&#xff0c;他是 ComfyUI 重度用户&#xff0c;扩展管理器怎么都装不上&#xff0c;pip 又抛出一连串externally-managed-environment、pip 无法识别、版本过老的警告。我帮他做的事很简单&#xff1a;把包管理器从 pip 换成 uv…

作者头像 李华
网站建设 2026/10/1 18:07:23

Agent Memory 实战:基于 MCP 与 Docker 构建长期记忆系统

1. 从“hindsight”说起&#xff1a;为什么记忆是 Agent 落地的最后一公里 “hindsight”这个词本身很有意思&#xff0c;字面意思是“事后的洞察力”&#xff0c;也就是我们常说的“后见之明”。把这个词放到 Agent Memory 这个语境里&#xff0c;它指向的东西非常具体&#x…

作者头像 李华