feat: build collaboration workspaces

This commit is contained in:
2026-07-03 03:02:36 -07:00
parent bf3dd256ab
commit 4ba2a11b88
53 changed files with 9557 additions and 29 deletions

View File

@@ -251,6 +251,73 @@ return jsonSuccess("健康数据已加载", data);
#### Correct
## Scenario: Collaboration Module Data Management
### 1. Scope / Trigger
- Trigger: changing 设备运维, 公告通知, 规则预警, or 家属服务 pages, APIs, seed data, or schema.
- Applies because these modules are real Drizzle/PostgreSQL-backed collaboration workspaces, not reserved/static module pages.
### 2. Signatures
- `GET /api/devices/assets`, `POST /api/devices/assets`, `PATCH|DELETE /api/devices/assets/[id]`
- `POST /api/devices/tickets`, `PATCH|DELETE /api/devices/tickets/[id]`
- `GET|POST /api/notices`, `POST|PATCH|DELETE /api/notices/[id]`
- `GET|POST /api/alerts/rules`, `PATCH|DELETE /api/alerts/rules/[id]`
- `POST /api/alerts/triggers`, `PATCH|DELETE /api/alerts/triggers/[id]`
- `GET|POST /api/family/contacts`, `PATCH|DELETE /api/family/contacts/[id]`
- `POST /api/family/visits`, `PATCH|DELETE /api/family/visits/[id]`
- `POST /api/family/feedback`, `PATCH|DELETE /api/family/feedback/[id]`
### 3. Contracts
- Reads require module read permission: `device:read`, `notice:read`, `alert:read`, or `family:read`.
- Mutations require module manage permission: `device:manage`, `notice:manage`, `alert:manage`, or `family:manage`.
- All records must be scoped by active `organizationId`; updates/deletes must filter by both `id` and `organizationId`.
- Read APIs return `{ success: true, reason, data }` where `data` is the module workspace DTO.
- Mutation APIs return the changed resource under a resource-specific key and write an audit log after successful persistence.
- Seed demo rows only inside `seedDefaultWorkspaceData(organizationId)` and connect them to real seeded elders/devices/rules where applicable.
### 4. Validation & Error Matrix
- Missing session or permission -> response from `requirePermission`; domain helper must not be called.
- Missing active organization -> `400` with a Chinese reason asking the user to select an organization.
- Invalid enum, empty required title/name/content, invalid date -> `400`.
- Cross-organization or missing referenced record -> `404` with entity-specific reason.
- Insert/update returning no row -> structured mutation failure with status `500` or `404`.
### 5. Good/Base/Bad Cases
- Good: Server page checks read permission, loads persisted workspace data, and passes serializable DTOs to a Client Component.
- Good: Client refreshes by calling the module read API after mutations.
- Good: notice read receipts use `POST /api/notices/[id]` with read permission; create/update/delete use manage permission.
- Base: alert rules and triggers are manually managed in v1; no background rule engine is implied.
- Bad: rendering fake collaboration counters or rows on reserved pages after these modules have real tables.
- Bad: updating a record by `id` alone without the active organization filter.
### 6. Tests Required
- `pnpm db:generate`, then review SQL for additive collaboration enums/tables/indexes/FKs.
- `pnpm lint`, `pnpm type-check`, `pnpm test`, and `pnpm build`.
- API route tests should cover permission denial, missing active organization, successful create/update audit, and missing/cross-organization mutation failures.
### 7. Wrong vs Correct
#### Wrong
```ts
await database.update(alertTriggers).set({ status }).where(eq(alertTriggers.id, id));
```
#### Correct
```ts
await database
.update(alertTriggers)
.set({ status, updatedAt: new Date() })
.where(and(eq(alertTriggers.id, id), eq(alertTriggers.organizationId, organizationId)));
```
```ts
const data = await listHealthAdminData(organizationId);
return jsonSuccess("健康数据已加载", { data });

View File

@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}

View File

@@ -0,0 +1,50 @@
# Design
## Architecture
Add four module slices following existing patterns:
- `modules/devices`, `modules/notices`, `modules/alerts`, and `modules/family`
- each module owns `types.ts`, `server/operations.ts`, and a client workspace component
- route handlers under `app/api/<module>` validate permissions, input, organization context, and audit mutations
- app route pages remain Server Components and pass initial data plus `canManage` into client components
## Data Model
Add Postgres enums and tables to `modules/core/server/schema.ts`:
- devices: asset status, ticket status, ticket priority; device assets and maintenance tickets
- notices: notice status; notices and notice read receipts
- alerts: rule type/status, trigger status; alert rules and alert triggers
- family: relation/status, visit status, feedback status/type; family contacts, visit appointments, feedback records
All business tables include `organizationId`, timestamps, and indexes for list/status lookups. FK references use cascade for organization-owned children and set-null where historical records should survive related record deletion.
## Permissions
Extend `Permission` and seeded permission definitions:
- `device:read`, `device:manage`
- `notice:read`, `notice:manage`
- `alert:read`, `alert:manage`
- `family:read`, `family:manage`
`org_admin` and `manager` receive read/manage for all four modules. `viewer` receives read permissions. `caregiver` receives read permissions for devices, alerts, and family plus existing care/health/facility access.
## UI Flow
Each workspace should provide:
- metric cards for key counts
- search and status/type filters
- tables with stable widths and empty states
- dialogs for create/edit/delete confirmation or status updates
- optimistic local refresh by refetching the module API after successful mutations
## Compatibility
Generate a Drizzle migration from schema changes. Existing installations need to run migrations before using the pages. Existing reserved-page component can remain for future modules but must no longer be used by these four routes.
## Rollback
The rollback point is the generated migration plus module files. If implementation gets too large, keep schema and API for all modules but reduce UI duplication by sharing small local helper components only where it does not obscure module boundaries.

View File

@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}

View File

@@ -0,0 +1,26 @@
# Implementation Plan
## Steps
1. Load relevant frontend, backend, and shared Trellis specs.
2. Add schema enums/tables and update core permission types/seed role definitions.
3. Generate the Drizzle migration.
4. Add module type contracts, validators, and server operations for devices, notices, alerts, and family.
5. Add API route handlers and route tests for read/manage permission behavior and organization scoping.
6. Add local seed records for the four modules using existing organization, elder, bed, incident, health, and account context where available.
7. Replace reserved route pages with data-backed Server Components and client workspace components.
8. Run `pnpm type-check`, `pnpm test`, and targeted lint/build checks as time allows.
9. Run Trellis check/update-spec finish steps and commit task changes.
## Validation Commands
- `pnpm db:generate`
- `pnpm type-check`
- `pnpm test`
- `pnpm lint`
## Risk Points
- Schema migration generation changes tracked Drizzle metadata; inspect before finalizing.
- Avoid touching unrelated user-modified files except where required by shared types/navigation/seed integration.
- Keep organization scoping explicit in every list and mutation query.

View File

@@ -0,0 +1,42 @@
# Build collaboration modules
## Goal
Replace the four reserved "协同" navigation pages with real persisted business modules for 设备运维, 公告通知, 规则预警, and 家属服务 so the local养老机构工作台 can exercise end-to-end CRUD workflows backed by Drizzle/Postgres data.
## Confirmed Facts
- The current navigation already exposes `/devices`, `/notices`, `/alerts`, and `/family`.
- These routes currently render `ReservedModulePages`, and the frontend spec requires reserved modules not to fabricate operational data.
- The stack uses Next.js App Router, React client components, project-owned Kumo UI adapters, Drizzle/Postgres, route handlers under `app/api`, and permission gates through `requirePermission`.
- Existing seed data is organization-scoped and idempotent for already-initialized workspaces.
## Requirements
- Add real schema, migrations, server operations, API routes, UI pages, permissions, and seed data for all four collaboration modules.
- Implement complete CRUD for each module's core records, plus the key status transitions needed for daily operations.
- Keep all records organization-scoped and prevent cross-organization reads or mutations.
- Add audit logs for create, update, delete, and status transition mutations.
- Replace reserved pages for both unscoped and organization-scoped app routes.
- Keep UI consistent with existing workspaces: server page loads initial data, client workspace handles filters, tables, dialogs, and mutations.
- Preserve TypeScript strictness and avoid new external dependencies.
## Module Scope
- 设备运维: equipment/device assets and maintenance tickets.
- 公告通知: notices, publish/retract lifecycle, and account read receipts.
- 规则预警: alert rules and triggered alert records. V1 persists and manages rules/triggers but does not implement a background rule engine.
- 家属服务: family contacts, visit appointments, and family feedback. V1 does not add family login or external messaging.
## Acceptance Criteria
- [ ] Four collaboration nav pages render real data-backed workspaces instead of reserved module placeholders.
- [ ] Each module supports list, create, edit, delete, and relevant status transitions through API routes.
- [ ] New data is seeded for local/demo organizations without overwriting existing workspace data.
- [ ] New permissions are registered and assigned to system roles consistently.
- [ ] Mutation API routes require manage permissions, read API routes require read permissions, and cross-organization records cannot be mutated.
- [ ] `pnpm db:generate`, `pnpm type-check`, and `pnpm test` pass.
## Out of Scope
- Family-member authentication, family-facing mobile/client portal, SMS/push delivery, and automatic alert-rule evaluation jobs.

View File

@@ -0,0 +1,26 @@
{
"id": "collaboration-modules",
"name": "collaboration-modules",
"title": "Build collaboration modules",
"description": "",
"status": "in_progress",
"dev_type": null,
"scope": null,
"package": null,
"priority": "P2",
"creator": "TalexDreamSoul",
"assignee": "TalexDreamSoul",
"createdAt": "2026-07-03",
"completedAt": null,
"branch": null,
"base_branch": "main",
"worktree_path": null,
"commit": null,
"pr_url": null,
"subtasks": [],
"children": [],
"parent": null,
"relatedFiles": [],
"notes": "",
"meta": {}
}