Files
zkxw/AGENTS.md
T
2026-05-25 17:43:49 +08:00

17 KiB
Raw Blame History

AGENTS.md — zkxw (陇耘鲜达)

Two-package monorepo: Python backend + Vue 3 admin frontend. Named "sanqiang" internally.

Repository Layout

backend/          FastAPI backend (Python 3.9, venv)
web-admin/        Vue 3 admin panel (pnpm, Vite 7, Element Plus, Tailwind CSS 4)
docs/             UI specs, SQL schemas, requirements docs
openspec/         OpenSpec: `config.yaml`; active changes under `openspec/changes/*/`
.cursorrules      Detailed UI conventions and constraints (Chinese)

OpenSpec engineering standards

Full specs: openspec/changes/zkxw-engineering-standards/specs/*/spec.md. Below are the key SHALL items every coding session MUST follow.

UI Conventions (web-admin + miniprogram)

  • Visual authority: web-admin SHALL follow docs/web-admin-ui-spec-fresh-mint.md (Fresh Mint palette, --primary #10b981). miniprogram SHALL follow docs/miniprogram-ui-spec-sanqiang.md (三墙 palette, brand green #0a9f6d).
  • No cross-app color mixing: web-admin SHALL NOT use #0a9f6d as primary; miniprogram SHALL NOT use #10b981 as primary.
  • Tree path display: Dropdown/tree nodes show node name only; input fields, table columns, exports, and view dialogs SHALL show full ancestor path. Separator: / (space-slash-space). See web-admin/src/utils/tree-path.ts.
  • Dialog forms: label-position="top". No backdrop blur (backdrop-filter: none). Use .dialog-form-layout with max-height: calc(100vh - 100px), only body scrolls.
  • Dialog grid: Default 2-column (.form-grid-2). Max 5 columns. Full-width fields use .form-col-span-2 (grid-column: 1 / -1). Narrow viewport SHALL fallback to fewer columns.
  • List panel heading: panel-top → h2.title-bar-heading SHALL show primary-color vertical bar via ::before. Ambiguous titles (e.g. "租户" containing "户") SHALL be registered in App.vue panelTitleBarTextRules.
  • Miniprogram media: Thumbnails 1:1 aspectFill; carousel 4:3 aspectFill; detail images widthFix. Min tap target 44×44px.
  • Sidebar menu icons: First-level menu items SHALL show icons before the name; second-level and deeper items SHALL NOT show icons (text only). Implemented via level === 0 check in SidebarSubmenu.vue.
  • Tab bar (WorkTab) icons: Tab bar tabs SHALL NOT show icons — only text titles. meta.icon is for sidebar only.
  • Form field annotations: Field hints (e.g. "数值越小越靠前") SHALL appear as small text after the label via <template #label>字段名<span class="form-label-tip">注释</span></template>, NOT beside the input control. Style class: .form-label-tip (12px, --mint-text-muted).
  • Attachment upload card layout: Upload trigger SHALL be a card (140×96px, dashed border #a7f3d0) inline as the first item in the same flex row as uploaded attachment cards; select file → immediate upload via fetchUploadAttachment; preview/download/delete on cards; hint below the row. Authority: ProtocolFormDialog.vue «协议附件». See openspec/changes/zkxw-engineering-standards/specs/ui-conventions/spec.md §「附件上传卡片化布局」for full Vue template + SCSS + interaction rules.
  • Button icons: All web-admin el-button with visible text labels SHALL include a leading <el-icon> from @element-plus/icons-vue (explicit import). See openspec/.../ui-conventions/spec.md §「按钮须携带图标」.
  • Sort fields (sort_order/orderNum): web-admin 列表、新增弹窗、编辑弹窗中默认不展示排序字段。后续根据功能需要自行添加。
  • Status/conclusion/type fields as Tags: All status, conclusion, and type fields in table columns and view dialogs SHALL render as <el-tag> with semantic colors. Tables: use <el-tag :type="..." size="small"> in column templates. SystemViewDialog: use tagType property on ViewField. Semantic colors: success=正常/启用/已完成/通过, warning=进行中/待确认/已过期, danger=异常/已作废/拒绝/不通过, info=待执行/待生效/停用/默认, primary=特殊分类/来源类型. SHALL NOT use plain text or custom <span class="tag">. See openspec/.../ui-conventions/spec.md "状态、结论与类型字段使用 Tag 标签展示".
  • Template pages — new pages SHALL match these exactly:
    • Standard list: src/views/system/unit/index.vue
    • Complex list: src/views/system/order/index.vue
    • Product list + view dialog: src/views/system/product/index.vue
    • Tree master data: src/views/system/category/index.vue
    • User CRUD: src/views/system/user/index.vue
  • UI pattern index — before implementing a new page, developers SHALL select a pattern code (P01–P27) per docs/web-admin-ui-pattern-index.md and OpenSpec ui-conventions §「界面模式索引与参考页选型」; PRs SHALL cite pattern code and reference page path.

API Conventions (backend)

  • Cell-storage sample cross-table key: Matching biz_protocol_sample to downstream rows (sample reception, QC work orders, etc.) SHALL use tenant_no + sample_code only—not collection_protocol_id or protocol_sample_id (protocol may change; sample code does not). See openspec/changes/zkxw-engineering-standards/specs/api-conventions/spec.md §「细胞存储样本跨表关联键」.
  • Tenant isolation: All business data queries SHALL filter by current user's tenant_no. All write/update endpoints SHALL set tenant_no to the current user's tenant. MUST NOT trust client-submitted tenant overrides (unless multi-tenant admin API with security review).
  • Data permission: All business queries SHALL apply data scope filtering based on the union of all roles assigned to the current user (menu + data permissions both use union semantics).
  • Default sort: Lists SHALL sort by create_time DESC when no custom sort is specified.
  • Route registration: New route modules SHALL be registered in app/api/__init__.py AND app/main.py. SHALL NOT bypass auth/crypto/audit middleware.

Database Conventions

  • Engine: MySQL 5.7, charset utf8mb4.
  • Public fields (every business table SHALL include these after business fields): id VARCHAR(64) UUID, tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag (default 0).
  • Field order: id → business fields → public fields (tenant_no through del_flag).
  • Soft delete: SHALL NOT physically delete business data. Delete = set del_flag=1. Queries SHALL exclude del_flag=1 by default.
  • Primary key: id SHALL be VARCHAR(64) NOT NULL, UUID value.

Architecture Conventions

  • Monorepo structure: Python backend (backend/) + Vue 3 web-admin (web-admin/) + uni-app miniprogram (miniprogram/). Shared backend and tenant model.
  • File attachments: SHALL use object storage (MinIO). Multiple attachments in one field SHALL be comma-separated URLs.
  • Authoritative docs: docs/中科兴皖需求V0.3.md (requirements), docs/web-admin-ui-spec-fresh-mint.md (web UI), docs/miniprogram-ui-spec-sanqiang.md (miniprogram UI).

Coding Conventions

  • Minimal changes: Commits SHALL contain only what's needed. No unrelated refactoring or formatting.
  • Frontend (web-admin): pnpm, Prettier (single quotes, no semicolons, 2-space indent). Vue/Element Plus auto-imports — SHALL NOT manually import auto-imported APIs/components.
  • Backend: Python 3.9, FastAPI + SQLAlchemy + Pydantic v2. Routes stay thin; business logic goes in app/services/ and app/crud/. Config via pydantic-settings + .env files.
  • DB changes: SHALL maintain SQL in docs/sql/. Schema changes SHALL align with database-conventions public field rules.
  • Commit messages: SHALL be complete sentences describing "what changed and why". Follow Conventional Commits (feat|fix|docs|…).
  • Field consistency (CRUD ↔ Schema ↔ Frontend): When implementing CRUD for any entity, the _row_to_dict function is the single source of truth for all readable fields. The CreateBody/UpdateBody Pydantic schemas and the frontend formData initialization SHALL include every writable field present in _row_to_dict (excluding computed/read-only fields like id, createTime, updateTime, stockQty). Run python scripts/check_field_consistency.py after implementation to verify. See docs/dev-field-consistency.md for details.

Permission Conventions

  • Role-menu: Selecting a child menu SHALL auto-include all ancestor menus (no orphan leaves).
  • Data scope: Per role — all / own dept / own dept and below / self only / custom. Custom uses sys_role_data_scope_detail with scope_type (dept/user) + scope_value.
  • Multi-role union: A user with multiple roles gets the union of menu permissions and the union of data scopes across all roles.
  • Dual menu trees: Web and miniprogram each have a separate top-level virtual root (parent_id=0). New menus SHALL be placed under the correct root.
  • Tenant management: Accessible ONLY by super_admin. All other system management runs within tenant context.

Workflow Conventions (target design, not yet implemented)

  • Engine: SHALL be implemented in Python backend as an independent, configurable approval/flow subsystem.
  • Node types: Start, End, Approver, Conditional Branch (multi-branch supported). Extensible but SHALL NOT break published definitions.
  • Approver strategies: Specified users, specified roles, or SQL-based resolution. Per-node: "any one passes" or "all must pass".
  • Versioning: Each flow definition has a version. Running instances SHALL stick to their launch version; new versions only affect new launches.
  • Task centers: System SHALL provide "Pending Tasks" and "Completed Tasks" views.

Backend (backend/)

Stack

FastAPI · SQLAlchemy · Pydantic v2 · MySQL (pymysql) · Redis · MinIO · JWT auth · Alembic migrations

Commands

source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env.local   # fill in DB, Redis, MinIO, etc.
./start-local.sh              # uvicorn --reload on 127.0.0.1:8000
./start-prod.sh start         # production (reads .env.production, PID-managed)
./start-prod.sh status|stop|restart|logs

Entrypoint & Structure

  • Entrypoint: app/main.py → app.main:app
  • app/api/ — Route files: public.py (no auth), menu.py, admin.py. Register new routers in app/api/__init__.py and app/main.py.
  • app/core/ — Config (config.py), DB (database.py), auth (auth.py, security.py), middleware (api_crypto_middleware.py, api_request_log_middleware.py), RSA login crypto (login_crypto.py)
  • app/models/ — SQLAlchemy models (models.py, base.py)
  • app/schemas/ — Pydantic schemas per domain (auth, order, product, user, etc.)
  • app/crud/ — Database CRUD operations (base.py has generic base)
  • app/services/ — Business logic layer
  • app/tasks/ — APScheduler scheduled tasks
  • scripts/ — SQL migrations and one-off scripts

Key Patterns

  • API prefix: /api (set via API_V1_PREFIX in config). Routes: /api/public/*, /api/admin/*, /api/supplier/*, /api/client/*, /api/deliver/*
  • Auth: JWT + RSA-encrypted login. Login RSA key auto-generated or set via LOGIN_RSA_PRIVATE_KEY_PEM env var.
  • API encryption middleware: symmetric crypto layer controlled by API_ENCRYPT_* env vars. Excluded paths listed in API_ENCRYPT_EXCLUDE_PATHS.
  • Config: pydantic-settings (app/core/config.py), reads from .env / .env.local / .env.production.
  • Database init / schema baseline: docs/sql/zkxw.sql(从当前库导出的全量 SQL)。Default admin: admin / 111111, role super_admin.
  • Swagger docs at /docs, ReDoc at /redoc.
  • Tests: minimal, only tests/test_api_crypto.py. Run with pytest.

Frontend (web-admin/)

Stack

Vue 3 · TypeScript (strict: false, noImplicitAny: false) · Vite 7 · Element Plus · Tailwind CSS 4 · Pinia · vue-router (hash mode) · SCSS · Axios · pnpm

Commands

pnpm install                  # if fails: pnpm install --ignore-scripts
pnpm dev                      # Vite dev server (port from .env.development)
pnpm build                    # production build
pnpm build:typecheck          # typecheck + build (vue-tsc --noEmit)
pnpm lint                     # ESLint check
pnpm fix                      # ESLint --fix
pnpm lint:prettier            # Prettier format all
pnpm lint:stylelint           # Stylelint fix SCSS/Vue
pnpm commit                   # cz-git interactive commit
pnpm clean:dev                # strip demo data for fresh start

Entrypoint & Structure

  • Entrypoint: src/main.ts
  • src/views/system/ — Main business pages: category/, order/, product/, tenant/, unit/, user/
  • src/api/ — Axios API modules: auth.ts, admin.ts, business.ts, system.ts, chinaRegion.ts
  • src/store/modules/ — Pinia stores: user.ts, menu.ts, setting.ts, table.ts, worktab.ts
  • src/router/modules/ — Route modules: index.ts, sqxp.ts, exception.ts
  • src/utils/tree-path.ts — Tree path utilities (buildTreePathLabelFromFlat, etc.). Separator: / (spaced slash).

Path Aliases (tsconfig + vite)

@/* → src/*, @views/*, @imgs/*, @icons/*, @utils/*, @stores/*, @plugins/*, @styles/*

Key Patterns

  • Auto-imports: unplugin-auto-import + unplugin-vue-components — Vue, vue-router, pinia, @vueuse/core APIs and Element Plus components are auto-imported. Don't manually import them.
  • Element Plus: auto-imported resolvers — use components directly, no manual imports.
  • Tailwind CSS 4: via @tailwindcss/vite plugin.
  • SCSS: global mixin/data injected via vite.config.ts additionalData (uses @styles/core/el-light.scss and @styles/core/mixin.scss).
  • API proxy: dev server proxies /api → VITE_API_PROXY_URL (localhost:8000). Also /web and /mini proxies configured.
  • Env files: .env.development (local), .env.production (prod). Uses VITE_* prefix.
  • API encryption: VITE_API_ENCRYPT_ENABLED toggles request/response crypto in dev. Production has it on.
  • Hash routing: URLs use /#/ format.
  • Access mode: VITE_ACCESS_MODE=frontend (fixed frontend menu mode).

Code Style

  • Prettier: single quotes, no semicolons, 2-space indent, trailing comma: none, vueIndentScriptAndStyle: true
  • ESLint: extends recommended + typescript + vue essential + prettier. @typescript-eslint/no-explicit-any is OFF.
  • Stylelint: SCSS + Vue + recess-order property sorting.
  • Commit: Conventional commits via cz-git + commitlint. Types: feat|fix|docs|style|refactor|perf|test|build|ci|revert|chore|wip.
  • Husky + lint-staged: pre-commit auto-runs ESLint, Prettier, Stylelint on staged files.

UI Design Authority

The .cursorrules file and docs/ are the authoritative source for all UI decisions.

  • Web admin UI spec: docs/web-admin-ui-spec-fresh-mint.md + docs/fresh-mint-green.html
  • Template pages (match these exactly for new pages):
    • Standard list: src/views/system/unit/index.vue (/#/demo/unit)
    • Complex list: src/views/system/order/index.vue (/#/demo/order)
    • Product list + view dialog: src/views/system/product/index.vue
    • Tree master data: src/views/system/category/index.vue
    • User CRUD: src/views/system/user/index.vue
    • Console/dashboard: src/views/dashboard/console/index.vue
  • Color tokens (web-admin): Primary #10b981, dark #059669, bg #ecfdf5. Fresh Mint palette. Do NOT use miniprogram colors in web-admin.
  • Tree display: dropdown shows node name; selected/input/table shows full path (spaced slash separator).

Knowledge Graph (代码知识图谱)

项目已生成代码知识图谱,用于理解模块间依赖关系、追踪修改影响范围。

图谱位置

项目 报告 可视化 数据
后端 backend/graphify-out/GRAPH_REPORT.md backend/graphify-out/graph.html backend/graphify-out/graph.json
前端 web-admin/graphify-out/GRAPH_REPORT.md web-admin/graphify-out/graph.html web-admin/graphify-out/graph.json

使用方式

  • 浏览器:直接打开 */graphify-out/graph.html 查看交互式图谱
  • AI Agent 查询:已配置 MCP 服务(graphify),可通过工具调用查询图谱
  • 手动更新:./scripts/update-graph.sh [backend|frontend|all]

Agent 更新规则

完成代码修改后(新建文件、修改函数签名、新增/删除 import、重构模块),Agent SHALL 执行 ./scripts/update-graph.sh 增量更新图谱,确保图谱与代码保持同步。如果只修改了单个项目(backend 或 web-admin),只需更新对应项目即可。

Important Constraints

  • Language: User communication in Chinese (简体中文) when user writes in Chinese.
  • Minimal changes: Don't expand scope, don't refactor unrelated code. Match surrounding naming/type/import style.
  • Cross-app colors: Web admin uses Fresh Mint (#10b981), miniprogram uses 三墙 (#0a9f6d). Don't mix.
  • No backdrop blur on modals: backdrop-filter: none.
  • Dialog forms: label-position="top".
  • Table action column: fixed="right", min-width ≥ 260px.
  • Table column widths: All el-table-column SHALL use min-width (not width) for proportional scaling when viewport resizes.
  • Toolbar: "已选 N 项" first, then primary action button (only one type="primary" per toolbar row), no space-between push.
  • Database changes: always pair with schema SQL in docs/sql/ and evaluate API/TypeScript type impact.