| New file |
| | |
| | | -- 卡片管理:卡片独立保存,绑定关系同步到 t_employee.card_no。 |
| | | CREATE TABLE IF NOT EXISTS `t_card` ( |
| | | `card_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '卡片主键', |
| | | `card_no` varchar(64) NOT NULL COMMENT '卡号', |
| | | `employee_id` bigint(20) DEFAULT NULL COMMENT '绑定员工主键', |
| | | `bind_time` datetime DEFAULT NULL COMMENT '绑定时间', |
| | | `del_flag` char(1) NOT NULL DEFAULT '0' COMMENT '删除标识:0正常 1删除', |
| | | `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 (`card_id`), |
| | | UNIQUE KEY `uk_card_no` (`card_no`, `del_flag`), |
| | | KEY `idx_card_employee` (`employee_id`, `del_flag`) |
| | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='卡片管理表'; |
| | | |
| | | -- 兼容已有员工卡号,首次执行迁移时自动建立卡片记录。 |
| | | INSERT INTO `t_card` (`card_no`, `employee_id`, `bind_time`, `del_flag`, `create_by`, `create_time`) |
| | | SELECT e.`card_no`, e.`employee_id`, e.`update_time`, '0', 'system', NOW() |
| | | FROM `t_employee` e |
| | | WHERE e.`card_no` IS NOT NULL |
| | | AND e.`card_no` <> '' |
| | | AND e.`del_flag` = '0' |
| | | AND NOT EXISTS ( |
| | | SELECT 1 FROM `t_card` c |
| | | WHERE c.`card_no` = e.`card_no` AND c.`del_flag` = '0' |
| | | ); |
| New file |
| | |
| | | -- 卡片管理菜单及权限,独立于卡片表结构迁移,且不受中台版本控制。 |
| | | INSERT INTO `sys_menu` ( |
| | | `menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, |
| | | `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, |
| | | `create_by`, `create_time`, `remark` |
| | | ) VALUES |
| | | (3013, '卡片管理', 3010, 3, 'card', 'visitor-admin/card/index', NULL, '1', '1', 'C', '0', '0', 'visitor:card:view', 'bank-card', 'admin', NOW(), '访客后台菜单'), |
| | | (3100, '卡片新增', 3013, 1, '#', NULL, NULL, '1', '1', 'F', '0', '0', 'visitor:card:add', '#', 'admin', NOW(), '访客后台按钮权限'), |
| | | (3101, '卡片编辑', 3013, 2, '#', NULL, NULL, '1', '1', 'F', '0', '0', 'visitor:card:edit', '#', 'admin', NOW(), '访客后台按钮权限'), |
| | | (3102, '卡片删除', 3013, 3, '#', NULL, NULL, '1', '1', 'F', '0', '0', 'visitor:card:remove', '#', 'admin', NOW(), '访客后台按钮权限'), |
| | | (3103, '卡片导入', 3013, 4, '#', NULL, NULL, '1', '1', 'F', '0', '0', 'visitor:card:import', '#', 'admin', NOW(), '访客后台按钮权限'), |
| | | (3104, '卡片导出', 3013, 5, '#', NULL, NULL, '1', '1', 'F', '0', '0', 'visitor:card:export', '#', 'admin', NOW(), '访客后台按钮权限'), |
| | | (3105, '卡片绑定', 3013, 6, '#', NULL, NULL, '1', '1', 'F', '0', '0', 'visitor:card:bind', '#', 'admin', NOW(), '访客后台按钮权限'), |
| | | (3106, '卡片解绑', 3013, 7, '#', NULL, NULL, '1', '1', 'F', '0', '0', 'visitor:card:unbind', '#', 'admin', NOW(), '访客后台按钮权限') |
| | | ON DUPLICATE KEY UPDATE |
| | | `menu_name` = VALUES(`menu_name`), |
| | | `parent_id` = VALUES(`parent_id`), |
| | | `order_num` = VALUES(`order_num`), |
| | | `path` = VALUES(`path`), |
| | | `component` = VALUES(`component`), |
| | | `query` = VALUES(`query`), |
| | | `is_frame` = VALUES(`is_frame`), |
| | | `is_cache` = VALUES(`is_cache`), |
| | | `menu_type` = VALUES(`menu_type`), |
| | | `visible` = VALUES(`visible`), |
| | | `status` = VALUES(`status`), |
| | | `perms` = VALUES(`perms`), |
| | | `icon` = VALUES(`icon`), |
| | | `remark` = VALUES(`remark`), |
| | | `update_by` = 'admin', |
| | | `update_time` = NOW(); |
| | | |
| | | -- 默认授权给若依管理员角色,普通角色可在角色管理中按需勾选。 |
| | | INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) |
| | | SELECT r.`role_id`, m.`menu_id` |
| | | FROM `sys_role` r |
| | | JOIN `sys_menu` m ON m.`menu_id` IN (3013, 3100, 3101, 3102, 3103, 3104, 3105, 3106) |
| | | WHERE r.`role_id` = 1 |
| | | AND NOT EXISTS ( |
| | | SELECT 1 |
| | | FROM `sys_role_menu` rm |
| | | WHERE rm.`role_id` = r.`role_id` |
| | | AND rm.`menu_id` = m.`menu_id` |
| | | ); |
| New file |
| | |
| | | package com.ruoyi.web.controller.api; |
| | | |
| | | import com.ruoyi.common.annotation.Log; |
| | | import com.ruoyi.common.core.controller.BaseController; |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | | import com.ruoyi.common.enums.BusinessType; |
| | | import com.ruoyi.system.dto.SysCardDeleteRequest; |
| | | import com.ruoyi.system.dto.SysCardDetailRequest; |
| | | import com.ruoyi.system.dto.SysCardEmployeeRequest; |
| | | import com.ruoyi.system.dto.SysCardPageRequest; |
| | | import com.ruoyi.system.dto.SysCardSaveRequest; |
| | | import com.ruoyi.system.service.ISysCardService; |
| | | import com.ruoyi.system.vo.SysCardVO; |
| | | import org.apache.poi.ss.usermodel.Cell; |
| | | import org.apache.poi.ss.usermodel.Row; |
| | | import org.apache.poi.ss.usermodel.Sheet; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | | import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.security.access.prepost.PreAuthorize; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.net.URLEncoder; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 卡片管理接口。卡片属于本地设备侧数据,不受中台版本管控。 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/system/card") |
| | | public class SysCardController extends BaseController |
| | | { |
| | | @Autowired |
| | | private ISysCardService cardService; |
| | | |
| | | @Log(title = "卡片管理", businessType = BusinessType.SELECT) |
| | | @PreAuthorize("@ss.hasPermi('visitor:card:view')") |
| | | @PostMapping("/page") |
| | | public AjaxResult page(@RequestBody(required = false) SysCardPageRequest request) |
| | | { |
| | | return success(cardService.pageList(request)); |
| | | } |
| | | |
| | | @Log(title = "卡片管理", businessType = BusinessType.SELECT) |
| | | @PreAuthorize("@ss.hasPermi('visitor:card:view')") |
| | | @PostMapping("/detail") |
| | | public AjaxResult detail(@RequestBody SysCardDetailRequest request) |
| | | { |
| | | return success(cardService.detail(request)); |
| | | } |
| | | |
| | | @Log(title = "卡片管理", businessType = BusinessType.SELECT) |
| | | @PreAuthorize("@ss.hasPermi('visitor:card:view')") |
| | | @PostMapping("/employee") |
| | | public AjaxResult employee(@RequestBody SysCardEmployeeRequest request) |
| | | { |
| | | return success(cardService.findEmployee(request)); |
| | | } |
| | | |
| | | @Log(title = "卡片管理", businessType = BusinessType.INSERT) |
| | | @PreAuthorize("@ss.hasPermi('visitor:card:add')") |
| | | @PostMapping("/add") |
| | | public AjaxResult add(@RequestBody SysCardSaveRequest request) |
| | | { |
| | | return toAjax(cardService.save(request, getUsername())); |
| | | } |
| | | |
| | | @Log(title = "卡片管理", businessType = BusinessType.UPDATE) |
| | | @PreAuthorize("@ss.hasPermi('visitor:card:edit')") |
| | | @PostMapping("/edit") |
| | | public AjaxResult edit(@RequestBody SysCardSaveRequest request) |
| | | { |
| | | return toAjax(cardService.save(request, getUsername())); |
| | | } |
| | | |
| | | @Log(title = "卡片管理", businessType = BusinessType.UPDATE) |
| | | @PreAuthorize("@ss.hasPermi('visitor:card:bind')") |
| | | @PostMapping("/bind") |
| | | public AjaxResult bind(@RequestBody SysCardSaveRequest request) |
| | | { |
| | | return toAjax(cardService.save(request, getUsername())); |
| | | } |
| | | |
| | | @Log(title = "卡片管理", businessType = BusinessType.UPDATE) |
| | | @PreAuthorize("@ss.hasPermi('visitor:card:unbind')") |
| | | @PostMapping("/unbind") |
| | | public AjaxResult unbind(@RequestBody SysCardSaveRequest request) |
| | | { |
| | | request.setEmployeeId(null); |
| | | request.setEmployeeName(null); |
| | | return toAjax(cardService.save(request, getUsername())); |
| | | } |
| | | |
| | | @Log(title = "卡片管理", businessType = BusinessType.DELETE) |
| | | @PreAuthorize("@ss.hasPermi('visitor:card:remove')") |
| | | @PostMapping("/delete") |
| | | public AjaxResult delete(@RequestBody SysCardDeleteRequest request) |
| | | { |
| | | return toAjax(cardService.delete(request, getUsername())); |
| | | } |
| | | |
| | | @Log(title = "卡片管理", businessType = BusinessType.IMPORT) |
| | | @PreAuthorize("@ss.hasPermi('visitor:card:import')") |
| | | @PostMapping("/importData") |
| | | public AjaxResult importData(@RequestParam("file") MultipartFile file) throws IOException |
| | | { |
| | | if (file == null || file.isEmpty()) |
| | | { |
| | | return error("请选择导入文件"); |
| | | } |
| | | return success(cardService.importData(file.getInputStream(), getUsername())); |
| | | } |
| | | |
| | | @Log(title = "卡片管理", businessType = BusinessType.EXPORT) |
| | | @PreAuthorize("@ss.hasPermi('visitor:card:export')") |
| | | @PostMapping("/export") |
| | | public void export(@RequestBody(required = false) SysCardPageRequest request, 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<SysCardVO> cards = cardService.list(request); |
| | | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | try (Workbook workbook = new XSSFWorkbook()) |
| | | { |
| | | Sheet sheet = workbook.createSheet("卡片列表"); |
| | | String[] headers = {"卡号", "员工姓名", "联系方式", "所属部门", "绑定时间", "卡片状态"}; |
| | | Row headerRow = sheet.createRow(0); |
| | | for (int index = 0; index < headers.length; index++) |
| | | { |
| | | Cell cell = headerRow.createCell(index); |
| | | cell.setCellValue(headers[index]); |
| | | sheet.setColumnWidth(index, 22 * 256); |
| | | } |
| | | for (int index = 0; index < cards.size(); index++) |
| | | { |
| | | SysCardVO card = cards.get(index); |
| | | Row row = sheet.createRow(index + 1); |
| | | row.createCell(0).setCellValue(value(card.getCardNo())); |
| | | row.createCell(1).setCellValue(value(card.getEmployeeName())); |
| | | row.createCell(2).setCellValue(value(card.getContactPhone())); |
| | | row.createCell(3).setCellValue(value(card.getDeptName())); |
| | | row.createCell(4).setCellValue(card.getBindTime() == null ? "" : dateFormat.format(card.getBindTime())); |
| | | row.createCell(5).setCellValue(Boolean.TRUE.equals(card.getBound()) ? "已绑定" : "未绑定"); |
| | | } |
| | | workbook.write(response.getOutputStream()); |
| | | } |
| | | } |
| | | |
| | | @Log(title = "卡片管理", businessType = BusinessType.EXPORT) |
| | | @PreAuthorize("@ss.hasPermi('visitor:card:import')") |
| | | @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"); |
| | | try (Workbook workbook = new XSSFWorkbook()) |
| | | { |
| | | Sheet sheet = workbook.createSheet("卡片导入"); |
| | | String[] headers = {"卡号", "员工姓名"}; |
| | | Row headerRow = sheet.createRow(0); |
| | | for (int index = 0; index < headers.length; index++) |
| | | { |
| | | headerRow.createCell(index).setCellValue(headers[index]); |
| | | sheet.setColumnWidth(index, 24 * 256); |
| | | } |
| | | workbook.write(response.getOutputStream()); |
| | | } |
| | | } |
| | | |
| | | private String value(String value) |
| | | { |
| | | return value == null ? "" : value; |
| | | } |
| | | } |
| | |
| | | # 部署模式:standalone单机版 cluster集群版 |
| | | deploymentMode: cluster |
| | | # 集群版是否对接中台:true对接 false不对接 |
| | | middlePlatformEnabled: false |
| | | middlePlatformEnabled: true |
| | | # 开发环境配置 |
| | | server: |
| | | # 服务器的HTTP端口,默认为8080 |
| | |
| | | # 部署模式:standalone单机版 cluster集群版 |
| | | deploymentMode: cluster |
| | | # 集群版是否对接中台:true对接 false不对接 |
| | | middlePlatformEnabled: false |
| | | middlePlatformEnabled: true |
| | | # 开发环境配置 |
| | | server: |
| | | # 服务器的HTTP端口,默认为8080 |
| | |
| | | # 项目相关配置 |
| | | spring: |
| | | profiles: |
| | | active: prod |
| | | active: test |
| New file |
| | |
| | | package com.ruoyi.system.domain; |
| | | |
| | | import com.ruoyi.common.core.domain.BaseEntity; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * 卡片管理实体,对应 t_card 表。 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class SysCard extends BaseEntity |
| | | { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | private Long cardId; |
| | | |
| | | private String cardNo; |
| | | |
| | | private Long employeeId; |
| | | |
| | | private String delFlag; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.dto; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 卡片删除请求。 |
| | | */ |
| | | @Data |
| | | public class SysCardDeleteRequest |
| | | { |
| | | @ApiModelProperty("卡片主键集合") |
| | | private List<Long> cardIds; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.dto; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * 卡片详情请求。 |
| | | */ |
| | | @Data |
| | | public class SysCardDetailRequest |
| | | { |
| | | @ApiModelProperty("卡片主键") |
| | | private Long cardId; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.dto; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * 按员工姓名查询绑定信息请求。 |
| | | */ |
| | | @Data |
| | | public class SysCardEmployeeRequest |
| | | { |
| | | @ApiModelProperty("员工姓名") |
| | | private String employeeName; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.dto; |
| | | |
| | | import com.ruoyi.common.core.domain.BasePage; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * 卡片分页查询请求。 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class SysCardPageRequest extends BasePage |
| | | { |
| | | @ApiModelProperty("卡号") |
| | | private String cardNo; |
| | | |
| | | @ApiModelProperty("员工姓名") |
| | | private String employeeName; |
| | | |
| | | @ApiModelProperty("卡片是否已绑定") |
| | | private Boolean bound; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.dto; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * 卡片新增或编辑请求。 |
| | | */ |
| | | @Data |
| | | public class SysCardSaveRequest |
| | | { |
| | | @ApiModelProperty("卡片主键,编辑时必填") |
| | | private Long cardId; |
| | | |
| | | @ApiModelProperty("卡号") |
| | | private String cardNo; |
| | | |
| | | @ApiModelProperty("员工主键,绑定时必填") |
| | | private Long employeeId; |
| | | |
| | | @ApiModelProperty("员工姓名,用于导入时校验") |
| | | private String employeeName; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.mapper; |
| | | |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.system.domain.SysCard; |
| | | import com.ruoyi.system.dto.SysCardPageRequest; |
| | | import com.ruoyi.system.vo.SysCardVO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 卡片管理数据层。 |
| | | */ |
| | | @Mapper |
| | | public interface SysCardMapper |
| | | { |
| | | List<SysCardVO> pageList(@Param("query") SysCardPageRequest query, @Param("pageInfo") PageInfo<SysCardVO> pageInfo); |
| | | |
| | | List<SysCardVO> selectList(@Param("query") SysCardPageRequest query); |
| | | |
| | | SysCardVO selectVoById(Long cardId); |
| | | |
| | | SysCard selectById(Long cardId); |
| | | |
| | | SysCard selectByCardNo(@Param("cardNo") String cardNo); |
| | | |
| | | SysCard selectByEmployeeId(@Param("employeeId") Long employeeId); |
| | | |
| | | int insertCard(SysCard card); |
| | | |
| | | int updateCard(SysCard card); |
| | | |
| | | int deleteByIds(@Param("cardIds") List<Long> cardIds, @Param("updateBy") String updateBy); |
| | | |
| | | int bindCard(@Param("cardId") Long cardId, @Param("employeeId") Long employeeId, @Param("updateBy") String updateBy); |
| | | |
| | | int unbindByEmployeeId(@Param("employeeId") Long employeeId, @Param("updateBy") String updateBy); |
| | | |
| | | int unbindByCardNo(@Param("cardNo") String cardNo, @Param("updateBy") String updateBy); |
| | | } |
| | |
| | | |
| | | public SysEmployeeVO selectVoById(Long employeeId); |
| | | |
| | | public List<SysEmployeeVO> selectVoByName(@Param("employeeName") String employeeName); |
| | | |
| | | public SysEmployee selectById(Long employeeId); |
| | | |
| | | public SysEmployee checkEmployeeNoUnique(@Param("employeeNo") String employeeNo, |
| | |
| | | |
| | | public int clearCard(@Param("employeeIds") List<Long> employeeIds, @Param("updateBy") String updateBy); |
| | | |
| | | public int updateCardNo(@Param("employeeId") Long employeeId, @Param("cardNo") String cardNo, |
| | | @Param("updateBy") String updateBy); |
| | | |
| | | public int clearFace(@Param("employeeIds") List<Long> employeeIds, @Param("updateBy") String updateBy); |
| | | |
| | | public int deleteByIds(@Param("employeeIds") List<Long> employeeIds, @Param("updateBy") String updateBy); |
| New file |
| | |
| | | package com.ruoyi.system.service; |
| | | |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.system.dto.SysCardDeleteRequest; |
| | | import com.ruoyi.system.dto.SysCardDetailRequest; |
| | | import com.ruoyi.system.dto.SysCardEmployeeRequest; |
| | | import com.ruoyi.system.dto.SysCardPageRequest; |
| | | import com.ruoyi.system.dto.SysCardSaveRequest; |
| | | import com.ruoyi.system.vo.SysCardVO; |
| | | |
| | | import java.io.InputStream; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 卡片管理服务。 |
| | | */ |
| | | public interface ISysCardService |
| | | { |
| | | PageInfo<SysCardVO> pageList(SysCardPageRequest request); |
| | | |
| | | List<SysCardVO> list(SysCardPageRequest request); |
| | | |
| | | SysCardVO detail(SysCardDetailRequest request); |
| | | |
| | | SysCardVO findEmployee(SysCardEmployeeRequest request); |
| | | |
| | | int save(SysCardSaveRequest request, String username); |
| | | |
| | | int delete(SysCardDeleteRequest request, String username); |
| | | |
| | | String importData(InputStream inputStream, String username); |
| | | } |
| New file |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.ruoyi.common.basic.PageInfo; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.system.domain.SysCard; |
| | | import com.ruoyi.system.domain.SysEmployee; |
| | | import com.ruoyi.system.dto.SysCardDeleteRequest; |
| | | import com.ruoyi.system.dto.SysCardDetailRequest; |
| | | import com.ruoyi.system.dto.SysCardEmployeeRequest; |
| | | import com.ruoyi.system.dto.SysCardPageRequest; |
| | | import com.ruoyi.system.dto.SysCardSaveRequest; |
| | | import com.ruoyi.system.mapper.SysCardMapper; |
| | | import com.ruoyi.system.mapper.SysEmployeeMapper; |
| | | import com.ruoyi.system.service.ISysCardService; |
| | | import com.ruoyi.system.utils.EmployeePhoneCrypto; |
| | | import com.ruoyi.system.vo.SysCardVO; |
| | | import com.ruoyi.system.vo.SysEmployeeVO; |
| | | import org.apache.poi.ss.usermodel.DataFormatter; |
| | | import org.apache.poi.ss.usermodel.Row; |
| | | import org.apache.poi.ss.usermodel.Sheet; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | | import org.apache.poi.ss.usermodel.WorkbookFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.io.InputStream; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 卡片管理服务实现。 |
| | | */ |
| | | @Service |
| | | public class SysCardServiceImpl implements ISysCardService |
| | | { |
| | | @Autowired |
| | | private SysCardMapper cardMapper; |
| | | |
| | | @Autowired |
| | | private SysEmployeeMapper employeeMapper; |
| | | |
| | | @Override |
| | | public PageInfo<SysCardVO> pageList(SysCardPageRequest request) |
| | | { |
| | | SysCardPageRequest query = normalizeQuery(request); |
| | | PageInfo<SysCardVO> pageInfo = new PageInfo<SysCardVO>(query.getPageNum(), query.getPageSize()); |
| | | List<SysCardVO> rows = cardMapper.pageList(query, pageInfo); |
| | | fillDisplayFields(rows, false); |
| | | pageInfo.setRecords(rows); |
| | | return pageInfo; |
| | | } |
| | | |
| | | @Override |
| | | public List<SysCardVO> list(SysCardPageRequest request) |
| | | { |
| | | List<SysCardVO> rows = cardMapper.selectList(normalizeQuery(request)); |
| | | fillDisplayFields(rows, true); |
| | | return rows; |
| | | } |
| | | |
| | | @Override |
| | | public SysCardVO detail(SysCardDetailRequest request) |
| | | { |
| | | Long cardId = requiredId(request == null ? null : request.getCardId(), "卡片主键不能为空"); |
| | | SysCardVO card = cardMapper.selectVoById(cardId); |
| | | if (card == null) |
| | | { |
| | | throw new ServiceException("卡片不存在"); |
| | | } |
| | | fillDisplayFields(Collections.singletonList(card), true); |
| | | return card; |
| | | } |
| | | |
| | | @Override |
| | | public SysCardVO findEmployee(SysCardEmployeeRequest request) |
| | | { |
| | | String employeeName = requiredText(request == null ? null : request.getEmployeeName(), "请输入员工姓名"); |
| | | List<SysEmployeeVO> employees = employeeMapper.selectVoByName(employeeName); |
| | | if (employees == null || employees.isEmpty()) |
| | | { |
| | | throw new ServiceException("该员工不存在,请到员工管理中添加"); |
| | | } |
| | | if (employees.size() > 1) |
| | | { |
| | | throw new ServiceException("员工姓名重复,请使用员工管理中的唯一姓名"); |
| | | } |
| | | SysEmployeeVO employee = employees.get(0); |
| | | employee.setContactPhone(EmployeePhoneCrypto.decrypt(employee.getContactPhone())); |
| | | SysCardVO result = new SysCardVO(); |
| | | result.setEmployeeId(employee.getEmployeeId()); |
| | | result.setEmployeeName(employee.getEmployeeName()); |
| | | result.setContactPhone(employee.getContactPhone()); |
| | | result.setDeptId(employee.getDeptId()); |
| | | result.setDeptName(employee.getDeptName()); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int save(SysCardSaveRequest request, String username) |
| | | { |
| | | if (request == null) |
| | | { |
| | | throw new ServiceException("卡片内容不能为空"); |
| | | } |
| | | String cardNo = requiredText(request.getCardNo(), "卡号不能为空"); |
| | | SysCard existing = request.getCardId() == null ? null : cardMapper.selectById(request.getCardId()); |
| | | if (request.getCardId() != null && existing == null) |
| | | { |
| | | throw new ServiceException("卡片不存在"); |
| | | } |
| | | |
| | | Long employeeId = resolveEmployeeId(request); |
| | | SysCard duplicated = cardMapper.selectByCardNo(cardNo); |
| | | if (duplicated != null && (existing == null || !duplicated.getCardId().equals(existing.getCardId()))) |
| | | { |
| | | throw new ServiceException("卡号已存在"); |
| | | } |
| | | |
| | | SysEmployee employee = employeeId == null ? null : employeeMapper.selectById(employeeId); |
| | | if (employeeId != null && employee == null) |
| | | { |
| | | throw new ServiceException("该员工不存在,请到员工管理中添加"); |
| | | } |
| | | if (employeeId != null) |
| | | { |
| | | if (StringUtils.isNotEmpty(StringUtils.trim(request.getEmployeeName())) |
| | | && !StringUtils.trim(request.getEmployeeName()).equals(employee.getEmployeeName())) |
| | | { |
| | | throw new ServiceException("员工信息已变更,请重新校验员工姓名"); |
| | | } |
| | | boolean editingEmployeeCard = existing != null && employeeId.equals(existing.getEmployeeId()); |
| | | if (StringUtils.isNotEmpty(employee.getCardNo()) |
| | | && !cardNo.equals(employee.getCardNo()) |
| | | && !editingEmployeeCard) |
| | | { |
| | | throw new ServiceException("该员工已绑定其他卡片"); |
| | | } |
| | | SysCard employeeCard = cardMapper.selectByEmployeeId(employeeId); |
| | | if (employeeCard != null && (existing == null || !employeeCard.getCardId().equals(existing.getCardId()))) |
| | | { |
| | | throw new ServiceException("该员工已绑定其他卡片"); |
| | | } |
| | | SysEmployee sameCardEmployee = employeeMapper.checkCardNoUnique(cardNo, employeeId); |
| | | if (sameCardEmployee != null) |
| | | { |
| | | throw new ServiceException("卡号已绑定其他员工"); |
| | | } |
| | | } |
| | | |
| | | if (existing == null) |
| | | { |
| | | SysCard card = new SysCard(); |
| | | card.setCardNo(cardNo); |
| | | card.setEmployeeId(employeeId); |
| | | card.setCreateBy(username); |
| | | int rows = cardMapper.insertCard(card); |
| | | if (employeeId != null) |
| | | { |
| | | employeeMapper.updateCardNo(employeeId, cardNo, username); |
| | | } |
| | | return rows; |
| | | } |
| | | |
| | | String oldCardNo = existing.getCardNo(); |
| | | Long oldEmployeeId = existing.getEmployeeId(); |
| | | if (oldEmployeeId != null && (!oldEmployeeId.equals(employeeId) || !oldCardNo.equals(cardNo))) |
| | | { |
| | | clearEmployeeCard(oldEmployeeId, oldCardNo, username); |
| | | cardMapper.unbindByEmployeeId(oldEmployeeId, username); |
| | | } |
| | | existing.setCardNo(cardNo); |
| | | existing.setUpdateBy(username); |
| | | int rows = cardMapper.updateCard(existing); |
| | | if (employeeId == null) |
| | | { |
| | | cardMapper.unbindByCardNo(cardNo, username); |
| | | } |
| | | else |
| | | { |
| | | cardMapper.bindCard(existing.getCardId(), employeeId, username); |
| | | employeeMapper.updateCardNo(employeeId, cardNo, username); |
| | | } |
| | | return rows; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int delete(SysCardDeleteRequest request, String username) |
| | | { |
| | | List<Long> cardIds = request == null ? null : request.getCardIds(); |
| | | if (cardIds == null || cardIds.isEmpty()) |
| | | { |
| | | throw new ServiceException("请选择卡片"); |
| | | } |
| | | for (Long cardId : cardIds) |
| | | { |
| | | SysCard card = cardMapper.selectById(requiredId(cardId, "卡片主键不能为空")); |
| | | if (card != null && card.getEmployeeId() != null) |
| | | { |
| | | clearEmployeeCard(card.getEmployeeId(), card.getCardNo(), username); |
| | | } |
| | | } |
| | | return cardMapper.deleteByIds(cardIds, username); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public String importData(InputStream inputStream, String username) |
| | | { |
| | | int successCount = 0; |
| | | List<String> errors = new ArrayList<String>(); |
| | | DataFormatter formatter = new DataFormatter(); |
| | | try (Workbook workbook = WorkbookFactory.create(inputStream)) |
| | | { |
| | | Sheet sheet = workbook.getSheetAt(0); |
| | | if (sheet == null || sheet.getLastRowNum() < 1) |
| | | { |
| | | throw new ServiceException("导入文件没有卡片数据"); |
| | | } |
| | | for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) |
| | | { |
| | | Row row = sheet.getRow(rowIndex); |
| | | String cardNo = getCell(row, 0, formatter); |
| | | String employeeName = getCell(row, 1, formatter); |
| | | if (StringUtils.isEmpty(cardNo) && StringUtils.isEmpty(employeeName)) |
| | | { |
| | | continue; |
| | | } |
| | | try |
| | | { |
| | | SysCardSaveRequest request = new SysCardSaveRequest(); |
| | | request.setCardNo(cardNo); |
| | | request.setEmployeeName(employeeName); |
| | | save(request, username); |
| | | successCount++; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | errors.add("第" + (rowIndex + 1) + "行:" + e.getMessage()); |
| | | } |
| | | } |
| | | } |
| | | catch (ServiceException e) |
| | | { |
| | | throw e; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | throw new ServiceException("卡片导入失败:" + e.getMessage()); |
| | | } |
| | | if (successCount == 0 && errors.isEmpty()) |
| | | { |
| | | throw new ServiceException("导入文件没有有效卡片数据"); |
| | | } |
| | | if (errors.isEmpty()) |
| | | { |
| | | return "导入成功,共导入" + successCount + "条卡片数据"; |
| | | } |
| | | return "导入完成,成功" + successCount + "条,失败" + errors.size() + "条;" + String.join(";", errors); |
| | | } |
| | | |
| | | private Long resolveEmployeeId(SysCardSaveRequest request) |
| | | { |
| | | if (request.getEmployeeId() != null) |
| | | { |
| | | return request.getEmployeeId(); |
| | | } |
| | | if (StringUtils.isEmpty(StringUtils.trim(request.getEmployeeName()))) |
| | | { |
| | | return null; |
| | | } |
| | | SysCardEmployeeRequest employeeRequest = new SysCardEmployeeRequest(); |
| | | employeeRequest.setEmployeeName(request.getEmployeeName()); |
| | | return findEmployee(employeeRequest).getEmployeeId(); |
| | | } |
| | | |
| | | private void clearEmployeeCard(Long employeeId, String cardNo, String username) |
| | | { |
| | | SysEmployee employee = employeeMapper.selectById(employeeId); |
| | | if (employee != null && cardNo != null && cardNo.equals(employee.getCardNo())) |
| | | { |
| | | employeeMapper.updateCardNo(employeeId, null, username); |
| | | } |
| | | } |
| | | |
| | | private SysCardPageRequest normalizeQuery(SysCardPageRequest request) |
| | | { |
| | | SysCardPageRequest query = request == null ? new SysCardPageRequest() : request; |
| | | query.setCardNo(StringUtils.trim(query.getCardNo())); |
| | | query.setEmployeeName(StringUtils.trim(query.getEmployeeName())); |
| | | return query; |
| | | } |
| | | |
| | | private void fillDisplayFields(List<SysCardVO> cards, boolean fullPhone) |
| | | { |
| | | for (SysCardVO card : cards) |
| | | { |
| | | String phone = EmployeePhoneCrypto.decrypt(card.getContactPhone()); |
| | | card.setContactPhone(fullPhone ? phone : maskPhone(phone)); |
| | | card.setBound(card.getEmployeeId() != null); |
| | | } |
| | | } |
| | | |
| | | private String maskPhone(String phone) |
| | | { |
| | | if (phone == null || phone.length() < 7) |
| | | { |
| | | return ""; |
| | | } |
| | | return phone.substring(0, 3) + "****" + phone.substring(phone.length() - 4); |
| | | } |
| | | |
| | | private String requiredText(String value, String message) |
| | | { |
| | | String result = StringUtils.trim(value); |
| | | if (StringUtils.isEmpty(result)) |
| | | { |
| | | throw new ServiceException(message); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private Long requiredId(Long value, String message) |
| | | { |
| | | if (value == null || value <= 0) |
| | | { |
| | | throw new ServiceException(message); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | private String getCell(Row row, int index, DataFormatter formatter) |
| | | { |
| | | return row == null ? "" : StringUtils.trim(formatter.formatCellValue(row.getCell(index))); |
| | | } |
| | | } |
| | |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.system.domain.SysEmployee; |
| | | import com.ruoyi.system.domain.SysCard; |
| | | import com.ruoyi.system.dto.SysEmployeeAddRequest; |
| | | import com.ruoyi.system.dto.SysEmployeeDeleteRequest; |
| | | import com.ruoyi.system.dto.SysEmployeeDetailRequest; |
| | |
| | | import com.ruoyi.system.dto.SysEmployeeUnbindRequest; |
| | | import com.ruoyi.system.mapper.SysDeptMapper; |
| | | import com.ruoyi.system.mapper.SysEmployeeMapper; |
| | | import com.ruoyi.system.mapper.SysCardMapper; |
| | | import com.ruoyi.system.service.ISysEmployeeService; |
| | | import com.ruoyi.system.utils.EmployeePhoneCrypto; |
| | | import com.ruoyi.system.vo.SysEmployeeVO; |
| | |
| | | import org.apache.poi.ss.usermodel.WorkbookFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import java.io.InputStream; |
| | |
| | | |
| | | @Autowired |
| | | private SysEmployeeMapper employeeMapper; |
| | | |
| | | @Autowired |
| | | private SysCardMapper cardMapper; |
| | | |
| | | @Autowired |
| | | private SysDeptMapper deptMapper; |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int add(SysEmployeeAddRequest request, String username) |
| | | { |
| | | if (request == null) |
| | |
| | | request.getContactPhone(), request.getPosition(), request.getCardNo(), request.getFaceImage(), |
| | | request.getEnabled(), null); |
| | | employee.setCreateBy(username); |
| | | return employeeMapper.insertEmployee(employee); |
| | | int rows = employeeMapper.insertEmployee(employee); |
| | | syncCard(employee.getEmployeeId(), null, employee.getCardNo(), username); |
| | | return rows; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int edit(SysEmployeeEditRequest request, String username) |
| | | { |
| | | if (request == null) |
| | |
| | | { |
| | | throw new ServiceException("员工不存在"); |
| | | } |
| | | SysEmployee oldEmployee = employeeMapper.selectById(employeeId); |
| | | SysEmployee employee = buildEmployee(request.getDeptId(), request.getEmployeeName(), request.getEmployeeNo(), |
| | | request.getContactPhone(), request.getPosition(), request.getCardNo(), request.getFaceImage(), |
| | | request.getEnabled(), employeeId); |
| | | employee.setEmployeeId(employeeId); |
| | | employee.setUpdateBy(username); |
| | | return employeeMapper.updateEmployee(employee); |
| | | int rows = employeeMapper.updateEmployee(employee); |
| | | syncCard(employeeId, oldEmployee.getCardNo(), employee.getCardNo(), username); |
| | | return rows; |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int unbindCard(SysEmployeeUnbindRequest request, String username) |
| | | { |
| | | return employeeMapper.clearCard(getRequiredEmployeeIds(request == null ? null : request.getEmployeeIds()), username); |
| | | List<Long> employeeIds = getRequiredEmployeeIds(request == null ? null : request.getEmployeeIds()); |
| | | int rows = employeeMapper.clearCard(employeeIds, username); |
| | | for (Long employeeId : employeeIds) |
| | | { |
| | | cardMapper.unbindByEmployeeId(employeeId, username); |
| | | } |
| | | return rows; |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int delete(SysEmployeeDeleteRequest request, String username) |
| | | { |
| | | return employeeMapper.deleteByIds(getRequiredEmployeeIds(request == null ? null : request.getEmployeeIds()), username); |
| | | List<Long> employeeIds = getRequiredEmployeeIds(request == null ? null : request.getEmployeeIds()); |
| | | int rows = employeeMapper.deleteByIds(employeeIds, username); |
| | | for (Long employeeId : employeeIds) |
| | | { |
| | | cardMapper.unbindByEmployeeId(employeeId, username); |
| | | } |
| | | return rows; |
| | | } |
| | | |
| | | @Override |
| | |
| | | return StringUtils.trim(value); |
| | | } |
| | | |
| | | /** |
| | | * 员工模块直接维护卡号时同步卡片关系,保证两个管理入口的数据一致。 |
| | | */ |
| | | private void syncCard(Long employeeId, String oldCardNo, String newCardNo, String username) |
| | | { |
| | | if (oldCardNo != null && !oldCardNo.equals(newCardNo)) |
| | | { |
| | | cardMapper.unbindByEmployeeId(employeeId, username); |
| | | } |
| | | if (newCardNo == null || newCardNo.length() == 0) |
| | | { |
| | | return; |
| | | } |
| | | SysCard card = cardMapper.selectByCardNo(newCardNo); |
| | | if (card == null) |
| | | { |
| | | card = new SysCard(); |
| | | card.setCardNo(newCardNo); |
| | | card.setEmployeeId(employeeId); |
| | | card.setCreateBy(username); |
| | | cardMapper.insertCard(card); |
| | | return; |
| | | } |
| | | if (card.getEmployeeId() != null && !employeeId.equals(card.getEmployeeId())) |
| | | { |
| | | throw new ServiceException("卡号已绑定其他员工"); |
| | | } |
| | | cardMapper.bindCard(card.getCardId(), employeeId, username); |
| | | } |
| | | |
| | | private void fillDisplayFields(SysEmployeeVO employee, boolean fullPhone) |
| | | { |
| | | String phone = EmployeePhoneCrypto.decrypt(employee.getContactPhone()); |
| New file |
| | |
| | | package com.ruoyi.system.vo; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import lombok.Data; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 卡片管理返回对象。 |
| | | */ |
| | | @Data |
| | | public class SysCardVO |
| | | { |
| | | private Long cardId; |
| | | |
| | | private String cardNo; |
| | | |
| | | private Long employeeId; |
| | | |
| | | private String employeeName; |
| | | |
| | | private String contactPhone; |
| | | |
| | | private Long deptId; |
| | | |
| | | private String deptName; |
| | | |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | private Date bindTime; |
| | | |
| | | private Boolean bound; |
| | | } |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8" ?> |
| | | <!DOCTYPE mapper |
| | | PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
| | | "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.ruoyi.system.mapper.SysCardMapper"> |
| | | |
| | | <resultMap type="SysCard" id="SysCardResult"> |
| | | <id property="cardId" column="card_id" /> |
| | | <result property="cardNo" column="card_no" /> |
| | | <result property="employeeId" column="employee_id" /> |
| | | <result property="delFlag" column="del_flag" /> |
| | | <result property="createBy" column="create_by" /> |
| | | <result property="createTime" column="create_time" /> |
| | | <result property="updateBy" column="update_by" /> |
| | | <result property="updateTime" column="update_time" /> |
| | | </resultMap> |
| | | |
| | | <resultMap type="SysCardVO" id="SysCardVOResult"> |
| | | <id property="cardId" column="card_id" /> |
| | | <result property="cardNo" column="card_no" /> |
| | | <result property="employeeId" column="employee_id" /> |
| | | <result property="employeeName" column="employee_name" /> |
| | | <result property="contactPhone" column="contact_phone_cipher" /> |
| | | <result property="deptId" column="dept_id" /> |
| | | <result property="deptName" column="dept_name" /> |
| | | <result property="bindTime" column="bind_time" /> |
| | | <result property="bound" column="bound" /> |
| | | </resultMap> |
| | | |
| | | <sql id="selectCardVo"> |
| | | select c.card_id, |
| | | c.card_no, |
| | | c.employee_id, |
| | | e.employee_name, |
| | | e.contact_phone_cipher, |
| | | e.dept_id, |
| | | d.dept_name, |
| | | c.bind_time, |
| | | case when c.employee_id is not null then 1 else 0 end as bound |
| | | from t_card c |
| | | left join t_employee e on e.employee_id = c.employee_id and e.del_flag = '0' |
| | | left join sys_dept d on d.dept_id = e.dept_id and d.del_flag = '0' |
| | | </sql> |
| | | |
| | | <select id="pageList" resultMap="SysCardVOResult"> |
| | | <include refid="selectCardVo" /> |
| | | <where> |
| | | c.del_flag = '0' |
| | | <if test="query.cardNo != null and query.cardNo != ''"> |
| | | and c.card_no like concat('%', #{query.cardNo}, '%') |
| | | </if> |
| | | <if test="query.employeeName != null and query.employeeName != ''"> |
| | | and e.employee_name like concat('%', #{query.employeeName}, '%') |
| | | </if> |
| | | <if test="query.bound != null and query.bound"> |
| | | and c.employee_id is not null |
| | | </if> |
| | | <if test="query.bound != null and !query.bound"> |
| | | and c.employee_id is null |
| | | </if> |
| | | </where> |
| | | order by c.bind_time desc, c.card_id desc |
| | | </select> |
| | | |
| | | <select id="selectList" resultMap="SysCardVOResult"> |
| | | <include refid="selectCardVo" /> |
| | | <where> |
| | | c.del_flag = '0' |
| | | <if test="query.cardNo != null and query.cardNo != ''"> |
| | | and c.card_no like concat('%', #{query.cardNo}, '%') |
| | | </if> |
| | | <if test="query.employeeName != null and query.employeeName != ''"> |
| | | and e.employee_name like concat('%', #{query.employeeName}, '%') |
| | | </if> |
| | | <if test="query.bound != null and query.bound"> |
| | | and c.employee_id is not null |
| | | </if> |
| | | <if test="query.bound != null and !query.bound"> |
| | | and c.employee_id is null |
| | | </if> |
| | | </where> |
| | | order by c.bind_time desc, c.card_id desc |
| | | </select> |
| | | |
| | | <select id="selectVoById" parameterType="Long" resultMap="SysCardVOResult"> |
| | | <include refid="selectCardVo" /> |
| | | where c.card_id = #{cardId} |
| | | and c.del_flag = '0' |
| | | </select> |
| | | |
| | | <select id="selectById" parameterType="Long" resultMap="SysCardResult"> |
| | | select card_id, card_no, employee_id, del_flag, create_by, create_time, update_by, update_time |
| | | from t_card |
| | | where card_id = #{cardId} |
| | | and del_flag = '0' |
| | | </select> |
| | | |
| | | <select id="selectByCardNo" resultMap="SysCardResult"> |
| | | select card_id, card_no, employee_id, del_flag, create_by, create_time, update_by, update_time |
| | | from t_card |
| | | where card_no = #{cardNo} |
| | | and del_flag = '0' |
| | | limit 1 |
| | | </select> |
| | | |
| | | <select id="selectByEmployeeId" resultMap="SysCardResult"> |
| | | select card_id, card_no, employee_id, del_flag, create_by, create_time, update_by, update_time |
| | | from t_card |
| | | where employee_id = #{employeeId} |
| | | and del_flag = '0' |
| | | limit 1 |
| | | </select> |
| | | |
| | | <insert id="insertCard" parameterType="SysCard" useGeneratedKeys="true" keyProperty="cardId"> |
| | | insert into t_card (card_no, employee_id, bind_time, create_by, create_time) |
| | | values (#{cardNo}, #{employeeId}, |
| | | <choose> |
| | | <when test="employeeId != null">sysdate()</when> |
| | | <otherwise>null</otherwise> |
| | | </choose>, |
| | | #{createBy}, sysdate()) |
| | | </insert> |
| | | |
| | | <update id="updateCard" parameterType="SysCard"> |
| | | update t_card |
| | | set card_no = #{cardNo}, |
| | | update_by = #{updateBy}, |
| | | update_time = sysdate() |
| | | where card_id = #{cardId} |
| | | and del_flag = '0' |
| | | </update> |
| | | |
| | | <update id="bindCard"> |
| | | update t_card |
| | | set employee_id = #{employeeId}, |
| | | bind_time = sysdate(), |
| | | update_by = #{updateBy}, |
| | | update_time = sysdate() |
| | | where card_id = #{cardId} |
| | | and del_flag = '0' |
| | | </update> |
| | | |
| | | <update id="unbindByEmployeeId"> |
| | | update t_card |
| | | set employee_id = null, |
| | | bind_time = null, |
| | | update_by = #{updateBy}, |
| | | update_time = sysdate() |
| | | where employee_id = #{employeeId} |
| | | and del_flag = '0' |
| | | </update> |
| | | |
| | | <update id="unbindByCardNo"> |
| | | update t_card |
| | | set employee_id = null, |
| | | bind_time = null, |
| | | update_by = #{updateBy}, |
| | | update_time = sysdate() |
| | | where card_no = #{cardNo} |
| | | and del_flag = '0' |
| | | </update> |
| | | |
| | | <update id="deleteByIds"> |
| | | update t_card |
| | | set employee_id = null, |
| | | bind_time = null, |
| | | del_flag = '1', |
| | | update_by = #{updateBy}, |
| | | update_time = sysdate() |
| | | where del_flag = '0' |
| | | and card_id in |
| | | <foreach collection="cardIds" item="cardId" open="(" separator="," close=")"> |
| | | #{cardId} |
| | | </foreach> |
| | | </update> |
| | | </mapper> |
| | |
| | | and e.del_flag = '0' |
| | | </select> |
| | | |
| | | <select id="selectVoByName" resultMap="SysEmployeeVOResult"> |
| | | <include refid="selectEmployeeVo" /> |
| | | where e.employee_name = #{employeeName} |
| | | and e.del_flag = '0' |
| | | order by e.employee_id |
| | | </select> |
| | | |
| | | <select id="selectById" parameterType="Long" resultMap="SysEmployeeResult"> |
| | | <include refid="selectEmployeeDomain" /> |
| | | where employee_id = #{employeeId} |
| | |
| | | </foreach> |
| | | </update> |
| | | |
| | | <update id="updateCardNo"> |
| | | update t_employee |
| | | set card_no = #{cardNo}, |
| | | update_by = #{updateBy}, |
| | | update_time = sysdate() |
| | | where employee_id = #{employeeId} |
| | | and del_flag = '0' |
| | | </update> |
| | | |
| | | <update id="clearFace"> |
| | | update t_employee |
| | | set face_image = null, |
| | |
| | | visitor_machine_entry_enabled = #{visitorMachineEntryEnabled}, |
| | | update_by = #{updateBy}, |
| | | update_time = sysdate(), |
| | | remark = #{remark} |
| | | remark = #{remark}, |
| | | center_path = #{centerPath} |
| | | where config_id = #{configId} |
| | | </update> |
| | | </mapper> |
| | |
| | | VUE_APP_PUBLIC_PATH = './' |
| | | |
| | | VUE_APP_VISITOR_FRONTEND_MODE = 'cluster' |
| | | VUE_APP_VISITOR_MIDDLE_PLATFORM_ENABLED = 'false' |
| | | VUE_APP_VISITOR_MIDDLE_PLATFORM_ENABLED = 'true' |
| | | # VUE_APP_VISITOR_LOGIN_MIDDLE_PLATFORM_ENABLED 未配置时默认跟随 VUE_APP_VISITOR_MIDDLE_PLATFORM_ENABLED |
| | | VUE_APP_VISITOR_API_BASE_URL = '/prod-api' |
| New file |
| | |
| | | import request from '@/utils/request' |
| | | |
| | | export function listCard(data) { |
| | | return request({ url: '/system/card/page', method: 'post', data }) |
| | | } |
| | | |
| | | export function getCard(cardId) { |
| | | return request({ |
| | | url: '/system/card/detail', |
| | | method: 'post', |
| | | data: { |
| | | cardId: cardId |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export function findCardEmployee(employeeName) { |
| | | return request({ |
| | | url: '/system/card/employee', |
| | | method: 'post', |
| | | data: { |
| | | employeeName: employeeName |
| | | }, |
| | | silentError: true |
| | | }) |
| | | } |
| | | |
| | | export function addCard(data) { |
| | | return request({ url: '/system/card/add', method: 'post', data }) |
| | | } |
| | | |
| | | export function updateCard(data) { |
| | | return request({ url: '/system/card/edit', method: 'post', data }) |
| | | } |
| | | |
| | | export function bindCard(data) { |
| | | return request({ url: '/system/card/bind', method: 'post', data }) |
| | | } |
| | | |
| | | export function unbindCard(data) { |
| | | return request({ url: '/system/card/unbind', method: 'post', data }) |
| | | } |
| | | |
| | | export function delCard(cardIds) { |
| | | return request({ |
| | | url: '/system/card/delete', |
| | | method: 'post', |
| | | data: { |
| | | cardIds: cardIds |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export function importCardData(data) { |
| | | return request({ |
| | | url: '/system/card/importData', |
| | | method: 'post', |
| | | data, |
| | | headers: { 'Content-Type': 'multipart/form-data' } |
| | | }) |
| | | } |
| | | |
| | | export function exportCard(data) { |
| | | return request({ url: '/system/card/export', method: 'post', data, responseType: 'blob' }) |
| | | } |
| | | |
| | | export function downloadCardTemplate() { |
| | | return request({ url: '/system/card/importTemplate', method: 'post', responseType: 'blob' }) |
| | | } |
| | |
| | | component: () => import('@/views/visitor-admin/device/index'), |
| | | name: 'VisitorDoorDevice', |
| | | meta: { title: '门禁管理', icon: 'server', deviceType: 'door' } |
| | | }, |
| | | { |
| | | path: 'card', |
| | | component: () => import('@/views/visitor-admin/card/index'), |
| | | name: 'VisitorCard', |
| | | meta: { title: '卡片管理', icon: 'bank-card' } |
| | | } |
| | | ] |
| | | }, |
| New file |
| | |
| | | <template> |
| | | <main class="visitor-page card-page"> |
| | | <section class="visitor-card"> |
| | | <header class="visitor-header"> |
| | | <h1>卡片管理</h1> |
| | | </header> |
| | | |
| | | <el-form ref="queryForm" :model="queryParams" size="small" :inline="true" class="visitor-query"> |
| | | <el-form-item label="卡号" prop="cardNo"> |
| | | <el-input v-model="queryParams.cardNo" placeholder="请输入" clearable @keyup.enter.native="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="姓名" prop="employeeName"> |
| | | <el-input v-model="queryParams.employeeName" placeholder="请输入" clearable @keyup.enter.native="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="卡片状态" prop="bound"> |
| | | <el-select v-model="queryParams.bound" placeholder="全部" clearable> |
| | | <el-option label="已绑定" :value="true" /> |
| | | <el-option label="未绑定" :value="false" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="resetQuery">重置</el-button> |
| | | <el-button type="primary" @click="handleQuery">搜索</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="card-toolbar"> |
| | | <div> |
| | | <el-button v-hasPermi="['visitor:card:import']" type="primary" plain icon="el-icon-upload2" size="small" @click="handleImport">批量导入</el-button> |
| | | <el-button v-hasPermi="['visitor:card:import']" type="text" icon="el-icon-download" size="small" @click="handleDownloadTemplate">下载模板</el-button> |
| | | <el-button v-hasPermi="['visitor:card:export']" type="primary" plain icon="el-icon-document" size="small" @click="handleExport">导出</el-button> |
| | | <input ref="cardImportFile" class="card-import-file" type="file" accept=".xlsx,.xls" @change="handleImportFileChange"> |
| | | </div> |
| | | <el-button v-hasPermi="['visitor:card:add']" type="primary" icon="el-icon-plus" size="small" @click="handleAdd">绑定卡片</el-button> |
| | | </div> |
| | | |
| | | <el-table v-loading="loading" class="visitor-table" :data="cardList"> |
| | | <el-table-column label="序号" width="64" align="center"> |
| | | <template slot-scope="scope">{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="卡号" prop="cardNo" min-width="150" show-overflow-tooltip /> |
| | | <el-table-column label="员工姓名" prop="employeeName" min-width="110" show-overflow-tooltip /> |
| | | <el-table-column label="联系方式" prop="contactPhone" min-width="130" /> |
| | | <el-table-column label="所属部门" prop="deptName" min-width="140" show-overflow-tooltip /> |
| | | <el-table-column label="绑定时间" prop="bindTime" min-width="165" /> |
| | | <el-table-column label="卡片状态" align="center" width="105"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="scope.row.bound ? 'success' : 'warning'">{{ scope.row.bound ? '已绑定' : '未绑定' }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column v-if="$auth.hasPermi('visitor:card:edit') || $auth.hasPermi('visitor:card:bind') || $auth.hasPermi('visitor:card:unbind') || $auth.hasPermi('visitor:card:remove')" label="操作" align="center" width="180" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button v-hasPermi="['visitor:card:edit']" type="text" @click="handleUpdate(scope.row)">编辑</el-button> |
| | | <el-button v-if="scope.row.bound" v-hasPermi="['visitor:card:unbind']" type="text" @click="handleUnbind(scope.row)">解绑</el-button> |
| | | <el-button v-else v-hasPermi="['visitor:card:bind']" type="text" @click="handleUpdate(scope.row)">绑定</el-button> |
| | | <el-button v-hasPermi="['visitor:card:remove']" type="text" class="danger-text" @click="handleDelete(scope.row)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" /> |
| | | </section> |
| | | |
| | | <el-dialog :title="title" :visible.sync="open" width="560px" append-to-body custom-class="visitor-card-dialog"> |
| | | <el-form ref="form" :model="form" :rules="rules" label-position="top"> |
| | | <el-form-item label="卡号" prop="cardNo"> |
| | | <el-input v-model="form.cardNo" placeholder="请输入卡号" /> |
| | | </el-form-item> |
| | | <el-form-item label="员工姓名" prop="employeeName"> |
| | | <el-input v-model="form.employeeName" placeholder="请输入员工姓名" @blur="handleEmployeeBlur" /> |
| | | <div v-if="employeeError" class="card-form-error">{{ employeeError }}</div> |
| | | </el-form-item> |
| | | <el-form-item label="所属部门"> |
| | | <el-input v-model="form.deptName" disabled placeholder="员工校验后自动带出" /> |
| | | </el-form-item> |
| | | <el-form-item label="联系方式"> |
| | | <el-input v-model="form.contactPhone" disabled placeholder="员工校验后自动带出" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="open = false">取消</el-button> |
| | | <el-button type="primary" @click="submitForm">保存</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </main> |
| | | </template> |
| | | |
| | | <script> |
| | | import { saveAs } from 'file-saver' |
| | | import { listCard, getCard, findCardEmployee, addCard, updateCard, bindCard, unbindCard, delCard, importCardData, exportCard, downloadCardTemplate } from '@/api/visitor-admin/card' |
| | | import { getPageRows, getPageTotal, getResponseData } from '@/utils/visitor-admin' |
| | | |
| | | export default { |
| | | name: 'VisitorCard', |
| | | data() { |
| | | return { |
| | | loading: false, |
| | | open: false, |
| | | title: '', |
| | | employeeError: '', |
| | | total: 0, |
| | | cardList: [], |
| | | queryParams: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | cardNo: '', |
| | | employeeName: '', |
| | | bound: undefined |
| | | }, |
| | | form: {}, |
| | | rules: { |
| | | cardNo: [{ required: true, message: '请输入卡号', trigger: 'blur' }], |
| | | employeeName: [{ required: true, message: '请输入员工姓名', trigger: 'blur' }] |
| | | } |
| | | } |
| | | }, |
| | | created() { |
| | | this.getList() |
| | | }, |
| | | methods: { |
| | | getList() { |
| | | this.loading = true |
| | | listCard(this.queryParams).then(res => { |
| | | this.cardList = getPageRows(res) |
| | | this.total = getPageTotal(res) |
| | | }).finally(() => { |
| | | this.loading = false |
| | | }) |
| | | }, |
| | | handleQuery() { |
| | | this.queryParams.pageNum = 1 |
| | | this.getList() |
| | | }, |
| | | resetQuery() { |
| | | this.resetForm('queryForm') |
| | | this.queryParams.bound = undefined |
| | | this.handleQuery() |
| | | }, |
| | | handleAdd() { |
| | | this.title = '绑定卡片' |
| | | this.form = { cardNo: '', employeeName: '', employeeId: null, deptName: '', contactPhone: '' } |
| | | this.employeeError = '' |
| | | this.open = true |
| | | }, |
| | | handleUpdate(row) { |
| | | getCard(row.cardId).then(res => { |
| | | this.title = row.bound ? '编辑卡片' : '绑定卡片' |
| | | this.form = getResponseData(res) || {} |
| | | this.employeeError = '' |
| | | this.open = true |
| | | }) |
| | | }, |
| | | handleEmployeeBlur() { |
| | | const employeeName = (this.form.employeeName || '').trim() |
| | | this.employeeError = '' |
| | | this.form.employeeId = null |
| | | this.form.deptName = '' |
| | | this.form.contactPhone = '' |
| | | if (!employeeName) { |
| | | return |
| | | } |
| | | findCardEmployee(employeeName).then(res => { |
| | | const employee = getResponseData(res) || {} |
| | | this.form.employeeId = employee.employeeId |
| | | this.form.employeeName = employee.employeeName |
| | | this.form.deptName = employee.deptName |
| | | this.form.contactPhone = employee.contactPhone |
| | | }).catch(error => { |
| | | this.employeeError = (error && error.message) || '该员工不存在,请到员工管理中添加' |
| | | }) |
| | | }, |
| | | submitForm() { |
| | | this.$refs.form.validate(valid => { |
| | | if (!valid) { |
| | | return |
| | | } |
| | | if (!this.form.employeeId) { |
| | | this.employeeError = '该员工不存在,请先到员工管理中添加' |
| | | return |
| | | } |
| | | const request = this.form.cardId ? (this.form.bound ? updateCard : bindCard) : addCard |
| | | request({ cardId: this.form.cardId, cardNo: this.form.cardNo, employeeId: this.form.employeeId, employeeName: this.form.employeeName }).then(() => { |
| | | this.$modal.msgSuccess('保存成功') |
| | | this.open = false |
| | | this.getList() |
| | | }) |
| | | }) |
| | | }, |
| | | handleUnbind(row) { |
| | | this.$modal.confirm('解绑后卡片将变为未绑定状态,确认解绑吗?').then(() => unbindCard({ cardId: row.cardId, cardNo: row.cardNo })).then(() => { |
| | | this.$modal.msgSuccess('解绑成功') |
| | | this.getList() |
| | | }) |
| | | }, |
| | | handleDelete(row) { |
| | | this.$modal.confirm('是否确认删除该卡片?').then(() => delCard([row.cardId])).then(() => { |
| | | this.$modal.msgSuccess('删除成功') |
| | | this.getList() |
| | | }) |
| | | }, |
| | | handleImport() { |
| | | this.$refs.cardImportFile && this.$refs.cardImportFile.click() |
| | | }, |
| | | handleImportFileChange(event) { |
| | | const file = event.target.files && event.target.files[0] |
| | | if (!file) { |
| | | return |
| | | } |
| | | const formData = new FormData() |
| | | formData.append('file', file) |
| | | importCardData(formData).then(res => { |
| | | this.$modal.msgSuccess(getResponseData(res) || '导入成功') |
| | | this.getList() |
| | | }).finally(() => { |
| | | event.target.value = '' |
| | | }) |
| | | }, |
| | | handleDownloadTemplate() { |
| | | downloadCardTemplate().then(data => saveAs(new Blob([data]), '卡片导入模板.xlsx')) |
| | | }, |
| | | handleExport() { |
| | | exportCard(this.queryParams).then(data => saveAs(new Blob([data]), '卡片列表.xlsx')) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .card-toolbar { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .card-import-file { |
| | | display: none; |
| | | } |
| | | |
| | | .card-form-error { |
| | | color: #f56c6c; |
| | | line-height: 20px; |
| | | margin-top: 4px; |
| | | } |
| | | |
| | | .danger-text { |
| | | color: #f56c6c; |
| | | } |
| | | </style> |