JGJS2026/CLAUDE.md
2026-03-17 12:05:22 +08:00

7.1 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

任何项目都务必遵守的规则(极其重要!!!)

Communication

  • 永远使用简体中文进行思考和对话

Documentation

  • 编写 .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

No test runner is configured. Use Playwright for UI automation when needed (see AGENTS.md).

Architecture Overview

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).

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.

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.

State & Persistence

  • 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.

Data Layer (src/sql.ts)

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 (E1E4 codes) with coefficient ranges
  • serviceList: consulting service types (D1D5 codes) with pricing method flags
  • additionalWorkList: extra work item definitions
  • exportFile: Excel export logic using ExcelJS

All fee calculation formulas and coefficient tables live here.

Lib Utilities (src/lib/)

  • 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

Views (src/components/views/)

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

AG Grid

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.

UI Components

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).

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}.