# CLAUDE.md — 水利安全生产监管信息系统 ## Project Overview - **Name**: 水利安全生产监管信息系统 (Water Safety Production Supervision System) - **Group/Artifact**: `com.goldenwater:slaj:3.9.2` - **Database**: Migrating from Oracle → PostgreSQL (HighGo/瀚高) ## Tech Stack | Layer | Technology | Version | |-------|-----------|---------| | Java | JDK | 17 | | Framework | Spring Boot | 4.0.3 | | ORM | MyBatis Spring Boot | 4.0.1 | | Database | PostgreSQL (HighGo) | — | | UI | Vue 3 + Element Plus | 3.5.26 / 2.13.1 | | Build (FE) | Vite | — | | Connection Pool | Druid | 1.2.28 | ## Module Structure ``` slaj/ ├── gw-admin/ # Admin web module (controllers, composite services) — main entry point ├── gw-common/ # Shared entities, VOs, domain objects ├── gw-framework/ # Framework base classes (BaseController, etc.) ├── gw-quartz/ # Scheduled tasks ├── gw-slaj/ # Slaj business module (mappers, domain, controllers) ├── gw-system/ # System module (common mappers, services, sys_dept, etc.) ├── gw-ui/ # Vue 3 frontend └── docs/ # DDL scripts, documents ``` ## Database Configuration - **Schema**: `slaj` - **MyBatis**: `mapUnderscoreToCamelCase=true` → DB columns `org_name` auto-map to Java `orgName` - **PageHelper**: `helperDialect: postgresql` (set in application.yml) - **Dev DB**: `39.98.38.2:5866/highgo` - **Test DB**: `192.168.0.149:5866/highgo` ## Key Conventions ### 1. Result Mapping in MyBatis XML Use `resultType` (auto-mapping) for JOIN query results. DO NOT use `resultMap` — PostgreSQL returns lowercase column names, but `mapUnderscoreToCamelCase=true` handles the conversion automatically. When using `resultMap`, column aliases must match the resultMap column names exactly, which may conflict with PostgreSQL's lower-case behavior. ### 2. PostgreSQL Compatibility - **`find_in_set`** → `ANY(string_to_array(col, ','))` - **Upsert**: Use `INSERT ... ON CONFLICT (guid) DO UPDATE SET ...` - **String concat**: `'%' || #{param} || '%'` (not MySQL `CONCAT('%', #{param}, '%')`) ### 3. Organization Types (3 types) | Type | 中文名 | Tables | Description | |------|--------|--------|-------------| | Water Org | 水利机构 | `sys_dept` + `att_org_base` + `att_org_ext` | Government water departments | | Uwat Org | 参建单位 | `sys_dept` + `att_org_base` + `att_org_uwat_ext` | Construction units | | Wsub Org | 分包单位 | `sys_dept` + `att_org_base` + `att_org_wsub` | Subcontractor units | **Shared UUID pattern**: `sys_dept.dept_id` = `att_org_base.guid` = extension_table.`org_guid` ### 4. Organization Insert Order (CRITICAL) `SysDeptServiceImpl.insertDept()` internally regenerates UUID (line 230), so: 1. Insert `sys_dept` FIRST 2. Get the generated `deptId` from the returned dept object 3. Use that `deptId` as the shared UUID for `att_org_base.guid` and extension table's `org_guid` ### 5. Composite Services (gw-admin) All composite org operations (`add`/`update`/`delete`) are in `gw-admin/src/main/java/com/goldenwater/web/service/`: - `OrgCompositeService.java` — Water org (水利机构): sys_dept + att_org_base + att_org_ext - `OrgUwatCompositeService.java` — Uwat org (参建单位): sys_dept + att_org_base + att_org_uwat_ext - `OrgWsubCompositeService.java` — Wsub org (分包单位): sys_dept + att_org_base + att_org_wsub All operations are **@Transactional** — all succeed or all roll back. ### 6. Redundant Table Sync (ATT_* → OBJ_*) 13 pairs of main/redundant tables. On every INSERT/UPDATE/DELETE to a main ATT_* table, the corresponding `ObjSyncMapper` upserts the OBJ_* redundant table via `ON CONFLICT DO UPDATE`. | Main Table | Redundant Table | |-----------|-----------------| | ATT_ENG_BASE | OBJ_ENG | | ATT_ENG_RES | OBJ_RES | | ATT_ENG_WAGA | OBJ_WAGA | | ATT_ENG_PUST | OBJ_PUST | | ATT_ENG_HYST | OBJ_HYST | | ATT_ENG_DIKE | OBJ_DIKE | | ATT_ENG_IRR | OBJ_IRR | | ATT_ENG_WADI | OBJ_WADI | | ATT_ENG_SD | OBJ_SD | | ATT_ENG_CWS | OBJ_CWS | | ATT_ENG_OTHE | OBJ_OTHE | | ATT_PROJ_BASE | OBJ_PROJ | | ATT_AD_BASE | OBJ_AD | ### 7. Business Relationship Chain ``` 项目 (ATT_PROJ_BASE) → 工程 (ATT_ENG_BASE) → 标段 (OBJ_TEND) → 参建单位 ``` - **项目↔工程**: Through `REL_PROJ_ORG` table (`proj_guid` + `org_guid` + `from_date` + `to_date`) - `fromDate` is auto-set by `RelProjOrgServiceImpl.insertRelProjOrg()` - **工程↔标段**: `OBJ_TEND.eng_guid` → `ATT_ENG_BASE.guid` - **标段↔参建单位**: `REL_TEND_ORG` table ### 8. Frontend Page Templates — Standard Styles ALL new pages MUST follow one of the two patterns below. Reference implementations: | Pattern | Example File | |---------|-------------| | Standalone page | `gw-ui/src/views/slaj/woas/ObjWoas.vue` | | Tree-sidebar page | `gw-ui/src/views/system/orgext/index.vue` | #### 8a. Standalone Page Pattern (no sidebar) Wrapper: `