From 25df88d0ab9d7444ed1d162b9efa1259ac2f6f66 Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期一, 27 四月 2026 10:13:53 +0800
Subject: [PATCH] 小程序对接finish

---
 backend/src/main/java/com/sinata/appointment/service/OpLogApplicationService.java |  157 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 156 insertions(+), 1 deletions(-)

diff --git a/backend/src/main/java/com/sinata/appointment/service/OpLogApplicationService.java b/backend/src/main/java/com/sinata/appointment/service/OpLogApplicationService.java
index 46365a3..63c10bb 100644
--- a/backend/src/main/java/com/sinata/appointment/service/OpLogApplicationService.java
+++ b/backend/src/main/java/com/sinata/appointment/service/OpLogApplicationService.java
@@ -1,11 +1,24 @@
 package com.sinata.appointment.service;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.sinata.appointment.dto.OpLogListVo;
 import com.sinata.appointment.entity.BizOpLog;
+import com.sinata.appointment.entity.MpUser;
+import com.sinata.appointment.entity.SysUser;
 import com.sinata.appointment.mapper.BizOpLogMapper;
+import com.sinata.appointment.mapper.MpUserMapper;
+import com.sinata.appointment.mapper.SysUserMapper;
 import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import org.slf4j.MDC;
 import org.springframework.scheduling.annotation.Async;
+import org.springframework.util.StringUtils;
 import org.springframework.stereotype.Service;
 
 @Service
@@ -13,18 +26,50 @@
 public class OpLogApplicationService {
 
     public static final String MDC_TRACE = "traceId";
+    public static final String SOURCE_ADMIN = "ADMIN";
+    public static final String SOURCE_MINI_EMPLOYEE = "MINI_EMPLOYEE";
 
     private final BizOpLogMapper bizOpLogMapper;
+    private final SysUserMapper sysUserMapper;
+    private final MpUserMapper mpUserMapper;
 
-    @Async
+    public IPage<OpLogListVo> page(long page, long size, String sourceType) {
+        Page<BizOpLog> pager = new Page<>(page, size);
+        LambdaQueryWrapper<BizOpLog> query =
+                new LambdaQueryWrapper<BizOpLog>()
+                        .eq(BizOpLog::getDelFlag, 0)
+                        .orderByDesc(BizOpLog::getOpTime)
+                        .orderByDesc(BizOpLog::getId);
+        String normalizedSourceType = normalizeSourceType(sourceType);
+        if (normalizedSourceType != null) {
+            query.eq(BizOpLog::getSourceType, normalizedSourceType);
+        }
+        IPage<BizOpLog> logPage = bizOpLogMapper.selectPage(pager, query);
+        Page<OpLogListVo> result =
+                new Page<>(logPage.getCurrent(), logPage.getSize(), logPage.getTotal());
+        List<BizOpLog> records = logPage.getRecords();
+        result.setRecords(toListVos(records));
+        return result;
+    }
+
+    @Async("applicationTaskExecutor")
     public void recordAsync(
+            String sourceType,
             Long operatorUserId,
             String module,
             String action,
             String resourceType,
             String resourceId,
             String detailJson) {
+        String normalizedSourceType = normalizeSourceType(sourceType);
+        if (!StringUtils.hasText(normalizedSourceType)) {
+            return;
+        }
+        if (SOURCE_MINI_EMPLOYEE.equals(normalizedSourceType) && !isEmployee(operatorUserId)) {
+            return;
+        }
         BizOpLog log = new BizOpLog();
+        log.setSourceType(normalizedSourceType);
         log.setOperatorUserId(operatorUserId);
         log.setModule(module);
         log.setAction(action);
@@ -35,4 +80,114 @@
         log.setTraceId(MDC.get(MDC_TRACE));
         bizOpLogMapper.insert(log);
     }
+
+    private List<OpLogListVo> toListVos(List<BizOpLog> records) {
+        if (records == null || records.isEmpty()) {
+            return List.of();
+        }
+        List<Long> adminUserIds =
+                records.stream()
+                        .filter(item -> SOURCE_ADMIN.equals(item.getSourceType()))
+                        .map(BizOpLog::getOperatorUserId)
+                        .filter(Objects::nonNull)
+                        .distinct()
+                        .toList();
+        List<Long> mpUserIds =
+                records.stream()
+                        .filter(item -> SOURCE_MINI_EMPLOYEE.equals(item.getSourceType()))
+                        .map(BizOpLog::getOperatorUserId)
+                        .filter(Objects::nonNull)
+                        .distinct()
+                        .toList();
+        Map<Long, String> adminNameMap = loadAdminNameMap(adminUserIds);
+        Map<Long, String> mpNameMap = loadMpNameMap(mpUserIds);
+        return records.stream()
+                .map(item -> toListVo(item, adminNameMap, mpNameMap))
+                .toList();
+    }
+
+    private OpLogListVo toListVo(
+            BizOpLog item, Map<Long, String> adminNameMap, Map<Long, String> mpNameMap) {
+        OpLogListVo vo = new OpLogListVo();
+        vo.setId(item.getId());
+        vo.setSourceType(item.getSourceType());
+        vo.setSourceTypeText(resolveSourceTypeText(item.getSourceType()));
+        vo.setOperatorUserId(item.getOperatorUserId());
+        vo.setModule(item.getModule());
+        vo.setAction(item.getAction());
+        vo.setResourceType(item.getResourceType());
+        vo.setResourceId(item.getResourceId());
+        vo.setDetailJson(item.getDetailJson());
+        vo.setTraceId(item.getTraceId());
+        vo.setOpTime(item.getOpTime());
+        if (SOURCE_MINI_EMPLOYEE.equals(item.getSourceType())) {
+            vo.setOperatorName(mpNameMap.getOrDefault(item.getOperatorUserId(), "—"));
+        } else {
+            vo.setOperatorName(adminNameMap.getOrDefault(item.getOperatorUserId(), "—"));
+        }
+        return vo;
+    }
+
+    private Map<Long, String> loadAdminNameMap(List<Long> userIds) {
+        if (userIds == null || userIds.isEmpty()) {
+            return Map.of();
+        }
+        return sysUserMapper.selectBatchIds(userIds).stream()
+                .collect(
+                        Collectors.toMap(
+                                SysUser::getId,
+                                user -> firstNonBlank(user.getRealName(), user.getUsername(), "—"),
+                                (a, _b) -> a));
+    }
+
+    private Map<Long, String> loadMpNameMap(List<Long> userIds) {
+        if (userIds == null || userIds.isEmpty()) {
+            return Map.of();
+        }
+        return mpUserMapper.selectBatchIds(userIds).stream()
+                .filter(user -> "EMPLOYEE".equals(user.getUserType()))
+                .collect(
+                        Collectors.toMap(
+                                MpUser::getId,
+                                user -> firstNonBlank(user.getNickName(), user.getMobile(), "—"),
+                                (a, _b) -> a));
+    }
+
+    private boolean isEmployee(Long operatorUserId) {
+        if (operatorUserId == null) {
+            return false;
+        }
+        MpUser user = mpUserMapper.selectById(operatorUserId);
+        return user != null && "EMPLOYEE".equals(user.getUserType());
+    }
+
+    private String normalizeSourceType(String sourceType) {
+        if (!StringUtils.hasText(sourceType)) {
+            return null;
+        }
+        String normalized = sourceType.trim().toUpperCase();
+        if (SOURCE_ADMIN.equals(normalized)) {
+            return SOURCE_ADMIN;
+        }
+        if (SOURCE_MINI_EMPLOYEE.equals(normalized)) {
+            return SOURCE_MINI_EMPLOYEE;
+        }
+        return null;
+    }
+
+    private String resolveSourceTypeText(String sourceType) {
+        if (SOURCE_MINI_EMPLOYEE.equals(sourceType)) {
+            return "员工端";
+        }
+        return "管理后台";
+    }
+
+    private String firstNonBlank(String... values) {
+        for (String value : values) {
+            if (StringUtils.hasText(value)) {
+                return value.trim();
+            }
+        }
+        return "—";
+    }
 }

--
Gitblit v1.7.1