新增流水明细查询前后端实施计划
This commit is contained in:
@@ -0,0 +1,413 @@
|
||||
# Project Detail Transaction Query Backend Implementation Plan
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** Build the backend query, filter options, detail, and export endpoints for the project detail bank statement page using local `ccdi_bank_statement` data.
|
||||
|
||||
**Architecture:** Extend the existing `ccdi-project` module with a dedicated bank statement controller and service, while reusing the current `CcdiBankStatementMapper` plus XML dynamic SQL. Keep DTO/VO layering strict, compute direction and display amount in the query layer, and export through `ruoyi-common` `ExcelUtil` so the page and export share one query contract.
|
||||
|
||||
**Tech Stack:** Java 21, Spring Boot 3, MyBatis Plus, MyBatis XML, Mockito + JUnit 5, RuoYi `ExcelUtil`
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Scaffold DTO/VO contracts and the first failing service test
|
||||
|
||||
**Files:**
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiBankStatementQueryDTO.java`
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiBankStatementOptionVO.java`
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiBankStatementFilterOptionsVO.java`
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiBankStatementListVO.java`
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiBankStatementDetailVO.java`
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiBankStatementService.java`
|
||||
- Create: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java`
|
||||
|
||||
**Step 1: Write the failing test**
|
||||
|
||||
```java
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CcdiBankStatementServiceImplTest {
|
||||
|
||||
@InjectMocks
|
||||
private CcdiBankStatementServiceImpl service;
|
||||
|
||||
@Mock
|
||||
private CcdiBankStatementMapper bankStatementMapper;
|
||||
|
||||
@Test
|
||||
void getFilterOptions_shouldReturnProjectWideOptions() {
|
||||
CcdiBankStatementFilterOptionsVO options = new CcdiBankStatementFilterOptionsVO();
|
||||
options.setOurSubjectOptions(List.of(new CcdiBankStatementOptionVO("主体A", "主体A")));
|
||||
when(bankStatementMapper.selectFilterOptions(100L)).thenReturn(options);
|
||||
|
||||
CcdiBankStatementFilterOptionsVO result = service.getFilterOptions(100L);
|
||||
|
||||
assertEquals(1, result.getOurSubjectOptions().size());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `mvn test -pl ccdi-project -Dtest=CcdiBankStatementServiceImplTest`
|
||||
|
||||
Expected: FAIL with missing `CcdiBankStatementServiceImpl`, DTO, or mapper methods.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
```java
|
||||
public interface ICcdiBankStatementService {
|
||||
CcdiBankStatementFilterOptionsVO getFilterOptions(Long projectId);
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
@Data
|
||||
public class CcdiBankStatementOptionVO {
|
||||
private String label;
|
||||
private String value;
|
||||
|
||||
public CcdiBankStatementOptionVO(String label, String value) {
|
||||
this.label = label;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Add the remaining DTO/VO classes with only the fields already confirmed in the design.
|
||||
|
||||
**Step 4: Run test to verify it still fails only on the missing service implementation**
|
||||
|
||||
Run: `mvn test -pl ccdi-project -Dtest=CcdiBankStatementServiceImplTest`
|
||||
|
||||
Expected: FAIL with `CcdiBankStatementServiceImpl` not found or method not implemented.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiBankStatementQueryDTO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiBankStatementOptionVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiBankStatementFilterOptionsVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiBankStatementListVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiBankStatementDetailVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiBankStatementService.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java
|
||||
git commit -m "新增流水明细查询后端契约与测试骨架"
|
||||
```
|
||||
|
||||
### Task 2: Implement mapper query methods for options, list, detail, and export
|
||||
|
||||
**Files:**
|
||||
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapper.java`
|
||||
- Modify: `ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml`
|
||||
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java`
|
||||
|
||||
**Step 1: Write the failing test**
|
||||
|
||||
Add tests that assert the service delegates to mapper methods with normalized arguments:
|
||||
|
||||
```java
|
||||
@Test
|
||||
void pageQuery_shouldNormalizeSortFieldAndDirection() {
|
||||
Page<CcdiBankStatementListVO> page = new Page<>(1, 10);
|
||||
CcdiBankStatementQueryDTO queryDTO = new CcdiBankStatementQueryDTO();
|
||||
queryDTO.setProjectId(100L);
|
||||
queryDTO.setOrderBy("amount");
|
||||
queryDTO.setOrderDirection("desc");
|
||||
|
||||
service.selectStatementPage(page, queryDTO);
|
||||
|
||||
verify(bankStatementMapper).selectStatementPage(eq(page), same(queryDTO));
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `mvn test -pl ccdi-project -Dtest=CcdiBankStatementServiceImplTest`
|
||||
|
||||
Expected: FAIL because mapper methods `selectStatementPage`, `selectStatementListForExport`, `selectStatementDetailById`, `selectFilterOptions` are missing.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
In `CcdiBankStatementMapper.java`, add:
|
||||
|
||||
```java
|
||||
Page<CcdiBankStatementListVO> selectStatementPage(Page<CcdiBankStatementListVO> page,
|
||||
@Param("query") CcdiBankStatementQueryDTO query);
|
||||
|
||||
List<CcdiBankStatementListVO> selectStatementListForExport(@Param("query") CcdiBankStatementQueryDTO query);
|
||||
|
||||
CcdiBankStatementDetailVO selectStatementDetailById(@Param("bankStatementId") Long bankStatementId);
|
||||
|
||||
CcdiBankStatementFilterOptionsVO selectFilterOptions(@Param("projectId") Long projectId);
|
||||
```
|
||||
|
||||
In `CcdiBankStatementMapper.xml`, add:
|
||||
|
||||
- a reusable SQL fragment for common filters
|
||||
- a reusable expression for parsed transaction time
|
||||
- a reusable expression for signed display amount
|
||||
- separate selects for page, export, detail, and distinct project options
|
||||
|
||||
**Step 4: Run test to verify it passes or fails only on service logic**
|
||||
|
||||
Run: `mvn test -pl ccdi-project -Dtest=CcdiBankStatementServiceImplTest`
|
||||
|
||||
Expected: mapper-signature errors gone; remaining failures only relate to unimplemented service methods.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapper.java ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java
|
||||
git commit -m "补充流水明细查询Mapper与动态SQL"
|
||||
```
|
||||
|
||||
### Task 3: Implement service normalization, page query, and project-wide filter options
|
||||
|
||||
**Files:**
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImpl.java`
|
||||
- Modify: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java`
|
||||
|
||||
**Step 1: Write the failing test**
|
||||
|
||||
Add focused service tests for:
|
||||
|
||||
- default `tabType=all`
|
||||
- invalid `orderBy` falling back to `trxDate`
|
||||
- invalid `orderDirection` falling back to `desc`
|
||||
- blank string fields trimming to `null`
|
||||
|
||||
```java
|
||||
@Test
|
||||
void normalizeQuery_shouldFallbackToSafeDefaults() {
|
||||
CcdiBankStatementQueryDTO queryDTO = new CcdiBankStatementQueryDTO();
|
||||
queryDTO.setProjectId(100L);
|
||||
queryDTO.setOrderBy("drop table");
|
||||
queryDTO.setOrderDirection("sideways");
|
||||
|
||||
service.selectStatementPage(new Page<>(1, 10), queryDTO);
|
||||
|
||||
assertEquals("trxDate", queryDTO.getOrderBy());
|
||||
assertEquals("desc", queryDTO.getOrderDirection());
|
||||
assertEquals("all", queryDTO.getTabType());
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `mvn test -pl ccdi-project -Dtest=CcdiBankStatementServiceImplTest`
|
||||
|
||||
Expected: FAIL because service normalization logic is missing.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
In `CcdiBankStatementServiceImpl.java`:
|
||||
|
||||
```java
|
||||
@Service
|
||||
public class CcdiBankStatementServiceImpl implements ICcdiBankStatementService {
|
||||
|
||||
@Resource
|
||||
private CcdiBankStatementMapper bankStatementMapper;
|
||||
|
||||
@Override
|
||||
public Page<CcdiBankStatementListVO> selectStatementPage(Page<CcdiBankStatementListVO> page,
|
||||
CcdiBankStatementQueryDTO queryDTO) {
|
||||
normalizeQuery(queryDTO);
|
||||
return bankStatementMapper.selectStatementPage(page, queryDTO);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Implement `normalizeQuery(queryDTO)` to enforce the white-listed sort fields and normalize blank strings and booleans before delegating to mapper.
|
||||
|
||||
**Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `mvn test -pl ccdi-project -Dtest=CcdiBankStatementServiceImplTest`
|
||||
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImpl.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java
|
||||
git commit -m "实现流水明细查询服务层规范化逻辑"
|
||||
```
|
||||
|
||||
### Task 4: Add detail lookup and export model with a failing export test
|
||||
|
||||
**Files:**
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/excel/CcdiBankStatementExcel.java`
|
||||
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiBankStatementService.java`
|
||||
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImpl.java`
|
||||
- Modify: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java`
|
||||
|
||||
**Step 1: Write the failing test**
|
||||
|
||||
Add a service test for export mapping:
|
||||
|
||||
```java
|
||||
@Test
|
||||
void selectStatementListForExport_shouldMapDisplayColumns() {
|
||||
CcdiBankStatementListVO row = new CcdiBankStatementListVO();
|
||||
row.setTrxDate("2024-02-01 10:33:44");
|
||||
row.setLeAccountNo("6222");
|
||||
row.setLeAccountName("张三");
|
||||
row.setDisplayAmount(new BigDecimal("-8.00"));
|
||||
when(bankStatementMapper.selectStatementListForExport(any())).thenReturn(List.of(row));
|
||||
|
||||
List<CcdiBankStatementExcel> result = service.selectStatementListForExport(new CcdiBankStatementQueryDTO());
|
||||
|
||||
assertEquals(1, result.size());
|
||||
assertEquals("6222", result.get(0).getLeAccountNo());
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `mvn test -pl ccdi-project -Dtest=CcdiBankStatementServiceImplTest`
|
||||
|
||||
Expected: FAIL because export model and export service method do not exist.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Create `CcdiBankStatementExcel.java` with `@Excel` annotations for:
|
||||
|
||||
- `trxDate`
|
||||
- `leAccountNo`
|
||||
- `leAccountName`
|
||||
- `customerAccountName`
|
||||
- `customerAccountNo`
|
||||
- `userMemo`
|
||||
- `cashType`
|
||||
- `displayAmount`
|
||||
|
||||
Add service methods:
|
||||
|
||||
```java
|
||||
List<CcdiBankStatementExcel> selectStatementListForExport(CcdiBankStatementQueryDTO queryDTO);
|
||||
|
||||
CcdiBankStatementDetailVO getStatementDetail(Long bankStatementId);
|
||||
```
|
||||
|
||||
Map export rows from `CcdiBankStatementListVO` to `CcdiBankStatementExcel`.
|
||||
|
||||
**Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `mvn test -pl ccdi-project -Dtest=CcdiBankStatementServiceImplTest`
|
||||
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/excel/CcdiBankStatementExcel.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiBankStatementService.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImpl.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java
|
||||
git commit -m "实现流水明细导出模型与详情查询"
|
||||
```
|
||||
|
||||
### Task 5: Add controller endpoints and the first failing controller test
|
||||
|
||||
**Files:**
|
||||
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiBankStatementController.java`
|
||||
- Create: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiBankStatementControllerTest.java`
|
||||
|
||||
**Step 1: Write the failing test**
|
||||
|
||||
```java
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CcdiBankStatementControllerTest {
|
||||
|
||||
@InjectMocks
|
||||
private CcdiBankStatementController controller;
|
||||
|
||||
@Mock
|
||||
private ICcdiBankStatementService bankStatementService;
|
||||
|
||||
@Test
|
||||
void options_shouldReturnAjaxResultSuccess() {
|
||||
when(bankStatementService.getFilterOptions(100L)).thenReturn(new CcdiBankStatementFilterOptionsVO());
|
||||
|
||||
AjaxResult result = controller.getOptions(100L);
|
||||
|
||||
assertEquals(200, result.get("code"));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `mvn test -pl ccdi-project -Dtest=CcdiBankStatementControllerTest`
|
||||
|
||||
Expected: FAIL because controller class and methods do not exist.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Add endpoints:
|
||||
|
||||
- `GET /ccdi/project/bank-statement/list`
|
||||
- `GET /ccdi/project/bank-statement/options`
|
||||
- `GET /ccdi/project/bank-statement/detail/{bankStatementId}`
|
||||
- `POST /ccdi/project/bank-statement/export`
|
||||
|
||||
Use `TableSupport.buildPageRequest()` for paging and `ExcelUtil<CcdiBankStatementExcel>` for export:
|
||||
|
||||
```java
|
||||
ExcelUtil<CcdiBankStatementExcel> util = new ExcelUtil<>(CcdiBankStatementExcel.class);
|
||||
util.exportExcel(response, list, "流水明细");
|
||||
```
|
||||
|
||||
Guard permissions with:
|
||||
|
||||
- query/list/detail/options: `ccdi:project:query`
|
||||
- export: `ccdi:project:export`
|
||||
|
||||
**Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `mvn test -pl ccdi-project -Dtest=CcdiBankStatementControllerTest`
|
||||
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiBankStatementController.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiBankStatementControllerTest.java
|
||||
git commit -m "新增流水明细查询控制器接口"
|
||||
```
|
||||
|
||||
### Task 6: Verify the backend end-to-end inside the module
|
||||
|
||||
**Files:**
|
||||
- Modify if needed after failures: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiBankStatementController.java`
|
||||
- Modify if needed after failures: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImpl.java`
|
||||
- Modify if needed after failures: `ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml`
|
||||
|
||||
**Step 1: Run the focused backend tests**
|
||||
|
||||
Run: `mvn test -pl ccdi-project -Dtest=CcdiBankStatementServiceImplTest,CcdiBankStatementControllerTest`
|
||||
|
||||
Expected: PASS
|
||||
|
||||
**Step 2: Run the module compile**
|
||||
|
||||
Run: `mvn clean compile -pl ccdi-project -am`
|
||||
|
||||
Expected: BUILD SUCCESS
|
||||
|
||||
**Step 3: Smoke-check the mapper XML and endpoint contracts**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
mvn test -pl ccdi-project -Dtest=CcdiBankStatementServiceImplTest -q
|
||||
```
|
||||
|
||||
Expected: PASS without XML binding errors or missing mapper statements.
|
||||
|
||||
**Step 4: Fix any compile or binding failures with the smallest possible patch**
|
||||
|
||||
Typical fixes:
|
||||
|
||||
- wrong `@Param("query")` names
|
||||
- missing VO field aliases in SQL
|
||||
- `Page<>` generic mismatch
|
||||
- `ExcelUtil` export field annotation issues
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiBankStatementController.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImpl.java ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankStatementServiceImplTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiBankStatementControllerTest.java
|
||||
git commit -m "完成流水明细查询后端实现与校验"
|
||||
```
|
||||
@@ -0,0 +1,411 @@
|
||||
# Project Detail Transaction Query Frontend Implementation Plan
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** Replace the placeholder `DetailQuery.vue` with the full project detail bank statement query page and remove the obsolete upload-record jump entry.
|
||||
|
||||
**Architecture:** Keep the page inside the existing `ccdiProject/detail.vue` dynamic component system. Use one dedicated API module for list, options, detail, and export calls; preload project-wide select options on page entry; keep the entire interaction inside `DetailQuery.vue` plus a minimal cleanup in `UploadData.vue`.
|
||||
|
||||
**Tech Stack:** Vue 2.6, Element UI 2.15, Axios request wrapper, existing global `this.download`, `npm run build:prod` + manual smoke validation
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Replace the placeholder with a typed page shell and make the build fail first
|
||||
|
||||
**Files:**
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue`
|
||||
- Create: `ruoyi-ui/src/api/ccdiProjectBankStatement.js`
|
||||
|
||||
**Step 1: Write the failing verification**
|
||||
|
||||
In `DetailQuery.vue`, replace the placeholder text with the final top-level data structure and import the new API module before creating it:
|
||||
|
||||
```javascript
|
||||
import {
|
||||
listBankStatement,
|
||||
getBankStatementOptions,
|
||||
getBankStatementDetail
|
||||
} from "@/api/ccdiProjectBankStatement";
|
||||
```
|
||||
|
||||
Also add empty methods `getList`, `getOptions`, and `handleExport`.
|
||||
|
||||
**Step 2: Run build to verify it fails**
|
||||
|
||||
Run: `cd ruoyi-ui && npm run build:prod`
|
||||
|
||||
Expected: FAIL because `@/api/ccdiProjectBankStatement` does not exist yet.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Create `ruoyi-ui/src/api/ccdiProjectBankStatement.js` with:
|
||||
|
||||
```javascript
|
||||
import request from "@/utils/request";
|
||||
|
||||
export function listBankStatement(query) {
|
||||
return request({
|
||||
url: "/ccdi/project/bank-statement/list",
|
||||
method: "get",
|
||||
params: query
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Add stubs for:
|
||||
|
||||
- `getBankStatementOptions(projectId)`
|
||||
- `getBankStatementDetail(bankStatementId)`
|
||||
|
||||
Do not add export wrapper here; use `this.download` directly in the component.
|
||||
|
||||
**Step 4: Run build to verify it passes**
|
||||
|
||||
Run: `cd ruoyi-ui && npm run build:prod`
|
||||
|
||||
Expected: PASS or fail only on unfinished component template bindings.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue ruoyi-ui/src/api/ccdiProjectBankStatement.js
|
||||
git commit -m "搭建流水明细查询前端页面骨架"
|
||||
```
|
||||
|
||||
### Task 2: Implement page state, preload list and project-wide select options
|
||||
|
||||
**Files:**
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue`
|
||||
|
||||
**Step 1: Write the failing verification**
|
||||
|
||||
Add the real component state before wiring the template:
|
||||
|
||||
```javascript
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
optionsLoading: false,
|
||||
activeTab: "all",
|
||||
queryParams: {
|
||||
projectId: this.projectId,
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
tabType: "all",
|
||||
transactionStartTime: "",
|
||||
transactionEndTime: "",
|
||||
counterpartyName: "",
|
||||
counterpartyNameEmpty: false,
|
||||
userMemo: "",
|
||||
userMemoEmpty: false,
|
||||
ourSubjects: [],
|
||||
ourBanks: [],
|
||||
ourAccounts: [],
|
||||
amountMin: "",
|
||||
amountMax: "",
|
||||
counterpartyAccount: "",
|
||||
counterpartyAccountEmpty: false,
|
||||
transactionType: "",
|
||||
transactionTypeEmpty: false,
|
||||
orderBy: "trxDate",
|
||||
orderDirection: "desc"
|
||||
},
|
||||
optionData: {
|
||||
ourSubjectOptions: [],
|
||||
ourBankOptions: [],
|
||||
ourAccountOptions: []
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Call both `getList()` and `getOptions()` in `created()`.
|
||||
|
||||
**Step 2: Run build to verify it fails**
|
||||
|
||||
Run: `cd ruoyi-ui && npm run build:prod`
|
||||
|
||||
Expected: FAIL because the template has not been updated to use the new reactive state yet, or methods are incomplete.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Implement:
|
||||
|
||||
- `getList()`
|
||||
- `getOptions()`
|
||||
- `syncProjectId()`
|
||||
- `handleQuery()`
|
||||
- `resetQuery()`
|
||||
|
||||
Ensure `created()` and the `projectId` watcher both call:
|
||||
|
||||
```javascript
|
||||
this.queryParams.projectId = this.projectId;
|
||||
this.getOptions();
|
||||
this.getList();
|
||||
```
|
||||
|
||||
**Step 4: Run build to verify it passes**
|
||||
|
||||
Run: `cd ruoyi-ui && npm run build:prod`
|
||||
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue
|
||||
git commit -m "实现流水明细查询页面初始加载逻辑"
|
||||
```
|
||||
|
||||
### Task 3: Build the left filter panel and local-search multi-selects
|
||||
|
||||
**Files:**
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue`
|
||||
|
||||
**Step 1: Write the failing verification**
|
||||
|
||||
Replace the old placeholder template with the final left column filter markup using Element UI controls:
|
||||
|
||||
- `el-date-picker` for transaction time range
|
||||
- `el-input` + `el-checkbox` for counterparty name, summary, counterparty account, transaction type
|
||||
- `el-select multiple filterable collapse-tags` for subject, bank, account
|
||||
- amount range inputs
|
||||
|
||||
Do not wire the search/reset buttons yet.
|
||||
|
||||
**Step 2: Run build to verify it fails**
|
||||
|
||||
Run: `cd ruoyi-ui && npm run build:prod`
|
||||
|
||||
Expected: FAIL because methods or bound state used in the template are incomplete.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Wire the filter controls to `queryParams` and `dateRange`:
|
||||
|
||||
```javascript
|
||||
watch: {
|
||||
dateRange(value) {
|
||||
this.queryParams.transactionStartTime = value && value[0] ? value[0] : "";
|
||||
this.queryParams.transactionEndTime = value && value[1] ? value[1] : "";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Add the left action buttons:
|
||||
|
||||
- `查询`
|
||||
- `重置`
|
||||
|
||||
Add local filter support inside each `el-select` using Element UI `filterable`.
|
||||
|
||||
**Step 4: Run build to verify it passes**
|
||||
|
||||
Run: `cd ruoyi-ui && npm run build:prod`
|
||||
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue
|
||||
git commit -m "完成流水明细查询筛选栏布局"
|
||||
```
|
||||
|
||||
### Task 4: Build the right result area, tabs, table, pagination, and detail drawer
|
||||
|
||||
**Files:**
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue`
|
||||
|
||||
**Step 1: Write the failing verification**
|
||||
|
||||
Add the right-side structure:
|
||||
|
||||
- top tabs `全部 / 流入 / 流出`
|
||||
- export button
|
||||
- `el-table`
|
||||
- `pagination`
|
||||
- detail drawer or dialog
|
||||
|
||||
Reference the final columns:
|
||||
|
||||
- `trxDate`
|
||||
- `leAccountNo / leAccountName`
|
||||
- `customerAccountName / customerAccountNo`
|
||||
- `userMemo / cashType`
|
||||
- `displayAmount`
|
||||
- `详情`
|
||||
|
||||
**Step 2: Run build to verify it fails**
|
||||
|
||||
Run: `cd ruoyi-ui && npm run build:prod`
|
||||
|
||||
Expected: FAIL because event handlers like `handleTabChange`, `handleSortChange`, `handleViewDetail`, or `handlePageChange` are missing.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Implement:
|
||||
|
||||
- `handleTabChange(tab)`
|
||||
- `handleSortChange({ prop, order })`
|
||||
- `handlePageChange(pageNum)`
|
||||
- `handleViewDetail(row)`
|
||||
- `closeDetailDialog()`
|
||||
|
||||
Sort mapping:
|
||||
|
||||
```javascript
|
||||
const sortMap = {
|
||||
trxDate: "trxDate",
|
||||
displayAmount: "amount"
|
||||
};
|
||||
```
|
||||
|
||||
Tab mapping:
|
||||
|
||||
```javascript
|
||||
const tabMap = {
|
||||
all: "all",
|
||||
in: "in",
|
||||
out: "out"
|
||||
};
|
||||
```
|
||||
|
||||
**Step 4: Run build to verify it passes**
|
||||
|
||||
Run: `cd ruoyi-ui && npm run build:prod`
|
||||
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue
|
||||
git commit -m "完成流水明细查询结果区与详情展示"
|
||||
```
|
||||
|
||||
### Task 5: Wire export, empty/error states, and responsive styles
|
||||
|
||||
**Files:**
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue`
|
||||
|
||||
**Step 1: Write the failing verification**
|
||||
|
||||
Add the `导出流水` button click handler without implementation:
|
||||
|
||||
```javascript
|
||||
handleExport() {
|
||||
// TODO
|
||||
}
|
||||
```
|
||||
|
||||
Show the button in the UI but keep it clickable.
|
||||
|
||||
**Step 2: Run build to verify it fails functionally in manual smoke**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
npm run build:prod
|
||||
```
|
||||
|
||||
Expected: BUILD PASS, but manual smoke in browser should show export button with no behavior yet.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Implement export with the existing global helper:
|
||||
|
||||
```javascript
|
||||
this.download(
|
||||
"ccdi/project/bank-statement/export",
|
||||
{ ...this.queryParams },
|
||||
`${this.projectInfo.projectName || "项目"}_流水明细_${Date.now()}.xlsx`
|
||||
);
|
||||
```
|
||||
|
||||
Add:
|
||||
|
||||
- empty state when `list.length === 0`
|
||||
- inline error tip when list load fails
|
||||
- disabled export when total is `0`
|
||||
- responsive layout styles for mobile widths
|
||||
|
||||
**Step 4: Run build and manual smoke verification**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
npm run build:prod
|
||||
```
|
||||
|
||||
Expected: BUILD PASS
|
||||
|
||||
Manual smoke:
|
||||
|
||||
1. Open project detail page
|
||||
2. Switch to `流水明细查询`
|
||||
3. Confirm left filters render
|
||||
4. Confirm export button is disabled on empty data and enabled on non-empty data
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue
|
||||
git commit -m "补齐流水明细查询导出与状态反馈"
|
||||
```
|
||||
|
||||
### Task 6: Remove obsolete upload-page operation column and finish smoke verification
|
||||
|
||||
**Files:**
|
||||
- Modify: `ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue`
|
||||
- Modify if needed: `ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue`
|
||||
|
||||
**Step 1: Write the failing verification**
|
||||
|
||||
Delete only the old upload-table operation column usage in the template, but do not clean methods yet.
|
||||
|
||||
**Step 2: Run build to verify it fails**
|
||||
|
||||
Run: `cd ruoyi-ui && npm run build:prod`
|
||||
|
||||
Expected: FAIL because `handleViewFlow` or `handleViewError` remains unused or referenced.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
In `UploadData.vue`:
|
||||
|
||||
- remove the upload-record operation column entirely
|
||||
- remove methods:
|
||||
- `handleViewFlow`
|
||||
- `handleViewError`
|
||||
- remove any event payload that tried to change menu to `detail`
|
||||
|
||||
Keep upload, polling, and record-list refresh behavior unchanged.
|
||||
|
||||
**Step 4: Run final verification**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd ruoyi-ui
|
||||
npm run build:prod
|
||||
```
|
||||
|
||||
Expected: BUILD PASS
|
||||
|
||||
Manual smoke:
|
||||
|
||||
1. Open one project detail page
|
||||
2. Confirm `上传数据` 页不再出现“查看流水”入口
|
||||
3. Confirm `流水明细查询` 可独立查询、筛选、分页、导出
|
||||
4. Confirm手机宽度下左右布局能够折叠为上下布局
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue ruoyi-ui/src/views/ccdiProject/components/detail/DetailQuery.vue ruoyi-ui/src/api/ccdiProjectBankStatement.js
|
||||
git commit -m "完成流水明细查询前端实现并移除旧跳转入口"
|
||||
```
|
||||
Reference in New Issue
Block a user