feat: Add Cross-Domain Job Fair and Alliance City Management

- Implemented AppOutdoorFairController for outdoor job fair public H5 interfaces.
- Created CrossCityAllianceController for managing cross-domain alliance cities.
- Added CrossCityAlliance domain model and corresponding service and mapper.
- Developed CrossDomainJobVO for aggregating job data across job fairs.
- Created SQL scripts for initializing the cross-city alliance table and modifying the public job fair schema.
- Added migration script for backing up and restoring the HighGo database schema.
This commit is contained in:
2026-06-27 22:44:56 +08:00
parent 0ccfb6e6dc
commit b35ed5989e
29 changed files with 1969 additions and 50 deletions

View File

@@ -0,0 +1,398 @@
package com.ruoyi.cms.controller.app;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.cms.domain.FairCompany;
import com.ruoyi.cms.domain.Job;
import com.ruoyi.cms.domain.OutdoorFair;
import com.ruoyi.cms.domain.OutdoorFairAttendee;
import com.ruoyi.cms.domain.OutdoorFairBoothBooking;
import com.ruoyi.cms.domain.OutdoorFairDevice;
import com.ruoyi.cms.mapper.CompanyMapper;
import com.ruoyi.cms.mapper.FairCompanyMapper;
import com.ruoyi.cms.mapper.OutdoorFairBoothBookingMapper;
import com.ruoyi.cms.mapper.OutdoorFairDeviceMapper;
import com.ruoyi.cms.mapper.OutdoorFairJobMapper;
import com.ruoyi.cms.domain.rc.PublicJobFair;
import com.ruoyi.cms.domain.rc.PublicJobFairQuery;
import com.ruoyi.cms.domain.rc.PublicJobFairResponse;
import com.ruoyi.cms.service.IOutdoorFairAttendeeService;
import com.ruoyi.cms.service.IOutdoorFairService;
import com.ruoyi.common.annotation.BussinessLog;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.Company;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 移动端:户外招聘会公共 H5 接口。
*/
@RestController
@RequestMapping("/app/outdoor-fair")
@Api(tags = "移动端户外招聘会公共H5")
public class AppOutdoorFairController extends BaseController
{
private static final String DAY_PATTERN = "yyyy-MM-dd";
@Autowired
private IOutdoorFairService outdoorFairService;
@Autowired
private CompanyMapper companyMapper;
@Autowired
private FairCompanyMapper fairCompanyMapper;
@Autowired
private OutdoorFairDeviceMapper outdoorFairDeviceMapper;
@Autowired
private OutdoorFairBoothBookingMapper outdoorFairBoothBookingMapper;
@Autowired
private OutdoorFairJobMapper outdoorFairJobMapper;
@Autowired
private IOutdoorFairAttendeeService outdoorFairAttendeeService;
@BussinessLog(title = "户外招聘会列表")
@ApiOperation("分页查询户外招聘会列表")
@GetMapping("/page")
public PublicJobFairResponse page(PublicJobFairQuery query)
{
if (query == null) {
query = new PublicJobFairQuery();
}
int pageNum = query.getPageNum() == null || query.getPageNum() < 1 ? 1 : query.getPageNum();
int pageSize = query.getPageSize() == null || query.getPageSize() < 1 ? 10 : query.getPageSize();
Page<OutdoorFair> page = outdoorFairService.page(new Page<>(pageNum, pageSize), buildOutdoorFairWrapper(query));
PublicJobFairResponse response = new PublicJobFairResponse();
response.setCode(200);
response.setMsg("查询成功");
response.setData(buildPageData(page, pageNum, pageSize));
return response;
}
@BussinessLog(title = "查看当季度户外招聘会信息")
@ApiOperation("查看当季度户外招聘会信息")
@GetMapping("/currentQuarter")
public AjaxResult currentQuarterFairs()
{
Calendar calendar = Calendar.getInstance();
int currentMonth = calendar.get(Calendar.MONTH);
int quarterStartMonth = currentMonth / 3 * 3;
calendar.set(Calendar.MONTH, quarterStartMonth);
calendar.set(Calendar.DAY_OF_MONTH, 1);
setStartOfDay(calendar);
Date startTime = calendar.getTime();
calendar.add(Calendar.MONTH, 3);
Date endTime = calendar.getTime();
return success(listOutdoorFairsByRange(startTime, endTime));
}
@BussinessLog(title = "查看当月户外招聘会信息")
@ApiOperation("查看当月户外招聘会信息")
@GetMapping("/currentMonth")
public AjaxResult currentMonthFairs()
{
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_MONTH, 1);
setStartOfDay(calendar);
Date startTime = calendar.getTime();
calendar.add(Calendar.MONTH, 1);
Date endTime = calendar.getTime();
return success(listOutdoorFairsByRange(startTime, endTime));
}
@BussinessLog(title = "查询有户外招聘会的日期列表")
@ApiOperation("查询有户外招聘会的日期列表")
@GetMapping("/dates")
public AjaxResult dates()
{
List<String> dates = outdoorFairService.list(new LambdaQueryWrapper<OutdoorFair>()
.isNotNull(OutdoorFair::getHoldTime)
.orderByAsc(OutdoorFair::getHoldTime))
.stream()
.map(OutdoorFair::getHoldTime)
.map(AppOutdoorFairController::formatDay)
.distinct()
.collect(Collectors.toList());
return success(dates);
}
@BussinessLog(title = "户外招聘会企业H5详情")
@ApiOperation("通过设备码获取户外招聘会企业H5详情")
@GetMapping("/company-page")
public AjaxResult companyPageByDeviceCode(@RequestParam String deviceCode, HttpServletRequest request)
{
if (StringUtils.isBlank(deviceCode)) {
return AjaxResult.error("设备码不能为空");
}
OutdoorFairDevice device = outdoorFairDeviceMapper.selectOne(new LambdaQueryWrapper<OutdoorFairDevice>()
.eq(OutdoorFairDevice::getDeviceCode, deviceCode)
.last("LIMIT 1"));
if (device == null || device.getCompanyId() == null) {
return AjaxResult.error("设备码未绑定参会企业");
}
return success(buildCompanyPage(device.getFairId(), device.getCompanyId(), device, request));
}
@BussinessLog(title = "户外招聘会企业H5详情")
@ApiOperation("通过招聘会ID和企业ID获取户外招聘会企业H5详情")
@GetMapping("/{fairId}/companies/{companyId}/page")
public AjaxResult companyPage(@PathVariable Long fairId, @PathVariable Long companyId,
HttpServletRequest request)
{
OutdoorFairDevice device = outdoorFairDeviceMapper.selectOne(new LambdaQueryWrapper<OutdoorFairDevice>()
.eq(OutdoorFairDevice::getFairId, fairId)
.eq(OutdoorFairDevice::getCompanyId, companyId)
.last("LIMIT 1"));
return success(buildCompanyPage(fairId, companyId, device, request));
}
@BussinessLog(title = "户外招聘会详情")
@ApiOperation("获取户外招聘会公共详情")
@GetMapping("/{fairId}")
public AjaxResult detail(@PathVariable Long fairId, HttpServletRequest request)
{
OutdoorFair fair = outdoorFairService.getById(fairId);
if (fair == null) {
return AjaxResult.error("招聘会不存在");
}
Map<String, Object> data = new HashMap<>();
data.put("fair", fair);
data.put("fairH5Url", buildFairH5Url(request, fairId));
return success(data);
}
/**
* 匿名签到(姓名+手机号。H5 企业页调用,无需登录。
*/
@BussinessLog(title = "户外招聘会企业H5签到")
@ApiOperation("匿名签到(姓名+手机号)")
@PostMapping("/check-in")
public AjaxResult checkIn(@RequestBody OutdoorFairAttendee attendee)
{
if (attendee.getFairId() == null) {
return AjaxResult.error("缺少招聘会参数");
}
if (StringUtils.isBlank(attendee.getName())) {
return AjaxResult.error("姓名不能为空");
}
if (StringUtils.isBlank(attendee.getPhone())) {
return AjaxResult.error("手机号不能为空");
}
// 同一招聘会下同手机号已签到则不重复记录
Long exists = outdoorFairAttendeeService.count(new LambdaQueryWrapper<OutdoorFairAttendee>()
.eq(OutdoorFairAttendee::getFairId, attendee.getFairId())
.eq(OutdoorFairAttendee::getPhone, attendee.getPhone()));
if (exists != null && exists > 0) {
return AjaxResult.error("该手机号已签到");
}
attendee.setCheckInTime(new Date());
return toAjax(outdoorFairAttendeeService.save(attendee));
}
private Map<String, Object> buildCompanyPage(Long fairId, Long companyId, OutdoorFairDevice device,
HttpServletRequest request)
{
OutdoorFair fair = outdoorFairService.getById(fairId);
if (fair == null) {
throw new ServiceException("招聘会不存在");
}
Company company = companyMapper.selectById(companyId);
if (company == null) {
throw new ServiceException("企业不存在");
}
Long relationCount = fairCompanyMapper.selectCount(new LambdaQueryWrapper<FairCompany>()
.eq(FairCompany::getJobFairId, fairId)
.eq(FairCompany::getCompanyId, companyId));
if (relationCount == null || relationCount == 0) {
throw new ServiceException("该企业未参加当前招聘会");
}
OutdoorFairBoothBooking booking = outdoorFairBoothBookingMapper.selectOne(
new LambdaQueryWrapper<OutdoorFairBoothBooking>()
.eq(OutdoorFairBoothBooking::getFairId, fairId)
.eq(OutdoorFairBoothBooking::getCompanyId, companyId)
.eq(OutdoorFairBoothBooking::getStatus, "reserved")
.last("LIMIT 1"));
List<Job> jobs = outdoorFairJobMapper.selectFairJobPage(
fairId, companyId, null, null, null, null, 0, 200);
String companyH5Url = buildCompanyH5Url(request, fairId, companyId);
Map<String, Object> data = new HashMap<>();
data.put("fair", fair);
data.put("company", company);
data.put("booth", booking);
data.put("jobs", jobs);
data.put("fairH5Url", buildFairH5Url(request, fairId));
data.put("companyH5Url", companyH5Url);
data.put("qrCodeContent", companyH5Url);
data.put("deviceId", device == null ? null : device.getId());
data.put("deviceCode", device == null ? null : device.getDeviceCode());
return data;
}
private String buildCompanyH5Url(HttpServletRequest request, Long fairId, Long companyId)
{
String baseUrl = buildBaseUrl(request);
return baseUrl + "/h5/outdoor-fair/company.html?fairId=" + fairId + "&companyId=" + companyId;
}
private String buildFairH5Url(HttpServletRequest request, Long fairId)
{
return buildBaseUrl(request) + "/h5/outdoor-fair/detail.html?fairId=" + fairId;
}
private LambdaQueryWrapper<OutdoorFair> buildOutdoorFairWrapper(PublicJobFairQuery query)
{
LambdaQueryWrapper<OutdoorFair> wrapper = new LambdaQueryWrapper<>();
if (query != null && StringUtils.isNotBlank(query.getJobFairTitle())) {
wrapper.like(OutdoorFair::getTitle, query.getJobFairTitle());
}
if (query != null && StringUtils.isNotBlank(query.getZphjbsj())) {
Date[] dayRange = parseDayRange(query.getZphjbsj());
if (dayRange != null) {
wrapper.lt(OutdoorFair::getHoldTime, dayRange[1])
.and(w -> w.isNull(OutdoorFair::getEndTime)
.or()
.ge(OutdoorFair::getEndTime, dayRange[0]));
}
}
wrapper.orderByDesc(OutdoorFair::getHoldTime)
.orderByDesc(OutdoorFair::getCreateTime);
return wrapper;
}
private PublicJobFairResponse.PageData buildPageData(Page<OutdoorFair> page, int pageNum, int pageSize)
{
PublicJobFairResponse.PageData data = new PublicJobFairResponse.PageData();
List<PublicJobFair> list = page.getRecords().stream()
.map(this::buildPublicJobFair)
.collect(Collectors.toList());
int pages = (int) page.getPages();
data.setTotal(page.getTotal());
data.setList(list);
data.setPageNum(pageNum);
data.setPageSize(pageSize);
data.setSize(list.size());
data.setStartRow(list.isEmpty() ? 0 : (pageNum - 1) * pageSize + 1);
data.setEndRow(list.isEmpty() ? 0 : (pageNum - 1) * pageSize + list.size());
data.setPages(pages);
data.setPrePage(pageNum > 1 ? pageNum - 1 : 0);
data.setNextPage(pageNum < pages ? pageNum + 1 : 0);
data.setIsFirstPage(pageNum <= 1);
data.setIsLastPage(pageNum >= pages);
data.setHasPreviousPage(pageNum > 1);
data.setHasNextPage(pageNum < pages);
data.setNavigatePages(8);
data.setNavigatepageNums(buildNavigatePageNums(pages));
data.setNavigateFirstPage(pages > 0 ? 1 : 0);
data.setNavigateLastPage(pages);
return data;
}
private List<Integer> buildNavigatePageNums(int pages)
{
List<Integer> pageNums = new ArrayList<>();
for (int i = 1; i <= pages; i++) {
pageNums.add(i);
}
return pageNums;
}
private List<PublicJobFair> listOutdoorFairsByRange(Date startTime, Date endTime)
{
return outdoorFairService.list(new LambdaQueryWrapper<OutdoorFair>()
.ge(OutdoorFair::getHoldTime, startTime)
.lt(OutdoorFair::getHoldTime, endTime)
.orderByAsc(OutdoorFair::getHoldTime))
.stream()
.map(this::buildPublicJobFair)
.collect(Collectors.toList());
}
private PublicJobFair buildPublicJobFair(OutdoorFair fair)
{
PublicJobFair jobFair = new PublicJobFair();
jobFair.setJobFairId(String.valueOf(fair.getId()));
jobFair.setJobFairTitle(fair.getTitle());
jobFair.setJobFairAddress(StringUtils.isNotBlank(fair.getAddress()) ? fair.getAddress() : fair.getVenueName());
jobFair.setJobFairType("outdoor");
jobFair.setJobFairStartTime(fair.getHoldTime());
jobFair.setJobFairEndTime(fair.getEndTime());
jobFair.setJobFairHostUnit(fair.getHostUnit());
jobFair.setJobFairOrganizeUnit(fair.getHostUnit());
jobFair.setJobFairIntroduction(StringUtils.isNotBlank(fair.getVenueName()) ? fair.getVenueName() : fair.getAddress());
jobFair.setJobFairImage(fair.getPhotoUrl());
jobFair.setJobFairSignUpStartTime(fair.getApplyStartTime());
jobFair.setJobFairSignUpEndTime(fair.getApplyEndTime());
jobFair.setJobFairVenueId(fair.getVenueId() == null ? null : String.valueOf(fair.getVenueId()));
jobFair.setBoothNum(fair.getBoothCount() == null ? null : String.valueOf(fair.getBoothCount()));
return jobFair;
}
private Date[] parseDayRange(String day)
{
try {
Date startTime = new SimpleDateFormat(DAY_PATTERN).parse(day);
Calendar calendar = Calendar.getInstance();
calendar.setTime(startTime);
calendar.add(Calendar.DAY_OF_MONTH, 1);
return new Date[]{startTime, calendar.getTime()};
} catch (ParseException e) {
return null;
}
}
private static String formatDay(Date date)
{
return new SimpleDateFormat(DAY_PATTERN).format(date);
}
private void setStartOfDay(Calendar calendar)
{
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}
private String buildBaseUrl(HttpServletRequest request)
{
String baseUrl = request.getScheme() + "://" + request.getServerName();
int port = request.getServerPort();
if (port != 80 && port != 443) {
baseUrl += ":" + port;
}
return baseUrl + (request.getContextPath() == null ? "" : request.getContextPath());
}
}

View File

@@ -39,6 +39,18 @@ public class CmsPublicJobFairController extends BaseController {
return getDataTable(list);
}
/**
* 查询跨域招聘会下的岗位可按联盟城市过滤cityNames 为逗号分隔的城市名称)
*/
@ApiOperation("跨域招聘会岗位列表")
@PreAuthorize("@ss.hasPermi('cms:crossCityFair:list')")
@GetMapping("/cross-domain-jobs")
public TableDataInfo crossDomainJobs(@RequestParam(required = false) String cityNames) {
startPage();
List<CrossDomainJobVO> list = publicJobFairService.selectCrossDomainJobs(cityNames);
return getDataTable(list);
}
/**
* 获取招聘会详情
*/

View File

@@ -0,0 +1,99 @@
package com.ruoyi.cms.controller.cms;
import java.util.Arrays;
import java.util.List;
import com.ruoyi.cms.domain.CrossCityAlliance;
import com.ruoyi.cms.service.ICrossCityAllianceService;
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
*
* @author ruoyi
* @date 2026-06-27
*/
@RestController
@RequestMapping("/cms/cross-city-alliance")
@Api(tags = "后台:跨域联合招聘会-联盟城市")
public class CrossCityAllianceController extends BaseController
{
@Autowired
private ICrossCityAllianceService crossCityAllianceService;
/**
* 查询联盟城市列表(支持按城市名称模糊查询)
*/
@ApiOperation("查询联盟城市列表")
@PreAuthorize("@ss.hasPermi('cms:crossCityFair:list')")
@GetMapping("/list")
public TableDataInfo list(CrossCityAlliance query)
{
startPage();
List<CrossCityAlliance> list = crossCityAllianceService.selectAllianceList(query);
return getDataTable(list);
}
/**
* 获取联盟城市详细信息
*/
@ApiOperation("获取联盟城市详细信息")
@PreAuthorize("@ss.hasPermi('cms:crossCityFair:query')")
@GetMapping("/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(crossCityAllianceService.getById(id));
}
/**
* 新增联盟城市
*/
@ApiOperation("新增联盟城市")
@PreAuthorize("@ss.hasPermi('cms:crossCityFair:add')")
@Log(title = "跨域联合招聘会-联盟城市", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody CrossCityAlliance alliance)
{
return toAjax(crossCityAllianceService.save(alliance));
}
/**
* 修改联盟城市
*/
@ApiOperation("修改联盟城市")
@PreAuthorize("@ss.hasPermi('cms:crossCityFair:edit')")
@Log(title = "跨域联合招聘会-联盟城市", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody CrossCityAlliance alliance)
{
return toAjax(crossCityAllianceService.updateById(alliance));
}
/**
* 删除联盟城市
*/
@ApiOperation("删除联盟城市")
@PreAuthorize("@ss.hasPermi('cms:crossCityFair:remove')")
@Log(title = "跨域联合招聘会-联盟城市", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(crossCityAllianceService.removeByIds(Arrays.asList(ids)));
}
}

View File

@@ -23,24 +23,31 @@ import com.ruoyi.cms.domain.Job;
import com.ruoyi.cms.domain.OutdoorFair;
import com.ruoyi.cms.domain.OutdoorFairBooth;
import com.ruoyi.cms.domain.OutdoorFairBoothBooking;
import com.ruoyi.cms.domain.OutdoorFairDevice;
import com.ruoyi.cms.domain.OutdoorFairDictDataRequest;
import com.ruoyi.cms.domain.OutdoorFairJob;
import com.ruoyi.cms.domain.VenueInfo;
import com.ruoyi.cms.mapper.FairCompanyMapper;
import com.ruoyi.cms.mapper.OutdoorFairBoothMapper;
import com.ruoyi.cms.mapper.OutdoorFairBoothBookingMapper;
import com.ruoyi.cms.mapper.OutdoorFairDeviceMapper;
import com.ruoyi.cms.mapper.OutdoorFairJobMapper;
import com.ruoyi.cms.mapper.CompanyMapper;
import com.ruoyi.cms.service.ICompanyService;
import com.ruoyi.cms.service.IJobService;
import com.ruoyi.cms.service.IOutdoorFairService;
import com.ruoyi.cms.service.IVenueInfoService;
import com.ruoyi.cms.util.RoleUtils;
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.domain.entity.Company;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -58,6 +65,8 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* 户外招聘会Controller
*
@@ -90,19 +99,27 @@ public class OutdoorFairController extends BaseController
@Autowired
private OutdoorFairJobMapper outdoorFairJobMapper;
@Autowired
private OutdoorFairDeviceMapper outdoorFairDeviceMapper;
@Autowired
private IJobService jobService;
@Autowired
private ICompanyService companyService;
/**
* 查询户外招聘会列表
*/
@ApiOperation("查询户外招聘会列表")
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:list')")
@GetMapping("/list")
public TableDataInfo list(OutdoorFair outdoorFair)
public TableDataInfo list(OutdoorFair outdoorFair, HttpServletRequest request)
{
Company company = RoleUtils.isCompanyAdmin() ? getCurrentCompanyOrNull() : null;
startPage();
List<OutdoorFair> list = outdoorFairService.selectOutdoorFairList(outdoorFair);
fillCompanyApplyState(list, request, company);
return getDataTable(list);
}
@@ -114,6 +131,9 @@ public class OutdoorFairController extends BaseController
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
if (RoleUtils.isCompanyAdmin()) {
return AjaxResult.error("企业用户无权查看招聘会详情");
}
return success(outdoorFairService.getById(id));
}
@@ -346,6 +366,9 @@ public class OutdoorFairController extends BaseController
@PostMapping
public AjaxResult add(@RequestBody OutdoorFair outdoorFair)
{
if (RoleUtils.isCompanyAdmin()) {
return AjaxResult.error("企业用户无权新增户外招聘会");
}
fillVenueFields(outdoorFair);
boolean saved = outdoorFairService.save(outdoorFair);
if (saved) {
@@ -364,6 +387,9 @@ public class OutdoorFairController extends BaseController
@PutMapping
public AjaxResult edit(@RequestBody OutdoorFair outdoorFair)
{
if (RoleUtils.isCompanyAdmin()) {
return AjaxResult.error("企业用户无权编辑户外招聘会");
}
OutdoorFair oldFair = outdoorFair.getId() == null ? null : outdoorFairService.getById(outdoorFair.getId());
fillVenueFields(outdoorFair);
boolean updated = outdoorFairService.updateById(outdoorFair);
@@ -383,6 +409,9 @@ public class OutdoorFairController extends BaseController
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
if (RoleUtils.isCompanyAdmin()) {
return AjaxResult.error("企业用户无权删除户外招聘会");
}
return toAjax(outdoorFairService.removeByIds(Arrays.asList(ids)));
}
@@ -395,23 +424,60 @@ public class OutdoorFairController extends BaseController
@PostMapping("/dict-data")
public AjaxResult addDictData(@Validated @RequestBody OutdoorFairDictDataRequest request)
{
if (RoleUtils.isCompanyAdmin()) {
return AjaxResult.error("企业用户无权维护户外招聘会字典");
}
return toAjax(outdoorFairService.insertOutdoorFairDictData(request.getDictType(), request.getDictLabel(), getUsername()));
}
@ApiOperation("企业报名户外招聘会")
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:list')")
@PostMapping("/{fairId}/company/signup")
@Transactional(rollbackFor = Exception.class)
public AjaxResult signupCompany(@PathVariable Long fairId, HttpServletRequest request)
{
Company company = getCurrentCompanyOrThrow();
ensureFairExists(fairId);
FairCompany relation = ensureFairCompany(fairId, company.getCompanyId(), "0");
Map<String, Object> data = buildCompanyQrCodeData(request, fairId, company.getCompanyId());
data.put("companyName", company.getName());
data.put("signedUp", true);
data.put("reviewStatus", relation.getReviewStatus());
data.put("reviewRemark", relation.getReviewRemark());
return success(data);
}
@ApiOperation("获取当前企业户外招聘会二维码内容")
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:list')")
@GetMapping("/{fairId}/company/qrcode")
public AjaxResult getCurrentCompanyQrCode(@PathVariable Long fairId, HttpServletRequest request)
{
Company company = getCurrentCompanyOrThrow();
ensureFairCompanyExists(fairId, company.getCompanyId());
ensureFairCompanyApprovedIfCompany(fairId, company.getCompanyId());
return success(buildCompanyQrCodeData(request, fairId, company.getCompanyId()));
}
@ApiOperation("查询户外招聘会参会企业")
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:query')")
@GetMapping("/{fairId}/companies")
public AjaxResult listCompanies(@PathVariable Long fairId, String companyName,
Integer current, Integer pageSize)
Integer current, Integer pageSize,
HttpServletRequest request)
{
List<FairCompany> relations = fairCompanyMapper.selectList(new LambdaQueryWrapper<FairCompany>()
LambdaQueryWrapper<FairCompany> relationWrapper = new LambdaQueryWrapper<FairCompany>()
.eq(FairCompany::getJobFairId, fairId)
.orderByDesc(FairCompany::getId));
.orderByDesc(FairCompany::getId);
if (RoleUtils.isCompanyAdmin()) {
Company company = getCurrentCompanyOrNull();
if (company == null) {
return emptyAjaxPage();
}
relationWrapper.eq(FairCompany::getCompanyId, company.getCompanyId());
}
List<FairCompany> relations = fairCompanyMapper.selectList(relationWrapper);
if (relations.isEmpty()) {
AjaxResult result = AjaxResult.success();
result.put("rows", new ArrayList<>());
result.put("total", 0);
return result;
return emptyAjaxPage();
}
List<Long> companyIds = relations.stream().map(FairCompany::getCompanyId).collect(Collectors.toList());
@@ -428,6 +494,11 @@ public class OutdoorFairController extends BaseController
item -> Long.valueOf(String.valueOf(item.get("companyId"))),
item -> Long.valueOf(String.valueOf(item.get("jobCount"))),
(a, b) -> a));
Map<Long, OutdoorFairDevice> deviceMap = outdoorFairDeviceMapper.selectList(new LambdaQueryWrapper<OutdoorFairDevice>()
.eq(OutdoorFairDevice::getFairId, fairId)
.isNotNull(OutdoorFairDevice::getCompanyId))
.stream()
.collect(Collectors.toMap(OutdoorFairDevice::getCompanyId, item -> item, (a, b) -> a));
List<Map<String, Object>> rows = new ArrayList<>();
for (FairCompany relation : relations) {
@@ -451,6 +522,16 @@ public class OutdoorFairController extends BaseController
row.put("boothId", booking == null ? null : booking.getBoothId());
row.put("boothNumber", booking == null ? null : booking.getBoothNumber());
row.put("jobCount", jobCountMap.getOrDefault(company.getCompanyId(), 0L));
row.put("reviewStatus", relation.getReviewStatus());
row.put("reviewBy", relation.getReviewBy());
row.put("reviewTime", relation.getReviewTime());
row.put("reviewRemark", relation.getReviewRemark());
OutdoorFairDevice device = deviceMap.get(company.getCompanyId());
String h5Url = buildOutdoorFairCompanyH5Url(request, fairId, company.getCompanyId());
row.put("deviceId", device == null ? null : device.getId());
row.put("deviceCode", device == null ? null : device.getDeviceCode());
row.put("h5Url", h5Url);
row.put("qrCodeContent", h5Url);
rows.add(row);
}
@@ -465,13 +546,30 @@ public class OutdoorFairController extends BaseController
return result;
}
@ApiOperation("分页查询户外招聘会参会岗位")
@ApiOperation("获取户外招聘会参会企业二维码内容")
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:query')")
@GetMapping("/{fairId}/companies/{companyId}/qrcode")
public AjaxResult getCompanyQrCode(@PathVariable Long fairId, @PathVariable Long companyId,
HttpServletRequest request)
{
ensureCurrentCompanyIfNeeded(companyId);
ensureFairCompanyExists(fairId, companyId);
ensureFairCompanyApprovedIfCompany(fairId, companyId);
return success(buildCompanyQrCodeData(request, fairId, companyId));
}
@ApiOperation("分页查询户外招聘会参会岗位")
@PreAuthorize("@ss.hasAnyPermi('cms:outdoorFair:list,cms:outdoorFair:query')")
@GetMapping("/{fairId}/jobs")
public AjaxResult listJobs(@PathVariable Long fairId, Long companyId, String companyName,
String jobTitle, String education, String experience,
Integer current, Integer pageSize)
{
if (RoleUtils.isCompanyAdmin()) {
Company company = getCurrentCompanyOrThrow();
companyId = company.getCompanyId();
companyName = null;
}
int page = current == null || current < 1 ? 1 : current;
int size = pageSize == null || pageSize < 1 ? 10 : Math.min(pageSize, 100);
int offset = (page - 1) * size;
@@ -491,14 +589,29 @@ public class OutdoorFairController extends BaseController
public AjaxResult getCompanyJob(@PathVariable Long fairId, @PathVariable Long jobId)
{
ensureFairJobExists(fairId, jobId);
ensureFairJobBelongsToCurrentCompanyIfNeeded(fairId, jobId);
return success(jobService.selectJobByJobId(jobId));
}
@ApiOperation("当前企业新增户外招聘会岗位")
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:list')")
@Transactional(rollbackFor = Exception.class)
@PostMapping("/{fairId}/company/jobs")
public AjaxResult addCurrentCompanyJob(@PathVariable Long fairId, @RequestBody Job job)
{
Company company = getCurrentCompanyOrThrow();
ensureFairCompanyApprovedIfCompany(fairId, company.getCompanyId());
return addCompanyJobInternal(fairId, company.getCompanyId(), job);
}
@ApiOperation("新增户外招聘会参会企业")
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:edit')")
@PostMapping("/{fairId}/companies")
public AjaxResult addCompany(@PathVariable Long fairId, @RequestBody Map<String, Object> request)
{
if (RoleUtils.isCompanyAdmin()) {
return AjaxResult.error("企业用户请使用报名入口");
}
Long companyId = Long.valueOf(String.valueOf(request.get("companyId")));
Company company = companyMapper.selectById(companyId);
if (company == null || company.getStatus() == null || company.getStatus() != 1) {
@@ -508,12 +621,36 @@ public class OutdoorFairController extends BaseController
return success();
}
@ApiOperation("审核户外招聘会参会企业")
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:edit')")
@PutMapping("/{fairId}/companies/{id}/review")
public AjaxResult reviewCompany(@PathVariable Long fairId, @PathVariable Long id,
@RequestBody Map<String, Object> request)
{
String reviewStatus = String.valueOf(request.get("reviewStatus"));
validateReviewStatus(reviewStatus);
FairCompany relation = fairCompanyMapper.selectById(id);
if (relation == null || !fairId.equals(relation.getJobFairId())) {
return AjaxResult.error("参会企业不存在");
}
String reviewRemark = request.get("reviewRemark") == null ? null : String.valueOf(request.get("reviewRemark"));
validateRejectRemark(reviewStatus, reviewRemark);
relation.setReviewStatus(reviewStatus);
relation.setReviewBy(getUsername());
relation.setReviewTime(new Date());
relation.setReviewRemark(reviewRemark);
return toAjax(fairCompanyMapper.updateById(relation));
}
@ApiOperation("移除户外招聘会参会企业")
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:edit')")
@DeleteMapping("/{fairId}/companies/{id}")
@Transactional(rollbackFor = Exception.class)
public AjaxResult removeCompany(@PathVariable Long fairId, @PathVariable Long id)
{
if (RoleUtils.isCompanyAdmin()) {
return AjaxResult.error("企业用户无权移除参会企业");
}
FairCompany relation = fairCompanyMapper.selectById(id);
if (relation == null || !fairId.equals(relation.getJobFairId())) {
return AjaxResult.error("参会企业不存在");
@@ -530,9 +667,19 @@ public class OutdoorFairController extends BaseController
@PostMapping("/{fairId}/companies/{companyId}/jobs")
public AjaxResult addCompanyJob(@PathVariable Long fairId, @PathVariable Long companyId,
@RequestBody Job job)
{
ensureCurrentCompanyIfNeeded(companyId);
ensureFairCompanyApprovedIfCompany(fairId, companyId);
return addCompanyJobInternal(fairId, companyId, job);
}
private AjaxResult addCompanyJobInternal(Long fairId, Long companyId, Job job)
{
ensureFairCompanyExists(fairId, companyId);
Company company = companyMapper.selectById(companyId);
if (company == null) {
return AjaxResult.error("企业不存在");
}
job.setCompanyId(companyId);
job.setCompanyName(company.getName());
if (job.getIsPublish() == null) {
@@ -546,6 +693,7 @@ public class OutdoorFairController extends BaseController
relation.setFairId(fairId);
relation.setCompanyId(companyId);
relation.setJobId(job.getJobId());
relation.setReviewStatus(RoleUtils.isCompanyAdmin() ? "0" : "1");
relation.setCreateBy(getUsername());
outdoorFairJobMapper.insert(relation);
return success(job);
@@ -558,6 +706,7 @@ public class OutdoorFairController extends BaseController
@RequestBody Job job)
{
ensureFairJobExists(fairId, jobId);
ensureFairJobBelongsToCurrentCompanyIfNeeded(fairId, jobId);
job.setJobId(jobId);
// 当前弹窗不修改发布状态,避免重复触发岗位发布流程。
job.setIsPublish(null);
@@ -571,12 +720,37 @@ public class OutdoorFairController extends BaseController
public AjaxResult removeCompanyJob(@PathVariable Long fairId, @PathVariable Long jobId)
{
ensureFairJobExists(fairId, jobId);
ensureFairJobBelongsToCurrentCompanyIfNeeded(fairId, jobId);
outdoorFairJobMapper.delete(new LambdaQueryWrapper<OutdoorFairJob>()
.eq(OutdoorFairJob::getFairId, fairId)
.eq(OutdoorFairJob::getJobId, jobId));
return toAjax(jobService.deleteJobByJobIds(new Long[]{jobId}));
}
@ApiOperation("审核户外招聘会岗位")
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:edit')")
@PutMapping("/{fairId}/jobs/{jobId}/review")
public AjaxResult reviewCompanyJob(@PathVariable Long fairId, @PathVariable Long jobId,
@RequestBody Map<String, Object> request)
{
String reviewStatus = String.valueOf(request.get("reviewStatus"));
validateReviewStatus(reviewStatus);
OutdoorFairJob relation = outdoorFairJobMapper.selectOne(new LambdaQueryWrapper<OutdoorFairJob>()
.eq(OutdoorFairJob::getFairId, fairId)
.eq(OutdoorFairJob::getJobId, jobId)
.last("LIMIT 1"));
if (relation == null) {
return AjaxResult.error("当前招聘会不存在该岗位");
}
String reviewRemark = request.get("reviewRemark") == null ? null : String.valueOf(request.get("reviewRemark"));
validateRejectRemark(reviewStatus, reviewRemark);
relation.setReviewStatus(reviewStatus);
relation.setReviewBy(getUsername());
relation.setReviewTime(new Date());
relation.setReviewRemark(reviewRemark);
return toAjax(outdoorFairJobMapper.updateById(relation));
}
private void ensureFairCompanyExists(Long fairId, Long companyId)
{
Long count = fairCompanyMapper.selectCount(new LambdaQueryWrapper<FairCompany>()
@@ -587,6 +761,30 @@ public class OutdoorFairController extends BaseController
}
}
private void ensureFairCompanyApprovedIfCompany(Long fairId, Long companyId)
{
if (!RoleUtils.isCompanyAdmin()) {
return;
}
FairCompany relation = fairCompanyMapper.selectOne(new LambdaQueryWrapper<FairCompany>()
.eq(FairCompany::getJobFairId, fairId)
.eq(FairCompany::getCompanyId, companyId)
.last("LIMIT 1"));
if (relation == null) {
throw new ServiceException("该企业未参加当前招聘会");
}
if (!"1".equals(relation.getReviewStatus())) {
throw new ServiceException("报名审核通过后才能操作");
}
}
private void ensureFairExists(Long fairId)
{
if (fairId == null || outdoorFairService.getById(fairId) == null) {
throw new ServiceException("户外招聘会不存在");
}
}
private void ensureFairJobExists(Long fairId, Long jobId)
{
Long count = outdoorFairJobMapper.selectCount(new LambdaQueryWrapper<OutdoorFairJob>()
@@ -597,18 +795,171 @@ public class OutdoorFairController extends BaseController
}
}
private void ensureFairJobBelongsToCurrentCompanyIfNeeded(Long fairId, Long jobId)
{
if (!RoleUtils.isCompanyAdmin()) {
return;
}
Company company = getCurrentCompanyOrThrow();
Long count = outdoorFairJobMapper.selectCount(new LambdaQueryWrapper<OutdoorFairJob>()
.eq(OutdoorFairJob::getFairId, fairId)
.eq(OutdoorFairJob::getJobId, jobId)
.eq(OutdoorFairJob::getCompanyId, company.getCompanyId()));
if (count == null || count == 0) {
throw new ServiceException("只能维护本企业报名岗位");
}
}
private void ensureCurrentCompanyIfNeeded(Long companyId)
{
if (!RoleUtils.isCompanyAdmin()) {
return;
}
Company company = getCurrentCompanyOrThrow();
if (!company.getCompanyId().equals(companyId)) {
throw new ServiceException("只能维护本企业报名信息");
}
}
private Company getCurrentCompanyOrThrow()
{
Company company = getCurrentCompanyOrNull();
if (company == null) {
throw new ServiceException("未查询到当前登录企业信息");
}
return company;
}
private Company getCurrentCompanyOrNull()
{
if (!RoleUtils.isCompanyAdmin()) {
return null;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser == null || loginUser.getUser() == null) {
return null;
}
SysUser sysUser = loginUser.getUser();
Company company = null;
if (StringUtils.isNotBlank(sysUser.getIdCard())) {
company = companyService.queryCodeCompany(sysUser.getIdCard());
if (company != null) {
return company;
}
}
Long userId = loginUser.getUserId() == null ? sysUser.getUserId() : loginUser.getUserId();
if (userId != null) {
company = companyMapper.selectOne(new LambdaQueryWrapper<Company>()
.eq(Company::getUserId, userId)
.eq(Company::getDelFlag, "0")
.orderByDesc(Company::getUpdateTime)
.last("LIMIT 1"));
if (company != null) {
return company;
}
}
List<String> companyNames = new ArrayList<>();
if (StringUtils.isNotBlank(sysUser.getNickName())) {
companyNames.add(sysUser.getNickName());
}
if (StringUtils.isNotBlank(sysUser.getUserName()) && !companyNames.contains(sysUser.getUserName())) {
companyNames.add(sysUser.getUserName());
}
if (!companyNames.isEmpty()) {
List<Company> companies = companyMapper.selectList(new LambdaQueryWrapper<Company>()
.in(Company::getName, companyNames)
.eq(Company::getStatus, 1)
.eq(Company::getDelFlag, "0")
.orderByDesc(Company::getUpdateTime));
if (companies.size() == 1) {
return companies.get(0);
}
}
return null;
}
private void fillCompanyApplyState(List<OutdoorFair> list, HttpServletRequest request, Company company)
{
if (!RoleUtils.isCompanyAdmin() || list == null || list.isEmpty()) {
return;
}
if (company == null) {
for (OutdoorFair fair : list) {
fair.setSignedUp(false);
}
return;
}
List<Long> fairIds = list.stream().map(OutdoorFair::getId).collect(Collectors.toList());
Map<Long, FairCompany> relationMap = fairCompanyMapper.selectList(new LambdaQueryWrapper<FairCompany>()
.in(FairCompany::getJobFairId, fairIds)
.eq(FairCompany::getCompanyId, company.getCompanyId()))
.stream()
.collect(Collectors.toMap(FairCompany::getJobFairId, item -> item, (a, b) -> a));
for (OutdoorFair fair : list) {
FairCompany relation = relationMap.get(fair.getId());
boolean signedUp = relation != null;
fair.setCompanyId(company.getCompanyId());
fair.setCompanyName(company.getName());
fair.setSignedUp(signedUp);
fair.setReviewStatus(relation == null ? null : relation.getReviewStatus());
fair.setReviewRemark(relation == null ? null : relation.getReviewRemark());
if (signedUp) {
String h5Url = buildOutdoorFairCompanyH5Url(request, fair.getId(), company.getCompanyId());
fair.setH5Url(h5Url);
fair.setQrCodeContent(h5Url);
}
}
}
private AjaxResult emptyAjaxPage()
{
AjaxResult result = AjaxResult.success();
result.put("rows", new ArrayList<>());
result.put("total", 0);
return result;
}
private void ensureFairCompany(Long fairId, Long companyId)
{
Long count = fairCompanyMapper.selectCount(new LambdaQueryWrapper<FairCompany>()
ensureFairCompany(fairId, companyId, "1");
}
private FairCompany ensureFairCompany(Long fairId, Long companyId, String reviewStatus)
{
FairCompany existing = fairCompanyMapper.selectOne(new LambdaQueryWrapper<FairCompany>()
.eq(FairCompany::getJobFairId, fairId)
.eq(FairCompany::getCompanyId, companyId));
if (count != null && count > 0) {
return;
.eq(FairCompany::getCompanyId, companyId)
.last("LIMIT 1"));
if (existing != null) {
if (StringUtils.isBlank(existing.getReviewStatus())) {
existing.setReviewStatus(reviewStatus);
fairCompanyMapper.updateById(existing);
}
return existing;
}
FairCompany fairCompany = new FairCompany();
fairCompany.setJobFairId(fairId);
fairCompany.setCompanyId(companyId);
fairCompany.setReviewStatus(reviewStatus);
fairCompanyMapper.insert(fairCompany);
return fairCompany;
}
private void validateReviewStatus(String reviewStatus)
{
if (!"0".equals(reviewStatus) && !"1".equals(reviewStatus) && !"2".equals(reviewStatus)) {
throw new ServiceException("审核状态不正确");
}
}
private void validateRejectRemark(String reviewStatus, String reviewRemark)
{
if ("2".equals(reviewStatus) && StringUtils.isBlank(reviewRemark)) {
throw new ServiceException("驳回时请填写原因");
}
}
private void resetBoothSnapshot(OutdoorFair outdoorFair, boolean forceRecreate)
@@ -640,4 +991,32 @@ public class OutdoorFairController extends BaseController
outdoorFair.setBoothCount(0);
}
}
private String buildOutdoorFairCompanyH5Url(HttpServletRequest request, Long fairId, Long companyId)
{
String baseUrl = request.getScheme() + "://" + request.getServerName();
int port = request.getServerPort();
if (port != 80 && port != 443) {
baseUrl += ":" + port;
}
String contextPath = request.getContextPath() == null ? "" : request.getContextPath();
return baseUrl + contextPath + "/h5/outdoor-fair/company.html?fairId=" + fairId + "&companyId=" + companyId;
}
private Map<String, Object> buildCompanyQrCodeData(HttpServletRequest request, Long fairId, Long companyId)
{
OutdoorFairDevice device = outdoorFairDeviceMapper.selectOne(new LambdaQueryWrapper<OutdoorFairDevice>()
.eq(OutdoorFairDevice::getFairId, fairId)
.eq(OutdoorFairDevice::getCompanyId, companyId)
.last("LIMIT 1"));
String h5Url = buildOutdoorFairCompanyH5Url(request, fairId, companyId);
Map<String, Object> data = new HashMap<>();
data.put("fairId", fairId);
data.put("companyId", companyId);
data.put("deviceId", device == null ? null : device.getId());
data.put("deviceCode", device == null ? null : device.getDeviceCode());
data.put("h5Url", h5Url);
data.put("qrCodeContent", h5Url);
return data;
}
}

View File

@@ -63,20 +63,21 @@ public class OutdoorFairDeviceController extends BaseController
}
/**
* 批量生成设备码UUID
* 请求体:{ fairId, quantity }
* 新增设备码(由用户手动填写设备码,可选同时绑定参会企业
* 请求体:{ fairId, deviceCode, companyId? }
*/
@ApiOperation("批量生成设备码")
@ApiOperation("新增设备码")
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:add')")
@Log(title = "户外招聘会设备码", businessType = BusinessType.INSERT)
@PostMapping("/batch")
public AjaxResult batch(@RequestBody Map<String, Object> request)
@PostMapping("/add")
public AjaxResult add(@RequestBody Map<String, Object> request)
{
Long fairId = request.get("fairId") == null ? null : Long.valueOf(String.valueOf(request.get("fairId")));
Integer quantity = request.get("quantity") == null ? null : Integer.valueOf(String.valueOf(request.get("quantity")));
List<OutdoorFairDevice> devices = outdoorFairDeviceService.batchGenerate(fairId, quantity);
AjaxResult result = AjaxResult.success("生成成功");
result.put("data", devices);
String deviceCode = request.get("deviceCode") == null ? null : String.valueOf(request.get("deviceCode")).trim();
Long companyId = request.get("companyId") == null ? null : Long.valueOf(String.valueOf(request.get("companyId")));
OutdoorFairDevice device = outdoorFairDeviceService.addDevice(fairId, deviceCode, companyId);
AjaxResult result = AjaxResult.success("新增成功");
result.put("data", device);
return result;
}

View File

@@ -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 com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
/**
* 跨域联合招聘会-联盟城市。
*/
@Data
@TableName("shz.cms_cross_city_alliance")
public class CrossCityAlliance extends BaseEntity
{
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/** 城市名称 */
private String name;
}

View File

@@ -9,6 +9,8 @@ import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseEntity;
import java.util.Date;
/**
* 公司招聘会关联对象 fair_company
* @author lishundong
@@ -34,4 +36,16 @@ public class FairCompany extends BaseEntity
@ApiModelProperty("招聘会id")
private Long jobFairId;
@ApiModelProperty("审核状态 0待审核 1通过 2驳回")
private String reviewStatus;
@ApiModelProperty("审核人")
private String reviewBy;
@ApiModelProperty("审核时间")
private Date reviewTime;
@ApiModelProperty("审核备注")
private String reviewRemark;
}

View File

@@ -202,6 +202,19 @@ public class Job extends BaseEntity
@ApiModelProperty("审核状态")
private String reviewStatus;
@TableField(exist = false)
@ApiModelProperty("户外招聘会岗位审核状态")
private String fairReviewStatus;
@TableField(exist = false)
@ApiModelProperty("户外招聘会岗位审核备注")
private String fairReviewRemark;
@TableField(exist = false)
@ApiModelProperty("户外招聘会岗位审核时间")
private String fairReviewTime;
//简历是否被查看
@TableField(exist = false)
private String isView;

View File

@@ -3,6 +3,7 @@ package com.ruoyi.cms.domain;
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;
@@ -88,4 +89,32 @@ public class OutdoorFair extends BaseEntity
@Excel(name = "招聘会照片")
@ApiModelProperty("招聘会照片")
private String photoUrl;
@TableField(exist = false)
@ApiModelProperty("当前企业ID")
private Long companyId;
@TableField(exist = false)
@ApiModelProperty("当前企业名称")
private String companyName;
@TableField(exist = false)
@ApiModelProperty("当前企业是否已报名")
private Boolean signedUp;
@TableField(exist = false)
@ApiModelProperty("当前企业公共H5页面链接")
private String h5Url;
@TableField(exist = false)
@ApiModelProperty("当前企业二维码内容")
private String qrCodeContent;
@TableField(exist = false)
@ApiModelProperty("当前企业报名审核状态")
private String reviewStatus;
@TableField(exist = false)
@ApiModelProperty("当前企业报名审核备注")
private String reviewRemark;
}

View File

@@ -1,11 +1,15 @@
package com.ruoyi.cms.domain;
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;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
/**
* 户外招聘会岗位关联。
*/
@@ -21,4 +25,20 @@ public class OutdoorFairJob extends BaseEntity
private Long companyId;
private Long jobId;
/** 审核状态 0待审核 1通过 2驳回。 */
private String reviewStatus;
private String reviewBy;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date reviewTime;
private String reviewRemark;
@TableField(exist = false)
private String companyName;
@TableField(exist = false)
private String jobTitle;
}

View File

@@ -0,0 +1,65 @@
package com.ruoyi.cms.domain.rc;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 跨域招聘会岗位视图(聚合 public_job_fair -> public_job_fair_job -> job -> company
*/
@Data
@ApiModel("跨域招聘会岗位")
public class CrossDomainJobVO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("岗位ID")
private Long jobId;
@ApiModelProperty("岗位名称")
private String jobTitle;
@ApiModelProperty("最低薪资")
private Integer minSalary;
@ApiModelProperty("最高薪资")
private Integer maxSalary;
@ApiModelProperty("学历要求")
private String education;
@ApiModelProperty("经验要求")
private String experience;
@ApiModelProperty("招聘人数")
private Integer vacancies;
@JsonFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty("发布日期")
private Date postingDate;
@ApiModelProperty("企业ID")
private Long companyId;
@ApiModelProperty("企业名称")
private String companyName;
@ApiModelProperty("行业")
private String industry;
@ApiModelProperty("企业规模")
private String scale;
@ApiModelProperty("招聘会ID")
private String jobFairId;
@ApiModelProperty("招聘会标题")
private String jobFairTitle;
@ApiModelProperty("跨域联盟城市(逗号分隔)")
private String crossDomainCities;
}

View File

@@ -151,6 +151,12 @@ public class PublicJobFair implements Serializable {
@ApiModelProperty("招聘会类别")
private String jobFairCategory;
@ApiModelProperty("是否跨域Y-是 N-否)")
private String isCrossDomain;
@ApiModelProperty("跨域联盟城市(逗号分隔的城市名称)")
private String crossDomainCities;
@ApiModelProperty("纬度")
private java.math.BigDecimal latitude;

View File

@@ -0,0 +1,11 @@
package com.ruoyi.cms.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.cms.domain.CrossCityAlliance;
/**
* 跨域联合招聘会-联盟城市 Mapper。
*/
public interface CrossCityAllianceMapper extends BaseMapper<CrossCityAlliance>
{
}

View File

@@ -32,6 +32,11 @@ public interface PublicJobFairMapper extends BaseMapper<PublicJobFair> {
*/
List<Job> selectJobListByJobFairIdAndCompanyId(@Param("jobFairId") String jobFairId, @Param("companyId") Long companyId);
/**
* 查询跨域招聘会下的岗位可按联盟城市过滤cityNames 为逗号分隔的城市名称)
*/
List<CrossDomainJobVO> selectCrossDomainJobs(@Param("cityNames") String cityNames);
/**
* 检查用户是否已报名
*/

View File

@@ -0,0 +1,17 @@
package com.ruoyi.cms.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.cms.domain.CrossCityAlliance;
import java.util.List;
/**
* 跨域联合招聘会-联盟城市 Service。
*/
public interface ICrossCityAllianceService extends IService<CrossCityAlliance>
{
/**
* 查询联盟城市列表(支持按城市名称模糊查询)。
*/
List<CrossCityAlliance> selectAllianceList(CrossCityAlliance query);
}

View File

@@ -16,13 +16,14 @@ public interface IOutdoorFairDeviceService extends IService<OutdoorFairDevice>
List<OutdoorFairDevice> selectDeviceList(OutdoorFairDevice query);
/**
* 批量生成设备码UUID)。
* 新增设备码(由用户手动填写设备码,可选同时绑定参会企业)。
*
* @param fairId 招聘会ID
* @param quantity 生成数量
* @return 已生成的设备码列表
* @param fairId 招聘会ID
* @param deviceCode 设备码(全局唯一)
* @param companyId 参会企业ID为空表示暂不绑定
* @return 新增的设备码
*/
List<OutdoorFairDevice> batchGenerate(Long fairId, Integer quantity);
OutdoorFairDevice addDevice(Long fairId, String deviceCode, Long companyId);
/**
* 绑定/解绑参会企业companyId 为空表示解绑)。

View File

@@ -0,0 +1,29 @@
package com.ruoyi.cms.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.cms.domain.CrossCityAlliance;
import com.ruoyi.cms.mapper.CrossCityAllianceMapper;
import com.ruoyi.cms.service.ICrossCityAllianceService;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 跨域联合招聘会-联盟城市 Service 实现。
*/
@Service
public class CrossCityAllianceServiceImpl
extends ServiceImpl<CrossCityAllianceMapper, CrossCityAlliance>
implements ICrossCityAllianceService
{
@Override
public List<CrossCityAlliance> selectAllianceList(CrossCityAlliance query)
{
LambdaQueryWrapper<CrossCityAlliance> wrapper = new LambdaQueryWrapper<>();
wrapper.like(StringUtils.isNotBlank(query.getName()), CrossCityAlliance::getName, query.getName());
wrapper.orderByAsc(CrossCityAlliance::getId);
return list(wrapper);
}
}

View File

@@ -15,10 +15,8 @@ import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* 户外招聘会设备码 Service 实现。
@@ -47,28 +45,45 @@ public class OutdoorFairDeviceServiceImpl
}
@Override
public List<OutdoorFairDevice> batchGenerate(Long fairId, Integer quantity)
public OutdoorFairDevice addDevice(Long fairId, String deviceCode, Long companyId)
{
if (fairId == null) {
throw new ServiceException("招聘会ID不能为空");
}
int count = quantity == null ? 0 : quantity;
if (count <= 0) {
throw new ServiceException("生成数量必须大于0");
if (StringUtils.isBlank(deviceCode)) {
throw new ServiceException("设备码不能为空");
}
if (count > 1000) {
throw new ServiceException("单次生成数量不能超过1000");
// 设备码全局唯一H5 端按设备码查询)
Long exists = baseMapper.selectCount(new LambdaQueryWrapper<OutdoorFairDevice>()
.eq(OutdoorFairDevice::getDeviceCode, deviceCode));
if (exists != null && exists > 0) {
throw new ServiceException("设备码已存在");
}
List<OutdoorFairDevice> devices = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
OutdoorFairDevice device = new OutdoorFairDevice();
device.setFairId(fairId);
// 去掉中划线,得到 32 位十六进制设备码
device.setDeviceCode(UUID.randomUUID().toString().replace("-", ""));
devices.add(device);
OutdoorFairDevice device = new OutdoorFairDevice();
device.setFairId(fairId);
device.setDeviceCode(deviceCode);
if (companyId != null) {
// 仅允许绑定已参加当前招聘会的企业
Long count = fairCompanyMapper.selectCount(new LambdaQueryWrapper<FairCompany>()
.eq(FairCompany::getJobFairId, fairId)
.eq(FairCompany::getCompanyId, companyId));
if (count == null || count == 0) {
throw new ServiceException("该企业未参加当前招聘会");
}
// 同一招聘会下,一个企业只能绑定一个设备码
Long bound = baseMapper.selectCount(new LambdaQueryWrapper<OutdoorFairDevice>()
.eq(OutdoorFairDevice::getFairId, fairId)
.eq(OutdoorFairDevice::getCompanyId, companyId));
if (bound != null && bound > 0) {
throw new ServiceException("该企业已绑定其他设备码");
}
Company company = companyMapper.selectById(companyId);
device.setCompanyId(companyId);
device.setCompanyName(company == null ? null : company.getName());
device.setBindTime(new Date());
}
saveBatch(devices);
return devices;
save(device);
return device;
}
@Override

View File

@@ -100,4 +100,9 @@ public interface IPublicJobFairService {
* 查询招聘会报名列表
*/
List<JobFairSignUpVO> selectSignUpList(String jobFairId);
/**
* 查询跨域招聘会下的岗位可按联盟城市过滤cityNames 为逗号分隔的城市名称)
*/
List<CrossDomainJobVO> selectCrossDomainJobs(String cityNames);
}

View File

@@ -219,4 +219,9 @@ public class PublicJobFairServiceImpl implements IPublicJobFairService {
public List<JobFairSignUpVO> selectSignUpList(String jobFairId) {
return publicJobFairMapper.selectSignUpListByJobFairId(jobFairId);
}
@Override
public List<CrossDomainJobVO> selectCrossDomainJobs(String cityNames) {
return publicJobFairMapper.selectCrossDomainJobs(cityNames);
}
}