feat(declare): 同一申报项目进行中只允许一条申报

- 新增 DeclareGuardService:按已通过/未处理驳回/待审核数判重,申报项目行加锁防连点
- 9 张申报表补 declare_id / declare_status / declare_remark,提交时写入并随审核结果回写
- 新增撤回、作废(强制放行)接口;挑战杯团队成员按手机号判重
- 申报项目支持配置允许重复提交与最多同时条数
- 迁移脚本 sql/20261102_add_declare_uniqueness.sql(含存量回填与重复清单)
This commit is contained in:
2026-11-02 19:28:56 +08:00
parent 76c9edd4be
commit 0e4986330a
28 changed files with 1089 additions and 15 deletions
@@ -0,0 +1,65 @@
package com.gxwebsoft.gxmu.mapper;
import com.gxwebsoft.gxmu.entity.Declare;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
import java.util.Map;
/**
* 申报记录跨模块查询(同一申报项目的重复申报限制)
*
* <p>table 只接受 {@link com.gxwebsoft.gxmu.service.DeclareGuardService} 白名单里的模块名,
* 调用方不得把用户输入直接传进来。</p>
*/
@Mapper
public interface DeclareRecordMapper {
/** 锁定申报项目行,串行化同一项目的并发提交 */
@Select("SELECT * FROM gxmu_declare WHERE id = #{id} AND deleted = 0 FOR UPDATE")
Declare lockDeclare(@Param("id") Integer id);
/** 某用户在某申报项目下、处于某状态的记录数 */
@Select("SELECT COUNT(*) FROM ${table} WHERE declare_id = #{declareId} AND user_id = #{userId} "
+ "AND declare_status = #{status} AND deleted = 0")
int countByStatus(@Param("table") String table,
@Param("declareId") Integer declareId,
@Param("userId") Integer userId,
@Param("status") Integer status);
/** 某用户在某申报项目下最近的一条记录 */
@Select("SELECT id AS id, declare_status AS declareStatus, create_time AS createTime, declare_remark AS declareRemark "
+ "FROM ${table} WHERE declare_id = #{declareId} AND user_id = #{userId} AND deleted = 0 "
+ "ORDER BY id DESC LIMIT 1")
Map<String, Object> selectLatestUserRecord(@Param("table") String table,
@Param("declareId") Integer declareId,
@Param("userId") Integer userId);
/** 某用户在某申报项目下的全部记录(申报项目列表回显本人状态用) */
@Select("SELECT id AS id, declare_id AS declareId, declare_status AS declareStatus, create_time AS createTime, "
+ "declare_remark AS declareRemark FROM ${table} WHERE user_id = #{userId} AND deleted = 0 ORDER BY id DESC")
List<Map<String, Object>> selectUserRecords(@Param("table") String table, @Param("userId") Integer userId);
/** 单条记录(撤回 / 作废时校验归属) */
@Select("SELECT id AS id, user_id AS userId, declare_id AS declareId, declare_status AS declareStatus "
+ "FROM ${table} WHERE id = #{id} AND deleted = 0")
Map<String, Object> selectRecord(@Param("table") String table, @Param("id") Integer id);
/** 同项目下其他有效申报的负责人手机号与团队成员,用于团队重复校验 */
@Select("SELECT id AS id, phone AS phone, team_members AS teamMembers FROM gxmu_tzbcy_form "
+ "WHERE declare_id = #{declareId} AND declare_status IN (1, 2, 3) AND deleted = 0 "
+ "AND id <> #{excludeId}")
List<Map<String, Object>> selectTzbcyTeamPhones(@Param("declareId") Integer declareId,
@Param("excludeId") Integer excludeId);
/** 更新申报记录状态(草稿 / 待审核 / 通过 / 驳回 / 作废) */
@Update("UPDATE ${table} SET declare_status = #{status}, declare_remark = #{remark}, update_time = NOW() "
+ "WHERE id = #{id} AND deleted = 0")
int updateStatus(@Param("table") String table,
@Param("id") Integer id,
@Param("status") Integer status,
@Param("remark") String remark);
}