mirror of
				https://github.com/dromara/RuoYi-Vue-Plus.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	update 补全漏提交文件
This commit is contained in:
		@@ -0,0 +1,14 @@
 | 
			
		||||
--- # 监控配置
 | 
			
		||||
spring:
 | 
			
		||||
  boot:
 | 
			
		||||
    admin:
 | 
			
		||||
      # Spring Boot Admin Client 客户端的相关配置
 | 
			
		||||
      client:
 | 
			
		||||
        # 增加客户端开关
 | 
			
		||||
        enabled: true
 | 
			
		||||
        # 设置 Spring Boot Admin Server 地址
 | 
			
		||||
        url: http://localhost:9090/admin
 | 
			
		||||
        instance:
 | 
			
		||||
          prefer-ip: true # 注册实例时,优先使用 IP
 | 
			
		||||
        username: ruoyi
 | 
			
		||||
        password: 123456
 | 
			
		||||
@@ -0,0 +1,14 @@
 | 
			
		||||
--- # 监控配置
 | 
			
		||||
spring:
 | 
			
		||||
  boot:
 | 
			
		||||
    admin:
 | 
			
		||||
      # Spring Boot Admin Client 客户端的相关配置
 | 
			
		||||
      client:
 | 
			
		||||
        # 增加客户端开关
 | 
			
		||||
        enabled: true
 | 
			
		||||
        # 设置 Spring Boot Admin Server 地址
 | 
			
		||||
        url: http://172.30.0.90:9090/admin
 | 
			
		||||
        instance:
 | 
			
		||||
          prefer-ip: true # 注册实例时,优先使用 IP
 | 
			
		||||
        username: ruoyi
 | 
			
		||||
        password: 123456
 | 
			
		||||
							
								
								
									
										66
									
								
								ruoyi-ui/src/plugins/tab.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								ruoyi-ui/src/plugins/tab.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
import store from '@/store'
 | 
			
		||||
import router from '@/router';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  // 刷新当前tab页签
 | 
			
		||||
  refreshPage(obj) {
 | 
			
		||||
    const { path, matched } = router.currentRoute;
 | 
			
		||||
    if (obj === undefined) {
 | 
			
		||||
      matched.forEach((m) => {
 | 
			
		||||
        if (m.components && m.components.default && m.components.default.name) {
 | 
			
		||||
          if (!['Layout', 'ParentView'].includes(m.components.default.name)) {
 | 
			
		||||
            obj = { name: m.components.default.name, path: path };
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    return store.dispatch('tagsView/delCachedView', obj).then(() => {
 | 
			
		||||
      const { path } = obj
 | 
			
		||||
      router.replace({
 | 
			
		||||
        path: '/redirect' + path
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  // 关闭当前tab页签,打开新页签
 | 
			
		||||
  closeOpenPage(obj) {
 | 
			
		||||
    store.dispatch("tagsView/delView", router.currentRoute);
 | 
			
		||||
    if (obj !== undefined) {
 | 
			
		||||
      return router.push(obj);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  // 关闭指定tab页签
 | 
			
		||||
  closePage(obj) {
 | 
			
		||||
    if (obj === undefined) {
 | 
			
		||||
      return store.dispatch('tagsView/delView', router.currentRoute).then(({ lastPath }) => {
 | 
			
		||||
        return router.push(lastPath || '/');
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    return store.dispatch('tagsView/delView', obj);
 | 
			
		||||
  },
 | 
			
		||||
  // 关闭所有tab页签
 | 
			
		||||
  closeAllPage() {
 | 
			
		||||
    return store.dispatch('tagsView/delAllViews');
 | 
			
		||||
  },
 | 
			
		||||
  // 关闭左侧tab页签
 | 
			
		||||
  closeLeftPage(obj) {
 | 
			
		||||
    return store.dispatch('tagsView/delLeftTags', obj || router.currentRoute);
 | 
			
		||||
  },
 | 
			
		||||
  // 关闭右侧tab页签
 | 
			
		||||
  closeRightPage(obj) {
 | 
			
		||||
    return store.dispatch('tagsView/delRightTags', obj || router.currentRoute);
 | 
			
		||||
  },
 | 
			
		||||
  // 关闭其他tab页签
 | 
			
		||||
  closeOtherPage(obj) {
 | 
			
		||||
    return store.dispatch('tagsView/delOthersViews', obj || router.currentRoute);
 | 
			
		||||
  },
 | 
			
		||||
  // 添加tab页签
 | 
			
		||||
  openPage(title, url) {
 | 
			
		||||
    var obj = { path: url, meta: { title: title } }
 | 
			
		||||
    store.dispatch('tagsView/addView', obj);
 | 
			
		||||
    return router.push(url);
 | 
			
		||||
  },
 | 
			
		||||
  // 修改tab页签
 | 
			
		||||
  updatePage(obj) {
 | 
			
		||||
    return store.dispatch('tagsView/updateVisitedView', obj);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,18 @@
 | 
			
		||||
package com.ruoyi.common.core.service;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 通用 参数配置服务
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public interface ConfigService {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据参数 key 获取参数值
 | 
			
		||||
     *
 | 
			
		||||
     * @param configKey 参数 key
 | 
			
		||||
     * @return 参数值
 | 
			
		||||
     */
 | 
			
		||||
    String getConfigValue(String configKey);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,57 @@
 | 
			
		||||
package com.ruoyi.common.core.service;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 通用 字典服务
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public interface DictService {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 分隔符
 | 
			
		||||
     */
 | 
			
		||||
    String SEPARATOR = ",";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据字典类型和字典值获取字典标签
 | 
			
		||||
     *
 | 
			
		||||
     * @param dictType  字典类型
 | 
			
		||||
     * @param dictValue 字典值
 | 
			
		||||
     * @return 字典标签
 | 
			
		||||
     */
 | 
			
		||||
    default String getDictLabel(String dictType, String dictValue) {
 | 
			
		||||
        return getDictLabel(dictType, dictValue, SEPARATOR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据字典类型和字典标签获取字典值
 | 
			
		||||
     *
 | 
			
		||||
     * @param dictType  字典类型
 | 
			
		||||
     * @param dictLabel 字典标签
 | 
			
		||||
     * @return 字典值
 | 
			
		||||
     */
 | 
			
		||||
    default String getDictValue(String dictType, String dictLabel) {
 | 
			
		||||
        return getDictValue(dictType, dictLabel, SEPARATOR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据字典类型和字典值获取字典标签
 | 
			
		||||
     *
 | 
			
		||||
     * @param dictType  字典类型
 | 
			
		||||
     * @param dictValue 字典值
 | 
			
		||||
     * @param separator 分隔符
 | 
			
		||||
     * @return 字典标签
 | 
			
		||||
     */
 | 
			
		||||
    String getDictLabel(String dictType, String dictValue, String separator);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据字典类型和字典标签获取字典值
 | 
			
		||||
     *
 | 
			
		||||
     * @param dictType  字典类型
 | 
			
		||||
     * @param dictLabel 字典标签
 | 
			
		||||
     * @param separator 分隔符
 | 
			
		||||
     * @return 字典值
 | 
			
		||||
     */
 | 
			
		||||
    String getDictValue(String dictType, String dictLabel, String separator);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,28 @@
 | 
			
		||||
package com.ruoyi.common.core.service;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.core.domain.entity.SysUser;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 通用 用户业务
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public interface UserService {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 通过用户名查询用户
 | 
			
		||||
     *
 | 
			
		||||
     * @param userName 用户名
 | 
			
		||||
     * @return 用户对象信息
 | 
			
		||||
     */
 | 
			
		||||
    SysUser selectUserByUserName(String userName);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 通过用户ID查询用户
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     * @return 用户对象信息
 | 
			
		||||
     */
 | 
			
		||||
    SysUser selectUserById(Long userId);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,108 @@
 | 
			
		||||
package com.ruoyi.common.excel;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import com.alibaba.excel.context.AnalysisContext;
 | 
			
		||||
import com.alibaba.excel.event.AnalysisEventListener;
 | 
			
		||||
import com.alibaba.excel.exception.ExcelAnalysisException;
 | 
			
		||||
import com.alibaba.excel.exception.ExcelDataConvertException;
 | 
			
		||||
import com.alibaba.fastjson.JSON;
 | 
			
		||||
import com.ruoyi.common.utils.ValidatorUtils;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
import javax.validation.ConstraintViolation;
 | 
			
		||||
import javax.validation.ConstraintViolationException;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Excel 导入监听
 | 
			
		||||
 *
 | 
			
		||||
 * @author Yjoioooo
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Slf4j
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
public class DefaultExcelListener<T> extends AnalysisEventListener<T> implements ExcelListener<T> {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否Validator检验,默认为是
 | 
			
		||||
     */
 | 
			
		||||
    private Boolean isValidate = Boolean.TRUE;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * excel 表头数据
 | 
			
		||||
     */
 | 
			
		||||
    private Map<Integer, String> headMap;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 导入回执
 | 
			
		||||
     */
 | 
			
		||||
    private ExcelResult<T> excelResult;
 | 
			
		||||
 | 
			
		||||
    public DefaultExcelListener(boolean isValidate) {
 | 
			
		||||
        this.excelResult = new DefautExcelResult<>();
 | 
			
		||||
        this.isValidate = isValidate;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理异常
 | 
			
		||||
     *
 | 
			
		||||
     * @param exception ExcelDataConvertException
 | 
			
		||||
     * @param context   Excel 上下文
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onException(Exception exception, AnalysisContext context) throws Exception {
 | 
			
		||||
        String errMsg = null;
 | 
			
		||||
        if (exception instanceof ExcelDataConvertException) {
 | 
			
		||||
            // 如果是某一个单元格的转换异常 能获取到具体行号
 | 
			
		||||
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
 | 
			
		||||
            Integer rowIndex = excelDataConvertException.getRowIndex();
 | 
			
		||||
            Integer columnIndex = excelDataConvertException.getColumnIndex();
 | 
			
		||||
            errMsg = StrUtil.format("第{}行-第{}列-表头{}: 解析异常<br/>",
 | 
			
		||||
                rowIndex + 1, columnIndex + 1, headMap.get(columnIndex));
 | 
			
		||||
            if (log.isDebugEnabled()) {
 | 
			
		||||
                log.error(errMsg);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (exception instanceof ConstraintViolationException) {
 | 
			
		||||
            ConstraintViolationException constraintViolationException = (ConstraintViolationException) exception;
 | 
			
		||||
            Set<ConstraintViolation<?>> constraintViolations = constraintViolationException.getConstraintViolations();
 | 
			
		||||
            String constraintViolationsMsg = constraintViolations.stream()
 | 
			
		||||
                .map(ConstraintViolation::getMessage)
 | 
			
		||||
                .collect(Collectors.joining(", "));
 | 
			
		||||
            errMsg = StrUtil.format("第{}行数据校验异常: {}", context.readRowHolder().getRowIndex() + 1, constraintViolationsMsg);
 | 
			
		||||
            if (log.isDebugEnabled()) {
 | 
			
		||||
                log.error(errMsg);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        excelResult.getErrorList().add(errMsg);
 | 
			
		||||
        throw new ExcelAnalysisException(errMsg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
 | 
			
		||||
        this.headMap = headMap;
 | 
			
		||||
        log.debug("解析到一条表头数据: {}", JSON.toJSONString(headMap));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void invoke(T data, AnalysisContext context) {
 | 
			
		||||
        if (isValidate) {
 | 
			
		||||
            ValidatorUtils.validate(data);
 | 
			
		||||
        }
 | 
			
		||||
        excelResult.getList().add(data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void doAfterAllAnalysed(AnalysisContext context) {
 | 
			
		||||
        log.debug("所有数据解析完成!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ExcelResult<T> getExcelResult() {
 | 
			
		||||
        return excelResult;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,73 @@
 | 
			
		||||
package com.ruoyi.common.excel;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import lombok.Setter;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 默认excel返回对象
 | 
			
		||||
 *
 | 
			
		||||
 * @author Yjoioooo
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public class DefautExcelResult<T> implements ExcelResult<T> {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 数据对象list
 | 
			
		||||
     */
 | 
			
		||||
    @Setter
 | 
			
		||||
    private List<T> list;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 错误信息列表
 | 
			
		||||
     */
 | 
			
		||||
    @Setter
 | 
			
		||||
    private List<String> errorList;
 | 
			
		||||
 | 
			
		||||
    public DefautExcelResult() {
 | 
			
		||||
        this.list = new ArrayList<>();
 | 
			
		||||
        this.errorList = new ArrayList<>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public DefautExcelResult(List<T> list, List<String> errorList) {
 | 
			
		||||
        this.list = list;
 | 
			
		||||
        this.errorList = errorList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public DefautExcelResult(ExcelResult<T> excelResult) {
 | 
			
		||||
        this.list = excelResult.getList();
 | 
			
		||||
        this.errorList = excelResult.getErrorList();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<T> getList() {
 | 
			
		||||
        return list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<String> getErrorList() {
 | 
			
		||||
        return errorList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取导入回执
 | 
			
		||||
     *
 | 
			
		||||
     * @return 导入回执
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getAnalysis() {
 | 
			
		||||
        int successCount = list.size();
 | 
			
		||||
        int errorCount = errorList.size();
 | 
			
		||||
        if (successCount == 0) {
 | 
			
		||||
            return "读取失败,未解析到数据";
 | 
			
		||||
        } else {
 | 
			
		||||
            if (errorCount == 0) {
 | 
			
		||||
                return StrUtil.format("恭喜您,全部读取成功!共{}条", successCount);
 | 
			
		||||
            } else {
 | 
			
		||||
                return "";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,14 @@
 | 
			
		||||
package com.ruoyi.common.excel;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.excel.read.listener.ReadListener;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Excel 导入监听
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public interface ExcelListener<T> extends ReadListener<T> {
 | 
			
		||||
 | 
			
		||||
    ExcelResult<T> getExcelResult();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								ruoyi/src/main/java/com/ruoyi/common/excel/ExcelResult.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								ruoyi/src/main/java/com/ruoyi/common/excel/ExcelResult.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
package com.ruoyi.common.excel;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * excel返回对象
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public interface ExcelResult<T> {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 对象列表
 | 
			
		||||
     */
 | 
			
		||||
    List<T> getList();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 错误列表
 | 
			
		||||
     */
 | 
			
		||||
    List<String> getErrorList();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 导入回执
 | 
			
		||||
     */
 | 
			
		||||
    String getAnalysis();
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,31 @@
 | 
			
		||||
package com.ruoyi.common.utils;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.lang.tree.Tree;
 | 
			
		||||
import cn.hutool.core.lang.tree.TreeNodeConfig;
 | 
			
		||||
import cn.hutool.core.lang.tree.TreeUtil;
 | 
			
		||||
import cn.hutool.core.lang.tree.parser.NodeParser;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 扩展 hutool TreeUtil 封装系统树构建
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public class TreeBuildUtils extends TreeUtil {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据前端定制差异化字段
 | 
			
		||||
     */
 | 
			
		||||
    public static final TreeNodeConfig DEFAULT_CONFIG = TreeNodeConfig.DEFAULT_CONFIG.setNameKey("label");
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 默认树父节点id
 | 
			
		||||
     */
 | 
			
		||||
    public static final Long DEFAULT_PARENT_ID = 0L;
 | 
			
		||||
 | 
			
		||||
    public static <T> List<Tree<Long>> build(List<T> list, NodeParser<T, Long> nodeParser) {
 | 
			
		||||
        return TreeUtil.build(list, DEFAULT_PARENT_ID, DEFAULT_CONFIG, nodeParser);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,25 @@
 | 
			
		||||
package com.ruoyi.common.utils;
 | 
			
		||||
 | 
			
		||||
import javax.validation.ConstraintViolation;
 | 
			
		||||
import javax.validation.ConstraintViolationException;
 | 
			
		||||
import javax.validation.Validation;
 | 
			
		||||
import javax.validation.Validator;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Validator 校验框架工具
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public class ValidatorUtils {
 | 
			
		||||
 | 
			
		||||
	private static final Validator VALID = Validation.buildDefaultValidatorFactory().getValidator();
 | 
			
		||||
 | 
			
		||||
	public static <T> void validate(T object, Class<?>... groups) {
 | 
			
		||||
        Set<ConstraintViolation<T>> validate = VALID.validate(object, groups);
 | 
			
		||||
        if (!validate.isEmpty()) {
 | 
			
		||||
            throw new ConstraintViolationException("参数校验异常", validate);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,61 @@
 | 
			
		||||
package com.ruoyi.demo.domain.bo;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.excel.annotation.ExcelProperty;
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotBlank;
 | 
			
		||||
import javax.validation.constraints.NotNull;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 测试单表业务对象 test_demo
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 * @date 2021-07-26
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
@ApiModel("测试单表业务对象")
 | 
			
		||||
public class TestDemoImportVo {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 部门id
 | 
			
		||||
     */
 | 
			
		||||
    @ApiModelProperty("部门id")
 | 
			
		||||
    @NotNull(message = "部门id不能为空")
 | 
			
		||||
    @ExcelProperty(value = "部门id")
 | 
			
		||||
    private Long deptId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户id
 | 
			
		||||
     */
 | 
			
		||||
    @ApiModelProperty("用户id")
 | 
			
		||||
    @NotNull(message = "用户id不能为空")
 | 
			
		||||
    @ExcelProperty(value = "用户id")
 | 
			
		||||
    private Long userId;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 排序号
 | 
			
		||||
     */
 | 
			
		||||
    @ApiModelProperty("排序号")
 | 
			
		||||
    @NotNull(message = "排序号不能为空")
 | 
			
		||||
    @ExcelProperty(value = "排序号")
 | 
			
		||||
    private Long orderNum;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * key键
 | 
			
		||||
     */
 | 
			
		||||
    @ApiModelProperty("key键")
 | 
			
		||||
    @NotBlank(message = "key键不能为空")
 | 
			
		||||
    @ExcelProperty(value = "key键")
 | 
			
		||||
    private String testKey;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 值
 | 
			
		||||
     */
 | 
			
		||||
    @ApiModelProperty("值")
 | 
			
		||||
    @NotBlank(message = "值不能为空")
 | 
			
		||||
    @ExcelProperty(value = "值")
 | 
			
		||||
    private String value;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								ruoyi/src/main/java/com/ruoyi/oss/constant/OssConstant.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								ruoyi/src/main/java/com/ruoyi/oss/constant/OssConstant.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
package com.ruoyi.oss.constant;
 | 
			
		||||
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 对象存储常量
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public class OssConstant {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * OSS模块KEY
 | 
			
		||||
	 */
 | 
			
		||||
	public static final String SYS_OSS_KEY = "sys_oss:";
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 对象存储配置KEY
 | 
			
		||||
	 */
 | 
			
		||||
	public static final String OSS_CONFIG_KEY = "OssConfig";
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 缓存配置KEY
 | 
			
		||||
	 */
 | 
			
		||||
	public static final String CACHE_CONFIG_KEY = SYS_OSS_KEY + OSS_CONFIG_KEY;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 预览列表资源开关Key
 | 
			
		||||
	 */
 | 
			
		||||
	public static final String PEREVIEW_LIST_RESOURCE_KEY = "sys.oss.previewListResource";
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 系统数据ids
 | 
			
		||||
	 */
 | 
			
		||||
	public static final List<Integer> SYSTEM_DATA_IDS = Arrays.asList(1, 2, 3, 4);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										63
									
								
								ruoyi/src/main/java/com/ruoyi/oss/enumd/OssEnumd.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								ruoyi/src/main/java/com/ruoyi/oss/enumd/OssEnumd.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
package com.ruoyi.oss.enumd;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.oss.service.impl.AliyunOssStrategy;
 | 
			
		||||
import com.ruoyi.oss.service.impl.MinioOssStrategy;
 | 
			
		||||
import com.ruoyi.oss.service.impl.QcloudOssStrategy;
 | 
			
		||||
import com.ruoyi.oss.service.impl.QiniuOssStrategy;
 | 
			
		||||
import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Getter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 对象存储服务商枚举
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Getter
 | 
			
		||||
@AllArgsConstructor
 | 
			
		||||
public enum OssEnumd {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 七牛云
 | 
			
		||||
	 */
 | 
			
		||||
	QINIU("qiniu", QiniuOssStrategy.class),
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 阿里云
 | 
			
		||||
	 */
 | 
			
		||||
	ALIYUN("aliyun", AliyunOssStrategy.class),
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 腾讯云
 | 
			
		||||
	 */
 | 
			
		||||
	QCLOUD("qcloud", QcloudOssStrategy.class),
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * minio
 | 
			
		||||
	 */
 | 
			
		||||
	MINIO("minio", MinioOssStrategy.class);
 | 
			
		||||
 | 
			
		||||
	private final String value;
 | 
			
		||||
 | 
			
		||||
	private final Class<?> serviceClass;
 | 
			
		||||
 | 
			
		||||
	public static Class<?> getServiceClass(String value) {
 | 
			
		||||
		for (OssEnumd clazz : values()) {
 | 
			
		||||
			if (clazz.getValue().equals(value)) {
 | 
			
		||||
				return clazz.getServiceClass();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static String getServiceName(String value) {
 | 
			
		||||
		for (OssEnumd clazz : values()) {
 | 
			
		||||
			if (clazz.getValue().equals(value)) {
 | 
			
		||||
				return StringUtils.uncapitalize(clazz.getServiceClass().getSimpleName());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,48 @@
 | 
			
		||||
package com.ruoyi.oss.properties;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * OSS对象存储 配置属性
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
public class OssProperties {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 域名
 | 
			
		||||
	 */
 | 
			
		||||
	private String endpoint;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 前缀
 | 
			
		||||
	 */
 | 
			
		||||
	private String prefix;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * ACCESS_KEY
 | 
			
		||||
	 */
 | 
			
		||||
	private String accessKey;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * SECRET_KEY
 | 
			
		||||
	 */
 | 
			
		||||
	private String secretKey;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 存储空间名
 | 
			
		||||
	 */
 | 
			
		||||
	private String bucketName;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 存储区域
 | 
			
		||||
	 */
 | 
			
		||||
	private String region;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 是否https(Y=是,N=否)
 | 
			
		||||
	 */
 | 
			
		||||
	private String isHttps;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										64
									
								
								ruoyi/src/main/java/com/ruoyi/oss/service/IOssStrategy.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								ruoyi/src/main/java/com/ruoyi/oss/service/IOssStrategy.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
package com.ruoyi.oss.service;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.oss.entity.UploadResult;
 | 
			
		||||
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 对象存储策略
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public interface IOssStrategy {
 | 
			
		||||
 | 
			
		||||
	void createBucket();
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 获取服务商类型
 | 
			
		||||
	 */
 | 
			
		||||
	String getServiceType();
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 文件上传
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param data 文件字节数组
 | 
			
		||||
	 * @param path 文件路径,包含文件名
 | 
			
		||||
	 * @return 返回http地址
 | 
			
		||||
	 */
 | 
			
		||||
	UploadResult upload(byte[] data, String path, String contentType);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 文件删除
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param path 文件路径,包含文件名
 | 
			
		||||
	 */
 | 
			
		||||
	void delete(String path);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 文件上传
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param data   文件字节数组
 | 
			
		||||
	 * @param suffix 后缀
 | 
			
		||||
	 * @return 返回http地址
 | 
			
		||||
	 */
 | 
			
		||||
	UploadResult uploadSuffix(byte[] data, String suffix, String contentType);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 文件上传
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param inputStream 字节流
 | 
			
		||||
	 * @param path        文件路径,包含文件名
 | 
			
		||||
	 * @return 返回http地址
 | 
			
		||||
	 */
 | 
			
		||||
	UploadResult upload(InputStream inputStream, String path, String contentType);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 文件上传
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param inputStream 字节流
 | 
			
		||||
	 * @param suffix      后缀
 | 
			
		||||
	 * @return 返回http地址
 | 
			
		||||
	 */
 | 
			
		||||
	UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,60 @@
 | 
			
		||||
package com.ruoyi.oss.service.abstractd;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.io.IoUtil;
 | 
			
		||||
import cn.hutool.core.util.IdUtil;
 | 
			
		||||
import com.ruoyi.common.utils.DateUtils;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.oss.entity.UploadResult;
 | 
			
		||||
import com.ruoyi.oss.properties.OssProperties;
 | 
			
		||||
import com.ruoyi.oss.service.IOssStrategy;
 | 
			
		||||
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 对象存储策略(支持七牛、阿里云、腾讯云、minio)
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public abstract class AbstractOssStrategy implements IOssStrategy {
 | 
			
		||||
 | 
			
		||||
	protected OssProperties properties;
 | 
			
		||||
 | 
			
		||||
	public abstract void init(OssProperties properties);
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public abstract void createBucket();
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public abstract String getServiceType();
 | 
			
		||||
 | 
			
		||||
	public String getPath(String prefix, String suffix) {
 | 
			
		||||
		// 生成uuid
 | 
			
		||||
		String uuid = IdUtil.fastSimpleUUID();
 | 
			
		||||
		// 文件路径
 | 
			
		||||
		String path = DateUtils.datePath() + "/" + uuid;
 | 
			
		||||
		if (StringUtils.isNotBlank(prefix)) {
 | 
			
		||||
			path = prefix + "/" + path;
 | 
			
		||||
		}
 | 
			
		||||
		return path + suffix;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public abstract UploadResult upload(byte[] data, String path, String contentType);
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public abstract void delete(String path);
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult upload(InputStream inputStream, String path, String contentType) {
 | 
			
		||||
		byte[] data = IoUtil.readBytes(inputStream);
 | 
			
		||||
		return this.upload(data, path, contentType);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public abstract UploadResult uploadSuffix(byte[] data, String suffix, String contentType);
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public abstract UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType);
 | 
			
		||||
 | 
			
		||||
	public abstract String getEndpointLink();
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,113 @@
 | 
			
		||||
package com.ruoyi.oss.service.impl;
 | 
			
		||||
 | 
			
		||||
import com.aliyun.oss.ClientConfiguration;
 | 
			
		||||
import com.aliyun.oss.OSSClient;
 | 
			
		||||
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
 | 
			
		||||
import com.aliyun.oss.model.CannedAccessControlList;
 | 
			
		||||
import com.aliyun.oss.model.CreateBucketRequest;
 | 
			
		||||
import com.aliyun.oss.model.ObjectMetadata;
 | 
			
		||||
import com.aliyun.oss.model.PutObjectRequest;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.oss.entity.UploadResult;
 | 
			
		||||
import com.ruoyi.oss.enumd.OssEnumd;
 | 
			
		||||
import com.ruoyi.oss.exception.OssException;
 | 
			
		||||
import com.ruoyi.oss.properties.OssProperties;
 | 
			
		||||
import com.ruoyi.oss.service.abstractd.AbstractOssStrategy;
 | 
			
		||||
 | 
			
		||||
import java.io.ByteArrayInputStream;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 阿里云存储策略
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public class AliyunOssStrategy extends AbstractOssStrategy {
 | 
			
		||||
 | 
			
		||||
	private OSSClient client;
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void init(OssProperties cloudStorageProperties) {
 | 
			
		||||
		properties = cloudStorageProperties;
 | 
			
		||||
		try {
 | 
			
		||||
			ClientConfiguration configuration = new ClientConfiguration();
 | 
			
		||||
			DefaultCredentialProvider credentialProvider = new DefaultCredentialProvider(
 | 
			
		||||
				properties.getAccessKey(), properties.getSecretKey());
 | 
			
		||||
			client = new OSSClient(properties.getEndpoint(), credentialProvider, configuration);
 | 
			
		||||
			createBucket();
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("阿里云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void createBucket() {
 | 
			
		||||
		try {
 | 
			
		||||
			String bucketName = properties.getBucketName();
 | 
			
		||||
			if (client.doesBucketExist(bucketName)) {
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
 | 
			
		||||
			createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
 | 
			
		||||
			client.createBucket(createBucketRequest);
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("创建Bucket失败, 请核对阿里云配置信息:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public String getServiceType() {
 | 
			
		||||
		return OssEnumd.ALIYUN.getValue();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult upload(byte[] data, String path, String contentType) {
 | 
			
		||||
		return upload(new ByteArrayInputStream(data), path, contentType);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult upload(InputStream inputStream, String path, String contentType) {
 | 
			
		||||
		try {
 | 
			
		||||
			ObjectMetadata metadata = new ObjectMetadata();
 | 
			
		||||
			metadata.setContentType(contentType);
 | 
			
		||||
			client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata));
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
		return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void delete(String path) {
 | 
			
		||||
		path = path.replace(getEndpointLink() + "/", "");
 | 
			
		||||
		try {
 | 
			
		||||
			client.deleteObject(properties.getBucketName(), path);
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
 | 
			
		||||
		return upload(data, getPath(properties.getPrefix(), suffix), contentType);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
 | 
			
		||||
		return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public String getEndpointLink() {
 | 
			
		||||
		String endpoint = properties.getEndpoint();
 | 
			
		||||
		StringBuilder sb = new StringBuilder(endpoint);
 | 
			
		||||
		if (StringUtils.containsAnyIgnoreCase(endpoint, "http://")) {
 | 
			
		||||
			sb.insert(7, properties.getBucketName() + ".");
 | 
			
		||||
		} else if (StringUtils.containsAnyIgnoreCase(endpoint, "https://")) {
 | 
			
		||||
			sb.insert(8, properties.getBucketName() + ".");
 | 
			
		||||
		} else {
 | 
			
		||||
			throw new OssException("Endpoint配置错误");
 | 
			
		||||
		}
 | 
			
		||||
		return sb.toString();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,181 @@
 | 
			
		||||
package com.ruoyi.oss.service.impl;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.oss.entity.UploadResult;
 | 
			
		||||
import com.ruoyi.oss.enumd.OssEnumd;
 | 
			
		||||
import com.ruoyi.oss.enumd.PolicyType;
 | 
			
		||||
import com.ruoyi.oss.exception.OssException;
 | 
			
		||||
import com.ruoyi.oss.properties.OssProperties;
 | 
			
		||||
import com.ruoyi.oss.service.abstractd.AbstractOssStrategy;
 | 
			
		||||
import io.minio.*;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
 | 
			
		||||
import java.io.ByteArrayInputStream;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * minio存储策略
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public class MinioOssStrategy extends AbstractOssStrategy {
 | 
			
		||||
 | 
			
		||||
	private MinioClient minioClient;
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void init(OssProperties cloudStorageProperties) {
 | 
			
		||||
		properties = cloudStorageProperties;
 | 
			
		||||
		try {
 | 
			
		||||
			minioClient = MinioClient.builder()
 | 
			
		||||
				.endpoint(properties.getEndpoint())
 | 
			
		||||
				.credentials(properties.getAccessKey(), properties.getSecretKey())
 | 
			
		||||
				.build();
 | 
			
		||||
			createBucket();
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("Minio存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void createBucket() {
 | 
			
		||||
		try {
 | 
			
		||||
			String bucketName = properties.getBucketName();
 | 
			
		||||
			boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
 | 
			
		||||
			if (exists) {
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			// 不存在就创建桶
 | 
			
		||||
			minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
 | 
			
		||||
			minioClient.setBucketPolicy(SetBucketPolicyArgs.builder()
 | 
			
		||||
				.bucket(bucketName)
 | 
			
		||||
				.config(getPolicy(bucketName, PolicyType.READ))
 | 
			
		||||
				.build());
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("创建Bucket失败, 请核对Minio配置信息:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public String getServiceType() {
 | 
			
		||||
		return OssEnumd.MINIO.getValue();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult upload(byte[] data, String path, String contentType) {
 | 
			
		||||
		return upload(new ByteArrayInputStream(data), path, contentType);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult upload(InputStream inputStream, String path, String contentType) {
 | 
			
		||||
		try {
 | 
			
		||||
			minioClient.putObject(PutObjectArgs.builder()
 | 
			
		||||
				.bucket(properties.getBucketName())
 | 
			
		||||
				.object(path)
 | 
			
		||||
				.contentType(StringUtils.blankToDefault(contentType, MediaType.APPLICATION_OCTET_STREAM_VALUE))
 | 
			
		||||
				.stream(inputStream, inputStream.available(), -1)
 | 
			
		||||
				.build());
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("上传文件失败,请核对Minio配置信息:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
		return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void delete(String path) {
 | 
			
		||||
		path = path.replace(getEndpointLink() + "/", "");
 | 
			
		||||
		try {
 | 
			
		||||
			minioClient.removeObject(RemoveObjectArgs.builder()
 | 
			
		||||
				.bucket(properties.getBucketName())
 | 
			
		||||
				.object(path)
 | 
			
		||||
				.build());
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException(e.getMessage());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
 | 
			
		||||
		return upload(data, getPath(properties.getPrefix(), suffix), contentType);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
 | 
			
		||||
		return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public String getEndpointLink() {
 | 
			
		||||
		return properties.getEndpoint() + "/" + properties.getBucketName();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private String getPolicy(String bucketName, PolicyType policyType) {
 | 
			
		||||
		StringBuilder builder = new StringBuilder();
 | 
			
		||||
		builder.append("{\n");
 | 
			
		||||
		builder.append("    \"Statement\": [\n");
 | 
			
		||||
		builder.append("        {\n");
 | 
			
		||||
		builder.append("            \"Action\": [\n");
 | 
			
		||||
		if (policyType == PolicyType.WRITE) {
 | 
			
		||||
			builder.append("                \"s3:GetBucketLocation\",\n");
 | 
			
		||||
			builder.append("                \"s3:ListBucketMultipartUploads\"\n");
 | 
			
		||||
		} else if (policyType == PolicyType.READ_WRITE) {
 | 
			
		||||
			builder.append("                \"s3:GetBucketLocation\",\n");
 | 
			
		||||
			builder.append("                \"s3:ListBucket\",\n");
 | 
			
		||||
			builder.append("                \"s3:ListBucketMultipartUploads\"\n");
 | 
			
		||||
		} else {
 | 
			
		||||
			builder.append("                \"s3:GetBucketLocation\"\n");
 | 
			
		||||
		}
 | 
			
		||||
		builder.append("            ],\n");
 | 
			
		||||
		builder.append("            \"Effect\": \"Allow\",\n");
 | 
			
		||||
		builder.append("            \"Principal\": \"*\",\n");
 | 
			
		||||
		builder.append("            \"Resource\": \"arn:aws:s3:::");
 | 
			
		||||
		builder.append(bucketName);
 | 
			
		||||
		builder.append("\"\n");
 | 
			
		||||
		builder.append("        },\n");
 | 
			
		||||
		if (PolicyType.READ.equals(policyType)) {
 | 
			
		||||
			builder.append("        {\n");
 | 
			
		||||
			builder.append("            \"Action\": [\n");
 | 
			
		||||
			builder.append("                \"s3:ListBucket\"\n");
 | 
			
		||||
			builder.append("            ],\n");
 | 
			
		||||
			builder.append("            \"Effect\": \"Deny\",\n");
 | 
			
		||||
			builder.append("            \"Principal\": \"*\",\n");
 | 
			
		||||
			builder.append("            \"Resource\": \"arn:aws:s3:::");
 | 
			
		||||
			builder.append(bucketName);
 | 
			
		||||
			builder.append("\"\n");
 | 
			
		||||
			builder.append("        },\n");
 | 
			
		||||
		}
 | 
			
		||||
		builder.append("        {\n");
 | 
			
		||||
		builder.append("            \"Action\": ");
 | 
			
		||||
		switch (policyType) {
 | 
			
		||||
			case WRITE:
 | 
			
		||||
				builder.append("[\n");
 | 
			
		||||
				builder.append("                \"s3:AbortMultipartUpload\",\n");
 | 
			
		||||
				builder.append("                \"s3:DeleteObject\",\n");
 | 
			
		||||
				builder.append("                \"s3:ListMultipartUploadParts\",\n");
 | 
			
		||||
				builder.append("                \"s3:PutObject\"\n");
 | 
			
		||||
				builder.append("            ],\n");
 | 
			
		||||
				break;
 | 
			
		||||
			case READ_WRITE:
 | 
			
		||||
				builder.append("[\n");
 | 
			
		||||
				builder.append("                \"s3:AbortMultipartUpload\",\n");
 | 
			
		||||
				builder.append("                \"s3:DeleteObject\",\n");
 | 
			
		||||
				builder.append("                \"s3:GetObject\",\n");
 | 
			
		||||
				builder.append("                \"s3:ListMultipartUploadParts\",\n");
 | 
			
		||||
				builder.append("                \"s3:PutObject\"\n");
 | 
			
		||||
				builder.append("            ],\n");
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				builder.append("\"s3:GetObject\",\n");
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		builder.append("            \"Effect\": \"Allow\",\n");
 | 
			
		||||
		builder.append("            \"Principal\": \"*\",\n");
 | 
			
		||||
		builder.append("            \"Resource\": \"arn:aws:s3:::");
 | 
			
		||||
		builder.append(bucketName);
 | 
			
		||||
		builder.append("/*\"\n");
 | 
			
		||||
		builder.append("        }\n");
 | 
			
		||||
		builder.append("    ],\n");
 | 
			
		||||
		builder.append("    \"Version\": \"2012-10-17\"\n");
 | 
			
		||||
		builder.append("}\n");
 | 
			
		||||
		return builder.toString();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,121 @@
 | 
			
		||||
package com.ruoyi.oss.service.impl;
 | 
			
		||||
 | 
			
		||||
import com.qcloud.cos.COSClient;
 | 
			
		||||
import com.qcloud.cos.ClientConfig;
 | 
			
		||||
import com.qcloud.cos.auth.BasicCOSCredentials;
 | 
			
		||||
import com.qcloud.cos.auth.COSCredentials;
 | 
			
		||||
import com.qcloud.cos.http.HttpProtocol;
 | 
			
		||||
import com.qcloud.cos.model.*;
 | 
			
		||||
import com.qcloud.cos.region.Region;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.oss.entity.UploadResult;
 | 
			
		||||
import com.ruoyi.oss.enumd.OssEnumd;
 | 
			
		||||
import com.ruoyi.oss.exception.OssException;
 | 
			
		||||
import com.ruoyi.oss.properties.OssProperties;
 | 
			
		||||
import com.ruoyi.oss.service.abstractd.AbstractOssStrategy;
 | 
			
		||||
 | 
			
		||||
import java.io.ByteArrayInputStream;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 腾讯云存储策略
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public class QcloudOssStrategy extends AbstractOssStrategy {
 | 
			
		||||
 | 
			
		||||
	private COSClient client;
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void init(OssProperties cloudStorageProperties) {
 | 
			
		||||
		properties = cloudStorageProperties;
 | 
			
		||||
		try {
 | 
			
		||||
			COSCredentials credentials = new BasicCOSCredentials(
 | 
			
		||||
				properties.getAccessKey(), properties.getSecretKey());
 | 
			
		||||
			// 初始化客户端配置
 | 
			
		||||
			ClientConfig clientConfig = new ClientConfig();
 | 
			
		||||
			// 设置bucket所在的区域,华南:gz 华北:tj 华东:sh
 | 
			
		||||
			clientConfig.setRegion(new Region(properties.getRegion()));
 | 
			
		||||
			if ("Y".equals(properties.getIsHttps())) {
 | 
			
		||||
				clientConfig.setHttpProtocol(HttpProtocol.https);
 | 
			
		||||
			} else {
 | 
			
		||||
				clientConfig.setHttpProtocol(HttpProtocol.http);
 | 
			
		||||
			}
 | 
			
		||||
			client = new COSClient(credentials, clientConfig);
 | 
			
		||||
			createBucket();
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("腾讯云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void createBucket() {
 | 
			
		||||
		try {
 | 
			
		||||
			String bucketName = properties.getBucketName();
 | 
			
		||||
			if (client.doesBucketExist(bucketName)) {
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
 | 
			
		||||
			createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);
 | 
			
		||||
			client.createBucket(createBucketRequest);
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("创建Bucket失败, 请核对腾讯云配置信息:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public String getServiceType() {
 | 
			
		||||
		return OssEnumd.QCLOUD.getValue();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult upload(byte[] data, String path, String contentType) {
 | 
			
		||||
		return upload(new ByteArrayInputStream(data), path, contentType);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult upload(InputStream inputStream, String path, String contentType) {
 | 
			
		||||
		try {
 | 
			
		||||
			ObjectMetadata metadata = new ObjectMetadata();
 | 
			
		||||
			metadata.setContentType(contentType);
 | 
			
		||||
			client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata));
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("上传文件失败,请检查腾讯云配置信息:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
		return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void delete(String path) {
 | 
			
		||||
		path = path.replace(getEndpointLink() + "/", "");
 | 
			
		||||
		try {
 | 
			
		||||
			client.deleteObject(new DeleteObjectRequest(properties.getBucketName(), path));
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("上传文件失败,请检腾讯云查配置信息:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
 | 
			
		||||
		return upload(data, getPath(properties.getPrefix(), suffix), contentType);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
 | 
			
		||||
		return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public String getEndpointLink() {
 | 
			
		||||
		String endpoint = properties.getEndpoint();
 | 
			
		||||
		StringBuilder sb = new StringBuilder(endpoint);
 | 
			
		||||
		if (StringUtils.containsAnyIgnoreCase(endpoint, "http://")) {
 | 
			
		||||
			sb.insert(7, properties.getBucketName() + ".");
 | 
			
		||||
		} else if (StringUtils.containsAnyIgnoreCase(endpoint, "https://")) {
 | 
			
		||||
			sb.insert(8, properties.getBucketName() + ".");
 | 
			
		||||
		} else {
 | 
			
		||||
			throw new OssException("Endpoint配置错误");
 | 
			
		||||
		}
 | 
			
		||||
		return sb.toString();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,127 @@
 | 
			
		||||
package com.ruoyi.oss.service.impl;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.ArrayUtil;
 | 
			
		||||
import com.qiniu.http.Response;
 | 
			
		||||
import com.qiniu.storage.BucketManager;
 | 
			
		||||
import com.qiniu.storage.Configuration;
 | 
			
		||||
import com.qiniu.storage.Region;
 | 
			
		||||
import com.qiniu.storage.UploadManager;
 | 
			
		||||
import com.qiniu.util.Auth;
 | 
			
		||||
import com.ruoyi.oss.entity.UploadResult;
 | 
			
		||||
import com.ruoyi.oss.enumd.OssEnumd;
 | 
			
		||||
import com.ruoyi.oss.exception.OssException;
 | 
			
		||||
import com.ruoyi.oss.properties.OssProperties;
 | 
			
		||||
import com.ruoyi.oss.service.abstractd.AbstractOssStrategy;
 | 
			
		||||
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 七牛云存储策略
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
public class QiniuOssStrategy extends AbstractOssStrategy {
 | 
			
		||||
 | 
			
		||||
	private UploadManager uploadManager;
 | 
			
		||||
	private BucketManager bucketManager;
 | 
			
		||||
	private Auth auth;
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void init(OssProperties cloudStorageProperties) {
 | 
			
		||||
		properties = cloudStorageProperties;
 | 
			
		||||
		try {
 | 
			
		||||
			Configuration config = new Configuration(getRegion(properties.getRegion()));
 | 
			
		||||
			// https设置
 | 
			
		||||
			config.useHttpsDomains = false;
 | 
			
		||||
			config.useHttpsDomains = "Y".equals(properties.getIsHttps());
 | 
			
		||||
			uploadManager = new UploadManager(config);
 | 
			
		||||
			auth = Auth.create(properties.getAccessKey(), properties.getSecretKey());
 | 
			
		||||
			String bucketName = properties.getBucketName();
 | 
			
		||||
			bucketManager = new BucketManager(auth, config);
 | 
			
		||||
 | 
			
		||||
			if (!ArrayUtil.contains(bucketManager.buckets(), bucketName)) {
 | 
			
		||||
				bucketManager.createBucket(bucketName, properties.getRegion());
 | 
			
		||||
			}
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("七牛云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void createBucket() {
 | 
			
		||||
		try {
 | 
			
		||||
			String bucketName = properties.getBucketName();
 | 
			
		||||
			if (ArrayUtil.contains(bucketManager.buckets(), bucketName)) {
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			bucketManager.createBucket(bucketName, properties.getRegion());
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("创建Bucket失败, 请核对七牛云配置信息:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public String getServiceType() {
 | 
			
		||||
		return OssEnumd.QINIU.getValue();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult upload(byte[] data, String path, String contentType) {
 | 
			
		||||
		try {
 | 
			
		||||
            String token = auth.uploadToken(properties.getBucketName());
 | 
			
		||||
            Response res = uploadManager.put(data, path, token, null, contentType, false);
 | 
			
		||||
			if (!res.isOK()) {
 | 
			
		||||
				throw new RuntimeException("上传七牛出错:" + res.error);
 | 
			
		||||
			}
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException("上传文件失败,请核对七牛配置信息:[" + e.getMessage() + "]");
 | 
			
		||||
		}
 | 
			
		||||
		return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void delete(String path) {
 | 
			
		||||
		try {
 | 
			
		||||
			path = path.replace(getEndpointLink() + "/", "");
 | 
			
		||||
			Response res = bucketManager.delete(properties.getBucketName(), path);
 | 
			
		||||
			if (!res.isOK()) {
 | 
			
		||||
				throw new RuntimeException("删除七牛文件出错:" + res.error);
 | 
			
		||||
			}
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			throw new OssException(e.getMessage());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
 | 
			
		||||
		return upload(data, getPath(properties.getPrefix(), suffix), contentType);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
 | 
			
		||||
		return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public String getEndpointLink() {
 | 
			
		||||
		return properties.getEndpoint();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private Region getRegion(String region) {
 | 
			
		||||
		switch (region) {
 | 
			
		||||
			case "z0":
 | 
			
		||||
				return Region.region0();
 | 
			
		||||
			case "z1":
 | 
			
		||||
				return Region.region1();
 | 
			
		||||
			case "z2":
 | 
			
		||||
				return Region.region2();
 | 
			
		||||
			case "na0":
 | 
			
		||||
				return Region.regionNa0();
 | 
			
		||||
			case "as0":
 | 
			
		||||
				return Region.regionAs0();
 | 
			
		||||
			default:
 | 
			
		||||
				return Region.autoRegion();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,109 @@
 | 
			
		||||
package com.ruoyi.system.listener;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.bean.BeanUtil;
 | 
			
		||||
import com.alibaba.excel.context.AnalysisContext;
 | 
			
		||||
import com.alibaba.excel.event.AnalysisEventListener;
 | 
			
		||||
import com.ruoyi.common.core.domain.entity.SysUser;
 | 
			
		||||
import com.ruoyi.common.excel.ExcelListener;
 | 
			
		||||
import com.ruoyi.common.excel.ExcelResult;
 | 
			
		||||
import com.ruoyi.common.exception.ServiceException;
 | 
			
		||||
import com.ruoyi.common.utils.SecurityUtils;
 | 
			
		||||
import com.ruoyi.common.utils.StringUtils;
 | 
			
		||||
import com.ruoyi.common.utils.spring.SpringUtils;
 | 
			
		||||
import com.ruoyi.system.domain.vo.SysUserImportVo;
 | 
			
		||||
import com.ruoyi.system.service.ISysConfigService;
 | 
			
		||||
import com.ruoyi.system.service.ISysUserService;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 系统用户自定义导入
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class SysUserImportListener extends AnalysisEventListener<SysUserImportVo> implements ExcelListener<SysUserImportVo> {
 | 
			
		||||
 | 
			
		||||
    private final ISysUserService userService;
 | 
			
		||||
 | 
			
		||||
    private final String password;
 | 
			
		||||
 | 
			
		||||
    private final Boolean isUpdateSupport;
 | 
			
		||||
 | 
			
		||||
    private final String operName;
 | 
			
		||||
 | 
			
		||||
    private int successNum = 0;
 | 
			
		||||
    private int failureNum = 0;
 | 
			
		||||
    private final StringBuilder successMsg = new StringBuilder();
 | 
			
		||||
    private final StringBuilder failureMsg = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
    public SysUserImportListener(Boolean isUpdateSupport) {
 | 
			
		||||
        this.userService = SpringUtils.getBean(ISysUserService.class);
 | 
			
		||||
        this.password = SpringUtils.getBean(ISysConfigService.class)
 | 
			
		||||
            .selectConfigByKey("sys.user.initPassword");
 | 
			
		||||
        this.isUpdateSupport = isUpdateSupport;
 | 
			
		||||
        this.operName = SecurityUtils.getUsername();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void invoke(SysUserImportVo userVo, AnalysisContext context) {
 | 
			
		||||
        SysUser user = this.userService.selectUserByUserName(userVo.getUserName());
 | 
			
		||||
        try {
 | 
			
		||||
            // 验证是否存在这个用户
 | 
			
		||||
            if (StringUtils.isNull(user)) {
 | 
			
		||||
                user = BeanUtil.toBean(userVo, SysUser.class);
 | 
			
		||||
                user.setPassword(SecurityUtils.encryptPassword(password));
 | 
			
		||||
                user.setCreateBy(operName);
 | 
			
		||||
                userService.insertUser(user);
 | 
			
		||||
                successNum++;
 | 
			
		||||
                successMsg.append("<br/>").append(successNum).append("、账号 ").append(user.getUserName()).append(" 导入成功");
 | 
			
		||||
            } else if (isUpdateSupport) {
 | 
			
		||||
                user.setUpdateBy(operName);
 | 
			
		||||
                userService.updateUser(user);
 | 
			
		||||
                successNum++;
 | 
			
		||||
                successMsg.append("<br/>").append(successNum).append("、账号 ").append(user.getUserName()).append(" 更新成功");
 | 
			
		||||
            } else {
 | 
			
		||||
                failureNum++;
 | 
			
		||||
                failureMsg.append("<br/>").append(failureNum).append("、账号 ").append(user.getUserName()).append(" 已存在");
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            failureNum++;
 | 
			
		||||
            String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败:";
 | 
			
		||||
            failureMsg.append(msg).append(e.getMessage());
 | 
			
		||||
            log.error(msg, e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void doAfterAllAnalysed(AnalysisContext context) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ExcelResult<SysUserImportVo> getExcelResult() {
 | 
			
		||||
        return new ExcelResult<SysUserImportVo>() {
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public String getAnalysis() {
 | 
			
		||||
                if (failureNum > 0) {
 | 
			
		||||
                    failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
 | 
			
		||||
                    throw new ServiceException(failureMsg.toString());
 | 
			
		||||
                } else {
 | 
			
		||||
                    successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
 | 
			
		||||
                }
 | 
			
		||||
                return successMsg.toString();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public List<SysUserImportVo> getList() {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public List<String> getErrorList() {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,42 @@
 | 
			
		||||
package com.ruoyi.system.runner;
 | 
			
		||||
 | 
			
		||||
import com.ruoyi.common.config.RuoYiConfig;
 | 
			
		||||
import com.ruoyi.system.service.ISysConfigService;
 | 
			
		||||
import com.ruoyi.system.service.ISysDictTypeService;
 | 
			
		||||
import com.ruoyi.system.service.ISysOssConfigService;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.boot.ApplicationArguments;
 | 
			
		||||
import org.springframework.boot.ApplicationRunner;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 初始化 system 模块对应业务数据
 | 
			
		||||
 *
 | 
			
		||||
 * @author Lion Li
 | 
			
		||||
 */
 | 
			
		||||
@Slf4j
 | 
			
		||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
 | 
			
		||||
@Component
 | 
			
		||||
public class SystemApplicationRunner implements ApplicationRunner {
 | 
			
		||||
 | 
			
		||||
    private final RuoYiConfig ruoyiConfig;
 | 
			
		||||
    private final ISysConfigService configService;
 | 
			
		||||
    private final ISysDictTypeService dictTypeService;
 | 
			
		||||
    private final ISysOssConfigService ossConfigService;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void run(ApplicationArguments args) throws Exception {
 | 
			
		||||
        ossConfigService.init();
 | 
			
		||||
        log.info("初始化OSS配置成功");
 | 
			
		||||
        if (ruoyiConfig.isCacheLazy()){
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        configService.loadingConfigCache();
 | 
			
		||||
        log.info("加载参数缓存数据成功");
 | 
			
		||||
        dictTypeService.loadingDictCache();
 | 
			
		||||
        log.info("加载字典缓存数据成功");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -180,7 +180,6 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser,
 | 
			
		||||
    public String checkPhoneUnique(SysUser user) {
 | 
			
		||||
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
 | 
			
		||||
        long count = count(new LambdaQueryWrapper<SysUser>()
 | 
			
		||||
                .select(SysUser::getUserId, SysUser::getPhonenumber)
 | 
			
		||||
                .eq(SysUser::getPhonenumber, user.getPhonenumber())
 | 
			
		||||
                .ne(SysUser::getUserId, userId));
 | 
			
		||||
        if (count > 0) {
 | 
			
		||||
@@ -199,7 +198,6 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser,
 | 
			
		||||
    public String checkEmailUnique(SysUser user) {
 | 
			
		||||
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
 | 
			
		||||
        long count = count(new LambdaQueryWrapper<SysUser>()
 | 
			
		||||
                .select(SysUser::getUserId, SysUser::getEmail)
 | 
			
		||||
                .eq(SysUser::getEmail, user.getEmail())
 | 
			
		||||
                .ne(SysUser::getUserId, userId));
 | 
			
		||||
        if (count > 0) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								ruoyi/src/main/resources/mapper/package-info.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								ruoyi/src/main/resources/mapper/package-info.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
java包使用 `.` 分割 resource 目录使用 `/` 分割
 | 
			
		||||
<br>
 | 
			
		||||
此文件目的 防止文件夹粘连找不到 `xml` 文件
 | 
			
		||||
@@ -644,10 +644,10 @@ create table gen_table_column (
 | 
			
		||||
drop table if exists sys_oss;
 | 
			
		||||
create table sys_oss (
 | 
			
		||||
  oss_id          bigint(20)   not null auto_increment    comment '对象存储主键',
 | 
			
		||||
  file_name       varchar(64)  not null default ''        comment '文件名',
 | 
			
		||||
  original_name   varchar(64)  not null default ''        comment '原名',
 | 
			
		||||
  file_name       varchar(255) not null default ''        comment '文件名',
 | 
			
		||||
  original_name   varchar(255) not null default ''        comment '原名',
 | 
			
		||||
  file_suffix     varchar(10)  not null default ''        comment '文件后缀名',
 | 
			
		||||
  url              varchar(200) not null                   comment 'URL地址',
 | 
			
		||||
  url              varchar(500) not null                   comment 'URL地址',
 | 
			
		||||
  create_time     datetime              default null      comment '创建时间',
 | 
			
		||||
  create_by       varchar(64)           default ''        comment '上传人',
 | 
			
		||||
  update_time     datetime              default null      comment '更新时间',
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user