From b1cb38c5fd61a5aee656da21041a3e2f669309ea Mon Sep 17 00:00:00 2001 From: lapuda <577732344@qq.com> Date: Fri, 24 Jul 2026 09:42:37 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=8B=9B=E8=81=98?= =?UTF-8?q?=E4=BC=9A=E6=9C=BA=E6=9E=84=E7=AE=A1=E7=90=86=E5=92=8C=E5=9C=BA?= =?UTF-8?q?=E5=9C=B0=E6=89=80=E5=B1=9E=E6=9C=BA=E6=9E=84=E5=85=B3=E8=81=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cms/JobFairInstitutionController.java | 86 ++++++++++ .../controller/cms/VenueInfoController.java | 10 +- .../ruoyi/cms/domain/JobFairInstitution.java | 30 ++++ .../java/com/ruoyi/cms/domain/VenueInfo.java | 9 ++ .../ruoyi/cms/domain/VenueInstitution.java | 21 +++ .../cms/mapper/JobFairInstitutionMapper.java | 11 ++ .../cms/mapper/VenueInstitutionMapper.java | 11 ++ .../service/IJobFairInstitutionService.java | 33 ++++ .../ruoyi/cms/service/IVenueInfoService.java | 13 ++ .../impl/JobFairInstitutionServiceImpl.java | 100 ++++++++++++ .../service/impl/VenueInfoServiceImpl.java | 132 +++++++++++++++- ...ion_job_fair_institution.test-executed.sql | 148 ++++++++++++++++++ 12 files changed, 599 insertions(+), 5 deletions(-) create mode 100644 ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/cms/JobFairInstitutionController.java create mode 100644 ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/JobFairInstitution.java create mode 100644 ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/VenueInstitution.java create mode 100644 ruoyi-bussiness/src/main/java/com/ruoyi/cms/mapper/JobFairInstitutionMapper.java create mode 100644 ruoyi-bussiness/src/main/java/com/ruoyi/cms/mapper/VenueInstitutionMapper.java create mode 100644 ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/IJobFairInstitutionService.java create mode 100644 ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/JobFairInstitutionServiceImpl.java create mode 100644 sql/migration_job_fair_institution.test-executed.sql diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/cms/JobFairInstitutionController.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/cms/JobFairInstitutionController.java new file mode 100644 index 0000000..b3d3053 --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/cms/JobFairInstitutionController.java @@ -0,0 +1,86 @@ +package com.ruoyi.cms.controller.cms; + +import java.util.Arrays; +import java.util.List; + +import com.ruoyi.cms.domain.JobFairInstitution; +import com.ruoyi.cms.service.IJobFairInstitutionService; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 招聘会机构管理 Controller。 + */ +@RestController +@RequestMapping("/cms/job-fair-institution") +@Api(tags = "后台:招聘会机构管理") +public class JobFairInstitutionController extends BaseController +{ + @Autowired + private IJobFairInstitutionService institutionService; + + @ApiOperation("查询机构列表") + @PreAuthorize("@ss.hasPermi('cms:jobFairInstitution:list')") + @GetMapping("/list") + public TableDataInfo list(JobFairInstitution query) + { + startPage(); + List list = institutionService.selectInstitutionList(query); + return getDataTable(list); + } + + @ApiOperation("获取机构详细信息") + @PreAuthorize("@ss.hasPermi('cms:jobFairInstitution:query')") + @GetMapping("/{id}") + public AjaxResult getInfo(@PathVariable("id") Long id) + { + return success(institutionService.getById(id)); + } + + @ApiOperation("新增机构") + @PreAuthorize("@ss.hasPermi('cms:jobFairInstitution:add')") + @Log(title = "招聘会机构", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody JobFairInstitution institution) + { + JobFairInstitution saved = institutionService.saveInstitution(institution); + AjaxResult result = toAjax(saved != null && saved.getId() != null); + if (result.isSuccess()) { + result.put("data", saved); + } + return result; + } + + @ApiOperation("修改机构") + @PreAuthorize("@ss.hasPermi('cms:jobFairInstitution:edit')") + @Log(title = "招聘会机构", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody JobFairInstitution institution) + { + return toAjax(institutionService.updateInstitution(institution)); + } + + @ApiOperation("删除机构") + @PreAuthorize("@ss.hasPermi('cms:jobFairInstitution:remove')") + @Log(title = "招聘会机构", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) + { + return toAjax(institutionService.removeInstitutionByIds(Arrays.asList(ids))); + } +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/cms/VenueInfoController.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/cms/VenueInfoController.java index 7d6d0e5..aa992b5 100644 --- a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/cms/VenueInfoController.java +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/cms/VenueInfoController.java @@ -100,7 +100,7 @@ public class VenueInfoController extends BaseController @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) { - return success(venueInfoService.getById(id)); + return success(venueInfoService.getVenueInfoWithInstitutions(id)); } /** @@ -109,11 +109,12 @@ public class VenueInfoController extends BaseController @ApiOperation("新增场地信息") @PreAuthorize("@ss.hasPermi('cms:venueInfo:add')") @Log(title = "场地信息", businessType = BusinessType.INSERT) + @Transactional(rollbackFor = Exception.class) @PostMapping public AjaxResult add(@RequestBody VenueInfo venueInfo) { fillHandleFields(venueInfo); - return toAjax(venueInfoService.save(venueInfo)); + return toAjax(venueInfoService.saveWithInstitutions(venueInfo)); } /** @@ -122,11 +123,12 @@ public class VenueInfoController extends BaseController @ApiOperation("修改场地信息") @PreAuthorize("@ss.hasPermi('cms:venueInfo:edit')") @Log(title = "场地信息", businessType = BusinessType.UPDATE) + @Transactional(rollbackFor = Exception.class) @PutMapping public AjaxResult edit(@RequestBody VenueInfo venueInfo) { fillHandleFields(venueInfo); - return toAjax(venueInfoService.updateById(venueInfo)); + return toAjax(venueInfoService.updateWithInstitutions(venueInfo)); } /** @@ -138,7 +140,7 @@ public class VenueInfoController extends BaseController @DeleteMapping("/{ids}") public AjaxResult remove(@PathVariable Long[] ids) { - return toAjax(venueInfoService.removeByIds(Arrays.asList(ids))); + return toAjax(venueInfoService.removeByIdsWithInstitutions(Arrays.asList(ids))); } /** diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/JobFairInstitution.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/JobFairInstitution.java new file mode 100644 index 0000000..b098bda --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/JobFairInstitution.java @@ -0,0 +1,30 @@ +package com.ruoyi.cms.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ruoyi.common.core.domain.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 招聘会机构对象 cms_job_fair_institution。 + */ +@Data +@ApiModel("招聘会机构") +@TableName("cms_job_fair_institution") +public class JobFairInstitution extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + @ApiModelProperty("主键ID") + private Long id; + + @ApiModelProperty("机构名称") + private String institutionName; + + @ApiModelProperty("机构简介") + private String institutionIntro; +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/VenueInfo.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/VenueInfo.java index 685bf36..0800463 100644 --- a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/VenueInfo.java +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/VenueInfo.java @@ -4,6 +4,7 @@ import java.math.BigDecimal; import java.util.Date; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; @@ -74,4 +75,12 @@ public class VenueInfo extends BaseEntity @Excel(name = "经办人") @ApiModelProperty("经办人") private String handler; + + @TableField(exist = false) + @ApiModelProperty("所属机构ID列表") + private java.util.List institutionIds; + + @TableField(exist = false) + @ApiModelProperty("所属机构名称,多个用顿号分隔") + private String institutionNames; } diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/VenueInstitution.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/VenueInstitution.java new file mode 100644 index 0000000..93786a5 --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/domain/VenueInstitution.java @@ -0,0 +1,21 @@ +package com.ruoyi.cms.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * 场地与招聘会机构关联对象 cms_venue_institution。 + */ +@Data +@TableName("cms_venue_institution") +public class VenueInstitution +{ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private Long venueId; + + private Long institutionId; +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/mapper/JobFairInstitutionMapper.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/mapper/JobFairInstitutionMapper.java new file mode 100644 index 0000000..e9d335d --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/mapper/JobFairInstitutionMapper.java @@ -0,0 +1,11 @@ +package com.ruoyi.cms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.cms.domain.JobFairInstitution; + +/** + * 招聘会机构 Mapper。 + */ +public interface JobFairInstitutionMapper extends BaseMapper +{ +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/mapper/VenueInstitutionMapper.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/mapper/VenueInstitutionMapper.java new file mode 100644 index 0000000..bbc153f --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/mapper/VenueInstitutionMapper.java @@ -0,0 +1,11 @@ +package com.ruoyi.cms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.cms.domain.VenueInstitution; + +/** + * 场地与招聘会机构关联 Mapper。 + */ +public interface VenueInstitutionMapper extends BaseMapper +{ +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/IJobFairInstitutionService.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/IJobFairInstitutionService.java new file mode 100644 index 0000000..b46d7a8 --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/IJobFairInstitutionService.java @@ -0,0 +1,33 @@ +package com.ruoyi.cms.service; + +import java.util.Collection; +import java.util.List; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.cms.domain.JobFairInstitution; + +/** + * 招聘会机构 Service。 + */ +public interface IJobFairInstitutionService extends IService +{ + /** + * 查询机构列表。 + */ + List selectInstitutionList(JobFairInstitution query); + + /** + * 新增机构并校验机构名称。 + */ + JobFairInstitution saveInstitution(JobFairInstitution institution); + + /** + * 修改机构并校验机构名称。 + */ + boolean updateInstitution(JobFairInstitution institution); + + /** + * 删除机构;已被场地使用的机构不允许删除。 + */ + boolean removeInstitutionByIds(Collection ids); +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/IVenueInfoService.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/IVenueInfoService.java index fbfc4a0..b7f08a6 100644 --- a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/IVenueInfoService.java +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/IVenueInfoService.java @@ -1,6 +1,7 @@ package com.ruoyi.cms.service; import java.util.List; +import java.util.Collection; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.cms.domain.VenueInfo; @@ -21,6 +22,18 @@ public interface IVenueInfoService extends IService */ List selectVenueInfoList(VenueInfo venueInfo); + /** 查询场地详情并填充所属机构。 */ + VenueInfo getVenueInfoWithInstitutions(Long id); + + /** 新增场地及所属机构关联。 */ + boolean saveWithInstitutions(VenueInfo venueInfo); + + /** 修改场地及所属机构关联。 */ + boolean updateWithInstitutions(VenueInfo venueInfo); + + /** 删除场地及所属机构关联。 */ + boolean removeByIdsWithInstitutions(Collection ids); + /** * 新增场地信息相关字典项 * diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/JobFairInstitutionServiceImpl.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/JobFairInstitutionServiceImpl.java new file mode 100644 index 0000000..0d74fcd --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/JobFairInstitutionServiceImpl.java @@ -0,0 +1,100 @@ +package com.ruoyi.cms.service.impl; + +import java.util.Collection; +import java.util.List; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.cms.domain.JobFairInstitution; +import com.ruoyi.cms.domain.VenueInstitution; +import com.ruoyi.cms.mapper.JobFairInstitutionMapper; +import com.ruoyi.cms.mapper.VenueInstitutionMapper; +import com.ruoyi.cms.service.IJobFairInstitutionService; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 招聘会机构 Service 实现。 + */ +@Service +public class JobFairInstitutionServiceImpl + extends ServiceImpl + implements IJobFairInstitutionService +{ + @Autowired + private VenueInstitutionMapper venueInstitutionMapper; + + @Override + public List selectInstitutionList(JobFairInstitution query) + { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.like(StringUtils.isNotBlank(query.getInstitutionName()), + JobFairInstitution::getInstitutionName, query.getInstitutionName()); + wrapper.orderByDesc(JobFairInstitution::getCreateTime); + wrapper.orderByAsc(JobFairInstitution::getId); + return list(wrapper); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public JobFairInstitution saveInstitution(JobFairInstitution institution) + { + normalizeAndCheck(institution, null); + save(institution); + return institution; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateInstitution(JobFairInstitution institution) + { + if (institution == null || institution.getId() == null || getById(institution.getId()) == null) { + throw new ServiceException("机构不存在"); + } + normalizeAndCheck(institution, institution.getId()); + return updateById(institution); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeInstitutionByIds(Collection ids) + { + if (ids == null || ids.isEmpty()) { + return false; + } + Long usedCount = venueInstitutionMapper.selectCount(new LambdaQueryWrapper() + .in(VenueInstitution::getInstitutionId, ids)); + if (usedCount != null && usedCount > 0) { + throw new ServiceException("机构已被场地使用,请先从场地信息中移除该机构"); + } + return removeByIds(ids); + } + + private void normalizeAndCheck(JobFairInstitution institution, Long excludingId) + { + if (institution == null) { + throw new ServiceException("机构信息不能为空"); + } + String name = StringUtils.trim(institution.getInstitutionName()); + if (StringUtils.isBlank(name)) { + throw new ServiceException("机构名称不能为空"); + } + if (name.length() > 200) { + throw new ServiceException("机构名称长度不能超过200个字符"); + } + if (StringUtils.isNotBlank(institution.getInstitutionIntro()) + && institution.getInstitutionIntro().length() > 2000) { + throw new ServiceException("机构简介长度不能超过2000个字符"); + } + institution.setInstitutionName(name); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(JobFairInstitution::getInstitutionName, name); + wrapper.ne(excludingId != null, JobFairInstitution::getId, excludingId); + if (count(wrapper) > 0) { + throw new ServiceException("机构名称已存在"); + } + } +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/VenueInfoServiceImpl.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/VenueInfoServiceImpl.java index ed2a5ce..88e3762 100644 --- a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/VenueInfoServiceImpl.java +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/VenueInfoServiceImpl.java @@ -1,16 +1,28 @@ package com.ruoyi.cms.service.impl; import java.util.List; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.stream.Collectors; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.cms.domain.VenueInfo; +import com.ruoyi.cms.domain.JobFairInstitution; +import com.ruoyi.cms.domain.VenueInstitution; +import com.ruoyi.cms.mapper.JobFairInstitutionMapper; import com.ruoyi.cms.mapper.VenueInfoMapper; +import com.ruoyi.cms.mapper.VenueInstitutionMapper; import com.ruoyi.cms.service.IVenueInfoService; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DictUtils; import com.ruoyi.common.utils.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; /** * 场地信息Service业务层处理 @@ -23,6 +35,12 @@ public class VenueInfoServiceImpl extends ServiceImpl list = list(queryWrapper); + enrichInstitutions(list); + return list; + } + + @Override + public VenueInfo getVenueInfoWithInstitutions(Long id) + { + VenueInfo venueInfo = getById(id); + if (venueInfo != null) { + enrichInstitutions(Collections.singletonList(venueInfo)); + } + return venueInfo; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean saveWithInstitutions(VenueInfo venueInfo) + { + validateInstitutionIds(venueInfo == null ? null : venueInfo.getInstitutionIds()); + boolean saved = save(venueInfo); + if (saved) { + replaceInstitutionRelations(venueInfo.getId(), venueInfo.getInstitutionIds()); + } + return saved; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateWithInstitutions(VenueInfo venueInfo) + { + if (venueInfo == null || venueInfo.getId() == null || getById(venueInfo.getId()) == null) { + return false; + } + validateInstitutionIds(venueInfo.getInstitutionIds()); + boolean updated = updateById(venueInfo); + if (updated) { + replaceInstitutionRelations(venueInfo.getId(), venueInfo.getInstitutionIds()); + } + return updated; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeByIdsWithInstitutions(Collection ids) + { + if (ids == null || ids.isEmpty()) { + return false; + } + venueInstitutionMapper.delete(new LambdaQueryWrapper() + .in(VenueInstitution::getVenueId, ids)); + return removeByIds(ids); + } + + private void validateInstitutionIds(List institutionIds) + { + if (institutionIds == null || institutionIds.isEmpty()) { + return; + } + List distinctIds = institutionIds.stream() + .filter(id -> id != null) + .distinct() + .collect(Collectors.toList()); + if (distinctIds.size() != institutionIds.stream().filter(id -> id != null).count()) { + throw new ServiceException("所属机构不能重复"); + } + if (distinctIds.size() != jobFairInstitutionMapper.selectBatchIds(distinctIds).size()) { + throw new ServiceException("所属机构中包含不存在的机构"); + } + } + + private void replaceInstitutionRelations(Long venueId, List institutionIds) + { + venueInstitutionMapper.delete(new LambdaQueryWrapper() + .eq(VenueInstitution::getVenueId, venueId)); + if (institutionIds == null) { + return; + } + for (Long institutionId : institutionIds.stream().filter(id -> id != null).distinct().collect(Collectors.toList())) { + VenueInstitution relation = new VenueInstitution(); + relation.setVenueId(venueId); + relation.setInstitutionId(institutionId); + venueInstitutionMapper.insert(relation); + } + } + + private void enrichInstitutions(List venues) + { + if (venues == null || venues.isEmpty()) { + return; + } + List venueIds = venues.stream().map(VenueInfo::getId).filter(id -> id != null).collect(Collectors.toList()); + List relations = venueInstitutionMapper.selectList(new LambdaQueryWrapper() + .in(!venueIds.isEmpty(), VenueInstitution::getVenueId, venueIds) + .orderByAsc(VenueInstitution::getId)); + Map> idsByVenue = new LinkedHashMap<>(); + for (VenueInstitution relation : relations) { + idsByVenue.computeIfAbsent(relation.getVenueId(), key -> new ArrayList<>()).add(relation.getInstitutionId()); + } + List institutionIds = relations.stream().map(VenueInstitution::getInstitutionId).distinct().collect(Collectors.toList()); + Map institutions = institutionIds.isEmpty() + ? Collections.emptyMap() + : jobFairInstitutionMapper.selectBatchIds(institutionIds).stream() + .collect(Collectors.toMap(JobFairInstitution::getId, item -> item)); + for (VenueInfo venue : venues) { + List ids = idsByVenue.getOrDefault(venue.getId(), Collections.emptyList()); + venue.setInstitutionIds(ids); + venue.setInstitutionNames(ids.stream() + .map(institutions::get) + .filter(item -> item != null) + .map(JobFairInstitution::getInstitutionName) + .collect(Collectors.joining("、"))); + } } /** diff --git a/sql/migration_job_fair_institution.test-executed.sql b/sql/migration_job_fair_institution.test-executed.sql new file mode 100644 index 0000000..459b7e6 --- /dev/null +++ b/sql/migration_job_fair_institution.test-executed.sql @@ -0,0 +1,148 @@ +-- 执行状态:测试环境已执行 +-- 测试环境:test +-- 测试执行时间:2026-07-24 09:39:31 +0800 +-- 正式环境:未执行 +-- 招聘会机构管理及场地所属机构多选关联。 +-- 依赖:招聘会管理目录(menu_name='招聘会管理')和场地信息维护权限已存在。 +-- 可重复执行;正式环境仅在功能验收通过并获单独授权后执行。 + +BEGIN; + +SET LOCAL search_path = shz, public; + +CREATE SEQUENCE IF NOT EXISTS cms_job_fair_institution_id_seq + START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; + +CREATE SEQUENCE IF NOT EXISTS cms_venue_institution_id_seq + START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1; + +CREATE TABLE IF NOT EXISTS cms_job_fair_institution ( + id BIGINT NOT NULL DEFAULT nextval('cms_job_fair_institution_id_seq') PRIMARY KEY, + institution_name VARCHAR(200) NOT NULL, + institution_intro TEXT, + create_by VARCHAR(64) DEFAULT '', + create_time TIMESTAMP(0), + update_by VARCHAR(64) DEFAULT '', + update_time TIMESTAMP(0), + remark VARCHAR(500), + del_flag CHAR(1) DEFAULT '0' +); + +COMMENT ON TABLE cms_job_fair_institution IS '招聘会机构管理表'; +COMMENT ON COLUMN cms_job_fair_institution.institution_name IS '机构名称'; +COMMENT ON COLUMN cms_job_fair_institution.institution_intro IS '机构简介'; +COMMENT ON COLUMN cms_job_fair_institution.del_flag IS '删除标志(0代表存在 2代表删除)'; + +CREATE UNIQUE INDEX IF NOT EXISTS uk_cms_job_fair_institution_name + ON cms_job_fair_institution (institution_name) WHERE del_flag = '0'; + +CREATE TABLE IF NOT EXISTS cms_venue_institution ( + id BIGINT NOT NULL DEFAULT nextval('cms_venue_institution_id_seq') PRIMARY KEY, + venue_id BIGINT NOT NULL, + institution_id BIGINT NOT NULL +); + +COMMENT ON TABLE cms_venue_institution IS '场地与招聘会机构关联表'; +COMMENT ON COLUMN cms_venue_institution.venue_id IS '场地ID'; +COMMENT ON COLUMN cms_venue_institution.institution_id IS '机构ID'; + +CREATE UNIQUE INDEX IF NOT EXISTS uk_cms_venue_institution + ON cms_venue_institution (venue_id, institution_id); +CREATE INDEX IF NOT EXISTS idx_cms_venue_institution_institution + ON cms_venue_institution (institution_id); + +WITH parent_menu AS ( + SELECT menu_id + FROM sys_menu + WHERE menu_name = '招聘会管理' AND parent_id = 0 + ORDER BY menu_id + LIMIT 1 +), inserted_page AS ( + INSERT INTO sys_menu ( + menu_id, menu_name, parent_id, order_num, path, component, query, route_name, + is_frame, is_cache, menu_type, visible, status, perms, icon, + create_by, create_time, remark + ) + SELECT + (SELECT COALESCE(MAX(menu_id), 0) + 1 FROM sys_menu), + '机构管理', parent_menu.menu_id, 3, 'institution', 'jobfair/institution/index', NULL, '', + 1, 0, 'C', '0', '0', 'cms:jobFairInstitution:list', '#', + 'system', NOW(), '招聘会机构管理菜单' + FROM parent_menu + WHERE NOT EXISTS ( + SELECT 1 + FROM sys_menu existing + WHERE existing.parent_id = parent_menu.menu_id + AND existing.menu_name = '机构管理' + ) + RETURNING menu_id +), institution_page AS ( + SELECT menu_id FROM inserted_page + UNION + SELECT menu_id + FROM sys_menu + WHERE menu_name = '机构管理' + AND parent_id = (SELECT menu_id FROM parent_menu) +), button_seed(menu_name, order_num, perms) AS ( + VALUES + ('机构查询', 1, 'cms:jobFairInstitution:query'), + ('机构新增', 2, 'cms:jobFairInstitution:add'), + ('机构修改', 3, 'cms:jobFairInstitution:edit'), + ('机构删除', 4, 'cms:jobFairInstitution:remove') +), max_menu AS ( + SELECT COALESCE(MAX(menu_id), 0) AS menu_id FROM sys_menu +) +INSERT INTO sys_menu ( + menu_id, menu_name, parent_id, order_num, path, component, query, route_name, + is_frame, is_cache, menu_type, visible, status, perms, icon, + create_by, create_time, remark +) +SELECT + max_menu.menu_id + 1 + ROW_NUMBER() OVER (ORDER BY button_seed.order_num), + button_seed.menu_name, institution_page.menu_id, button_seed.order_num, '', NULL, NULL, '', + 1, 0, 'F', '0', '0', button_seed.perms, '#', + 'system', NOW(), '招聘会机构管理按钮权限' +FROM institution_page +CROSS JOIN button_seed +CROSS JOIN max_menu +WHERE NOT EXISTS ( + SELECT 1 FROM sys_menu existing WHERE existing.perms = button_seed.perms +); + +WITH institution_menus AS ( + SELECT menu_id + FROM sys_menu + WHERE perms IN ( + 'cms:jobFairInstitution:list', + 'cms:jobFairInstitution:query', + 'cms:jobFairInstitution:add', + 'cms:jobFairInstitution:edit', + 'cms:jobFairInstitution:remove' + ) + UNION + SELECT menu_id + FROM sys_menu + WHERE menu_name = '机构管理' + AND parent_id = (SELECT menu_id FROM sys_menu WHERE menu_name = '招聘会管理' AND parent_id = 0 ORDER BY menu_id LIMIT 1) +), venue_roles AS ( + SELECT DISTINCT role_id + FROM sys_role_menu + WHERE menu_id IN ( + SELECT menu_id FROM sys_menu WHERE perms = 'cms:venueInfo:list' + ) +), role_menu_rows AS ( + SELECT venue_roles.role_id, institution_menus.menu_id + FROM venue_roles + CROSS JOIN institution_menus +) +INSERT INTO sys_role_menu (role_id, menu_id) +SELECT role_menu_rows.role_id, role_menu_rows.menu_id +FROM role_menu_rows +WHERE NOT EXISTS ( + SELECT 1 + FROM sys_role_menu existing + WHERE existing.role_id = role_menu_rows.role_id + AND existing.menu_id = role_menu_rows.menu_id +); + +COMMIT;