<!-- Generated by scripts/build-prompts.mjs — do not edit by hand. -->
# 请帮我做这个工具: Verarbeitungsverzeichnis

*下面是完整的功能需求。请照此实现；需求没说到的地方由你判断，并说明你的假设。*

## 从哪里开始

使用 **openToolbox** 模板：https://github.com/m-dohmen/openToolbox。先读该仓库里的 `AGENTS.md` —— 它是 schema 形态、字段类型以及「哪些做法会破坏单文件构建」的权威说明。所有业务相关的内容只写进一个文件：`src/domain.js`。

> 如果已安装 openToolbox skill（`claude plugin install opentoolbox@opentoolbox`），直接粘贴本文件即可，它会自己去取模板。

## 它解决的问题

按 GDPR 第 30 条，几乎每家企业都必须建立处理活动记录。几乎没有一家真正建得起来 —— 原因很少是不愿意，而是收集。答案分散在十二个人手里：求职材料在人事，邮件订阅工具在市场，监控系统在物业。想在中心统一填写的人，发出十二封邮件，收回九封。因此这个工具必须能被「发出去」：每个部门填报自己的处理活动，保存，寄回。

## 最终必须交付什么

一个自包含的 HTML 文件，双击即可打开，无需服务器、无需安装。文件本身就是数据库：保存会写出一个新的 HTML 文件，数据嵌在其中。

## 记录

一条记录是 **Verarbeitung**，多条是 **Verarbeitungen**。

**字段**

| 键 | 标签 | 类型 | 说明 |
| --- | --- | --- | --- |
| `name` | Verarbeitungstätigkeit | text | 必填 |
| `area` | Bereich | enum | 取值之一：Personal · Vertrieb · Marketing · IT · Buchhaltung · Empfang |
| `contact` | Ansprechperson | text | 表头 `Kontakt` |
| `purpose` | Zweck der Verarbeitung | text | 多行, 表头 `Zweck` |
| `subjects` | Betroffene | enum | 取值之一：Beschäftigte · Bewerberinnen und Bewerber · Kundinnen und Kunden · Interessenten · Lieferanten · Besucher |
| `categories` | Datenkategorien | text | 多行, 表头 `Daten` |
| `basis` | Rechtsgrundlage | enum | 取值之一：Vertrag (Art. 6 I b) · Rechtliche Pflicht (Art. 6 I c) · Berechtigtes Interesse (Art. 6 I f) · Einwilligung (Art. 6 I a) · noch zu klären, 表头 `Grundlage` |
| `system` | System / Ablage | text | 表头 `System` |
| `processor` | Auftragsverarbeiter | text | 表头 `AV` |
| `thirdCountry` | Drittlandtransfer | enum | 取值之一：nein · ja · unklar, 表头 `Drittland` |
| `retention` | Löschfrist | text | 表头 `Frist` |
| `risk` | Risiko | enum | 取值之一：gering · mittel · hoch |
| `status` | Status | enum | 取值之一：gemeldet · in Prüfung · freigegeben · nachzubessern |
| `reviewed` | Zuletzt geprüft | date | 表头 `Geprüft` |
| `note` | Notiz | text | 多行 |
| `age` | Tage seit Prüfung | computed | 计算得出，从不存储, 表头 `Alter` |

**呈现方式**

- 主列：`name`
- 主列下方的第二行：`area`
- 表格列，按此顺序：`name`, `area`, `basis`, `subjects`, `retention`, `age`, `status`
- 侧栏筛选：`area`, `status`, `risk`
- 不再计为未完成的条件：`r.status === 'freigegeben'`
- 标红的条件：`!r.reviewed || r.reviewed < iso(-365)`

**计算字段**

每次渲染时求值，绝不写回记录 —— 一旦某个输入变化，存下来的派生值当场就是错的。

- `age` (Tage seit Prüfung):

  ```js
  const reviewed = localDateFromIso(r.reviewed)
  if (!reviewed) return ''
  /* Ganze lokale Tage über die Date.UTC-Differenz der Tageskompo-
     nenten - exakt ganzzahlig, ohne Rundungsrettung und ohne den
     Mix aus UTC-Mitternacht und Lokal-Mitternacht. */
  const now = new Date()
  return (
    (Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()) -
      Date.UTC(reviewed.getFullYear(), reviewed.getMonth(), reviewed.getDate())) /
    86400000
  )
  ```

**校验规则**

跨字段的条件。必须只在一处生效，使表单、CSV 导入和 AI 提出的改动都走同一套检查。

- **当** `r.basis === 'Einwilligung (Art. 6 I a)'` → **则** `note`
  **提示语:** „Bei einer Einwilligung gehört in die Notiz, wie und wo sie eingeholt wird.“
- **当** `r.thirdCountry === 'ja'` → **则** `processor`
  **提示语:** „Bei einem Drittlandtransfer muss stehen, wer dort verarbeitet.“
- **当** `r.status === 'freigegeben'` → **则** `purpose`, `categories`, `retention`, `reviewed`
  **提示语:** „Freigeben lässt sich nur, was Zweck, Datenkategorien, Löschfrist und Prüfdatum hat.“
- **当** `r.risk === 'hoch'` → **则** `note`
  **提示语:** „Ein hohes Risiko braucht eine Begründung — es kann eine Folgenabschätzung auslösen.“

## 仪表板

统计整个记录集，而不是筛选后的视图。

- 一个数字：**Verarbeitungen** — 记录条数 · „im Verzeichnis“
- 一个数字：**Prüfung überfällig** — 记录条数（仅符合筛选条件的记录）: `isOverdue(r)` · „nie oder vor über einem Jahr“
- 一个数字：**Offene Fragen** — 记录条数（仅符合筛选条件的记录）: `r.basis === 'noch zu klären' || r.thirdCountry === 'unklar'` · „Rechtsgrundlage oder Drittland unklar“
- 按 `status` 的取值分组的环形图
- 按 `area` 的取值分组的条形，度量 记录条数 — **Verarbeitungen je Bereich**
- 按 `risk` 的取值分组的条形，度量 记录条数 — **Verteilung nach Risiko**

## 引导式录入

给「只需报告一件事、并不熟悉这个工具」的人用的一串短步骤。在最后一步确认之前不写入任何数据 —— 中途放弃必须不留痕迹。

标题：**Eine Verarbeitung melden**

> Fünf kurze Schritte. Wenn Sie etwas nicht wissen, lassen Sie es leer — ein unvollständiger Eintrag ist besser als keiner. Gespeichert wird erst am Ende.

1. **步骤 1** — Was und wer: 字段：`name`, `area`, `contact`
2. **步骤 2** — Zweck und Daten: 字段：`purpose`, `subjects`, `categories`
3. **步骤 3** — Rechtsgrundlage: 字段：`basis`, `note`
4. **步骤 4** — Wo liegt es: 字段：`system`, `processor`, `thirdCountry`, `retention`
5. **步骤 5** — Risiko: 字段：`risk`
   仅当：`drafts.records?.subjects === 'Beschäftigte' || drafts.records?.subjects === 'Bewerberinnen und Bewerber' || drafts.records?.thirdCountry === 'ja'`
6. **步骤 6** — Prüfen: 由 schema 自动生成的摘要

结束页：“Danke — das ist aufgenommen. Bitte die Datei speichern und zurücksenden.”

## 默认设置

在 `src/app.jsx` 的 `DEFAULT_SETTINGS`、`DEFAULT_COLORS` 和 `DEFAULT_HOME` 中设置。

- 标题: **Verarbeitungsverzeichnis**
- 副标题: Art. 30 DSGVO — gemeldet von den Fachbereichen
- 文件名: `verarbeitungsverzeichnis`
- 版本: `1.0`
- 界面语言: `de`
- 打开方式: 引导式录入（隐藏列表）
- 配色: `accent` #3a5a8c · `band` #1b2333 · `flag` #b0472e · `ok` #3a7a5e · `pending` #c08a12

## 起始页

应用以这段文字作为起始页。它是一个很小的 Markdown 子集：标题、列表、引用、加粗、斜体、行内代码和链接。请原样使用：

```markdown
# Verzeichnis von Verarbeitungstätigkeiten

Nach **Art. 30 DSGVO** muss fast jedes Unternehmen eines führen. Fast keines führt eines, das den
Namen verdient — und der Grund ist selten Unwille.

Es ist die Erhebung. Die Angaben liegen bei zwölf verschiedenen Leuten: die Bewerbungsmappen bei
der Personalstelle, das Newsletter-Werkzeug im Marketing, die Videoanlage beim Hausmeister. Wer das
zentral ausfüllen will, schreibt zwölf Mails und bekommt neun Antworten.

## Was diese Demo zeigt

Diese Datei ist im **Erfassungsmodus** ausgeliefert: sie öffnet direkt im Meldeformular und zeigt
die Liste gar nicht. Gedacht ist sie zum Weiterschicken — jeder Fachbereich meldet seine eigene
Verarbeitung, speichert und schickt zurück. Die Rückläufer führt man mit *Datei abgleichen*
zusammen.

Umschalten auf das vollständige Werkzeug: **Einstellungen → Anwendung → Öffnet als**.

> Erfundene Einträge, Veranschaulichung der Struktur. Keine Rechtsberatung.
```

## 示例数据

添加 10 条真实感的示例记录，使文件初次打开时不为空。按上面的字段风格自行编写；它们只是示例，不是用户的数据。告诉用户，他自己的数据通过 **Import CSV → replace all** 导入。

## 完成的标准

- `npm run build` 产出单个自包含的 `dist/index.html`
- `npm test` 通过
- 双击可打开，并显示示例记录
- 计算字段有值，规则会拒绝违反它们的记录
- 设置、配色和起始页与上面的规格一致

## 交付之前

这些由你决定，不要留给接收方：把 `copyright` 设为工具的归属方，替换指向 openToolbox 仓库的顶栏链接，若接收方只录入数据就关闭 `examplePrompts`。交付时主动说明使用计数器（设置 → 安全）。

---

*由 `examples/gdpr-processing.domain.js` 生成 —— 即[在线演示](https://m-dohmen.github.io/openToolbox/demos/gdpr-processing/)的真实源码。重新生成：`npm run prompts`。*

*演示中的数据均为虚构。它展示的是这类工具的结构，不构成法律建议，也不能作为合规证明。*
