package jnpf.onlinedev.controller;
|
|
import jnpf.base.ActionResult;
|
import jnpf.base.DataSourceApi;
|
import jnpf.base.entity.VisualAliasEntity;
|
import jnpf.base.entity.VisualdevEntity;
|
import jnpf.base.entity.VisualdevReleaseEntity;
|
import jnpf.base.model.FormDeleteResult;
|
import jnpf.base.model.VisualDevJsonModel;
|
import jnpf.base.model.export.VisualExportVo;
|
import jnpf.base.model.flow.DataModel;
|
import jnpf.base.model.flow.FlowFormDataModel;
|
import jnpf.base.model.flow.FlowStateModel;
|
import jnpf.base.model.online.VisualdevModelDataInfoVO;
|
import jnpf.base.service.FlowFormRelationService;
|
import jnpf.base.service.VisualAliasService;
|
import jnpf.base.service.VisualdevReleaseService;
|
import jnpf.base.service.VisualdevService;
|
import jnpf.base.util.FlowFormDataUtil;
|
import jnpf.base.util.FlowFormHttpReqUtils;
|
import jnpf.database.model.entity.DbLinkEntity;
|
import jnpf.onlinedev.VisualdevOnlineApi;
|
import jnpf.onlinedev.model.OnlineInfoModel;
|
import jnpf.onlinedev.model.VisualParamModel;
|
import jnpf.onlinedev.model.log.VisualLogForm;
|
import jnpf.onlinedev.service.VisualDevInfoService;
|
import jnpf.onlinedev.service.VisualDevListService;
|
import jnpf.onlinedev.service.VisualLogService;
|
import jnpf.onlinedev.service.VisualdevModelDataService;
|
import jnpf.onlinedev.util.FlowFormCustomUtils;
|
import jnpf.onlinedev.util.OnlinePublicUtils;
|
import jnpf.util.*;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.collections4.CollectionUtils;
|
import org.springframework.stereotype.Component;
|
import org.springframework.web.bind.annotation.*;
|
|
import java.util.ArrayList;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
@Slf4j
|
@RestController
|
@RequiredArgsConstructor
|
@RequestMapping("/VisualdevForFlow")
|
public class VisualdevForFlowController implements VisualdevOnlineApi {
|
|
private final VisualdevReleaseService visualdevReleaseService;
|
private final VisualDevListService visualDevListService;
|
private final VisualDevInfoService visualDevInfoService;
|
private final FlowFormHttpReqUtils flowFormHttpReqUtils;
|
private final FlowFormCustomUtils flowFormCustomUtils;
|
private final FlowFormDataUtil flowDataUtil;
|
private final DataSourceApi dblinkService;
|
private final FlowFormRelationService flowFormRelationService;
|
private final VisualdevModelDataService visualdevModelDataService;
|
private final VisualdevService visualdevService;
|
private final VisualAliasService aliasService;
|
// AUDIT 补丁(2026-08-05,登记 tasks/jnpf-platform-patches.md #7):
|
// 流程实例删除会连带删掉业务表单数据,平台原生此路径不发任何 VSLOG 事件。
|
private final VisualLogService visualLogService;
|
|
@Override
|
@PostMapping("/saveOrUpdate")
|
public ActionResult<Object> saveOrUpdate(@RequestBody FlowFormDataModel flowFormDataModel) {
|
DataModel dataModel = null;
|
try {
|
String id = flowFormDataModel.getId();
|
String formId = flowFormDataModel.getFormId();
|
String flowId = flowFormDataModel.getFlowId();
|
Map<String, Object> map = flowFormDataModel.getMap();
|
List<Map<String, Object>> formOperates = flowFormDataModel.getFormOperates();
|
VisualdevReleaseEntity entity = visualdevReleaseService.getById(formId);
|
VisualdevEntity visualdevEntity = JsonUtil.getJsonToBean(entity, VisualdevEntity.class);
|
|
map.put(FlowFormConstant.FLOWID, flowId);
|
if (map.get(TableFeildsEnum.VERSION.getField().toUpperCase()) != null) {//针对Oracle数据库大小写敏感,出现大写字段补充修复
|
map.put(TableFeildsEnum.VERSION.getField(), map.get(TableFeildsEnum.VERSION.getField().toUpperCase()));
|
}
|
|
//系统表单
|
if (entity.getType() == 2) {
|
map.put("formOperates", formOperates);
|
flowFormHttpReqUtils.saveOrUpdate(visualdevEntity, id, UserProvider.getToken(), map);
|
} else {
|
dataModel = flowFormCustomUtils.saveOrUpdate(visualdevEntity, flowFormDataModel);
|
}
|
} catch (Exception e) {
|
log.error(e.getMessage(), e);
|
return ActionResult.fail(e.getMessage());
|
}
|
return ActionResult.success(dataModel);
|
}
|
|
@Override
|
@DeleteMapping("/delete")
|
public boolean delete(@RequestParam("formId") String formId, @RequestParam("id") String id) {
|
try {
|
VisualdevReleaseEntity entity = visualdevReleaseService.getById(formId);
|
VisualdevEntity visualdevEntity = JsonUtil.getJsonToBean(entity, VisualdevEntity.class);
|
//系统表单
|
if (entity.getType() == 2) {
|
// 系统表单的数据不在本库(走 HTTP 打到外部系统),本地无快照可取,
|
// 也不该产出指向本库的审计事件——这条分支不发。
|
flowFormHttpReqUtils.delete(visualdevEntity, id, UserProvider.getToken());
|
} else {
|
VisualDevJsonModel visualJsonModel = OnlinePublicUtils.getVisualJsonModel(visualdevEntity);
|
DbLinkEntity linkEntity = StringUtil.isNotEmpty(visualdevEntity.getDbLinkId()) ? dblinkService.getInfo(visualdevEntity.getDbLinkId()) : null;
|
|
// ── AUDIT 补丁(2026-08-05,登记 tasks/jnpf-platform-patches.md #7)第 1/2 段 ──
|
// 触发链:用户在流程列表删除流程实例 → TaskServiceImpl.delete/deleteBatch
|
// → OperatorUtil.deleteFormData → ServiceUtil.deleteFormData
|
// → Feign visualdevApi.delete(formId, id) → 本方法。
|
// 🔴 顺序是硬约束:主键解析与快照都必须在 deleteTable **之前**——删完再查什么都没有。
|
// 入参 id 可能是 flowTaskId(deleteTable 按「主键 = id OR flowTaskId = id」定位),
|
// 而审计事件的 dataId 必须是业务主键,否则查询侧对不上记录。
|
Object auditMainId = null;
|
Map<String, Object> auditSnapshot = null;
|
try {
|
auditMainId = flowDataUtil.resolveMainId(id, visualJsonModel, linkEntity);
|
if (auditMainId != null) {
|
auditSnapshot = auditDeleteSnapshot(String.valueOf(auditMainId), visualdevEntity);
|
}
|
} catch (Throwable t) {
|
log.warn("[AUDIT] 流程删除取快照失败,本次删除不带内容快照。formId={}, id={}, error={}",
|
formId, id, t.getMessage());
|
auditMainId = null;
|
auditSnapshot = null;
|
}
|
// ── 第 1/2 段结束 ──────────────────────────────────────────────────────────
|
|
FormDeleteResult delResult = flowDataUtil.deleteTable(id, visualJsonModel, linkEntity);
|
|
// ── AUDIT 补丁 第 2/2 段 ───────────────────────────────────────────────────
|
// dataId 回落到 delResult.getMainId():上面解析失败但删除成功时,
|
// 「这次删过」这个事实不能缺——缺的只能是内容快照。
|
// 不设 batchOpId/batchSize:这是单条删除,审计侧 batchOpId 为空时回落到
|
// EVENT_ID_PREFIX + eventId,batchSize 为 null 时不缀「共 N 条」。
|
// 不设 bizSign:流程实例删除没有电子签名入口。
|
Object eventDataId = auditMainId != null ? auditMainId : (delResult == null ? null : delResult.getMainId());
|
if (delResult != null && delResult.isDeleted() && eventDataId != null) {
|
try {
|
visualLogService.createEventLog(VisualLogForm.builder()
|
.modelId(formId)
|
.dataId(String.valueOf(eventDataId))
|
.newData(auditSnapshot)
|
.type(2)
|
.build());
|
} catch (Throwable t) {
|
log.warn("[AUDIT] 流程删除事件发布失败,已跳过。formId={}, id={}, error={}",
|
formId, id, t.getMessage());
|
}
|
}
|
// ── AUDIT 补丁结束 ────────────────────────────────────────────────────────
|
}
|
} catch (Exception e) {
|
return false;
|
}
|
return true;
|
}
|
|
@Override
|
@GetMapping("/info")
|
public ActionResult<Object> info(@RequestParam("formId") String formId, @RequestParam("id") String id) {
|
ActionResult<Object> result = new ActionResult<>();
|
Map<String, Object> allDataMap = new HashMap<>();
|
VisualdevReleaseEntity entity = visualdevReleaseService.getById(formId);
|
VisualdevEntity visualdevEntity = JsonUtil.getJsonToBean(entity, VisualdevEntity.class);
|
result.setCode(visualdevEntity == null ? 400 : 200);
|
result.setMsg(visualdevEntity == null ? "表单信息不存在" : "");
|
if (visualdevEntity != null) {
|
//判断是否为系统表单
|
boolean b = visualdevEntity.getType() == 2;
|
if (b) {
|
allDataMap.putAll(flowFormHttpReqUtils.info(visualdevEntity, id, UserProvider.getToken()));
|
} else {
|
allDataMap.putAll(flowFormCustomUtils.info(visualdevEntity, id));
|
}
|
}
|
result.setData(allDataMap);
|
return result;
|
}
|
|
@Override
|
@GetMapping("/getFormConfig")
|
public VisualdevEntity getFormConfig(@RequestParam("formId") String formId) {
|
VisualdevReleaseEntity entity = visualdevReleaseService.getById(formId);
|
return JsonUtil.getJsonToBean(entity, VisualdevEntity.class);
|
}
|
|
@Override
|
@PostMapping("/getFormConfigList")
|
public List<VisualdevEntity> getFormConfigList(@RequestBody List<String> formIds) {
|
List<VisualdevReleaseEntity> list = visualdevReleaseService.selectByIds(formIds,
|
VisualdevReleaseEntity::getId,
|
VisualdevReleaseEntity::getEnCode,
|
VisualdevReleaseEntity::getFullName,
|
VisualdevReleaseEntity::getWebType,
|
VisualdevReleaseEntity::getType);
|
return CollectionUtils.isNotEmpty(list) ? JsonUtil.getJsonToList(list, VisualdevEntity.class) : new ArrayList<>();
|
}
|
|
@Override
|
@PostMapping("/saveFlowIdByFormIds")
|
public void saveFlowIdByFormIds(@RequestBody String flowId, @RequestParam("formId") List<String> formIds) {
|
flowFormRelationService.saveFlowIdByFormIds(flowId, formIds);
|
}
|
|
@Override
|
@GetMapping("/getReleaseInfo")
|
public VisualdevEntity getReleaseInfo(@RequestParam("formId") String formId) {
|
return visualdevService.getReleaseInfo(formId);
|
}
|
|
@Override
|
@PostMapping("/getListWithTableList")
|
public List<Map<String, Object>> getListWithTableList(@RequestBody VisualParamModel model) {
|
return visualDevListService.getListWithTableList(model.getVisualDevJsonModel(), model.getPagination(), model.getUserInfo());
|
}
|
|
@Override
|
@PostMapping("/getEditDataInfo")
|
public VisualdevModelDataInfoVO getEditDataInfo(@RequestBody VisualParamModel model) {
|
return visualDevInfoService.getEditDataInfo(model.getId(), model.getVisualdevEntity(), OnlineInfoModel.builder().build());
|
}
|
|
@Override
|
@PostMapping("/visualCreate")
|
public ActionResult<Object> visualCreate(@RequestBody VisualParamModel model) {
|
DataModel dataModel;
|
try {
|
dataModel = visualdevModelDataService.visualCreate(VisualParamModel.builder().visualdevEntity(model.getVisualdevEntity()).data(model.getData()).build());
|
} catch (Exception e) {
|
e.printStackTrace();
|
return ActionResult.fail(e.getMessage());
|
}
|
return ActionResult.success(dataModel);
|
}
|
|
@Override
|
@PostMapping("/visualUpdate")
|
public ActionResult<Object> visualUpdate(@RequestBody VisualParamModel model) {
|
DataModel dataModel;
|
try {
|
dataModel = visualdevModelDataService.visualUpdate(model);
|
} catch (Exception e) {
|
e.printStackTrace();
|
return ActionResult.fail(e.getMessage());
|
}
|
return ActionResult.success(dataModel);
|
}
|
|
@Override
|
@PostMapping("/visualDelete")
|
public ActionResult<Object> visualDelete(@RequestBody VisualParamModel model) {
|
try {
|
visualdevModelDataService.visualDelete(model.getVisualdevEntity(), model.getDataList());
|
} catch (Exception e) {
|
e.printStackTrace();
|
return ActionResult.fail(e.getMessage());
|
}
|
return ActionResult.success();
|
}
|
|
@Override
|
@PostMapping("/deleteByTableName")
|
public ActionResult<Object> deleteByTableName(@RequestBody FlowFormDataModel model) {
|
try {
|
visualdevModelDataService.deleteByTableName(model);
|
} catch (Exception e) {
|
e.printStackTrace();
|
return ActionResult.fail(e.getMessage());
|
}
|
return ActionResult.success();
|
}
|
|
@Override
|
@PostMapping("/saveState")
|
public void saveState(@RequestBody FlowStateModel model) {
|
List<String> formIds = model.getFormIds();
|
String flowTaskId = model.getFlowTaskId();
|
Integer flowState = model.getFlowState();
|
for (String formId : formIds) {
|
VisualdevReleaseEntity entity = visualdevReleaseService.getById(formId);
|
if (entity == null) continue;
|
VisualdevEntity visualdevEntity = JsonUtil.getJsonToBean(entity, VisualdevEntity.class);
|
//系统表单
|
if (entity.getType() == 2) {
|
flowFormHttpReqUtils.saveState(visualdevEntity, flowTaskId, flowState);
|
} else {
|
flowDataUtil.saveState(visualdevEntity, flowTaskId, flowState);
|
}
|
}
|
}
|
|
@Override
|
@GetMapping("/getExportList")
|
public List<VisualExportVo> getExportList(@RequestParam("systemId") String systemId) {
|
return visualdevService.getExportList(systemId);
|
}
|
|
@Override
|
@PostMapping("/importCopy")
|
public boolean importCopy(@RequestBody List<VisualExportVo> list, @RequestParam("systemId") String systemId) {
|
try {
|
for (VisualExportVo item : list) {
|
VisualdevEntity entity = JsonUtil.getJsonToBean(item, VisualdevEntity.class);
|
String id = RandomUtil.uuId();
|
entity.setId(id);
|
entity.setCreatorTime(DateUtil.getNowDate());
|
entity.setCreatorUserId(UserProvider.getUser().getUserId());
|
entity.setLastModifyTime(null);
|
entity.setLastModifyUserId(null);
|
entity.setState(0);
|
entity.setSystemId(systemId);
|
visualdevService.setAutoEnCode(entity);
|
visualdevService.save(entity);
|
if (StringUtil.isNotEmpty(item.getAliasListJson())) {
|
List<VisualAliasEntity> jsonToList = JsonUtil.getJsonToList(item.getAliasListJson(), VisualAliasEntity.class);
|
for (VisualAliasEntity aliasEntity : jsonToList) {
|
aliasService.copyEntity(aliasEntity, id);
|
}
|
}
|
}
|
return true;
|
} catch (Exception e) {
|
log.error(e.getMessage());
|
}
|
return false;
|
}
|
|
@Override
|
@GetMapping("/deleteBySystemId")
|
public void deleteBySystemId(@RequestParam("systemId") String systemId) {
|
visualdevService.deleteBySystemId(systemId);
|
}
|
|
/**
|
* AUDIT 补丁(2026-08-05,登记 tasks/jnpf-platform-patches.md #7):
|
* 取被删数据的快照,供审计层 0 渲染标题与留存 data_snapshot。
|
*
|
* <p>与 {@code VisualdevModelDataController.auditDeleteSnapshot} 同款参数
|
* (needRlationFiled=true, needSwap=false),保证两条删除路径产出的 newData 同构,
|
* 审计侧的渲染链路得以原样复用。
|
*
|
* <p>入参必须是**业务主键**(不是 flowTaskId)——调用方先经
|
* {@code flowDataUtil.resolveMainId} 解析。
|
*
|
* <p>取不到返回 null:事件照发(「这次删过」不能缺),只是没有快照可渲染。
|
*/
|
private Map<String, Object> auditDeleteSnapshot(String id, VisualdevEntity visualdevEntity) {
|
try {
|
VisualdevModelDataInfoVO info = visualDevInfoService.getEditDataInfo(id, visualdevEntity,
|
OnlineInfoModel.builder().needRlationFiled(true).needSwap(false).build());
|
return info == null ? null : JsonUtil.stringToMap(info.getData());
|
} catch (Throwable t) {
|
log.warn("[AUDIT] 取删除快照失败 id={}, error={}", id, t.getMessage());
|
return null;
|
}
|
}
|
|
}
|