liujie
2026-07-13 edccaca25b8b6bdb582c60cbd2983bc05a4e1ff3
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/SysEmployeeController.java
@@ -17,6 +17,7 @@
import com.ruoyi.system.dto.SysEmployeeUnbindRequest;
import com.ruoyi.system.mapper.SysDoorDeviceMapper;
import com.ruoyi.system.service.ISysEmployeeService;
import com.ruoyi.system.vo.SysEmployeeVO;
import com.ruoyi.web.controller.tool.HikvisionAccessControlApi;
import com.ruoyi.web.controller.tool.MiddlePlatformDataQuery;
import org.apache.poi.ss.usermodel.Cell;
@@ -40,9 +41,11 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
 * 员工管理接口
@@ -177,7 +180,11 @@
    @PostMapping("/delete")
    public AjaxResult delete(@RequestBody SysEmployeeDeleteRequest request)
    {
        return toAjax(employeeService.delete(request, getUsername()));
        List<SysEmployeeVO> employees = loadDeleteEmployees(request);
        Map<String, Object> hikvisionDelete = deleteEmployeesFromHikvision(employees);
        AjaxResult ajax = toAjax(employeeService.delete(request, getUsername()));
        ajax.put("hikvisionDelete", hikvisionDelete);
        return ajax;
    }
    /**
@@ -232,6 +239,133 @@
    /**
     * 目的:中台查询异常时返回统一业务错误,避免异常栈直接暴露给前端。
     */
    private List<SysEmployeeVO> loadDeleteEmployees(SysEmployeeDeleteRequest request)
    {
        if (request == null || request.getEmployeeIds() == null || request.getEmployeeIds().isEmpty())
        {
            throw new ServiceException("请选择员工");
        }
        List<SysEmployeeVO> employees = new ArrayList<SysEmployeeVO>();
        Set<Long> uniqueEmployeeIds = new HashSet<Long>();
        for (Long employeeId : request.getEmployeeIds())
        {
            if (employeeId == null || employeeId <= 0)
            {
                throw new ServiceException("员工主键不能为空");
            }
            if (!uniqueEmployeeIds.add(employeeId))
            {
                continue;
            }
            SysEmployeeDetailRequest detailRequest = new SysEmployeeDetailRequest();
            detailRequest.setEmployeeId(employeeId);
            employees.add(employeeService.detail(detailRequest));
        }
        return employees;
    }
    private Map<String, Object> deleteEmployeesFromHikvision(List<SysEmployeeVO> employees)
    {
        Map<String, Object> result = new LinkedHashMap<String, Object>();
        result.put("employees", employees.size());
        List<SysDoorDevice> devices = doorDeviceMapper.selectEnabledHikvisionDevices();
        result.put("total", devices.size());
        if (devices.isEmpty())
        {
            result.put("status", "skipped");
            result.put("message", "未配置启用的海康门禁设备");
            return result;
        }
        String username = readHikvisionConfig("hikvision.access.username", "HIKVISION_ACCESS_USERNAME", "admin");
        String password = readHikvisionConfig("hikvision.access.password", "HIKVISION_ACCESS_PASSWORD", "");
        if (StringUtils.isEmpty(password))
        {
            result.put("status", "skipped");
            result.put("message", "未配置海康门禁设备密码");
            handleHikvisionDeleteFailure(result);
            return result;
        }
        List<Map<String, Object>> records = new ArrayList<Map<String, Object>>();
        int successCount = 0;
        int totalCount = devices.size() * employees.size();
        for (SysDoorDevice device : devices)
        {
            for (SysEmployeeVO employee : employees)
            {
                Map<String, Object> record = deleteEmployeeFromHikvisionDevice(device, employee, username, password);
                records.add(record);
                if (Boolean.TRUE.equals(record.get("success")))
                {
                    successCount++;
                }
            }
        }
        result.put("success", successCount);
        result.put("failed", totalCount - successCount);
        result.put("records", records);
        result.put("status", successCount == totalCount ? "success" : (successCount == 0 ? "failed" : "partial"));
        handleHikvisionDeleteFailure(result);
        return result;
    }
    private Map<String, Object> deleteEmployeeFromHikvisionDevice(SysDoorDevice device, SysEmployeeVO employee,
                                                                  String username, String password)
    {
        Map<String, Object> record = new LinkedHashMap<String, Object>();
        record.put("doorId", device.getDoorId());
        record.put("deviceName", device.getDeviceName());
        record.put("deviceId", device.getDeviceId());
        record.put("employeeId", employee.getEmployeeId());
        record.put("employeeNo", employee.getEmployeeNo());
        record.put("cardNo", employee.getCardNo());
        try
        {
            HikvisionAccessControlApi.DeviceConfig deviceConfig = HikvisionAccessControlApi.DeviceConfig
                    .http(device.getDeviceId(), username, password);
            deviceConfig.setPort(readHikvisionIntConfig("hikvision.access.port", "HIKVISION_ACCESS_PORT", 80));
            deviceConfig.setHttps(readHikvisionBooleanConfig("hikvision.access.https", "HIKVISION_ACCESS_HTTPS", false));
            HikvisionAccessControlApi.DeleteResult deleteResult = HikvisionAccessControlApi.deleteEmployee(
                    deviceConfig, buildHikvisionDeleteEmployee(employee));
            boolean success = isHikvisionDeleteSuccess(deleteResult);
            record.put("success", success);
            record.put("result", deleteResult);
            if (!success)
            {
                record.put("message", "海康门禁员工删除部分失败");
            }
        }
        catch (Exception e)
        {
            record.put("success", false);
            record.put("message", e.getMessage());
        }
        return record;
    }
    private HikvisionAccessControlApi.EmployeeCredential buildHikvisionDeleteEmployee(SysEmployeeVO employee)
    {
        return HikvisionAccessControlApi.EmployeeCredential.of(
                employee.getEmployeeNo(), employee.getEmployeeName(), employee.getCardNo());
    }
    private boolean isHikvisionDeleteSuccess(HikvisionAccessControlApi.DeleteResult result)
    {
        return result != null
                && isHikvisionResultSuccess(result.getUserInfo())
                && isHikvisionResultSuccess(result.getCard())
                && isHikvisionResultSuccess(result.getFace());
    }
    private boolean isHikvisionResultSuccess(HikvisionAccessControlApi.HikvisionResult result)
    {
        return result == null || result.isSuccess();
    }
    private Map<String, Object> issueEmployeeToHikvision(SysEmployeeAddRequest request)
    {
        Map<String, Object> result = new LinkedHashMap<String, Object>();
@@ -428,6 +562,18 @@
        }
    }
    private void handleHikvisionDeleteFailure(Map<String, Object> result)
    {
        if (!readHikvisionBooleanConfig("hikvision.access.fail-on-error", "HIKVISION_ACCESS_FAIL_ON_ERROR", false))
        {
            return;
        }
        if ("failed".equals(result.get("status")) || "partial".equals(result.get("status")))
        {
            throw new ServiceException("海康门禁员工删除失败");
        }
    }
    private AjaxResult middlePlatformError(IOException e)
    {
        return error("中台数据查询失败:" + e.getMessage());