ludc
2023-11-24 07c80a52302e47cc4eb5fd19e4eb2dad6c7c7885
本地日志文件下载功能完善
已修改2个文件
已添加11个文件
915 ■■■■■ 文件已修改
Source/UBCS-WEB/src/views/monitor/log/authLog.vue 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS-WEB/src/views/monitor/log/localLog.vue 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS-WEB/src/views/monitor/log/loginLog.vue 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS-WEB/src/views/monitor/log/operateLog.vue 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/LogApplication.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/controller/LogErrorController.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/controller/LogLocalController.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/controller/LogOperateController.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/mapper/LogOperateMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/service/ILogLocalService.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/service/ILogOperateService.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/service/impl/LogLocalServiceImpl.java 318 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/service/impl/LogOperateServiceImpl.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/UBCS-WEB/src/views/monitor/log/authLog.vue
Source/UBCS-WEB/src/views/monitor/log/localLog.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,208 @@
<template>
    <basic-container>
      <avue-crud ref="crud"
               v-model="form"
               :before-close="beforeClose"
               :before-open="beforeOpen"
               :data="data"
               :option="option"
               :permission="permissionList"
               :table-loading="loading"
               @row-del="rowDel"
               @search-change="searchChange"
               @search-reset="searchReset"
               @selection-change="selectionChange"
               @row-click="clickRowChange"
               @current-change="currentChange"
               @size-change="sizeChange"
               @refresh-change="refreshChange"
               @on-load="onLoad"
               @tree-load="treeLoad">
            <template slot="menu" slot-scope="scope">
                <el-button
                    icon="el-icon-download el-icon--right"
                    size="small"
                    type="text"
                    :loading="downloadLoading"
                    @click="downLoadLogFile(scope.row)"
                    v-if="permissionList.downLoadBtn"
                >下载
                </el-button>
            </template>
      </avue-crud>
    </basic-container>
  </template>
  <script>
    import {getLazyList, deleteLocalLog,downLoadLog} from "@/api/logs";
    import func from "@/util/func";
    import {mapGetters} from "vuex";
    export default {
      data() {
        return {
          form: {},
          selectionList: [],
          query: {},
          logPath: "",
          loading: true,
          page: {
            pageSize: 10,
            currentPage: 1,
            total: 0
          },
          option: {
            height: "auto",
            lazy: true,
            columnBtn: false,
            tip: false,
            searchShow: true,
            searchMenuSpan: 6,
            tree: true,
            border: true,
            index: true,
            selection: true,
            editBtn: false,
            delBtn: true,
            addBtn: false,
            viewBtn: false,
            // menuWidth: 300,
            dialogClickModal: false,
            highlightCurrentRow: true, //行选中时高亮
            rowKey: "logName", //行数据的 Key,用来优化 Table çš„æ¸²æŸ“
            column: [
              {
                label: "服务名称",
                prop: "serviceName",
                width:'120',
                search: true
              },
              {
                label: "服务ID",
                prop: "serviceId",
                search: true
              },
              {
                label: "日志路径",
                prop: "logPath",
                width:'160'
              },
              {
                label: "日志名称",
                prop: "logName",
                width:'80',
              },
              {
                label: "日志类型",
                prop: "logType"
              },
              {
                label: "创建时间",
                prop: "createTime",
                width:'180'
              },
              {
                label: "最后修改时间",
                prop: "lastModifier",
                width:'180'
              }
            ]
          },
          data: [],
          downloadLoading: false,
        };
      },
      computed: {
        ...mapGetters(["permission"]),
        permissionList() {
          return {
            delBtn: this.vaildData(this.permission.localLog.localLog_delete, false),
            downLoadBtn: this.vaildData(this.permission.localLog.localLog_dwonload, false)
          };
        }
      },
      methods: {
        downLoadLogFile(row){
            this.downloadLoading = true;
            let logPath = row.hasChildren ?  row.logPath:row.logPath+"\\"+row.logName;
            downLoadLog(Object.assign({},row,{logFullPaths:logPath})).then(res=>{
                func.downloadFileByBlobHandler(res);
                this.downloadLoading = false;
            }).catch((res)=>{
                //this.$message.warning(res)
                this.downloadLoading = false;
            })
        },
        // è¡Œåˆ é™¤
        rowDel(row, index, done) {
            this.$confirm("确定将选择的日志文件删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
            .then(() => {
                let logPath = row.hasChildren ?  row.logPath:row.logPath+"\\"+row.logName;
                return deleteLocalLog(Object.assign({},row,{logFullPaths:logPath}));
            })
            .then(() => {
                this.$message({
                    type: "success",
                    message: "操作成功!"
                });
                // æ•°æ®å›žè°ƒè¿›è¡Œåˆ·æ–°
                done(row);
                //this.onLoad();
            });
        },
        searchReset() {
            this.query = {};
            this.parentId = 0;
            this.onLoad(this.page);
        },
        searchChange(params, done) {
            this.query = params;
            this.parentId = '';
            this.page.currentPage = 1;
            this.onLoad(this.page, params);
            done();
        },
        clickRowChange(row) {
            this.$refs.crud.toggleSelection();
            this.selectionList = row;
            this.$refs.crud.setCurrentRow(row);
            this.$refs.crud.toggleRowSelection(row); //选中当前行
        },
        selectionChange(list) {
            this.selectionList = list;
            this.$refs.crud.setCurrentRow(this.selectionList[list.length - 1]);
        },
        selectionClear() {
            this.selectionList = [];
            this.$refs.crud.toggleSelection();
        },
        refreshChange() {
            this.onLoad(this.page, this.query);
        },
        onLoad(page, params = {}) {
            this.loading = true;
            //Object.assign(params, this.query)
            getLazyList({"logPath": this.logPath}).then(res => {
                this.data = res.data.data;
                this.loading = false;
                this.selectionClear();
            });
        },
        treeLoad(tree, treeNode, resolve) {
            const logPath = tree.logPath;
            getLazyList({"logPath": logPath}).then(res => {
                resolve(res.data.data);
            });
        }
      }
    };
  </script>
  <style>
  </style>
Source/UBCS-WEB/src/views/monitor/log/loginLog.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,139 @@
<template>
  <basic-container>
    <avue-crud :option="option"
               :table-loading="loading"
               :data="data"
               ref="crud"
               v-model="form"
               :permission="permissionList"
               :page.sync="page"
               :before-open="beforeOpen"
               @search-change="searchChange"
               @search-reset="searchReset"
               @current-change="currentChange"
               @size-change="sizeChange"
               @refresh-change="refreshChange"
               @on-load="onLoad">
    </avue-crud>
  </basic-container>
</template>
<script>
  import {getUsualList, getUsualLogs} from "@/api/logs";
  import {mapGetters} from "vuex";
  export default {
    data() {
      return {
        form: {},
        selectionList: [],
        query: {},
        loading: true,
        page: {
          pageSize: 10,
          currentPage: 1,
          total: 0
        },
        option: {
          height: 'auto',
          calcHeight: 30,
          columnBtn:false,
          tip: false,
          searchShow: true,
          searchMenuSpan: 6,
          border: true,
          index: true,
          viewBtn: true,
          editBtn: false,
          addBtn: false,
          delBtn: false,
          menuWidth: 120,
          dialogType: 'drawer',
          column: [
            {
              label: "用户名",
              prop: "serviceId",
              search: true
            },
            {
              label: "姓名",
              prop: "serverHost",
              search: true
            },
            {
              label: "用户id",
              prop: "serverIp"
            },
            {
              label: "模块",
              prop: "env",
              width:'80'
            },
            {
              label: "时间",
              prop: "logLevel"
            },
            {
              label: "操作结果",
              prop: "logId"
            },
            {
              label: "描述",
              prop: "requestUri"
            },
          ]
        },
        data: []
      };
    },
    computed: {
      ...mapGetters(["permission"]),
      permissionList() {
        return {
          viewBtn: this.vaildData(this.permission.log_usual.log_usual_view, false)
        };
      }
    },
    methods: {
      searchReset() {
        this.query = {};
        this.onLoad(this.page);
      },
      searchChange(params, done) {
        this.query = params;
        this.page.currentPage = 1;
        this.onLoad(this.page, params);
        done();
      },
      beforeOpen(done, type) {
        if (["edit", "view"].includes(type)) {
          getUsualLogs(this.form.id).then(res => {
            this.form = res.data.data;
          });
        }
        done();
      },
      currentChange(currentPage){
        this.page.currentPage = currentPage;
      },
      sizeChange(pageSize){
        this.page.pageSize = pageSize;
      },
      refreshChange() {
        this.onLoad(this.page, this.query);
      },
      onLoad(page, params = {}) {
        this.loading = true;
        getUsualList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
          const data = res.data.data;
          this.page.total = data.total;
          this.data = data.records;
          this.loading = false;
        });
      }
    }
  };
</script>
<style>
</style>
Source/UBCS-WEB/src/views/monitor/log/operateLog.vue
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/LogApplication.java
@@ -29,7 +29,7 @@
 * @author Chill
 */
@EnableDiscoveryClient
@EnableFeignClients("org.springblade")
@EnableFeignClients(basePackages = {"com.vci.ubcs", "org.springblade"})
@SpringBootApplication
public class LogApplication {
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/controller/LogErrorController.java
@@ -25,10 +25,7 @@
import org.springblade.core.mp.support.Query;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springframework.web.bind.annotation.GetMapping;
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.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import java.util.Map;
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/controller/LogLocalController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,83 @@
package com.vci.ubcs.log.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.common.utils.StringUtils;
import com.vci.ubcs.log.dto.LocalLogVO;
import com.vci.ubcs.log.service.ILogLocalService;
import com.vci.ubcs.log.entity.LocalLog;
import com.vci.ubcs.resource.utils.FileDownloadUtil;
import com.vci.ubcs.starter.web.util.ControllerUtil;
import com.vci.ubcs.starter.web.util.LangBaseUtil;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.rmi.ServerException;
import java.util.List;
import java.util.Map;
/**
 * æœ¬åœ°ç³»ç»Ÿæ—¥å¿—
 * @author ludc
 * @date 2023/10/31 15:37
 */
@NonDS
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/localLog")
public class LogLocalController {
    private final ILogLocalService logLocalService;
    /**
     * èŽ·å–æ—¥å¿—æ–‡ä»¶åˆ—è¡¨
     * @param localLog
     * @return
     */
    @PostMapping("/lazy-list")
    public R<List<LocalLog>> getSystemLogList(@RequestBody LocalLog localLog){
         return R.data(logLocalService.getSystemLogList(localLog.getLogPath()));
    }
    /**
     * ä¸‹è½½æ—¥å¿—文件
     * @param localLogVO ä¸‹è½½æ—¥å¿—的全路径集合
     * @param response
     * @return
     */
    @RequestMapping(value = "/downLoadLog",method = {RequestMethod.GET,RequestMethod.POST})
    public void downloadLogByServiceName(@RequestBody LocalLogVO localLogVO, HttpServletResponse response) throws IOException {
        try {
            //ControllerUtil.writeFileToResponse(response,excelName);
            FileDownloadUtil.downloadFileLocal(response, logLocalService.downloadLogByServiceNameAndFileName(localLogVO),true);
        } catch (Throwable e) {
            //如果出错,把错误信息写到text
            String msg = LangBaseUtil.getErrorMsg(e);
            if(StringUtils.isBlank(msg)){
                msg = "未知错误";
            }
            ControllerUtil.writeDataToResponse(response,msg.getBytes(StandardCharsets.UTF_8),null);
        }
    }
    /**
     * åˆ é™¤æ—¥å¿—文件
     * @param localLogVO
     * @return
     * @throws ServerException
     */
    @DeleteMapping("/deleteLogFile")
    public R deleteLogFile(@RequestBody LocalLogVO localLogVO) throws ServerException {
        return logLocalService.deleteLogFile(localLogVO);
    }
}
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/controller/LogOperateController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.vci.ubcs.log.controller;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tenant.annotation.NonDS;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * æ“ä½œæ—¥å¿—管理:(包括登录日志、操作日志、授权日志,以及管理员的以上三种日志)
 * @author ludc
 * @date 2023/11/24 10:43
 */
@NonDS
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/operateLog")
public class LogOperateController {
}
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/mapper/LogOperateMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.vci.ubcs.log.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.vci.ubcs.log.entity.LogOperate;
import org.apache.ibatis.annotations.Mapper;
/**
 * æ“ä½œæ—¥å¿—管理:(包括登录日志、操作日志、授权日志,以及管理员的以上三种日志)
 * @author ludc
 * @date 2023/11/24 10:50
 */
@Mapper
public interface LogOperateMapper extends BaseMapper<LogOperate> {
}
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/service/ILogLocalService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
package com.vci.ubcs.log.service;
import com.vci.ubcs.log.dto.LocalLogVO;
import com.vci.ubcs.log.entity.LocalLog;
import com.vci.ubcs.resource.bo.FileObjectBO;
import org.springblade.core.tool.api.R;
import java.rmi.ServerException;
import java.util.List;
import java.util.Map;
/**
 * æœ¬åœ°ç³»ç»Ÿæ—¥å¿—
 * @author ludc
 * @date 2023/10/31 15:38
 */
public interface ILogLocalService {
    /**
     * æŸ¥çœ‹ï¼Œæœ¬åœ°ç³»ç»Ÿæ—¥å¿—列表
     * @param logParentPath
     * @return
     */
    List<LocalLog> getSystemLogList(String logParentPath);
    /**
     * ä¸‹è½½ï¼Œæ ¹æ®æœåŠ¡åæ‰€åœ¨æ–‡ä»¶åå’Œæ–‡ä»¶åä¸‹è½½æ–‡ä»¶
     * @param localLogVO ä¸‹è½½æ—¥å¿—的对象
     * @return æ–‡ä»¶çš„信息
     */
    FileObjectBO downloadLogByServiceNameAndFileName(LocalLogVO localLogVO) throws ServerException;
    /**
     * åˆ é™¤ï¼Œæ ¹æ®æœåŠ¡æ‰€åœ¨æ–‡ä»¶åï¼Œå’Œæ—¥å¿—æ–‡ä»¶åç§°åˆ é™¤
     * @param localLogVO
     * @return æ‰§è¡Œç»“æžœ
     */
    R deleteLogFile(LocalLogVO localLogVO) throws ServerException;
}
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/service/ILogOperateService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
package com.vci.ubcs.log.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.vci.ubcs.log.entity.LogOperate;
import java.util.List;
/**
 * æ“ä½œæ—¥å¿—管理:(包括登录日志、操作日志、授权日志,以及管理员的以上三种日志)
 * @author ludc
 * @date 2023/11/24 10:50
 */
public interface ILogOperateService extends IService<LogOperate> {
    /**
     * ä¿å­˜æ“ä½œæ—¥å¿—
     * @param logOperate
     * @return
     */
    boolean saveLogOperate(LogOperate logOperate);
    /**
     * æ¡ä»¶æŸ¥è¯¢èŽ·å–æ—¥å¿—åˆ—è¡¨
     * @param logOperate
     * @return
     */
    List<LogOperate> listByCondition(LogOperate logOperate);
}
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/service/impl/LogLocalServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,318 @@
package com.vci.ubcs.log.service.impl;
import com.vci.ubcs.log.dto.LocalLogVO;
import com.vci.ubcs.log.service.ILogLocalService;
import com.vci.ubcs.log.entity.LocalLog;
import com.vci.ubcs.resource.utils.FileUtil;
import com.vci.ubcs.resource.utils.ZipUtil;
import com.vci.ubcs.resource.vo.FileObjectVO;
import com.vci.ubcs.starter.exception.VciBaseException;
import com.vci.ubcs.starter.web.util.BeanUtil;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springblade.core.log.exception.ServiceException;
import com.vci.ubcs.omd.cache.EnumCache;
import com.vci.ubcs.omd.enums.EnumEnum;
import com.vci.ubcs.resource.bo.FileObjectBO;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.rmi.ServerException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
 * æœ¬åœ°ç³»ç»Ÿæ—¥å¿—
 * @author ludc
 * @date 2023/10/31 15:39
 */
@Service
@Slf4j
public class LogLocalServiceImpl implements ILogLocalService{
    /**
     * å„个服务存放的的父路径
     */
    @Value("${local-log.parent-path:/data1/ubcs/ubcs-server}")
    private String PARENTPATH;
    /**
     * æ—¥å¿—文件的具体位置
     */
    @Value("${local-log.log-path:/target/log}")
    private String LOGPATH;
    /**
     * å½“前操作系统,是否为windows系统
     */
    private Boolean isWindows = true;
    {
        String os = System.getProperty("os.name").toLowerCase();
        //默认就配置为windows的,如果不是当前系统不是windows就需要对其转换为linux的文件路径格式
        if (!os.contains("win")) {
            this.PARENTPATH = this.PARENTPATH.substring(this.PARENTPATH.lastIndexOf(":") + 1).replace("\\", "/");
            this.LOGPATH = this.LOGPATH.replace("\\", "/");
            this.isWindows = false;
        }
    }
    /**
     * åŽ‹ç¼©æ–‡ä»¶çš„å·¥å…·ç±»
     */
    @Resource
    private ZipUtil zipUtil;
    /**
     * èŽ·å–æœ¬åœ°æ—¥å¿—åˆ—è¡¨
     * @param logParentPath
     * @return
     */
    //@Override
    public List<LocalLog> getSystemLogList(String logParentPath) {
        List<LocalLog> localLogs = new ArrayList<>();
        // ä¸ä¸ºç©ºè¯´æ˜Žæ˜¯åŠ è½½å½“å‰è¿™ä¸ªæœåŠ¡è·¯å¾„ä¸‹çš„æ—¥å¿—æ–‡ä»¶
        if(Func.isNotEmpty(logParentPath)){
            File file = new File(logParentPath);
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                Arrays.stream(files).forEach(item->{
                    // ç»„建日志文件对象
                    LocalLog localLog = new LocalLog();
                    localLog.setLogName(item.getName());
                    localLog.setLogType(getLogType(item.getName()));
                    localLog.setCreateTime(getLastModifiedOrCreatTime(false,logParentPath));
                    localLog.setLastModifier(getLastModifiedOrCreatTime(true,logParentPath));
                    localLog.setLogPath(logParentPath);
                    String serviceId = getServiceId(logParentPath);
                    localLog.setServiceId(serviceId);
                    localLog.setServiceName(getServiceName(serviceId));
                    localLog.setHasChildren(false);
                    localLogs.add(localLog);
                });
            }
        }else {
            File fileDir = new File(PARENTPATH);
            File[] childDir = fileDir.listFiles();
            Arrays.stream(childDir).forEach(dir->{
                if(dir.getName().contains("ubcs_")){
                    String fullPath = dir.getPath() + LOGPATH;
                    File file = new File(fullPath);
                    LocalLog localLog = new LocalLog();
                    localLog.setLastModifier(getLastModifiedOrCreatTime(true,fullPath));
                    localLog.setCreateTime(getLastModifiedOrCreatTime(false,fullPath));
                    localLog.setLogPath(fullPath);
                    String serviceId = getServiceId(file.getPath());
                    localLog.setServiceId(serviceId);
                    String serviceName = getServiceName(serviceId);
                    localLog.setServiceName(serviceName);
                    localLog.setLogType(serviceName+"日志父目录");
                    localLog.setLogName(serviceName+"日志父目录");
                    localLog.setHasChildren(true);
                    localLogs.add(localLog);
                }
            });
        }
        return localLogs;
    }
    /**
     * èŽ·å–æ–‡ä»¶æœ€åŽä¿®æ”¹æˆ–è€…åˆ›å»ºæ—¶é—´
     * @param isModifier
     * @return
     */
    private String getLastModifiedOrCreatTime(boolean isModifier,String pathStr) {
        Path path = FileSystems.getDefault().getPath(pathStr);
        String date = "";
        try {
            BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // æ˜¯èŽ·å–æœ€åŽä¿®æ”¹æ—¶é—´
            if(isModifier){
                date = dateFormat.format(new Date(attr.lastModifiedTime().toMillis()));
            }else {
                date = dateFormat.format(new Date(attr.creationTime().toMillis()));
            }
        } catch (IOException e) {
            throw new ServiceException("Error reading file date attributes: " + e.getMessage());
        }
        return date;
    }
    /**
     * èŽ·å–æ—¥å¿—ç±»åž‹
     * @param fileName
     * @return
     */
    private String getLogType(String fileName){
        //判断日志的的类型
        if (fileName.contains("error")) {
            return "Error";
        } else if (fileName.contains("info")) {
            return "Info";
        } else if (fileName.contains("warning")) {
            return "Warning";
        } else {
            return "Unknown";
        }
    }
    /**
     * èŽ·å–æœåŠ¡ID
     * @param servciePath
     * @return
     */
    private String getServiceId(String servciePath){
        // æ ¹æ®å½“前操作系统来决定是通过什么字符来截取
        String[] parts = servciePath.split(this.isWindows ? "\\\\":"/");
        String extractedString = "";
        if(parts.length > 3){
            extractedString = parts[parts.length - 3];
        }
        return extractedString;
    }
    /**
     * èŽ·å–æœåŠ¡åç§°
     * @param serViceId
     * @return
     */
    private String getServiceName(String serViceId){
        return EnumCache.getValue(EnumEnum.SERCIVE_NAME_ROLE, serViceId);
    }
    /**
     * æˆªå–路径中的日志文件名称
     * @param logFullPath
     * @return
     */
    private String getLogFileName(String logFullPath){
        // æ ¹æ®å½“前操作系统来决定是通过什么字符来截取
        String[] parts = logFullPath.split(this.isWindows ? "\\\\":"/");
        String logFileName = "";
        if(parts.length > 3){
            logFileName = parts[parts.length - 1];
        }
        return logFileName;
    }
    /**
     * ä¸‹è½½æ—¥å¿—文件
     * @param localLogVO ä¸‹è½½æ—¥å¿—对象
     * @return
     * @throws ServerException
     */
    @Override
    public FileObjectBO downloadLogByServiceNameAndFileName(LocalLogVO localLogVO) throws ServerException {
        if(Func.isEmpty(localLogVO) || Func.isEmpty(localLogVO.getLogPath())){
            throw new ServerException("未获取到该日志路径!");
        }
        FileObjectBO fileObjectBO = new FileObjectBO();
        String logFullPaths = localLogVO.getLogFullPaths();
        // åˆ¤æ–­æ˜¯å¦æ˜¯çˆ¶ç›®å½•
        if(!localLogVO.getHasChildren()){
            //只下载一个日志文件
            File file = new File(logFullPaths);
            if(!file.isFile() || !file.exists()){
                throw new ServerException("本地日志文件路径"+ logFullPaths +"中未找到日志");
            }
            try {
                fileObjectBO.setName(file.getName());
                fileObjectBO.setInputStream(new FileInputStream(file));
                fileObjectBO.setFileLocalPath(logFullPaths);
                fileObjectBO.setFileExtension(".log");
            }catch (Throwable e){
                throw new VciBaseException("获取文件的流有问题",new String[]{logFullPaths},e);
            }
        }else{
            // æ˜¯çˆ¶ç›®å½•,所以需要获取到下面的所有子目录
            // æœ‰å¤šä¸ªï¼Œéœ€è¦ä½¿ç”¨zip进行压缩
            String tempFolder = FileUtil.getDefaultTempFolder();
            File[] file1 = new File(logFullPaths).listFiles();
            if(file1.length > 0){
                Arrays.stream(file1).forEach(item->{
                    String fileName = tempFolder + File.separator + System.currentTimeMillis() + ".log";
                    File file = new File(fileName);
                    try {
                        if(!file.exists()) {
                            file.createNewFile();
                        }
                    }catch (Throwable e){
                        throw new VciBaseException("创建文件出错,{0}",new String[]{fileName});
                    }
                    File logFile = new File(item.getPath());
                    if(!logFile.exists() || !logFile.isFile()){
                        throw new VciBaseException("本地日志文件路径"+item.getPath()+"中未找到日志");
                    }
                    try(OutputStream os = new FileOutputStream(file);
                        InputStream ins = new FileInputStream(logFile);
                    ){
                        IOUtils.copy(ins,os);
                    }catch (Throwable e){
                        throw new VciBaseException("下载文件到临时文件夹里出错,{0}",new String[]{fileName});
                    }
                });
                String zipName = new File(tempFolder).getPath() + File.separator + getLogFileName(logFullPaths) + "等"+file1.length + "个文件.zip";
                zipUtil.folderToZipFile(tempFolder,zipName);
                fileObjectBO.setFileLocalPath(zipName);
                fileObjectBO.setFileExtension(".log");
                if(log.isDebugEnabled()){
                    log.debug("下载文件的信息,",zipName);
                }
            }
        }
        return fileObjectBO;
    }
    /**
     * åˆ é™¤æ—¥å¿—文件
     * @param localLogVO æ–‡ä»¶å…¨è·¯å¾„集合
     * @throws ServerException
     */
    @Override
    public R deleteLogFile(LocalLogVO localLogVO) throws ServerException {
        List<String> resMsgs = new ArrayList<>();
        // åˆ¤æ–­æ˜¯å¦æ˜¯æ—¥å¿—顶层目录
        if(localLogVO.getHasChildren()){
            // æ˜¯é¡¶å±‚目录,需要循环去删除包含的所有日志文件
            File parentFile = new File(localLogVO.getLogFullPaths());
            if(parentFile.isDirectory()){
                Arrays.stream(parentFile.listFiles()).forEach(logFile->{
                    if (logFile.exists()) {
                        //删除失败的直接记录下文件名
                        if (!logFile.delete()) {
                            resMsgs.add(getLogFileName(logFile.getPath()));
                        }
                    }
                });
            }
        }else {
            // å•个删除
            File file = new File(localLogVO.getLogFullPaths());
            if (file.exists()) {
                //删除失败的直接记录下文件名
                if (!file.delete()) {
                    resMsgs.add(getLogFileName(localLogVO.getLogFullPaths()));
                }
            }
        }
        return resMsgs.size()==0 ? R.success("删除成功!"):R.fail("以下日志文件:"+resMsgs.stream().collect(Collectors.joining(","))+"删除失败!");
    }
}
Source/UBCS/ubcs-ops/ubcs-log/src/main/java/com/vci/ubcs/log/service/impl/LogOperateServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
package com.vci.ubcs.log.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.vci.ubcs.log.entity.LogOperate;
import com.vci.ubcs.log.mapper.LogOperateMapper;
import com.vci.ubcs.log.service.ILogOperateService;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.tool.utils.Func;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * æ“ä½œæ—¥å¿—管理:(包括登录日志、操作日志、授权日志,以及管理员的以上三种日志)
 * @author ludc
 * @date 2023/11/24 10:51
 */
@Service
public class LogOperateServiceImpl extends ServiceImpl<LogOperateMapper,LogOperate> implements ILogOperateService {
    @Autowired
    private LogOperateMapper logOperateMapper;
    /**
     * ä¿å­˜æ“ä½œæ—¥å¿—
     * @param logOperate
     * @return
     */
    @Override
    public boolean saveLogOperate(LogOperate logOperate) {
        if(Func.isEmpty(logOperate)){
            return false;
        }
        return SqlHelper.retBool(logOperateMapper.insert(logOperate));
    }
    /**
     * æ¡ä»¶æŸ¥è¯¢èŽ·å–æ—¥å¿—åˆ—è¡¨
     * @param logOperate
     * @return
     */
    @Override
    public List<LogOperate> listByCondition(LogOperate logOperate) {
        QueryWrapper<LogOperate> queryWrapper = Condition.getQueryWrapper(logOperate);
        this.list(queryWrapper);
        return this.list(queryWrapper);
    }
}