# 个人工作台、任务与网站

工作台集中展示本机个人任务、网页收藏和最近访问。它不要求先加入企业组织，也没有把任务提交到共享企业后台。iOS 与 Android 共用产品方向，但当前筛选、日期、网址保存和持久化实现存在差异，应按平台理解实际行为。

## 责任与数据边界

| 内容 | iOS | Android |
| --- | --- | --- |
| 任务状态 | `LocalWorkspaceStore.tasks` | `AppState.tasks` 与 `LocalData.tasks()` |
| 收藏 | `bookmarks: [SavedSite]` | `bookmarks` JSON 数组 |
| 最近访问 | `recentSites: [SavedSite]` | `recents` JSON 数组 |
| 落盘方式 | 一份 `workspace.json` 快照，原子替换 | SharedPreferences 中的 JSON 字符串 |
| 是否采用记忆库 AES-GCM | 否 | 否 |
| 账号切换 | 不清除个人工作台数据 | 不清除个人工作台数据 |

上述文件或偏好属于 App 私有存储，但不能据此称为记忆 vault 的加密内容。它们不自动同步到另一台设备，不属于记忆转出 JSON，也不会因为聊天账号退出而删除。设备丢失、清除应用数据或卸载后的恢复不由聊天服务保证。字段和时间编码见[本机数据格式](https://document.thestarline.cn/app/local-data-formats.md)。

共享后台中的 `/enterprise/*` 管理组织、企业成员、频道、企业待办和公告，是独立星企产品的领域。个人任务没有组织 ID、负责人、协作评论、分派、共享或企业审计字段。当前工作台也没有第三方任务自动汇聚；不能由后台路由存在推导出这些前台功能已经可用。

## 任务模型与编辑

| 概念 | iOS 字段 | Android 字段与差异 |
| --- | --- | --- |
| 标识 | `id: UUID` | `id: String`，新建时生成 UUID |
| 标题 | `title: String`，保存前去首尾空白 | `title`，编辑器限制 160 个 UTF-16 代码单元并 trim |
| 说明 | `notes: String` | `notes`，编辑器限制 2,000 个 UTF-16 代码单元并 trim |
| 截止 | `dueDate: Date?`，可选具体日期和时间 | `dueAt`，Unix 毫秒；缺失或 0 表示未设截止 |
| 完成 | `isCompleted: Bool` | `isCompleted: Boolean`，读取缺省 false |
| 关联网页 | `sourceURL: URL?`，有完整输入校验 | 浏览器新建任务时写 `sourceURL` 和网址备注；任务弹窗不提供独立网址编辑框 |
| 创建／修改 | `createdAt`、`updatedAt` | `createdAt`；编辑和勾选完成时写 `updatedAt`，某些初次创建路径可能尚无该键 |

iOS 编辑器要求非空标题，允许补充说明、设置或清除截止时间、调整完成状态及关联 HTTP/HTTPS 网站。初次建任务保留创建时间，后续编辑更新修改时间；保存失败时编辑页保持打开，原输入仍可重试。当前 iOS 编辑器没有 Android 对应的 160／2,000 长度截取，不应把两者当统一协议上限。

Android 用可滚动弹窗编辑名称、备注和到期日。日期选择器把所选日期设为设备时区的 23:59:59、毫秒为 0；清除后保存 `dueAt=0`。保存基于原 JSON 的副本修改可见字段，因此浏览器任务已有的 `sourceURL` 不会仅因打开弹窗而丢失。已存在任务可通过删除确认框移除；取消编辑不提交本次表单。

## 筛选、排序与“今天”

| 行为 | iOS 当前实现 | Android 当前实现 |
| --- | --- | --- |
| 全部待办 | `isCompleted == false` | “待办”同样按完成布尔值过滤 |
| 已完成 | 只包含已完成项 | 同左 |
| 包含已完成与未完成 | 无独立“全部”范围 | “全部”范围 |
| 今天 | 未完成，且截止与设备当前日历为同一天 | 首页按未完成、正数 `dueAt` 不晚于当天末尾选择，包含以前逾期任务 |
| 已逾期 | 未完成且 `dueDate < now`，有独立入口 | 行内可显示逾期颜色，没有独立逾期筛选 |
| 搜索 | 在当前范围内查标题或说明，使用本地标准字符串匹配 | 当前任务页没有搜索框 |
| 列表排序 | 截止时间升序，无截止放末尾；截止相同按创建时间倒序 | 保留内存列表顺序；新任务插前，编辑不重新排序 |

iOS 的“今天”和“已逾期”可以重叠：今天上午截止而尚未完成的任务同时符合两者。没有截止时间的任务仅出现在全部待办或已完成中。工作台今日任务按截止时间排序，最近访问只预览前三项，逾期待办入口进入相应任务范围；从编辑页保存回来不会重建任务页的搜索和筛选状态。

Android 首页最多展示三个上述“今日待办”，另有待处理和网页收藏等计数。当天末尾在 Composable 中通过 `remember` 计算，长时间停留跨过午夜时不能假定立即重新计算；刷新与跨日行为需要独立回归。其任务页“全部”只是完成状态范围，不表示来自企业或云端的全部任务。

## 收藏和访问记录

iOS 的 `SavedSite.normalizedURL` 会小写 scheme 和 host、去掉 HTTP 80／HTTPS 443 默认端口和 fragment。收藏按规范化 URL 去重：重复收藏更新标题并移到前面，保留既有标识；最近访问按规范化地址合并并只留 30 项。删除收藏和删除历史是两个操作，不会互相代替。

Android 以完整 URL 字符串比较收藏和历史：相同字符串的重复收藏替换原位置，最近访问则移到前面并截为 30 项。大小写、默认端口或 fragment 不会自动套用 iOS 的去重规则。网页标题为空时界面可退回显示主机名。两端保存的只是标题、网址与访问元数据，不是网页全文离线副本。

## 从浏览到任务的步骤

1. 在工作台打开网站入口、收藏或最近访问；输入地址时没有 scheme 可按页面逻辑补成 HTTPS。
2. 确认实际主机和页面加载结果。iOS 对 HTTP 显示继续确认；Android 显示 HTTP 提示，并受 Release 明文网络禁用规则约束。遇到证书错误不能继续放行。
3. 选择收藏，或选择“存为任务”。iOS 打开任务编辑器并预填页面标题和网址，由用户保存；Android 在加载成功后直接创建任务，把网址同时写入备注与 `sourceURL`。
4. 在任务列表调整内容或完成状态。网页任务只是保留来源，不会解析页面待办、登录 Cookie 或企业任务状态。

iOS 普通浏览器使用 `WKWebView`，账号确认模式使用独立非持久网站数据存储并限制为 Account HTTPS 来源；原生登录另走系统授权浏览器。Android 工作台使用 WebView，启用 JavaScript 和 DOM storage，禁止混合内容，SSL 错误调用取消；离开其组合界面时停止加载并销毁 WebView。系统浏览器中的账号身份不应与工作台网页数据混为一谈。

## 正常与失败结果

| 场景 | 应如何理解 |
| --- | --- |
| 标题为空 | 两端阻止确认保存；不是创建一项无名任务 |
| iOS 关联 URL 不是完整 HTTP/HTTPS | 留在编辑器并显示地址错误 |
| iOS 快照读取失败 | 根视图提示本机数据无法读取；不使用空快照覆盖 |
| iOS 写文件失败 | Store 先持久化再替换内存，编辑保留输入 |
| Android 普通数组解析失败 | `LocalData.array` 对非加密数据退回空数组，没有记忆库的锁定保护；不可据此宣称旧文件已经修复 |
| Android 内存已修改但持久化失败 | 当前操作不是跨内存与偏好的数据库事务；界面状态不能作为磁盘写入回执 |
| 网络失败 | 已有个人任务和收藏仍属于本机数据；网页和聊天的网络错误分别处理 |

扩展工作台时，先确定数据是否仍属个人本机；再明确字段、默认值、筛选含义、写入失败策略和旧数据兼容。若新增协作，应另接服务端权限，而不是在个人 JSON 增加一个“企业”标签就宣称支持团队。改变日期规则还需检查时区、午夜、无截止、已完成和逾期的交集。

## 源码与静态核验

iOS 入口为 `Sources/Domain/WorkTask.swift`、`SavedSite.swift`、`TaskQuery.swift`、`Data/LocalWorkspaceStore.swift` 及 `Features/Tasks`、`Features/Browser`；Android 入口为 `WorkScreens.kt`、`AppState.kt` 与 `AppData.kt`。已有领域和存储测试可供回归选用，详见[QA矩阵](https://document.thestarline.cn/app/qa-matrix.md)。本篇仅完成源码与文档静态核对，没有执行构建、模拟器、真实网页或产品流程。
