Merge branch 'main' of http://124.243.245.42:3000/zkr/shz-backend into main
This commit is contained in:
10
.gitignore
vendored
10
.gitignore
vendored
@@ -45,4 +45,12 @@ nbdist/
|
||||
!*/build/*.java
|
||||
!*/build/*.html
|
||||
!*/build/*.xml
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
|
||||
# Local credentials for project-scoped Codex skills
|
||||
.codex/skills/*/.password
|
||||
|
||||
# Local application runtime files
|
||||
.local/
|
||||
.codex/
|
||||
local.sh
|
||||
10
pom.xml
10
pom.xml
@@ -33,6 +33,7 @@
|
||||
<mybatis-plus.version>3.5.1</mybatis-plus.version>
|
||||
<qiniu.version>7.19.0</qiniu.version>
|
||||
<aliyun.oss.version>2.5.0</aliyun.oss.version>
|
||||
<lombok.version>1.18.34</lombok.version>
|
||||
<qcloud.cos.version>5.5.9</qcloud.cos.version>
|
||||
</properties>
|
||||
|
||||
@@ -129,6 +130,13 @@
|
||||
<version>${velocity.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Lombok (强制升级以兼容 Java 21) -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里JSON解析器 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
@@ -228,7 +236,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.ruoyi.cms.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
|
||||
/**
|
||||
* 面试菜单权限自动迁移
|
||||
* 应用启动后自动检查并添加面试列表菜单及按钮权限到 sys_menu 和 sys_role_menu 表
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class InterviewMenuMigration {
|
||||
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
public void migrate() {
|
||||
log.info("开始检查面试菜单权限...");
|
||||
try (Connection conn = dataSource.getConnection()) {
|
||||
// Step 1: 查找岗位管理目录的 menu_id
|
||||
Long parentId = null;
|
||||
try (Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery(
|
||||
"SELECT menu_id FROM sys_menu WHERE path = 'management' AND menu_type = 'M' LIMIT 1")) {
|
||||
if (rs.next()) {
|
||||
parentId = rs.getLong("menu_id");
|
||||
}
|
||||
}
|
||||
|
||||
if (parentId == null) {
|
||||
log.warn("未找到 management 目录菜单,跳过面试菜单迁移");
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("找到 management 目录菜单,parent_id={}", parentId);
|
||||
|
||||
// Step 2: 插入面试列表菜单(幂等)
|
||||
Long menuId = insertMenuIfNotExists(conn, 2100L, "面试列表", parentId, 10,
|
||||
"interview-list", "Management/InterviewList", "InterviewList",
|
||||
"C", "cms:interview:list", "message");
|
||||
|
||||
if (menuId == null) {
|
||||
log.warn("面试列表菜单插入失败(可能已存在但 parent_id 不同)");
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 3: 插入按钮权限
|
||||
insertMenuIfNotExists(conn, 2101L, "面试查询", menuId, 1,
|
||||
"", "", "", "F", "cms:interview:query", "#");
|
||||
insertMenuIfNotExists(conn, 2102L, "面试新增", menuId, 2,
|
||||
"", "", "", "F", "cms:interview:add", "#");
|
||||
insertMenuIfNotExists(conn, 2103L, "面试修改", menuId, 3,
|
||||
"", "", "", "F", "cms:interview:edit", "#");
|
||||
insertMenuIfNotExists(conn, 2104L, "面试删除", menuId, 4,
|
||||
"", "", "", "F", "cms:interview:remove", "#");
|
||||
|
||||
// Step 4: 将新菜单赋给所有非管理员角色
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.execute(
|
||||
"INSERT INTO sys_role_menu (role_id, menu_id) " +
|
||||
"SELECT r.role_id, " + menuId + " FROM sys_role r " +
|
||||
"WHERE r.role_key != 'admin' " +
|
||||
"AND NOT EXISTS (SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = r.role_id AND rm.menu_id = " + menuId + ")");
|
||||
} catch (Exception e) {
|
||||
log.debug("角色菜单关联已存在或插入失败: {}", e.getMessage());
|
||||
}
|
||||
|
||||
// 按钮也赋给角色
|
||||
for (long btnId : new long[]{2101L, 2102L, 2103L, 2104L}) {
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.execute(
|
||||
"INSERT INTO sys_role_menu (role_id, menu_id) " +
|
||||
"SELECT r.role_id, " + btnId + " FROM sys_role r " +
|
||||
"WHERE r.role_key != 'admin' " +
|
||||
"AND NOT EXISTS (SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = r.role_id AND rm.menu_id = " + btnId + ")");
|
||||
} catch (Exception e) {
|
||||
log.debug("按钮角色关联已存在: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
log.info("面试菜单权限迁移完成");
|
||||
} catch (Exception e) {
|
||||
log.error("面试菜单迁移失败: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 幂等插入菜单记录
|
||||
*/
|
||||
private Long insertMenuIfNotExists(Connection conn, Long menuId, String menuName,
|
||||
Long parentId, int orderNum, String path,
|
||||
String component, String routeName,
|
||||
String menuType, String perms, String icon) {
|
||||
try {
|
||||
// 检查是否已存在
|
||||
try (PreparedStatement ps = conn.prepareStatement(
|
||||
"SELECT 1 FROM sys_menu WHERE menu_id = ?")) {
|
||||
ps.setLong(1, menuId);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
log.debug("菜单已存在: {} (id={})", menuName, menuId);
|
||||
return menuId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 插入新菜单
|
||||
try (PreparedStatement ps = conn.prepareStatement(
|
||||
"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) " +
|
||||
"VALUES (?, ?, ?, ?, ?, ?, '', ?, 1, 0, ?, '0', '0', ?, ?, 'admin', CURRENT_TIMESTAMP)")) {
|
||||
ps.setLong(1, menuId);
|
||||
ps.setString(2, menuName);
|
||||
ps.setLong(3, parentId);
|
||||
ps.setInt(4, orderNum);
|
||||
ps.setString(5, path);
|
||||
ps.setString(6, component);
|
||||
ps.setString(7, routeName);
|
||||
ps.setString(8, menuType);
|
||||
ps.setString(9, perms);
|
||||
ps.setString(10, icon);
|
||||
ps.executeUpdate();
|
||||
log.info("菜单创建成功: {} (id={}, perms={})", menuName, menuId, perms);
|
||||
return menuId;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("菜单创建失败: {} (id={}), error={}", menuName, menuId, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.BufferedReader;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -67,7 +69,32 @@ public class AppInterviewController extends BaseController {
|
||||
*/
|
||||
@ApiOperation("更新面试邀约状态")
|
||||
@PutMapping("/status/{id}")
|
||||
public AjaxResult updateStatus(@PathVariable Long id, @RequestParam String status){
|
||||
public AjaxResult updateStatus(@PathVariable Long id, HttpServletRequest request) {
|
||||
String status = request.getParameter("status");
|
||||
// 如果 URL 参数没有,尝试从 JSON body 中读取
|
||||
if (status == null || status.isEmpty()) {
|
||||
try {
|
||||
BufferedReader reader = request.getReader();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
String body = sb.toString();
|
||||
if (body != null && !body.isEmpty()) {
|
||||
// 简单解析 JSON: {"status": "accepted"}
|
||||
status = body.replaceAll(".*\"status\"\\s*:\\s*\"([^\"]+)\".*", "$1");
|
||||
if (status.equals(body)) {
|
||||
status = null;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// ignore body read errors
|
||||
}
|
||||
}
|
||||
if (status == null || status.isEmpty()) {
|
||||
return AjaxResult.error("状态参数不能为空");
|
||||
}
|
||||
int rows = interviewInvitationService.updateInterviewStatus(id, status);
|
||||
if (rows > 0 && "accepted".equals(status)) {
|
||||
// 接受时返回面试官联系方式,供前端弹窗展示
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ruoyi.cms.controller.cms;
|
||||
|
||||
import com.ruoyi.cms.domain.InterviewInvitation;
|
||||
import com.ruoyi.cms.domain.vo.InterviewInvitationVO;
|
||||
import com.ruoyi.cms.service.InterviewInvitationService;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
@@ -38,7 +39,7 @@ public class CmsInterviewController extends BaseController {
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(InterviewInvitation interviewInvitation){
|
||||
startPage();
|
||||
List<InterviewInvitation> list = interviewInvitationService.getInterviewInvitationList(interviewInvitation);
|
||||
List<InterviewInvitationVO> list = interviewInvitationService.getInterviewInvitationVOList(interviewInvitation);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.ruoyi.cms.controller.cms;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.cms.domain.OutdoorFair;
|
||||
import com.ruoyi.cms.domain.OutdoorFairDictDataRequest;
|
||||
import com.ruoyi.cms.domain.VenueInfo;
|
||||
import com.ruoyi.cms.service.IOutdoorFairService;
|
||||
import com.ruoyi.cms.service.IVenueInfoService;
|
||||
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 com.ruoyi.common.exception.ServiceException;
|
||||
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.validation.annotation.Validated;
|
||||
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-25
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/cms/outdoor-fair")
|
||||
@Api(tags = "后台:户外招聘会")
|
||||
public class OutdoorFairController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IOutdoorFairService outdoorFairService;
|
||||
|
||||
@Autowired
|
||||
private IVenueInfoService venueInfoService;
|
||||
|
||||
/**
|
||||
* 查询户外招聘会列表
|
||||
*/
|
||||
@ApiOperation("查询户外招聘会列表")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(OutdoorFair outdoorFair)
|
||||
{
|
||||
startPage();
|
||||
List<OutdoorFair> list = outdoorFairService.selectOutdoorFairList(outdoorFair);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取户外招聘会详细信息
|
||||
*/
|
||||
@ApiOperation("获取户外招聘会详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(outdoorFairService.getById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增户外招聘会
|
||||
*/
|
||||
@ApiOperation("新增户外招聘会")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:add')")
|
||||
@Log(title = "户外招聘会", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody OutdoorFair outdoorFair)
|
||||
{
|
||||
fillVenueFields(outdoorFair);
|
||||
return toAjax(outdoorFairService.save(outdoorFair));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改户外招聘会
|
||||
*/
|
||||
@ApiOperation("修改户外招聘会")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:edit')")
|
||||
@Log(title = "户外招聘会", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody OutdoorFair outdoorFair)
|
||||
{
|
||||
fillVenueFields(outdoorFair);
|
||||
return toAjax(outdoorFairService.updateById(outdoorFair));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除户外招聘会
|
||||
*/
|
||||
@ApiOperation("删除户外招聘会")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:remove')")
|
||||
@Log(title = "户外招聘会", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(outdoorFairService.removeByIds(Arrays.asList(ids)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增户外招聘会页面使用的字典项
|
||||
*/
|
||||
@ApiOperation("新增户外招聘会字典项")
|
||||
@PreAuthorize("@ss.hasAnyPermi('cms:outdoorFair:add,cms:outdoorFair:edit')")
|
||||
@Log(title = "户外招聘会字典项", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/dict-data")
|
||||
public AjaxResult addDictData(@Validated @RequestBody OutdoorFairDictDataRequest request)
|
||||
{
|
||||
return toAjax(outdoorFairService.insertOutdoorFairDictData(request.getDictType(), request.getDictLabel(), getUsername()));
|
||||
}
|
||||
|
||||
private void fillVenueFields(OutdoorFair outdoorFair)
|
||||
{
|
||||
if (outdoorFair.getVenueId() == null) {
|
||||
return;
|
||||
}
|
||||
VenueInfo venueInfo = venueInfoService.getById(outdoorFair.getVenueId());
|
||||
if (venueInfo == null) {
|
||||
throw new ServiceException("绑定场地不存在");
|
||||
}
|
||||
outdoorFair.setVenueName(venueInfo.getVenueName());
|
||||
outdoorFair.setBoothCount(venueInfo.getFloorCount() == null ? 0 : venueInfo.getFloorCount());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
package com.ruoyi.cms.controller.cms;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.ruoyi.cms.domain.VenueInfo;
|
||||
import com.ruoyi.cms.domain.OutdoorFair;
|
||||
import com.ruoyi.cms.domain.OutdoorFairBoothBooking;
|
||||
import com.ruoyi.cms.domain.VenueBooth;
|
||||
import com.ruoyi.cms.domain.VenueInfoDictDataRequest;
|
||||
import com.ruoyi.cms.domain.VenueBoothSwapRequest;
|
||||
import com.ruoyi.cms.mapper.CompanyMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairBoothBookingMapper;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairMapper;
|
||||
import com.ruoyi.cms.mapper.VenueBoothMapper;
|
||||
import com.ruoyi.cms.service.IVenueInfoService;
|
||||
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.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
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.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
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-25
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/cms/venue-info")
|
||||
@Api(tags = "后台:场地信息维护")
|
||||
public class VenueInfoController extends BaseController
|
||||
{
|
||||
@Autowired
|
||||
private IVenueInfoService venueInfoService;
|
||||
|
||||
@Autowired
|
||||
private VenueBoothMapper venueBoothMapper;
|
||||
|
||||
@Autowired
|
||||
private OutdoorFairMapper outdoorFairMapper;
|
||||
|
||||
@Autowired
|
||||
private OutdoorFairBoothBookingMapper outdoorFairBoothBookingMapper;
|
||||
|
||||
@Autowired
|
||||
private CompanyMapper companyMapper;
|
||||
|
||||
/**
|
||||
* 查询场地信息列表
|
||||
*/
|
||||
@ApiOperation("查询场地信息列表")
|
||||
@PreAuthorize("@ss.hasPermi('cms:venueInfo:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(VenueInfo venueInfo)
|
||||
{
|
||||
startPage();
|
||||
List<VenueInfo> list = venueInfoService.selectVenueInfoList(venueInfo);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取场地信息详细信息
|
||||
*/
|
||||
@ApiOperation("获取场地信息详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('cms:venueInfo:query')")
|
||||
@GetMapping(value = "/{id}")
|
||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||
{
|
||||
return success(venueInfoService.getById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增场地信息
|
||||
*/
|
||||
@ApiOperation("新增场地信息")
|
||||
@PreAuthorize("@ss.hasPermi('cms:venueInfo:add')")
|
||||
@Log(title = "场地信息", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody VenueInfo venueInfo)
|
||||
{
|
||||
fillHandleFields(venueInfo);
|
||||
return toAjax(venueInfoService.save(venueInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改场地信息
|
||||
*/
|
||||
@ApiOperation("修改场地信息")
|
||||
@PreAuthorize("@ss.hasPermi('cms:venueInfo:edit')")
|
||||
@Log(title = "场地信息", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody VenueInfo venueInfo)
|
||||
{
|
||||
fillHandleFields(venueInfo);
|
||||
return toAjax(venueInfoService.updateById(venueInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除场地信息
|
||||
*/
|
||||
@ApiOperation("删除场地信息")
|
||||
@PreAuthorize("@ss.hasPermi('cms:venueInfo:remove')")
|
||||
@Log(title = "场地信息", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
{
|
||||
return toAjax(venueInfoService.removeByIds(Arrays.asList(ids)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增场地信息维护页面使用的字典项
|
||||
*/
|
||||
@ApiOperation("新增场地信息字典项")
|
||||
@PreAuthorize("@ss.hasAnyPermi('cms:venueInfo:add,cms:venueInfo:edit')")
|
||||
@Log(title = "场地信息字典项", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/dict-data")
|
||||
public AjaxResult addDictData(@Validated @RequestBody VenueInfoDictDataRequest request)
|
||||
{
|
||||
return toAjax(venueInfoService.insertVenueInfoDictData(request.getDictType(), request.getDictLabel(), getUsername()));
|
||||
}
|
||||
|
||||
@ApiOperation("查询场地展位图")
|
||||
@PreAuthorize("@ss.hasAnyPermi('cms:venueInfo:query,cms:outdoorFair:query')")
|
||||
@GetMapping("/{venueId}/booths")
|
||||
public AjaxResult listBooths(@PathVariable Long venueId)
|
||||
{
|
||||
List<VenueBooth> list = venueBoothMapper.selectList(new LambdaQueryWrapper<VenueBooth>()
|
||||
.eq(VenueBooth::getVenueId, venueId)
|
||||
.orderByAsc(VenueBooth::getPositionY)
|
||||
.orderByAsc(VenueBooth::getPositionX)
|
||||
.orderByAsc(VenueBooth::getBoothNumber));
|
||||
return success(list);
|
||||
}
|
||||
|
||||
@ApiOperation("保存场地展位图")
|
||||
@PreAuthorize("@ss.hasPermi('cms:venueInfo:edit')")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@PostMapping("/{venueId}/booths")
|
||||
public AjaxResult saveBooths(@PathVariable Long venueId, @RequestBody List<VenueBooth> booths)
|
||||
{
|
||||
venueBoothMapper.physicalDeleteDeletedByVenueId(venueId);
|
||||
List<VenueBooth> existingBooths = venueBoothMapper.selectList(new LambdaQueryWrapper<VenueBooth>()
|
||||
.eq(VenueBooth::getVenueId, venueId));
|
||||
Map<Long, VenueBooth> existingById = existingBooths.stream()
|
||||
.filter(item -> item.getId() != null)
|
||||
.collect(Collectors.toMap(VenueBooth::getId, item -> item, (a, b) -> a));
|
||||
Map<String, VenueBooth> existingByNumber = existingBooths.stream()
|
||||
.filter(item -> StringUtils.isNotBlank(item.getBoothNumber()))
|
||||
.collect(Collectors.toMap(VenueBooth::getBoothNumber, item -> item, (a, b) -> a));
|
||||
Set<String> boothNumbers = new HashSet<>();
|
||||
Set<Long> savedIds = new HashSet<>();
|
||||
if (booths != null) {
|
||||
for (VenueBooth booth : booths) {
|
||||
if (StringUtils.isBlank(booth.getBoothNumber())) {
|
||||
return AjaxResult.error("展位号不能为空");
|
||||
}
|
||||
if (!boothNumbers.add(booth.getBoothNumber())) {
|
||||
return AjaxResult.error("展位号不能重复:" + booth.getBoothNumber());
|
||||
}
|
||||
}
|
||||
for (VenueBooth booth : booths) {
|
||||
VenueBooth existing = booth.getId() == null ? null : existingById.get(booth.getId());
|
||||
if (existing == null) {
|
||||
existing = existingByNumber.get(booth.getBoothNumber());
|
||||
}
|
||||
booth.setVenueId(venueId);
|
||||
if (existing == null) {
|
||||
booth.setId(null);
|
||||
venueBoothMapper.insert(booth);
|
||||
} else {
|
||||
booth.setId(existing.getId());
|
||||
venueBoothMapper.updateById(booth);
|
||||
}
|
||||
if (booth.getId() != null) {
|
||||
savedIds.add(booth.getId());
|
||||
}
|
||||
}
|
||||
VenueInfo venueInfo = venueInfoService.getById(venueId);
|
||||
if (venueInfo != null) {
|
||||
venueInfo.setFloorCount(booths.size());
|
||||
venueInfoService.updateById(venueInfo);
|
||||
}
|
||||
}
|
||||
List<Long> removedIds = existingBooths.stream()
|
||||
.map(VenueBooth::getId)
|
||||
.filter(id -> id != null && !savedIds.contains(id))
|
||||
.collect(Collectors.toList());
|
||||
if (!removedIds.isEmpty()) {
|
||||
venueBoothMapper.physicalDeleteByVenueIdAndIds(venueId, removedIds);
|
||||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
@ApiOperation("查询户外招聘会展位图")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:query')")
|
||||
@GetMapping("/fair/{fairId}/booth-map")
|
||||
public AjaxResult fairBoothMap(@PathVariable Long fairId)
|
||||
{
|
||||
OutdoorFair fair = outdoorFairMapper.selectById(fairId);
|
||||
if (fair == null || fair.getVenueId() == null) {
|
||||
return success(new ArrayList<>());
|
||||
}
|
||||
List<VenueBooth> booths = venueBoothMapper.selectList(new LambdaQueryWrapper<VenueBooth>()
|
||||
.eq(VenueBooth::getVenueId, fair.getVenueId())
|
||||
.orderByAsc(VenueBooth::getPositionY)
|
||||
.orderByAsc(VenueBooth::getPositionX)
|
||||
.orderByAsc(VenueBooth::getBoothNumber));
|
||||
List<OutdoorFairBoothBooking> bookings = outdoorFairBoothBookingMapper.selectList(new LambdaQueryWrapper<OutdoorFairBoothBooking>()
|
||||
.eq(OutdoorFairBoothBooking::getFairId, fairId));
|
||||
Map<Long, OutdoorFairBoothBooking> bookingMap = bookings.stream().collect(Collectors.toMap(OutdoorFairBoothBooking::getBoothId, item -> item, (a, b) -> a));
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
for (VenueBooth booth : booths) {
|
||||
OutdoorFairBoothBooking booking = bookingMap.get(booth.getId());
|
||||
Map<String, Object> row = new java.util.HashMap<>();
|
||||
row.put("id", booth.getId());
|
||||
row.put("boothId", booth.getId());
|
||||
row.put("boothNumber", booth.getBoothNumber());
|
||||
row.put("positionX", booth.getPositionX());
|
||||
row.put("positionY", booth.getPositionY());
|
||||
row.put("bookingId", booking == null ? null : booking.getId());
|
||||
row.put("companyId", booking == null ? null : booking.getCompanyId());
|
||||
row.put("companyName", booking == null ? null : booking.getCompanyName());
|
||||
row.put("status", booking == null ? "available" : booking.getStatus());
|
||||
result.add(row);
|
||||
}
|
||||
return success(result);
|
||||
}
|
||||
|
||||
@ApiOperation("预定户外招聘会展位")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:edit')")
|
||||
@PostMapping("/fair/{fairId}/booth-booking")
|
||||
public AjaxResult bookBooth(@PathVariable Long fairId, @RequestBody OutdoorFairBoothBooking booking)
|
||||
{
|
||||
if (booking.getCompanyId() == null) {
|
||||
return AjaxResult.error("请选择预定单位");
|
||||
}
|
||||
Company company = companyMapper.selectById(booking.getCompanyId());
|
||||
if (company == null || company.getStatus() == null || company.getStatus() != 1) {
|
||||
return AjaxResult.error("只能预定审核通过的企业");
|
||||
}
|
||||
VenueBooth booth = venueBoothMapper.selectById(booking.getBoothId());
|
||||
booking.setFairId(fairId);
|
||||
booking.setBoothNumber(booth == null ? booking.getBoothNumber() : booth.getBoothNumber());
|
||||
booking.setCompanyName(company.getName());
|
||||
booking.setStatus(StringUtils.isBlank(booking.getStatus()) ? "reserved" : booking.getStatus());
|
||||
OutdoorFairBoothBooking existing = outdoorFairBoothBookingMapper.selectOne(new LambdaQueryWrapper<OutdoorFairBoothBooking>()
|
||||
.eq(OutdoorFairBoothBooking::getFairId, fairId)
|
||||
.eq(OutdoorFairBoothBooking::getBoothId, booking.getBoothId())
|
||||
.last("limit 1"));
|
||||
if (existing == null) {
|
||||
return toAjax(outdoorFairBoothBookingMapper.insert(booking));
|
||||
}
|
||||
booking.setId(existing.getId());
|
||||
return toAjax(outdoorFairBoothBookingMapper.updateById(booking));
|
||||
}
|
||||
|
||||
@ApiOperation("取消户外招聘会展位预定")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:edit')")
|
||||
@DeleteMapping("/fair/{fairId}/booth-booking/{boothId}")
|
||||
public AjaxResult cancelBooth(@PathVariable Long fairId, @PathVariable Long boothId)
|
||||
{
|
||||
return toAjax(outdoorFairBoothBookingMapper.delete(new LambdaQueryWrapper<OutdoorFairBoothBooking>()
|
||||
.eq(OutdoorFairBoothBooking::getFairId, fairId)
|
||||
.eq(OutdoorFairBoothBooking::getBoothId, boothId)));
|
||||
}
|
||||
|
||||
@ApiOperation("调换户外招聘会展位")
|
||||
@PreAuthorize("@ss.hasPermi('cms:outdoorFair:edit')")
|
||||
@PostMapping("/fair/{fairId}/booth-swap")
|
||||
public AjaxResult swapBooth(@PathVariable Long fairId, @RequestBody VenueBoothSwapRequest request)
|
||||
{
|
||||
OutdoorFairBoothBooking first = outdoorFairBoothBookingMapper.selectOne(new LambdaQueryWrapper<OutdoorFairBoothBooking>()
|
||||
.eq(OutdoorFairBoothBooking::getFairId, fairId)
|
||||
.eq(OutdoorFairBoothBooking::getBoothId, request.getFirstBoothId()).last("limit 1"));
|
||||
OutdoorFairBoothBooking second = outdoorFairBoothBookingMapper.selectOne(new LambdaQueryWrapper<OutdoorFairBoothBooking>()
|
||||
.eq(OutdoorFairBoothBooking::getFairId, fairId)
|
||||
.eq(OutdoorFairBoothBooking::getBoothId, request.getSecondBoothId()).last("limit 1"));
|
||||
if (first == null || second == null) {
|
||||
return AjaxResult.error("请选择两个已预定展位");
|
||||
}
|
||||
Long companyId = first.getCompanyId();
|
||||
String companyName = first.getCompanyName();
|
||||
first.setCompanyId(second.getCompanyId());
|
||||
first.setCompanyName(second.getCompanyName());
|
||||
second.setCompanyId(companyId);
|
||||
second.setCompanyName(companyName);
|
||||
outdoorFairBoothBookingMapper.updateById(first);
|
||||
outdoorFairBoothBookingMapper.updateById(second);
|
||||
return success();
|
||||
}
|
||||
|
||||
private void fillHandleFields(VenueInfo venueInfo)
|
||||
{
|
||||
if (venueInfo.getHandleDate() == null) {
|
||||
venueInfo.setHandleDate(new Date());
|
||||
}
|
||||
if (StringUtils.isBlank(venueInfo.getHandler())) {
|
||||
venueInfo.setHandler(getUsername());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,6 +77,11 @@ public class InterviewInvitation extends BaseEntity {
|
||||
*/
|
||||
@ApiModelProperty("面试官联系方式")
|
||||
private String contactPhone;
|
||||
/**
|
||||
* 面试官姓名
|
||||
*/
|
||||
@ApiModelProperty("面试官姓名")
|
||||
private String interviewerName;
|
||||
/**
|
||||
* 公司名称(冗余存储,创建时从company表获取)
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.ruoyi.cms.domain;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 户外招聘会对象 cms_outdoor_fair
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-06-25
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("户外招聘会")
|
||||
@TableName("cms_outdoor_fair")
|
||||
public class OutdoorFair extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
@ApiModelProperty("主键ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "招聘会标题")
|
||||
@ApiModelProperty("招聘会标题")
|
||||
private String title;
|
||||
|
||||
@Excel(name = "举办单位")
|
||||
@ApiModelProperty("举办单位")
|
||||
private String hostUnit;
|
||||
|
||||
@Excel(name = "招聘会类型")
|
||||
@ApiModelProperty("招聘会类型")
|
||||
private String fairType;
|
||||
|
||||
@Excel(name = "举办区域")
|
||||
@ApiModelProperty("举办区域")
|
||||
private String region;
|
||||
|
||||
@Excel(name = "绑定场地ID")
|
||||
@ApiModelProperty("绑定场地ID")
|
||||
private Long venueId;
|
||||
|
||||
@Excel(name = "绑定场地")
|
||||
@ApiModelProperty("绑定场地")
|
||||
private String venueName;
|
||||
|
||||
@Excel(name = "举办地址")
|
||||
@ApiModelProperty("举办地址")
|
||||
private String address;
|
||||
|
||||
@Excel(name = "展位数量")
|
||||
@ApiModelProperty("展位数量")
|
||||
private Integer boothCount;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "举办时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("举办时间")
|
||||
private Date holdTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "截止时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("截止时间")
|
||||
private Date endTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "开放申请时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("开放申请时间")
|
||||
private Date applyStartTime;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "截止申请时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
@ApiModelProperty("截止申请时间")
|
||||
private Date applyEndTime;
|
||||
|
||||
@Excel(name = "是否开启线上申请")
|
||||
@ApiModelProperty("是否开启线上申请")
|
||||
private Boolean onlineApply;
|
||||
|
||||
@Excel(name = "招聘会照片")
|
||||
@ApiModelProperty("招聘会照片")
|
||||
private String photoUrl;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
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;
|
||||
|
||||
@Data
|
||||
@ApiModel("户外招聘会展位预定")
|
||||
@TableName("cms_outdoor_fair_booth_booking")
|
||||
public class OutdoorFairBoothBooking extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("招聘会ID")
|
||||
private Long fairId;
|
||||
|
||||
@ApiModelProperty("场地展位ID")
|
||||
private Long boothId;
|
||||
|
||||
@ApiModelProperty("展位号")
|
||||
private String boothNumber;
|
||||
|
||||
@ApiModelProperty("企业ID")
|
||||
private Long companyId;
|
||||
|
||||
@ApiModelProperty("企业名称")
|
||||
private String companyName;
|
||||
|
||||
@ApiModelProperty("预定状态")
|
||||
private String status;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.ruoyi.cms.domain;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 户外招聘会字典新增请求
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-06-25
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("户外招聘会字典新增请求")
|
||||
public class OutdoorFairDictDataRequest
|
||||
{
|
||||
@NotBlank(message = "字典类型不能为空")
|
||||
@ApiModelProperty(value = "字典类型", required = true)
|
||||
private String dictType;
|
||||
|
||||
@NotBlank(message = "字典标签不能为空")
|
||||
@ApiModelProperty(value = "字典标签", required = true)
|
||||
private String dictLabel;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
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;
|
||||
|
||||
@Data
|
||||
@ApiModel("场地展位")
|
||||
@TableName("cms_venue_booth")
|
||||
public class VenueBooth extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("场地ID")
|
||||
private Long venueId;
|
||||
|
||||
@ApiModelProperty("展位号")
|
||||
private String boothNumber;
|
||||
|
||||
@ApiModelProperty("X坐标")
|
||||
private Integer positionX;
|
||||
|
||||
@ApiModelProperty("Y坐标")
|
||||
private Integer positionY;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.ruoyi.cms.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class VenueBoothSwapRequest
|
||||
{
|
||||
private Long firstBoothId;
|
||||
private Long secondBoothId;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.ruoyi.cms.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 场地信息对象 cms_venue_info
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-06-25
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("场地信息")
|
||||
@TableName("cms_venue_info")
|
||||
public class VenueInfo extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
@ApiModelProperty("主键ID")
|
||||
private Long id;
|
||||
|
||||
@Excel(name = "场地类型")
|
||||
@ApiModelProperty("场地类型")
|
||||
private String venueType;
|
||||
|
||||
@Excel(name = "场地名称")
|
||||
@ApiModelProperty("场地名称")
|
||||
private String venueName;
|
||||
|
||||
@Excel(name = "场地面积")
|
||||
@ApiModelProperty("场地面积")
|
||||
private BigDecimal venueArea;
|
||||
|
||||
@Excel(name = "展位数量")
|
||||
@ApiModelProperty("展位数量")
|
||||
private Integer floorCount;
|
||||
|
||||
@Excel(name = "场地地址")
|
||||
@ApiModelProperty("场地地址")
|
||||
private String venueAddress;
|
||||
|
||||
@Excel(name = "联系电话")
|
||||
@ApiModelProperty("联系电话")
|
||||
private String contactPhone;
|
||||
|
||||
@Excel(name = "乘坐线路ID")
|
||||
@ApiModelProperty("乘坐线路ID,多个用英文逗号分隔")
|
||||
private String routeLineIds;
|
||||
|
||||
@Excel(name = "乘坐线路")
|
||||
@ApiModelProperty("乘坐线路名称,多个用英文逗号分隔")
|
||||
private String routeLineNames;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "经办日期", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@ApiModelProperty("经办日期")
|
||||
private Date handleDate;
|
||||
|
||||
@Excel(name = "经办机构")
|
||||
@ApiModelProperty("经办机构")
|
||||
private String handleOrg;
|
||||
|
||||
@Excel(name = "经办人")
|
||||
@ApiModelProperty("经办人")
|
||||
private String handler;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.ruoyi.cms.domain;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 场地信息字典新增请求
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-06-25
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("场地信息字典新增请求")
|
||||
public class VenueInfoDictDataRequest
|
||||
{
|
||||
@NotBlank(message = "字典类型不能为空")
|
||||
@ApiModelProperty(value = "字典类型", required = true)
|
||||
private String dictType;
|
||||
|
||||
@NotBlank(message = "字典标签不能为空")
|
||||
@ApiModelProperty(value = "字典标签", required = true)
|
||||
private String dictLabel;
|
||||
}
|
||||
@@ -18,4 +18,6 @@ public class CandidateVO extends AppUser {
|
||||
private String companyName;
|
||||
@Excel(name = "岗位名称", sort = 1)
|
||||
private String jobName;
|
||||
private String interviewStatus;
|
||||
private Long interviewId;
|
||||
}
|
||||
|
||||
@@ -11,4 +11,10 @@ public class InterviewInvitationVO extends InterviewInvitation {
|
||||
|
||||
@ApiModelProperty("岗位名称(来自关联查询的实时数据)")
|
||||
private String jobTitle;
|
||||
|
||||
@ApiModelProperty("求职者姓名(来自关联查询的实时数据)")
|
||||
private String applicantName;
|
||||
|
||||
@ApiModelProperty("求职者联系方式(来自关联查询的实时数据)")
|
||||
private String applicantPhone;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.ruoyi.cms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.cms.domain.OutdoorFairBoothBooking;
|
||||
|
||||
public interface OutdoorFairBoothBookingMapper extends BaseMapper<OutdoorFairBoothBooking>
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.ruoyi.cms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.cms.domain.OutdoorFair;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
/**
|
||||
* 户外招聘会Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-06-25
|
||||
*/
|
||||
public interface OutdoorFairMapper extends BaseMapper<OutdoorFair>
|
||||
{
|
||||
/**
|
||||
* 查询字典项是否存在
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictValue 字典值
|
||||
* @return 存在数量
|
||||
*/
|
||||
@Select("select count(1) from sys_dict_data where dict_type = #{dictType} and dict_value = #{dictValue}")
|
||||
int countDictDataByTypeAndValue(@Param("dictType") String dictType, @Param("dictValue") String dictValue);
|
||||
|
||||
/**
|
||||
* 获取字典下一个排序
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @return 下一个排序值
|
||||
*/
|
||||
@Select("select coalesce(max(dict_sort), 0) + 1 from sys_dict_data where dict_type = #{dictType}")
|
||||
Long selectNextDictSort(@Param("dictType") String dictType);
|
||||
|
||||
/**
|
||||
* 新增系统字典项
|
||||
*
|
||||
* @param dictSort 字典排序
|
||||
* @param dictLabel 字典标签
|
||||
* @param dictValue 字典值
|
||||
* @param dictType 字典类型
|
||||
* @param createBy 创建人
|
||||
* @return 影响行数
|
||||
*/
|
||||
@Insert("insert into sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark) " +
|
||||
"values ((select coalesce(max(dict_code), 0) + 1 from sys_dict_data), #{dictSort}, #{dictLabel}, #{dictValue}, #{dictType}, 'default', 'N', '0', #{createBy}, sysdate(), '户外招聘会页面新增')")
|
||||
int insertDictData(@Param("dictSort") Long dictSort,
|
||||
@Param("dictLabel") String dictLabel,
|
||||
@Param("dictValue") String dictValue,
|
||||
@Param("dictType") String dictType,
|
||||
@Param("createBy") String createBy);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.ruoyi.cms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.cms.domain.VenueBooth;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface VenueBoothMapper extends BaseMapper<VenueBooth>
|
||||
{
|
||||
@Delete("DELETE FROM cms_venue_booth WHERE venue_id = #{venueId} AND del_flag <> '0'")
|
||||
int physicalDeleteDeletedByVenueId(@Param("venueId") Long venueId);
|
||||
|
||||
@Delete({
|
||||
"<script>",
|
||||
"DELETE FROM cms_venue_booth WHERE venue_id = #{venueId} AND id IN",
|
||||
"<foreach collection='ids' item='id' open='(' separator=',' close=')'>",
|
||||
"#{id}",
|
||||
"</foreach>",
|
||||
"</script>"
|
||||
})
|
||||
int physicalDeleteByVenueIdAndIds(@Param("venueId") Long venueId, @Param("ids") List<Long> ids);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.ruoyi.cms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.cms.domain.VenueInfo;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
/**
|
||||
* 场地信息Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-06-25
|
||||
*/
|
||||
public interface VenueInfoMapper extends BaseMapper<VenueInfo>
|
||||
{
|
||||
/**
|
||||
* 查询字典项是否存在
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictValue 字典值
|
||||
* @return 存在数量
|
||||
*/
|
||||
@Select("select count(1) from sys_dict_data where dict_type = #{dictType} and dict_value = #{dictValue}")
|
||||
int countDictDataByTypeAndValue(@Param("dictType") String dictType, @Param("dictValue") String dictValue);
|
||||
|
||||
/**
|
||||
* 获取字典下一个排序
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @return 下一个排序值
|
||||
*/
|
||||
@Select("select coalesce(max(dict_sort), 0) + 1 from sys_dict_data where dict_type = #{dictType}")
|
||||
Long selectNextDictSort(@Param("dictType") String dictType);
|
||||
|
||||
/**
|
||||
* 新增系统字典项
|
||||
*
|
||||
* @param dictSort 字典排序
|
||||
* @param dictLabel 字典标签
|
||||
* @param dictValue 字典值
|
||||
* @param dictType 字典类型
|
||||
* @param createBy 创建人
|
||||
* @return 影响行数
|
||||
*/
|
||||
@Insert("insert into sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, list_class, is_default, status, create_by, create_time, remark) " +
|
||||
"values ((select coalesce(max(dict_code), 0) + 1 from sys_dict_data), #{dictSort}, #{dictLabel}, #{dictValue}, #{dictType}, 'default', 'N', '0', #{createBy}, sysdate(), '场地信息维护页面新增')")
|
||||
int insertDictData(@Param("dictSort") Long dictSort,
|
||||
@Param("dictLabel") String dictLabel,
|
||||
@Param("dictValue") String dictValue,
|
||||
@Param("dictType") String dictType,
|
||||
@Param("createBy") String createBy);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.ruoyi.cms.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.cms.domain.OutdoorFair;
|
||||
|
||||
/**
|
||||
* 户外招聘会Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-06-25
|
||||
*/
|
||||
public interface IOutdoorFairService extends IService<OutdoorFair>
|
||||
{
|
||||
/**
|
||||
* 查询户外招聘会列表
|
||||
*
|
||||
* @param outdoorFair 户外招聘会
|
||||
* @return 户外招聘会集合
|
||||
*/
|
||||
List<OutdoorFair> selectOutdoorFairList(OutdoorFair outdoorFair);
|
||||
|
||||
/**
|
||||
* 新增户外招聘会相关字典项
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictLabel 字典标签
|
||||
* @param createBy 创建人
|
||||
* @return 影响行数
|
||||
*/
|
||||
int insertOutdoorFairDictData(String dictType, String dictLabel, String createBy);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.ruoyi.cms.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.ruoyi.cms.domain.VenueInfo;
|
||||
|
||||
/**
|
||||
* 场地信息Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-06-25
|
||||
*/
|
||||
public interface IVenueInfoService extends IService<VenueInfo>
|
||||
{
|
||||
/**
|
||||
* 查询场地信息列表
|
||||
*
|
||||
* @param venueInfo 场地信息
|
||||
* @return 场地信息集合
|
||||
*/
|
||||
List<VenueInfo> selectVenueInfoList(VenueInfo venueInfo);
|
||||
|
||||
/**
|
||||
* 新增场地信息相关字典项
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictLabel 字典标签
|
||||
* @param createBy 创建人
|
||||
* @return 影响行数
|
||||
*/
|
||||
int insertVenueInfoDictData(String dictType, String dictLabel, String createBy);
|
||||
}
|
||||
@@ -72,7 +72,7 @@ public class ESJobSearchImpl implements IESJobSearchService
|
||||
/**
|
||||
* 项目启动时,初始化索引及数据
|
||||
*/
|
||||
@PostConstruct
|
||||
// @PostConstruct
|
||||
public void init()
|
||||
{
|
||||
boolean isLockAcquired = false;
|
||||
|
||||
@@ -17,12 +17,14 @@ import com.ruoyi.common.core.domain.entity.Company;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Statement;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -43,8 +45,9 @@ public class InterviewInvitationServiceImpl implements InterviewInvitationServic
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@PostConstruct
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
public void initTable() {
|
||||
log.info("开始检查并初始化 interview_invitation 表...");
|
||||
try (Connection conn = dataSource.getConnection();
|
||||
Statement stmt = conn.createStatement()) {
|
||||
// Check if id column has auto-increment (BIGSERIAL or sequence default)
|
||||
@@ -80,6 +83,7 @@ public class InterviewInvitationServiceImpl implements InterviewInvitationServic
|
||||
+ "meeting_password varchar(100) NULL,"
|
||||
+ "interview_location varchar(500) NULL,"
|
||||
+ "contact_phone varchar(50) NULL,"
|
||||
+ "interviewer_name varchar(100) NULL,"
|
||||
+ "company_name varchar(200) NULL,"
|
||||
+ "job_name varchar(200) NULL,"
|
||||
+ "status varchar(20) DEFAULT 'pending' NULL,"
|
||||
@@ -96,9 +100,16 @@ public class InterviewInvitationServiceImpl implements InterviewInvitationServic
|
||||
log.info("interview_invitation 表创建成功(序列自增)!");
|
||||
} else {
|
||||
log.info("interview_invitation 表结构正常,检查新增列...");
|
||||
// 为已有数据库添加新列(幂等操作)
|
||||
try { stmt.execute("ALTER TABLE interview_invitation ADD COLUMN IF NOT EXISTS company_name varchar(200) NULL"); } catch (Exception ignored) {}
|
||||
try { stmt.execute("ALTER TABLE interview_invitation ADD COLUMN IF NOT EXISTS job_name varchar(200) NULL"); } catch (Exception ignored) {}
|
||||
// 为已有数据库添加新列(幂等操作,使用 DO 块兼容不支持 IF NOT EXISTS 的数据库版本)
|
||||
try {
|
||||
stmt.execute("DO $$ BEGIN ALTER TABLE interview_invitation ADD COLUMN company_name varchar(200) NULL; EXCEPTION WHEN duplicate_column THEN END; $$;");
|
||||
} catch (Exception e) { log.warn("添加 company_name 列失败: {}", e.getMessage()); }
|
||||
try {
|
||||
stmt.execute("DO $$ BEGIN ALTER TABLE interview_invitation ADD COLUMN job_name varchar(200) NULL; EXCEPTION WHEN duplicate_column THEN END; $$;");
|
||||
} catch (Exception e) { log.warn("添加 job_name 列失败: {}", e.getMessage()); }
|
||||
try {
|
||||
stmt.execute("DO $$ BEGIN ALTER TABLE interview_invitation ADD COLUMN interviewer_name varchar(100) NULL; EXCEPTION WHEN duplicate_column THEN END; $$;");
|
||||
} catch (Exception e) { log.warn("添加 interviewer_name 列失败: {}", e.getMessage()); }
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("初始化表失败: {}", e.getMessage());
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.ruoyi.cms.service.impl;
|
||||
|
||||
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.OutdoorFair;
|
||||
import com.ruoyi.cms.mapper.OutdoorFairMapper;
|
||||
import com.ruoyi.cms.service.IOutdoorFairService;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.DictUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 户外招聘会Service业务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-06-25
|
||||
*/
|
||||
@Service
|
||||
public class OutdoorFairServiceImpl extends ServiceImpl<OutdoorFairMapper, OutdoorFair> implements IOutdoorFairService
|
||||
{
|
||||
private static final String OUTDOOR_FAIR_TYPE_DICT = "outdoor_fair_type";
|
||||
|
||||
private static final String OUTDOOR_FAIR_REGION_DICT = "outdoor_fair_region";
|
||||
|
||||
/**
|
||||
* 查询户外招聘会列表
|
||||
*
|
||||
* @param outdoorFair 户外招聘会
|
||||
* @return 户外招聘会集合
|
||||
*/
|
||||
@Override
|
||||
public List<OutdoorFair> selectOutdoorFairList(OutdoorFair outdoorFair)
|
||||
{
|
||||
LambdaQueryWrapper<OutdoorFair> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.like(StringUtils.isNotBlank(outdoorFair.getTitle()), OutdoorFair::getTitle, outdoorFair.getTitle());
|
||||
queryWrapper.like(StringUtils.isNotBlank(outdoorFair.getHostUnit()), OutdoorFair::getHostUnit, outdoorFair.getHostUnit());
|
||||
queryWrapper.eq(StringUtils.isNotBlank(outdoorFair.getFairType()), OutdoorFair::getFairType, outdoorFair.getFairType());
|
||||
queryWrapper.eq(StringUtils.isNotBlank(outdoorFair.getRegion()), OutdoorFair::getRegion, outdoorFair.getRegion());
|
||||
queryWrapper.eq(outdoorFair.getVenueId() != null, OutdoorFair::getVenueId, outdoorFair.getVenueId());
|
||||
queryWrapper.orderByDesc(OutdoorFair::getHoldTime);
|
||||
queryWrapper.orderByDesc(OutdoorFair::getCreateTime);
|
||||
return list(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增户外招聘会相关字典项
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictLabel 字典标签
|
||||
* @param createBy 创建人
|
||||
* @return 影响行数
|
||||
*/
|
||||
@Override
|
||||
public int insertOutdoorFairDictData(String dictType, String dictLabel, String createBy)
|
||||
{
|
||||
if (!OUTDOOR_FAIR_TYPE_DICT.equals(dictType) && !OUTDOOR_FAIR_REGION_DICT.equals(dictType)) {
|
||||
throw new ServiceException("只允许维护户外招聘会类型和举办区域字典");
|
||||
}
|
||||
String trimmedLabel = StringUtils.trim(dictLabel);
|
||||
if (StringUtils.isBlank(trimmedLabel)) {
|
||||
throw new ServiceException("字典名称不能为空");
|
||||
}
|
||||
if (trimmedLabel.length() > 100) {
|
||||
throw new ServiceException("字典名称长度不能超过100个字符");
|
||||
}
|
||||
if (baseMapper.countDictDataByTypeAndValue(dictType, trimmedLabel) > 0) {
|
||||
return 1;
|
||||
}
|
||||
Long dictSort = baseMapper.selectNextDictSort(dictType);
|
||||
int rows = baseMapper.insertDictData(dictSort, trimmedLabel, trimmedLabel, dictType, createBy);
|
||||
if (rows > 0) {
|
||||
DictUtils.removeDictCache(dictType);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.ruoyi.cms.service.impl;
|
||||
|
||||
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.VenueInfo;
|
||||
import com.ruoyi.cms.mapper.VenueInfoMapper;
|
||||
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.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 场地信息Service业务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-06-25
|
||||
*/
|
||||
@Service
|
||||
public class VenueInfoServiceImpl extends ServiceImpl<VenueInfoMapper, VenueInfo> implements IVenueInfoService
|
||||
{
|
||||
private static final String VENUE_TYPE_DICT = "venue_info_type";
|
||||
|
||||
/**
|
||||
* 查询场地信息列表
|
||||
*
|
||||
* @param venueInfo 场地信息
|
||||
* @return 场地信息集合
|
||||
*/
|
||||
@Override
|
||||
public List<VenueInfo> selectVenueInfoList(VenueInfo venueInfo)
|
||||
{
|
||||
LambdaQueryWrapper<VenueInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(StringUtils.isNotBlank(venueInfo.getVenueType()), VenueInfo::getVenueType, venueInfo.getVenueType());
|
||||
queryWrapper.like(StringUtils.isNotBlank(venueInfo.getVenueName()), VenueInfo::getVenueName, venueInfo.getVenueName());
|
||||
queryWrapper.like(StringUtils.isNotBlank(venueInfo.getVenueAddress()), VenueInfo::getVenueAddress, venueInfo.getVenueAddress());
|
||||
queryWrapper.orderByDesc(VenueInfo::getCreateTime);
|
||||
return list(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增场地信息相关字典项
|
||||
*
|
||||
* @param dictType 字典类型
|
||||
* @param dictLabel 字典标签
|
||||
* @param createBy 创建人
|
||||
* @return 影响行数
|
||||
*/
|
||||
@Override
|
||||
public int insertVenueInfoDictData(String dictType, String dictLabel, String createBy)
|
||||
{
|
||||
if (!VENUE_TYPE_DICT.equals(dictType)) {
|
||||
throw new ServiceException("只允许维护场地类型字典");
|
||||
}
|
||||
String trimmedLabel = StringUtils.trim(dictLabel);
|
||||
if (StringUtils.isBlank(trimmedLabel)) {
|
||||
throw new ServiceException("字典名称不能为空");
|
||||
}
|
||||
if (trimmedLabel.length() > 100) {
|
||||
throw new ServiceException("字典名称长度不能超过100个字符");
|
||||
}
|
||||
if (baseMapper.countDictDataByTypeAndValue(dictType, trimmedLabel) > 0) {
|
||||
return 1;
|
||||
}
|
||||
Long dictSort = baseMapper.selectNextDictSort(dictType);
|
||||
int rows = baseMapper.insertDictData(dictSort, trimmedLabel, trimmedLabel, dictType, createBy);
|
||||
if (rows > 0) {
|
||||
DictUtils.removeDictCache(dictType);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
<result property="meetingPassword" column="meeting_password"/>
|
||||
<result property="interviewLocation" column="interview_location"/>
|
||||
<result property="contactPhone" column="contact_phone"/>
|
||||
<result property="interviewerName" column="interviewer_name"/>
|
||||
<result property="companyName" column="company_name"/>
|
||||
<result property="jobName" column="job_name"/>
|
||||
<result property="status" column="status"/>
|
||||
@@ -30,12 +31,14 @@
|
||||
<!-- VO 带公司名和岗位名(继承基础映射,jobTitle 来自关联查询的实时数据) -->
|
||||
<resultMap type="com.ruoyi.cms.domain.vo.InterviewInvitationVO" id="InterviewInvitationVOResult" extends="InterviewInvitationResult">
|
||||
<result property="jobTitle" column="job_title"/>
|
||||
<result property="applicantName" column="applicant_name"/>
|
||||
<result property="applicantPhone" column="applicant_phone"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectInterviewInvitationVo">
|
||||
select id, company_id, job_id, user_id, apply_id, interview_time,
|
||||
interview_method, meeting_link, meeting_password, interview_location,
|
||||
contact_phone, company_name, job_name, status, del_flag,
|
||||
contact_phone, interviewer_name, company_name, job_name, status, del_flag,
|
||||
create_by, create_time, update_by, update_time, remark
|
||||
from interview_invitation
|
||||
</sql>
|
||||
@@ -53,13 +56,22 @@
|
||||
</select>
|
||||
|
||||
<!-- 带公司名和岗位名的列表查询,COALESCE 优先用关联表实时数据,兜底用冗余存储 -->
|
||||
<!-- 注意:不用 t.* 避免 company_name 列名冲突,显式列出除 company_name 外的所有列 -->
|
||||
<select id="getInterviewInvitationVOList" resultMap="InterviewInvitationVOResult" parameterType="InterviewInvitation">
|
||||
select t.*,
|
||||
select t.id, t.company_id, t.job_id, t.user_id, t.apply_id,
|
||||
t.interview_time, t.interview_method, t.meeting_link,
|
||||
t.meeting_password, t.interview_location,
|
||||
t.contact_phone, t.interviewer_name,
|
||||
t.job_name, t.status, t.del_flag,
|
||||
t.create_by, t.create_time, t.update_by, t.update_time, t.remark,
|
||||
COALESCE(c.name, t.company_name) as company_name,
|
||||
COALESCE(j.job_title, t.job_name) as job_title
|
||||
COALESCE(j.job_title, t.job_name) as job_title,
|
||||
u.name as applicant_name,
|
||||
u.phone as applicant_phone
|
||||
from interview_invitation t
|
||||
left join company c on c.company_id = t.company_id and c.del_flag = '0'
|
||||
left join job j on j.job_id = t.job_id and j.del_flag = '0'
|
||||
left join app_user u on u.user_id = t.user_id and u.del_flag = '0'
|
||||
<where> t.del_flag = '0'
|
||||
<if test="companyId != null and companyId != ''"> and t.company_id = #{companyId}</if>
|
||||
<if test="jobId != null and jobId != ''"> and t.job_id = #{jobId}</if>
|
||||
|
||||
@@ -42,10 +42,26 @@
|
||||
ORDER BY ja.create_time DESC
|
||||
</select>
|
||||
<select id="candidates" resultType="com.ruoyi.cms.domain.vo.CandidateVO">
|
||||
SELECT au.*,jc.create_time as apply_date,jc.matching_degree,jc.id as applyId
|
||||
SELECT au.*, jc.create_time as apply_date, jc.matching_degree, jc.id as applyId,
|
||||
latest_ii.status as interviewStatus, latest_ii.id as interviewId
|
||||
from job_apply as jc
|
||||
inner join app_user as au on jc.user_id = au.user_id
|
||||
left join (
|
||||
select ii1.*
|
||||
from interview_invitation ii1
|
||||
inner join (
|
||||
select user_id, job_id, max(create_time) as max_ct
|
||||
from interview_invitation
|
||||
where del_flag = '0'
|
||||
group by user_id, job_id
|
||||
) ii2 on ii1.user_id = ii2.user_id
|
||||
and ii1.job_id = ii2.job_id
|
||||
and ii1.create_time = ii2.max_ct
|
||||
) latest_ii on latest_ii.user_id = jc.user_id
|
||||
and latest_ii.job_id = jc.job_id
|
||||
and latest_ii.del_flag = '0'
|
||||
where jc.job_id = #{jobId} and jc.del_flag = '0' and au.del_flag ='0'
|
||||
order by jc.create_time desc
|
||||
</select>
|
||||
|
||||
<select id="trendChart" resultType="java.util.HashMap" parameterType="JobApply">
|
||||
@@ -104,10 +120,26 @@
|
||||
</select>
|
||||
|
||||
<select id="selectApplyJobUserList" parameterType="com.ruoyi.common.core.domain.entity.AppUser" resultType="com.ruoyi.cms.domain.vo.CandidateVO">
|
||||
select a.id applyId, a.hire, b.job_title jobName,l.name companyName,e.* from job_apply a
|
||||
select a.id applyId, a.hire, b.job_title jobName, l.name companyName, e.*,
|
||||
latest_ii.status as interviewStatus, latest_ii.id as interviewId
|
||||
from job_apply a
|
||||
INNER join job b on a.job_id=b.job_id and b.del_flag='0'
|
||||
INNER join app_user e on a.user_id =e.user_id and e.del_flag='0'
|
||||
INNER join company l on b.company_id =l.company_id and l.del_flag='0'
|
||||
left join (
|
||||
select ii1.*
|
||||
from interview_invitation ii1
|
||||
inner join (
|
||||
select user_id, job_id, max(create_time) as max_ct
|
||||
from interview_invitation
|
||||
where del_flag = '0'
|
||||
group by user_id, job_id
|
||||
) ii2 on ii1.user_id = ii2.user_id
|
||||
and ii1.job_id = ii2.job_id
|
||||
and ii1.create_time = ii2.max_ct
|
||||
) latest_ii on latest_ii.user_id = a.user_id
|
||||
and latest_ii.job_id = a.job_id
|
||||
and latest_ii.del_flag = '0'
|
||||
where a.del_flag='0'
|
||||
<if test="company != null and company.jobTitle != null and company.jobTitle != ''"> and b.job_title like concat('%', cast(#{company.jobTitle, jdbcType=VARCHAR} as varchar), '%')</if>
|
||||
<if test="company != null and company.education != null and company.education != ''"> and b.education = #{company.education}</if>
|
||||
|
||||
58
sql/cms_outdoor_fair.sql
Normal file
58
sql/cms_outdoor_fair.sql
Normal file
@@ -0,0 +1,58 @@
|
||||
-- 户外招聘会表
|
||||
-- 瀚高数据库 / PostgreSQL 兼容
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS "cms_outdoor_fair_id_seq"
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "cms_outdoor_fair" (
|
||||
"id" BIGINT NOT NULL DEFAULT nextval('"cms_outdoor_fair_id_seq"') PRIMARY KEY,
|
||||
"title" VARCHAR(200) NOT NULL,
|
||||
"host_unit" VARCHAR(200) NOT NULL,
|
||||
"fair_type" VARCHAR(50) NOT NULL,
|
||||
"region" VARCHAR(100) NOT NULL,
|
||||
"venue_id" BIGINT,
|
||||
"venue_name" VARCHAR(200),
|
||||
"address" VARCHAR(500) NOT NULL,
|
||||
"booth_count" INTEGER NOT NULL DEFAULT 0,
|
||||
"hold_time" TIMESTAMP(0) NOT NULL,
|
||||
"end_time" TIMESTAMP(0) NOT NULL,
|
||||
"apply_start_time" TIMESTAMP(0) NOT NULL,
|
||||
"apply_end_time" TIMESTAMP(0) NOT NULL,
|
||||
"online_apply" BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
"photo_url" VARCHAR(500),
|
||||
"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_outdoor_fair" IS '户外招聘会表';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."id" IS '主键ID';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."title" IS '招聘会标题';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."host_unit" IS '举办单位';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."fair_type" IS '招聘会类型';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."region" IS '举办区域';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."venue_id" IS '绑定场地ID';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."venue_name" IS '绑定场地';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."address" IS '举办地址';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."booth_count" IS '展位数量';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."hold_time" IS '举办时间';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."end_time" IS '截止时间';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."apply_start_time" IS '开放申请时间';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."apply_end_time" IS '截止申请时间';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."online_apply" IS '是否开启线上申请';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."photo_url" IS '招聘会照片';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."del_flag" IS '删除标志(0代表存在 2代表删除)';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "idx_cms_outdoor_fair_title" ON "cms_outdoor_fair" ("title");
|
||||
CREATE INDEX IF NOT EXISTS "idx_cms_outdoor_fair_host_unit" ON "cms_outdoor_fair" ("host_unit");
|
||||
CREATE INDEX IF NOT EXISTS "idx_cms_outdoor_fair_type" ON "cms_outdoor_fair" ("fair_type");
|
||||
CREATE INDEX IF NOT EXISTS "idx_cms_outdoor_fair_venue_id" ON "cms_outdoor_fair" ("venue_id");
|
||||
CREATE INDEX IF NOT EXISTS "idx_cms_outdoor_fair_hold_time" ON "cms_outdoor_fair" ("hold_time");
|
||||
CREATE INDEX IF NOT EXISTS "idx_cms_outdoor_fair_del_flag" ON "cms_outdoor_fair" ("del_flag");
|
||||
20
sql/cms_outdoor_fair_bind_venue.sql
Normal file
20
sql/cms_outdoor_fair_bind_venue.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
-- 户外招聘会绑定场地字段
|
||||
-- 瀚高数据库 / PostgreSQL 兼容
|
||||
-- 可重复执行。
|
||||
|
||||
ALTER TABLE "cms_outdoor_fair"
|
||||
ADD COLUMN IF NOT EXISTS "venue_id" BIGINT;
|
||||
|
||||
ALTER TABLE "cms_outdoor_fair"
|
||||
ADD COLUMN IF NOT EXISTS "venue_name" VARCHAR(200);
|
||||
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."venue_id" IS '绑定场地ID';
|
||||
COMMENT ON COLUMN "cms_outdoor_fair"."venue_name" IS '绑定场地';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "idx_cms_outdoor_fair_venue_id" ON "cms_outdoor_fair" ("venue_id");
|
||||
|
||||
UPDATE "cms_outdoor_fair" fair
|
||||
SET "venue_name" = venue."venue_name",
|
||||
"booth_count" = COALESCE(venue."floor_count", 0)
|
||||
FROM "cms_venue_info" venue
|
||||
WHERE fair."venue_id" = venue."id";
|
||||
202
sql/cms_outdoor_fair_seed_shihezi.sql
Normal file
202
sql/cms_outdoor_fair_seed_shihezi.sql
Normal file
@@ -0,0 +1,202 @@
|
||||
-- 户外招聘会石河子 mock 数据
|
||||
-- 可重复执行:按 title 去重,已存在同名招聘会时不会重复插入。
|
||||
|
||||
INSERT INTO "cms_outdoor_fair" (
|
||||
"title", "host_unit", "fair_type", "region", "address", "booth_count",
|
||||
"hold_time", "end_time", "apply_start_time", "apply_end_time",
|
||||
"online_apply", "photo_url", "create_by", "create_time", "update_by", "update_time", "del_flag"
|
||||
)
|
||||
SELECT
|
||||
'2026年石河子市春季户外综合招聘会',
|
||||
'第八师石河子市人力资源和社会保障局',
|
||||
'综合类',
|
||||
'第八师(石河子市)',
|
||||
'石河子市北三路石河子大学中区图书馆前广场',
|
||||
80,
|
||||
TIMESTAMP '2026-03-15 09:00:00',
|
||||
TIMESTAMP '2026-03-15 17:00:00',
|
||||
TIMESTAMP '2026-03-01 00:00:00',
|
||||
TIMESTAMP '2026-03-10 23:59:59',
|
||||
TRUE,
|
||||
'https://picsum.photos/seed/shihezi-outdoor-1/400/300',
|
||||
'system',
|
||||
NOW(),
|
||||
'system',
|
||||
NOW(),
|
||||
'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM "cms_outdoor_fair" WHERE "title" = '2026年石河子市春季户外综合招聘会');
|
||||
|
||||
INSERT INTO "cms_outdoor_fair" (
|
||||
"title", "host_unit", "fair_type", "region", "address", "booth_count",
|
||||
"hold_time", "end_time", "apply_start_time", "apply_end_time",
|
||||
"online_apply", "photo_url", "create_by", "create_time", "update_by", "update_time", "del_flag"
|
||||
)
|
||||
SELECT
|
||||
'2026年石河子大学毕业生户外专场招聘会',
|
||||
'石河子大学就业指导中心',
|
||||
'校园招聘',
|
||||
'第八师(石河子市)',
|
||||
'石河子大学中区主楼前广场',
|
||||
60,
|
||||
TIMESTAMP '2026-04-18 09:30:00',
|
||||
TIMESTAMP '2026-04-18 16:30:00',
|
||||
TIMESTAMP '2026-04-01 00:00:00',
|
||||
TIMESTAMP '2026-04-12 23:59:59',
|
||||
TRUE,
|
||||
'https://picsum.photos/seed/shihezi-outdoor-2/400/300',
|
||||
'system',
|
||||
NOW(),
|
||||
'system',
|
||||
NOW(),
|
||||
'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM "cms_outdoor_fair" WHERE "title" = '2026年石河子大学毕业生户外专场招聘会');
|
||||
|
||||
INSERT INTO "cms_outdoor_fair" (
|
||||
"title", "host_unit", "fair_type", "region", "address", "booth_count",
|
||||
"hold_time", "end_time", "apply_start_time", "apply_end_time",
|
||||
"online_apply", "photo_url", "create_by", "create_time", "update_by", "update_time", "del_flag"
|
||||
)
|
||||
SELECT
|
||||
'2026年石河子经开区制造业户外招聘会',
|
||||
'石河子经济技术开发区管委会',
|
||||
'行业专场',
|
||||
'第八师(石河子市)',
|
||||
'石河子经济技术开发区企业服务中心广场',
|
||||
100,
|
||||
TIMESTAMP '2026-05-16 09:00:00',
|
||||
TIMESTAMP '2026-05-16 17:30:00',
|
||||
TIMESTAMP '2026-04-25 00:00:00',
|
||||
TIMESTAMP '2026-05-10 23:59:59',
|
||||
TRUE,
|
||||
'https://picsum.photos/seed/shihezi-outdoor-3/400/300',
|
||||
'system',
|
||||
NOW(),
|
||||
'system',
|
||||
NOW(),
|
||||
'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM "cms_outdoor_fair" WHERE "title" = '2026年石河子经开区制造业户外招聘会');
|
||||
|
||||
INSERT INTO "cms_outdoor_fair" (
|
||||
"title", "host_unit", "fair_type", "region", "address", "booth_count",
|
||||
"hold_time", "end_time", "apply_start_time", "apply_end_time",
|
||||
"online_apply", "photo_url", "create_by", "create_time", "update_by", "update_time", "del_flag"
|
||||
)
|
||||
SELECT
|
||||
'2026年石河子市高新区数字经济户外招聘会',
|
||||
'石河子高新技术产业开发区管理委员会',
|
||||
'高新技术专场',
|
||||
'第八师(石河子市)',
|
||||
'石河子高新区科技企业孵化器广场',
|
||||
55,
|
||||
TIMESTAMP '2026-06-20 09:00:00',
|
||||
TIMESTAMP '2026-06-20 16:30:00',
|
||||
TIMESTAMP '2026-06-01 00:00:00',
|
||||
TIMESTAMP '2026-06-14 23:59:59',
|
||||
TRUE,
|
||||
'https://picsum.photos/seed/shihezi-outdoor-4/400/300',
|
||||
'system',
|
||||
NOW(),
|
||||
'system',
|
||||
NOW(),
|
||||
'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM "cms_outdoor_fair" WHERE "title" = '2026年石河子市高新区数字经济户外招聘会');
|
||||
|
||||
INSERT INTO "cms_outdoor_fair" (
|
||||
"title", "host_unit", "fair_type", "region", "address", "booth_count",
|
||||
"hold_time", "end_time", "apply_start_time", "apply_end_time",
|
||||
"online_apply", "photo_url", "create_by", "create_time", "update_by", "update_time", "del_flag"
|
||||
)
|
||||
SELECT
|
||||
'2026年石河子军垦文化广场服务业招聘会',
|
||||
'石河子市就业服务中心',
|
||||
'服务业专场',
|
||||
'第八师(石河子市)',
|
||||
'石河子市军垦文化广场',
|
||||
45,
|
||||
TIMESTAMP '2026-07-11 10:00:00',
|
||||
TIMESTAMP '2026-07-11 17:00:00',
|
||||
TIMESTAMP '2026-06-20 00:00:00',
|
||||
TIMESTAMP '2026-07-05 23:59:59',
|
||||
FALSE,
|
||||
'https://picsum.photos/seed/shihezi-outdoor-5/400/300',
|
||||
'system',
|
||||
NOW(),
|
||||
'system',
|
||||
NOW(),
|
||||
'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM "cms_outdoor_fair" WHERE "title" = '2026年石河子军垦文化广场服务业招聘会');
|
||||
|
||||
INSERT INTO "cms_outdoor_fair" (
|
||||
"title", "host_unit", "fair_type", "region", "address", "booth_count",
|
||||
"hold_time", "end_time", "apply_start_time", "apply_end_time",
|
||||
"online_apply", "photo_url", "create_by", "create_time", "update_by", "update_time", "del_flag"
|
||||
)
|
||||
SELECT
|
||||
'2026年第八师团场农业技术人才户外招聘会',
|
||||
'第八师农业农村局',
|
||||
'行业专场',
|
||||
'第八师(石河子市)',
|
||||
'石河子市人民广场东侧',
|
||||
50,
|
||||
TIMESTAMP '2026-08-08 09:00:00',
|
||||
TIMESTAMP '2026-08-08 17:00:00',
|
||||
TIMESTAMP '2026-07-20 00:00:00',
|
||||
TIMESTAMP '2026-08-02 23:59:59',
|
||||
FALSE,
|
||||
'https://picsum.photos/seed/shihezi-outdoor-6/400/300',
|
||||
'system',
|
||||
NOW(),
|
||||
'system',
|
||||
NOW(),
|
||||
'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM "cms_outdoor_fair" WHERE "title" = '2026年第八师团场农业技术人才户外招聘会');
|
||||
|
||||
INSERT INTO "cms_outdoor_fair" (
|
||||
"title", "host_unit", "fair_type", "region", "address", "booth_count",
|
||||
"hold_time", "end_time", "apply_start_time", "apply_end_time",
|
||||
"online_apply", "photo_url", "create_by", "create_time", "update_by", "update_time", "del_flag"
|
||||
)
|
||||
SELECT
|
||||
'2026年石河子市金秋就业援助户外招聘会',
|
||||
'石河子市公共就业和人才服务中心',
|
||||
'就业援助专场',
|
||||
'第八师(石河子市)',
|
||||
'石河子市幸福路步行街广场',
|
||||
70,
|
||||
TIMESTAMP '2026-09-19 09:30:00',
|
||||
TIMESTAMP '2026-09-19 17:30:00',
|
||||
TIMESTAMP '2026-09-01 00:00:00',
|
||||
TIMESTAMP '2026-09-13 23:59:59',
|
||||
TRUE,
|
||||
'https://picsum.photos/seed/shihezi-outdoor-7/400/300',
|
||||
'system',
|
||||
NOW(),
|
||||
'system',
|
||||
NOW(),
|
||||
'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM "cms_outdoor_fair" WHERE "title" = '2026年石河子市金秋就业援助户外招聘会');
|
||||
|
||||
INSERT INTO "cms_outdoor_fair" (
|
||||
"title", "host_unit", "fair_type", "region", "address", "booth_count",
|
||||
"hold_time", "end_time", "apply_start_time", "apply_end_time",
|
||||
"online_apply", "photo_url", "create_by", "create_time", "update_by", "update_time", "del_flag"
|
||||
)
|
||||
SELECT
|
||||
'2026年石河子市文旅商贸户外招聘会',
|
||||
'石河子市文化体育广电和旅游局',
|
||||
'文旅专场',
|
||||
'第八师(石河子市)',
|
||||
'石河子市北湖公园游客服务中心广场',
|
||||
40,
|
||||
TIMESTAMP '2026-10-24 10:00:00',
|
||||
TIMESTAMP '2026-10-24 17:00:00',
|
||||
TIMESTAMP '2026-10-01 00:00:00',
|
||||
TIMESTAMP '2026-10-18 23:59:59',
|
||||
FALSE,
|
||||
'https://picsum.photos/seed/shihezi-outdoor-8/400/300',
|
||||
'system',
|
||||
NOW(),
|
||||
'system',
|
||||
NOW(),
|
||||
'0'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM "cms_outdoor_fair" WHERE "title" = '2026年石河子市文旅商贸户外招聘会');
|
||||
86
sql/cms_venue_booth_map.sql
Normal file
86
sql/cms_venue_booth_map.sql
Normal file
@@ -0,0 +1,86 @@
|
||||
-- 场地展位图与户外招聘会展位预定
|
||||
-- 瀚高数据库 / PostgreSQL 兼容
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS "cms_venue_booth_id_seq" START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1;
|
||||
CREATE TABLE IF NOT EXISTS "cms_venue_booth" (
|
||||
"id" BIGINT NOT NULL DEFAULT nextval('"cms_venue_booth_id_seq"') PRIMARY KEY,
|
||||
"venue_id" BIGINT NOT NULL,
|
||||
"booth_number" VARCHAR(50) NOT NULL,
|
||||
"position_x" INTEGER NOT NULL DEFAULT 0,
|
||||
"position_y" INTEGER NOT NULL DEFAULT 0,
|
||||
"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_venue_booth" IS '场地展位图';
|
||||
COMMENT ON COLUMN "cms_venue_booth"."venue_id" IS '场地ID';
|
||||
COMMENT ON COLUMN "cms_venue_booth"."booth_number" IS '展位号';
|
||||
COMMENT ON COLUMN "cms_venue_booth"."position_x" IS 'X坐标';
|
||||
COMMENT ON COLUMN "cms_venue_booth"."position_y" IS 'Y坐标';
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "uk_cms_venue_booth_number" ON "cms_venue_booth" ("venue_id", "booth_number");
|
||||
CREATE INDEX IF NOT EXISTS "idx_cms_venue_booth_venue" ON "cms_venue_booth" ("venue_id");
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS "cms_outdoor_fair_booth_booking_id_seq" START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1;
|
||||
CREATE TABLE IF NOT EXISTS "cms_outdoor_fair_booth_booking" (
|
||||
"id" BIGINT NOT NULL DEFAULT nextval('"cms_outdoor_fair_booth_booking_id_seq"') PRIMARY KEY,
|
||||
"fair_id" BIGINT NOT NULL,
|
||||
"booth_id" BIGINT NOT NULL,
|
||||
"booth_number" VARCHAR(50) NOT NULL,
|
||||
"company_id" BIGINT,
|
||||
"company_name" VARCHAR(200),
|
||||
"status" VARCHAR(30) DEFAULT 'reserved',
|
||||
"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_outdoor_fair_booth_booking" IS '户外招聘会展位预定';
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "uk_cms_outdoor_fair_booth_booking" ON "cms_outdoor_fair_booth_booking" ("fair_id", "booth_id");
|
||||
CREATE INDEX IF NOT EXISTS "idx_cms_outdoor_fair_booth_booking_fair" ON "cms_outdoor_fair_booth_booking" ("fair_id");
|
||||
|
||||
WITH target_venue AS (
|
||||
SELECT "id" AS venue_id
|
||||
FROM "cms_venue_info"
|
||||
WHERE "venue_name" = '石河子市人民广场户外招聘区'
|
||||
LIMIT 1
|
||||
),
|
||||
seed AS (
|
||||
SELECT
|
||||
target_venue.venue_id,
|
||||
'KJ' || LPAD(gs::text, 2, '0') AS booth_number,
|
||||
40 + ((gs - 1) % 20) * 54 AS position_x,
|
||||
40 + ((gs - 1) / 20) * 54 AS position_y
|
||||
FROM target_venue
|
||||
CROSS JOIN generate_series(1, 80) gs
|
||||
)
|
||||
INSERT INTO "cms_venue_booth" ("venue_id", "booth_number", "position_x", "position_y", "create_by", "create_time", "del_flag")
|
||||
SELECT seed.venue_id, seed.booth_number, seed.position_x, seed.position_y, 'system', NOW(), '0'
|
||||
FROM seed
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "cms_venue_booth" existing
|
||||
WHERE existing."venue_id" = seed.venue_id
|
||||
AND existing."booth_number" = seed.booth_number
|
||||
);
|
||||
|
||||
UPDATE "cms_venue_info" venue
|
||||
SET "floor_count" = booth_counts.total
|
||||
FROM (
|
||||
SELECT "venue_id", COUNT(*) AS total
|
||||
FROM "cms_venue_booth"
|
||||
GROUP BY "venue_id"
|
||||
) booth_counts
|
||||
WHERE venue."id" = booth_counts."venue_id";
|
||||
|
||||
UPDATE "cms_outdoor_fair" fair
|
||||
SET "booth_count" = venue."floor_count"
|
||||
FROM "cms_venue_info" venue
|
||||
WHERE fair."venue_id" = venue."id";
|
||||
215
sql/cms_venue_info.sql
Normal file
215
sql/cms_venue_info.sql
Normal file
@@ -0,0 +1,215 @@
|
||||
-- 场地信息维护表、字典、菜单
|
||||
-- 瀚高数据库 / PostgreSQL 兼容
|
||||
-- 可重复执行。
|
||||
|
||||
CREATE SEQUENCE IF NOT EXISTS "cms_venue_info_id_seq"
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "cms_venue_info" (
|
||||
"id" BIGINT NOT NULL DEFAULT nextval('"cms_venue_info_id_seq"') PRIMARY KEY,
|
||||
"venue_type" VARCHAR(100) NOT NULL,
|
||||
"venue_name" VARCHAR(200) NOT NULL,
|
||||
"venue_area" NUMERIC(12, 2),
|
||||
"floor_count" INTEGER,
|
||||
"venue_address" VARCHAR(500) NOT NULL,
|
||||
"contact_phone" VARCHAR(50),
|
||||
"route_line_ids" VARCHAR(500),
|
||||
"route_line_names" VARCHAR(1000),
|
||||
"handle_date" DATE,
|
||||
"handle_org" VARCHAR(200),
|
||||
"handler" VARCHAR(100),
|
||||
"create_by" VARCHAR(64) DEFAULT '',
|
||||
"create_time" TIMESTAMP(0),
|
||||
"update_by" VARCHAR(64) DEFAULT '',
|
||||
"update_time" TIMESTAMP(0),
|
||||
"remark" VARCHAR(100),
|
||||
"del_flag" CHAR(1) DEFAULT '0'
|
||||
);
|
||||
|
||||
COMMENT ON TABLE "cms_venue_info" IS '场地信息维护表';
|
||||
COMMENT ON COLUMN "cms_venue_info"."id" IS '主键ID';
|
||||
COMMENT ON COLUMN "cms_venue_info"."venue_type" IS '场地类型';
|
||||
COMMENT ON COLUMN "cms_venue_info"."venue_name" IS '场地名称';
|
||||
COMMENT ON COLUMN "cms_venue_info"."venue_area" IS '场地面积';
|
||||
COMMENT ON COLUMN "cms_venue_info"."floor_count" IS '展位数量';
|
||||
COMMENT ON COLUMN "cms_venue_info"."venue_address" IS '场地地址';
|
||||
COMMENT ON COLUMN "cms_venue_info"."contact_phone" IS '联系电话';
|
||||
COMMENT ON COLUMN "cms_venue_info"."route_line_ids" IS '乘坐线路ID,多个用英文逗号分隔';
|
||||
COMMENT ON COLUMN "cms_venue_info"."route_line_names" IS '乘坐线路名称,多个用英文逗号分隔';
|
||||
COMMENT ON COLUMN "cms_venue_info"."handle_date" IS '经办日期';
|
||||
COMMENT ON COLUMN "cms_venue_info"."handle_org" IS '经办机构';
|
||||
COMMENT ON COLUMN "cms_venue_info"."handler" IS '经办人';
|
||||
COMMENT ON COLUMN "cms_venue_info"."remark" IS '备注';
|
||||
COMMENT ON COLUMN "cms_venue_info"."del_flag" IS '删除标志(0代表存在 2代表删除)';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "idx_cms_venue_info_type" ON "cms_venue_info" ("venue_type");
|
||||
CREATE INDEX IF NOT EXISTS "idx_cms_venue_info_name" ON "cms_venue_info" ("venue_name");
|
||||
CREATE INDEX IF NOT EXISTS "idx_cms_venue_info_del_flag" ON "cms_venue_info" ("del_flag");
|
||||
|
||||
INSERT INTO "sys_dict_type" (
|
||||
"dict_id", "dict_name", "dict_type", "status", "create_by", "create_time", "remark"
|
||||
)
|
||||
SELECT
|
||||
(SELECT COALESCE(MAX("dict_id"), 0) + 1 FROM "sys_dict_type"),
|
||||
'场地类型',
|
||||
'venue_info_type',
|
||||
'0',
|
||||
'system',
|
||||
NOW(),
|
||||
'场地信息维护使用'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM "sys_dict_type" WHERE "dict_type" = 'venue_info_type'
|
||||
);
|
||||
|
||||
WITH seed("dict_sort", "dict_label", "dict_value", "list_class", "is_default") AS (
|
||||
VALUES
|
||||
(1, '智能化招聘场馆', '智能化招聘场馆', 'primary', 'Y'),
|
||||
(2, '户外招聘广场', '户外招聘广场', 'success', 'N'),
|
||||
(3, '高校招聘场地', '高校招聘场地', 'processing', 'N'),
|
||||
(4, '园区招聘场地', '园区招聘场地', 'cyan', 'N'),
|
||||
(5, '临时招聘场地', '临时招聘场地', 'warning', 'N'),
|
||||
(6, '其他', '其他', 'default', 'N')
|
||||
),
|
||||
new_rows AS (
|
||||
SELECT
|
||||
ROW_NUMBER() OVER (ORDER BY seed."dict_sort") AS rn,
|
||||
seed.*
|
||||
FROM seed
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "sys_dict_data" data
|
||||
WHERE data."dict_type" = 'venue_info_type'
|
||||
AND data."dict_value" = seed."dict_value"
|
||||
)
|
||||
),
|
||||
base AS (
|
||||
SELECT COALESCE(MAX("dict_code"), 0) AS max_code FROM "sys_dict_data"
|
||||
)
|
||||
INSERT INTO "sys_dict_data" (
|
||||
"dict_code", "dict_sort", "dict_label", "dict_value", "dict_type",
|
||||
"css_class", "list_class", "is_default", "status", "create_by", "create_time", "remark"
|
||||
)
|
||||
SELECT
|
||||
base.max_code + new_rows.rn,
|
||||
new_rows."dict_sort",
|
||||
new_rows."dict_label",
|
||||
new_rows."dict_value",
|
||||
'venue_info_type',
|
||||
NULL,
|
||||
new_rows."list_class",
|
||||
new_rows."is_default",
|
||||
'0',
|
||||
'system',
|
||||
NOW(),
|
||||
'场地类型'
|
||||
FROM new_rows
|
||||
CROSS JOIN base;
|
||||
|
||||
WITH parent_menu AS (
|
||||
SELECT "menu_id" FROM "sys_menu" WHERE "menu_id" = 2055
|
||||
),
|
||||
inserted_page AS (
|
||||
INSERT INTO "sys_menu" (
|
||||
"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
|
||||
'场地信息维护',
|
||||
parent_menu."menu_id",
|
||||
2,
|
||||
'jobfair/venueinfo',
|
||||
'jobfair/venueinfo/index',
|
||||
NULL,
|
||||
'',
|
||||
1,
|
||||
0,
|
||||
'C',
|
||||
'0',
|
||||
'0',
|
||||
'cms:venueInfo:list',
|
||||
'#',
|
||||
'system',
|
||||
NOW(),
|
||||
'场地信息维护菜单'
|
||||
FROM parent_menu
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM "sys_menu" WHERE "parent_id" = parent_menu."menu_id" AND "menu_name" = '场地信息维护'
|
||||
)
|
||||
RETURNING "menu_id"
|
||||
),
|
||||
page_menu AS (
|
||||
SELECT "menu_id" FROM inserted_page
|
||||
UNION
|
||||
SELECT "menu_id" FROM "sys_menu" WHERE "parent_id" = 2055 AND "menu_name" = '场地信息维护'
|
||||
),
|
||||
button_seed("menu_name", "order_num", "perms") AS (
|
||||
VALUES
|
||||
('场地信息查询', 1, 'cms:venueInfo:query'),
|
||||
('场地信息新增', 2, 'cms:venueInfo:add'),
|
||||
('场地信息修改', 3, 'cms:venueInfo:edit'),
|
||||
('场地信息删除', 4, 'cms:venueInfo:remove')
|
||||
)
|
||||
INSERT INTO "sys_menu" (
|
||||
"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
|
||||
button_seed."menu_name",
|
||||
page_menu."menu_id",
|
||||
button_seed."order_num",
|
||||
'',
|
||||
NULL,
|
||||
NULL,
|
||||
'',
|
||||
1,
|
||||
0,
|
||||
'F',
|
||||
'0',
|
||||
'0',
|
||||
button_seed."perms",
|
||||
'#',
|
||||
'system',
|
||||
NOW(),
|
||||
'场地信息维护按钮'
|
||||
FROM page_menu
|
||||
CROSS JOIN button_seed
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM "sys_menu" WHERE "perms" = button_seed."perms"
|
||||
);
|
||||
|
||||
WITH outdoor_roles AS (
|
||||
SELECT DISTINCT "role_id"
|
||||
FROM "sys_role_menu"
|
||||
WHERE "menu_id" = 2111
|
||||
),
|
||||
venue_menus AS (
|
||||
SELECT "menu_id"
|
||||
FROM "sys_menu"
|
||||
WHERE ("parent_id" = 2055 AND "menu_name" = '场地信息维护')
|
||||
OR "perms" IN (
|
||||
'cms:venueInfo:query',
|
||||
'cms:venueInfo:add',
|
||||
'cms:venueInfo:edit',
|
||||
'cms:venueInfo:remove'
|
||||
)
|
||||
),
|
||||
role_menu_rows AS (
|
||||
SELECT outdoor_roles."role_id", venue_menus."menu_id"
|
||||
FROM outdoor_roles
|
||||
CROSS JOIN venue_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"
|
||||
);
|
||||
90
sql/migration_interview_menu.sql
Normal file
90
sql/migration_interview_menu.sql
Normal file
@@ -0,0 +1,90 @@
|
||||
-- =====================================================
|
||||
-- 面试列表 - 菜单权限配置 SQL
|
||||
-- 在 岗位管理 菜单下增加"面试列表"子菜单及按钮权限
|
||||
--
|
||||
-- 执行前请确认:
|
||||
-- 1. 确认 parent_id:面试列表将放在 "岗位管理" 目录下
|
||||
-- 如果数据库中岗位管理目录的 menu_id 不同,请修改下面子查询中的条件
|
||||
-- 2. sys_menu 表使用自增主键(auto_increment=2000),
|
||||
-- 本脚本使用 2100+ 的固定ID,避免与已有数据冲突
|
||||
-- 3. 执行后需要在"角色管理"中将新菜单分配给对应角色
|
||||
-- =====================================================
|
||||
|
||||
-- Step 1: 新增菜单项(C=菜单页面)
|
||||
-- parent_id 动态查找:path='management' 的目录菜单
|
||||
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, update_by, update_time, remark)
|
||||
SELECT 2100, '面试列表',
|
||||
(SELECT menu_id FROM sys_menu WHERE path = 'management' AND menu_type = 'M' LIMIT 1),
|
||||
10, 'interview-list', 'Management/InterviewList', '', 'InterviewList', 1, 0, 'C', '0', '0',
|
||||
'cms:interview:list', 'message', 'admin', CURRENT_TIMESTAMP, '', null, '面试列表菜单'
|
||||
WHERE EXISTS (SELECT 1 FROM sys_menu WHERE path = 'management' AND menu_type = 'M');
|
||||
|
||||
-- Step 2: 新增按钮权限(F=按钮)
|
||||
-- 面试查询
|
||||
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, update_by, update_time, remark)
|
||||
SELECT 2101, '面试查询', 2100, 1, '', '', '', '', 1, 0, 'F', '0', '0',
|
||||
'cms:interview:query', '#', 'admin', CURRENT_TIMESTAMP, '', null, ''
|
||||
WHERE EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2100);
|
||||
|
||||
-- 面试新增
|
||||
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, update_by, update_time, remark)
|
||||
SELECT 2102, '面试新增', 2100, 2, '', '', '', '', 1, 0, 'F', '0', '0',
|
||||
'cms:interview:add', '#', 'admin', CURRENT_TIMESTAMP, '', null, ''
|
||||
WHERE EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2100);
|
||||
|
||||
-- 面试修改
|
||||
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, update_by, update_time, remark)
|
||||
SELECT 2103, '面试修改', 2100, 3, '', '', '', '', 1, 0, 'F', '0', '0',
|
||||
'cms:interview:edit', '#', 'admin', CURRENT_TIMESTAMP, '', null, ''
|
||||
WHERE EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2100);
|
||||
|
||||
-- 面试删除
|
||||
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, update_by, update_time, remark)
|
||||
SELECT 2104, '面试删除', 2100, 4, '', '', '', '', 1, 0, 'F', '0', '0',
|
||||
'cms:interview:remove', '#', 'admin', CURRENT_TIMESTAMP, '', null, ''
|
||||
WHERE EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2100);
|
||||
|
||||
-- Step 3: 将新菜单分配给角色
|
||||
-- 为所有非管理员角色分配面试列表权限(管理员角色无需分配,通配符 *:*:* 自动拥有全部权限)
|
||||
-- 如需仅限特定角色,请修改 WHERE 条件
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT r.role_id, 2100
|
||||
FROM sys_role r
|
||||
WHERE r.role_key != 'admin'
|
||||
AND EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2100);
|
||||
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT r.role_id, 2101
|
||||
FROM sys_role r
|
||||
WHERE r.role_key != 'admin'
|
||||
AND EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2101);
|
||||
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT r.role_id, 2102
|
||||
FROM sys_role r
|
||||
WHERE r.role_key != 'admin'
|
||||
AND EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2102);
|
||||
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT r.role_id, 2103
|
||||
FROM sys_role r
|
||||
WHERE r.role_key != 'admin'
|
||||
AND EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2103);
|
||||
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT r.role_id, 2104
|
||||
FROM sys_role r
|
||||
WHERE r.role_key != 'admin'
|
||||
AND EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2104);
|
||||
|
||||
-- =====================================================
|
||||
-- 验证 SQL(可选执行)
|
||||
-- =====================================================
|
||||
-- 检查菜单是否创建成功
|
||||
-- SELECT * FROM sys_menu WHERE menu_id BETWEEN 2100 AND 2104;
|
||||
|
||||
-- 检查角色菜单关联
|
||||
-- SELECT r.role_name, m.menu_name FROM sys_role_menu rm
|
||||
-- JOIN sys_role r ON r.role_id = rm.role_id
|
||||
-- JOIN sys_menu m ON m.menu_id = rm.menu_id
|
||||
-- WHERE rm.menu_id BETWEEN 2100 AND 2104;
|
||||
70
sql/sys_dict_outdoor_fair_region.sql
Normal file
70
sql/sys_dict_outdoor_fair_region.sql
Normal file
@@ -0,0 +1,70 @@
|
||||
-- 户外招聘会举办区域系统字典
|
||||
-- 可重复执行:按 dict_type / dict_value 去重。
|
||||
|
||||
INSERT INTO "sys_dict_type" (
|
||||
"dict_id", "dict_name", "dict_type", "status", "create_by", "create_time", "remark"
|
||||
)
|
||||
SELECT
|
||||
(SELECT COALESCE(MAX("dict_id"), 0) + 1 FROM "sys_dict_type"),
|
||||
'户外招聘会举办区域',
|
||||
'outdoor_fair_region',
|
||||
'0',
|
||||
'system',
|
||||
NOW(),
|
||||
'户外招聘会管理使用'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM "sys_dict_type" WHERE "dict_type" = 'outdoor_fair_region'
|
||||
);
|
||||
|
||||
WITH seed("dict_sort", "dict_label", "dict_value", "list_class", "is_default") AS (
|
||||
VALUES
|
||||
(1, '石河子市', '石河子市', 'primary', 'N'),
|
||||
(2, '第一师(阿拉尔市)', '第一师(阿拉尔市)', 'default', 'N'),
|
||||
(3, '第二师(铁门关市)', '第二师(铁门关市)', 'default', 'N'),
|
||||
(4, '第三师(图木舒克市)', '第三师(图木舒克市)', 'default', 'N'),
|
||||
(5, '第四师(可克达拉市)', '第四师(可克达拉市)', 'default', 'N'),
|
||||
(6, '第五师(双河市)', '第五师(双河市)', 'default', 'N'),
|
||||
(7, '第六师(五家渠市)', '第六师(五家渠市)', 'default', 'N'),
|
||||
(8, '第七师(胡杨河市)', '第七师(胡杨河市)', 'default', 'N'),
|
||||
(9, '第八师(石河子市)', '第八师(石河子市)', 'success', 'Y'),
|
||||
(10, '第九师(白杨市)', '第九师(白杨市)', 'default', 'N'),
|
||||
(11, '第十师(北屯市)', '第十师(北屯市)', 'default', 'N'),
|
||||
(12, '第十一师(建工师)', '第十一师(建工师)', 'default', 'N'),
|
||||
(13, '第十二师', '第十二师', 'default', 'N'),
|
||||
(14, '第十三师(新星市)', '第十三师(新星市)', 'default', 'N'),
|
||||
(15, '第十四师(昆玉市)', '第十四师(昆玉市)', 'default', 'N')
|
||||
),
|
||||
new_rows AS (
|
||||
SELECT
|
||||
ROW_NUMBER() OVER (ORDER BY seed."dict_sort") AS rn,
|
||||
seed.*
|
||||
FROM seed
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "sys_dict_data" data
|
||||
WHERE data."dict_type" = 'outdoor_fair_region'
|
||||
AND data."dict_value" = seed."dict_value"
|
||||
)
|
||||
),
|
||||
base AS (
|
||||
SELECT COALESCE(MAX("dict_code"), 0) AS max_code FROM "sys_dict_data"
|
||||
)
|
||||
INSERT INTO "sys_dict_data" (
|
||||
"dict_code", "dict_sort", "dict_label", "dict_value", "dict_type",
|
||||
"css_class", "list_class", "is_default", "status", "create_by", "create_time", "remark"
|
||||
)
|
||||
SELECT
|
||||
base.max_code + new_rows.rn,
|
||||
new_rows."dict_sort",
|
||||
new_rows."dict_label",
|
||||
new_rows."dict_value",
|
||||
'outdoor_fair_region',
|
||||
NULL,
|
||||
new_rows."list_class",
|
||||
new_rows."is_default",
|
||||
'0',
|
||||
'system',
|
||||
NOW(),
|
||||
'户外招聘会举办区域'
|
||||
FROM new_rows
|
||||
CROSS JOIN base;
|
||||
64
sql/sys_dict_outdoor_fair_type.sql
Normal file
64
sql/sys_dict_outdoor_fair_type.sql
Normal file
@@ -0,0 +1,64 @@
|
||||
-- 户外招聘会类型系统字典
|
||||
-- 可重复执行:按 dict_type / dict_value 去重。
|
||||
|
||||
INSERT INTO "sys_dict_type" (
|
||||
"dict_id", "dict_name", "dict_type", "status", "create_by", "create_time", "remark"
|
||||
)
|
||||
SELECT
|
||||
(SELECT COALESCE(MAX("dict_id"), 0) + 1 FROM "sys_dict_type"),
|
||||
'户外招聘会类型',
|
||||
'outdoor_fair_type',
|
||||
'0',
|
||||
'system',
|
||||
NOW(),
|
||||
'户外招聘会管理使用'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM "sys_dict_type" WHERE "dict_type" = 'outdoor_fair_type'
|
||||
);
|
||||
|
||||
WITH seed("dict_sort", "dict_label", "dict_value", "list_class", "is_default") AS (
|
||||
VALUES
|
||||
(1, '综合类', '综合类', 'primary', 'Y'),
|
||||
(2, '校园招聘', '校园招聘', 'success', 'N'),
|
||||
(3, '行业专场', '行业专场', 'processing', 'N'),
|
||||
(4, '高新技术专场', '高新技术专场', 'purple', 'N'),
|
||||
(5, '智能制造专场', '智能制造专场', 'cyan', 'N'),
|
||||
(6, '服务业专场', '服务业专场', 'blue', 'N'),
|
||||
(7, '就业援助专场', '就业援助专场', 'warning', 'N'),
|
||||
(8, '文旅专场', '文旅专场', 'magenta', 'N'),
|
||||
(9, '其他', '其他', 'default', 'N')
|
||||
),
|
||||
new_rows AS (
|
||||
SELECT
|
||||
ROW_NUMBER() OVER (ORDER BY seed."dict_sort") AS rn,
|
||||
seed.*
|
||||
FROM seed
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM "sys_dict_data" data
|
||||
WHERE data."dict_type" = 'outdoor_fair_type'
|
||||
AND data."dict_value" = seed."dict_value"
|
||||
)
|
||||
),
|
||||
base AS (
|
||||
SELECT COALESCE(MAX("dict_code"), 0) AS max_code FROM "sys_dict_data"
|
||||
)
|
||||
INSERT INTO "sys_dict_data" (
|
||||
"dict_code", "dict_sort", "dict_label", "dict_value", "dict_type",
|
||||
"css_class", "list_class", "is_default", "status", "create_by", "create_time", "remark"
|
||||
)
|
||||
SELECT
|
||||
base.max_code + new_rows.rn,
|
||||
new_rows."dict_sort",
|
||||
new_rows."dict_label",
|
||||
new_rows."dict_value",
|
||||
'outdoor_fair_type',
|
||||
NULL,
|
||||
new_rows."list_class",
|
||||
new_rows."is_default",
|
||||
'0',
|
||||
'system',
|
||||
NOW(),
|
||||
'户外招聘会类型'
|
||||
FROM new_rows
|
||||
CROSS JOIN base;
|
||||
204
启动指南.md
Normal file
204
启动指南.md
Normal file
@@ -0,0 +1,204 @@
|
||||
# 石河子后端服务 - 手动启动指南
|
||||
|
||||
## 项目概述
|
||||
|
||||
- **框架**: RuoYi (若依) v3.8.8 / Spring Boot 2.5.15
|
||||
- **语言**: Java 1.8 (兼容 Java 21)
|
||||
- **构建工具**: Maven 3.9+
|
||||
- **默认端口**: `9091`
|
||||
- **主启动类**: `com.ruoyi.RuoYiApplication`
|
||||
|
||||
---
|
||||
|
||||
## 1. 环境要求
|
||||
|
||||
| 依赖 | 当前环境 | 备注 |
|
||||
|------|----------|------|
|
||||
| **JDK** | 21.0.11 (Temurin) | 路径: `C:\Program Files\Eclipse Adoptium\jdk-21.0.11.10-hotspot` |
|
||||
| **Maven** | 3.9.9 | 路径: `C:\Users\franc\apache-maven-3.9.9` |
|
||||
| **数据库** | Highgo DB (远程) | `39.98.44.136:6023` (local 配置) |
|
||||
| **Redis** | 远程 | `124.243.245.42:5379` (local 配置) |
|
||||
| **Elasticsearch** | 远程 | `124.243.245.42:9200` (local 配置) |
|
||||
|
||||
---
|
||||
|
||||
## 2. 环境变量设置
|
||||
|
||||
### Git Bash / WSL
|
||||
|
||||
```bash
|
||||
export PATH="/c/Users/franc/apache-maven-3.9.9/bin:$PATH"
|
||||
```
|
||||
|
||||
### 永久生效 (可选)
|
||||
|
||||
将上述 export 命令添加到 `~/.bashrc` 末尾:
|
||||
|
||||
```bash
|
||||
echo 'export PATH="/c/Users/franc/apache-maven-3.9.9/bin:$PATH"' >> ~/.bashrc
|
||||
```
|
||||
|
||||
### 验证安装
|
||||
|
||||
```bash
|
||||
java -version # 应显示 OpenJDK 21
|
||||
mvn -version # 应显示 Apache Maven 3.9.9
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 构建项目
|
||||
|
||||
```bash
|
||||
# 进入后端项目目录
|
||||
cd shz-backend
|
||||
|
||||
# 清理并构建(跳过测试,4线程并行编译)
|
||||
mvn clean install -DskipTests -T 4
|
||||
```
|
||||
|
||||
> **构建产物**: `ruoyi-admin/target/ruoyi-admin.jar`
|
||||
|
||||
---
|
||||
|
||||
## 4. 启动服务
|
||||
|
||||
### 前台运行(用于调试,Ctrl+C 停止)
|
||||
|
||||
```bash
|
||||
cd shz-backend
|
||||
java -jar ruoyi-admin/target/ruoyi-admin.jar --spring.profiles.active=local
|
||||
```
|
||||
|
||||
### 后台运行
|
||||
|
||||
```bash
|
||||
cd shz-backend
|
||||
|
||||
# 创建日志目录
|
||||
mkdir -p logs
|
||||
|
||||
# 后台启动
|
||||
nohup java -jar ruoyi-admin/target/ruoyi-admin.jar \
|
||||
--spring.profiles.active=local \
|
||||
>> logs/backend.log 2>&1 &
|
||||
|
||||
# 跟踪日志
|
||||
tail -f logs/backend.log
|
||||
```
|
||||
|
||||
### JVM 参数调优(可选)
|
||||
|
||||
```bash
|
||||
java -Xms2048M -Xmx2048M -jar ruoyi-admin/target/ruoyi-admin.jar \
|
||||
--spring.profiles.active=local
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 验证服务
|
||||
|
||||
```bash
|
||||
# 检查服务首页
|
||||
curl http://localhost:9091/
|
||||
# 返回: 欢迎使用RuoYi后台管理框架,当前版本:v3.8.8
|
||||
|
||||
# 检查 Swagger API 文档
|
||||
curl -s -o /dev/null -w "HTTP: %{http_code}" http://localhost:9091/swagger-ui/index.html
|
||||
# 返回: HTTP: 200
|
||||
|
||||
# 检查 Druid 监控面板
|
||||
# 浏览器访问: http://localhost:9091/druid/
|
||||
# 账号: ruoyi / 123456
|
||||
|
||||
# 查看运行中的进程
|
||||
jps -l | grep ruoyi
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 停止服务
|
||||
|
||||
```bash
|
||||
# 方法一: 查找并终止(推荐)
|
||||
jps -l | grep ruoyi # 查找 PID
|
||||
kill <PID> # 优雅关闭
|
||||
|
||||
# 方法二: 按端口查找
|
||||
netstat -ano | findstr 9091 # Windows
|
||||
lsof -i :9091 # Linux/Mac
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 可用配置 Profile
|
||||
|
||||
| Profile | 配置文件 | 数据库 | 端口 |
|
||||
|---------|----------|--------|------|
|
||||
| `dev` | [`application-dev.yml`](ruoyi-admin/src/main/resources/application-dev.yml) | 内网 `172.31.9.107:8765` | `9091` |
|
||||
| `local` | [`application-local.yml`](ruoyi-admin/src/main/resources/application-local.yml) | 外网 `39.98.44.136:6023` | `9091` |
|
||||
|
||||
默认激活 Profile 在 [`application.yml`](ruoyi-admin/src/main/resources/application.yml) 的 `spring.profiles.active` 中配置。
|
||||
|
||||
---
|
||||
|
||||
## 8. 构建常见问题
|
||||
|
||||
### 编译错误: `NoSuchFieldError: JCTree$JCImport qualid`
|
||||
|
||||
Lombok 版本与 JDK 21 不兼容。确保 `pom.xml` 中 Lombok 版本 ≥ 1.18.32:
|
||||
|
||||
```xml
|
||||
<lombok.version>1.18.34</lombok.version>
|
||||
```
|
||||
|
||||
### 编译错误: `maven-compiler-plugin` 版本过低
|
||||
|
||||
需要 `maven-compiler-plugin` ≥ 3.11.0 才支持 JDK 21:
|
||||
|
||||
```xml
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
</plugin>
|
||||
```
|
||||
|
||||
### Maven 下载依赖缓慢
|
||||
|
||||
项目已配置阿里云 Maven 镜像(`maven.aliyun.com`),无需额外配置。
|
||||
|
||||
---
|
||||
|
||||
## 9. 项目结构
|
||||
|
||||
```
|
||||
shz-backend/
|
||||
├── pom.xml # 根 POM(依赖管理)
|
||||
├── ruoyi-admin/ # Web 入口模块(Spring Boot 启动类)
|
||||
│ └── src/main/resources/
|
||||
│ ├── application.yml # 主配置
|
||||
│ ├── application-dev.yml # 开发环境
|
||||
│ └── application-local.yml # 本地环境
|
||||
├── ruoyi-common/ # 通用工具模块
|
||||
├── ruoyi-framework/ # 核心框架模块
|
||||
├── ruoyi-system/ # 系统管理模块
|
||||
├── ruoyi-bussiness/ # 业务模块
|
||||
├── ruoyi-quartz/ # 定时任务模块
|
||||
├── ruoyi-generator/ # 代码生成模块
|
||||
├── sql/ # 数据库脚本
|
||||
├── docs/ # 项目文档
|
||||
└── buildAndStart.sh # Linux 部署脚本
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 相关服务地址
|
||||
|
||||
| 服务 | 地址 |
|
||||
|------|------|
|
||||
| 后端 API | `http://localhost:9091/` |
|
||||
| Swagger 文档 | `http://localhost:9091/swagger-ui/index.html` |
|
||||
| Druid 监控 | `http://localhost:9091/druid/` |
|
||||
| 管理后台前端 | `shz-admin/` 目录(需单独启动) |
|
||||
| 微信小程序 | `shzApp/` 目录(uniapp 项目) |
|
||||
Reference in New Issue
Block a user