# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Multi-client SaaS platform (基于 likeadmin 脚手架改造) centered on 中医在线问诊 — video consultations (TRTC), prescriptions, medicine library, 企微 (QYWX) integration, and payments. Single repo contains a PHP backend plus four independent frontend clients. ## Top-Level Layout | Dir | Stack | Purpose | |-----|-------|---------| | `server/` | ThinkPHP 8 + PHP 8.0+ | REST API, the single source of truth | | `admin/` | Vue 3 + Vite + Element Plus + Tailwind | 管理后台 (desktop) | | `pc/` | Nuxt 3 + Element Plus | 公开 PC 站 (SSR/SSG) | | `uniapp/` | uni-app (Vue 3, Vite) | H5 / 小程序 / App 多端客户端 | | `wx/` | uni-app 微信小程序 | 独立 TRTC 微信小程序壳 | | `TUICallKit*/` | Tencent TRTC UIKit | Vendor SDK source used by clients | | `docker/` | docker-compose (nginx + php-fpm + mysql) | Local dev stack | | `doc/`, `ps/` | Supporting docs / psd | Design & reference material | Each frontend is deployed to `server/public//` (see `server/route/app.php` fallback routes). Don’t rely on a root-level workspace — each client has its own `package.json` and must be built separately. ## Common Commands ### Backend (`server/`) ``` composer install # install deps php think run --host 0.0.0.0 --port 8080 # dev server (if PHP CLI) php think # run CLI commands (see app/command/) php think crontab # trigger cron tasks manually ``` - Docker alternative: `cd docker && docker-compose up -d` (exposes nginx on :80, mysql on :3306). - SQL migrations live in `server/sql//*.sql` (versioned by date). Apply manually in order; there is no automatic migration runner. Current version directory: `server/sql/1.9.20260420/`. ### Admin (`admin/`) ``` npm install npm run dev # Vite dev server npm run build # production build + node scripts/release.mjs npm run type-check # vue-tsc --noEmit npm run lint # ESLint with --fix npm run clean # node scripts/clean.mjs ``` ### PC (`pc/`) ``` npm install npm run dev # Nuxt dev server on :3000 npm run build # nuxt generate + scripts/build.mjs (static export) npm run build:ssr # Nuxt SSR build ``` ### uniapp (`uniapp/`) ``` npm install npm run dev:h5 # H5 npm run dev:mp-weixin # 微信小程序 npm run dev:app # App npm run build:h5 # build + scripts/release.mjs # other targets: mp-alipay, mp-baidu, mp-qq, mp-toutiao, quickapp-webview... npm run lint ``` ### Running a single test There is no unit-test harness checked in (no Jest/Vitest/PHPUnit config). When adding tests, wire the framework first; don’t assume one exists. ## Backend Architecture (likeadmin conventions) `server/app/` is a ThinkPHP multi-app project. Three apps with a shared `common/` layer: - `adminapi/` — admin panel API (consumed by `admin/`) - `api/` — public/end-user API (consumed by `pc/`, `uniapp/`, `wx/`) - `index/` — default app fallback - `common/` — shared models, services, enums, exceptions, listeners Each app follows the layered pattern: ``` / ├── controller/ # HTTP entry; extends BaseAdminController / BaseApiController ├── logic/ # Business logic; static methods invoked by controllers ├── lists/ # List-query objects (pagination/filter/export encapsulation) ├── validate/ # Request validation rules ├── service/ # App-scoped services ├── http/ # Middleware, route groups └── config/ # App-specific config ``` Key conventions: - **Controllers stay thin.** They pull `$this->request->get()/post()`, delegate to a `Logic` class, and wrap the result with `$this->data(...)` / `$this->success(...)` / `$this->fail(...)` from `BaseLikeAdminController` (in `common/controller`). - **Logic returns plain arrays.** Throw `\app\common\exception\*` for failures — the global exception handler (`app/ExceptionHandle.php`) converts them to JSON envelopes. - **Models extend `app\common\model\BaseModel`** which auto-completes image paths via `FileService`. - **Route registration is menu-driven.** Admin routes are auto-resolved from menu entries (see `add_conversion_stats_menu.sql` as an example of wiring a new admin page). Public routes are declared in `app/api/route/` and `server/route/app.php`. - **Payment / third-party callbacks** bypass auth — declared explicitly in `server/route/app.php` (e.g. wechat-notify, alipay-notify, TRTC recording-notify). ## Admin Architecture (`admin/src/`) ``` src/ ├── api/ # One file per domain (stats.ts, order.ts, doctor.ts...) ├── views/ # Page components grouped by domain (mirrors api/) ├── router/ │ ├── index.ts # Dynamic route generation from backend menu │ └── routes.ts # Static/constant routes + LAYOUT wrapper ├── stores/modules/ # Pinia stores (user, app, tagsView...) ├── components/ # Shared components ├── utils/request/ # Axios instance + interceptors ├── hooks/ # Composables ├── install/ # Global plugin registration (app.use(install)) └── permission.ts # Login/permission guard mounted on router ``` - **Views are dynamically loaded** via `import.meta.glob('/src/views/**/*.vue')` in `router/index.ts`. A view path from the backend menu (e.g. `stats/conversion/index`) resolves to `src/views/stats/conversion/index.vue`. When adding a page, the corresponding menu record must be inserted via SQL (pattern: `server/sql/.../add_*_menu.sql`). - **API calls go through `utils/request`** which normalizes the response envelope and handles auth/error toasts. Don’t use axios directly. - **Auto-imports**: Element Plus components, `ref`/`reactive`/router composables are auto-imported via `unplugin-auto-import` — no need to import them explicitly (see `auto-imports.d.ts`). ## Cross-Cutting Concerns - **Versioned SQL migrations.** New schema/menu changes go in `server/sql//*.sql`. When adding an admin view, pair it with an `add_*_menu.sql` file (see current WIP: `add_conversion_stats_menu.sql` + `admin/src/views/stats/conversion/`). - **TRTC integration.** Video-call logic is split between `TUICallKit/` (vendor), `admin/src/utils/call-*.ts` and `src/utils/im-*.ts`, and the `api/controller/TrtcController`. Cloud recording is triggered server-side and written back via the `/api/trtc/recording-notify` callback. - **企微 (QYWX).** `server/app/adminapi/controller/qywx/` + `admin/src/views/qywx/` + `pc/` pages exchange via `easywechat`. OAuth/bind flow uses `admin/src/utils/wecomOauthPostMessage.ts` and `wecomBindGuard.ts`. - **Multi-cloud storage.** File uploads support Qiniu / Tencent COS / Aliyun OSS — configuration is driven by runtime admin settings, resolved in `FileService`. ## Trellis Workflow This repo is Trellis-managed (see `.trellis/`). New work should go through: 1. `/trellis:start` — loads session context 2. `/trellis:brainstorm` for complex/vague asks (creates `prd.md`) 3. Research → `task.py init-context` → Implement → Check agents 4. `/trellis:finish-work` before committing Code-spec files under `.trellis/spec/` are injected into sub-agent contexts automatically. Relevant thinking guides live in `.trellis/spec/guides/`. ## Language & Docs All user-facing commentary, commit messages, and code comments in this repo use 简体中文 when addressing the product domain; identifiers, API paths, and this file stay in English. The backend still carries original likeadmin attribution headers — do not remove them on edit.