chore: seal Design Vision v1 and monorepo scaffold
Archive the differentiated YuXinGu product docs, AI engineering system, design contract, and Go/Vue scaffold. Next execution prioritizes Cece-parity over early innovation (see .ai/product/STRATEGY.md). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
# AI Engineering System
|
||||
|
||||
Machine-readable rules for Cursor / Claude Code / other agents.
|
||||
**Source of truth for engineering constraints.** Prompts are helpers, not the core.
|
||||
|
||||
## Priority (what AI depends on most)
|
||||
|
||||
1. `constitution.md` — laws
|
||||
2. `architecture.md` — layers
|
||||
3. `domain.md` — ubiquitous language
|
||||
4. `patterns/` — how to implement
|
||||
5. `examples/` — copy shapes
|
||||
6. `playbooks/` — step flows
|
||||
7. `review.md` + `definition-of-done.md` + `checklists/`
|
||||
8. `prompts/` — optional task templates
|
||||
|
||||
Also always: `ai-contract.md`, `forbidden.md`, `file-map.md`, `workflow.md`, `commands.md`, `adr/`.
|
||||
|
||||
## Tree
|
||||
|
||||
```
|
||||
.ai/
|
||||
├── constitution.md
|
||||
├── architecture.md
|
||||
├── tech-stack.md
|
||||
├── domain.md
|
||||
├── domain/
|
||||
│ └── domain-map.md # DDD contexts / aggregates
|
||||
├── product/
|
||||
│ ├── feature-map.md # 愈心谷 Feature Tree
|
||||
│ └── cece-feature-map.md
|
||||
├── file-map.md
|
||||
├── workflow.md
|
||||
├── ai-contract.md
|
||||
├── coding.md
|
||||
├── api.md
|
||||
├── database.md
|
||||
├── ui.md # IA pointer → design/
|
||||
├── design/ # AI Design System Contract
|
||||
│ ├── design-system.md
|
||||
│ ├── component-catalog.md
|
||||
│ └── platform/
|
||||
├── deployment.md
|
||||
├── testing.md
|
||||
├── security.md
|
||||
├── review.md
|
||||
├── definition-of-done.md
|
||||
├── forbidden.md
|
||||
├── commands.md
|
||||
├── adr/
|
||||
├── patterns/
|
||||
├── playbooks/
|
||||
├── checklists/
|
||||
├── examples/
|
||||
└── prompts/ # auxiliary
|
||||
```
|
||||
|
||||
## Cursor
|
||||
|
||||
`.cursor/rules|templates|commands` are **symlinks** into this directory.
|
||||
Truth = `.ai/` only. See `../.cursor/README.md`.
|
||||
|
||||
## Evolution
|
||||
|
||||
See `ROADMAP.md` — Phase 2/3 (anti-patterns, metrics, gates, memory, graph, mcp, skills) are deferred on purpose.
|
||||
|
||||
Root entry: `AGENTS.md` · `CLAUDE.md`
|
||||
@@ -0,0 +1,38 @@
|
||||
# AI System Evolution Roadmap
|
||||
|
||||
Do **not** build everything at once. Rules have maintenance cost.
|
||||
|
||||
## Phase 1 — Now (shipped)
|
||||
|
||||
- Rules: constitution, architecture, domain, coding, api, database, ui, …
|
||||
- ADR, patterns, examples, playbooks
|
||||
- Review / DoD / checklists / forbidden / commands / workflow / file-map
|
||||
- `ai-contract.md`
|
||||
- Cursor runtime: `.cursor/*` → symlink → `.ai/` (no content copy)
|
||||
|
||||
**Invest next engineering time in:** polishing `patterns/`, `examples/`, `playbooks/` while building real features — not more rule files.
|
||||
|
||||
## Phase 2 — When the codebase grows
|
||||
|
||||
Add only when pain appears:
|
||||
|
||||
| Item | Why wait |
|
||||
|---|---|
|
||||
| `anti-patterns/` | Useful after real mistakes accumulate |
|
||||
| `metrics.md` | Numbers matter once CI exists |
|
||||
| `quality-gates.md` | Wire when lint/test gates are real |
|
||||
| `memory/` (known-bugs, tech-debt, todo) | Fill from actual incidents |
|
||||
|
||||
## Phase 3 — Multi-agent / heavy automation
|
||||
|
||||
| Item | Why wait |
|
||||
|---|---|
|
||||
| `graph/domain.yaml` | Knowledge graph for relation reasoning |
|
||||
| `mcp/*.json` | Structured context servers |
|
||||
| `skills/<feature>/` | Packaged feature kits (login, payment, …) |
|
||||
|
||||
Markdown remains human-readable; JSON/YAML for machines — introduce when agents > 1 or retrieval latency hurts.
|
||||
|
||||
## Rule of thumb
|
||||
|
||||
If adding a rule file does not prevent a repeated AI failure this week, **do not add it**.
|
||||
@@ -0,0 +1,20 @@
|
||||
# ADR-0001 Use Golang for API
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Decision
|
||||
|
||||
Backend is Go only (`apps/api`).
|
||||
|
||||
## Reason
|
||||
|
||||
1. Fits small team / AI-assisted CRUD + rule engines
|
||||
2. Simple deploy (single binary)
|
||||
3. Strong concurrency for future AI/proxy workloads
|
||||
|
||||
## Never
|
||||
|
||||
Never replace the API language with Node/Java/Python without a new ADR and explicit approval.
|
||||
Legacy `server.py` is temporary and must not grow new product APIs.
|
||||
@@ -0,0 +1,19 @@
|
||||
# ADR-0002 Use gin HTTP framework
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Decision
|
||||
|
||||
Use `github.com/gin-gonic/gin` for HTTP routing and middleware.
|
||||
|
||||
## Reason
|
||||
|
||||
1. Widely known; good AI completion quality
|
||||
2. Enough features for REST MVP
|
||||
3. Low ceremony
|
||||
|
||||
## Never
|
||||
|
||||
Never switch to echo/fiber/chi “for fun” mid-feature. Framework change needs a new ADR.
|
||||
@@ -0,0 +1,20 @@
|
||||
# ADR-0003 REST API (not GraphQL)
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Decision
|
||||
|
||||
Public HTTP API is REST under `/api/v1` with envelope `{code,message,data}`.
|
||||
|
||||
## Reason
|
||||
|
||||
1. Simpler mental model for H5 + mini-program
|
||||
2. Better Cursor/Claude reliability than GraphQL schemas mid-flight
|
||||
3. Easier debugging with curl
|
||||
|
||||
## Never
|
||||
|
||||
Never replace with GraphQL without approval + new ADR.
|
||||
Internal gRPC later is allowed only behind a new ADR; public clients stay REST.
|
||||
@@ -0,0 +1,19 @@
|
||||
# ADR-0004 JWT (or opaque Bearer) for auth
|
||||
|
||||
## Status
|
||||
|
||||
Accepted (direction)
|
||||
|
||||
## Decision
|
||||
|
||||
Clients send `Authorization: Bearer <token>`. Prefer JWT for stateless MVP; server may later move to opaque tokens + session store via new ADR.
|
||||
|
||||
## Reason
|
||||
|
||||
1. Works for H5 and future mini-program
|
||||
2. Simple middleware story
|
||||
|
||||
## Never
|
||||
|
||||
Never invent parallel auth headers (`X-User-Id` as sole auth).
|
||||
Never trust client-only “isVip” flags.
|
||||
@@ -0,0 +1,22 @@
|
||||
# ADR-0005 Redis — deferred
|
||||
|
||||
## Status
|
||||
|
||||
Deferred (not accepted for MVP)
|
||||
|
||||
## Decision
|
||||
|
||||
MVP does **not** require Redis. Use PostgreSQL + process memory only when safe.
|
||||
|
||||
## Reason
|
||||
|
||||
1. Reduce moving parts for first ship
|
||||
2. Membership/session can start in Postgres
|
||||
|
||||
## When to revisit
|
||||
|
||||
Rate limiting, hot session cache, or distributed locks → write ADR-0005b Accepted before adding Redis.
|
||||
|
||||
## Never
|
||||
|
||||
Never add Redis “just in case” without an Accepted ADR update.
|
||||
@@ -0,0 +1,21 @@
|
||||
# ADR-0006 Monorepo + Vue3 user-h5
|
||||
|
||||
## Status
|
||||
|
||||
Accepted
|
||||
|
||||
## Decision
|
||||
|
||||
- npm workspaces Monorepo: `apps/*` + `packages/*`
|
||||
- Primary client: Vue 3 + TypeScript + Vite (`apps/user-h5`)
|
||||
- Shared network: `packages/sdk`
|
||||
|
||||
## Reason
|
||||
|
||||
1. Multi-platform path to mini-program via SDK adapters
|
||||
2. AI-friendly explicit boundaries
|
||||
3. Retire root Legacy HTML gradually
|
||||
|
||||
## Never
|
||||
|
||||
Never start a second unrelated frontend framework for user-h5 without ADR.
|
||||
@@ -0,0 +1,36 @@
|
||||
# AI Contract
|
||||
|
||||
Highest operational contract for every agent session.
|
||||
|
||||
## Before coding
|
||||
|
||||
MUST read:
|
||||
|
||||
1. `.ai/constitution.md`
|
||||
2. `.ai/architecture.md`
|
||||
3. `.ai/domain.md` (+ `domain/domain-map.md` when touching models/API)
|
||||
4. `.ai/coding.md`
|
||||
5. Task-relevant: `api.md` / `database.md` / `ui.md` / `security.md` / `product/feature-map.md`
|
||||
6. UI tasks: `design/design-system.md` + `design/component-catalog.md` + `design/platform/*`
|
||||
7. Relevant ADR under `.ai/adr/` if changing stack or style
|
||||
|
||||
## After coding
|
||||
|
||||
MUST:
|
||||
|
||||
1. Run / follow `.ai/review.md` and print Review block
|
||||
2. Verify `.ai/definition-of-done.md`
|
||||
3. Use matching checklist under `.ai/checklists/`
|
||||
4. Prefer verifying with `.ai/commands.md` (build/test/health)
|
||||
|
||||
## Never
|
||||
|
||||
- Guess API shape
|
||||
- Guess DB schema
|
||||
- Guess product requirement
|
||||
- Invent endpoints, tables, or domain words not in `.ai/domain.md` / OpenAPI / task
|
||||
- Silently reverse an Accepted ADR
|
||||
|
||||
## If unclear
|
||||
|
||||
**ASK FIRST.** Do not invent. Do not “assume and continue”.
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
# API — Golden Rules
|
||||
|
||||
## Style
|
||||
|
||||
- REST only for public HTTP.
|
||||
- Never use POST for pure queries (use GET).
|
||||
- Verbs: GET / POST / PUT / DELETE.
|
||||
- Prefix: `/api/v1`.
|
||||
|
||||
## Envelope (mandatory — never invent alternatives)
|
||||
|
||||
Success:
|
||||
|
||||
```json
|
||||
{ "code": 0, "message": "success", "data": {} }
|
||||
```
|
||||
|
||||
Error:
|
||||
|
||||
```json
|
||||
{ "code": 10001, "message": "user not found" }
|
||||
```
|
||||
|
||||
Forbidden shapes: `{ success: true }`, `{ ok: true }`, bare arrays as root.
|
||||
|
||||
## Error codes
|
||||
|
||||
- Start business codes at **10000**.
|
||||
- 0 = success.
|
||||
- Ranges: 1xxxx general/auth, 2xxxx profile, 3xxxx report/scale, 4xxxx order/membership, 5xxxx AI/companion.
|
||||
|
||||
## Pagination
|
||||
|
||||
Query: `page`, `page_size`
|
||||
Data:
|
||||
|
||||
```json
|
||||
{ "list": [], "total": 0, "page": 1, "page_size": 20 }
|
||||
```
|
||||
|
||||
## Auth
|
||||
|
||||
- Bearer token in `Authorization` header when required.
|
||||
- Resource ownership checked in service layer.
|
||||
|
||||
## Docs
|
||||
|
||||
- Public route changes update `proto/openapi.yaml` in the same change set.
|
||||
- Do not invent endpoints that are not in OpenAPI / task spec.
|
||||
@@ -0,0 +1,51 @@
|
||||
# Architecture
|
||||
|
||||
## Allowed call graph
|
||||
|
||||
```
|
||||
UI (user-h5 / mini-program)
|
||||
→ packages/sdk
|
||||
→ API Handler
|
||||
→ Service
|
||||
→ Repository
|
||||
→ Database
|
||||
```
|
||||
|
||||
## Forbidden
|
||||
|
||||
- Handler → Database (skip Service/Repository)
|
||||
- UI → Database
|
||||
- UI direct `fetch` to raw URLs (must use `@yuxingu/sdk` or `src/api` thin wrapper)
|
||||
- Service importing Handler
|
||||
- Circular package imports
|
||||
- Giant `utils` / `common` dump packages
|
||||
|
||||
## Monorepo map
|
||||
|
||||
| Path | Role |
|
||||
|---|---|
|
||||
| `apps/api` | Only backend |
|
||||
| `apps/user-h5` | Primary client (Vue3+TS) |
|
||||
| `apps/mini-program` | Scaffold only until tasked |
|
||||
| `apps/admin-h5` | Deferred |
|
||||
| `packages/sdk` | Multi-platform HTTP client |
|
||||
| `packages/types` | Shared TS types |
|
||||
| `packages/utils` | Pure helpers |
|
||||
| `packages/ui` | Design tokens |
|
||||
| Root HTML / `server.py` | Legacy — do not extend |
|
||||
|
||||
## Feature flow (mandatory when adding a feature)
|
||||
|
||||
```
|
||||
API route + handler
|
||||
→ service
|
||||
→ repository (if persistence)
|
||||
→ migration (if schema change)
|
||||
→ SDK / types update
|
||||
→ UI page or component
|
||||
→ test for money/scoring/auth paths
|
||||
→ OpenAPI touch if public API changed
|
||||
→ self-review
|
||||
```
|
||||
|
||||
Missing migration or skipping service layer = incomplete.
|
||||
@@ -0,0 +1,9 @@
|
||||
# Checklist: Bugfix
|
||||
|
||||
- [ ] Failure mode stated
|
||||
- [ ] Root cause located (file/func)
|
||||
- [ ] Minimal fix only
|
||||
- [ ] Regression test if scoring/auth/payment
|
||||
- [ ] No unrelated refactors
|
||||
- [ ] Build/tests green
|
||||
- [ ] Review: Architecture / Security / Test / Scope
|
||||
@@ -0,0 +1,16 @@
|
||||
# Checklist: Feature
|
||||
|
||||
- [ ] Architecture layers respected
|
||||
- [ ] Domain words match `.ai/domain.md`
|
||||
- [ ] API (+ OpenAPI if public)
|
||||
- [ ] Service
|
||||
- [ ] Repository (if persistence)
|
||||
- [ ] Migration (if schema)
|
||||
- [ ] SDK/types (if client needs)
|
||||
- [ ] UI (if user-facing)
|
||||
- [ ] Test or smoke steps
|
||||
- [ ] Docs touched if behavior user-visible
|
||||
- [ ] `go test` / `npm run build:h5` as applicable
|
||||
- [ ] Health still OK
|
||||
- [ ] Review block printed
|
||||
- [ ] DoD satisfied
|
||||
@@ -0,0 +1,8 @@
|
||||
# Checklist: Refactor
|
||||
|
||||
- [ ] Goal / non-goals stated (behavior unchanged unless asked)
|
||||
- [ ] No ADR silently reversed
|
||||
- [ ] Layers still clean
|
||||
- [ ] File/function size improved toward limits
|
||||
- [ ] Tests still pass; added if extracting unscored logic
|
||||
- [ ] Review: Architecture / Readability / Test / Scope
|
||||
@@ -0,0 +1,10 @@
|
||||
# Checklist: Release
|
||||
|
||||
- [ ] main green: `go test ./...`, `npm run build:h5`
|
||||
- [ ] Migrations applied plan documented
|
||||
- [ ] Health endpoint verified
|
||||
- [ ] No secrets in artifact
|
||||
- [ ] Image tag ≠ `latest` (prod)
|
||||
- [ ] OpenAPI matches deployed routes
|
||||
- [ ] Changelog / version tag if shipping
|
||||
- [ ] Rollback path known
|
||||
@@ -0,0 +1,37 @@
|
||||
# Coding — Golden Rules
|
||||
|
||||
## Size
|
||||
|
||||
- One responsibility per file.
|
||||
- One responsibility per function.
|
||||
- No function longer than **50** lines.
|
||||
- No file longer than **400** lines (hard preference; split earlier if possible).
|
||||
- No circular dependency.
|
||||
|
||||
## Go
|
||||
|
||||
- Business packages by domain: `auth`, `profile`, `report`, `order`, `payment` — not `utils`.
|
||||
- Interface defined at **caller** (usually handler), implemented by service.
|
||||
- First parameter of I/O methods: `context.Context`.
|
||||
- Errors: `return fmt.Errorf("create user: %w", err)`.
|
||||
- Never `panic` in request path.
|
||||
- Never use package-level mutable globals for request state.
|
||||
- Export comments required on public funcs (what / in / out / side effects).
|
||||
|
||||
## TypeScript / Vue
|
||||
|
||||
- `strict: true`. No casual `any`.
|
||||
- Components: `PascalCase.vue` (`UserCard.vue`).
|
||||
- Pages under `src/pages/`, composables under `src/hooks/`.
|
||||
- No direct `fetch` in pages — use SDK.
|
||||
- Shared domain types go to `packages/types`.
|
||||
|
||||
## Naming
|
||||
|
||||
- Consistent domain words: profile, report, scale, membership, order.
|
||||
- Prefer boring clear names over clever short names.
|
||||
|
||||
## Comments
|
||||
|
||||
- Public APIs: always document.
|
||||
- Do not narrate obvious code. Document intent, invariants, side effects.
|
||||
@@ -0,0 +1,67 @@
|
||||
# Commands — Do Not Guess
|
||||
|
||||
Run from repo root unless noted.
|
||||
|
||||
## Go API (`apps/api`)
|
||||
|
||||
```bash
|
||||
export GOPROXY=https://goproxy.cn,direct # if download timeout
|
||||
|
||||
cd apps/api
|
||||
go mod tidy
|
||||
go build ./...
|
||||
go test ./...
|
||||
go run ./cmd/server
|
||||
```
|
||||
|
||||
Health:
|
||||
|
||||
```bash
|
||||
curl -s http://127.0.0.1:8080/api/v1/healthz
|
||||
curl -s http://127.0.0.1:8080/api/v1/ping
|
||||
```
|
||||
|
||||
## User H5
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev:h5
|
||||
npm run build:h5
|
||||
```
|
||||
|
||||
## Docker / DB
|
||||
|
||||
```bash
|
||||
docker compose -f deploy/docker-compose.yml up -d
|
||||
docker compose -f deploy/docker-compose.yml down
|
||||
```
|
||||
|
||||
## Lint (when configured)
|
||||
|
||||
```bash
|
||||
# Go — after golangci-lint is added:
|
||||
# cd apps/api && golangci-lint run
|
||||
|
||||
# H5 — after eslint is added:
|
||||
# npm run lint -w @yuxingu/user-h5
|
||||
```
|
||||
|
||||
## Migrations (when make targets exist)
|
||||
|
||||
```bash
|
||||
# Preferred once Makefile lands:
|
||||
# make migrate
|
||||
# make migrate-down
|
||||
|
||||
# Until then: document the goose/migrate command used in the PR.
|
||||
```
|
||||
|
||||
## Dev all (local)
|
||||
|
||||
```bash
|
||||
# terminal 1
|
||||
cd apps/api && go run ./cmd/server
|
||||
|
||||
# terminal 2
|
||||
npm run dev:h5
|
||||
```
|
||||
@@ -0,0 +1,34 @@
|
||||
# Project Constitution — 愈心谷
|
||||
|
||||
最高原则。与本文件冲突时,以本文件为准。
|
||||
|
||||
## Absolute Laws
|
||||
|
||||
1. Architecture never broken. Layers: UI → API → Service → Repository → Database. No skipping.
|
||||
2. Readability > Cleverness.
|
||||
3. Deterministic > Magic.
|
||||
4. Simple > Complex.
|
||||
5. Explicit > Implicit.
|
||||
6. No hidden global state.
|
||||
7. Every module independently testable.
|
||||
8. Every feature deployable.
|
||||
9. Every API documented (OpenAPI or apps/docs).
|
||||
10. Every database change versioned (migration required).
|
||||
|
||||
## Product Laws (YuXinGu)
|
||||
|
||||
1. Never invent medical efficacy claims.
|
||||
2. Never use fortune-telling / 吉凶祸福 wording.
|
||||
3. Birthday and profile data are sensitive — minimize, authorize, allow delete.
|
||||
4. Billing and unlock decisions happen on the server, never trust the client alone.
|
||||
5. New product code lives in `apps/` and `packages/` only. Legacy root HTML is read-only unless the task is explicit migration.
|
||||
|
||||
## AI Laws
|
||||
|
||||
1. Obey `.ai/ai-contract.md` every session.
|
||||
2. Load constitution → architecture → domain before writing code.
|
||||
3. Never invent APIs/DB/domain words; never reverse Accepted ADRs silently.
|
||||
4. Never modify files outside the current task scope.
|
||||
5. Prefer patterns + examples + playbooks over prompts.
|
||||
6. Prefer small diffs. One feature per change set.
|
||||
7. Think → architecture check → code → commands → review → DoD.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Database — Golden Rules
|
||||
|
||||
## Naming
|
||||
|
||||
- `snake_case` only for tables and columns.
|
||||
- Good: `user_profile`, `payment_order`, `user_session`.
|
||||
- Forbidden prefixes: `tbl_`, `t_`.
|
||||
|
||||
## Required columns on business tables
|
||||
|
||||
```
|
||||
id
|
||||
created_at
|
||||
updated_at
|
||||
deleted_at
|
||||
```
|
||||
|
||||
## Types
|
||||
|
||||
- Never `varchar(5000)` as a habit.
|
||||
- Prefer bounded `varchar(n)`.
|
||||
- `TEXT` only when necessary (long content bodies).
|
||||
- Timestamps: `timestamptz`.
|
||||
|
||||
## Keys & indexes
|
||||
|
||||
- Every foreign key indexed.
|
||||
- Unique business keys enforced with UNIQUE.
|
||||
|
||||
## Migrations
|
||||
|
||||
- Schema change without migration = incomplete feature.
|
||||
- Migrations live in `apps/api/migrations/`.
|
||||
- Provide Up and Down when tool supports it.
|
||||
|
||||
## Soft delete
|
||||
|
||||
- Default: set `deleted_at`, do not hard delete user content in MVP.
|
||||
- Queries must filter `deleted_at IS NULL` unless explicitly including deleted.
|
||||
@@ -0,0 +1,17 @@
|
||||
# Definition of Done
|
||||
|
||||
Code finished ≠ Done.
|
||||
|
||||
A feature is Done only when applicable items PASS:
|
||||
|
||||
- [ ] Code (compiles / typechecks)
|
||||
- [ ] API (handler + service + repository as needed)
|
||||
- [ ] Test (unit or listed smoke for critical paths)
|
||||
- [ ] Migration (if schema changed)
|
||||
- [ ] Docker / deploy notes (if new service or env)
|
||||
- [ ] Docs (OpenAPI / short PRD note if user-visible)
|
||||
- [ ] Review (`.ai/review.md` checklist output)
|
||||
- [ ] Build (`go test ./...` and/or `npm run build:h5` for touched side)
|
||||
- [ ] Health check still green (`/api/v1/healthz`)
|
||||
|
||||
If an item is N/A, state why. Silent skip = not Done.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Deployment — Golden Rules
|
||||
|
||||
## Containers
|
||||
|
||||
- Every runnable service that ships to prod must have a Dockerfile.
|
||||
- Never use image tag `latest` in production.
|
||||
- Always semantic version tags: `v0.1.0` or git SHA.
|
||||
|
||||
## Health
|
||||
|
||||
- Liveness: `GET /api/v1/healthz` required.
|
||||
- When DB is required for traffic: add readiness endpoint (e.g. `/api/v1/readyz`) that checks DB.
|
||||
- Alias names `/health` `/readiness` `/liveness` may map to the above; keep one canonical path documented in OpenAPI.
|
||||
|
||||
## Config
|
||||
|
||||
- Secrets via env only. Commit `.env.example`, never `.env`.
|
||||
- Required: `APP_ENV`, `HTTP_ADDR`, `DATABASE_URL`.
|
||||
|
||||
## CI
|
||||
|
||||
- No manual prod deploy as the happy path — CI builds and tags.
|
||||
- Minimum gates: `go test ./...` (api), `npm run build:h5`.
|
||||
|
||||
## Local
|
||||
|
||||
```bash
|
||||
docker compose -f deploy/docker-compose.yml up -d
|
||||
cd apps/api && go run ./cmd/server
|
||||
npm run dev:h5
|
||||
```
|
||||
|
||||
If Go module download times out in CN: `export GOPROXY=https://goproxy.cn,direct`.
|
||||
@@ -0,0 +1,15 @@
|
||||
# AI Design System
|
||||
|
||||
Machine-readable **UI/UX/VI contract** for agents generating H5 / Mini Program / Web / App UI.
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| [design-system.md](design-system.md) | Foundation: tokens, color, type, spacing, motion, voice |
|
||||
| [component-catalog.md](component-catalog.md) | Button / Card / Chat / Report / Membership … |
|
||||
| [platform/h5.md](platform/h5.md) | Mobile Web implementation limits |
|
||||
| [platform/mini-program.md](platform/mini-program.md) | WeChat constraints |
|
||||
| [platform/website.md](platform/website.md) | Desktop / SEO / admin |
|
||||
| [platform/flutter.md](platform/flutter.md) | Future native |
|
||||
|
||||
Runtime tokens: `packages/ui/src/tokens.css`
|
||||
Product chrome / tabs: `../ui.md`
|
||||
@@ -0,0 +1,233 @@
|
||||
# Component Catalog — AI Contract
|
||||
|
||||
Agents MUST check this file + platform `components/` before creating UI.
|
||||
|
||||
Naming: PascalCase; domain words from `.ai/domain.md`.
|
||||
Visual tokens: [design-system.md](design-system.md).
|
||||
Ship path today: `apps/user-h5/src/components/` (Vue). Mini Program / Flutter map 1:1 by name.
|
||||
|
||||
Status: `exists` | `required` (build when first needed) | `future`
|
||||
|
||||
---
|
||||
|
||||
## Primitives
|
||||
|
||||
### Button
|
||||
|
||||
Status: **required**
|
||||
|
||||
Types ONLY: `Primary` · `Secondary` · `Ghost` · `Danger` · `Loading` · `Disabled`
|
||||
|
||||
| Prop | Notes |
|
||||
|---|---|
|
||||
| variant | primary / secondary / ghost / danger |
|
||||
| loading | shows progress; blocks double submit |
|
||||
| disabled | uses `--color-primary-disabled` or neutral |
|
||||
| block | full width on H5 forms |
|
||||
|
||||
MUST NOT: `SpecialButton`, `CustomButton2`, one-off gradient buttons outside Primary.
|
||||
|
||||
Primary visual: pill + brand CTA gradient from design-system.
|
||||
|
||||
### IconTile
|
||||
|
||||
Status: **required**
|
||||
|
||||
Square/rounded tile for Explore / Home grid. Soft accent bg + symbol (△ ◆ ☯ 问), not emoji.
|
||||
|
||||
### Avatar
|
||||
|
||||
Status: **required**
|
||||
|
||||
Profile face placeholder (initials or soft color). Sizes: sm 32 / md 40 / lg 56.
|
||||
|
||||
### Tag / Chip
|
||||
|
||||
Status: **required**
|
||||
|
||||
Filter chips, Soft labels. Active = white surface + primary text + light shadow.
|
||||
|
||||
### Divider
|
||||
|
||||
Status: **required** — `--color-border`, 1px.
|
||||
|
||||
### Skeleton
|
||||
|
||||
Status: **required** — list/card placeholders; calm pulse ≤300ms feel, no flashy shimmer rainbow.
|
||||
|
||||
### Toast / Banner
|
||||
|
||||
Status: **required** — success / error / info. Short copy; no fear wording.
|
||||
|
||||
---
|
||||
|
||||
## Layout chrome
|
||||
|
||||
### AppShell
|
||||
|
||||
Status: **exists** (TabBar + max-width column)
|
||||
|
||||
User column `max-width: var(--layout-max-user)`. Safe-area bottom padding.
|
||||
|
||||
### TabBar
|
||||
|
||||
Status: **exists**
|
||||
|
||||
Tabs: 首页 / 探索 / **问** / 陪伴 / 我的. Center Ask may use primary circle. Active = primary.
|
||||
|
||||
### TopBar
|
||||
|
||||
Status: **required**
|
||||
|
||||
Secondary pages: back · title · optional action. Soft wash or white; not heavy app bar.
|
||||
|
||||
### ContentSheet
|
||||
|
||||
Status: **required**
|
||||
|
||||
White rounded sheet over peach wash (home feed pattern).
|
||||
|
||||
---
|
||||
|
||||
## Forms
|
||||
|
||||
### TextField / DateField
|
||||
|
||||
Status: **required**
|
||||
|
||||
Label required · error · disabled · focus border soft primary. Birthday Decode uses compact year/month/day fields.
|
||||
|
||||
### FormSection
|
||||
|
||||
Status: **required** — label + control + helper/error.
|
||||
|
||||
Rules: Label, error, loading, disabled states always.
|
||||
|
||||
---
|
||||
|
||||
## Cards
|
||||
|
||||
### Card (base)
|
||||
|
||||
Status: **required**
|
||||
|
||||
Structure: Container → Padding (`--spacing-md`) → Content → Optional Action.
|
||||
Surface white, `--radius-lg`, `--shadow-card`. No random card skins.
|
||||
|
||||
### FeatureCard
|
||||
|
||||
Status: **required** — Explore entry (icon + title + one line).
|
||||
|
||||
### ReportCard
|
||||
|
||||
Status: **required**
|
||||
|
||||
Decode / Match summary. Shows free conclusion; locked sections use PaywallLock. Footer disclaimer slot.
|
||||
|
||||
### MoodCard
|
||||
|
||||
Status: **required** — Companion daily mood entry/result. Soft, never clinical.
|
||||
|
||||
### SolarTermCard
|
||||
|
||||
Status: **required** — Today’s SolarTerm title + short lifestyle tip (no 吉凶).
|
||||
|
||||
### SubscriptionCard
|
||||
|
||||
Status: **required**
|
||||
|
||||
Membership plans. Clear price · period · benefits. **MUST NOT** fake countdown / dark patterns. CTA = Primary Button.
|
||||
|
||||
### UnlockCard
|
||||
|
||||
Status: **required** — single Report / Match Unlock alternative to VIP.
|
||||
|
||||
---
|
||||
|
||||
## AI / Ask
|
||||
|
||||
### ChatThread
|
||||
|
||||
Status: **required** — scrollable Ask history; Profile context chip at top (Self / Other switch).
|
||||
|
||||
### ChatBubble
|
||||
|
||||
Status: **required**
|
||||
|
||||
User vs AI. AI bubble: soft surface, calm radius; no neon bot skins. Streaming = typing/skeleton, not decorative bounce spam.
|
||||
|
||||
### AIMessage
|
||||
|
||||
Status: **required**
|
||||
|
||||
Structured Ask answer: short answer · optional bullets · disclaimer when health-adjacent. Prefer structured blocks over wall of text.
|
||||
|
||||
### PromptChip
|
||||
|
||||
Status: **required** — suggested follow-ups under Ask input; path-aware (性格 / 关系 / 养生), never 运势.
|
||||
|
||||
### AskInputBar
|
||||
|
||||
Status: **required** — bottom composer; ≥44px hit; send loading state.
|
||||
|
||||
---
|
||||
|
||||
## Profile & social
|
||||
|
||||
### ProfileSwitcher
|
||||
|
||||
Status: **required** — Self / Other list; “帮 TA 测” entry.
|
||||
|
||||
### ShareCard
|
||||
|
||||
Status: **required** — Decode / ScaleResult share visual; brand + one conclusion line; no medical claims.
|
||||
|
||||
### ScaleQuestion / ScaleResultView
|
||||
|
||||
Status: **required** — progress · options · result type + CTA to Decode/Ask.
|
||||
|
||||
---
|
||||
|
||||
## Commerce
|
||||
|
||||
### PaywallLock
|
||||
|
||||
Status: **required** — blurred/locked reason+plan; CTA Unlock or Membership.
|
||||
|
||||
### OrderSummary
|
||||
|
||||
Status: **required** — plan/report line items before pay-mock.
|
||||
|
||||
---
|
||||
|
||||
## States
|
||||
|
||||
### EmptyState
|
||||
|
||||
Status: **required** — one sentence + one action.
|
||||
|
||||
### ErrorState
|
||||
|
||||
Status: **required** — message + retry/back.
|
||||
|
||||
### LoadingBlock
|
||||
|
||||
Status: **required** — page/section skeleton wrapper.
|
||||
|
||||
---
|
||||
|
||||
## Forbidden inventions
|
||||
|
||||
Without approval / catalog update:
|
||||
|
||||
- Parallel button systems
|
||||
- “Glassmorphism” chat skins
|
||||
- Emoji-only navigation
|
||||
- New layout shells beside AppShell
|
||||
- Countdown / guilt paywalls
|
||||
|
||||
---
|
||||
|
||||
## Extension rule
|
||||
|
||||
Need a new component → add a row here (name, status, props, do/don’t) in the **same PR** as the first implementation. Then build under platform `components/`.
|
||||
@@ -0,0 +1,276 @@
|
||||
# AI Design System Contract — 愈心谷
|
||||
|
||||
**Mandatory.** Agents MUST read this before creating or modifying frontend UI
|
||||
(`apps/user-h5`, `apps/mini-program`, `apps/admin-h5`, future website / Flutter).
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| [component-catalog.md](component-catalog.md) | Reusable components — check before inventing |
|
||||
| [platform/h5.md](platform/h5.md) | Mobile Web (primary) |
|
||||
| [platform/mini-program.md](platform/mini-program.md) | WeChat Mini Program |
|
||||
| [platform/website.md](platform/website.md) | Desktop / marketing Web |
|
||||
| [platform/flutter.md](platform/flutter.md) | Native app (future) |
|
||||
|
||||
Tokens: `packages/ui/src/tokens.css`
|
||||
IA / tabs: `.ai/ui.md` · Domain: `.ai/domain.md`
|
||||
|
||||
---
|
||||
|
||||
## 0. Purpose
|
||||
|
||||
This is an **AI contract**, not a traditional design deck.
|
||||
|
||||
- Consistent brand across H5 / Mini Program / Web / App
|
||||
- Stop random UI decisions
|
||||
- Reuse components before inventing
|
||||
- Shared language here; platform limits in `platform/*`
|
||||
|
||||
When uncertain: **DO NOT invent. ASK FIRST.** Consistency > creativity.
|
||||
|
||||
---
|
||||
|
||||
## 1. Design Philosophy
|
||||
|
||||
### Core values
|
||||
|
||||
| Value | UI implication |
|
||||
|---|---|
|
||||
| Simple | One job per section; short copy |
|
||||
| Calm | Warm soft surfaces; low motion; no neon |
|
||||
| Trustworthy | Clear hierarchy; disclaimer on reports |
|
||||
| Professional | Stable tokens; no gaming chrome |
|
||||
| Human-centered | Soft language; easy exit from paywalls |
|
||||
| AI-first | Ask / chat are first-class patterns |
|
||||
|
||||
### Domain (psychology / wellness) — MUST
|
||||
|
||||
- Gentle self-understanding — not clinical hospital UI, not fortune-telling casino.
|
||||
- Atmosphere: warm peach / coral wash → white content sheet.
|
||||
- Unicode symbols (△ ☯ ◈) or SVG over emoji in chrome.
|
||||
- Copy: friendly, clear, respectful, encouraging.
|
||||
- **MUST NOT:** fear, guilt, fake urgency, medical cure claims, 吉凶祸福.
|
||||
|
||||
### MUST NOT create
|
||||
|
||||
- Excessive multi-stop gradients on chrome
|
||||
- Neon, glow, dark-mode-by-default, purple-on-white “AI slop”
|
||||
- Gaming HUD, particle spam, continuous decorative animation
|
||||
- Random illustrations / emoji clusters
|
||||
- Inconsistent spacing / one-off hex colors
|
||||
- Dashboard clutter in home first viewport
|
||||
|
||||
---
|
||||
|
||||
## 2. Design Architecture
|
||||
|
||||
```
|
||||
Foundation (tokens) → Components (catalog) → Platform implementation
|
||||
```
|
||||
|
||||
AI MUST follow this order. Never invent page magic numbers or duplicate components.
|
||||
|
||||
---
|
||||
|
||||
## 3. Foundation — Design Tokens
|
||||
|
||||
All UI values MUST use tokens from `packages/ui` (or platform mapping of the same names).
|
||||
|
||||
Forbidden: `padding:17px; color:#2563eb; border-radius:13px;`
|
||||
Required: `padding:var(--spacing-md); color:var(--color-primary); border-radius:var(--radius-md);`
|
||||
|
||||
If a token is missing: **ASK** or add it to `packages/ui/src/tokens.css` in the same change — do not hardcode.
|
||||
|
||||
Legacy `--yxg-*` remains valid; new code SHOULD prefer semantic names below.
|
||||
|
||||
---
|
||||
|
||||
## 4. Color System
|
||||
|
||||
Use only these semantic colors. Do not invent brand hues.
|
||||
|
||||
### Primary
|
||||
|
||||
| Token | Value | Use |
|
||||
|---|---|---|
|
||||
| `--color-primary` | `#E54D42` | CTA, brand, active tab |
|
||||
| `--color-primary-hover` | `#D44338` | Hover / pressed |
|
||||
| `--color-primary-soft` | `#FFE4E4` | Soft chip / Ask surface |
|
||||
| `--color-primary-disabled` | `#F5B5B0` | Disabled primary |
|
||||
|
||||
Brand CTA gradient (only this one):
|
||||
`linear-gradient(135deg, #FF7A6E, var(--color-primary))`
|
||||
|
||||
### Atmosphere
|
||||
|
||||
| Token | Value |
|
||||
|---|---|
|
||||
| `--color-bg-start` | `#FFD1C7` |
|
||||
| `--color-bg-end` | `#FFC8B5` |
|
||||
| `--color-bg-sheet` | `#FFF9F7` |
|
||||
|
||||
Do not replace with flat gray or purple gradients.
|
||||
|
||||
### Neutral
|
||||
|
||||
| Token | Value | Use |
|
||||
|---|---|---|
|
||||
| `--color-surface` | `#FFFFFF` | Cards, sheets, nav |
|
||||
| `--color-text-primary` | `#333333` | Titles / body |
|
||||
| `--color-text-secondary` | `#999999` | Subcopy |
|
||||
| `--color-text-tertiary` | `#BBBBBB` | Meta |
|
||||
| `--color-border` | `#F0F0F0` | Dividers |
|
||||
| `--color-border-strong` | `#EEEEEE` | Inputs |
|
||||
| `--color-input-bg` | `#FDFAF8` | Form fields |
|
||||
|
||||
### Domain accents (tint only — not global CTA)
|
||||
|
||||
| Token | Value | Feature |
|
||||
|---|---|---|
|
||||
| `--color-accent-gold` | `#C8923A` | Decode |
|
||||
| `--color-accent-gold-soft` | `#FFF3D6` | Decode tile |
|
||||
| `--color-accent-blue` | `#4A90E2` | Scale |
|
||||
| `--color-accent-blue-soft` | `#E3EEFF` | Scale tile |
|
||||
| `--color-accent-green` | `#5CB85C` | Companion / SolarTerm |
|
||||
| `--color-accent-green-soft` | `#E0F6E4` | Companion tile |
|
||||
| `--color-accent-orange` | `#E8985A` | Warm secondary |
|
||||
| `--color-accent-purple` | `#8B5CF6` | Sparse only — never page theme |
|
||||
|
||||
### Status (only)
|
||||
|
||||
`success` · `warning` · `error` · `info`
|
||||
Map: success≈green, warning≈orange/gold, error≈primary family, info≈blue.
|
||||
|
||||
### Forbidden
|
||||
|
||||
Neon / pure-black full-bleed / random Tailwind blue as brand / purple global theme.
|
||||
|
||||
---
|
||||
|
||||
## 5. Typography
|
||||
|
||||
Stack: `-apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", "Helvetica Neue", sans-serif`
|
||||
Do not add Inter/Roboto/display fonts on product UI without ADR.
|
||||
|
||||
| Level | Size | Weight | Use |
|
||||
|---|---|---|---|
|
||||
| Display | 28–32px | 700 | Brand 愈心谷 only |
|
||||
| Heading 1 | 20–22px | 700 | Page hero |
|
||||
| Heading 2 | 16–17px | 600–700 | Section |
|
||||
| Heading 3 | 15px | 600 | Card title |
|
||||
| Body | 14px | 400 | Default |
|
||||
| Body Small | 12–13px | 400 | Secondary |
|
||||
| Caption | 10–11px | 400 | Tab / disclaimer |
|
||||
|
||||
No arbitrary sizes. Body line-height ≈ 1.6–1.7.
|
||||
|
||||
---
|
||||
|
||||
## 6. Spacing
|
||||
|
||||
Scale: **4 · 8 · 12 · 16 · 24 · 32 · 48 · 64**
|
||||
|
||||
| Token | px |
|
||||
|---|---|
|
||||
| `--spacing-2xs` | 4 |
|
||||
| `--spacing-xs` | 8 |
|
||||
| `--spacing-sm` | 12 |
|
||||
| `--spacing-md` | 16 |
|
||||
| `--spacing-lg` | 24 |
|
||||
| `--spacing-xl` | 32 |
|
||||
| `--spacing-2xl` | 48 |
|
||||
| `--spacing-3xl` | 64 |
|
||||
|
||||
Forbidden: 13 / 18 / 27 / 35. Page pad default: 16.
|
||||
|
||||
---
|
||||
|
||||
## 7. Radius, shadow, width
|
||||
|
||||
| Token | Value | Use |
|
||||
|---|---|---|
|
||||
| `--radius-sm` | 10px | Back / small controls |
|
||||
| `--radius-md` | 12px | Inputs / tiles |
|
||||
| `--radius-lg` | 16px | Cards |
|
||||
| `--radius-xl` | 18–20px | Large sheets |
|
||||
| `--radius-pill` | 999px | CTA capsule |
|
||||
|
||||
Shadows: `--shadow-card: 0 2px 10px rgba(0,0,0,.04)`; `--shadow-nav: 0 -2px 8px rgba(0,0,0,.03)`. No glow.
|
||||
|
||||
`--layout-max-user: 430px` · `--layout-nav-h: 56px`
|
||||
|
||||
---
|
||||
|
||||
## 8. Components
|
||||
|
||||
MUST reuse. Before creating: catalog → `src/components/` → extend.
|
||||
No `SpecialButton` / `CustomButton2` / `NewCard`.
|
||||
|
||||
---
|
||||
|
||||
## 9. Layout Patterns
|
||||
|
||||
| Pattern | Screens |
|
||||
|---|---|
|
||||
| HomeWash | Brand + Decode + white sheet |
|
||||
| List | Explore, orders |
|
||||
| Detail | Report / Match |
|
||||
| Form | Decode birthday, edit Profile |
|
||||
| Profile | Mine / switch Profile |
|
||||
| Settings | Account, privacy |
|
||||
| AI Chat | Ask |
|
||||
| Paywall | Membership / Unlock |
|
||||
| Companion | SolarTerm + Mood |
|
||||
|
||||
Home first viewport: **brand · headline · Decode form · CTA**. No stats/promo clutter.
|
||||
|
||||
---
|
||||
|
||||
## 10. Interaction States
|
||||
|
||||
Network UI MUST have: Loading (skeleton) · Empty · Error (+ recovery) · Success · Disabled.
|
||||
Paywall: free conclusion, lock reason/plan; no fake countdown.
|
||||
|
||||
---
|
||||
|
||||
## 11. Motion
|
||||
|
||||
Durations: **150 / 200 / 300ms**. Feedback only.
|
||||
No continuous loops or decorative scroll animation.
|
||||
|
||||
---
|
||||
|
||||
## 12. Accessibility
|
||||
|
||||
Contrast for body text; touch ≥ 44px; no hover-only essentials; label interactive controls.
|
||||
|
||||
---
|
||||
|
||||
## 13. Brand Voice
|
||||
|
||||
温和、清晰、尊重。禁止恐吓 / 道德绑架 / 虚假倒计时.
|
||||
Report/Ask: lifestyle disclaimer(非医疗、非算命). Labels follow `.ai/domain.md`.
|
||||
|
||||
---
|
||||
|
||||
## 14. Platforms
|
||||
|
||||
Shared language = this file. Limits = `platform/*`.
|
||||
Priority: **H5 → Mini Program → Website → Flutter**.
|
||||
|
||||
---
|
||||
|
||||
## 15. Before Coding Checklist
|
||||
|
||||
- [ ] Catalog + components checked
|
||||
- [ ] Correct `platform/*.md` read
|
||||
- [ ] Tokens only
|
||||
- [ ] Loading / empty / error
|
||||
- [ ] Compliance copy if Report / Ask / Membership
|
||||
- [ ] A11y (touch / contrast)
|
||||
- [ ] No emoji chrome; no medical / 吉凶 wording
|
||||
|
||||
---
|
||||
|
||||
## 16. Final Rule
|
||||
|
||||
Uncertain → **ASK**. Do not invent colors, components, or layouts.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Platform Contract — Flutter / Native App
|
||||
|
||||
Future client. Not in MVP scope unless task explicitly opens it.
|
||||
Design language: [../design-system.md](../design-system.md) · Catalog names stay the same.
|
||||
|
||||
---
|
||||
|
||||
## Priority
|
||||
|
||||
**Performance > Native experience > Visual decoration**
|
||||
|
||||
---
|
||||
|
||||
## MUST
|
||||
|
||||
- Map tokens to `ThemeData` / design token classes — same hex and spacing scale.
|
||||
- Native navigation patterns (Material/Cupertino as decided by ADR).
|
||||
- Platform permissions (camera, photos, notifications) only with clear UX rationale.
|
||||
- 60fps interactions; avoid heavy blur/shadow on low-end devices.
|
||||
- Reuse catalog component names (`Button`, `ChatBubble`, `SubscriptionCard`…).
|
||||
- Same compliance and domain copy rules.
|
||||
|
||||
---
|
||||
|
||||
## MUST NOT
|
||||
|
||||
- Invent a dark-neon “AI app” skin.
|
||||
- Bypass API unlock/membership rules with local flags.
|
||||
- Port Web DOM assumptions.
|
||||
|
||||
---
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Token theme 1:1 with `packages/ui`
|
||||
- [ ] Catalog parity for screens in scope
|
||||
- [ ] Permission + performance considered
|
||||
- [ ] ADR if introducing Flutter stack officially
|
||||
@@ -0,0 +1,47 @@
|
||||
# Platform Contract — H5 (Mobile Web)
|
||||
|
||||
Primary shipping client: `apps/user-h5` (Vue 3 + Vite).
|
||||
Design language: [../design-system.md](../design-system.md) · Components: [../component-catalog.md](../component-catalog.md)
|
||||
|
||||
---
|
||||
|
||||
## MUST
|
||||
|
||||
- Mobile-first; content column `max-width: var(--layout-max-user)` (430px), centered on large screens.
|
||||
- Touch targets ≥ 44×44px.
|
||||
- Prefer bottom actions (TabBar, AskInputBar, sticky CTA).
|
||||
- Safe area: `env(safe-area-inset-bottom)` on TabBar / fixed footers.
|
||||
- `user-scalable` / viewport per existing app shell; no desktop-only hover for essentials.
|
||||
- Import tokens from `@yuxingu/ui` / `packages/ui` — no page-local brand hex.
|
||||
- Data via `src/api` → `@yuxingu/sdk` only (no raw `fetch` in pages).
|
||||
- Structure: `pages/` · `components/` · `layouts/` · `stores/` · `router/`.
|
||||
- Loading / empty / error on every network view.
|
||||
- Report / Decode / Ask: compliance disclaimer.
|
||||
|
||||
---
|
||||
|
||||
## MUST NOT
|
||||
|
||||
- Rely on hover tooltips for critical info.
|
||||
- Use `window` APIs that break iOS WeChat/browser without fallback.
|
||||
- Invent a second tab IA; tabs = Home / Explore / Ask / Companion / Mine.
|
||||
- Grow Legacy root HTML (`yuxingu.html`, `pages/`) for new UI.
|
||||
|
||||
---
|
||||
|
||||
## Layout notes
|
||||
|
||||
- HomeWash: peach gradient body + Decode form + white ContentSheet.
|
||||
- Secondary: TopBar + padded content.
|
||||
- Keyboard: inputs must not hide primary CTA (scroll / visualViewport aware when needed).
|
||||
|
||||
---
|
||||
|
||||
## Checklist before Done
|
||||
|
||||
- [ ] Tokens only
|
||||
- [ ] Catalog component reused or catalog updated
|
||||
- [ ] 44px touch
|
||||
- [ ] Safe area
|
||||
- [ ] States + compliance if needed
|
||||
- [ ] `npm run build:h5`
|
||||
@@ -0,0 +1,47 @@
|
||||
# Platform Contract — WeChat Mini Program
|
||||
|
||||
Client: `apps/mini-program`.
|
||||
Design language shared with H5; **implementation is native mini-program**, not Vue SFC reuse.
|
||||
|
||||
Tokens: map `packages/ui` values into `app.wxss` / CSS variables supported by the base library — do not fork a second palette.
|
||||
|
||||
---
|
||||
|
||||
## MUST
|
||||
|
||||
- Use Mini Program lifecycle (`onLoad` / `onShow` / …) and `wx` APIs.
|
||||
- Native navigation (`wx.navigateTo`, tabBar in `app.json`).
|
||||
- Components under `components/`; pages call `services/*` only (same idea as H5 sdk).
|
||||
- Support: share (`onShareAppMessage`), user authorization, payment flow when enabled.
|
||||
- Touch ≥ 44px; rpx spacing aligned to 4/8/12/16… scale.
|
||||
- Same IA tabs and domain copy rules as H5.
|
||||
- Paywall / Membership decisions still from API — never local unlock only.
|
||||
|
||||
---
|
||||
|
||||
## MUST NOT
|
||||
|
||||
- `window` / `document` / DOM browser APIs.
|
||||
- Import Vue SFCs from `user-h5` as runtime.
|
||||
- Duplicate brand colors with new hex values.
|
||||
- Build UGC广场 or Consult marketplace in MVP.
|
||||
|
||||
---
|
||||
|
||||
## Mapping
|
||||
|
||||
| H5 | Mini Program |
|
||||
|---|---|
|
||||
| Vue page | `pages/*` |
|
||||
| Pinia | global / store pattern approved in playbook |
|
||||
| `@yuxingu/sdk` | same package or thin `services` wrapper |
|
||||
| CSS modules | `wxss` + shared token sheet |
|
||||
|
||||
---
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] No browser-only APIs
|
||||
- [ ] Tokens mapped 1:1
|
||||
- [ ] Share / auth / pay paths considered
|
||||
- [ ] Catalog names reused
|
||||
@@ -0,0 +1,44 @@
|
||||
# Platform Contract — Website (Desktop / Marketing Web)
|
||||
|
||||
Future or secondary surfaces (landing, SEO pages, admin beyond mobile shell).
|
||||
Brand tokens identical to [../design-system.md](../design-system.md).
|
||||
|
||||
---
|
||||
|
||||
## MUST
|
||||
|
||||
- SEO basics: title / description / semantic headings on marketing pages.
|
||||
- Keyboard navigation and visible focus for interactive controls.
|
||||
- Hover states allowed as **enhancement**; core actions still work without hover.
|
||||
- Large screens: may use sidebar, table, multi-column — do not ship desktop-only flows that leave mobile broken if the same app is responsive.
|
||||
- Accessibility: contrast, labels, skip/focus order.
|
||||
- Admin (`apps/admin-h5`): denser List/Table OK; still use tokens (primary coral, not random admin blue).
|
||||
|
||||
---
|
||||
|
||||
## MUST NOT
|
||||
|
||||
- Purple SaaS gradient landing that ignores 愈心谷 peach/coral brand.
|
||||
- Heavy dashboard chrome on consumer marketing hero (see design-system home budget).
|
||||
- Medical / 吉凶 claims in SEO copy.
|
||||
|
||||
---
|
||||
|
||||
## Breakpoints
|
||||
|
||||
| Name | Guide |
|
||||
|---|---|
|
||||
| Mobile | < 768px — follow H5 patterns |
|
||||
| Tablet | 768–1024px — adapt columns, keep touch sizes |
|
||||
| Desktop | > 1024px — sidebar / multi-column allowed |
|
||||
|
||||
Do not merely scale desktop UI down to mobile.
|
||||
|
||||
---
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Tokens + brand voice
|
||||
- [ ] Keyboard / focus
|
||||
- [ ] Responsive behavior explicit
|
||||
- [ ] SEO for public pages
|
||||
@@ -0,0 +1,65 @@
|
||||
# Domain Language — Ubiquitous Terms
|
||||
|
||||
Use ONLY these words in code, API, UI copy (Chinese labels noted).
|
||||
Do not invent synonyms (Customer / Client / Account) unless added here via ADR.
|
||||
|
||||
**Bounded contexts / aggregates / ER:** [domain/domain-map.md](domain/domain-map.md)
|
||||
**Product feature tree:** [product/feature-map.md](product/feature-map.md)
|
||||
|
||||
## Identity & access
|
||||
|
||||
| Term | Meaning | Not |
|
||||
|---|---|---|
|
||||
| **Visitor** | 未登录访客;可有匿名 device id | Guest(勿混用) |
|
||||
| **User** | 已注册主体(有 user id) | Customer / Client |
|
||||
| **Member** | 同 User:已注册用户的业务称呼;代码字段优先 `user` | — |
|
||||
| **VIP** | 付费会员期内的 User(membership active) | Member(勿把所有注册用户叫 VIP) |
|
||||
| **Session** | 登录态 / token 会话 | — |
|
||||
|
||||
## Commerce
|
||||
|
||||
| Term | Meaning |
|
||||
|---|---|
|
||||
| **Subscription** | 会员订阅计划(月/季/年) |
|
||||
| **Membership** | 用户当前会员权益状态(是否 VIP、到期时间、额度) |
|
||||
| **Order** | 支付订单(报告解锁或订阅) |
|
||||
| **Payment** | 一笔支付尝试 / 渠道回调结果 |
|
||||
| **Refund** | 退款记录 |
|
||||
| **Unlock** | 对某 Report 的购买解锁(非 VIP 也可单次解锁) |
|
||||
|
||||
## Profile & content
|
||||
|
||||
| Term | Meaning |
|
||||
|---|---|
|
||||
| **Profile** | 档案:自己或 TA 的生日等输入 |
|
||||
| **Self Profile** | relation = self |
|
||||
| **Other Profile** | relation = other(TA) |
|
||||
| **Decode** | 愈心解码报告(数字性格 + 体质建议) |
|
||||
| **Report** | 统称:Decode / Match / 尊享报告等可交付物 |
|
||||
| **Match** | 双人/家庭契合度报告 |
|
||||
| **Scale** | 心理量表 |
|
||||
| **ScaleResult** | 量表作答与计分结果 |
|
||||
|
||||
## Retention & AI
|
||||
|
||||
| Term | Meaning |
|
||||
|---|---|
|
||||
| **Companion** | 陪伴域:节气、心情 |
|
||||
| **SolarTerm** | 二十四节气内容单元 |
|
||||
| **Mood** | 每日心情打卡 |
|
||||
| **Ask** | 「问」能力:基于 Profile 的解读对话 |
|
||||
| **Consult** | 真人顾问咨询(后置) |
|
||||
|
||||
## Platform
|
||||
|
||||
| Term | Meaning |
|
||||
|---|---|
|
||||
| **user-h5** | 用户 H5 客户端 |
|
||||
| **mini-program** | 微信小程序客户端 |
|
||||
| **api** | Go 后端唯一服务 |
|
||||
| **Legacy** | 根目录旧静态原型,只读 |
|
||||
|
||||
## Naming in code
|
||||
|
||||
- Go packages / JSON: `user`, `profile`, `report`, `order`, `membership`, `scale`
|
||||
- Never: `customer`, `client` (except HTTP client), `account` (unless wallet later + ADR)
|
||||
@@ -0,0 +1,6 @@
|
||||
# Domain docs
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| [../domain.md](../domain.md) | Ubiquitous language — terms only |
|
||||
| [domain-map.md](domain-map.md) | Bounded contexts, aggregates, ER sketch |
|
||||
@@ -0,0 +1,183 @@
|
||||
# Domain Map — 愈心谷(DDD 视角)
|
||||
|
||||
给后端 / DB / OpenAPI / SDK 用的**能力域与实体图**。
|
||||
词汇以 [../domain.md](../domain.md) 为准;产品范围以 [../product/feature-map.md](../product/feature-map.md) 为准。
|
||||
竞品能力对照:[../product/cece-feature-map.md](../product/cece-feature-map.md)。
|
||||
|
||||
AI 生成表结构或 API 时:先落本图中的 Context / Aggregate,再写 migration;禁止发明未列出的聚合根名。
|
||||
|
||||
---
|
||||
|
||||
## 1. Bounded Contexts
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
|
||||
│ Identity │──▶│ Profile │──▶│ Discovery │
|
||||
│ (User) │ │ Life Archive│ │ Decode/Scale│
|
||||
└─────────────┘ └──────┬───────┘ └──────┬──────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────┐ ┌─────────────┐
|
||||
│ Relationship │ │ Ask │
|
||||
│ Match │ │ Companion │
|
||||
└──────┬───────┘ └──────┬──────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────────────────────────────┐
|
||||
│ Commerce │
|
||||
│ Subscription / Order / Unlock │
|
||||
└─────────────────────────────────┘
|
||||
│
|
||||
┌──────────────┼──────────────┐
|
||||
▼ ▼ ▼
|
||||
ContentFeed GrowthShare Consult(*)
|
||||
(* later)
|
||||
```
|
||||
|
||||
| Context | 职责 | MVP |
|
||||
|---|---|---|
|
||||
| **Identity** | Visitor/User/Session | Yes |
|
||||
| **Profile** | Self/Other 生命档案 | Yes |
|
||||
| **Discovery** | Decode、Scale、Report 生成 | Yes |
|
||||
| **Relationship** | Match | Yes |
|
||||
| **Ask** | 档案上下文对话、额度 | Skeleton |
|
||||
| **Companion** | SolarTerm、Mood | Skeleton |
|
||||
| **Commerce** | Subscription、Membership、Order、Unlock、Payment | Yes (mock) |
|
||||
| **Content** | Feed 配置 | Static OK |
|
||||
| **Growth** | Share 卡片元数据 | Minimal |
|
||||
| **Consult** | 真人顾问 Marketplace | No |
|
||||
| **Recommendation** | 推荐 | V1 rules |
|
||||
|
||||
---
|
||||
|
||||
## 2. Aggregates & Entities(命名强制)
|
||||
|
||||
### Identity
|
||||
|
||||
| Type | Name | Notes |
|
||||
|---|---|---|
|
||||
| Aggregate | **User** | 注册主体 |
|
||||
| Entity | Session | token 会话 |
|
||||
| Entity | DeviceIdentity | Visitor 匿名 |
|
||||
|
||||
### Profile(生命档案)
|
||||
|
||||
| Type | Name | Notes |
|
||||
|---|---|---|
|
||||
| Aggregate | **Profile** | `relation`: self \| other |
|
||||
| VO | BirthInput | date;time/place optional later |
|
||||
| VO | RelationType | partner/family/friend/… |
|
||||
|
||||
### Discovery
|
||||
|
||||
| Type | Name | Notes |
|
||||
|---|---|---|
|
||||
| Aggregate | **Report** | type: decode \| match \| … |
|
||||
| Domain Svc | DecodeEngine | 可复算;结果入 Report |
|
||||
| Aggregate | **Scale** | 量表定义 |
|
||||
| Entity | ScaleQuestion | |
|
||||
| Aggregate | **ScaleResult** | 作答 + 计分 |
|
||||
|
||||
### Relationship
|
||||
|
||||
| Type | Name | Notes |
|
||||
|---|---|---|
|
||||
| Aggregate | **Match** | 引用两个 Profile;产出 Report 或嵌入 |
|
||||
|
||||
### Ask / Companion
|
||||
|
||||
| Type | Name | Notes |
|
||||
|---|---|---|
|
||||
| Aggregate | **AskThread** | 挂 profile_id |
|
||||
| Entity | AskMessage | role user/assistant |
|
||||
| Entity | AskQuota | 与 Membership 联动 |
|
||||
| Aggregate | **Mood** | 日维度打卡 |
|
||||
| Read Model | **SolarTerm** | 日历内容;可配置表 |
|
||||
|
||||
### Commerce
|
||||
|
||||
| Type | Name | Notes |
|
||||
|---|---|---|
|
||||
| Aggregate | **Subscription** | 计划 SKU |
|
||||
| Aggregate | **Membership** | 用户权益状态 |
|
||||
| Aggregate | **Order** | 订阅或 Unlock |
|
||||
| Entity | Payment | mock / 渠道 |
|
||||
| Entity | Unlock | order → report 解锁 |
|
||||
|
||||
### Content / Growth(薄)
|
||||
|
||||
| Type | Name | Notes |
|
||||
|---|---|---|
|
||||
| Entity | FeedItem | 运营配置 |
|
||||
| VO | SharePayload | 分享卡字段 |
|
||||
|
||||
### Consult(Later)
|
||||
|
||||
| Type | Name | Notes |
|
||||
|---|---|---|
|
||||
| Aggregate | Consultant | |
|
||||
| Aggregate | ConsultOrder | |
|
||||
| Entity | ConsultSession | |
|
||||
|
||||
---
|
||||
|
||||
## 3. 关键关系(ER 草图)
|
||||
|
||||
```
|
||||
User 1──* Profile
|
||||
Profile 1──* Report
|
||||
Profile 1──* AskThread
|
||||
User 1──* ScaleResult
|
||||
User 1──0..1 Membership
|
||||
User 1──* Order
|
||||
Order 0..1── Unlock ──▶ Report
|
||||
Profile ── Match ── Profile
|
||||
User 1──* Mood
|
||||
```
|
||||
|
||||
权益规则:**Membership / Unlock 只由服务端判定**;客户端不可信任。
|
||||
|
||||
---
|
||||
|
||||
## 4. Context → 代码落点
|
||||
|
||||
| Context | Go | H5 |
|
||||
|---|---|---|
|
||||
| Identity | `internal/service/user` | login / mine |
|
||||
| Profile | `service/profile` | decode form, mine |
|
||||
| Discovery | `service/report`, `service/scale` | decode, explore, report |
|
||||
| Relationship | `service/match` | match |
|
||||
| Ask | `service/ask` | ask tab |
|
||||
| Companion | `service/companion` | companion tab |
|
||||
| Commerce | `service/order`, `membership` | paywall, mine |
|
||||
|
||||
包名只用 `domain.md` 词汇:`user` `profile` `report` `order` `membership` `scale` `ask` `mood`。
|
||||
|
||||
---
|
||||
|
||||
## 5. 测测域 → 愈心谷域 映射
|
||||
|
||||
| 测测概念 | 愈心谷 |
|
||||
|---|---|
|
||||
| 星盘档案 | **Profile**(生日+体质相关输入) |
|
||||
| 测测 AI | **Ask** |
|
||||
| 真人 1v1 | **Consult**(后置) |
|
||||
| MBTI 等 | **Scale** |
|
||||
| 缘分合盘 | **Match**(合规叙事) |
|
||||
| 今日运势 | **SolarTerm** + 生活建议(替换) |
|
||||
| 会员 | **Subscription / Membership** |
|
||||
| AI 玩法广场 | **[No] MVP** |
|
||||
| 心情打卡 | **Mood** |
|
||||
| 沙盘/心情小镇 | **[No]** |
|
||||
|
||||
---
|
||||
|
||||
## 6. 生成顺序(给 AI)
|
||||
|
||||
1. 改范围 → 更新 `product/feature-map.md` MVP 标记
|
||||
2. 新实体 → 本文件 + `domain.md` 词条(若新词)
|
||||
3. migration → `playbooks/new-table.md`
|
||||
4. API → `playbooks/add-api.md` + OpenAPI
|
||||
5. 页面 → `playbooks/new-page.md` + design contract
|
||||
|
||||
下一步可选:单独 `apps/docs/erd.md` 或 migrations 初稿(本任务不强制)。
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"success_example": {
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"summary": "简版结论占位",
|
||||
"profile_id": "p_123"
|
||||
}
|
||||
},
|
||||
"error_example": {
|
||||
"code": 30001,
|
||||
"message": "invalid birth date"
|
||||
},
|
||||
"list_example": {
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"list": [{ "slug": "mbti", "name": "MBTI" }],
|
||||
"total": 1,
|
||||
"page": 1,
|
||||
"page_size": 20
|
||||
}
|
||||
},
|
||||
"_comment": "Never use {success:true} or {ok:true} as root."
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
//go:build ignore
|
||||
|
||||
// EXAMPLE — reference shape for AI. Not compiled into apps/api.
|
||||
package examples
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type apiBody struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type DecodeInput struct {
|
||||
Year int
|
||||
Month int
|
||||
Day int
|
||||
}
|
||||
|
||||
type DecodeOutput struct {
|
||||
Summary string `json:"summary"`
|
||||
}
|
||||
|
||||
type DecodeService interface {
|
||||
Decode(ctx context.Context, in DecodeInput) (*DecodeOutput, error)
|
||||
}
|
||||
|
||||
type DecodeHandler struct {
|
||||
Svc DecodeService
|
||||
}
|
||||
|
||||
// Decode handles POST /api/v1/reports/decode
|
||||
func (h *DecodeHandler) Decode(c *gin.Context) {
|
||||
var req struct {
|
||||
Year int `json:"year" binding:"required"`
|
||||
Month int `json:"month" binding:"required"`
|
||||
Day int `json:"day" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, apiBody{Code: 10000, Message: "invalid request"})
|
||||
return
|
||||
}
|
||||
out, err := h.Svc.Decode(c.Request.Context(), DecodeInput(req))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, apiBody{Code: 30001, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, apiBody{Code: 0, Message: "success", Data: out})
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//go:build ignore
|
||||
|
||||
// EXAMPLE — reference shape for AI. Not compiled into apps/api.
|
||||
package examples
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type DecodeRepo interface {
|
||||
SaveDecode(ctx context.Context, userID string, summary string) error
|
||||
}
|
||||
|
||||
type DecodeServiceImpl struct {
|
||||
Repo DecodeRepo
|
||||
}
|
||||
|
||||
func (s *DecodeServiceImpl) Decode(ctx context.Context, in DecodeInput) (*DecodeOutput, error) {
|
||||
if in.Year < 1900 || in.Month < 1 || in.Month > 12 || in.Day < 1 || in.Day > 31 {
|
||||
return nil, fmt.Errorf("invalid birth date")
|
||||
}
|
||||
// engine would run here
|
||||
summary := "简版结论占位"
|
||||
if err := s.Repo.SaveDecode(ctx, "user-from-ctx", summary); err != nil {
|
||||
return nil, fmt.Errorf("save decode: %w", err)
|
||||
}
|
||||
return &DecodeOutput{Summary: summary}, nil
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//go:build ignore
|
||||
|
||||
// EXAMPLE — table-driven unit test shape.
|
||||
package examples
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestClampBirthMonth(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
month int
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "ok", month: 6, wantErr: false},
|
||||
{name: "zero", month: 0, wantErr: true},
|
||||
{name: "thirteen", month: 13, wantErr: true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := validateMonth(tt.month)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Fatalf("validateMonth(%d) err=%v wantErr=%v", tt.month, err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func validateMonth(m int) error {
|
||||
if m < 1 || m > 12 {
|
||||
return errInvalid
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var errInvalid = errString("invalid")
|
||||
|
||||
type errString string
|
||||
|
||||
func (e errString) Error() string { return string(e) }
|
||||
@@ -0,0 +1,93 @@
|
||||
# File Map — Who Owns What
|
||||
|
||||
## apps/api
|
||||
|
||||
```
|
||||
apps/api/
|
||||
cmd/server/ # main only: wire deps, start HTTP
|
||||
internal/
|
||||
handler/ # HTTP bind/unbind, validate input, call service interfaces
|
||||
service/<domain>/ # business rules, transactions orchestration
|
||||
repository/ # SQL / DB access only
|
||||
model/ # DB structs / domain structs (no HTTP types leakage preferred)
|
||||
middleware/ # auth, request id, recovery helpers
|
||||
config/ # env config
|
||||
pkg/ # small reusable libs (e.g. response envelope)
|
||||
migrations/ # schema versions
|
||||
```
|
||||
|
||||
### Forbidden placements
|
||||
|
||||
| Wrong | Right |
|
||||
|---|---|
|
||||
| SQL in `handler/` | `repository/` |
|
||||
| gin.Context in `repository/` | keep HTTP out of repo |
|
||||
| Business unlock rules only in UI | `service/` + persist |
|
||||
| Fat `pkg/utils` | domain package or focused pkg |
|
||||
|
||||
## apps/user-h5
|
||||
|
||||
```
|
||||
src/
|
||||
pages/ # route screens
|
||||
components/ # reusable UI
|
||||
api/ # thin wrappers → @yuxingu/sdk
|
||||
stores/ # pinia
|
||||
hooks/ # composables
|
||||
router/
|
||||
layouts/
|
||||
assets/
|
||||
```
|
||||
|
||||
No raw `fetch` in `pages/`.
|
||||
|
||||
## packages
|
||||
|
||||
| Package | Owns |
|
||||
|---|---|
|
||||
| `sdk` | HTTP client + adapters |
|
||||
| `types` | Shared TS domain types |
|
||||
| `utils` | Pure helpers |
|
||||
| `ui` | CSS tokens |
|
||||
|
||||
## .ai/
|
||||
|
||||
Rules, ADR, patterns, examples, playbooks, checklists. Not runtime code.
|
||||
|
||||
### .ai/product/ & .ai/domain/
|
||||
|
||||
| Path | Owns |
|
||||
|---|---|
|
||||
| `product/feature-map.md` | 愈心谷 L0/L1/L2 + MVP 标记 |
|
||||
| `product/cece-feature-map.md` | 测测竞品合并 Feature Tree |
|
||||
| `domain/domain-map.md` | Bounded contexts / aggregates / ER |
|
||||
| `domain.md` | Ubiquitous terms only |
|
||||
|
||||
### .ai/design/
|
||||
|
||||
| Path | Owns |
|
||||
|---|---|
|
||||
| `design-system.md` | Tokens, color, type, spacing, motion, voice |
|
||||
| `component-catalog.md` | Allowed reusable UI components |
|
||||
| `platform/*.md` | H5 / mini-program / website / Flutter limits |
|
||||
|
||||
Runtime CSS tokens: `packages/ui/src/tokens.css` (must stay aligned with design-system).
|
||||
|
||||
## apps/docs/
|
||||
|
||||
Product / business docs (not engineering rules):
|
||||
|
||||
| Path | Owns |
|
||||
|---|---|
|
||||
| `README.md` | Reading order |
|
||||
| `analysis/` | Competitor teardowns |
|
||||
| `prd-mvp.md` | MVP scope & acceptance |
|
||||
| `business-model.md` | Revenue layers |
|
||||
| `product-roadmap.md` | Phased vertical slices |
|
||||
| `adr/` | Optional business-facing ADRs |
|
||||
|
||||
Engineering standards live in `.ai/` only; `apps/docs/standards/*` is deprecated.
|
||||
|
||||
## Legacy (do not extend)
|
||||
|
||||
Root `yuxingu.html`, `pages/`, `css/`, `js/`, `server.py`.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Forbidden — Never
|
||||
|
||||
AI obeys NEVER rules strictly.
|
||||
|
||||
## Code
|
||||
|
||||
- Never use `panic` on request paths.
|
||||
- Never ignore errors (`_ = err` on important paths).
|
||||
- Never create circular dependencies.
|
||||
- Never put SQL in handlers.
|
||||
- Never put `gin.Context` in repositories.
|
||||
- Never use package-level mutable globals for request state.
|
||||
- Never use `SELECT *` in new SQL.
|
||||
- Never introduce `any` casually in TypeScript.
|
||||
- Never put `fetch` directly in Vue pages.
|
||||
|
||||
## API / data
|
||||
|
||||
- Never invent response shapes other than `{code,message,data}`.
|
||||
- Never use POST for pure read/query.
|
||||
- Never skip migration when schema changes.
|
||||
- Never hard-delete user PII without explicit task (use soft delete).
|
||||
|
||||
## Security / deploy
|
||||
|
||||
- Never hardcode passwords, tokens, or secrets.
|
||||
- Never commit `.env` or private keys.
|
||||
- Never use Docker image tag `latest` in production.
|
||||
- Never log full birthday + answers payloads casually.
|
||||
|
||||
## Product / process
|
||||
|
||||
- Never invent medical efficacy or 吉凶祸福 copy.
|
||||
- Never reverse an Accepted ADR without a new ADR + approval.
|
||||
- Never modify files outside the current task.
|
||||
- Never extend Legacy root HTML unless the task is migration.
|
||||
- Never guess requirements — ASK FIRST.
|
||||
@@ -0,0 +1,14 @@
|
||||
# Pattern: CRUD slice
|
||||
|
||||
For a resource `Foo`:
|
||||
|
||||
1. Migration `foo` table (`id, created_at, updated_at, deleted_at`, …)
|
||||
2. `model.Foo`
|
||||
3. `repository` methods: Get / List / Create / Update / SoftDelete
|
||||
4. `service` with authz + validation
|
||||
5. `handler` REST routes
|
||||
6. OpenAPI paths
|
||||
7. SDK methods + types
|
||||
8. UI only if user-facing
|
||||
|
||||
List endpoints always paginate (`page`, `page_size`, `total`).
|
||||
@@ -0,0 +1,37 @@
|
||||
# Pattern: Handler
|
||||
|
||||
## Responsibility
|
||||
|
||||
HTTP only: bind JSON/query → validate → call service interface → map errors to envelope.
|
||||
|
||||
## Shape
|
||||
|
||||
```go
|
||||
type ReportService interface {
|
||||
Decode(ctx context.Context, in DecodeInput) (*DecodeOutput, error)
|
||||
}
|
||||
|
||||
type ReportHandler struct {
|
||||
svc ReportService
|
||||
}
|
||||
|
||||
func (h *ReportHandler) Decode(c *gin.Context) {
|
||||
var req DecodeRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Fail(c, 400, 10000, "invalid request")
|
||||
return
|
||||
}
|
||||
out, err := h.svc.Decode(c.Request.Context(), toInput(req))
|
||||
if err != nil {
|
||||
// map domain errors → codes
|
||||
response.Fail(c, 400, 30001, err.Error())
|
||||
return
|
||||
}
|
||||
response.OK(c, out)
|
||||
}
|
||||
```
|
||||
|
||||
## Never
|
||||
|
||||
- SQL here
|
||||
- Business unlock math here (belongs service)
|
||||
@@ -0,0 +1,13 @@
|
||||
# Pattern: JWT / Bearer
|
||||
|
||||
## Middleware
|
||||
|
||||
1. Read `Authorization: Bearer <token>`
|
||||
2. Parse/verify
|
||||
3. Put `user_id` into context
|
||||
4. Reject with code in 1xxxx if missing/invalid
|
||||
|
||||
## Service
|
||||
|
||||
Always take `userID` from context for mutating ops.
|
||||
Never trust body `user_id` from client for ownership.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Pattern: Pagination
|
||||
|
||||
## Query
|
||||
|
||||
`?page=1&page_size=20`
|
||||
|
||||
Defaults: page=1, page_size=20, max page_size=100.
|
||||
|
||||
## Response data
|
||||
|
||||
```json
|
||||
{
|
||||
"list": [],
|
||||
"total": 0,
|
||||
"page": 1,
|
||||
"page_size": 20
|
||||
}
|
||||
```
|
||||
|
||||
## SQL
|
||||
|
||||
`LIMIT $n OFFSET $m` with bound params. Always return `total` via `COUNT(*)` (or approximate only with ADR).
|
||||
@@ -0,0 +1,24 @@
|
||||
# Pattern: Repository
|
||||
|
||||
## Responsibility
|
||||
|
||||
Persistence only. Parameterized SQL. Map rows ↔ model.
|
||||
|
||||
## Shape
|
||||
|
||||
```go
|
||||
func (r *ReportRepository) SaveReport(ctx context.Context, m *model.Report) error {
|
||||
const q = `INSERT INTO report (id, user_id, kind, payload, created_at, updated_at)
|
||||
VALUES ($1,$2,$3,$4,now(),now())`
|
||||
_, err := r.db.ExecContext(ctx, q, m.ID, m.UserID, m.Kind, m.Payload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("insert report: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
## Never
|
||||
|
||||
- `SELECT *` in new code
|
||||
- Business policy (VIP checks) here — return data, let service decide
|
||||
@@ -0,0 +1,31 @@
|
||||
# Pattern: Service
|
||||
|
||||
## Responsibility
|
||||
|
||||
Business rules, authorization, orchestration, transactions.
|
||||
|
||||
## Shape
|
||||
|
||||
```go
|
||||
type ReportRepo interface {
|
||||
SaveReport(ctx context.Context, r *model.Report) error
|
||||
}
|
||||
|
||||
type ReportService struct {
|
||||
repo ReportRepo
|
||||
}
|
||||
|
||||
func (s *ReportService) Decode(ctx context.Context, in DecodeInput) (*DecodeOutput, error) {
|
||||
if err := in.Validate(); err != nil {
|
||||
return nil, fmt.Errorf("validate decode: %w", err)
|
||||
}
|
||||
// rules / engine
|
||||
// persist via repo
|
||||
return out, nil
|
||||
}
|
||||
```
|
||||
|
||||
## Never
|
||||
|
||||
- Import `gin`
|
||||
- Bypass repo with ad-hoc SQL drivers scattered around
|
||||
@@ -0,0 +1,19 @@
|
||||
# Playbook: Add API
|
||||
|
||||
Use when: “新增xxx接口”
|
||||
|
||||
## Steps
|
||||
|
||||
1. **OpenAPI** — add path to `proto/openapi.yaml`
|
||||
2. **Migration** — if new/changed table (`apps/api/migrations/`)
|
||||
3. **Model** — `internal/model`
|
||||
4. **Repository** — SQL only
|
||||
5. **Service** — business + authz
|
||||
6. **Handler** — bind + envelope; interface at handler
|
||||
7. **Wire** — register route in `cmd/server` or router file
|
||||
8. **Test** — at least service/engine unit test if logic-heavy
|
||||
9. **SDK/types** — update `packages/sdk` + `packages/types` if clients need it
|
||||
10. **Commands** — `go test ./...`, hit with curl
|
||||
11. **Review + DoD + checklist/feature.md**
|
||||
|
||||
Follow patterns: `handler.md` `service.md` `repository.md` `pagination.md`.
|
||||
@@ -0,0 +1,14 @@
|
||||
# Playbook: Login / Auth
|
||||
|
||||
## Steps
|
||||
|
||||
1. Cite ADR-0004
|
||||
2. Define Visitor vs User in API behavior (`.ai/domain.md`)
|
||||
3. Issue Bearer token; document in OpenAPI
|
||||
4. Middleware extracts `user_id`
|
||||
5. Persist session/user as designed (Postgres MVP; Redis deferred)
|
||||
6. H5: store token via adapter (`localStorage` key `yxg_token`)
|
||||
7. SDK `getToken` wired
|
||||
8. Tests: invalid token / expired / ownership
|
||||
9. Security review checklist
|
||||
10. Never accept `X-User-Id` alone as auth
|
||||
@@ -0,0 +1,18 @@
|
||||
# Playbook: New H5 Page
|
||||
|
||||
Use when: “新增页面”
|
||||
|
||||
## Steps
|
||||
|
||||
1. Confirm IA tab vs secondary page (`.ai/ui.md`)
|
||||
2. Read `.ai/design/design-system.md` + `component-catalog.md` + `design/platform/h5.md`
|
||||
3. Reuse catalog components; update catalog if adding a new one
|
||||
4. Add route in `apps/user-h5/src/router`
|
||||
5. Add `pages/XxxPage.vue` (PascalCase); tokens only (no raw brand hex)
|
||||
6. Extract components if file approaches 300–400 lines
|
||||
7. Data via `src/api` → `@yuxingu/sdk` only
|
||||
8. Use domain words from `.ai/domain.md`
|
||||
9. Loading / empty / error states
|
||||
10. Compliance copy if report-like
|
||||
11. `npm run build:h5`
|
||||
12. Review + checklist/feature.md
|
||||
@@ -0,0 +1,14 @@
|
||||
# Playbook: New Table
|
||||
|
||||
Use when: “新建表 / 加字段”
|
||||
|
||||
## Steps
|
||||
|
||||
1. Name with `snake_case` (`.ai/database.md` + `.ai/domain.md`)
|
||||
2. Columns include `id, created_at, updated_at, deleted_at`
|
||||
3. Write migration Up (+ Down)
|
||||
4. Index FKs
|
||||
5. Update `model` + repository
|
||||
6. Never ship app code that queries columns not migrated
|
||||
7. Document in PR
|
||||
8. Review (Deployment + Docs items)
|
||||
@@ -0,0 +1,14 @@
|
||||
# Playbook: Payment / Unlock / Subscription
|
||||
|
||||
## Steps
|
||||
|
||||
1. Terms: Order, Payment, Unlock, Subscription, Membership, VIP (`.ai/domain.md`)
|
||||
2. Server creates Order with amount/currency/product ref
|
||||
3. Client never sets final price unilaterally
|
||||
4. Payment callback verifies signature + idempotency
|
||||
5. On success: grant Membership or Unlock in service transaction
|
||||
6. Report access checks Membership/Unlock server-side every time
|
||||
7. Migration for `payment_order` / related tables
|
||||
8. Tests: double callback, wrong amount, replay
|
||||
9. No secrets in frontend
|
||||
10. Feature checklist + security review
|
||||
@@ -0,0 +1,12 @@
|
||||
# Product docs for AI agents
|
||||
|
||||
| File | Audience | Purpose |
|
||||
|---|---|---|
|
||||
| [STRATEGY.md](STRATEGY.md) | All agents | **执行优先级**:先测测 parity,Vision v1 已封存 |
|
||||
| [feature-map.md](feature-map.md) | PRD / H5 / API | 愈心谷差异化能力树(Design Vision v1) |
|
||||
| [cece-feature-map.md](cece-feature-map.md) | Competitor / parity | 测测 Feature Tree — 下一版对齐主参考 |
|
||||
| [../domain/domain-map.md](../domain/domain-map.md) | Backend / DB / OpenAPI | Bounded contexts & entities |
|
||||
| [../domain.md](../domain.md) | All code | Ubiquitous language (terms only) |
|
||||
|
||||
Product narrative docs (human PRD): `apps/docs/`.
|
||||
**冲突时:** `STRATEGY.md` 的 parity 执行 > Vision v1 创新项。
|
||||
@@ -0,0 +1,32 @@
|
||||
# Product Strategy Snapshot
|
||||
|
||||
## Sealed design (this repo state)
|
||||
|
||||
Documented vision: **愈心谷差异化** — 数字性格 + 中医体质 + 关系档案 + 节气,学测测飞轮但替换运势主叙事。
|
||||
|
||||
Canonical docs at seal time:
|
||||
|
||||
- `product/feature-map.md` — 愈心谷能力树(含 MVP 标记)
|
||||
- `product/cece-feature-map.md` — 测测竞品树
|
||||
- `domain/domain-map.md` — 领域模型
|
||||
- `apps/docs/prd-mvp.md` · `business-model.md` · `product-roadmap.md`
|
||||
- `.ai/design/*` — Design System Contract
|
||||
|
||||
Treat the above as **Design Vision v1(已封存)** — 可对照、可回退,不作为下一迭代的强制做完清单。
|
||||
|
||||
---
|
||||
|
||||
## Next build direction(执行优先)
|
||||
|
||||
**先出一版和测测结构类似的产品,不要一上来就创新。**
|
||||
|
||||
| 原则 | 含义 |
|
||||
|---|---|
|
||||
| IA 对齐测测 | 首页发现 · 问(AI)· 在线/咨询位 · 消息或可后置 · 我的 |
|
||||
| 能力对齐测测漏斗 | 测评拉新 → 档案 → AI 问 → 会员 → 咨询占位 |
|
||||
| 叙事可先「泛心理 + 星座/性格」 | 体质/节气差异化后置,不阻塞首版 |
|
||||
| 不做冷启动重资产 | 不做达人双边冷启动、不做硬件、不做 UGC 玩法广场首版 |
|
||||
|
||||
差异化 Vision v1 在首版跑通测测式漏斗后再渐进引入(Decode 体质、节气陪伴等)。
|
||||
|
||||
执行时以即将撰写的 **Cece-parity PRD / feature-map-v0** 为准;冲突时:**parity 执行 > Vision v1 创新项**。
|
||||
@@ -0,0 +1,307 @@
|
||||
# 测测 App — Feature Map(竞品 · 合并视角)
|
||||
|
||||
来源:[人人都是产品经理 · 测测深度体验](https://www.woshipm.com/evaluating/6391148.html) + 公开产品形态 / 行业常见能力。
|
||||
用途:竞品分析与 AI 产品设计对照。**不代表**测测未公开内部功能;版本会变。
|
||||
|
||||
视角说明:
|
||||
|
||||
| 视角 | 回答的问题 | 本文件位置 |
|
||||
|---|---|---|
|
||||
| L0 Product IA | 用户打开 App 看到什么、怎么付费 | §1 L0 |
|
||||
| L1 Capability | 系统背后有哪些能力域 | §2 挂在各入口下 / §3 横切 |
|
||||
| 演进 | 工具 → AI 顾问 → Life OS | §4 |
|
||||
|
||||
愈心谷落地地图见 [feature-map.md](feature-map.md)。领域实体见 [../domain/domain-map.md](../domain/domain-map.md)。
|
||||
|
||||
---
|
||||
|
||||
## §0 一级能力域总览(Domain 视角)
|
||||
|
||||
```
|
||||
测测能力域
|
||||
├── 1. 用户体系
|
||||
├── 2. 首页与内容分发
|
||||
├── 3. AI 智能助手
|
||||
├── 4. 测试与测算
|
||||
├── 5. 星座体系
|
||||
├── 6. 命理体系
|
||||
├── 7. 塔罗体系
|
||||
├── 8. 情感关系分析
|
||||
├── 9. 心理与自我探索
|
||||
├── 10. 社区生态
|
||||
├── 11. 专家咨询
|
||||
├── 12. 内容体系
|
||||
├── 13. 会员与商业化
|
||||
├── 14. 用户增长
|
||||
└── 15. 数据与推荐系统
|
||||
```
|
||||
|
||||
演进增量(行业方向,非全部已上线):人生档案 / AI Agent / 情绪 OS / 梦境 / 冥想 / 中医体质 / 易经决策 / 多模态 / 长期成长模型。
|
||||
|
||||
---
|
||||
|
||||
## §1 L0 — App 信息架构(用户路径)
|
||||
|
||||
```
|
||||
打开 App
|
||||
→ 首页发现与激活
|
||||
→ 问(AI 战略入口)
|
||||
→ 在线(真人 Marketplace)
|
||||
→ 消息(关系与通知)
|
||||
→ 我的(资产 / 会员)
|
||||
横切:增长运营 · 集团生态
|
||||
```
|
||||
|
||||
```
|
||||
测测 App
|
||||
├── 首页
|
||||
├── 消息
|
||||
├── 问
|
||||
├── 在线
|
||||
├── 我的
|
||||
├── 增长运营
|
||||
└── 集团生态
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## §2 L0 × L1 × L2 — 合并功能树
|
||||
|
||||
### 1. 首页(发现与激活中心)
|
||||
|
||||
#### 1.1 用户建档 → 生命档案系统
|
||||
|
||||
| 二级 | 三级 |
|
||||
|---|---|
|
||||
| 1.1.1 创建本人档案 | 出生日期 / 时间 / 地点 / 性别 |
|
||||
| 1.1.2 创建关系档案 | 伴侣 / 家人 / 朋友 / 暗恋对象等 |
|
||||
| 1.1.3 档案管理 | 编辑 / 删除 / 多档案切换 / AI 关联分析 |
|
||||
| 1.1.4 兴趣与状态标签 | 爱情·事业·财富·健康·性格·家庭;情感/职业状态 |
|
||||
|
||||
#### 1.2 工具入口宫格(前台)↔ 能力归类(后台)
|
||||
|
||||
| 前台入口 | 归属能力域 |
|
||||
|---|---|
|
||||
| I人E人 / MBTI | 心理测评 / 测试系统 |
|
||||
| 星座 / 星盘 | 星座体系 |
|
||||
| 缘分合盘 | 情感关系 + 星座 |
|
||||
| 沙盘 | 心理沉浸工具 |
|
||||
| 陪伴小星 | AI 陪伴 |
|
||||
| 倾诉 | 咨询 / AI 入口 |
|
||||
| 商城 | 商业化 |
|
||||
| AI 玩法广场 | 内容生态 · GPT Store 型 |
|
||||
| 更多 | 收纳扩展 |
|
||||
|
||||
#### 1.3 首页推荐与信息流
|
||||
|
||||
- 今日运势 / 热门测试 / AI 入口 / 专家推荐 / 热门文章 / 社区动态
|
||||
- 文章 · 视频 · 故事 · 达人内容 · AI 生成内容 · 个性推荐
|
||||
|
||||
#### 1.4 个性化推荐
|
||||
|
||||
- 按生日 / 兴趣 / 历史行为 / 付费意愿推荐
|
||||
|
||||
#### 1.5 AI 玩法广场(≈ GPT Store + 传播)
|
||||
|
||||
- 玩法模板 → Prompt 应用 → 用户/达人创建 AI 小应用 → 热度榜 → 裂变
|
||||
- 示例形态:SBTI、答案之书、三生三世你和 Ta、灵魂伴侣等
|
||||
|
||||
#### 1.6 沉浸体验入口
|
||||
|
||||
- 3D 心理沙盘(投射分析)
|
||||
- AI 心情小镇入口
|
||||
|
||||
---
|
||||
|
||||
### 2. 消息(互动与触达)
|
||||
|
||||
| 二级 | 三级 |
|
||||
|---|---|
|
||||
| 2.1 AI 消息 | 会话提醒、未读 AI 对话 |
|
||||
| 2.2 达人消息 | 咨询会话、达人回复 |
|
||||
| 2.3 社区互动 | 赞评关私信通知 |
|
||||
| 2.4 系统通知 | 公告、合规、功能 |
|
||||
| 2.5 商业通知 | 会员到期、订单、活动 |
|
||||
|
||||
---
|
||||
|
||||
### 3. 问(核心战略 · AI Life Assistant)
|
||||
|
||||
实测:底部中央「问」Tab → 测测 AI;顶栏「测测AI ‖ 真人1v1」。
|
||||
|
||||
#### 3.1 AI 人格层
|
||||
|
||||
- 普通助手 / 情感陪伴 / 心理向疏导 / 星盘专家向 / 塔罗向 / 人生顾问
|
||||
- 报道中的灵犀 / 小智:更接近模式或子场景,非并列 Tab 级产品
|
||||
|
||||
#### 3.2 AI 聊天场景
|
||||
|
||||
- 一般聊天 · 情感倾诉 · 人生建议 · 性格分析 · 梦境解析 · 星座咨询 · 命理解读
|
||||
|
||||
#### 3.3 AI 上下文层(差异化)
|
||||
|
||||
- 当前用户 → 生命档案 → 关系档案 → 历史对话 → 情绪轨迹 → 长期记忆
|
||||
- UI:星盘维度 · 对象切换(自己/TA)· 深度思考 · 灵魂伴侣子入口
|
||||
|
||||
#### 3.4 AI 能力层(底层)
|
||||
|
||||
- LLM(心元等)· 心理知识库 · 星盘计算 · 测算模型 · 测试模型 · 推荐
|
||||
|
||||
#### 3.5 AI 报告生成
|
||||
|
||||
- 性格 / 爱情 / 职业 / 财富 / 综合人生报告
|
||||
|
||||
#### 3.6 AI 商业层
|
||||
|
||||
- 免费次数 → 会员扩容 → 高级模型/深度思考 → 转真人专家
|
||||
|
||||
#### 3.7 AI 心情小镇等沉浸
|
||||
|
||||
- 多虚拟倾诉师人设 · OCR/情感识别 · 角色陪伴
|
||||
|
||||
#### 3.8 已知能力缺口(公开评价)
|
||||
|
||||
- 偏被动响应(少主动触达)
|
||||
- 跨会话长期记忆不足
|
||||
- 引导问题偏运势,易被感知为「算命 AI」
|
||||
|
||||
---
|
||||
|
||||
### 4. 在线(真人 Marketplace)
|
||||
|
||||
```
|
||||
达人供应 → 平台撮合 → 交易 → 评价 → 复购 / 分佣
|
||||
```
|
||||
|
||||
| 二级 | 三级 |
|
||||
|---|---|
|
||||
| 4.1 专家类型 | 星座专家 · 塔罗师 · 命理师 · 心理/情感达人 |
|
||||
| 4.2 供给运营 | 达人资料 · 审核 · 培训激励(达人版工具) |
|
||||
| 4.3 咨询流程 | 列表 → 预约 → 支付 → 文字/语音/连麦 → 评价 |
|
||||
| 4.4 撮合与分佣 | 推荐排序 · 平台抽成 |
|
||||
|
||||
---
|
||||
|
||||
### 5. 我的(用户资产 → Life Profile)
|
||||
|
||||
| 二级 | 三级 |
|
||||
|---|---|
|
||||
| 5.1 账号 | 手机 / 微信 / Apple · 游客升级 |
|
||||
| 5.2 生命档案资产 | 本人档案 · 关系档案 · 编辑切换 |
|
||||
| 5.3 测试与报告资产 | 测试记录 · 报告库 · 收藏 |
|
||||
| 5.4 AI 资产 | 对话历史 · AI 报告 |
|
||||
| 5.5 会员与订单 | 订阅状态 · 解锁记录 · 咨询订单 |
|
||||
| 5.6 行为画像沉淀 | 浏览 / 测试 / 收藏 / 咨询记录 |
|
||||
|
||||
---
|
||||
|
||||
### 6. 增长运营(横切)
|
||||
|
||||
| 二级 | 三级 |
|
||||
|---|---|
|
||||
| 6.1 分享裂变 | 测试结果卡 · 邀请好友 · 社交传播 |
|
||||
| 6.2 裂变引擎(产品逻辑) | 结果分享 → 好友进入 → 建档 → 再传播 |
|
||||
| 6.3 内容获客 | SEO / 搜索 → 测试 → 注册 → 会员 |
|
||||
| 6.4 激励 | 签到 · 积分 · 等级 · 勋章 |
|
||||
| 6.5 广告 | 曾有;主动压缩干扰广告 |
|
||||
| 6.6 品牌 | 创始人/媒体露出;少大规模买量 |
|
||||
|
||||
---
|
||||
|
||||
### 7. 集团生态(Business Layer)
|
||||
|
||||
| 二级 | 三级 |
|
||||
|---|---|
|
||||
| 7.1 C 端 App | 测测主站 |
|
||||
| 7.2 达人平台 | 测测达人版 |
|
||||
| 7.3 教育延伸 | 快乐测测 |
|
||||
| 7.4 B 端 | 企业 EAP · 校园心理健康 |
|
||||
| 7.5 硬件 | 巴布家庭陪伴机器人(买断 + 模型协同) |
|
||||
| 7.6 模型底座 | 心元大模型备案与训练数据飞轮 |
|
||||
|
||||
---
|
||||
|
||||
## §3 能力域详表(便于对照数据库 / 模块)
|
||||
|
||||
### A. 测试系统
|
||||
|
||||
- **性格**:MBTI · 九型 · 性格/优势/弱点画像
|
||||
- **情感**:恋爱人格 · 伴侣匹配 · 关系状态 · 分手/婚恋向
|
||||
- **心理**:情绪 · 压力 · 焦虑 · 自我探索 · 心理画像
|
||||
- **趣味**:灵魂动物 · 前世 · 小游戏 · 趣味问答
|
||||
|
||||
### B. 星座体系
|
||||
|
||||
- 十二星座 · 星盘 · 上升/月亮 · 行星分析
|
||||
- 匹配:恋爱/友情/婚姻指数
|
||||
- 日运/周运/月运/年运
|
||||
|
||||
### C. 命理体系
|
||||
|
||||
- 八字:四柱 · 五行 · 十神 · 格局 · 大运 · 流年
|
||||
- 紫微:命盘 · 十二宫 · 主星 · 流年
|
||||
- 姓名/五格 · 风水建议
|
||||
|
||||
### D. 塔罗体系
|
||||
|
||||
- 抽牌:单牌 · 三牌 · 爱情/事业阵 · 趋势
|
||||
- AI 解读:牌义 · 组合 · 行动建议 · 情绪支持
|
||||
|
||||
### E. 情感关系
|
||||
|
||||
- 恋爱分析:双人星盘 · 合婚 · 性格匹配 · 相处建议
|
||||
- 关系管理:记录伴侣 · 关系变化 · 重要日期 · 情绪记录
|
||||
|
||||
### F. 心理成长
|
||||
|
||||
- 自我探索:性格 · 原生家庭 · 价值 · 内在需求
|
||||
- 情绪管理:记录 · 分析 · 安慰陪伴 · 放松
|
||||
- 成长计划:目标 · 每日练习 · 打卡 · 成长报告
|
||||
- 沉浸:沙盘 · 心情小镇
|
||||
|
||||
### G. 社区生态
|
||||
|
||||
- 内容社区:发帖评论赞藏分享
|
||||
- 用户关系:关注粉丝私信群组
|
||||
- 话题:星座讨论 · 情感故事 · 测试分享 · AI 内容
|
||||
|
||||
### H. 内容体系
|
||||
|
||||
- 文章:星座/情感/心理/命理
|
||||
- 视频:短视频 · 直播 · 课程
|
||||
|
||||
### I. 商业化
|
||||
|
||||
- 会员:月/季/年;权益含完整报告、AI 次数、专属内容、去广告等
|
||||
- 增值:单次报告 · 真人咨询 · 课程 · 商城
|
||||
|
||||
### J. 数据与推荐
|
||||
|
||||
- 数据:行为 · 情绪 · 测试 · 对话
|
||||
- 推荐:内容 · 测试 · 专家 · 商品
|
||||
|
||||
---
|
||||
|
||||
## §4 产品演进阶梯(分析用)
|
||||
|
||||
```
|
||||
测测 1.0 测试工具集合
|
||||
↓
|
||||
测测 2.0 AI 人生顾问(档案化问答 + 订阅 + 咨询)
|
||||
↓
|
||||
AI Life OS 用户长期人生数据库(记忆 · Agent · 多模态 · 具身)
|
||||
```
|
||||
|
||||
**第一梯队护城河(公开叙事)**:生命档案 · AI「问」· 关系系统 · AI 玩法广场
|
||||
**第二梯队获客**:MBTI · 星座星盘 · 塔罗 · 测评
|
||||
**第三梯队**:商城 · 广告 · 周边
|
||||
|
||||
---
|
||||
|
||||
## §5 与愈心谷对照(一句话)
|
||||
|
||||
学:**档案化 AI、五 Tab 战略位、订阅为主、关系对象、分享裂变、克制广告。**
|
||||
弃/降权:运势主叙事、塔罗/重玄学默认、UGC 玩法广场冷启动、达人双边、硬件、多智能体品牌矩阵。
|
||||
替换:数字性格 + 中医体质 + 节气陪伴 + 合规生活建议。
|
||||
|
||||
落地见 [feature-map.md](feature-map.md)。
|
||||
@@ -0,0 +1,212 @@
|
||||
# 愈心谷 — Product Feature Map
|
||||
|
||||
**权威产品能力树**(PRD / 路由 / 竖切范围以此为准)。
|
||||
竞品原文树:[cece-feature-map.md](cece-feature-map.md)
|
||||
领域实体:[../domain/domain-map.md](../domain/domain-map.md)
|
||||
词汇:[../domain.md](../domain.md) · PRD:`apps/docs/prd-mvp.md`
|
||||
|
||||
标记:`[MVP]` `[V1]` `[Later]` `[No]`
|
||||
|
||||
---
|
||||
|
||||
## L0 — App 信息架构
|
||||
|
||||
```
|
||||
愈心谷
|
||||
├── 首页 HomeWash:品牌 + Decode + Feed
|
||||
├── 探索 Scale / Decode / 轻工具
|
||||
├── 问 Ask(战略中心 Tab)
|
||||
├── 陪伴 SolarTerm + Mood
|
||||
├── 我的 Life Profile 资产
|
||||
├── 增长运营(横切)
|
||||
└── 平台生态(横切 · 后置)
|
||||
```
|
||||
|
||||
路径:`发现 → 建档/测评 → 问/陪伴留存 → 会员·解锁 →(后)Consult`
|
||||
|
||||
---
|
||||
|
||||
## L1 — 产品能力树(合并 IA × Domain)
|
||||
|
||||
```
|
||||
愈心谷 Feature Tree
|
||||
├── 1. Identity & 生命档案
|
||||
├── 2. Self Discovery(自我探索)
|
||||
├── 3. Relationship(关系)
|
||||
├── 4. AI Companion(问)
|
||||
├── 5. Companion Rhythm(陪伴节奏)
|
||||
├── 6. Human Expert(真人 · 后置)
|
||||
├── 7. Content & Feed
|
||||
├── 8. Growth
|
||||
├── 9. Commerce
|
||||
└── 10. Data & Recommendation(平台能力)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1. Identity & 生命档案
|
||||
|
||||
| 二级 | 三级 | 范围 |
|
||||
|---|---|---|
|
||||
| 1.1 注册登录 | 手机 / 微信 / 游客 device / 升级 User | [MVP] 游客+升级;微信 [V1] |
|
||||
| 1.2 Self Profile | 生日(必填);时辰/地点(可选后置) | [MVP] 生日 |
|
||||
| 1.3 Other Profile | 伴侣/家人/朋友等关系对象 | [MVP] 基础 Other |
|
||||
| 1.4 档案管理 | 编辑 · 删除 · 多档案切换 · Ask 关联 | [MVP] |
|
||||
| 1.5 兴趣标签 | 性格/关系/养生等(非运势标签) | [V1] |
|
||||
| 1.6 行为资产 | 浏览 · Decode · Scale · Ask · Order 记录 | [MVP] 服务端最小集 |
|
||||
|
||||
**[No]** 出生地理风水必填、吉凶标签画像。
|
||||
|
||||
---
|
||||
|
||||
### 2. Self Discovery(获客工具层)
|
||||
|
||||
| 二级 | 三级 | 范围 |
|
||||
|---|---|---|
|
||||
| 2.1 Decode | 数字性格 + 体质倾向;简版结论 / 完整原因+方案 | **[MVP] 核心** |
|
||||
| 2.2 Scale 性格 | MBTI 等热门量表 · 结果页 · 分享 | [MVP] ≥1 热门 |
|
||||
| 2.3 Scale 情感/心理 | 恋爱人格、情绪压力等 | [V1] |
|
||||
| 2.4 趣味 Scale | 轻传播向 | [V1] 克制 |
|
||||
| 2.5 五行/八卦轻解读 | 挂在 Decode 或探索,非运势主叙事 | [V1] |
|
||||
| 2.6 中医体质系统 | 体质倾向 · 生活建议 · 节气联动 | [MVP] 在 Decode 内;深化 [V1] |
|
||||
|
||||
**[No]** 塔罗默认入口、紫微/抽签主路径、今日运势主 Feed。
|
||||
**[Later]** 易经决策系统(合规评审后)。
|
||||
|
||||
---
|
||||
|
||||
### 3. Relationship
|
||||
|
||||
| 二级 | 三级 | 范围 |
|
||||
|---|---|---|
|
||||
| 3.1 Match | 双人契合分预览 · 解读锁定 | [MVP] |
|
||||
| 3.2 相处建议 | 基于性格×体质,非合婚吉凶 | [MVP] 简版;[V1] 完整 |
|
||||
| 3.3 关系管理 | 重要日期、关系笔记 | [Later] |
|
||||
|
||||
**[No]** 八字合婚吉凶、缘分指数恐吓文案。
|
||||
|
||||
---
|
||||
|
||||
### 4. AI Companion(问 = AI Life Assistant)
|
||||
|
||||
| 二级 | 三级 | 范围 |
|
||||
|---|---|---|
|
||||
| 4.1 Ask 对话 | 性格 / 关系 / 养生路径引导;非运势默认 | [MVP] 规则模板或薄 LLM |
|
||||
| 4.2 上下文 | 当前 Profile(Self/Other)挂载 | **[MVP]** |
|
||||
| 4.3 视角切换 | Ask 顶栏显式切换档案 | [MVP] |
|
||||
| 4.4 结构化回答 | 短答 · 要点 · 免责声明 | [MVP] |
|
||||
| 4.5 长期记忆 | 跨会话情绪/事件记忆 | [V1+] |
|
||||
| 4.6 报告生成 | 从 Ask/Decode 生成可 Unlock Report | [V1] |
|
||||
| 4.7 双轨入口 | Ask ‖ Consult 占位切换 | [MVP] 占位;履约 [Later] |
|
||||
|
||||
**[No]** 多智能体并列品牌(灵犀/小智式)、算命引导语、AI 心情小镇级 3D。
|
||||
|
||||
人格模式(产品语义,非多 App):陪伴模式 / 解读模式 — [V1]。
|
||||
|
||||
---
|
||||
|
||||
### 5. Companion Rhythm(陪伴 Tab)
|
||||
|
||||
| 二级 | 三级 | 范围 |
|
||||
|---|---|---|
|
||||
| 5.1 SolarTerm | 今日节气 · 生活方式建议 | [MVP] 可静态 |
|
||||
| 5.2 Mood | 打卡 · 简史 | [MVP] 最小写 |
|
||||
| 5.3 情绪分析/练习 | 安抚话术、放松练习 | [V1] |
|
||||
| 5.4 成长计划 | 目标 · 打卡 · 成长报告 | [Later] |
|
||||
|
||||
**[No]** 运势日历作为陪伴主轴。
|
||||
|
||||
---
|
||||
|
||||
### 6. Human Expert(Consult)
|
||||
|
||||
| 二级 | 三级 | 范围 |
|
||||
|---|---|---|
|
||||
| 6.1 顾问类型 | 养生顾问 / 关系顾问(合规资质) | [Later] |
|
||||
| 6.2 流程 | 列表 · 预约 · 支付 · 会话 · 评价 | [Later] |
|
||||
| 6.3 Marketplace | 达人入驻 · 分佣 | [Later] 非冷启动优先 |
|
||||
|
||||
**[MVP]** 仅「顾问预约」表单占位,不履约。
|
||||
|
||||
---
|
||||
|
||||
### 7. Content & Feed
|
||||
|
||||
| 二级 | 三级 | 范围 |
|
||||
|---|---|---|
|
||||
| 7.1 首页 Feed | 官方卡片:热门 Scale、Decode、节气 | [MVP] 运营配置/静态 |
|
||||
| 7.2 文章 | 性格 / 关系 / 养生知识 | [V1] |
|
||||
| 7.3 社区 UGC | 发帖赞评关注 | **[No] MVP**;[Later] 审慎 |
|
||||
| 7.4 AI 玩法广场 | UGC Prompt 集市 | **[No] MVP**;[Later] |
|
||||
|
||||
---
|
||||
|
||||
### 8. Growth
|
||||
|
||||
| 二级 | 三级 | 范围 |
|
||||
|---|---|---|
|
||||
| 8.1 分享卡 | Decode / ScaleResult / Match 预览 | [MVP] |
|
||||
| 8.2 裂变 | 分享 → 建档 → 再测 | [V1] |
|
||||
| 8.3 激励 | 签到积分勋章 | [Later] |
|
||||
| 8.4 SEO/内容获客 | Web 落地 | [Later] website |
|
||||
|
||||
**[No]** 干扰广告、虚假紧迫倒计时。
|
||||
|
||||
---
|
||||
|
||||
### 9. Commerce
|
||||
|
||||
| 二级 | 三级 | 范围 |
|
||||
|---|---|---|
|
||||
| 9.1 Subscription | 月/季/年 | [MVP] mock 支付 |
|
||||
| 9.2 Membership 权益 | 完整 Decode、Ask 次数、深度节气等 | [MVP] |
|
||||
| 9.3 Unlock | 单次报告 / Match 解读 | [MVP] |
|
||||
| 9.4 Order / Payment | 下单 · pay-mock ·(真支付) | [MVP] mock;真支付 [V1] |
|
||||
| 9.5 课程/商城 | — | [Later] / 低优 |
|
||||
|
||||
---
|
||||
|
||||
### 10. Data & Recommendation(平台)
|
||||
|
||||
| 二级 | 三级 | 范围 |
|
||||
|---|---|---|
|
||||
| 10.1 用户数据 | 行为 · Mood · Scale · Ask(最小化、可删) | [MVP] 基础 |
|
||||
| 10.2 推荐 | Feed / Scale 推荐 | [V1] 规则即可 |
|
||||
| 10.3 专家/商品推荐 | — | [Later] |
|
||||
|
||||
---
|
||||
|
||||
## L2 — 页面 / 路由映射(user-h5)
|
||||
|
||||
| L0 | 路由建议 | 主要能力 |
|
||||
|---|---|---|
|
||||
| 首页 | `/` | Decode 入口、Feed |
|
||||
| 探索 | `/explore` | Scale 列表、工具 |
|
||||
| 问 | `/ask` | Ask + Consult 占位 |
|
||||
| 陪伴 | `/companion` | SolarTerm、Mood |
|
||||
| 我的 | `/mine` | Profiles、Membership、Orders |
|
||||
| 二级 | `/decode` `/scales/:slug` `/match` `/report/:id` | Discovery / Relationship / Commerce |
|
||||
|
||||
实现约束:`.ai/design/*` · playbook `new-page` / `add-api`。
|
||||
|
||||
---
|
||||
|
||||
## 护城河优先级(愈心谷)
|
||||
|
||||
| 梯队 | 能力 | 说明 |
|
||||
|---|---|---|
|
||||
| ★★★★★ | 生命档案 Profile · Ask 挂档案 · Relationship Match · Decode(性格×体质) | Memory + 差异化叙事 |
|
||||
| ★★★★ | Scale · SolarTerm/Mood · Membership/Unlock | 获客与留存与变现 |
|
||||
| ★★ | Feed 运营 · 分享裂变 | 增长 |
|
||||
| ★ / No | UGC 广场 · 达人市场 · 硬件 · 塔罗主路径 | 明确后置或不做 |
|
||||
|
||||
---
|
||||
|
||||
## 竖切顺序(与 roadmap 对齐)
|
||||
|
||||
1. **Phase A** — Identity + Decode + Commerce mock
|
||||
2. **Phase B** — Scale + Match + Share
|
||||
3. **Phase C** — Ask 骨架 + Companion
|
||||
4. **Phase D** — 真支付 · 小程序 · Consult 试点
|
||||
|
||||
详见 `apps/docs/product-roadmap.md`。
|
||||
@@ -0,0 +1,17 @@
|
||||
# Prompt: Bugfix
|
||||
|
||||
Load first: `.ai/constitution.md`, `.ai/coding.md`, `.ai/security.md`, `.ai/review.md`.
|
||||
|
||||
## Process
|
||||
|
||||
1. Reproduce or state the failure mode clearly.
|
||||
2. Find root cause (file + function). Prefer evidence over guess.
|
||||
3. Fix the smallest correct change.
|
||||
4. Add a regression test when the bug is in scoring, auth, or payment.
|
||||
5. Verify build/health.
|
||||
6. Output Review block (at least Architecture, Security, Test, Scope).
|
||||
|
||||
## Forbidden
|
||||
|
||||
- Drive-by refactors unrelated to the bug.
|
||||
- Swallowing errors to “make it pass”.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Prompt: New Feature
|
||||
|
||||
Load first: `.ai/constitution.md`, `.ai/architecture.md`, `.ai/coding.md`, `.ai/api.md`, `.ai/review.md`, `.ai/definition-of-done.md`.
|
||||
|
||||
## Process
|
||||
|
||||
1. Restate the feature in one sentence and list files you will touch.
|
||||
2. Follow feature flow: API → Service → Repository → Migration → SDK/types → UI → Test → Docs.
|
||||
3. Implement the smallest vertical slice that works end-to-end.
|
||||
4. Run builds/tests for touched sides.
|
||||
5. Output `.ai/review.md` Review block.
|
||||
6. Confirm Definition of Done.
|
||||
|
||||
## Forbidden
|
||||
|
||||
- Inventing APIs not in the task / OpenAPI.
|
||||
- Editing legacy root HTML unless migration is the task.
|
||||
- Shipping UI-only unlock/payment without server checks.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Prompt: Refactor
|
||||
|
||||
Load first: `.ai/constitution.md`, `.ai/architecture.md`, `.ai/coding.md`, `.ai/testing.md`, `.ai/review.md`.
|
||||
|
||||
## Process
|
||||
|
||||
1. State goal and non-goals. No behavior change unless asked.
|
||||
2. Keep layers intact. Improve names, size, and boundaries.
|
||||
3. Prefer move/extract over rewrite.
|
||||
4. Keep tests green; add tests if extracting scorable logic with none.
|
||||
5. Output Review block focusing on Architecture, Readability, Test, Scope.
|
||||
|
||||
## Forbidden
|
||||
|
||||
- Mixing refactor with feature work in one change set.
|
||||
- Breaking public API envelope or URL contracts silently.
|
||||
@@ -0,0 +1,40 @@
|
||||
# AI Self-Review — mandatory before claiming Done
|
||||
|
||||
After coding, check every item. Output a Review block.
|
||||
|
||||
## Checklist
|
||||
|
||||
| Area | Ask |
|
||||
|---|---|
|
||||
| Architecture | Layers respected? No Handler→DB? |
|
||||
| Naming | Consistent domain terms? |
|
||||
| Performance | Obvious N+1 / unbounded lists? |
|
||||
| Security | AuthZ, validation, no secrets? |
|
||||
| Readability | Files ≤400, funcs ≤50? |
|
||||
| Error handling | Wrapped errors / user-safe messages? |
|
||||
| Logging | Structured, no PII spam? |
|
||||
| Test | Critical path covered or smoke listed? |
|
||||
| Deployment | Migration / health / env noted if needed? |
|
||||
| Docs | OpenAPI / PRD touch if public behavior changed? |
|
||||
| Design | UI change? Tokens + catalog + platform contract followed? |
|
||||
| Scope | No unrelated files modified? |
|
||||
|
||||
## Output format (required)
|
||||
|
||||
```
|
||||
## Review
|
||||
- Architecture: PASS | FAIL — <note>
|
||||
- Naming: PASS | FAIL — <note>
|
||||
- Performance: PASS | FAIL — <note>
|
||||
- Security: PASS | FAIL — <note>
|
||||
- Readability: PASS | FAIL — <note>
|
||||
- Error handling: PASS | FAIL — <note>
|
||||
- Logging: PASS | FAIL — <note>
|
||||
- Test: PASS | FAIL — <note>
|
||||
- Deployment: PASS | FAIL — <note>
|
||||
- Docs: PASS | FAIL — <note>
|
||||
- Design: PASS | FAIL | N/A — <note>
|
||||
- Scope: PASS | FAIL — <note>
|
||||
```
|
||||
|
||||
Any FAIL → fix before finishing. Do not hide FAILs.
|
||||
@@ -0,0 +1,26 @@
|
||||
# Security — Golden Rules
|
||||
|
||||
## AuthZ
|
||||
|
||||
- Authenticate before mutating user data.
|
||||
- Authorize ownership: user A cannot read/write user B resources.
|
||||
|
||||
## Input
|
||||
|
||||
- Validate all external input at handler boundary.
|
||||
- Parameterized SQL only. Never string-concatenate SQL.
|
||||
|
||||
## Secrets
|
||||
|
||||
- No secrets in repo, frontend bundles, or logs.
|
||||
- Rotate via env / secret manager.
|
||||
|
||||
## Privacy
|
||||
|
||||
- Birthday / answers / reports are personal data.
|
||||
- Soft-delete and future account deletion path required in design.
|
||||
- Log request ids; avoid logging full PII payloads.
|
||||
|
||||
## Content compliance
|
||||
|
||||
- Reject generating 疗效 / 吉凶文案 in prompts and templates.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Tech Stack — frozen unless ADR says otherwise
|
||||
|
||||
## Backend
|
||||
|
||||
- Language: Go 1.22+
|
||||
- HTTP: gin
|
||||
- DB: PostgreSQL
|
||||
- Migrations: goose (or golang-migrate) under `apps/api/migrations/`
|
||||
- Log: structured (zap or slog wrapper). No `fmt.Println` in business paths.
|
||||
- Module path: `github.com/yuxingu/digital-psychology/apps/api`
|
||||
|
||||
## User H5
|
||||
|
||||
- Vue 3 + TypeScript (`strict: true`) + Vite
|
||||
- Router: vue-router
|
||||
- State: pinia
|
||||
- Package: `@yuxingu/user-h5`
|
||||
|
||||
## Shared
|
||||
|
||||
- npm workspaces at repo root
|
||||
- `@yuxingu/sdk` `createClient({ baseURL, adapters })`
|
||||
- TS camelCase in app; SDK converts to/from API snake_case
|
||||
|
||||
## Mini program
|
||||
|
||||
- Native WeChat mini-program structure
|
||||
- Same SDK via adapters (`wx.request`, storage)
|
||||
- No shared Vue SFC with H5
|
||||
|
||||
## Deploy
|
||||
|
||||
- Docker Compose for local Postgres: `deploy/docker-compose.yml`
|
||||
- API health: `/api/v1/healthz` (liveness). Add readiness when DB is wired.
|
||||
- Never deploy with image tag `latest` in prod.
|
||||
|
||||
## Do not introduce without ADR
|
||||
|
||||
- Another backend language
|
||||
- GraphQL / gRPC as primary public API (REST is primary)
|
||||
- ORM that hides SQL without team agreement
|
||||
- New state manager besides Pinia on H5
|
||||
@@ -0,0 +1,22 @@
|
||||
# Testing — Golden Rules
|
||||
|
||||
## Priority
|
||||
|
||||
Test money, scoring, auth, and unlock paths first.
|
||||
|
||||
## Go
|
||||
|
||||
- Pure engines (decode / scale scoring) must have unit tests.
|
||||
- `go test ./...` must pass before claiming API done.
|
||||
|
||||
## H5
|
||||
|
||||
- Critical utils may use Vitest when introduced.
|
||||
- Until then: PR must list manual smoke steps for touched flows.
|
||||
|
||||
## Definition for AI
|
||||
|
||||
Do not mark a feature Done if:
|
||||
|
||||
- Scorable logic has zero tests, or
|
||||
- Build is broken (`go test` / `npm run build:h5` fail).
|
||||
@@ -0,0 +1,64 @@
|
||||
# UI — Product chrome + pointer to Design Contract
|
||||
|
||||
**Visual / component rules:** `.ai/design/design-system.md` (mandatory before UI work).
|
||||
**Catalog:** `.ai/design/component-catalog.md`
|
||||
**Platform:** `.ai/design/platform/h5.md` (default) · `mini-program.md` · `website.md` · `flutter.md`
|
||||
|
||||
---
|
||||
|
||||
## Brand (summary)
|
||||
|
||||
- Primary `#E54D42` → `--color-primary` / `--yxg-pri`
|
||||
- Atmosphere: peach wash → white sheet
|
||||
- Mobile-first; user column ~430px
|
||||
- Unicode symbols over emoji in chrome
|
||||
|
||||
---
|
||||
|
||||
## H5 structure
|
||||
|
||||
```
|
||||
apps/user-h5/src/
|
||||
pages/
|
||||
components/
|
||||
layouts/
|
||||
hooks/
|
||||
api/
|
||||
stores/
|
||||
router/
|
||||
assets/
|
||||
```
|
||||
|
||||
No raw `fetch` in `pages/`. Tokens from `packages/ui`.
|
||||
|
||||
---
|
||||
|
||||
## Tabs (product IA)
|
||||
|
||||
Home / Explore / **Ask** / Companion / Mine.
|
||||
Ask is the strategic center tab.
|
||||
|
||||
---
|
||||
|
||||
## Copy / compliance
|
||||
|
||||
- No medical cure claims
|
||||
- No 吉凶祸福
|
||||
- Report screens include disclaimer
|
||||
- Brand voice: see design-system §13
|
||||
|
||||
---
|
||||
|
||||
## Interaction
|
||||
|
||||
- One job per section
|
||||
- Home first viewport: brand, decode entry, then content sheet
|
||||
- Loading / empty / error required for network views
|
||||
|
||||
---
|
||||
|
||||
## Mini program
|
||||
|
||||
- Own `components/`; share tokens from `packages/ui`, not Vue SFCs
|
||||
- Pages → `services/*` only
|
||||
- See `design/platform/mini-program.md`
|
||||
@@ -0,0 +1,33 @@
|
||||
# Workflow — Default Development Loop
|
||||
|
||||
```
|
||||
Receive task
|
||||
↓
|
||||
Read AI Contract + constitution + architecture + domain
|
||||
↓
|
||||
Architecture Check (ADR + file-map + layers)
|
||||
↓
|
||||
Choose playbook (add-api / new-page / new-table / …)
|
||||
↓
|
||||
Coding (follow patterns + examples)
|
||||
↓
|
||||
Commands (build / test / health)
|
||||
↓
|
||||
Review (.ai/review.md)
|
||||
↓
|
||||
DoD + checklist
|
||||
↓
|
||||
Commit (Conventional Commits, one concern)
|
||||
```
|
||||
|
||||
## Architecture Check questions
|
||||
|
||||
1. Does this change reverse an Accepted ADR? If yes → ASK / new ADR.
|
||||
2. Correct layer? Handler / Service / Repository?
|
||||
3. Domain words match `.ai/domain.md`?
|
||||
4. API envelope still `{code,message,data}`?
|
||||
|
||||
## Stop conditions
|
||||
|
||||
- Unclear requirement → ASK FIRST
|
||||
- Need GraphQL / new DB / new auth scheme → write or cite ADR before coding
|
||||
@@ -0,0 +1,13 @@
|
||||
# Cursor as Agent Runtime
|
||||
|
||||
`.cursor/` is **not** a second source of truth.
|
||||
|
||||
Everything under `rules/`, `templates/`, `commands/` is a **symlink** into `.ai/`.
|
||||
|
||||
| Cursor path | Points to |
|
||||
|---|---|
|
||||
| `rules/*.md` | `.ai/*.md` (constitution, architecture, coding, …) |
|
||||
| `templates/feature.md` | `.ai/playbooks/add-api.md` |
|
||||
| `commands/review.md` | `.ai/review.md` |
|
||||
|
||||
Edit only `.ai/`. Never duplicate content here.
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../.ai/commands.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/prompts/refactor.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/review.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/ai-contract.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/api.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/architecture.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/coding.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/constitution.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/database.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/design/design-system.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/domain/domain-map.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/domain.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/product/feature-map.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/forbidden.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/review.md
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../.ai/checklists/feature.md
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.ai/playbooks/add-api.md
|
||||
+20
@@ -4,3 +4,23 @@ __pycache__/
|
||||
*.log
|
||||
.env
|
||||
.DS_Store
|
||||
|
||||
# Node
|
||||
node_modules/
|
||||
dist/
|
||||
*.local
|
||||
|
||||
# Go
|
||||
apps/api/bin/
|
||||
*.exe
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Data / local db
|
||||
*.db
|
||||
.scale_results.db
|
||||
|
||||
# OS
|
||||
Thumbs.db
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# AGENTS.md — AI System Entry
|
||||
|
||||
You are the software engineer for **愈心谷 (YuXinGu)**.
|
||||
|
||||
This file is for AI agents.
|
||||
|
||||
## Load order (every task)
|
||||
|
||||
1. `.ai/ai-contract.md`
|
||||
2. `.ai/constitution.md`
|
||||
3. `.ai/architecture.md`
|
||||
4. `.ai/domain.md` (+ product/API tasks: `domain/domain-map.md`)
|
||||
5. `.ai/forbidden.md`
|
||||
6. `.ai/file-map.md` + `.ai/workflow.md`
|
||||
7. Task rules: `.ai/coding.md` / `api.md` / `database.md` / `ui.md` / `security.md` / …
|
||||
8. **Product scope / PRD slicing:** `.ai/product/feature-map.md` (竞品对照: `product/cece-feature-map.md`)
|
||||
9. **Any UI work:** `.ai/design/design-system.md` + `component-catalog.md` + matching `design/platform/*.md` (H5 default)
|
||||
10. Matching **ADR** in `.ai/adr/` before changing stack or API style
|
||||
11. Prefer **patterns/** + **examples/** + **playbooks/** over inventing structure
|
||||
12. Before Done: `.ai/review.md` + `.ai/definition-of-done.md` + `.ai/checklists/*`
|
||||
13. Verify via `.ai/commands.md`
|
||||
14. `prompts/` are optional helpers — not a substitute for rules above
|
||||
|
||||
## Hard constraints
|
||||
|
||||
- Never violate architecture or Accepted ADRs.
|
||||
- Never invent APIs, DB tables, or domain synonyms.
|
||||
- Never guess requirements — **ASK FIRST**.
|
||||
- Never modify files outside the current task.
|
||||
- New code only under `apps/` and `packages/` (unless legacy migration task).
|
||||
- One concern per change set. Function ≤50 lines. File ≤400 lines.
|
||||
- Print the Review block when a coding task finishes.
|
||||
|
||||
## Cursor
|
||||
|
||||
`.cursor/` is an Agent Runtime view of this system via symlinks. Edit `.ai/` only.
|
||||
|
||||
## Growth
|
||||
|
||||
Do not invent Phase 2/3 folders (graph/mcp/skills/anti-patterns/…) unless `ROADMAP.md` says so and the task asks. Prefer improving patterns/examples/playbooks.
|
||||
|
||||
## Product one-liner
|
||||
|
||||
Birthday → Profile (digital personality + constitution) → Companion / Ask retention → Membership & Report unlock → Consult later. Compliant lifestyle wording only.
|
||||
@@ -0,0 +1,9 @@
|
||||
# ARCHITECTURE.md
|
||||
|
||||
Canonical architecture rules for AI and humans live in:
|
||||
|
||||
**[.ai/architecture.md](.ai/architecture.md)**
|
||||
**[.ai/tech-stack.md](.ai/tech-stack.md)**
|
||||
**[.ai/constitution.md](.ai/constitution.md)**
|
||||
|
||||
Start at [AGENTS.md](AGENTS.md).
|
||||
@@ -1,64 +1,49 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
愈心谷 is an **AI-first** Monorepo. Treat `.ai/` as the executable engineering system.
|
||||
|
||||
## Project overview
|
||||
## On every task
|
||||
|
||||
愈心谷 (YuXinGu) — a digital mental health platform. The codebase is a collection of standalone, mobile-first HTML pages with no build step, no framework, no package.json, and no JavaScript dependencies.
|
||||
1. Read [AGENTS.md](AGENTS.md) (load order is authoritative).
|
||||
2. Especially: `.ai/ai-contract.md`, `constitution.md`, `architecture.md`, `domain.md`, `forbidden.md`.
|
||||
3. Prefer `patterns/` + `examples/` + `playbooks/` over free-form invention.
|
||||
4. Finish with Review + DoD + matching checklist.
|
||||
|
||||
The product vision is detailed in `立项文档.md` (Chinese): combine digital psychology (numerology-based personality analysis) with TCM constitution theory (中医体质) to create a "test → report → subscribe → consult" funnel. Target audience is Chinese-speaking; all UI text is Chinese (zh-CN).
|
||||
## Layout
|
||||
|
||||
## Running the app
|
||||
| Path | Role |
|
||||
|---|---|
|
||||
| `.ai/` | AI Engineering System (source of truth for rules) |
|
||||
| `apps/api` | Go API |
|
||||
| `apps/user-h5` | Vue3 user H5 |
|
||||
| `apps/mini-program` | Mini-program scaffold |
|
||||
| `packages/*` | sdk / types / utils / ui |
|
||||
| `apps/docs/` | Human PRD / business docs (not a substitute for `.ai/`) |
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
python3 server.py [port] # default port 8001
|
||||
export GOPROXY=https://goproxy.cn,direct # if needed
|
||||
cd apps/api && go run ./cmd/server
|
||||
npm install && npm run dev:h5
|
||||
```
|
||||
|
||||
The server serves static files from the project root and exposes two JSON API endpoints:
|
||||
## Legacy
|
||||
|
||||
- `GET /load` — returns mindmap data from `mindmap_data.json`
|
||||
- `POST /save` — persists mindmap data to `mindmap_data.json` (validates JSON before writing)
|
||||
Root `yuxingu.html`, `pages/`, `server.py` = prototype. Do not extend. See [LEGACY.md](LEGACY.md).
|
||||
|
||||
There are no tests, no linters, and no build pipeline. To verify changes, run the server and open the relevant HTML file in a browser.
|
||||
## Skill routing
|
||||
|
||||
## File map
|
||||
When the user's request matches an available skill, invoke it. When in doubt, invoke the skill.
|
||||
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `index.html` | Landing page linking to all sections |
|
||||
| `yuxingu.html` | Main app shell — hero, service cards, activity center, bottom nav |
|
||||
| `shuzi.html` | Digital psychology calculator — life-number triangle, bagua, liuren, zodiac, wuxing modules |
|
||||
| `mindmap.html` | Canvas-based mind-map editor with multi-map management |
|
||||
| `yangsheng.html` | AI Eastern wellness — bazi/wuxing constitution analysis, weekly/daily reports |
|
||||
| `manual.html` | Static "life manual" poster with pyramid triangle charts rendered via inline SVG |
|
||||
| `yuxingu_v1.html` | Earlier iteration of the main page (kept for reference, not linked from index) |
|
||||
| `server.py` | Minimal HTTP server (Python stdlib, no dependencies) |
|
||||
| `立项文档.md` | Product requirements doc — market analysis, business model, pricing, MVP scope |
|
||||
|
||||
### Unrelated files
|
||||
|
||||
These files are not part of the 愈心谷 app — they belong to a separate crypto trading visualization project that happens to share the repo:
|
||||
|
||||
- `link_regime_chart.html` — LINK token HMM regime K-line chart
|
||||
- `l2_LINK_*.json` (3 files) — market data and signals for the above
|
||||
|
||||
## Architecture notes
|
||||
|
||||
- **Every HTML file is self-contained.** All CSS and JS are embedded in `<style>` / `<script>` tags. There are no shared `.js` or `.css` files.
|
||||
- **Mobile-first design** with `max-width: 430px–500px` containers, `user-scalable=no`, and `env(safe-area-inset-bottom)` for notched phones.
|
||||
- **CSS custom properties** define the brand palette: `--pri: #E54D42` (primary red), with per-page accent colors (gold, blue, green, orange).
|
||||
- **Emoji are deliberately avoided** in the main UI — icons use CSS shapes, Unicode text symbols (△, ☯, ◈), or inline SVG.
|
||||
- **Google Analytics** (`G-LVVXH3TL04`) is embedded in every HTML page via a `<script>` block in `<head>`.
|
||||
- **Static assets**: `logo.png`, `logo.jpg`, `cube.jpg`. The logo is referenced from multiple pages but lives at the project root.
|
||||
|
||||
### Page-specific details
|
||||
|
||||
**`mindmap.html`** — Uses `<canvas>` for rendering with hand-rolled hit-testing, drag-to-pan, and inline text editing. Dual persistence: primary store is `localStorage` (key `yuxingu_maps`), with secondary server sync via `POST /save` and `GET /load`. The sidebar lists multiple named maps; each map is a tree with colored nodes. Data format is an array of `{name, tree: {id, text, color, children}}` objects.
|
||||
|
||||
**`shuzi.html`** — Full numerology engine in embedded JS: digit reduction, triangle calculation, joint codes, missing-number detection. Includes a custom base64-embedded font (`TriangleDigits`) for styled number rendering. Tabbed panels for 梅花易数, 小六壬, 大六壬, 奇门遁甲, 星座, and 五行八卦 with content rendered dynamically. Also includes a 3D bagua scene rendered on canvas.
|
||||
|
||||
**`yangsheng.html`** — Computes bazi (八字), five elements (五行), organ-meridian mapping, and wuyun-liuqi (五运六气) from a birth date. Weekly/daily panels use the current date to generate time-appropriate health advice. Builds on the same numerological engine concepts as `shuzi.html` but oriented toward TCM wellness rather than personality analysis.
|
||||
|
||||
**`manual.html`** — A static reference poster. Uses inline SVG to draw pyramid triangle charts for life-number interpretation. Different aesthetic (serif fonts, paper-like colors) from the rest of the app.
|
||||
|
||||
**`server.py`** — Thin wrapper around `http.server.SimpleHTTPRequestHandler`. Disables caching for HTML and JSON responses. Adds `/save` + `/load` routes. No database, no auth. Single-threaded with a 30-second socket timeout. Binds to `127.0.0.1` only (no external network access).
|
||||
- Product ideas/brainstorming → `/office-hours`
|
||||
- Strategy/scope → `/plan-ceo-review`
|
||||
- Architecture → `/plan-eng-review`
|
||||
- Design → `/design-consultation` or `/plan-design-review`
|
||||
- Full review pipeline → `/autoplan`
|
||||
- Bugs/errors → `/investigate`
|
||||
- QA → `/qa` or `/qa-only`
|
||||
- Code review → `/review`
|
||||
- Ship/PR → `/ship` or `/land-and-deploy`
|
||||
- Save/resume context → `/context-save` / `/context-restore`
|
||||
- Spec/issue → `/spec`
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# CONTRIBUTING
|
||||
|
||||
## AI-first
|
||||
|
||||
This project is driven by the **AI Engineering System** under [`.ai/`](.ai/).
|
||||
Agents must load [AGENTS.md](AGENTS.md) and `.ai/*` before coding.
|
||||
|
||||
Human product docs (PRD, business) stay in `apps/docs/`.
|
||||
Do **not** treat `apps/docs/standards/` as the source of truth — it only points here for history.
|
||||
|
||||
## Local
|
||||
|
||||
```bash
|
||||
# optional CN Go proxy
|
||||
export GOPROXY=https://goproxy.cn,direct
|
||||
|
||||
cd apps/api && go mod tidy && go run ./cmd/server
|
||||
npm install && npm run dev:h5
|
||||
docker compose -f deploy/docker-compose.yml up -d # postgres
|
||||
```
|
||||
|
||||
## Git
|
||||
|
||||
Trunk-Based: short `feature/*` / `fix/*` into `main`.
|
||||
Commits: Conventional Commits (`feat:`, `fix:`, `docs:`, …).
|
||||
|
||||
## PR
|
||||
|
||||
- One feature point.
|
||||
- Include Review checklist results when AI-assisted.
|
||||
- API changes update `proto/openapi.yaml`.
|
||||
@@ -0,0 +1,9 @@
|
||||
# Legacy 原型说明
|
||||
|
||||
以下路径为重构前的静态 H5 原型,**默认只读**,新功能请在 `apps/user-h5` 与 `apps/api` 开发:
|
||||
|
||||
- `yuxingu.html`、`index.html`
|
||||
- `pages/`、`css/`、`js/`
|
||||
- `server.py`(Python 静态站 + 量表 API)
|
||||
|
||||
可对照交互与文案,迁移完成后移入 `archive/legacy-h5/`。
|
||||
@@ -0,0 +1,48 @@
|
||||
# 愈心谷(YuXinGu)
|
||||
|
||||
数字性格 × 中医体质。Monorepo:Go API + Vue3 H5,预留小程序。
|
||||
|
||||
## AI Engineering System(规范真相源)
|
||||
|
||||
本仓库是 **AI-first**:不用长篇《开发手册》当主约束,而用可执行的 **`.ai/`**:
|
||||
|
||||
```
|
||||
.ai/
|
||||
ai-contract.md · constitution · architecture · domain
|
||||
file-map · workflow · forbidden · commands
|
||||
coding / api / database / ui / deployment / testing / security
|
||||
review · definition-of-done
|
||||
adr/ patterns/ examples/ playbooks/ checklists/
|
||||
prompts/ # 辅助,非核心
|
||||
```
|
||||
|
||||
优先级:constitution → architecture → domain → patterns/examples/playbooks → review/DoD → prompts。
|
||||
Cursor 运行时:[.cursor/](.cursor/)(软链到 `.ai/`,不复制内容)。
|
||||
演进节奏:[.ai/ROADMAP.md](.ai/ROADMAP.md)(二/三阶段:anti-patterns、metrics、graph、mcp、skills…按需再加)。
|
||||
入口:[AGENTS.md](AGENTS.md) · [CLAUDE.md](CLAUDE.md) · [.ai/README.md](.ai/README.md)
|
||||
|
||||
产品文档(给人看):[prd-mvp](apps/docs/prd-mvp.md) · [business-model](apps/docs/business-model.md)
|
||||
|
||||
## 快速开始
|
||||
|
||||
```bash
|
||||
export GOPROXY=https://goproxy.cn,direct # 若需要
|
||||
|
||||
docker compose -f deploy/docker-compose.yml up -d # 可选
|
||||
cd apps/api && go mod tidy && go run ./cmd/server
|
||||
# → http://127.0.0.1:8080/api/v1/healthz
|
||||
|
||||
npm install && npm run dev:h5
|
||||
# → http://127.0.0.1:5173
|
||||
```
|
||||
|
||||
## 目录
|
||||
|
||||
| 路径 | 说明 |
|
||||
|---|---|
|
||||
| `.ai/` | AI 工程系统(必须遵守) |
|
||||
| `apps/api` | Go 后端 |
|
||||
| `apps/user-h5` | 用户 H5 |
|
||||
| `apps/mini-program` | 小程序脚手架 |
|
||||
| `packages/*` | sdk / types / utils / ui |
|
||||
| 根目录 HTML / `server.py` | Legacy,见 [LEGACY.md](LEGACY.md) |
|
||||
@@ -0,0 +1,3 @@
|
||||
# admin-h5
|
||||
|
||||
运营后台(内容库、订单、会员)。**业务后置**,当前仅占位。
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "@yuxingu/admin-h5",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "运营后台占位,业务后置"
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Command server starts the 愈心谷 HTTP API.
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/yuxingu/digital-psychology/apps/api/internal/config"
|
||||
"github.com/yuxingu/digital-psychology/apps/api/internal/handler"
|
||||
"github.com/yuxingu/digital-psychology/apps/api/internal/middleware"
|
||||
"github.com/yuxingu/digital-psychology/apps/api/pkg/response"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cfg := config.Load()
|
||||
if cfg.AppEnv == "prod" {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
|
||||
r := gin.New()
|
||||
r.Use(gin.Recovery(), gin.Logger(), middleware.RequestID())
|
||||
|
||||
api := r.Group("/api/v1")
|
||||
handler.NewHealthHandler().Register(api)
|
||||
|
||||
// Placeholder route to demonstrate unified envelope.
|
||||
api.GET("/ping", func(c *gin.Context) {
|
||||
response.OK(c, gin.H{"pong": true})
|
||||
})
|
||||
|
||||
addr := cfg.HTTPAddr
|
||||
log.Printf("yuxingu api listening on %s env=%s", addr, cfg.AppEnv)
|
||||
if err := r.Run(addr); err != nil {
|
||||
log.Printf("server stopped: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
module github.com/yuxingu/digital-psychology/apps/api
|
||||
|
||||
go 1.22
|
||||
|
||||
require github.com/gin-gonic/gin v1.10.0
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.23.0 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/sys v0.20.0 // indirect
|
||||
golang.org/x/text v0.15.0 // indirect
|
||||
google.golang.org/protobuf v1.34.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
@@ -0,0 +1,89 @@
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
@@ -0,0 +1,27 @@
|
||||
// Package config loads process configuration from environment variables.
|
||||
package config
|
||||
|
||||
import "os"
|
||||
|
||||
// Config holds runtime settings for the API server.
|
||||
type Config struct {
|
||||
HTTPAddr string
|
||||
DatabaseURL string
|
||||
AppEnv string
|
||||
}
|
||||
|
||||
// Load reads configuration from the environment with safe defaults for local dev.
|
||||
func Load() Config {
|
||||
return Config{
|
||||
HTTPAddr: getenv("HTTP_ADDR", ":8080"),
|
||||
DatabaseURL: getenv("DATABASE_URL", "postgres://yuxingu:yuxingu@127.0.0.1:5432/yuxingu?sslmode=disable"),
|
||||
AppEnv: getenv("APP_ENV", "dev"),
|
||||
}
|
||||
}
|
||||
|
||||
func getenv(key, fallback string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/yuxingu/digital-psychology/apps/api/pkg/response"
|
||||
)
|
||||
|
||||
// HealthHandler serves liveness probes.
|
||||
type HealthHandler struct{}
|
||||
|
||||
// NewHealthHandler constructs HealthHandler.
|
||||
func NewHealthHandler() *HealthHandler {
|
||||
return &HealthHandler{}
|
||||
}
|
||||
|
||||
// Register mounts health routes on the engine or router group.
|
||||
func (h *HealthHandler) Register(r gin.IRoutes) {
|
||||
r.GET("/healthz", h.Healthz)
|
||||
}
|
||||
|
||||
// Healthz returns a simple OK payload for load balancers.
|
||||
func (h *HealthHandler) Healthz(c *gin.Context) {
|
||||
response.OK(c, gin.H{"status": "ok"})
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// RequestID attaches X-Request-ID to every request/response for tracing.
|
||||
func RequestID() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
id := c.GetHeader("X-Request-ID")
|
||||
if id == "" {
|
||||
id = newID()
|
||||
}
|
||||
c.Set("request_id", id)
|
||||
c.Header("X-Request-ID", id)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func newID() string {
|
||||
var b [16]byte
|
||||
if _, err := rand.Read(b[:]); err != nil {
|
||||
return "req-unknown"
|
||||
}
|
||||
return hex.EncodeToString(b[:])
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Package response provides the unified API envelope {code,message,data}.
|
||||
package response
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Body is the standard JSON response shape for all HTTP APIs.
|
||||
type Body struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// OK writes a success response with optional data.
|
||||
func OK(c *gin.Context, data interface{}) {
|
||||
c.JSON(http.StatusOK, Body{Code: 0, Message: "success", Data: data})
|
||||
}
|
||||
|
||||
// Fail writes a business error with HTTP status and app code.
|
||||
func Fail(c *gin.Context, httpStatus int, code int, message string) {
|
||||
c.JSON(httpStatus, Body{Code: code, Message: message})
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
# 愈心谷产品与业务文档
|
||||
|
||||
工程规则以仓库根目录 [`.ai/`](../../.ai/) 为准;本目录放**产品 / 商业 / 竞品分析 / ADR(业务向)**。
|
||||
|
||||
`apps/docs/standards/*` 已废弃,请改读 `.ai/`。
|
||||
|
||||
---
|
||||
|
||||
## 阅读顺序(产品重设计)
|
||||
|
||||
1. [analysis/cece-teardown.md](analysis/cece-teardown.md) — 测测拆解 → 愈心谷映射
|
||||
2. [`.ai/product/cece-feature-map.md`](../../.ai/product/cece-feature-map.md) — 测测 Feature Map(IA × 能力域)
|
||||
3. [`.ai/product/feature-map.md`](../../.ai/product/feature-map.md) — 愈心谷 Feature Map + MVP
|
||||
4. [prd-mvp.md](prd-mvp.md) — MVP 目标、IA、用户故事、API 切片、验收
|
||||
5. [business-model.md](business-model.md) — 三层收入与飞轮
|
||||
6. [product-roadmap.md](product-roadmap.md) — Phase A→D 竖切计划
|
||||
|
||||
域词汇:[`.ai/domain.md`](../../.ai/domain.md) · 领域图:[`.ai/domain/domain-map.md`](../../.ai/domain/domain-map.md)
|
||||
|
||||
---
|
||||
|
||||
## 其他
|
||||
|
||||
| 文档 | 说明 |
|
||||
|---|---|
|
||||
| [adr/](adr/) | 架构/选型 ADR(与 `.ai/adr/` 分工:业务向可放此处) |
|
||||
| 根目录 `立项文档.md` | 早期立项材料;冲突时以本目录 + `.ai/` 为准 |
|
||||
@@ -0,0 +1,23 @@
|
||||
# ADR 0001: Monorepo + Go API + Vue H5
|
||||
|
||||
## 状态
|
||||
|
||||
已采纳(2026-08-02)
|
||||
|
||||
## 背景
|
||||
|
||||
愈心谷需从静态 HTML 原型演进为可多端扩展的产品,并引入 AI 辅助开发;需统一规范与清晰边界。
|
||||
|
||||
## 决策
|
||||
|
||||
- 采用 npm workspaces Monorepo(`apps/*` + `packages/*`)。
|
||||
- 后端唯一实现:Go(gin)于 `apps/api`。
|
||||
- 当前主客户端:Vue3 + TS H5(`apps/user-h5`);小程序仅脚手架。
|
||||
- 多端网络层:`packages/sdk` 适配器模式。
|
||||
- Git:Trunk-Based + Conventional Commits。
|
||||
|
||||
## 后果
|
||||
|
||||
- 新功能不得继续堆在根目录 legacy HTML。
|
||||
- 共享类型与 SDK 降低后续小程序迁移成本。
|
||||
- 需维护 workspace 与 Go module 两套依赖工具链。
|
||||
@@ -0,0 +1,7 @@
|
||||
# ADR location moved
|
||||
|
||||
Canonical Architecture Decision Records live in:
|
||||
|
||||
**[../../../.ai/adr/](../../../.ai/adr/)**
|
||||
|
||||
This folder keeps historical notes only if needed; do not add new ADRs here.
|
||||
@@ -0,0 +1,79 @@
|
||||
# 竞品拆解:测测 → 愈心谷映射
|
||||
|
||||
来源:[测测 App 深度体验报告(人人都是产品经理)](https://www.woshipm.com/evaluating/6391148.html)
|
||||
下游:[PRD MVP](../prd-mvp.md) · [商业模式](../business-model.md) · [产品路线图](../product-roadmap.md) · [文档索引](../README.md)
|
||||
|
||||
原则:学结构,不抄神秘学主叙事;愈心谷差异 = **数字性格 + 中医体质 + 关系档案 + 节气陪伴**(合规:无疗效、无吉凶)。
|
||||
|
||||
域词汇以 [`.ai/domain.md`](../../../.ai/domain.md) 为准。
|
||||
|
||||
---
|
||||
|
||||
## 1. 测测做对了什么(可迁移)
|
||||
|
||||
| 测测能力 | 本质 | 愈心谷对应 |
|
||||
|---|---|---|
|
||||
| 趣味测评拉新(MBTI 等) | 社交传播入口 | **Scale** + 分享卡片 |
|
||||
| 生日建档 /「了解 TA」 | 关系数据资产 | **Profile**(Self / Other) |
|
||||
| 五 Tab,中间「问」突出 | 战略入口可视化 | Home / Explore / **Ask** / Companion / Mine |
|
||||
| AI 挂档案,非通用闲聊 | 垂直差异化 | **Ask** 必须带 Profile 上下文 |
|
||||
| AI ‖ 真人 1v1 双轨 | 低摩擦升单 | Ask 内切换 **Consult**(后置) |
|
||||
| 会员订阅为主营收 | 可预测现金流 | **Subscription** → **Membership** / **VIP** |
|
||||
| 达人咨询高客单 | ARPU 拔高 | **Consult** |
|
||||
| 砍干扰广告 | 信任优先 | 不做干扰广告 |
|
||||
| 分享裂变 | 低 CAC | Decode / ScaleResult 分享 |
|
||||
|
||||
## 2. 测测的坑(愈心谷要避开)
|
||||
|
||||
| 风险 | 测测表现 | 愈心谷对策 |
|
||||
|---|---|---|
|
||||
| 定位拧巴 | 泛心理 vs 占星吸引力冲突 | 主叙事:文化测评 + 国标体质生活建议;重玄学模块降权 |
|
||||
| AI 像「算命」 | 引导问题偏运势 | Ask 按进入路径动态引导(性格/关系/养生) |
|
||||
| 视角切换难发现 | 「分析 TA」藏太深 | 首页解码后强引导建 Other Profile;Ask 顶部显式切换 Self/Other |
|
||||
| 跨会话记忆弱 | 电子闺蜜体验断裂 | MVP 先做 Profile 结构化记忆;长对话记忆 V1.2+ |
|
||||
| 多智能体认知负担 | 入口并列 | **只做一个 Ask**;不并行灵犀/小智式品牌矩阵 |
|
||||
|
||||
## 3. 信息架构对照
|
||||
|
||||
```
|
||||
测测: 首页 | 消息 | 问 | 在线 | 我的
|
||||
愈心谷: 首页 | 探索 | 问 | 陪伴 | 我的
|
||||
```
|
||||
|
||||
- **探索** ≈ 测测首页宫格 + AI 玩法广场的「内容供给」(MVP 不做 UGC 广场,只做官方 Scale / Decode 入口)
|
||||
- **陪伴** ≈ 每日心情 + 节气(测测心情打卡的留存位,换成 SolarTerm + Mood)
|
||||
- **消息 / 在线** 后置;Consult 先做预约表单,不做达人双边平台
|
||||
|
||||
## 4. 核心用户路径(对标测测三条场景)
|
||||
|
||||
### P1 自我探索(拉新)
|
||||
|
||||
Visitor → 首页 Decode 或 Scale → 简版结论 → 分享 → 注册为 User
|
||||
|
||||
### P2 关系决策(差异化)
|
||||
|
||||
User 建 Other Profile → Match 预览分数 → Unlock 解读 →(可选)Ask 切换 TA
|
||||
|
||||
### P3 情绪 / 养生留存(夜间场景)
|
||||
|
||||
Mood 打卡 / SolarTerm → Ask(档案上下文)→ 额度用尽 → Subscription
|
||||
|
||||
## 5. 能力分层(对标测测「情感陪伴层」)
|
||||
|
||||
```
|
||||
入口层(免费) Decode 简版 / Scale 部分 / Share
|
||||
留存层(VIP) Ask 额度 / SolarTerm 个性化 / Mood / 多 Profile
|
||||
转化层(高客单) Report Unlock / Match / Consult
|
||||
```
|
||||
|
||||
## 6. 不做清单(相对测测)
|
||||
|
||||
- 不自研大模型备案叙事(可接外部 LLM)
|
||||
- 不做硬件(巴布类)
|
||||
- 不做达人双边平台冷启动
|
||||
- 不做 AI 心情小镇 / 3D 沙盘(成本高,非差异化必需)
|
||||
- Legacy 根目录 HTML 不承接新需求(见 `.ai/architecture.md`)
|
||||
|
||||
## 7. 结论(一句话)
|
||||
|
||||
测测验证了「测评入口 → 档案化 AI → 订阅 + 咨询」飞轮;愈心谷用 **体质与节气** 替换「运势主叙事」,用 **家庭/关系 Profile** 做裂变,用 **合规生活建议** 守住审核与信任。
|
||||
@@ -0,0 +1,90 @@
|
||||
# 愈心谷商业模式
|
||||
|
||||
关联:[PRD MVP](prd-mvp.md) · [测测拆解](analysis/cece-teardown.md) · [产品路线图](product-roadmap.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 一句话
|
||||
|
||||
用「数字性格 + 中医体质」做**可复算、可对照**的自我认知入口,以**订阅为主、报告/契合为辅、咨询为远期高客单**,承接测测式漏斗,但避开算命与医疗承诺。
|
||||
|
||||
---
|
||||
|
||||
## 2. 价值主张
|
||||
|
||||
| 对用户 | 对产品 |
|
||||
|---|---|
|
||||
| 知道「我是谁 / 我缺什么 / 怎么相处」 | 低摩擦获客(生日 / 量表) |
|
||||
| 比泛星座更「有结构」、比纯心理量表更「东方语境」 | 差异化:体质 × 性格 × 关系档案 |
|
||||
| 节气与日更内容形成回访理由 | 订阅续费钩子 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 收入三层(对齐测测,本地化)
|
||||
|
||||
```
|
||||
L1 免费获客 Decode 简版 / Scale / 分享卡
|
||||
↓
|
||||
L2 订阅留存 Membership:Ask 次数、完整报告、SolarTerm 深度、Mood 复盘
|
||||
↓
|
||||
L3 高 ARPU Unlock 单次报告/Match ·(远期)Consult
|
||||
```
|
||||
|
||||
| 层级 | 产品 | 定价方向(可调) | 备注 |
|
||||
|---|---|---|---|
|
||||
| L1 | 简版 Decode、热门 Scale | 0 | 结论可见 |
|
||||
| L2 | 月/季/年 VIP | 参考测测档位,偏下探试价 | 主收入 |
|
||||
| L2.5 | Unlock 完整报告 / Match 解读 | 单次低客单 | 不愿订也可转化 |
|
||||
| L3 | Consult | 远期 | 需履约与合规,非 MVP |
|
||||
|
||||
**不做:** 侵入式广告、诱导抽奖、伪医疗售卖。
|
||||
|
||||
---
|
||||
|
||||
## 4. 飞轮
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Share[分享卡/社交] --> Free[免费测评]
|
||||
Free --> Profile[档案沉淀]
|
||||
Profile --> Paywall[原因与方案付费墙]
|
||||
Paywall --> VIP[订阅]
|
||||
VIP --> Ask[问 / 陪伴回访]
|
||||
Ask --> Share
|
||||
Profile --> Match[关系档案]
|
||||
Match --> Unlock[单次解锁]
|
||||
Unlock --> VIP
|
||||
```
|
||||
|
||||
关键:Profile 越多 → Match/Ask 越有用 → 续费与解锁越高。
|
||||
|
||||
---
|
||||
|
||||
## 5. 单位经济(假设,待校验)
|
||||
|
||||
| 指标 | MVP 观测 |
|
||||
|---|---|
|
||||
| 免费完成率 | Decode 简版 / Scale 完成率 |
|
||||
| 付费转化 | 简版→Unlock 或 VIP |
|
||||
| ARPU | 订阅为主,Unlock 为辅 |
|
||||
| 留存 | D1/D7;节气打开率 |
|
||||
| 合规成本 | 客服投诉 / 违规文案拦截率 |
|
||||
|
||||
付费与权益**只信服务端**(见 `.ai/security.md`)。
|
||||
|
||||
---
|
||||
|
||||
## 6. B2B / 扩展(非 MVP)
|
||||
|
||||
企业 EAP、线下门店引流、内容授权——在 C 端漏斗跑通后再开。平台扩展路径:H5 → 小程序(同一 `packages/sdk`)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 与测测的差异化(商业)
|
||||
|
||||
| 测测 | 愈心谷 |
|
||||
|---|---|
|
||||
| 星盘+心理+社交玩法宽 | 数字性格+体质窄而深 |
|
||||
| 强娱乐/玄学氛围 | 可复算、生活建议、免责声明 |
|
||||
| 咨询达人网络 | 先模板 Ask,后 Consult |
|
||||
| UGC 广场 | 暂不做,避免内容治理成本 |
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user