# XQ-20260414-002 开发思路与改动

## 问题分析

### 问题1根因分析
查看 `TSTaskListMapper.xml` 的 `selectFinishUnionTaskPage` 查询：

```sql
SELECT DISTINCT ta.TASKLISTID, ta.WORKFLOWID, ...
FROM TSTaskList ta
LEFT JOIN TShwfProcessNode n ON ta.WorkflowID = n.processid
WHERE ta.BUSSTATUS = 2 
AND ta.WORKFLOWID IN (
    SELECT DISTINCT WORKFLOWID FROM tsopinion tso
    <where>
        <if test="customParamMap.childUnitSwitch != null and customParamMap.childUnitSwitch != ''">
            -- 有 childUnitSwitch 时的过滤逻辑
        </if>
        -- 注意：如果 childUnitSwitch 为空或不存在，整个 WHERE 块不生效
        -- 导致子查询返回 tsopinion 表中所有 WORKFLOWID
    </where>
)
```

**根本原因**：当 `childUnitSwitch` 参数不存在时，子查询没有任何过滤条件，返回 tsopinion 表中所有 WORKFLOWID，导致已办列表显示全自治区的记录。

### 问题2根因分析
查询结果中每条 TASKLIST 记录会对应 TShwfProcessNode 表中的多个节点记录（每个环节一个），而 DISTINCT 无法将同一业务的多条记录合并成一条。

---

## 解决方案

### 修复1: 已办列表按机构范围过滤

**修改文件**: `TaskController.java` (第280行附近 `finishTaskUnionPage` 方法)

**当前逻辑**：
```java
if (customParamMap != null && customParamMap.containsKey("childUnitSwitch")) {
    // 只有当 childUnitSwitch 存在时才设置机构过滤参数
}
```

**修改后逻辑**：
```java
// 获取当前用户机构信息
String myOrgNumber = StringUtils.clearRegionZero(curUser.getRegionID());
if (StringUtils.isNotBlank(myOrgNumber)) {
    customParamMap.put("myOrgNumber", myOrgNumber);
    customParamMap.put("myOrgNumberLike", myOrgNumber + "%");
    
    // 判断是否为自治区账号（机构等级为1）
    Map<String, String> orgParams = new HashMap<>();
    orgParams.put("deleted", "0");
    orgParams.put("unittype", "1");
    orgParams.put("orgNumber", myOrgNumber);
    OrgUnits org = aicorgService.queryByOrgNumberMap(orgParams);
    boolean isAutonomousRegion = org != null && org.getOrgLevel() != null && org.getOrgLevel() == 1;
    
    // 设置是否查看下级单位标志
    // childUnitSwitch = "1" 表示查看下级
    // childUnitSwitch 不传或为 "0" 表示不查看下级
    // 但自治区账号即使不查看下级，也应该能看到本级数据
    if (customParamMap.containsKey("childUnitSwitch")) {
        // 前端明确传了 childUnitSwitch，使用前端值
    } else {
        // 前端没传，默认不查看下级（childUnitSwitch = "0"）
        customParamMap.put("childUnitSwitch", "0");
    }
}
```

**同步修改 Mapper XML**: 确保当 `childUnitSwitch = "0"` 时，也要有机构过滤逻辑（不仅仅是 "1" 时）。

### 修复2: 每笔业务只显示一条记录

**方案**: 在外层查询使用 GROUP BY BIZSEQID，选择每个业务最新的一条记录。

**修改文件**: `TSTaskListMapper.xml` 的 `selectFinishUnionTaskPage`

**当前**:
```sql
SELECT * FROM (
    (select DISTINCT ta.TASKLISTID, ta.WORKFLOWID, ta.BIZSEQID, ...
     from TSTaskList ta
     LEFT JOIN TShwfProcessNode n on ta.WorkflowID = n.processid
     where ...)
) m
ORDER BY m.LAUPTIME DESC
```

**修改后**:
```sql
SELECT m.* FROM (
    SELECT * FROM (
        (select ... from TSTaskList ... UNION all select ... from tsrevtasklist ...)
    ) sub
    GROUP BY sub.BIZSEQID
    HAVING sub.LAUPTIME = MAX(sub.LAUPTIME)  -- 取每笔业务最新的一条
) m
ORDER BY m.LAUPTIME DESC
```

或者使用窗口函数：
```sql
SELECT * FROM (
    SELECT t.*, 
           ROW_NUMBER() OVER (PARTITION BY t.BIZSEQID ORDER BY t.LAUPTIME DESC) as rn
    FROM (
        (select ... from TSTaskList ta ... UNION all select ... from tsrevtasklist ...)
    ) t
) tt
WHERE tt.rn = 1
ORDER BY tt.LAUPTIME DESC
```

---

## 具体代码改动

### 1. TaskController.java 修改（约第290行）

在 `finishTaskUnionPage` 方法中，修改机构过滤逻辑：

```java
// 原有代码（只处理 childUnitSwitch 存在时）：
// if (customParamMap != null && customParamMap.containsKey("childUnitSwitch")) {

// 修改为：无条件设置机构参数
if (customParamMap != null) {
    String myOrgNumber = StringUtils.clearRegionZero(curUser.getRegionID());
    if (StringUtils.isNotBlank(myOrgNumber)) {
        customParamMap.put("myOrgNumber", myOrgNumber);
        customParamMap.put("myOrgNumberLike", myOrgNumber + "%");
    }
    
    // 确保 childUnitSwitch 有值（前端没传时默认为"0"）
    if (!customParamMap.containsKey("childUnitSwitch")) {
        customParamMap.put("childUnitSwitch", "0");
    }
}
```

### 2. TSTaskListMapper.xml 修改（约第580-790行）

**2.1 修改子查询逻辑**：

当 `childUnitSwitch = "0"`（不查看下级）时，也需要按机构过滤：

```xml
<when test='customParamMap.childUnitSwitch eq "0"'>
    and (
        tso.HANDLERID = #{customParamMap.userId}
        or exists(select 1 from CXAICORG.T_USERS tu 
                  left join CXAICORG.T_ORGUNITS torg on tu.ORGUNITID = torg.ORGUNITID
                  where tso.HANDLERID = tu.USERID 
                  and torg.ORGNUMBER = #{customParamMap.myOrgNumber})
    )
</when>
```

**2.2 添加自治区账号特殊处理**：

当机构等级为1（自治区）时，不过滤：

```xml
<when test='customParamMap.childUnitSwitch eq "0"'>
    <choose>
        <when test="customParamMap.isAutonomousRegion != null and customParamMap.isAutonomousRegion == true">
            <!-- 自治区账号，不过滤，返回所有 -->
        </when>
        <otherwise>
            and (
                tso.HANDLERID = #{customParamMap.userId}
                or exists(select 1 from CXAICORG.T_USERS tu 
                          left join CXAICORG.T_ORGUNITS torg on tu.ORGUNITID = torg.ORGUNITID
                          where tso.HANDLERID = tu.USERID 
                          and torg.ORGNUMBER = #{customParamMap.myOrgNumber})
            )
        </otherwise>
    </choose>
</when>
```

**2.3 去重逻辑**：

在外层包装查询结果，按 BIZSEQID 分组取最新：

```xml
SELECT * FROM (
    SELECT m.*, 
           ROW_NUMBER() OVER (PARTITION BY m.BIZSEQID ORDER BY m.LAUPTIME DESC) as rn
    FROM (
        <!-- 现有的 UNION ALL 查询 -->
    ) m
) mm
WHERE mm.rn = 1
ORDER BY mm.LAUPTIME DESC
```

---

## 注意事项

1. **自治区账号识别**：需要在 Controller 层判断并传递 `isAutonomousRegion` 参数
2. **兼容性**：确保修改后与现有功能兼容，不要破坏其他业务线的已办查询
3. **性能**：去重查询可能影响性能，如果 BIZSEQID 已建立索引应无大碍
4. **第3点难点**：如果去重逻辑 SQL 难以修改（涉及多表 UNION），可以在 Service 层用 Java 代码处理，但会增加内存压力
