生成时间: 2026-08-02 · 数据来源: xnybw平台需求及工作计划.xlsx(南网在线绿能云缺陷跟踪表)· 仅针对 backup730/730backup 分支代码

① 基本信息

问题描述在项目提交有计划并网审核的情况下,项目不可以被删除,但是目前对有提交计划并网审核情况下对项目进行勾选可以进行删除,删除之后刷新页面,该项目实际上没有被删除,还能继续勾选删除;在项目有实际并网审核的情况下,项目不应该可以被删除,但是实际可以被删除
一级模块项目信息填报
二级模块/
涉及类型全部类型
所属区域五区
严重性严重
当前状态2.1.待开发
研发处理人杨智超
处理说明待调整

② 问题截图

生物质项目列表-删除测试项目仍在列表中
项目列表中"删除测试项目-1""删除测试项目-2"(计划并网流程分别为"已审核""待审核")仍在列表中可见、可操作
删除操作确认
删除操作及提示
刷新后项目仍在
刷新页面后项目仍然存在,可继续勾选删除

③ 旧代码涉及的项目文件及行数

xnybw5f / src/views/projectNew/projectNewList.vue 第 494-537 行 _deleteBatch(单条/批量删除共用此方法,第542-551行分别为 handleDelete/handleBatchDelete 的调用入口)
_deleteBatch(goalRow) {
  ...
  projectBaseApi.deleteBatchImpl(param).then(res => {
    this.tableLoading = false
    this.selectedData = []
    this.$message.info('删除成功')     // 无论后端 res 里返回的是"删除成功"还是"批量删除失败:xxx无法删除"的拦截文案,
                                         // 前端都不判断内容,一律提示"删除成功"并刷新列表
    this.getDataList(this.searchForm)
    this.$refs.listTable.tableClearSelection()
  }).catch((error) => { this.$message.error('调用接口出错:' + error) })
}
xnybw5b / src/main/java/cn/csg/so/oms/in/newenergy/project/appservice/ProjectImplAppService.java 第 1749-1841 行 deleteBatchImpl;第 1843-1868 行 validateProjectDelete;第 1891-1911 行拦截原因拼装
public String deleteBatchImpl(ProjectVo vo) throws Exception {
    ...
    String msg = validateProjectDelete(requestedImplIds, true);
    if (msg != "") { return msg; }   // 校验不通过时返回说明文字,HTTP状态码仍是200,前端未读取内容
    ...
}
// getDeleteBlockedReasons 中:
if (Integer.valueOf(1).equals(validation.getPlanGridBlocked())) {
    blockedReasons.add("计划并网容量信息处于审核中或已审核状态");
}
if (Integer.valueOf(1).equals(validation.getActualGridBlocked())) {   // 该字段永远是 null,见下方SQL
    blockedReasons.add("实际并网容量信息处于审核中或已审核状态");
}
if (Integer.valueOf(1).equals(validation.getMaterialBlocked())) {     // 该字段也永远是 null
    blockedReasons.add("并网资料信息处于审核中或已审核状态");
}
xnybw5b / src/main/resources/cn/csg/so/oms/in/energy/project/dbconfig/NePjImplSQL_mysql.xml 第 1273-1288 行 SoInNePjImplDO_selectDeleteValidation
<select id="SoInNePjImplDO_selectDeleteValidation" ... resultType="...ProjectDeleteValidationVO">
    SELECT impl.ID AS implId, impl.PLAN_NAME AS planName, ...,
    CASE WHEN EXISTS (
        SELECT 1 FROM so_in_flow plan_flow
        WHERE plan_flow.PLAN_ID = impl.PLAN_ID AND plan_flow.FLOWSTATUS IN (1, 2)
    ) THEN 1 ELSE 0 END AS planGridBlocked   -- 只查了"计划并网"一种流程状态,
                                                 -- resultType 对应的 VO 还定义了 actualGridBlocked / materialBlocked 两个字段,
                                                 -- 但SELECT列表里完全没有对应的CASE子句,MyBatis自动映射结果为null
    FROM SO_IN_NE_PJ_IMPL impl WHERE impl.ID IN (...)
</select>
两个独立根因、且互相印证:① 前端 _deleteBatch 无条件提示"删除成功"并刷新(projectNewList.vue:527),导致即便后端正确拦截了"计划并网审核中"的项目,用户也看不到拦截提示、只会看到项目"没删掉但也没报错";② 后端 SQL SoInNePjImplDO_selectDeleteValidation 漏写了 actualGridBlocked/materialBlocked 两列的计算,导致"实际并网审核中/并网资料审核中"的项目完全没有被拦截,真的会被删除掉。

④ 修复代码涉及的项目文件及行数

xnybw5b / .../dbconfig/NePjImplSQL_mysql.xml 第 1273-1288 行:补齐 actualGridBlocked / materialBlocked 两列的 CASE WHEN EXISTS 子查询
SELECT impl.ID AS implId, impl.PLAN_NAME AS planName, impl.DISPATCH_NAME AS dispatchName, impl.GRID_CAPACITY AS actualGridCapacity,
CASE WHEN EXISTS (SELECT 1 FROM so_in_flow plan_flow WHERE plan_flow.PLAN_ID = impl.PLAN_ID AND plan_flow.FLOWSTATUS IN (1, 2)) THEN 1 ELSE 0 END AS planGridBlocked,
+CASE WHEN EXISTS (SELECT 1 FROM so_in_flow actual_flow WHERE actual_flow.PLAN_ID = impl.PLAN_ID AND actual_flow.FLOW_TYPE = 'ACTUAL' AND actual_flow.FLOWSTATUS IN (1, 2)) THEN 1 ELSE 0 END AS actualGridBlocked,
+CASE WHEN EXISTS (SELECT 1 FROM so_in_flow material_flow WHERE material_flow.PLAN_ID = impl.PLAN_ID AND material_flow.FLOW_TYPE = 'MATERIAL' AND material_flow.FLOWSTATUS IN (1, 2)) THEN 1 ELSE 0 END AS materialBlocked
FROM SO_IN_NE_PJ_IMPL impl WHERE impl.ID IN (...)
注:实际并网/并网资料流程在 so_in_flow表中的区分字段名需以实际表结构为准(可能是 FLOW_TYPE,也可能是拆分到不同的流程表),此处示意的是补齐逻辑的思路,具体关联条件需要结合数据库实际字段核实。
xnybw5f / src/views/projectNew/projectNewList.vue 第 494-537 行 _deleteBatch:读取后端返回内容区分成功/拦截
projectBaseApi.deleteBatchImpl(param).then(res => {
  this.tableLoading = false
-  this.$message.info('删除成功')
+  if (res.data && res.data.indexOf('无法删除') !== -1) {
+    this.$message.warning(res.data)   // 展示后端真实的拦截原因,不再一律提示"删除成功"
+  } else {
+    this.$message.success('删除成功')
+  }
  this.selectedData = []
  this.getDataList(this.searchForm)
  this.$refs.listTable.tableClearSelection()
})

⑤ 修复方案

本条本质是两个独立缺陷叠加,需要分别修复:

  1. 后端漏拦截(安全/数据一致性问题,优先级更高)SoInNePjImplDO_selectDeleteValidation SQL 只计算了 planGridBlocked(计划并网审核中/已审核),完全没有计算 actualGridBlocked(实际并网)和 materialBlocked(并网资料)两项,导致 Java 侧 Integer.valueOf(1).equals(null) 恒为 false,这两类审核状态下的项目能被真正删除掉。需要补齐 SQL 的两个 CASE WHEN 子句。
  2. 前端误报"删除成功"(体验/误导问题)_deleteBatch 不管后端返回内容是什么都提示"删除成功",导致"计划并网审核中"项目本来已被后端正确拦截,用户却看到"删除成功"的假象,误以为系统有 bug、反复重试删除。需要读取后端返回文案,按"是否包含拦截关键字"区分成功/失败提示。
建议优先修复①(后端漏拦截),这是实际的数据完整性/业务规则问题;②属于前端提示准确性问题,两者互相独立,但共同导致了本条问题描述里"看起来什么都能删、删了又没删掉"的困惑现象。