正在修复一些问题
This commit is contained in:
1 parent
ad363041c3
commit
66069ef0f1
11 files changed
+207
-142
No files matched your search
@@ -1,115 +1,85 @@
|
||||
|
||||
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
# 任何项目都务必遵守的规则(极其重要!!!)
|
||||
## Project Overview
|
||||
保持中文回复和中文询问
|
||||
|
||||
## Communication
|
||||
Offline, client-side Vue 3 application for calculating transportation infrastructure consulting fees (交通工程造价咨询收费). All data persists to IndexedDB via localforage — there is no backend API.
|
||||
|
||||
- 永远使用简体中文进行思考和对话
|
||||
## Tech Stack
|
||||
|
||||
## Documentation
|
||||
- **Framework**: Vue 3 with Composition API (`<script setup>` SFCs)
|
||||
- **Language**: TypeScript (strict mode)
|
||||
- **Build**: Vite 8 (beta) with Rolldown
|
||||
- **Package Manager**: Bun
|
||||
- **Styling**: Tailwind CSS v4 via `@tailwindcss/vite` plugin
|
||||
- **UI Primitives**: Reka UI (headless), Lucide icons
|
||||
- **Grids**: AG Grid Enterprise v35 (modules registered globally in `main.ts`)
|
||||
- **State**: Pinia with custom IndexedDB persistence plugin (`src/pinia/Plugin/indexdb.ts`)
|
||||
- **Math**: decimal.js for precise fee calculations
|
||||
|
||||
- 编写 .md 文档时,也要用中文
|
||||
- 正式文档写到项目的 docs/ 目录下
|
||||
- 用于讨论和评审的计划、方案等文档,写到项目的 discuss/ 目录下
|
||||
|
||||
## Code Architecture
|
||||
|
||||
- 编写代码的硬性指标,包括以下原则:
|
||||
(1)对于 Python、JavaScript、TypeScript 等动态语言,尽可能确保每个代码文件不要超过 500 行
|
||||
(3)每层文件夹中的文件,尽可能不超过 8 个。如有超过,需要规划为多层子文件夹
|
||||
- 除了硬性指标以外,还需要时刻关注优雅的架构设计,避免出现以下可能侵蚀我们代码质量的「坏味道」:
|
||||
(1)僵化 (Rigidity): 系统难以变更,任何微小的改动都会引发一连串的连锁修改。
|
||||
(2)冗余 (Redundancy): 同样的代码逻辑在多处重复出现,导致维护困难且容易产生不一致。
|
||||
(3)循环依赖 (Circular Dependency): 两个或多个模块互相纠缠,形成无法解耦的“死结”,导致难以测试与复用。
|
||||
(4)脆弱性 (Fragility): 对代码一处的修改,导致了系统中其他看似无关部分功能的意外损坏。
|
||||
(5)晦涩性 (Obscurity): 代码意图不明,结构混乱,导致阅读者难以理解其功能和设计。
|
||||
(6)数据泥团 (Data Clump): 多个数据项总是一起出现在不同方法的参数中,暗示着它们应该被组合成一个独立的对象。
|
||||
(7)不必要的复杂性 (Needless Complexity): 用“杀牛刀”去解决“杀鸡”的问题,过度设计使系统变得臃肿且难以理解。
|
||||
- 【非常重要!!】无论是你自己编写代码,还是阅读或审核他人代码时,都要严格遵守上述硬性指标,以及时刻关注优雅的架构设计。
|
||||
- 【非常重要!!】无论何时,一旦你识别出那些可能侵蚀我们代码质量的「坏味道」,都应当立即询问用户是否需要优化,并给出合理的优化建议。
|
||||
## Commands
|
||||
|
||||
- **Dev server**: `bun run dev` (uses `bunx --bun vite`)
|
||||
- **Build**: `bun run build` (type-checks then bundles via Vite)
|
||||
- **Type check only**: `bun run type-check`
|
||||
- **Preview build**: `bun run preview`
|
||||
```bash
|
||||
bun run dev # Dev server (bunx --bun vite)
|
||||
bun run build # Type-check then build (vue-tsc -b && vite build)
|
||||
bun run preview # Preview production build
|
||||
bun run type-check # Type-check only (vue-tsc --noEmit)
|
||||
```
|
||||
|
||||
No test runner is configured. Use Playwright for UI automation when needed (see AGENTS.md).
|
||||
No test framework is configured.
|
||||
|
||||
## Architecture Overview
|
||||
## Architecture
|
||||
|
||||
This is a **browser-only Vue 3 SPA** — no backend, no SSR. All data is persisted client-side via IndexedDB (through localforage). The domain is **交通建设项目工程造价咨询** (transport infrastructure cost-consulting fee calculation for road, railway, and waterway projects).
|
||||
### Navigation (No Vue Router)
|
||||
|
||||
### App Entry & Routing
|
||||
|
||||
There is no Vue Router. Navigation is tab-based, managed entirely by `useTabStore` (`src/pinia/tab.ts`). `src/App.vue` shows either `HomeEntryView` (first-launch onboarding) or the main `Tab` layout depending on `tabStore.hasCompletedSetup`.
|
||||
|
||||
The `Tab` layout (`src/layout/tab.vue`) renders the active tab's component by name using `defineAsyncComponent` with a map of component names → import paths.
|
||||
Tab-based navigation managed by `useTabStore` (`src/pinia/tab.ts`). Each tab has a `componentName` resolved via `defineAsyncComponent` in `src/layout/tab.vue`. Protected tabs cannot be closed by the user.
|
||||
|
||||
### Workspace Modes
|
||||
|
||||
Defined in `src/lib/workspace.ts`. Three modes: `home`, `project`, `quick`. The current mode is persisted to `localStorage` under key `jgjs-workspace-mode-v1`. Two fixed/protected tab IDs exist: `ProjectCalcView` and `QuickCalcView` (and the quick-contract tab), which cannot be closed.
|
||||
Two modes stored in localStorage under `jgjs-workspace-mode-v1`:
|
||||
- `project` — multi-contract project workspace (default)
|
||||
- `quick` — single quick-calculation mode
|
||||
|
||||
### State & Persistence
|
||||
Mode logic and tab ID constants live in `src/lib/workspace.ts`.
|
||||
|
||||
- **Pinia** is used for all state management with `pinia-plugin-persistedstate`.
|
||||
- The persistence plugin is customized at `src/pinia/Plugin/indexdb` — it stores pinia state in IndexedDB (not localStorage), using localforage with `mode: 'multiple'` (each store in its own IndexedDB store named `pinia`).
|
||||
- `useTabStore` (`src/pinia/tab.ts`): tab list, active tab, setup flag. Persisted.
|
||||
- `useZxFwPricingStore` (`src/pinia/zxFwPricing.ts`): the core domain store. Manages contract-level 咨询服务 (consulting service) pricing state, per-service pricing method states, and contract extra-fee states. Uses a generic key/value layer (`getKeyState`/`setKeyState`/`loadKeyState`) backed by `useKvStore`.
|
||||
- `useKvStore` (`src/pinia/kv.ts`): raw key-value access to IndexedDB via localforage.
|
||||
### Pinia Stores
|
||||
|
||||
### Data Layer (`src/sql.ts`)
|
||||
| Store | File | Purpose |
|
||||
|-------|------|---------|
|
||||
| `useTabStore` | `src/pinia/tab.ts` | Tab list, active tab, workspace entry |
|
||||
| `useKvStore` | `src/pinia/kv.ts` | Generic key-value persistence layer |
|
||||
| `useZxFwPricingStore` | `src/pinia/zxFwPricing.ts` | Core pricing/contract data with versioned snapshot diffing |
|
||||
|
||||
Despite the name, there is no SQL database. `src/sql.ts` is a large static data file containing:
|
||||
- `industryTypeList`: road / railway / waterway
|
||||
- `majorList`: engineering specialties (E1–E4 codes) with coefficient ranges
|
||||
- `serviceList`: consulting service types (D1–D5 codes) with pricing method flags
|
||||
- `additionalWorkList`: extra work item definitions
|
||||
- `exportFile`: Excel export logic using ExcelJS
|
||||
All stores persist to IndexedDB via the custom plugin in `src/pinia/Plugin/indexdb.ts` (uses localforage).
|
||||
|
||||
All fee calculation formulas and coefficient tables live here.
|
||||
### Domain Data
|
||||
|
||||
### Lib Utilities (`src/lib/`)
|
||||
`src/sql.ts` contains the full fee schedule: majors (专业), services (咨询服务), work types, and pricing method lookup tables. Four pricing methods: 投资规模法, 用地规模法, 工作量法, 工时法.
|
||||
|
||||
- `decimal.ts` / `number.ts` / `numberFormat.ts`: safe arithmetic using `decimal.js`, thousand-separator formatting
|
||||
- `zwArchive.ts`: AES-GCM encryption/decryption for `.zw` save files (import/export format). The key is derived from a fixed seed via SHA-256. File magic bytes: `JGJSZW`.
|
||||
- `workspace.ts`: workspace mode constants and storage helpers
|
||||
- `diyAgGridOptions.ts`: shared AG Grid configuration defaults
|
||||
- `pricingScaleFee.ts` / `pricingMethodTotals.ts`: fee calculation helpers
|
||||
- `projectWorkspace.ts` / `xmFactorDefaults.ts`: project-level workspace helpers
|
||||
- `zxFwPricingSync.ts`: syncs pricing store state to/from IndexedDB on demand
|
||||
### Key Directories
|
||||
|
||||
### Views (`src/components/views/`)
|
||||
- `src/components/views/` — top-level view components (rendered in tabs)
|
||||
- `src/components/ht/` — contract (合同) components
|
||||
- `src/components/xm/` — project (项目) components
|
||||
- `src/components/pricing/` — pricing method panes (one per method)
|
||||
- `src/components/shared/` — reusable AG Grid wrappers
|
||||
- `src/components/ui/` — primitive UI components (shadcn-vue style)
|
||||
- `src/lib/` — utilities: decimal math, number formatting, AG Grid config, workspace logic, `.zw` archive encode/decode
|
||||
- `src/layout/` — tab shell and layout components
|
||||
|
||||
Key views:
|
||||
- `HomeEntryView.vue`: onboarding screen shown on first launch; dispatches `home-import-selected` DOM event on completion
|
||||
- `ProjectWorkspaceView.vue` / `xmCard.vue`: project card workspace (项目卡片)
|
||||
- `QuickCalcView.vue`: quick calculation mode
|
||||
- `ZxFwView.vue`: 咨询服务 (consulting services) grid — the primary fee input view
|
||||
- `Ht.vue` / `htCard.vue`: contract (合同) views
|
||||
- `HtFeeMethodTypeLineView.vue`: per-service fee method line (rate/hourly/quantity-unit-price)
|
||||
- `WorkContentGrid.vue`: AG Grid-based work content table
|
||||
### Import/Export
|
||||
|
||||
### AG Grid
|
||||
Custom `.zw` binary archive format (`src/lib/zwArchive.ts`) for project data. Excel export via ExcelJS (`src/sql.ts`).
|
||||
|
||||
AG Grid Enterprise is used throughout. Modules are registered once globally in `src/main.ts`. A license key is set there. Shared grid option defaults live in `src/lib/diyAgGridOptions.ts`.
|
||||
## Path Alias
|
||||
|
||||
### UI Components
|
||||
`@` maps to `src/` (configured in both `vite.config.ts` and `tsconfig.json`).
|
||||
|
||||
Reka UI (headless component library) + Tailwind CSS v4 + `lucide-vue-next` icons + `@iconify/vue`. Shared UI primitives are in `src/components/ui/`. Tailwind is integrated as a Vite plugin (`@tailwindcss/vite`).
|
||||
## Conventions
|
||||
|
||||
### Build
|
||||
|
||||
Vite 8 with rolldown. Output goes to `dist/` with `base: './'` (relative paths — important for local file:// deployment). Code-splitting separates `ag-grid`, `vue/pinia`, and `reka-ui` into distinct vendor chunks.
|
||||
|
||||
### Code Conventions
|
||||
|
||||
- All code comments are in Chinese.
|
||||
- Composition API (`<script setup>`) everywhere.
|
||||
- No Vue Router — use `useTabStore.openTab()` to navigate.
|
||||
- Numeric calculations always go through `src/lib/decimal.ts` helpers to avoid floating-point errors.
|
||||
- Storage keys follow patterns like `zxFW-{contractId}`, `tzGMF-{contractId}-{serviceId}`, `htExtraFee-{contractId}-{feeType}`.
|
||||
- All UI text is in Chinese (zh-CN)
|
||||
- Immutable state updates in Pinia stores (create new arrays/objects, don't mutate)
|
||||
- AG Grid modules are registered once globally in `main.ts` — don't re-register in components
|
||||
- Decimal.js is used for all fee arithmetic to avoid floating-point errors (`src/lib/decimal.ts`)
|
||||
Reference in new issue
Block a user