From 12076c5d0b862881d39e7659f8c433fbb5b51c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E6=98=8A?= Date: Tue, 26 May 2026 19:19:12 +0800 Subject: [PATCH] =?UTF-8?q?feat(hrm):=20=E6=96=B0=E5=A2=9E=E5=91=98?= =?UTF-8?q?=E5=B7=A5=E7=B4=A7=E6=80=A5=E8=81=94=E7=B3=BB=E4=BA=BA=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 完成员工紧急联系人模块的全流程开发,包括: 1. 数据库表结构、Mapper、Service、Controller后端代码 2. 前端页面、API接口、导入导出功能 3. 配套SQL脚本、导入模板与使用文档 4. 支持批量导入导出、数据校验与用户关联匹配 --- .../HrmEmergencyContactController.java | 117 +++++ .../ruoyi/hrm/domain/HrmEmergencyContact.java | 39 ++ .../hrm/domain/bo/HrmEmergencyContactBo.java | 45 ++ .../vo/HrmEmergencyContactImportVo.java | 138 ++++++ .../hrm/domain/vo/HrmEmergencyContactVo.java | 72 +++ .../hrm/mapper/HrmEmergencyContactMapper.java | 8 + .../service/IHrmEmergencyContactService.java | 27 ++ .../impl/HrmEmergencyContactServiceImpl.java | 254 ++++++++++ .../mapper/HrmEmergencyContactMapper.xml | 27 ++ ruoyi-ui/src/api/hrm/emergencyContact.js | 55 +++ ruoyi-ui/src/api/hrm/index.js | 1 + .../src/views/hrm/emergencyContact/index.vue | 449 ++++++++++++++++++ sql/hrm_emergency_contact.sql | 41 ++ sql/hrm_emergency_contact_cleanup.sql | 30 ++ sql/hrm_emergency_contact_manual_guide.md | 115 +++++ sql/hrm_emergency_contact_menu.sql | 42 ++ sql/hrm_emergency_contact_sample_data.sql | 24 + sql/信息部紧急联系人导入.xlsx | Bin 0 -> 6556 bytes sql/紧急联系人导入模板示例.xlsx | 25 + 19 files changed, 1509 insertions(+) create mode 100644 fad-hrm/src/main/java/com/ruoyi/hrm/controller/HrmEmergencyContactController.java create mode 100644 fad-hrm/src/main/java/com/ruoyi/hrm/domain/HrmEmergencyContact.java create mode 100644 fad-hrm/src/main/java/com/ruoyi/hrm/domain/bo/HrmEmergencyContactBo.java create mode 100644 fad-hrm/src/main/java/com/ruoyi/hrm/domain/vo/HrmEmergencyContactImportVo.java create mode 100644 fad-hrm/src/main/java/com/ruoyi/hrm/domain/vo/HrmEmergencyContactVo.java create mode 100644 fad-hrm/src/main/java/com/ruoyi/hrm/mapper/HrmEmergencyContactMapper.java create mode 100644 fad-hrm/src/main/java/com/ruoyi/hrm/service/IHrmEmergencyContactService.java create mode 100644 fad-hrm/src/main/java/com/ruoyi/hrm/service/impl/HrmEmergencyContactServiceImpl.java create mode 100644 fad-hrm/src/main/resources/mapper/HrmEmergencyContactMapper.xml create mode 100644 ruoyi-ui/src/api/hrm/emergencyContact.js create mode 100644 ruoyi-ui/src/views/hrm/emergencyContact/index.vue create mode 100644 sql/hrm_emergency_contact.sql create mode 100644 sql/hrm_emergency_contact_cleanup.sql create mode 100644 sql/hrm_emergency_contact_manual_guide.md create mode 100644 sql/hrm_emergency_contact_menu.sql create mode 100644 sql/hrm_emergency_contact_sample_data.sql create mode 100644 sql/信息部紧急联系人导入.xlsx create mode 100644 sql/紧急联系人导入模板示例.xlsx diff --git a/fad-hrm/src/main/java/com/ruoyi/hrm/controller/HrmEmergencyContactController.java b/fad-hrm/src/main/java/com/ruoyi/hrm/controller/HrmEmergencyContactController.java new file mode 100644 index 0000000..ca2edc1 --- /dev/null +++ b/fad-hrm/src/main/java/com/ruoyi/hrm/controller/HrmEmergencyContactController.java @@ -0,0 +1,117 @@ +package com.ruoyi.hrm.controller; + +import com.alibaba.excel.EasyExcel; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.hrm.domain.bo.HrmEmergencyContactBo; +import com.ruoyi.hrm.domain.vo.HrmEmergencyContactImportVo; +import com.ruoyi.hrm.domain.vo.HrmEmergencyContactVo; +import com.ruoyi.hrm.service.IHrmEmergencyContactService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/hrm/emergencyContact") +public class HrmEmergencyContactController extends BaseController { + + private final IHrmEmergencyContactService service; + + @GetMapping("/list") + public TableDataInfo list(HrmEmergencyContactBo bo, PageQuery pageQuery) { + return service.queryPageList(bo, pageQuery); + } + + @GetMapping("/{contactId}") + public R getInfo(@NotNull(message = "主键不能为空") @PathVariable Long contactId) { + return R.ok(service.queryById(contactId)); + } + + @Log(title = "紧急联系人管理", businessType = BusinessType.INSERT) + @PostMapping + public R add(@Validated @RequestBody HrmEmergencyContactBo bo) { + return toAjax(service.insertByBo(bo)); + } + + @Log(title = "紧急联系人管理", businessType = BusinessType.UPDATE) + @PutMapping + public R edit(@Validated @RequestBody HrmEmergencyContactBo bo) { + return toAjax(service.updateByBo(bo)); + } + + @Log(title = "紧急联系人管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{contactIds}") + public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] contactIds) { + return toAjax(service.deleteWithValidByIds(Arrays.asList(contactIds), true)); + } + + @Log(title = "紧急联系人管理", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HrmEmergencyContactBo bo, HttpServletResponse response) { + List list = service.queryList(bo); + ExcelUtil.exportExcel(list, "紧急联系人数据", HrmEmergencyContactVo.class, response); + } + + @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public R importData(@RequestPart("file") MultipartFile file, @RequestParam(defaultValue = "false") boolean updateSupport) throws IOException { + List list = ExcelUtil.importExcel(file.getInputStream(), HrmEmergencyContactImportVo.class, false).getList(); + String msg = service.importByVoList(list, updateSupport); + return R.ok(msg); + } + + @PostMapping("/importTemplate") + public void importTemplate(HttpServletResponse response) throws IOException { + // 设置响应头 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + String fileName = URLEncoder.encode("紧急联系人导入模板", "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); + + // 示例数据(字段名第一行,示例数据第二行) + List exampleList = new ArrayList<>(); + + // 添加示例数据 + HrmEmergencyContactImportVo example = new HrmEmergencyContactImportVo(); + example.setHireDate("2025.06.18"); + example.setCompanyName("山东福安德信息科技有限公司"); + example.setDeptName("信息化部"); + example.setRealName("张三"); + example.setPhone("183xxxxxxxx"); + example.setIdCard("341xxxxxxxxxxxxxxx"); + example.setGender("男"); + example.setAge(23); + example.setEmergencyContact("李四"); + example.setRelationship("母子"); + example.setEmergencyPhone1("159xxxxxxxx"); + example.setEmergencyPhone2(""); + example.setEmergencyAddress("xx省xx市xx县xx镇xx村"); + example.setRemark("仅紧急情况联系"); + exampleList.add(example); + + // 使用EasyExcel写入(字段名在第一行,示例数据在第二行) + ServletOutputStream out = response.getOutputStream(); + EasyExcel.write(out, HrmEmergencyContactImportVo.class) + .sheet("导入模板") + .doWrite(exampleList); + out.flush(); + } +} diff --git a/fad-hrm/src/main/java/com/ruoyi/hrm/domain/HrmEmergencyContact.java b/fad-hrm/src/main/java/com/ruoyi/hrm/domain/HrmEmergencyContact.java new file mode 100644 index 0000000..14dd260 --- /dev/null +++ b/fad-hrm/src/main/java/com/ruoyi/hrm/domain/HrmEmergencyContact.java @@ -0,0 +1,39 @@ +package com.ruoyi.hrm.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("hrm_emergency_contact") +public class HrmEmergencyContact extends BaseEntity implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.AUTO) + private Long contactId; + private Long userId; + private Long deptId; + private String realName; + private String phone; + private String idCard; + private String gender; + private Integer age; + private String companyName; + private Date hireDate; + private String emergencyContact; + private String relationship; + private String emergencyPhone1; + private String emergencyPhone2; + private String emergencyAddress; + private String remark; + @TableLogic + private Integer delFlag; +} diff --git a/fad-hrm/src/main/java/com/ruoyi/hrm/domain/bo/HrmEmergencyContactBo.java b/fad-hrm/src/main/java/com/ruoyi/hrm/domain/bo/HrmEmergencyContactBo.java new file mode 100644 index 0000000..a0c5fbc --- /dev/null +++ b/fad-hrm/src/main/java/com/ruoyi/hrm/domain/bo/HrmEmergencyContactBo.java @@ -0,0 +1,45 @@ +package com.ruoyi.hrm.domain.bo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +public class HrmEmergencyContactBo extends BaseEntity { + + private Long contactId; + + @NotNull(message = "用户ID不能为空") + private Long userId; + + private Long deptId; + private String realName; + private String phone; + private String idCard; + private String gender; + private Integer age; + private String companyName; + + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private Date hireDate; + + @NotBlank(message = "紧急联系人姓名不能为空") + private String emergencyContact; + + private String relationship; + + @NotBlank(message = "紧急联系人电话1不能为空") + private String emergencyPhone1; + + private String emergencyPhone2; + private String emergencyAddress; + private String remark; +} diff --git a/fad-hrm/src/main/java/com/ruoyi/hrm/domain/vo/HrmEmergencyContactImportVo.java b/fad-hrm/src/main/java/com/ruoyi/hrm/domain/vo/HrmEmergencyContactImportVo.java new file mode 100644 index 0000000..12c1362 --- /dev/null +++ b/fad-hrm/src/main/java/com/ruoyi/hrm/domain/vo/HrmEmergencyContactImportVo.java @@ -0,0 +1,138 @@ +package com.ruoyi.hrm.domain.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentStyle; +import com.alibaba.excel.annotation.write.style.HeadStyle; +import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum; +import com.ruoyi.common.annotation.Excel; +import lombok.Data; + +import java.io.Serializable; + +/** + * 紧急联系人导入 VO + * 与用户提供的Excel格式保持一致 + * + * Excel表头顺序: + * 入职时间 | 公司名称 | 部门 | 姓名 | 联系电话 | 身份证号 | 性别 | 年龄 | 紧急联系人 | 与本人关系 | 联系电话1 | 联系电话2 | 紧急联系人地址 | 备注 + */ +@Data +@HeadStyle(fillForegroundColor = 44, horizontalAlignment = HorizontalAlignmentEnum.CENTER) +@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT) +public class HrmEmergencyContactImportVo implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 入职时间 + * 格式:yyyy.MM.dd 或 yyyy-MM-dd + */ + @Excel(name = "入职时间", width = 12) + @ExcelProperty("入职时间") + @ColumnWidth(12) + private String hireDate; + + /** + * 公司名称 + */ + @Excel(name = "公司名称", width = 40) + @ExcelProperty("公司名称") + @ColumnWidth(40) + private String companyName; + + /** + * 部门 + */ + @Excel(name = "部门", width = 12) + @ExcelProperty("部门") + @ColumnWidth(12) + private String deptName; + + /** + * 姓名 + */ + @Excel(name = "姓名", width = 10) + @ExcelProperty("姓名") + @ColumnWidth(10) + private String realName; + + /** + * 联系电话 + */ + @Excel(name = "联系电话", width = 15) + @ExcelProperty("联系电话") + @ColumnWidth(15) + private String phone; + + /** + * 身份证号 + */ + @Excel(name = "身份证号", width = 22) + @ExcelProperty("身份证号") + @ColumnWidth(22) + private String idCard; + + /** + * 性别 + */ + @Excel(name = "性别", width = 8, readConverterExp = "男=0,女=1,未知=2") + @ExcelProperty("性别") + @ColumnWidth(8) + private String gender; + + /** + * 年龄 + */ + @Excel(name = "年龄", width = 8) + @ExcelProperty("年龄") + @ColumnWidth(8) + private Integer age; + + /** + * 紧急联系人 + */ + @Excel(name = "紧急联系人", width = 12) + @ExcelProperty("紧急联系人") + @ColumnWidth(12) + private String emergencyContact; + + /** + * 与本人关系 + */ + @Excel(name = "与本人关系", width = 12) + @ExcelProperty("与本人关系") + @ColumnWidth(12) + private String relationship; + + /** + * 联系电话1 + */ + @Excel(name = "联系电话1", width = 15) + @ExcelProperty("联系电话1") + @ColumnWidth(15) + private String emergencyPhone1; + + /** + * 联系电话2 + */ + @Excel(name = "联系电话2", width = 15) + @ExcelProperty("联系电话2") + @ColumnWidth(15) + private String emergencyPhone2; + + /** + * 紧急联系人地址 + */ + @Excel(name = "紧急联系人地址", width = 40) + @ExcelProperty("紧急联系人地址") + @ColumnWidth(40) + private String emergencyAddress; + + /** + * 备注 + */ + @Excel(name = "备注", width = 20) + @ExcelProperty("备注") + @ColumnWidth(20) + private String remark; +} diff --git a/fad-hrm/src/main/java/com/ruoyi/hrm/domain/vo/HrmEmergencyContactVo.java b/fad-hrm/src/main/java/com/ruoyi/hrm/domain/vo/HrmEmergencyContactVo.java new file mode 100644 index 0000000..63fe47c --- /dev/null +++ b/fad-hrm/src/main/java/com/ruoyi/hrm/domain/vo/HrmEmergencyContactVo.java @@ -0,0 +1,72 @@ +package com.ruoyi.hrm.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +public class HrmEmergencyContactVo implements Serializable { + private static final long serialVersionUID = 1L; + + @Excel(name = "联系人ID") + private Long contactId; + + @Excel(name = "用户ID") + private Long userId; + + @Excel(name = "部门ID") + private Long deptId; + + @Excel(name = "部门名称") + private String deptName; + + @Excel(name = "姓名") + private String realName; + + @Excel(name = "联系电话") + private String phone; + + @Excel(name = "身份证号") + private String idCard; + + @Excel(name = "性别", readConverterExp = "0=男,1=女,2=未知") + private String gender; + + @Excel(name = "年龄") + private Integer age; + + @Excel(name = "公司名称") + private String companyName; + + @Excel(name = "入职时间", width = 20, dateFormat = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date hireDate; + + @Excel(name = "紧急联系人") + private String emergencyContact; + + @Excel(name = "与本人关系") + private String relationship; + + @Excel(name = "紧急电话1") + private String emergencyPhone1; + + @Excel(name = "紧急电话2") + private String emergencyPhone2; + + @Excel(name = "紧急联系人地址") + private String emergencyAddress; + + @Excel(name = "备注") + private String remark; + + private String createBy; + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date createTime; + private String updateBy; + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date updateTime; +} diff --git a/fad-hrm/src/main/java/com/ruoyi/hrm/mapper/HrmEmergencyContactMapper.java b/fad-hrm/src/main/java/com/ruoyi/hrm/mapper/HrmEmergencyContactMapper.java new file mode 100644 index 0000000..25b4c29 --- /dev/null +++ b/fad-hrm/src/main/java/com/ruoyi/hrm/mapper/HrmEmergencyContactMapper.java @@ -0,0 +1,8 @@ +package com.ruoyi.hrm.mapper; + +import com.ruoyi.common.core.mapper.BaseMapperPlus; +import com.ruoyi.hrm.domain.HrmEmergencyContact; +import com.ruoyi.hrm.domain.vo.HrmEmergencyContactVo; + +public interface HrmEmergencyContactMapper extends BaseMapperPlus { +} diff --git a/fad-hrm/src/main/java/com/ruoyi/hrm/service/IHrmEmergencyContactService.java b/fad-hrm/src/main/java/com/ruoyi/hrm/service/IHrmEmergencyContactService.java new file mode 100644 index 0000000..920f408 --- /dev/null +++ b/fad-hrm/src/main/java/com/ruoyi/hrm/service/IHrmEmergencyContactService.java @@ -0,0 +1,27 @@ +package com.ruoyi.hrm.service; + +import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.hrm.domain.bo.HrmEmergencyContactBo; +import com.ruoyi.hrm.domain.vo.HrmEmergencyContactVo; +import com.ruoyi.hrm.domain.vo.HrmEmergencyContactImportVo; + +import java.util.Collection; +import java.util.List; + +public interface IHrmEmergencyContactService { + + HrmEmergencyContactVo queryById(Long contactId); + + TableDataInfo queryPageList(HrmEmergencyContactBo bo, PageQuery pageQuery); + + List queryList(HrmEmergencyContactBo bo); + + Boolean insertByBo(HrmEmergencyContactBo bo); + + Boolean updateByBo(HrmEmergencyContactBo bo); + + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + String importByVoList(List voList, boolean updateSupport); +} diff --git a/fad-hrm/src/main/java/com/ruoyi/hrm/service/impl/HrmEmergencyContactServiceImpl.java b/fad-hrm/src/main/java/com/ruoyi/hrm/service/impl/HrmEmergencyContactServiceImpl.java new file mode 100644 index 0000000..71c8a02 --- /dev/null +++ b/fad-hrm/src/main/java/com/ruoyi/hrm/service/impl/HrmEmergencyContactServiceImpl.java @@ -0,0 +1,254 @@ +package com.ruoyi.hrm.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.hrm.domain.HrmEmergencyContact; +import com.ruoyi.hrm.domain.bo.HrmEmergencyContactBo; +import com.ruoyi.hrm.domain.vo.HrmEmergencyContactVo; +import com.ruoyi.hrm.domain.vo.HrmEmergencyContactImportVo; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.hrm.mapper.HrmEmergencyContactMapper; +import com.ruoyi.hrm.service.IHrmEmergencyContactService; +import com.ruoyi.system.mapper.SysUserMapper; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.regex.Pattern; + +@RequiredArgsConstructor +@Service +public class HrmEmergencyContactServiceImpl implements IHrmEmergencyContactService { + + private final HrmEmergencyContactMapper baseMapper; + private final SysUserMapper sysUserMapper; + + // 手机号正则 + private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$"); + // 身份证号正则(15位或18位) + private static final Pattern ID_CARD_PATTERN = Pattern.compile("(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)"); + + @Override + public HrmEmergencyContactVo queryById(Long contactId) { + return baseMapper.selectVoById(contactId); + } + + @Override + public TableDataInfo queryPageList(HrmEmergencyContactBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + @Override + public List queryList(HrmEmergencyContactBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean insertByBo(HrmEmergencyContactBo bo) { + HrmEmergencyContact add = BeanUtil.toBean(bo, HrmEmergencyContact.class); + return baseMapper.insert(add) > 0; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean updateByBo(HrmEmergencyContactBo bo) { + HrmEmergencyContact update = BeanUtil.toBean(bo, HrmEmergencyContact.class); + return baseMapper.updateById(update) > 0; + } + + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + return baseMapper.deleteBatchIds(ids) > 0; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public String importByVoList(List voList, boolean updateSupport) { + if (CollUtil.isEmpty(voList)) { + throw new ServiceException("导入数据不能为空"); + } + int successNum = 0; + int failNum = 0; + StringBuilder failMsg = new StringBuilder(); + + for (int i = 0; i < voList.size(); i++) { + HrmEmergencyContactImportVo vo = voList.get(i); + int rowNum = i + 2; + + try { + // 转换日期格式:将 yyyy.MM.dd 转换为 yyyy-MM-dd + Date hireDate = null; + if (StrUtil.isNotBlank(vo.getHireDate())) { + String dateStr = vo.getHireDate().replace(".", "-"); + vo.setHireDate(dateStr); + hireDate = DateUtil.parseDate(dateStr); + } + + // 性别转换:Excel 中为"男"/"女"/"未知",统一转代码值 + String gender = vo.getGender(); + if (StrUtil.isNotBlank(gender)) { + if ("男".equals(gender)) { gender = "0"; } + else if ("女".equals(gender)) { gender = "1"; } + else if ("未知".equals(gender)) { gender = "2"; } + vo.setGender(gender); + } + + // 数据校验 + String validateMsg = validateImportData(vo); + if (StrUtil.isNotBlank(validateMsg)) { + failNum++; + failMsg.append("
").append(failNum).append("、第").append(rowNum).append("行 ") + .append(StrUtil.blankToDefault(vo.getRealName(), "无名")).append(":").append(validateMsg); + continue; + } + + HrmEmergencyContact entity = BeanUtil.toBean(vo, HrmEmergencyContact.class); + // 根据姓名+身份证号匹配 sys_user,自动填充 userId/deptId + Long matchedUserId = matchUserId(vo.getRealName(), vo.getIdCard()); + entity.setUserId(matchedUserId != null ? matchedUserId : 0L); + // 显式设置入职日期(BeanUtil 可能无法自动转换 String -> Date) + if (hireDate != null) { + entity.setHireDate(hireDate); + } + + // 按「姓名 + 身份证号」去重 + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(HrmEmergencyContact::getRealName, entity.getRealName()); + lqw.eq(HrmEmergencyContact::getIdCard, entity.getIdCard()); + HrmEmergencyContact existing = baseMapper.selectOne(lqw); + + if (existing != null) { + if (updateSupport) { + entity.setContactId(existing.getContactId()); + baseMapper.updateById(entity); + successNum++; + } else { + failNum++; + failMsg.append("
").append(failNum).append("、第").append(rowNum).append("行 ") + .append(vo.getRealName()).append(":数据已存在(姓名+身份证号重复)"); + } + } else { + baseMapper.insert(entity); + successNum++; + } + } catch (Exception e) { + failNum++; + failMsg.append("
").append(failNum).append("、第").append(rowNum).append("行 ") + .append(StrUtil.blankToDefault(vo.getRealName(), "无名")).append(":导入失败,").append(e.getMessage()); + } + } + + if (failNum > 0) { + return "导入完成!成功 " + successNum + " 条,失败 " + failNum + " 条。错误信息:" + failMsg; + } + return "恭喜您,数据已全部导入成功!共 " + successNum + " 条"; + } + + /** + * 根据姓名+身份证号匹配 sys_user,返回 userId;匹配不到返回 null + */ + private Long matchUserId(String realName, String idCard) { + // 1. 优先按 realName + idCard 精确匹配 + if (StrUtil.isNotBlank(realName) && StrUtil.isNotBlank(idCard)) { + SysUser user = sysUserMapper.selectOne(Wrappers.lambdaQuery() + .eq(SysUser::getNickName, realName) + .eq(SysUser::getIdCard, idCard) + .last("limit 1")); + if (user != null) { + return user.getUserId(); + } + } + // 2. 仅按 idCard 匹配(唯一性高) + if (StrUtil.isNotBlank(idCard)) { + SysUser user = sysUserMapper.selectOne(Wrappers.lambdaQuery() + .eq(SysUser::getIdCard, idCard) + .last("limit 1")); + if (user != null) { + return user.getUserId(); + } + } + // 3. 仅按 realName 匹配(有重名风险,作为最后的兜底) + if (StrUtil.isNotBlank(realName)) { + SysUser user = sysUserMapper.selectOne(Wrappers.lambdaQuery() + .eq(SysUser::getNickName, realName) + .last("limit 1")); + if (user != null) { + return user.getUserId(); + } + } + return null; + } + + /** + * 校验导入数据 + */ + private String validateImportData(HrmEmergencyContactImportVo vo) { + StringBuilder msg = new StringBuilder(); + + if (StrUtil.isBlank(vo.getRealName())) { + msg.append("姓名为空;"); + } + if (StrUtil.isBlank(vo.getPhone())) { + msg.append("联系电话为空;"); + } else if (!PHONE_PATTERN.matcher(vo.getPhone()).matches()) { + msg.append("联系电话格式错误(需11位手机号);"); + } + if (StrUtil.isBlank(vo.getIdCard())) { + msg.append("身份证号为空;"); + } else if (!ID_CARD_PATTERN.matcher(vo.getIdCard()).matches()) { + msg.append("身份证号格式错误;"); + } + if (StrUtil.isBlank(vo.getGender())) { + msg.append("性别为空;"); + } + if (vo.getAge() == null) { + msg.append("年龄为空;"); + } + if (StrUtil.isBlank(vo.getEmergencyContact())) { + msg.append("紧急联系人为空;"); + } + if (StrUtil.isBlank(vo.getRelationship())) { + msg.append("与本人关系为空;"); + } + if (StrUtil.isBlank(vo.getEmergencyPhone1())) { + msg.append("联系电话1为空;"); + } else if (!PHONE_PATTERN.matcher(vo.getEmergencyPhone1()).matches()) { + msg.append("联系电话1格式错误(需11位手机号);"); + } + if (StrUtil.isBlank(vo.getEmergencyAddress())) { + msg.append("紧急联系人地址为空;"); + } + if (StrUtil.isNotBlank(vo.getEmergencyPhone2()) && !PHONE_PATTERN.matcher(vo.getEmergencyPhone2()).matches()) { + msg.append("联系电话2格式错误(需11位手机号);"); + } + + return msg.toString(); + } + + private LambdaQueryWrapper buildQueryWrapper(HrmEmergencyContactBo bo) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(bo.getContactId() != null, HrmEmergencyContact::getContactId, bo.getContactId()); + lqw.eq(bo.getUserId() != null, HrmEmergencyContact::getUserId, bo.getUserId()); + lqw.like(bo.getRealName() != null, HrmEmergencyContact::getRealName, bo.getRealName()); + lqw.like(bo.getPhone() != null, HrmEmergencyContact::getPhone, bo.getPhone()); + lqw.like(bo.getEmergencyContact() != null, HrmEmergencyContact::getEmergencyContact, bo.getEmergencyContact()); + lqw.eq(bo.getDeptId() != null, HrmEmergencyContact::getDeptId, bo.getDeptId()); + lqw.eq(bo.getGender() != null, HrmEmergencyContact::getGender, bo.getGender()); + return lqw; + } +} diff --git a/fad-hrm/src/main/resources/mapper/HrmEmergencyContactMapper.xml b/fad-hrm/src/main/resources/mapper/HrmEmergencyContactMapper.xml new file mode 100644 index 0000000..5134b05 --- /dev/null +++ b/fad-hrm/src/main/resources/mapper/HrmEmergencyContactMapper.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ruoyi-ui/src/api/hrm/emergencyContact.js b/ruoyi-ui/src/api/hrm/emergencyContact.js new file mode 100644 index 0000000..d1d6641 --- /dev/null +++ b/ruoyi-ui/src/api/hrm/emergencyContact.js @@ -0,0 +1,55 @@ +import request from '@/utils/request' +import { download } from '@/utils/request' + +// 查询紧急联系人列表 +export function listEmergencyContact(query) { + return request({ + url: '/hrm/emergencyContact/list', + method: 'get', + params: query + }) +} + +// 查询紧急联系人详细 +export function getEmergencyContact(contactId) { + return request({ + url: `/hrm/emergencyContact/${contactId}`, + method: 'get' + }) +} + +// 新增紧急联系人 +export function addEmergencyContact(data) { + return request({ + url: '/hrm/emergencyContact', + method: 'post', + data: data + }) +} + +// 修改紧急联系人 +export function updateEmergencyContact(data) { + return request({ + url: '/hrm/emergencyContact', + method: 'put', + data: data + }) +} + +// 删除紧急联系人 +export function delEmergencyContact(contactIds) { + return request({ + url: `/hrm/emergencyContact/${contactIds}`, + method: 'delete' + }) +} + +// 导出紧急联系人 +export function exportEmergencyContact(query) { + return download('/hrm/emergencyContact/export', query, '紧急联系人数据.xlsx') +} + +// 下载导入模板 +export function importTemplate() { + return download('/hrm/emergencyContact/importTemplate', {}, '紧急联系人导入模板.xlsx') +} diff --git a/ruoyi-ui/src/api/hrm/index.js b/ruoyi-ui/src/api/hrm/index.js index c555c22..d126686 100644 --- a/ruoyi-ui/src/api/hrm/index.js +++ b/ruoyi-ui/src/api/hrm/index.js @@ -12,4 +12,5 @@ export * from './org' export * from './reimburse' export * from './seal' export * from './travel' +export * from './emergencyContact' diff --git a/ruoyi-ui/src/views/hrm/emergencyContact/index.vue b/ruoyi-ui/src/views/hrm/emergencyContact/index.vue new file mode 100644 index 0000000..e66afa3 --- /dev/null +++ b/ruoyi-ui/src/views/hrm/emergencyContact/index.vue @@ -0,0 +1,449 @@ + + + + + diff --git a/sql/hrm_emergency_contact.sql b/sql/hrm_emergency_contact.sql new file mode 100644 index 0000000..e9a59e5 --- /dev/null +++ b/sql/hrm_emergency_contact.sql @@ -0,0 +1,41 @@ +-- ===================================================================== +-- 员工紧急联系人信息表 +-- 通过 user_id 关联 sys_user,自动带出姓名/性别/身份证号/联系电话 +-- ===================================================================== +CREATE TABLE IF NOT EXISTS `hrm_emergency_contact` ( + `contact_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '紧急联系人ID', + + -- 关联信息(从 sys_user 自动带出 / 关联查询) + `user_id` BIGINT NOT NULL COMMENT '用户ID(关联 sys_user)', + `dept_id` BIGINT DEFAULT NULL COMMENT '部门ID(关联 sys_dept,从 sys_user 自动带出)', + + -- 员工基本信息(新增/导入时从 sys_user 自动填充,允许手动修改) + `real_name` VARCHAR(30) DEFAULT NULL COMMENT '姓名(从 sys_user.nick_name 自动带出)', + `phone` VARCHAR(20) DEFAULT NULL COMMENT '联系电话(从 sys_user.phonenumber 自动带出)', + `id_card` VARCHAR(200) DEFAULT NULL COMMENT '身份证号(从 sys_user.id_card 自动带出)', + `gender` CHAR(1) DEFAULT '0' COMMENT '性别(0男 1女 2未知,从 sys_user.sex 自动带出)', + `age` INT DEFAULT NULL COMMENT '年龄', + + -- 公司信息(sys_user 无此字段,手动录入) + `company_name` VARCHAR(100) DEFAULT NULL COMMENT '公司名称', + `hire_date` DATE DEFAULT NULL COMMENT '入职时间', + + -- 紧急联系人信息 + `emergency_contact` VARCHAR(30) DEFAULT NULL COMMENT '紧急联系人姓名', + `relationship` VARCHAR(30) DEFAULT NULL COMMENT '与本人关系', + `emergency_phone1` VARCHAR(20) DEFAULT NULL COMMENT '紧急联系人电话1', + `emergency_phone2` VARCHAR(20) DEFAULT NULL COMMENT '紧急联系人电话2', + `emergency_address` VARCHAR(200) DEFAULT NULL COMMENT '紧急联系人地址', + + -- 基础字段 + `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', + `del_flag` CHAR(1) DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)', + `create_by` VARCHAR(64) DEFAULT '' COMMENT '创建者', + `create_time` DATETIME DEFAULT NULL COMMENT '创建时间', + `update_by` VARCHAR(64) DEFAULT '' COMMENT '更新者', + `update_time` DATETIME DEFAULT NULL COMMENT '更新时间', + + PRIMARY KEY (`contact_id`) USING BTREE, + KEY `idx_user_id` (`user_id`) USING BTREE, + KEY `idx_dept_id` (`dept_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='员工紧急联系人信息表'; diff --git a/sql/hrm_emergency_contact_cleanup.sql b/sql/hrm_emergency_contact_cleanup.sql new file mode 100644 index 0000000..554dff7 --- /dev/null +++ b/sql/hrm_emergency_contact_cleanup.sql @@ -0,0 +1,30 @@ +-- ===================================================================== +-- 清理紧急联系人菜单脏数据(执行前请确认) +-- ===================================================================== + +-- 方式1:按 menu_id 范围删除(如果之前用的是 2000-2100 或 2070-2076) +-- DELETE FROM sys_menu WHERE menu_id BETWEEN 2000 AND 2100; +-- DELETE FROM sys_menu WHERE menu_id BETWEEN 2070 AND 2076; + +-- 方式2:按菜单名称删除(推荐,更精确) +-- DELETE FROM sys_menu WHERE menu_name = '紧急联系人'; + +-- 方式3:按权限标识删除(删除所有相关按钮权限) +-- DELETE FROM sys_menu WHERE perms LIKE 'hrm:emergencyContact:%'; + +-- 方式4:组合删除(先查后删,安全) +-- 先查询确认 +SELECT menu_id, menu_name, parent_id, perms, create_time +FROM sys_menu +WHERE menu_name = '紧急联系人' + OR perms LIKE 'hrm:emergencyContact:%'; + +-- 确认无误后再执行删除 +-- DELETE FROM sys_menu WHERE menu_name = '紧急联系人' OR perms LIKE 'hrm:emergencyContact:%'; + +-- ===================================================================== +-- 执行步骤: +-- 1. 先执行 SELECT 查询,确认要删除的数据 +-- 2. 确认无误后,再执行 DELETE 语句 +-- 3. 删除完成后,在若依系统菜单管理界面手动添加菜单 +-- ===================================================================== diff --git a/sql/hrm_emergency_contact_manual_guide.md b/sql/hrm_emergency_contact_manual_guide.md new file mode 100644 index 0000000..0f95223 --- /dev/null +++ b/sql/hrm_emergency_contact_manual_guide.md @@ -0,0 +1,115 @@ +# 紧急联系人菜单手动添加指南 + +## 第一步:清理脏数据(在Navicat/DBeaver中执行) + +```sql +-- 先查询确认 +SELECT menu_id, menu_name, parent_id, perms, create_time +FROM sys_menu +WHERE menu_name = '紧急联系人' + OR perms LIKE 'hrm:emergencyContact:%'; + +-- 确认无误后再执行删除 +DELETE FROM sys_menu +WHERE menu_name = '紧急联系人' + OR perms LIKE 'hrm:emergencyContact:%'; +``` + +--- + +## 第二步:在若依系统菜单管理中手动添加 + +### 1. 添加主菜单 + +进入 **系统管理 → 菜单管理**,点击【新增】按钮,填写以下信息: + +| 字段 | 值 | +|------|-----| +| 上级菜单 | 人事中心(或你想要的父菜单) | +| 菜单类型 | 菜单 | +| 菜单图标 | user | +| 菜单名称 | 紧急联系人 | +| 显示排序 | 99 | +| 是否外链 | 否 | +| 路由地址 | emergencyContact | +| 组件路径 | hrm/emergencyContact/index | +| 权限字符 | hrm:emergencyContact:list | +| 路由参数 | (留空) | +| 是否缓存 | 缓存 | +| 显示状态 | 显示 | +| 菜单状态 | 正常 | + +点击【确定】保存。 + +--- + +### 2. 添加按钮权限 + +主菜单添加成功后,在菜单列表中找到【紧急联系人】,点击右侧的【新增】按钮(添加子菜单/按钮)。 + +需要添加以下6个按钮权限: + +#### ① 查询按钮 +- 菜单类型:按钮 +- 菜单名称:查询 +- 显示排序:1 +- 权限字符:hrm:emergencyContact:query +- 显示状态:显示 +- 菜单状态:正常 + +#### ② 新增按钮 +- 菜单类型:按钮 +- 菜单名称:新增 +- 显示排序:2 +- 权限字符:hrm:emergencyContact:add +- 显示状态:显示 +- 菜单状态:正常 + +#### ③ 修改按钮 +- 菜单类型:按钮 +- 菜单名称:修改 +- 显示排序:3 +- 权限字符:hrm:emergencyContact:edit +- 显示状态:显示 +- 菜单状态:正常 + +#### ④ 删除按钮 +- 菜单类型:按钮 +- 菜单名称:删除 +- 显示排序:4 +- 权限字符:hrm:emergencyContact:remove +- 显示状态:显示 +- 菜单状态:正常 + +#### ⑤ 导出按钮 +- 菜单类型:按钮 +- 菜单名称:导出 +- 显示排序:5 +- 权限字符:hrm:emergencyContact:export +- 显示状态:显示 +- 菜单状态:正常 + +#### ⑥ 导入按钮 +- 菜单类型:按钮 +- 菜单名称:导入 +- 显示排序:6 +- 权限字符:hrm:emergencyContact:import +- 显示状态:显示 +- 菜单状态:正常 + +--- + +## 第三步:刷新系统 + +1. 添加完成后,**退出登录**或 **刷新页面** +2. 重新登录后,在对应父菜单下应该能看到【紧急联系人】菜单 +3. 进入菜单测试功能是否正常 + +--- + +## 注意事项 + +1. **上级菜单选择**:如果想放在"人事中心"下,就选择"人事中心";如果想放在顶级,就选择"主类目" +2. **权限字符**:必须严格按照 `hrm:emergencyContact:list`、`hrm:emergencyContact:query` 等格式填写 +3. **路由地址**:必须与前端路由配置一致,这里是 `emergencyContact` +4. **组件路径**:必须与前端组件路径一致,这里是 `hrm/emergencyContact/index` diff --git a/sql/hrm_emergency_contact_menu.sql b/sql/hrm_emergency_contact_menu.sql new file mode 100644 index 0000000..4f371db --- /dev/null +++ b/sql/hrm_emergency_contact_menu.sql @@ -0,0 +1,42 @@ +-- ===================================================================== +-- 菜单 SQL:员工紧急联系人管理(若依框架兼容版) +-- 必须分步执行,不能批量执行! +-- ===================================================================== + +-- ============================================================ +-- 第一步:清理可能存在的脏数据(如果之前执行失败过) +-- ============================================================ +-- DELETE FROM sys_menu WHERE menu_id BETWEEN 2070 AND 2076; + +-- ============================================================ +-- 第二步:插入主菜单(先执行这行,成功后再执行按钮) +-- parent_id = 0 表示顶级菜单,可根据需要改为实际的HRM菜单ID +-- ============================================================ +INSERT INTO sys_menu ( + menu_id, menu_name, parent_id, order_num, path, component, query_param, + is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time +) VALUES ( + 2070, '紧急联系人', 0, 99, 'emergencyContact', 'hrm/emergencyContact/index', '', + 1, 0, 'C', '0', '0', 'hrm:emergencyContact:list', 'user', 'admin', NOW() +); + +-- ============================================================ +-- 第三步:主菜单插入成功后,再执行按钮权限 +-- ============================================================ +INSERT INTO sys_menu ( + menu_id, menu_name, parent_id, order_num, path, component, + is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time +) VALUES + (2071, '查询', 2070, 1, '#', NULL, 1, 0, 'F', '0', '0', 'hrm:emergencyContact:query', '#', 'admin', NOW()), + (2072, '新增', 2070, 2, '#', NULL, 1, 0, 'F', '0', '0', 'hrm:emergencyContact:add', '#', 'admin', NOW()), + (2073, '修改', 2070, 3, '#', NULL, 1, 0, 'F', '0', '0', 'hrm:emergencyContact:edit', '#', 'admin', NOW()), + (2074, '删除', 2070, 4, '#', NULL, 1, 0, 'F', '0', '0', 'hrm:emergencyContact:remove', '#', 'admin', NOW()), + (2075, '导出', 2070, 5, '#', NULL, 1, 0, 'F', '0', '0', 'hrm:emergencyContact:export', '#', 'admin', NOW()), + (2076, '导入', 2070, 6, '#', NULL, 1, 0, 'F', '0', '0', 'hrm:emergencyContact:import', '#', 'admin', NOW()); + +-- ============================================================ +-- 使用说明: +-- 1. 如果之前执行失败过,先执行第一步的 DELETE 清理脏数据 +-- 2. 先执行第二步(主菜单),确认成功后再执行第三步(按钮权限) +-- 3. 如需将菜单放在HRM模块下,将 parent_id 从 0 改为 HRM菜单的实际ID +-- ============================================================ diff --git a/sql/hrm_emergency_contact_sample_data.sql b/sql/hrm_emergency_contact_sample_data.sql new file mode 100644 index 0000000..3d5ea01 --- /dev/null +++ b/sql/hrm_emergency_contact_sample_data.sql @@ -0,0 +1,24 @@ +-- ===================================================================== +-- 示例数据:信息部员工紧急联系人 +-- 使用前请将 user_id 替换为实际 sys_user 表中的 ID +-- ===================================================================== + +-- 示例数据1:张伟 +INSERT INTO `hrm_emergency_contact` (`user_id`, `dept_id`, `real_name`, `phone`, `id_card`, `gender`, `age`, `company_name`, `hire_date`, `emergency_contact`, `relationship`, `emergency_phone1`, `emergency_phone2`, `emergency_address`, `remark`, `del_flag`, `create_by`, `create_time`) +VALUES (1, 100, '张伟', '13800138001', '110101199001011234', '0', 36, '上海泛微网络科技股份有限公司', '2022-03-15', '李芳', '配偶', '13900139001', '13800138002', '上海市浦东新区张江高科技园区200号', '信息部经理', '0', 'admin', NOW()); + +-- 示例数据2:李娜 +INSERT INTO `hrm_emergency_contact` (`user_id`, `dept_id`, `real_name`, `phone`, `id_card`, `gender`, `age`, `company_name`, `hire_date`, `emergency_contact`, `relationship`, `emergency_phone1`, `emergency_phone2`, `emergency_address`, `remark`, `del_flag`, `create_by`, `create_time`) +VALUES (2, 100, '李娜', '13800138003', '110101199205022345', '1', 34, '上海泛微网络科技股份有限公司', '2021-07-01', '王强', '配偶', '13900139003', '', '上海市徐汇区漕河泾开发区100号', '需求分析师', '0', 'admin', NOW()); + +-- 示例数据3:王强 +INSERT INTO `hrm_emergency_contact` (`user_id`, `dept_id`, `real_name`, `phone`, `id_card`, `gender`, `age`, `company_name`, `hire_date`, `emergency_contact`, `relationship`, `emergency_phone1`, `emergency_phone2`, `emergency_address`, `remark`, `del_flag`, `create_by`, `create_time`) +VALUES (3, 100, '王强', '13800138005', '110101198803033456', '0', 38, '上海泛微网络科技股份有限公司', '2020-01-10', '刘静', '配偶', '13900139005', '13800138006', '上海市闵行区七宝镇50号', '开发主管', '0', 'admin', NOW()); + +-- 示例数据4:赵敏 +INSERT INTO `hrm_emergency_contact` (`user_id`, `dept_id`, `real_name`, `phone`, `id_card`, `gender`, `age`, `company_name`, `hire_date`, `emergency_contact`, `relationship`, `emergency_phone1`, `emergency_phone2`, `emergency_address`, `remark`, `del_flag`, `create_by`, `create_time`) +VALUES (4, 100, '赵敏', '13800138007', '110101199507044567', '1', 31, '上海泛微网络科技股份有限公司', '2023-05-20', '赵建国', '父母', '13900139007', '', '上海市静安区南京西路300号', '前端开发', '0', 'admin', NOW()); + +-- 示例数据5:陈浩 +INSERT INTO `hrm_emergency_contact` (`user_id`, `dept_id`, `real_name`, `phone`, `id_card`, `gender`, `age`, `company_name`, `hire_date`, `emergency_contact`, `relationship`, `emergency_phone1`, `emergency_phone2`, `emergency_address`, `remark`, `del_flag`, `create_by`, `create_time`) +VALUES (5, 100, '陈浩', '13800138009', '110101199608055678', '0', 30, '上海泛微网络科技股份有限公司', '2022-11-01', '陈芳', '父母', '13900139009', '13800138010', '上海市浦东新区陆家嘴环路1000号', '后端开发', '0', 'admin', NOW()); diff --git a/sql/信息部紧急联系人导入.xlsx b/sql/信息部紧急联系人导入.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..d4d1f7aea833f147a0e2adfea9ab75998377d8db GIT binary patch literal 6556 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