diff --git a/.DS_Store b/.DS_Store index fcc8bf48..8eda584e 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/AGENTS.md b/AGENTS.md index b09dfae2..001dea93 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,8 +26,10 @@ - 前端实施计划放 `docs/plans/frontend/` - 前端开发直接在当前分支进行,不需要额外创建 git worktree - 测试结束后,自动关闭测试过程中启动的前后端进程 +- 重启后端时,必须优先使用 `bin/restart_java_backend.sh`,不要直接手工执行 `java -jar` 替代正式重启流程 - 遇到 MCP 数据库操作时,使用项目配置文件中的数据库连接信息 - 执行包含中文内容的 MySQL SQL 脚本或数据库导入时,禁止直接手写 `mysql -e` 或普通重定向执行;必须优先使用 `bin/mysql_utf8_exec.sh `,确保会话字符集为 `utf8mb4`,避免导入或写入乱码 +- 数据库字符集与排序规则统一要求:所有业务表、系统表新增或修改时,必须显式使用 `utf8mb4` 字符集与 `utf8mb4_general_ci` 排序规则;禁止引入 `utf8mb4_0900_ai_ci`、`utf8mb4_unicode_ci` 或其他混用排序规则 - 银行流水打标相关规则与参数编码需要统一使用全大写;新增或修改 `rule_code`、`indicator_code`、`param_code` 时,禁止混用大小写风格 --- @@ -165,6 +167,7 @@ return AjaxResult.success(result); - 前端表单不要暴露通用审计字段 - 新增菜单、字典、初始化数据时,同步补充 SQL 脚本 - 执行数据库脚本或导入数据库前,需确认客户端会话字符集为 `utf8mb4`;涉及中文插入、更新、导入时默认使用 `bin/mysql_utf8_exec.sh` +- 所有系统表和业务表的表级、字符字段级排序规则统一为 `utf8mb4_general_ci`;新增建表 SQL、字段追加 SQL、表结构修复 SQL 必须显式声明,避免因默认排序规则漂移导致联表或条件查询报错 ### 前端规范 diff --git a/bin/restart_java_backend.sh b/bin/restart_java_backend.sh index eebe6aeb..bc8f1ae3 100755 --- a/bin/restart_java_backend.sh +++ b/bin/restart_java_backend.sh @@ -83,7 +83,7 @@ collect_pids() { fi fi - marker_pids=$(pgrep -f "$APP_MARKER" 2>/dev/null || true) + marker_pids=$(pgrep -f -- "$APP_MARKER" 2>/dev/null || true) if [ -n "${marker_pids:-}" ]; then for pid in $marker_pids; do if is_managed_backend_pid "$pid"; then @@ -92,6 +92,15 @@ collect_pids() { done fi + port_pids=$(lsof -tiTCP:"$SERVER_PORT" -sTCP:LISTEN 2>/dev/null || true) + if [ -n "${port_pids:-}" ]; then + for pid in $port_pids; do + if is_managed_backend_pid "$pid"; then + all_pids="$all_pids $pid" + fi + done + fi + unique_pids="" for pid in $all_pids; do case " $unique_pids " in diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/controller/CcdiIntermediaryController.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/controller/CcdiIntermediaryController.java index 070ff06d..b1c5692f 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/controller/CcdiIntermediaryController.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/controller/CcdiIntermediaryController.java @@ -72,6 +72,26 @@ public class CcdiIntermediaryController extends BaseController { return success(vo); } + /** + * 查询中介亲属列表 + */ + @Operation(summary = "查询中介亲属列表") + @PreAuthorize("@ss.hasPermi('ccdi:intermediary:query')") + @GetMapping("/{bizId}/relatives") + public AjaxResult getRelativeList(@PathVariable String bizId) { + return success(intermediaryService.selectIntermediaryRelativeList(bizId)); + } + + /** + * 查询中介亲属详情 + */ + @Operation(summary = "查询中介亲属详情") + @PreAuthorize("@ss.hasPermi('ccdi:intermediary:query')") + @GetMapping("/relative/{relativeBizId}") + public AjaxResult getRelativeInfo(@PathVariable String relativeBizId) { + return success(intermediaryService.selectIntermediaryRelativeDetail(relativeBizId)); + } + /** * 查询实体中介详情 */ @@ -105,6 +125,28 @@ public class CcdiIntermediaryController extends BaseController { return toAjax(intermediaryService.updateIntermediaryPerson(editDTO)); } + /** + * 新增中介亲属 + */ + @Operation(summary = "新增中介亲属") + @PreAuthorize("@ss.hasPermi('ccdi:intermediary:add')") + @Log(title = "中介亲属", businessType = BusinessType.INSERT) + @PostMapping("/{bizId}/relative") + public AjaxResult addRelative(@PathVariable String bizId, @Validated @RequestBody CcdiIntermediaryRelativeAddDTO addDTO) { + return toAjax(intermediaryService.insertIntermediaryRelative(bizId, addDTO)); + } + + /** + * 修改中介亲属 + */ + @Operation(summary = "修改中介亲属") + @PreAuthorize("@ss.hasPermi('ccdi:intermediary:edit')") + @Log(title = "中介亲属", businessType = BusinessType.UPDATE) + @PutMapping("/relative") + public AjaxResult editRelative(@Validated @RequestBody CcdiIntermediaryRelativeEditDTO editDTO) { + return toAjax(intermediaryService.updateIntermediaryRelative(editDTO)); + } + /** * 新增实体中介 */ @@ -127,6 +169,49 @@ public class CcdiIntermediaryController extends BaseController { return toAjax(intermediaryService.updateIntermediaryEntity(editDTO)); } + /** + * 查询中介关联机构列表 + */ + @Operation(summary = "查询中介关联机构列表") + @PreAuthorize("@ss.hasPermi('ccdi:intermediary:query')") + @GetMapping("/{bizId}/enterprise-relations") + public AjaxResult getEnterpriseRelationList(@PathVariable String bizId) { + return success(intermediaryService.selectIntermediaryEnterpriseRelationList(bizId)); + } + + /** + * 查询中介关联机构详情 + */ + @Operation(summary = "查询中介关联机构详情") + @PreAuthorize("@ss.hasPermi('ccdi:intermediary:query')") + @GetMapping("/enterprise-relation/{id}") + public AjaxResult getEnterpriseRelationInfo(@PathVariable Long id) { + return success(intermediaryService.selectIntermediaryEnterpriseRelationDetail(id)); + } + + /** + * 新增中介关联机构 + */ + @Operation(summary = "新增中介关联机构") + @PreAuthorize("@ss.hasPermi('ccdi:intermediary:add')") + @Log(title = "中介关联机构", businessType = BusinessType.INSERT) + @PostMapping("/{bizId}/enterprise-relation") + public AjaxResult addEnterpriseRelation(@PathVariable String bizId, + @Validated @RequestBody CcdiIntermediaryEnterpriseRelationAddDTO addDTO) { + return toAjax(intermediaryService.insertIntermediaryEnterpriseRelation(bizId, addDTO)); + } + + /** + * 修改中介关联机构 + */ + @Operation(summary = "修改中介关联机构") + @PreAuthorize("@ss.hasPermi('ccdi:intermediary:edit')") + @Log(title = "中介关联机构", businessType = BusinessType.UPDATE) + @PutMapping("/enterprise-relation") + public AjaxResult editEnterpriseRelation(@Validated @RequestBody CcdiIntermediaryEnterpriseRelationEditDTO editDTO) { + return toAjax(intermediaryService.updateIntermediaryEnterpriseRelation(editDTO)); + } + /** * 删除中介 */ @@ -138,6 +223,28 @@ public class CcdiIntermediaryController extends BaseController { return toAjax(intermediaryService.deleteIntermediaryByIds(ids)); } + /** + * 删除中介亲属 + */ + @Operation(summary = "删除中介亲属") + @PreAuthorize("@ss.hasPermi('ccdi:intermediary:remove')") + @Log(title = "中介亲属", businessType = BusinessType.DELETE) + @DeleteMapping("/relative/{relativeBizId}") + public AjaxResult removeRelative(@PathVariable String relativeBizId) { + return toAjax(intermediaryService.deleteIntermediaryRelative(relativeBizId)); + } + + /** + * 删除中介关联机构 + */ + @Operation(summary = "删除中介关联机构") + @PreAuthorize("@ss.hasPermi('ccdi:intermediary:remove')") + @Log(title = "中介关联机构", businessType = BusinessType.DELETE) + @DeleteMapping("/enterprise-relation/{id}") + public AjaxResult removeEnterpriseRelation(@PathVariable Long id) { + return toAjax(intermediaryService.deleteIntermediaryEnterpriseRelation(id)); + } + /** * 校验人员ID唯一性 */ diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiIntermediaryQueryDTO.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiIntermediaryQueryDTO.java index abf26407..fbf1e889 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiIntermediaryQueryDTO.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/dto/CcdiIntermediaryQueryDTO.java @@ -19,12 +19,15 @@ public class CcdiIntermediaryQueryDTO implements Serializable { @Serial private static final long serialVersionUID = 1L; - @Schema(description = "姓名/机构名称") + @Schema(description = "名称") private String name; - @Schema(description = "证件号/统一社会信用代码") + @Schema(description = "证件号") private String certificateNo; - @Schema(description = "中介类型(1=个人, 2=实体)") - private String intermediaryType; + @Schema(description = "记录类型(INTERMEDIARY/RELATIVE/ENTERPRISE_RELATION)") + private String recordType; + + @Schema(description = "关联中介信息(姓名或证件号)") + private String relatedIntermediaryKeyword; } diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/CcdiIntermediaryVO.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/CcdiIntermediaryVO.java index a875cdea..2f6aae6d 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/CcdiIntermediaryVO.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/CcdiIntermediaryVO.java @@ -21,32 +21,25 @@ public class CcdiIntermediaryVO implements Serializable { @Serial private static final long serialVersionUID = 1L; - @Schema(description = "ID") - private String id; + @Schema(description = "记录类型") + private String recordType; - @Schema(description = "姓名/机构名称") + @Schema(description = "记录ID") + private String recordId; + + @Schema(description = "名称") private String name; - @Schema(description = "证件号/统一社会信用代码") + @Schema(description = "证件号") private String certificateNo; - @Schema(description = "中介类型(1=个人, 2=实体)") - private String intermediaryType; + @Schema(description = "关联中介姓名") + private String relatedIntermediaryName; - @Schema(description = "人员类型") - private String personType; - - @Schema(description = "公司") - private String company; - - @Schema(description = "数据来源") - private String dataSource; + @Schema(description = "关联关系") + private String relationText; @Schema(description = "创建时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; - - @Schema(description = "修改时间") - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private Date updateTime; } diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/ICcdiIntermediaryService.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/ICcdiIntermediaryService.java index 07eeb727..195633a0 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/ICcdiIntermediaryService.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/ICcdiIntermediaryService.java @@ -4,8 +4,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.info.collection.domain.dto.*; import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEntityExcel; import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryPersonExcel; +import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEnterpriseRelationVO; import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEntityDetailVO; import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryPersonDetailVO; +import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryRelativeVO; import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryVO; import java.util.List; @@ -35,6 +37,22 @@ public interface ICcdiIntermediaryService { */ CcdiIntermediaryPersonDetailVO selectIntermediaryPersonDetail(String bizId); + /** + * 查询中介亲属列表 + * + * @param bizId 中介本人ID + * @return 亲属列表 + */ + List selectIntermediaryRelativeList(String bizId); + + /** + * 查询中介亲属详情 + * + * @param relativeBizId 亲属ID + * @return 亲属详情 + */ + CcdiIntermediaryRelativeVO selectIntermediaryRelativeDetail(String relativeBizId); + /** * 查询实体中介详情 * @@ -59,6 +77,31 @@ public interface ICcdiIntermediaryService { */ int updateIntermediaryPerson(CcdiIntermediaryPersonEditDTO editDTO); + /** + * 新增中介亲属 + * + * @param bizId 中介本人ID + * @param addDTO 新增DTO + * @return 结果 + */ + int insertIntermediaryRelative(String bizId, CcdiIntermediaryRelativeAddDTO addDTO); + + /** + * 修改中介亲属 + * + * @param editDTO 编辑DTO + * @return 结果 + */ + int updateIntermediaryRelative(CcdiIntermediaryRelativeEditDTO editDTO); + + /** + * 删除中介亲属 + * + * @param relativeBizId 亲属ID + * @return 结果 + */ + int deleteIntermediaryRelative(String relativeBizId); + /** * 新增实体中介 * @@ -75,6 +118,47 @@ public interface ICcdiIntermediaryService { */ int updateIntermediaryEntity(CcdiIntermediaryEntityEditDTO editDTO); + /** + * 查询中介关联机构列表 + * + * @param bizId 中介本人ID + * @return 关联机构列表 + */ + List selectIntermediaryEnterpriseRelationList(String bizId); + + /** + * 查询中介关联机构详情 + * + * @param id 主键ID + * @return 关联机构详情 + */ + CcdiIntermediaryEnterpriseRelationVO selectIntermediaryEnterpriseRelationDetail(Long id); + + /** + * 新增中介关联机构 + * + * @param bizId 中介本人ID + * @param addDTO 新增DTO + * @return 结果 + */ + int insertIntermediaryEnterpriseRelation(String bizId, CcdiIntermediaryEnterpriseRelationAddDTO addDTO); + + /** + * 修改中介关联机构 + * + * @param editDTO 编辑DTO + * @return 结果 + */ + int updateIntermediaryEnterpriseRelation(CcdiIntermediaryEnterpriseRelationEditDTO editDTO); + + /** + * 删除中介关联机构 + * + * @param id 主键ID + * @return 结果 + */ + int deleteIntermediaryEnterpriseRelation(Long id); + /** * 批量删除中介 * diff --git a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiIntermediaryServiceImpl.java b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiIntermediaryServiceImpl.java index 8ae5dcf2..ddeb8a7d 100644 --- a/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiIntermediaryServiceImpl.java +++ b/ccdi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiIntermediaryServiceImpl.java @@ -4,14 +4,18 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.info.collection.domain.CcdiBizIntermediary; import com.ruoyi.info.collection.domain.CcdiEnterpriseBaseInfo; +import com.ruoyi.info.collection.domain.CcdiIntermediaryEnterpriseRelation; import com.ruoyi.info.collection.domain.dto.*; import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryEntityExcel; import com.ruoyi.info.collection.domain.excel.CcdiIntermediaryPersonExcel; +import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEnterpriseRelationVO; import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryEntityDetailVO; import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryPersonDetailVO; +import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryRelativeVO; import com.ruoyi.info.collection.domain.vo.CcdiIntermediaryVO; import com.ruoyi.info.collection.mapper.CcdiBizIntermediaryMapper; import com.ruoyi.info.collection.mapper.CcdiEnterpriseBaseInfoMapper; +import com.ruoyi.info.collection.mapper.CcdiIntermediaryEnterpriseRelationMapper; import com.ruoyi.info.collection.mapper.CcdiIntermediaryMapper; import com.ruoyi.info.collection.service.ICcdiIntermediaryEntityImportService; import com.ruoyi.info.collection.service.ICcdiIntermediaryPersonImportService; @@ -48,6 +52,9 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { @Resource private CcdiIntermediaryMapper intermediaryMapper; + @Resource + private CcdiIntermediaryEnterpriseRelationMapper enterpriseRelationMapper; + @Resource private ICcdiIntermediaryPersonImportService personImportService; @@ -81,7 +88,7 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { @Override public CcdiIntermediaryPersonDetailVO selectIntermediaryPersonDetail(String bizId) { CcdiBizIntermediary person = bizIntermediaryMapper.selectById(bizId); - if (person == null) { + if (person == null || !isIntermediaryPerson(person)) { return null; } @@ -92,6 +99,24 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { return vo; } + @Override + public List selectIntermediaryRelativeList(String bizId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(CcdiBizIntermediary::getRelatedNumId, bizId) + .ne(CcdiBizIntermediary::getPersonSubType, "本人") + .orderByDesc(CcdiBizIntermediary::getCreateTime); + return bizIntermediaryMapper.selectList(wrapper).stream().map(this::buildRelativeVo).toList(); + } + + @Override + public CcdiIntermediaryRelativeVO selectIntermediaryRelativeDetail(String relativeBizId) { + CcdiBizIntermediary relative = bizIntermediaryMapper.selectById(relativeBizId); + if (relative == null || isIntermediaryPerson(relative)) { + return null; + } + return buildRelativeVo(relative); + } + /** * 查询实体中介详情 * @@ -130,6 +155,8 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { CcdiBizIntermediary person = new CcdiBizIntermediary(); BeanUtils.copyProperties(addDTO, person); + person.setPersonSubType("本人"); + person.setRelatedNumId(null); person.setDataSource("MANUAL"); return bizIntermediaryMapper.insert(person); @@ -151,12 +178,64 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { } } + CcdiBizIntermediary existing = bizIntermediaryMapper.selectById(editDTO.getBizId()); + if (existing == null || !isIntermediaryPerson(existing)) { + throw new RuntimeException("中介本人不存在"); + } + CcdiBizIntermediary person = new CcdiBizIntermediary(); BeanUtils.copyProperties(editDTO, person); + person.setPersonSubType("本人"); + person.setRelatedNumId(null); return bizIntermediaryMapper.updateById(person); } + @Override + @Transactional + public int insertIntermediaryRelative(String bizId, CcdiIntermediaryRelativeAddDTO addDTO) { + CcdiBizIntermediary owner = requireIntermediaryPerson(bizId); + validateRelativePersonSubType(addDTO.getPersonSubType()); + if (!checkPersonIdUnique(addDTO.getPersonId(), null)) { + throw new RuntimeException("该证件号已存在"); + } + + CcdiBizIntermediary relative = new CcdiBizIntermediary(); + BeanUtils.copyProperties(addDTO, relative); + relative.setRelatedNumId(owner.getBizId()); + relative.setDataSource("MANUAL"); + return bizIntermediaryMapper.insert(relative); + } + + @Override + @Transactional + public int updateIntermediaryRelative(CcdiIntermediaryRelativeEditDTO editDTO) { + CcdiBizIntermediary existing = bizIntermediaryMapper.selectById(editDTO.getBizId()); + if (existing == null || isIntermediaryPerson(existing)) { + throw new RuntimeException("中介亲属不存在"); + } + validateRelativePersonSubType(editDTO.getPersonSubType()); + if (StringUtils.isNotEmpty(editDTO.getPersonId()) + && !checkPersonIdUnique(editDTO.getPersonId(), editDTO.getBizId())) { + throw new RuntimeException("该证件号已存在"); + } + + CcdiBizIntermediary relative = new CcdiBizIntermediary(); + BeanUtils.copyProperties(editDTO, relative); + relative.setRelatedNumId(existing.getRelatedNumId()); + return bizIntermediaryMapper.updateById(relative); + } + + @Override + @Transactional + public int deleteIntermediaryRelative(String relativeBizId) { + CcdiBizIntermediary existing = bizIntermediaryMapper.selectById(relativeBizId); + if (existing == null || isIntermediaryPerson(existing)) { + throw new RuntimeException("中介亲属不存在"); + } + return bizIntermediaryMapper.deleteById(relativeBizId); + } + /** * 新增实体中介 * @@ -197,6 +276,49 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { return enterpriseBaseInfoMapper.updateById(entity); } + @Override + public List selectIntermediaryEnterpriseRelationList(String bizId) { + return enterpriseRelationMapper.selectByIntermediaryBizId(bizId); + } + + @Override + public CcdiIntermediaryEnterpriseRelationVO selectIntermediaryEnterpriseRelationDetail(Long id) { + return enterpriseRelationMapper.selectDetailById(id); + } + + @Override + @Transactional + public int insertIntermediaryEnterpriseRelation(String bizId, CcdiIntermediaryEnterpriseRelationAddDTO addDTO) { + CcdiBizIntermediary owner = requireIntermediaryPerson(bizId); + validateEnterpriseRelation(owner.getBizId(), addDTO.getSocialCreditCode(), null); + + CcdiIntermediaryEnterpriseRelation relation = new CcdiIntermediaryEnterpriseRelation(); + BeanUtils.copyProperties(addDTO, relation); + relation.setIntermediaryBizId(owner.getBizId()); + return enterpriseRelationMapper.insert(relation); + } + + @Override + @Transactional + public int updateIntermediaryEnterpriseRelation(CcdiIntermediaryEnterpriseRelationEditDTO editDTO) { + CcdiIntermediaryEnterpriseRelation existing = enterpriseRelationMapper.selectById(editDTO.getId()); + if (existing == null) { + throw new RuntimeException("中介关联机构不存在"); + } + validateEnterpriseRelation(existing.getIntermediaryBizId(), editDTO.getSocialCreditCode(), existing.getId()); + + CcdiIntermediaryEnterpriseRelation relation = new CcdiIntermediaryEnterpriseRelation(); + BeanUtils.copyProperties(editDTO, relation); + relation.setIntermediaryBizId(existing.getIntermediaryBizId()); + return enterpriseRelationMapper.updateById(relation); + } + + @Override + @Transactional + public int deleteIntermediaryEnterpriseRelation(Long id) { + return enterpriseRelationMapper.deleteById(id); + } + /** * 批量删除中介 * @@ -208,12 +330,19 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { public int deleteIntermediaryByIds(String[] ids) { int count = 0; for (String id : ids) { - // 判断是个人还是实体(个人ID长度较长,实体统一社会信用代码18位) - if (id.length() > 18) { - // 个人中介 + CcdiBizIntermediary intermediary = bizIntermediaryMapper.selectById(id); + if (intermediary != null) { + if (isIntermediaryPerson(intermediary)) { + bizIntermediaryMapper.delete(new LambdaQueryWrapper() + .eq(CcdiBizIntermediary::getRelatedNumId, id)); + enterpriseRelationMapper.delete(new LambdaQueryWrapper() + .eq(CcdiIntermediaryEnterpriseRelation::getIntermediaryBizId, id)); + } count += bizIntermediaryMapper.deleteById(id); - } else { - // 实体中介 + continue; + } + + if (enterpriseBaseInfoMapper.selectById(id) != null) { count += enterpriseBaseInfoMapper.deleteById(id); } } @@ -325,4 +454,45 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { return taskId; } + + private boolean isIntermediaryPerson(CcdiBizIntermediary person) { + return "本人".equals(person.getPersonSubType()); + } + + private CcdiBizIntermediary requireIntermediaryPerson(String bizId) { + CcdiBizIntermediary owner = bizIntermediaryMapper.selectById(bizId); + if (owner == null || !isIntermediaryPerson(owner)) { + throw new RuntimeException("中介本人不存在"); + } + return owner; + } + + private void validateRelativePersonSubType(String personSubType) { + if ("本人".equals(personSubType)) { + throw new RuntimeException("亲属关系不能为本人"); + } + } + + private void validateEnterpriseRelation(String bizId, String socialCreditCode, Long excludeId) { + requireIntermediaryPerson(bizId); + if (enterpriseBaseInfoMapper.selectById(socialCreditCode) == null) { + throw new RuntimeException("关联机构不存在"); + } + boolean exists = enterpriseRelationMapper.existsByIntermediaryBizIdAndSocialCreditCode(bizId, socialCreditCode); + if (exists) { + if (excludeId == null) { + throw new RuntimeException("该中介已关联此机构"); + } + CcdiIntermediaryEnterpriseRelation existing = enterpriseRelationMapper.selectById(excludeId); + if (existing == null || !socialCreditCode.equals(existing.getSocialCreditCode())) { + throw new RuntimeException("该中介已关联此机构"); + } + } + } + + private CcdiIntermediaryRelativeVO buildRelativeVo(CcdiBizIntermediary relative) { + CcdiIntermediaryRelativeVO vo = new CcdiIntermediaryRelativeVO(); + BeanUtils.copyProperties(relative, vo); + return vo; + } } diff --git a/ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiIntermediaryMapper.xml b/ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiIntermediaryMapper.xml index 3601d0bd..3aa07391 100644 --- a/ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiIntermediaryMapper.xml +++ b/ccdi-info-collection/src/main/resources/mapper/info/collection/CcdiIntermediaryMapper.xml @@ -4,57 +4,86 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - + diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankTagServiceImpl.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankTagServiceImpl.java index 75d879b1..1665f81f 100644 --- a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankTagServiceImpl.java +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankTagServiceImpl.java @@ -39,6 +39,7 @@ public class CcdiBankTagServiceImpl implements ICcdiBankTagService { private static final String STATUS_RUNNING = "RUNNING"; private static final String STATUS_SUCCESS = "SUCCESS"; private static final String STATUS_FAILED = "FAILED"; + private static final String TASK_ERROR_MESSAGE_FALLBACK = "任务失败,详细异常请查看后端日志"; private static final String RESULT_TYPE_STATEMENT = "STATEMENT"; private static final String OBJECT_TYPE_STAFF_ID_CARD = "STAFF_ID_CARD"; @@ -147,12 +148,11 @@ public class CcdiBankTagServiceImpl implements ICcdiBankTagService { return task.getId(); } catch (Exception ex) { task.setStatus(STATUS_FAILED); - task.setErrorMessage(ex.getMessage()); task.setEndTime(new Date()); task.setNeedRerun(null); task.setUpdateBy(operator); task.setUpdateTime(new Date()); - taskMapper.updateTask(task); + updateFailedTaskSafely(task, ex); projectService.updateProjectStatus(projectId, CcdiProjectStatusConstants.PROCESSING, operator); log.error("【流水标签】任务执行失败: taskId={}, projectId={}, modelCode={}, triggerType={}, error={}", task.getId(), projectId, modelCode, triggerType, ex.getMessage(), ex); @@ -359,4 +359,44 @@ public class CcdiBankTagServiceImpl implements ICcdiBankTagService { } return Integer.parseInt(value); } + + private void updateFailedTaskSafely(CcdiBankTagTask task, Exception ex) { + task.setErrorMessage(buildSafeTaskErrorMessage(ex)); + try { + taskMapper.updateTask(task); + } catch (Exception updateEx) { + log.error("【流水标签】写入任务失败状态异常: taskId={}, error={}", + task.getId(), updateEx.getMessage(), updateEx); + task.setErrorMessage(TASK_ERROR_MESSAGE_FALLBACK); + taskMapper.updateTask(task); + } + } + + private static String buildSafeTaskErrorMessage(Throwable throwable) { + if (throwable == null) { + return TASK_ERROR_MESSAGE_FALLBACK; + } + + StringBuilder builder = new StringBuilder(); + if (throwable.getMessage() != null && !throwable.getMessage().isBlank()) { + builder.append(throwable.getMessage().trim()); + } + + Throwable rootCause = throwable; + while (rootCause.getCause() != null && rootCause.getCause() != rootCause) { + rootCause = rootCause.getCause(); + } + + if (rootCause != throwable && rootCause.getMessage() != null && !rootCause.getMessage().isBlank()) { + String rootMessage = rootCause.getMessage().trim(); + if (!builder.toString().contains(rootMessage)) { + if (!builder.isEmpty()) { + builder.append(" | rootCause="); + } + builder.append(rootMessage); + } + } + + return builder.isEmpty() ? TASK_ERROR_MESSAGE_FALLBACK : builder.toString(); + } } diff --git a/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankTagAnalysisMapper.xml b/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankTagAnalysisMapper.xml index 76a5a42d..4c0d8af8 100644 --- a/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankTagAnalysisMapper.xml +++ b/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankTagAnalysisMapper.xml @@ -924,7 +924,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" from ccdi_purchase_transaction pt inner join ( - ) project_staff on project_staff.staffId = pt.applicant_id + ) project_staff on project_staff.staffId COLLATE utf8mb4_general_ci = pt.applicant_id COLLATE utf8mb4_general_ci where IFNULL(pt.actual_amount, 0) > 100000 union select distinct @@ -935,7 +935,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" from ccdi_purchase_transaction pt inner join ( - ) project_staff on project_staff.staffId = pt.purchase_leader_id + ) project_staff on project_staff.staffId COLLATE utf8mb4_general_ci = pt.purchase_leader_id COLLATE utf8mb4_general_ci where pt.purchase_leader_id is not null and IFNULL(pt.actual_amount, 0) > 100000 ) t @@ -975,7 +975,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" from ccdi_purchase_transaction pt inner join ( - ) project_staff on project_staff.staffId = pt.applicant_id + ) project_staff on project_staff.staffId COLLATE utf8mb4_general_ci = pt.applicant_id COLLATE utf8mb4_general_ci where IFNULL(pt.actual_amount, 0) > 0 and IFNULL(pt.supplier_name, '') <> '' @@ -989,7 +989,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" from ccdi_purchase_transaction pt inner join ( - ) project_staff on project_staff.staffId = pt.purchase_leader_id + ) project_staff on project_staff.staffId COLLATE utf8mb4_general_ci = pt.purchase_leader_id COLLATE utf8mb4_general_ci where pt.purchase_leader_id is not null and IFNULL(pt.actual_amount, 0) > 0 and IFNULL(pt.supplier_name, '') <> '' @@ -1006,7 +1006,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" from ccdi_purchase_transaction pt inner join ( - ) project_staff on project_staff.staffId = pt.applicant_id + ) project_staff on project_staff.staffId COLLATE utf8mb4_general_ci = pt.applicant_id COLLATE utf8mb4_general_ci where IFNULL(pt.actual_amount, 0) > 0 union @@ -1018,7 +1018,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" from ccdi_purchase_transaction pt inner join ( - ) project_staff on project_staff.staffId = pt.purchase_leader_id + ) project_staff on project_staff.staffId COLLATE utf8mb4_general_ci = pt.purchase_leader_id COLLATE utf8mb4_general_ci where pt.purchase_leader_id is not null and IFNULL(pt.actual_amount, 0) > 0 ) source_total diff --git a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiBankTagAnalysisMapperXmlTest.java b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiBankTagAnalysisMapperXmlTest.java index 745c1372..d92fecd5 100644 --- a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiBankTagAnalysisMapperXmlTest.java +++ b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiBankTagAnalysisMapperXmlTest.java @@ -148,6 +148,34 @@ class CcdiBankTagAnalysisMapperXmlTest { ); } + @Test + void largePurchaseTransactionRule_shouldAlignCollationForJoinFields() throws Exception { + String xml = readXml(RESOURCE); + String purchaseSelectSql = extractSelectSql(xml, "selectLargePurchaseTransactionStatements"); + String supplierSelectSql = extractSelectSql(xml, "selectSupplierConcentrationObjects"); + + assertTrue( + purchaseSelectSql.contains("project_staff.staffId COLLATE utf8mb4_general_ci = pt.applicant_id COLLATE utf8mb4_general_ci") + ); + assertTrue( + purchaseSelectSql.contains("project_staff.staffId COLLATE utf8mb4_general_ci = pt.purchase_leader_id COLLATE utf8mb4_general_ci") + ); + assertTrue( + supplierSelectSql.contains("project_staff.staffId COLLATE utf8mb4_general_ci = pt.applicant_id COLLATE utf8mb4_general_ci") + ); + assertTrue( + supplierSelectSql.contains("project_staff.staffId COLLATE utf8mb4_general_ci = pt.purchase_leader_id COLLATE utf8mb4_general_ci") + ); + assertTrue( + !xml.contains("project_staff.staffId = pt.applicant_id"), + "采购交易相关 join 不应再使用未声明 COLLATE 的 applicant_id 比较" + ); + assertTrue( + !xml.contains("project_staff.staffId = pt.purchase_leader_id"), + "采购交易相关 join 不应再使用未声明 COLLATE 的 purchase_leader_id 比较" + ); + } + @Test void assetRegistrationMismatchRules_shouldUseRealSqlAndAssetTable() throws Exception { String xml = readXml(RESOURCE); diff --git a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankTagServiceImplTest.java b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankTagServiceImplTest.java index eeb201a0..0ecf92f8 100644 --- a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankTagServiceImplTest.java +++ b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankTagServiceImplTest.java @@ -28,9 +28,11 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Executor; import java.math.BigDecimal; +import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -494,6 +496,23 @@ class CcdiBankTagServiceImplTest { ))); } + @Test + void buildSafeTaskErrorMessage_shouldKeepLongMessageForLongTextColumn() throws Exception { + Method method = CcdiBankTagServiceImpl.class.getDeclaredMethod( + "buildSafeTaskErrorMessage", Throwable.class + ); + method.setAccessible(true); + + String longMessage = "X".repeat(5000); + RuntimeException throwable = new RuntimeException("root-cause:" + longMessage); + + String result = (String) method.invoke(null, throwable); + + assertNotNull(result); + assertTrue(result.length() > 2000, "LONGTEXT 方案下不应继续把错误信息截断到 2000"); + assertTrue(result.contains("root-cause"), "错误信息应保留根因关键字"); + } + @Test void abnormalAccountMapperXml_shouldDeclareObjectSelects() throws Exception { String xml = Files.readString(Path.of("src/main/resources/mapper/ccdi/project/CcdiBankTagAnalysisMapper.xml")); diff --git a/docs/plans/backend/2026-04-17-intermediary-library-refactor-backend-implementation.md b/docs/plans/backend/2026-04-17-intermediary-library-refactor-backend-implementation.md index f2ecfccb..613db21d 100644 --- a/docs/plans/backend/2026-04-17-intermediary-library-refactor-backend-implementation.md +++ b/docs/plans/backend/2026-04-17-intermediary-library-refactor-backend-implementation.md @@ -115,7 +115,7 @@ CREATE TABLE IF NOT EXISTS `ccdi_intermediary_enterprise_relation` ( UNIQUE KEY `uk_intermediary_enterprise` (`intermediary_biz_id`, `social_credit_code`), KEY `idx_intermediary_biz_id` (`intermediary_biz_id`), KEY `idx_social_credit_code` (`social_credit_code`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='中介关联机构关系表'; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='中介关联机构关系表'; ``` - [ ] **Step 3: 编写 `person_sub_type` 固定值脚本** @@ -529,6 +529,20 @@ mvn -pl ccdi-info-collection -am -DskipTests compile bin/mysql_utf8_exec.sh sql/migration/2026-04-17-create-intermediary-enterprise-relation.sql ``` +## 执行结果 + +- 实际测试命令:`mvn -pl ccdi-info-collection -am -Dsurefire.failIfNoSpecifiedTests=false -Dtest=CcdiIntermediaryServiceImplTest,CcdiIntermediaryMapperTest,CcdiIntermediaryControllerTest test` +- 测试结果:`BUILD SUCCESS`,共执行 8 个测试,`Failures: 0, Errors: 0, Skipped: 0` +- 实际编译命令:`mvn -pl ccdi-info-collection -am -DskipTests compile` +- 编译结果:`BUILD SUCCESS` +- 实际数据库变更命令:`bin/mysql_utf8_exec.sh sql/migration/2026-04-17-create-intermediary-enterprise-relation.sql` +- 数据库变更结果:`ccdi_intermediary_enterprise_relation` 已创建成功 +- 实际全库排序规则修复命令:`bin/mysql_utf8_exec.sh sql/migration/2026-04-17-unify-all-table-collation-to-utf8mb4-general-ci.sql` +- 排序规则修复结果:业务表、系统表的表级与字符字段级排序规则已统一为 `utf8mb4_general_ci` +- 实际运行验证: + - 重新打包命令:`mvn -pl ruoyi-admin -am -DskipTests package` + - 接口验证:`POST /login/test` 获取 token 后,`GET /ccdi/intermediary/list?pageNum=1&pageSize=10` 返回 `code=200`,联合查询不再出现 `Illegal mix of collations` + ## 完成标准 - `ccdi_intermediary_enterprise_relation` 表与唯一约束创建完成 diff --git a/docs/plans/backend/2026-04-20-docker-bank-tag-stuck-backend-implementation.md b/docs/plans/backend/2026-04-20-docker-bank-tag-stuck-backend-implementation.md new file mode 100644 index 00000000..2032d22d --- /dev/null +++ b/docs/plans/backend/2026-04-20-docker-bank-tag-stuck-backend-implementation.md @@ -0,0 +1,65 @@ +# Docker 环境项目打标卡住后端实施记录 + +## 背景 + +- 现象:Docker 部署后的后端中,项目打标任务会长时间停留在“打标中”。 +- 样本项目:`90337` +- 排查目标:确认任务卡住的真实根因,并按最短路径修复。 + +## 已定位问题 + +### 1. 打标规则 SQL 在 MySQL 8 / Docker 环境触发排序规则冲突 + +- 规则:`LARGE_PURCHASE_TRANSACTION` +- 异常:`Illegal mix of collations (utf8mb4_0900_ai_ci) and (utf8mb4_general_ci)` +- 影响:任务在规则执行阶段直接失败。 + +### 2. 失败落库时错误信息过长,导致任务状态无法更新 + +- 表:`ccdi_bank_tag_task` +- 字段:`error_message` +- 异常:`Data too long for column 'error_message'` +- 影响: + - 任务本应更新为 `FAILED`,但更新再次失败 + - 项目状态没有从 `打标中` 回退 + - 前端看到的就是“打标一直卡住” + +## 本次改动范围 + +- `ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankTagAnalysisMapper.xml` + - 为 `LARGE_PURCHASE_TRANSACTION` 相关 join 显式补齐统一排序规则。 +- `sql/migration/2026-04-20-fix-bank-tag-task-error-message-longtext.sql` + - 将 `ccdi_bank_tag_task` 表统一到 `utf8mb4_general_ci`,并把 `error_message` 调整为 `LONGTEXT`。 +- `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiBankTagServiceImpl.java` + - 调整任务失败错误信息拼装逻辑,保留完整根因,不再按 2000 截断。 +- `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiBankTagServiceImplTest.java` + - 新增错误信息裁剪测试。 +- `ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiBankTagAnalysisMapperXmlTest.java` + - 新增 SQL 排序规则约束测试。 + +## 验证 + +- 运行新增测试,先确认失败,再完成修复后确认通过。 +- 修复后检查项目 `90337` 的任务状态是否能正确进入失败态或完成态,不再停留在 `RUNNING`。 + +## 实际执行结果 + +- 已执行数据库脚本: + - `sql/migration/2026-04-20-fix-bank-tag-task-error-message-longtext.sql` +- 已重新打包并重启 Docker 后端容器。 +- 已手工复位历史卡死任务: + - `ccdi_bank_tag_task.id = 76` +- 已重新触发项目 `90337` 打标。 +- 最新验证结果: + - `ccdi_bank_tag_task.id = 79` + - `status = SUCCESS` + - `success_rule_count = 35` + - `hit_count = 132` + - 项目 `90337` 状态已回到 `1 = 已完成` + +## 结论 + +- “打标卡住”并非任务一直运行,而是: + 1. 采购相关规则 SQL 因排序规则冲突失败 + 2. 失败异常写入 `ccdi_bank_tag_task.error_message` 时又因字段长度不足再次失败 +- 本次已按数据库方案改为 `LONGTEXT`,并将采购链路所有相关 join 显式统一为 `utf8mb4_general_ci`。 diff --git a/docs/plans/frontend/2026-04-17-intermediary-library-refactor-frontend-implementation.md b/docs/plans/frontend/2026-04-17-intermediary-library-refactor-frontend-implementation.md index e342e47e..8dc8c221 100644 --- a/docs/plans/frontend/2026-04-17-intermediary-library-refactor-frontend-implementation.md +++ b/docs/plans/frontend/2026-04-17-intermediary-library-refactor-frontend-implementation.md @@ -459,6 +459,15 @@ source ~/.nvm/nvm.sh && nvm use 14.21.3 npm run build:prod ``` +## 执行结果 + +- 实际执行命令:`cd /Users/wkc/Desktop/ccdi/ccdi/ruoyi-ui && source ~/.nvm/nvm.sh && nvm use 14.21.3 && npm run build:prod` +- Node 版本:`v14.21.3` +- 构建结果:`DONE Build complete. The dist directory is ready to be deployed.` +- 备注:仅存在既有包体积告警(asset size / entrypoint size limit),无语法错误和模块解析错误 +- 补充修复:中介库首页“查看中介亲属”弹窗已改为只读模式,查看态不再允许编辑或提交 +- 补充修复:中介库首页“查看关联机构”弹窗已改为只读模式,查看态不再允许编辑或提交 + ## 完成标准 - 首页搜索字段调整为名称、证件号、记录类型、关联中介信息 diff --git a/ruoyi-ui/src/api/ccdiIntermediary.js b/ruoyi-ui/src/api/ccdiIntermediary.js index 7edb58c0..f6252390 100644 --- a/ruoyi-ui/src/api/ccdiIntermediary.js +++ b/ruoyi-ui/src/api/ccdiIntermediary.js @@ -43,15 +43,6 @@ export function addEntityIntermediary(data) { }) } -// 修改中介黑名单 -export function updateIntermediary(data) { - return request({ - url: '/ccdi/intermediary', - method: 'put', - data: data - }) -} - // 修改个人中介黑名单 export function updatePersonIntermediary(data) { return request({ @@ -78,6 +69,90 @@ export function delIntermediary(intermediaryIds) { }) } +// 查询中介亲属列表 +export function listIntermediaryRelatives(bizId) { + return request({ + url: '/ccdi/intermediary/' + bizId + '/relatives', + method: 'get' + }) +} + +// 查询中介亲属详情 +export function getIntermediaryRelative(relativeBizId) { + return request({ + url: '/ccdi/intermediary/relative/' + relativeBizId, + method: 'get' + }) +} + +// 新增中介亲属 +export function addIntermediaryRelative(bizId, data) { + return request({ + url: '/ccdi/intermediary/' + bizId + '/relative', + method: 'post', + data: data + }) +} + +// 修改中介亲属 +export function updateIntermediaryRelative(data) { + return request({ + url: '/ccdi/intermediary/relative', + method: 'put', + data: data + }) +} + +// 删除中介亲属 +export function delIntermediaryRelative(relativeBizId) { + return request({ + url: '/ccdi/intermediary/relative/' + relativeBizId, + method: 'delete' + }) +} + +// 查询中介关联机构列表 +export function listIntermediaryEnterpriseRelations(bizId) { + return request({ + url: '/ccdi/intermediary/' + bizId + '/enterprise-relations', + method: 'get' + }) +} + +// 查询中介关联机构详情 +export function getIntermediaryEnterpriseRelation(id) { + return request({ + url: '/ccdi/intermediary/enterprise-relation/' + id, + method: 'get' + }) +} + +// 新增中介关联机构 +export function addIntermediaryEnterpriseRelation(bizId, data) { + return request({ + url: '/ccdi/intermediary/' + bizId + '/enterprise-relation', + method: 'post', + data: data + }) +} + +// 修改中介关联机构 +export function updateIntermediaryEnterpriseRelation(data) { + return request({ + url: '/ccdi/intermediary/enterprise-relation', + method: 'put', + data: data + }) +} + +// 删除中介关联机构 +export function delIntermediaryEnterpriseRelation(id) { + return request({ + url: '/ccdi/intermediary/enterprise-relation/' + id, + method: 'delete' + }) +} + // 下载导入模板(已废弃,保留以兼容旧代码) export function importTemplate() { return request({ diff --git a/ruoyi-ui/src/views/ccdiIntermediary/components/DataTable.vue b/ruoyi-ui/src/views/ccdiIntermediary/components/DataTable.vue index 2dd53758..360760b5 100644 --- a/ruoyi-ui/src/views/ccdiIntermediary/components/DataTable.vue +++ b/ruoyi-ui/src/views/ccdiIntermediary/components/DataTable.vue @@ -2,34 +2,29 @@
- - - - - + + + + - + @@ -80,12 +69,49 @@ export default { detailData: { type: Object, default: () => ({}) + }, + relativeList: { + type: Array, + default: () => [] + }, + enterpriseRelationList: { + type: Array, + default: () => [] } }, + data() { + return { + dialogVisible: false + }; + }, watch: { - visible(val) { + visible: { + immediate: true, + handler(val) { + this.dialogVisible = val; + } + }, + dialogVisible(val) { this.$emit("update:visible", val); } + }, + methods: { + formatGender(gender) { + if (gender === "M") return "男"; + if (gender === "F") return "女"; + if (gender === "O") return "其他"; + return gender || "-"; + } } }; + + diff --git a/ruoyi-ui/src/views/ccdiIntermediary/components/EditDialog.vue b/ruoyi-ui/src/views/ccdiIntermediary/components/EditDialog.vue index df4a1a20..12c27f4d 100644 --- a/ruoyi-ui/src/views/ccdiIntermediary/components/EditDialog.vue +++ b/ruoyi-ui/src/views/ccdiIntermediary/components/EditDialog.vue @@ -1,314 +1,104 @@ @@ -41,6 +60,10 @@ export default { ownerName: { type: String, default: "" + }, + readonly: { + type: Boolean, + default: false } }, data() { @@ -72,6 +95,9 @@ export default { }, methods: { handleSubmit() { + if (this.readonly) { + return; + } this.$refs.formRef.validate(valid => { if (valid) { this.$emit("submit", { ...this.localForm }); diff --git a/ruoyi-ui/src/views/ccdiIntermediary/components/RelativeEditDialog.vue b/ruoyi-ui/src/views/ccdiIntermediary/components/RelativeEditDialog.vue index f4a82cd9..1fac95c9 100644 --- a/ruoyi-ui/src/views/ccdiIntermediary/components/RelativeEditDialog.vue +++ b/ruoyi-ui/src/views/ccdiIntermediary/components/RelativeEditDialog.vue @@ -9,7 +9,7 @@ - + - + - + - + - + - + - + - + - + - + - + @@ -124,6 +124,10 @@ export default { type: String, default: "" }, + readonly: { + type: Boolean, + default: false + }, relationTypeOptions: { type: Array, default: () => [] @@ -177,6 +181,9 @@ export default { }, methods: { handleSubmit() { + if (this.readonly) { + return; + } this.$refs.formRef.validate(valid => { if (valid) { this.$emit("submit", { ...this.localForm }); diff --git a/ruoyi-ui/src/views/ccdiIntermediary/components/SearchForm.vue b/ruoyi-ui/src/views/ccdiIntermediary/components/SearchForm.vue index 06a2765e..912758d3 100644 --- a/ruoyi-ui/src/views/ccdiIntermediary/components/SearchForm.vue +++ b/ruoyi-ui/src/views/ccdiIntermediary/components/SearchForm.vue @@ -1,11 +1,11 @@