Merge branch 'master' of gitee.com:sz_30/supervison-java into wsq-20260727

Signed-off-by: wsm <8454518+new-twice@user.noreply.gitee.com>
This commit is contained in:
wsm
2026-07-27 06:29:13 +00:00
committed by Gitee
33 changed files with 724 additions and 132 deletions
@@ -18,6 +18,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.excel.ExcelAnnotationUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.system.vo.SelectTreeModel;
import org.jeecg.modules.bg.constant.BpmStatus;
@@ -456,7 +457,9 @@ public class BgXiSpeakController extends JeecgController<BgXiSpeak, IBgXiSpeakSe
@RequiresPermissions("bg.xispeak:bg_xi_speak:exportXls")
@GetMapping(value = "/exportXlsHeaders")
public void exportXlsHeaders(HttpServletResponse response) throws IOException {
super.exportXlsHeadersByEasyExcel(response, BgXiSpeak.class, "习总书记重要讲话指示批示情况");
BgXiSpeak example = ExcelAnnotationUtils.buildExample(BgXiSpeak.class);
super.exportXlsWithData(response, BgXiSpeak.class, "习总书记重要讲话指示批示情况",
java.util.Collections.singletonList(example));
}
/**
@@ -10,6 +10,9 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.excel.ExcelAnnotationUtils;
import org.jeecg.modules.bg.constant.BpmStatus;
import org.jeecg.modules.bg.constant.SupervisionConstant;
import org.jeecg.modules.bg.xispeak.entity.BgXiSpeak;
import org.jeecg.modules.demo.dqinspecttask.entity.DqInspectTask;
import org.springframework.beans.factory.annotation.Autowired;
@@ -466,10 +469,11 @@ public class BgPartymatterController extends JeecgController<BgPartymatter, IBgP
return super.importExcelByEasyExcel(request, BgPartymatter.class,
Map.of(
BgPartymatterConstant.ClassFieldName.MEETING_TYPE_NAME, meetingType,
BgPartymatterConstant.ClassFieldName.DEL_FLAG_NAME,
BgPartymatterConstant.DelFlag.NORMAL));
BgPartymatterConstant.ClassFieldName.DEL_FLAG_NAME, BgPartymatterConstant.DelFlag.NORMAL,
SupervisionConstant.ClassFieldName.BPM_STATUS_NAME, BpmStatus.NOT_START.getCode()));
}
/**
* 通过EasyExcel导出数据,根据 meetingType 动态切换标题
*/
@@ -482,14 +486,15 @@ public class BgPartymatterController extends JeecgController<BgPartymatter, IBgP
}
/**
* 导出Excel表头(EasyExcel),通过 meetingType 参数指定模板类型
* 导出Excel模板(含表头和一行示例数据),通过 meetingType 参数指定模板类型
*/
@RequiresPermissions("bgpartymatter:bg_partymatter:exportXls")
@GetMapping(value = "/exportXlsHeaders")
public void exportXlsHeaders(HttpServletResponse response,
@RequestParam(defaultValue = "party") String meetingType) throws IOException {
String title = BgPartymatterConstant.MeetingType.OFFICE.equals(meetingType) ? "所务会" : "党委会";
super.exportXlsHeadersByEasyExcel(response, BgPartymatter.class, title);
BgPartymatter example = ExcelAnnotationUtils.buildExample(BgPartymatter.class);
super.exportXlsWithData(response, BgPartymatter.class, title, java.util.Collections.singletonList(example));
}
@@ -13,6 +13,9 @@ import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSONObject;
import org.flowable.engine.RuntimeService;
import org.jeecg.modules.bg.constant.BpmStatus;
import org.jeecg.modules.bg.constant.SupervisionConstant;
import org.jeecg.modules.bg.xispeak.entity.BgXiSpeak;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
@@ -24,6 +27,7 @@ import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.query.QueryRuleEnum;
import org.jeecg.common.util.excel.ExcelAnnotationUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.demo.bqtakepulse.dto.BgTakepulseBpmSaveDTO;
import org.jeecg.modules.demo.bqtakepulse.entity.BgTakepulseFeedback;
@@ -449,7 +453,12 @@ public class BgTakepulseController extends JeecgController<BgTakepulse, IBgTakep
@RequiresPermissions("bqtakepulse:bg_takepulse:importExcel")
@PostMapping(value = "/importExcelByEasyExcel")
public Result<?> importExcelByEasyExcel(HttpServletRequest request) {
return super.importExcelByEasyExcel(request, BgTakepulse.class);
return super.importExcelByEasyExcel(request, BgTakepulse.class,
Map.of(
SupervisionConstant.ClassFieldName.BPM_STATUS_NAME,
BpmStatus.NOT_START.getCode(),
SupervisionConstant.ClassFieldName.DEL_FLAG_NAME,
SupervisionConstant.DelFlag.NORMAL));
}
/**
@@ -468,7 +477,9 @@ public class BgTakepulseController extends JeecgController<BgTakepulse, IBgTakep
@RequiresPermissions("bqtakepulse:bg_takepulse:exportXls")
@GetMapping(value = "/exportXlsHeaders")
public void exportXlsHeaders(HttpServletResponse response) throws IOException {
super.exportXlsHeadersByEasyExcel(response, BgTakepulse.class, "我为四所把把脉");
BgTakepulse example = ExcelAnnotationUtils.buildExample(BgTakepulse.class);
super.exportXlsWithData(response, BgTakepulse.class, "我为四所把把脉",
java.util.Collections.singletonList(example));
}
}
@@ -23,6 +23,7 @@ import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.query.QueryRuleEnum;
import org.jeecg.common.util.excel.ExcelAnnotationUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.modules.demo.dqinspecttask.entity.DqInspectProgress;
@@ -354,7 +355,9 @@ public class DqInspectTaskController extends JeecgController<DqInspectTask, IDqI
@RequiresPermissions("dqinspecttask:dq_inspect_task:exportXls")
@GetMapping(value = "/exportXlsHeaders")
public void exportXlsHeaders(HttpServletResponse response) throws IOException {
super.exportXlsHeadersByEasyExcel(response, DqInspectTask.class, "dq_inspect_task");
DqInspectTask example = ExcelAnnotationUtils.buildExample(DqInspectTask.class);
super.exportXlsWithData(response, DqInspectTask.class, "dq_inspect_task",
java.util.Collections.singletonList(example));
}
}
@@ -13,6 +13,9 @@ import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.system.vo.SelectTreeModel;
import org.jeecg.modules.bg.constant.BpmStatus;
import org.jeecg.modules.bg.constant.SupervisionConstant;
import org.jeecg.modules.demo.bqtakepulse.entity.BgTakepulse;
import org.jeecg.modules.dj.inspectimprove.entity.DjInspectImprove;
import org.jeecg.modules.dj.inspectimprove.service.IDjInspectImproveService;
@@ -310,7 +313,12 @@ public class DjInspectImproveController extends JeecgController<DjInspectImprove
@RequiresPermissions("dj.inspectimprove:dj_inspect_improve:importExcel")
@RequestMapping(value = "/importExcelByEasyExcel", method = RequestMethod.POST)
public Result<?> importExcelByEasyExcel(HttpServletRequest request) {
return super.importExcelByEasyExcel(request, DjInspectImprove.class);
return super.importExcelByEasyExcel(request, DjInspectImprove.class,
Map.of(
SupervisionConstant.ClassFieldName.BPM_STATUS_NAME,
BpmStatus.NOT_START.getCode(),
SupervisionConstant.ClassFieldName.DEL_FLAG_NAME,
SupervisionConstant.DelFlag.NORMAL));
}
/**
@@ -102,7 +102,8 @@ public class ImprovementProposalController {
ImprovementProposal improvementProposal = new ImprovementProposal();
BeanUtils.copyProperties(improvementProposalPage, improvementProposal);
improvementProposal.setBpmStatus("1");
improvementProposalService.saveMain(improvementProposal, improvementProposalPage.getImprovementDeptScoreList(),improvementProposalPage.getImprovementInstituteVoteList());
// 新增申请阶段只创建主表,评分和投票子表由后续流程节点维护。
improvementProposalService.saveMain(improvementProposal, null, null);
return Result.OK("添加成功!");
}
@@ -117,14 +118,36 @@ public class ImprovementProposalController {
@RequiresPermissions("improvementproposal:improvement_proposal:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<String> edit(@RequestBody ImprovementProposalPage improvementProposalPage) {
ImprovementProposal improvementProposal = new ImprovementProposal();
BeanUtils.copyProperties(improvementProposalPage, improvementProposal);
ImprovementProposal improvementProposalEntity = improvementProposalService.getById(improvementProposal.getId());
if(improvementProposalEntity==null) {
return Result.error("未找到对应数据");
try {
ImprovementProposal improvementProposal = new ImprovementProposal();
BeanUtils.copyProperties(improvementProposalPage, improvementProposal);
improvementProposalService.updateMain(improvementProposal, improvementProposalPage.getImprovementDeptScoreList(),improvementProposalPage.getImprovementInstituteVoteList());
return Result.OK("编辑成功!");
} catch (IllegalStateException e) {
return Result.error(e.getMessage());
}
}
/**
* 使用改善提案主表作为流程业务数据发起审批,不复用督办任务表。
*/
@PostMapping(value = "/startProcess")
public Result<String> startProcess(@RequestBody(required = false) Map<String, String> requestBody,
@RequestParam(name = "id", required = false) String id) {
// defHttp 的 POST 参数默认在请求体中;同时兼容外部调用将 id 放在 URL 查询串的场景。
if (oConvertUtils.isEmpty(id) && requestBody != null) {
id = requestBody.get("id");
}
if (oConvertUtils.isEmpty(id)) {
return Result.error("提案ID不能为空");
}
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
try {
String processInstanceId = improvementProposalService.startProcess(id, sysUser.getUsername());
return Result.OK("流程发起成功!", processInstanceId);
} catch (IllegalStateException e) {
return Result.error(e.getMessage());
}
improvementProposalService.updateMain(improvementProposal, improvementProposalPage.getImprovementDeptScoreList(),improvementProposalPage.getImprovementInstituteVoteList());
return Result.OK("编辑成功!");
}
/**
@@ -138,8 +161,12 @@ public class ImprovementProposalController {
@RequiresPermissions("improvementproposal:improvement_proposal:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
improvementProposalService.delMain(id);
return Result.OK("删除成功!");
try {
improvementProposalService.delMain(id);
return Result.OK("删除成功!");
} catch (IllegalStateException e) {
return Result.error(e.getMessage());
}
}
/**
@@ -153,8 +180,12 @@ public class ImprovementProposalController {
@RequiresPermissions("improvementproposal:improvement_proposal:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.improvementProposalService.delBatchMain(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
try {
this.improvementProposalService.delBatchMain(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
} catch (IllegalStateException e) {
return Result.error(e.getMessage());
}
}
/**
@@ -278,7 +309,8 @@ public class ImprovementProposalController {
for (ImprovementProposalPage page : list) {
ImprovementProposal po = new ImprovementProposal();
BeanUtils.copyProperties(page, po);
improvementProposalService.saveMain(po, page.getImprovementDeptScoreList(),page.getImprovementInstituteVoteList());
// 导入新提案时同样只创建主表,不提前生成评分或投票数据。
improvementProposalService.saveMain(po, null, null);
}
return Result.OK("文件导入成功!数据行数:" + list.size());
} catch (Exception e) {
@@ -101,9 +101,13 @@ public class ImprovementProposal implements Serializable {
@Schema(description = "部门精益专员初步评定奖项")
private String initialAward;
/**是否需要部门评议打分:Y/N*/
@Excel(name = "是否需要部门评议打分:Y/N", width = 15)
@Schema(description = "是否需要部门评议打分:Y/N")
@Excel(name = "是否需要部门评议打分:1/0", width = 15)
@Schema(description = "是否需要部门评议打分:1/0")
private String needDeptScore;
/**是否需要部门评议打分:Y/N*/
@Excel(name = "是否需要所级评议小组投票:1/0", width = 15)
@Schema(description = "是否需要所级评议小组投票:1/0")
private String isneedvote;
/**部门评议平均分*/
@Excel(name = "部门评议平均分", width = 15)
@Schema(description = "部门评议平均分")
@@ -1,8 +1,7 @@
package org.jeecg.modules.improvementproposal.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.improvementproposal.entity.ImprovementProposal;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@@ -15,5 +14,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface ImprovementProposalMapper extends BaseMapper<ImprovementProposal> {
String selectLatestProposalNoByYear(@Param("year") Integer year);
/**
* 锁定提案主表,串行化流程发起、编辑和删除操作,避免同一提案生成多个流程实例。
*/
@Select("SELECT * FROM improvement_proposal WHERE id = #{id} AND del_flag = '0' FOR UPDATE")
ImprovementProposal selectByIdForUpdate(@Param("id") String id);
}
@@ -16,6 +16,15 @@ import java.util.List;
*/
public interface IImprovementProposalService extends IService<ImprovementProposal> {
/**
* 发起改善提案审批流程。
*
* @param id 提案主表 ID
* @param username 当前发起人账号
* @return 流程实例 ID
*/
String startProcess(String id, String username);
/**
* 添加一对多
*
@@ -7,6 +7,9 @@ import org.jeecg.modules.improvementproposal.mapper.ImprovementDeptScoreMapper;
import org.jeecg.modules.improvementproposal.mapper.ImprovementInstituteVoteMapper;
import org.jeecg.modules.improvementproposal.mapper.ImprovementProposalMapper;
import org.jeecg.modules.improvementproposal.service.IImprovementProposalService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.extbpm.process.service.impl.BpmBaseExtApiImpl;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
@@ -26,6 +29,9 @@ import java.util.regex.Pattern;
@Service
public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementProposalMapper, ImprovementProposal> implements IImprovementProposalService {
private static final String NORMAL_DEL_FLAG = "0";
private static final String BPM_STATUS_DRAFT = "1";
private static final String FLOW_CODE = "dev_improvement_proposal_001";
private static final String BPM_FORM_URL = "gh/improvementProposal/components/ImprovementProposalBPMForm";
@Autowired
private ImprovementProposalMapper improvementProposalMapper;
@@ -33,6 +39,34 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
private ImprovementDeptScoreMapper improvementDeptScoreMapper;
@Autowired
private ImprovementInstituteVoteMapper improvementInstituteVoteMapper;
@Autowired
private BpmBaseExtApiImpl bpmBaseExtApi;
@Override
@Transactional(rollbackFor = Exception.class)
public String startProcess(String id, String username) {
ImprovementProposal proposal = getDraftProposalForUpdate(id);
try {
// 改善提案以自身主表 ID 作为流程业务键,不引入 task_task 的重复督办中间表。
Result<String> result = bpmBaseExtApi.startMutilProcess(FLOW_CODE, proposal.getId(), BPM_FORM_URL, BPM_FORM_URL, username, null);
if (result == null || !result.isSuccess() || oConvertUtils.isEmpty(result.getResult())) {
throw new IllegalStateException(result == null || oConvertUtils.isEmpty(result.getMessage()) ? "发起流程失败" : result.getMessage());
}
// 流程引擎会按 BPM 配置将 bpm_status 回写为处理中;此处使用局部对象更新,避免旧实体的草稿状态将其覆盖。
ImprovementProposal processUpdate = new ImprovementProposal();
processUpdate.setId(proposal.getId());
processUpdate.setProcessInstanceId(result.getResult());
if (improvementProposalMapper.updateById(processUpdate) != 1) {
throw new IllegalStateException("流程已启动,但流程实例关联保存失败");
}
return result.getResult();
} catch (IllegalStateException e) {
throw e;
} catch (Exception e) {
throw new IllegalStateException("发起流程失败:" + e.getMessage(), e);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
@@ -67,6 +101,10 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
@Override
@Transactional(rollbackFor = Exception.class)
public void updateMain(ImprovementProposal improvementProposal,List<ImprovementDeptScore> improvementDeptScoreList,List<ImprovementInstituteVote> improvementInstituteVoteList) {
ImprovementProposal existingProposal = getDraftProposalForUpdate(improvementProposal.getId());
// 草稿编辑不能伪造流程状态或覆盖已关联的流程实例。
improvementProposal.setBpmStatus(existingProposal.getBpmStatus());
improvementProposal.setProcessInstanceId(existingProposal.getProcessInstanceId());
improvementProposalMapper.updateById(improvementProposal);
//1.先删除子表数据
@@ -99,6 +137,7 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
@Override
@Transactional(rollbackFor = Exception.class)
public void delMain(String id) {
getDraftProposalForUpdate(id);
improvementDeptScoreMapper.deleteByMainId(id);
improvementInstituteVoteMapper.deleteByMainId(id);
improvementProposalMapper.deleteById(id);
@@ -108,11 +147,30 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
@Transactional(rollbackFor = Exception.class)
public void delBatchMain(Collection<? extends Serializable> idList) {
for(Serializable id:idList) {
getDraftProposalForUpdate(id.toString());
improvementDeptScoreMapper.deleteByMainId(id.toString());
improvementInstituteVoteMapper.deleteByMainId(id.toString());
improvementProposalMapper.deleteById(id);
}
}
/**
* 任何会改变主表生命周期的操作都必须先锁定并确认仍是未发起草稿,
* 这样并发的“发起流程”和“编辑/删除”不会让流程与业务数据脱节。
*/
private ImprovementProposal getDraftProposalForUpdate(String id) {
if (oConvertUtils.isEmpty(id)) {
throw new IllegalStateException("提案ID不能为空");
}
ImprovementProposal proposal = improvementProposalMapper.selectByIdForUpdate(id);
if (proposal == null) {
throw new IllegalStateException("未找到对应提案");
}
if (!BPM_STATUS_DRAFT.equals(proposal.getBpmStatus()) || oConvertUtils.isNotEmpty(proposal.getProcessInstanceId())) {
throw new IllegalStateException("提案已进入流程,不能编辑、删除或重复发起");
}
return proposal;
}
@Override
public Integer getLatestProposalSequence(Integer year) {