2
0

8 کامیت‌ها 7249c4226d ... 8f87b33b46

نویسنده SHA1 پیام تاریخ
  yourname 8f87b33b46 📝 docs(stories): 更新移植残疾人管理UI故事文档 2 روز پیش
  yourname b9fc7a1a4c fix(api): 清理残留的fileUrl设置代码,更新验证逻辑说明 2 روز پیش
  yourname 3183975698 docs(story): 修正故事008.006中的验证逻辑说明 2 روز پیش
  yourname 20416269f9 docs(story): 更新故事008.006的API调用信息,添加银行卡、备注、回访信息数据结构 2 روز پیش
  yourname 6d8e2aefca docs(story): 更新故事008.006任务列表,添加银行卡、备注、回访信息组件任务 2 روز پیش
  yourname 5b7b44e166 🐛 fix(ui): 修复残疾人照片信息显示问题 2 روز پیش
  yourname 1994d9238d fix(api): 清理服务层fullUrl设置代码,使用parseWithAwait处理异步URL 2 روز پیش
  yourname e23fd7ade2 test(ui): 修复测试mock缺少聚合路由 2 روز پیش

+ 0 - 43
allin-packages/disability-module/src/services/aggregated.service.ts

@@ -148,21 +148,6 @@ export class AggregatedService {
       savedVisits = await this.visitRepository.save(visitsToSave);
     }
 
-    // 为照片获取文件URL
-    for (const photo of savedPhotos) {
-      if (photo.fileId) {
-        try {
-          const file = await this.fileRepository.findOne({ where: { id: photo.fileId } });
-          if (file) {
-            const url = await file.fullUrl;
-            (photo as any).fileUrl = url;
-          }
-        } catch (error) {
-          console.error('获取文件URL失败:', error);
-          (photo as any).fileUrl = null;
-        }
-      }
-    }
 
     // 返回创建的所有信息
     return {
@@ -193,20 +178,6 @@ export class AggregatedService {
       throw new Error('未找到该残疾人信息');
     }
 
-    // 为照片获取文件URL
-    if (person.photos) {
-      for (const photo of person.photos) {
-        if (photo.file) {
-          try {
-            const url = await photo.file.fullUrl;
-            (photo as any).fileUrl = url;
-          } catch (error) {
-            console.error('获取文件URL失败:', error);
-            (photo as any).fileUrl = null;
-          }
-        }
-      }
-    }
 
     return {
       personInfo: person,
@@ -310,20 +281,6 @@ export class AggregatedService {
       return null;
     }
 
-    // 为照片获取文件URL
-    for (const photo of updatedPerson.photos || []) {
-      if (photo.fileId) {
-        try {
-          const file = await this.fileRepository.findOne({ where: { id: photo.fileId } });
-          if (file) {
-            const url = await file.fullUrl;
-            (photo as any).fileUrl = url;
-          }
-        } catch (error) {
-          console.error('获取文件URL失败:', error);
-        }
-      }
-    }
 
     return {
       personInfo: updatedPerson,

+ 0 - 36
allin-packages/disability-module/src/services/disabled-person.service.ts

@@ -95,18 +95,6 @@ export class DisabledPersonService extends GenericCrudService<DisabledPerson> {
     });
 
     if (person && person.photos) {
-      // 为每个照片获取文件URL
-      for (const photo of person.photos) {
-        if (photo.file) {
-          try {
-            const url = await photo.file.fullUrl;
-            (photo as any).fileUrl = url;
-          } catch (error) {
-            console.error('获取文件URL失败:', error);
-            (photo as any).fileUrl = null;
-          }
-        }
-      }
     }
 
     return person;
@@ -174,18 +162,6 @@ export class DisabledPersonService extends GenericCrudService<DisabledPerson> {
         this.visitRepository.find({ where: { personId: In(personIds) } })
       ]);
 
-      // 为每个照片获取文件URL
-      for (const photo of photos) {
-        if (photo.file) {
-          try {
-            const url = await photo.file.fullUrl;
-            (photo as any).fileUrl = url;
-          } catch (error) {
-            console.error('获取文件URL失败:', error);
-            (photo as any).fileUrl = null;
-          }
-        }
-      }
 
       // 将关联数据分组到对应的残疾人
       const bankCardsMap = new Map<number, DisabledBankCard[]>();
@@ -239,18 +215,6 @@ export class DisabledPersonService extends GenericCrudService<DisabledPerson> {
     });
 
     if (person && person.photos) {
-      // 为每个照片获取文件URL
-      for (const photo of person.photos) {
-        if (photo.file) {
-          try {
-            const url = await photo.file.fullUrl;
-            (photo as any).fileUrl = url;
-          } catch (error) {
-            console.error('获取文件URL失败:', error);
-            (photo as any).fileUrl = null;
-          }
-        }
-      }
     }
 
     return person;

+ 2 - 2
allin-packages/disability-person-management-ui/src/components/DisabilityPersonManagement.tsx

@@ -975,8 +975,8 @@ const DisabilityPersonManagement: React.FC = () => {
                       id: photo.id,
                       photoType: photo.photoType,
                       fileId: photo.fileId,
-                      fileUrl: photo.fileUrl,
-                      fileName: `照片-${photo.photoType}`,
+                      fileUrl: photo.file?.fullUrl,
+                      fileName: photo.file?.name || `照片-${photo.photoType}`,
                       canDownload: photo.canDownload,
                       uploadTime: photo.uploadTime
                     }))}

+ 55 - 0
allin-packages/disability-person-management-ui/tests/integration/disability-person.integration.test.tsx

@@ -108,6 +108,61 @@ vi.mock('../../src/api/disabilityClient', () => {
         success: true
       }))),
     },
+    getAggregatedDisabledPerson: {
+      ':id': {
+        $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
+          personInfo: {
+            id: 1,
+            name: '张三',
+            gender: '男',
+            idCard: '110101199001011234',
+            disabilityId: 'D123456789',
+            disabilityType: '肢体残疾',
+            disabilityLevel: '一级',
+            idAddress: '北京市东城区',
+            phone: '13800138000',
+            province: '北京市',
+            city: '北京市',
+            district: '东城区',
+            detailedAddress: '某街道某号',
+            nation: '汉族',
+            isMarried: 0,
+            canDirectContact: 1,
+            isInBlackList: 0,
+            jobStatus: 1,
+            createTime: '2024-01-01T00:00:00Z',
+            updateTime: '2024-01-01T00:00:00Z'
+          },
+          bankCards: [],
+          photos: [
+            {
+              id: 1,
+              personId: 1,
+              photoType: '身份证照片',
+              fileId: 1,
+              uploadTime: '2024-01-01T10:30:00Z',
+              canDownload: 0,
+              file: {
+                id: 1,
+                name: '身份证照片.jpg',
+                type: 'image/jpeg',
+                size: 102400,
+                path: '/uploads/2024/01/id-photo.jpg',
+                fullUrl: 'https://minio.example.com/d8dai/uploads/2024/01/id-photo.jpg',
+                description: '身份证正面照片',
+                uploadUserId: 1,
+                uploadTime: '2024-01-01T10:30:00Z',
+                lastUpdated: null,
+                createdAt: '2024-01-01T10:30:00Z',
+                updatedAt: '2024-01-01T10:30:00Z'
+              }
+            }
+          ],
+          remarks: [],
+          visits: []
+        }))),
+      },
+    },
     searchDisabledPersons: {
       $get: vi.fn(() => Promise.resolve(createMockResponse(200, {
         data: [

+ 155 - 27
docs/stories/008.006.transplant-disability-person-management-ui.story.md

@@ -1,7 +1,7 @@
 # Story 008.006: 移植残疾人个人管理UI(disability_person → @d8d/allin-disability-person-management-ui)
 
 ## Status
-Ready for Review - 照片上传功能已完善
+In Progress - 需要实现银行卡、备注、回访信息组件
 
 ## Story
 **As a** 开发者,
@@ -128,8 +128,15 @@ Ready for Review - 照片上传功能已完善
   - [x] 创建备注管理组件:`src/components/RemarkManagement.tsx`
     - **目标文件**:`allin-packages/disability-person-management-ui/src/components/RemarkManagement.tsx`
     - **功能**:残疾人备注管理,支持添加、编辑、删除备注
+  - [ ] 创建银行卡管理组件:`src/components/BankCardManagement.tsx`
+    - **目标文件**:`allin-packages/disability-person-management-ui/src/components/BankCardManagement.tsx`
+    - **功能**:残疾人银行卡管理,支持添加、编辑、删除银行卡,支持默认银行卡设置
+    - **集成文件上传**:银行卡照片上传功能
+  - [ ] 创建回访信息管理组件:`src/components/VisitManagement.tsx`
+    - **目标文件**:`allin-packages/disability-person-management-ui/src/components/VisitManagement.tsx`
+    - **功能**:残疾人回访记录管理,支持添加、编辑、删除回访记录
   - [x] 创建多步骤表单状态管理:使用React状态管理多步骤表单流程
-    - **步骤**:基本信息 → 照片上传 → 区域选择 → 备注管理
+    - **步骤**:基本信息 → 照片上传 → 银行卡管理 → 区域选择 → 备注管理 → 回访管理
     - **状态管理**:使用React Context或useReducer管理多步骤状态
 
 - [x] 任务7:编写集成测试 (AC: 10)
@@ -148,6 +155,12 @@ Ready for Review - 照片上传功能已完善
   - [x] 实现枚举选择器集成测试:验证枚举选择功能
     - **测试场景**:枚举选择器组件集成,选项加载和选择
     - **验证点**:枚举值正确传递,表单验证正常工作
+  - [ ] 实现银行卡管理集成测试:验证银行卡管理功能
+    - **测试场景**:银行卡管理组件集成,银行卡添加、编辑、删除、默认银行卡设置
+    - **验证点**:银行卡照片上传功能,默认银行卡逻辑
+  - [ ] 实现回访信息集成测试:验证回访信息管理功能
+    - **测试场景**:回访信息管理组件集成,回访记录添加、编辑、删除
+    - **验证点**:回访日期、类型、内容等字段验证
   - [x] 实现表单验证测试:验证必填字段、身份证号唯一性等
     - **测试场景**:必填字段验证、身份证号格式验证、身份证号唯一性验证
     - **参考模式**:残疾人模块集成测试中的验证逻辑
@@ -155,14 +168,35 @@ Ready for Review - 照片上传功能已完善
     - **测试场景**:API错误、网络错误、表单验证错误
     - **参考模式**:平台管理集成测试中的错误处理
 
-- [x] 任务8:验证和测试 (AC: 11)
-  - [x] 运行`pnpm typecheck`确保无类型错误
-  - [x] 运行`pnpm test`确保所有集成测试通过
-  - [x] 验证文件上传组件集成正常工作
-  - [x] 验证区域选择器组件集成正常工作
-  - [x] 验证枚举选择器组件集成正常工作
-  - [x] 验证表单验证和错误处理功能
-  - [x] 验证组件导出和类型定义正确
+- [ ] 任务8:实现银行卡、备注、回访信息组件 (AC: 2, 3, 7, 8)
+  - [ ] 分析原系统银行卡管理功能:`allin_system-master/client/app/admin/dashboard/disability_person/AddDisabledPersonModal.tsx`
+    - **源文件**:`allin_system-master/client/app/admin/dashboard/disability_person/AddDisabledPersonModal.tsx`
+    - **查看要点**:银行卡管理UI、银行卡照片上传、默认银行卡设置
+  - [ ] 分析原系统回访信息管理功能:`allin_system-master/client/app/admin/dashboard/disability_person/AddDisabledPersonModal.tsx`
+    - **源文件**:`allin_system-master/client/app/admin/dashboard/disability_person/AddDisabledPersonModal.tsx`
+    - **查看要点**:回访记录管理UI、回访类型、回访内容、下次回访日期
+  - [ ] 创建银行卡管理组件:`src/components/BankCardManagement.tsx`
+    - **目标文件**:`allin-packages/disability-person-management-ui/src/components/BankCardManagement.tsx`
+    - **功能**:支持多个银行卡管理,每个银行卡包含银行名称、卡号、持卡人姓名、发卡支行、是否默认
+    - **文件上传**:集成FileSelector组件用于银行卡照片上传
+    - **默认银行卡逻辑**:只能有一个默认银行卡
+  - [ ] 创建回访信息管理组件:`src/components/VisitManagement.tsx`
+    - **目标文件**:`allin-packages/disability-person-management-ui/src/components/VisitManagement.tsx`
+    - **功能**:支持多个回访记录管理,每个回访包含回访日期、回访类型、回访内容、回访结果、下次回访日期
+  - [ ] 集成到主表单:在DisabilityPersonManagement.tsx中集成银行卡和回访信息管理
+    - **表单集成**:在创建/编辑表单中添加银行卡和回访信息管理标签页或折叠面板
+    - **数据传递**:通过聚合API传递银行卡和回访信息数据
+
+- [ ] 任务9:验证和测试 (AC: 10, 11)
+  - [ ] 运行`pnpm typecheck`确保无类型错误
+  - [ ] 运行`pnpm test`确保所有集成测试通过
+  - [ ] 验证文件上传组件集成正常工作
+  - [ ] 验证区域选择器组件集成正常工作
+  - [ ] 验证枚举选择器组件集成正常工作
+  - [ ] 验证银行卡管理组件集成正常工作
+  - [ ] 验证回访信息管理组件集成正常工作
+  - [ ] 验证表单验证和错误处理功能
+  - [ ] 验证组件导出和类型定义正确
 
 ## Dev Notes
 
@@ -287,10 +321,63 @@ Ready for Review - 照片上传功能已完善
   }
   ```
 
-- **照片验证逻辑**(来自`AggregatedService`):
-  - 验证`fileId`的有效性(检查文件是否存在)
-  - 照片必须包含有效的文件ID
-  - 自动为照片添加`fileUrl`字段(从文件模块获取)
+- **银行卡数据结构**(来自`DisabledBankCardSchema`):
+  ```typescript
+  {
+    id?: number;           // 银行卡ID(创建时可选)
+    personId?: number;     // 残疾人ID(创建时可选)
+    subBankName: string;   // 发卡支行
+    bankName: string;      // 银行名称
+    cardNumber: string;    // 卡号
+    cardholderName: string; // 持卡人姓名
+    fileId: number;        // **银行卡照片文件ID**(引用@d8d/file-module)
+    isDefault: number;     // 是否默认:1-是,0-否
+  }
+  ```
+
+- **备注数据结构**(来自`DisabledRemarkSchema`):
+  ```typescript
+  {
+    id?: number;           // 备注ID(创建时可选)
+    personId?: number;     // 残疾人ID(创建时可选)
+    remarkContent: string; // 备注内容
+    isSpecialNeeds: number; // 是否特殊需求:1-是,0-否
+    operatorId: number;    // 操作人ID
+    remarkTime?: Date;     // 备注时间(创建时自动生成)
+  }
+  ```
+
+- **回访数据结构**(来自`DisabledVisitSchema`):
+  ```typescript
+  {
+    id?: number;           // 回访ID(创建时可选)
+    personId?: number;     // 残疾人ID(创建时可选)
+    visitDate: Date;       // 回访日期
+    visitType: string;     // 回访类型
+    visitContent: string;  // 回访内容
+    visitResult?: string;  // 回访结果(可选)
+    nextVisitDate?: Date;  // 下次回访日期(可选)
+    visitorId: number;     // 回访人ID
+    visitTime?: Date;      // 记录时间(创建时自动生成)
+  }
+  ```
+
+- **数据验证逻辑**(来自`AggregatedService`):
+  - **照片验证**:
+    - 验证`fileId`的有效性(检查文件实体是否存在)
+    - 照片必须包含有效的文件ID
+    - **注意**:不再自动添加`fileUrl`字段,使用`parseWithAwait`处理异步的`fullUrl`
+  - **银行卡验证**:
+    - 验证银行卡照片`fileId`的有效性(检查文件实体是否存在)
+    - 确保只有一个默认银行卡(`isDefault: 1`)
+    - **注意**:Schema中只有银行卡号长度验证(`max(50)`),没有格式验证
+  - **备注验证**:
+    - 验证备注内容不能为空
+    - 自动设置`remarkTime`为当前时间
+  - **回访验证**:
+    - 验证回访日期不能晚于当前日期
+    - 验证回访内容不能为空
+    - 自动设置`visitTime`为当前时间
 
 - **照片上传流程**(新系统):
   1. 通过`FileSelector`上传到文件模块,获取`fileId`
@@ -299,19 +386,42 @@ Ready for Review - 照片上传功能已完善
   4. 响应中包含`fileUrl`(从文件模块获取)
 
 ### 残疾人模块RPC API调用信息(基于集成测试和路由定义)
-- **RPC客户端调用方式**(来自`allin-packages/disability-module/tests/integration/disability.integration.test.ts`和`allin-packages/disability-module/src/routes/disabled-person-custom.routes.ts`):
-  - `disabilityClientManager.get().createDisabledPerson.$post({ json: personData })` - 创建残疾人记录
-  - `disabilityClientManager.get().updateDisabledPerson.$post({ json: personData })` - 更新残疾人记录
-  - `disabilityClientManager.get().deleteDisabledPerson.$post({ json: { id } })` - 删除残疾人记录
-  - `disabilityClientManager.get().getDisabledPersonList.$get({ query: { page, pageSize, filters, sortBy, sortOrder } })` - 获取残疾人列表(分页)
-  - `disabilityClientManager.get().getDisabledPersonById.$get({ query: { id } })` - 获取残疾人详情
-
-- **API路径映射**(来自`allin-packages/disability-module/src/routes/disabled-person-custom.routes.ts`):
-  - `POST /createDisabledPerson` → `disabilityClientManager.get().createDisabledPerson.$post`
-  - `POST /updateDisabledPerson` → `disabilityClientManager.get().updateDisabledPerson.$post`
-  - `POST /deleteDisabledPerson` → `disabilityClientManager.get().deleteDisabledPerson.$post`
-  - `GET /getDisabledPersonList` → `disabilityClientManager.get().getDisabledPersonList.$get`
-  - `GET /getDisabledPersonById` → `disabilityClientManager.get().getDisabledPersonById.$get`
+- **RPC客户端调用方式**(来自`allin-packages/disability-module/tests/integration/disability.integration.test.ts`和路由定义):
+  - **基本CRUD API**:
+    - `disabilityClientManager.get().createDisabledPerson.$post({ json: personData })` - 创建残疾人记录(仅基本信息)
+    - `disabilityClientManager.get().updateDisabledPerson.$post({ json: personData })` - 更新残疾人记录(仅基本信息)
+    - `disabilityClientManager.get().deleteDisabledPerson.$post({ json: { id } })` - 删除残疾人记录
+    - `disabilityClientManager.get().getDisabledPersonList.$get({ query: { page, pageSize, filters, sortBy, sortOrder } })` - 获取残疾人列表(分页)
+    - `disabilityClientManager.get().getDisabledPersonById.$get({ query: { id } })` - 获取残疾人详情(仅基本信息)
+
+  - **聚合API**(包含银行卡、照片、备注、回访信息):
+    - `disabilityClientManager.get().createAggregatedDisabledPerson.$post({ json: aggregatedData })` - **聚合创建残疾人所有信息**
+    - `disabilityClientManager.get().getAggregatedDisabledPerson[':id']['$get']({ param: { id } })` - **聚合查询残疾人所有信息**
+    - `disabilityClientManager.get().updateAggregatedDisabledPerson[':id']['$put']({ json: aggregatedData, param: { id } })` - **聚合更新残疾人所有信息**
+
+- **API路径映射**:
+  - **基本CRUD API**(来自`disabled-person-custom.routes.ts`):
+    - `POST /createDisabledPerson` → `disabilityClientManager.get().createDisabledPerson.$post`
+    - `POST /updateDisabledPerson` → `disabilityClientManager.get().updateDisabledPerson.$post`
+    - `POST /deleteDisabledPerson` → `disabilityClientManager.get().deleteDisabledPerson.$post`
+    - `GET /getDisabledPersonList` → `disabilityClientManager.get().getDisabledPersonList.$get`
+    - `GET /getDisabledPersonById` → `disabilityClientManager.get().getDisabledPersonById.$get`
+
+  - **聚合API**(来自`aggregated.routes.ts`):
+    - `POST /createAggregatedDisabledPerson` → `disabilityClientManager.get().createAggregatedDisabledPerson.$post`
+    - `GET /getAggregatedDisabledPerson/{id}` → `disabilityClientManager.get().getAggregatedDisabledPerson[':id']['$get']`
+    - `PUT /updateAggregatedDisabledPerson/{id}` → `disabilityClientManager.get().updateAggregatedDisabledPerson[':id']['$put']`
+
+- **聚合数据结构**(`CreateAggregatedDisabledPersonSchema`):
+  ```typescript
+  {
+    personInfo: CreateDisabledPersonSchema,  // 残疾人基本信息
+    bankCards?: DisabledBankCardSchema[],    // 银行卡信息数组(可选)
+    photos?: DisabledPhotoSchema[],          // 照片信息数组(可选)
+    remarks?: DisabledRemarkSchema[],        // 备注信息数组(可选)
+    visits?: DisabledVisitSchema[]           // 回访信息数组(可选)
+  }
+  ```
 
 - **残疾人数据字段**(来自`allin-packages/disability-module/src/schemas/disabled-person.schema.ts`):
   - `name: string` - 姓名
@@ -418,6 +528,24 @@ Claude Code (d8d-model)
    - ✅ 集成聚合API,支持照片数据完整传输
    - ✅ 更新查看详情功能,显示照片预览
 
+9. **API支持检查完成**:
+   - ✅ 检查残疾人模块实体定义:已确认有银行卡、备注、回访信息实体
+   - ✅ 检查Schema定义:已确认有银行卡、备注、回访信息Schema
+   - ✅ 检查聚合API:已确认支持银行卡、备注、回访信息的创建、查询、更新
+   - ✅ 检查服务层实现:aggregated.service.ts已支持银行卡、备注、回访信息处理
+   - ✅ 检查RPC API定义:**没有独立的银行卡、备注、回访信息API**,所有相关数据通过聚合API处理
+   - ✅ 检查前端API客户端:已包含聚合API的类型定义(`CreateAggregatedDisabledPersonRequest`、`GetAggregatedDisabledPersonResponse`等)
+   - ✅ **API调用方式**:
+     - 创建:`disabilityClientManager.get().createAggregatedDisabledPerson.$post({ json: aggregatedData })`
+     - 查询:`disabilityClientManager.get().getAggregatedDisabledPerson[':id']['$get']({ param: { id } })`
+     - 更新:`disabilityClientManager.get().updateAggregatedDisabledPerson[':id']['$put']({ json: aggregatedData, param: { id } })`
+
+10. **待实现功能**:
+    - ⚠️ **银行卡管理组件**:需要创建`BankCardManagement.tsx`组件,支持多个银行卡管理、银行卡照片上传、默认银行卡设置
+    - ⚠️ **回访信息管理组件**:需要创建`VisitManagement.tsx`组件,支持多个回访记录管理
+    - ⚠️ **备注管理组件**:已在任务6中创建,但需要验证是否完整实现
+    - ⚠️ **主表单集成**:需要在DisabilityPersonManagement.tsx中集成银行卡、备注、回访信息管理功能
+
 ### File List
 **新创建的文件:**
 - `allin-packages/disability-person-management-ui/package.json` - 包配置文件