mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-03-25 18:43:46 +08:00
2.0版本
This commit is contained in:
21
ruoyi-admin/src/main/java/org/ruoyi/RuoYiApplication.java
Normal file
21
ruoyi-admin/src/main/java/org/ruoyi/RuoYiApplication.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package org.ruoyi;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
|
||||
|
||||
/**
|
||||
* 启动程序
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class RuoYiApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication application = new SpringApplication(RuoYiApplication.class);
|
||||
application.setApplicationStartup(new BufferingApplicationStartup(2048));
|
||||
application.run(args);
|
||||
System.out.println("(♥◠‿◠)ノ゙ RuoYiAi启动成功 ლ(´ڡ`ლ)゙");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.ruoyi;
|
||||
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
|
||||
/**
|
||||
* web容器中进行部署
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class RuoYiServletInitializer extends SpringBootServletInitializer {
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(RuoYiApplication.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package org.ruoyi.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import org.ruoyi.common.core.constant.Constants;
|
||||
import org.ruoyi.common.core.domain.R;
|
||||
import org.ruoyi.common.core.domain.model.EmailLoginBody;
|
||||
import org.ruoyi.common.core.domain.model.LoginBody;
|
||||
import org.ruoyi.common.core.domain.model.RegisterBody;
|
||||
import org.ruoyi.common.core.domain.model.SmsLoginBody;
|
||||
import org.ruoyi.common.core.domain.model.VisitorLoginBody;
|
||||
import org.ruoyi.common.core.utils.MapstructUtils;
|
||||
import org.ruoyi.common.core.utils.StreamUtils;
|
||||
import org.ruoyi.common.core.utils.StringUtils;
|
||||
import org.ruoyi.common.satoken.utils.LoginHelper;
|
||||
import org.ruoyi.common.tenant.helper.TenantHelper;
|
||||
import org.ruoyi.system.domain.bo.SysTenantBo;
|
||||
import org.ruoyi.system.domain.vo.LoginTenantVo;
|
||||
import org.ruoyi.system.domain.vo.SysTenantVo;
|
||||
import org.ruoyi.system.domain.vo.TenantListVo;
|
||||
import org.ruoyi.system.service.ISysTenantService;
|
||||
|
||||
import org.ruoyi.system.service.SysLoginService;
|
||||
import org.ruoyi.system.service.SysRegisterService;
|
||||
import org.ruoyi.system.domain.vo.LoginVo;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 认证
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SaIgnore
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
public class AuthController {
|
||||
|
||||
private final SysLoginService loginService;
|
||||
private final SysRegisterService registerService;
|
||||
private final ISysTenantService tenantService;
|
||||
|
||||
/**
|
||||
* 登录方法
|
||||
*
|
||||
* @param body 登录信息
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping("/login")
|
||||
public R<LoginVo> login(@Validated @RequestBody LoginBody body) {
|
||||
body.setTenantId(Constants.TENANT_ID);
|
||||
LoginVo loginVo = new LoginVo();
|
||||
// 生成令牌
|
||||
String token = loginService.login(
|
||||
body.getTenantId(),
|
||||
body.getUsername(), body.getPassword(),
|
||||
body.getCode(), body.getUuid());
|
||||
loginVo.setToken(token);
|
||||
loginVo.setUserInfo(LoginHelper.getLoginUser());
|
||||
return R.ok(loginVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信登录
|
||||
*
|
||||
* @param body 登录信息
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping("/smsLogin")
|
||||
public R<LoginVo> smsLogin(@Validated @RequestBody SmsLoginBody body) {
|
||||
LoginVo loginVo = new LoginVo();
|
||||
// 生成令牌
|
||||
String token = loginService.smsLogin(body.getTenantId(), body.getPhonenumber(), body.getSmsCode());
|
||||
loginVo.setToken(token);
|
||||
return R.ok(loginVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 访客登录
|
||||
* @param loginBody 登录信息
|
||||
* @return token信息
|
||||
*/
|
||||
@PostMapping("/visitorLogin")
|
||||
public R<LoginVo> visitorLogin(@RequestBody VisitorLoginBody loginBody) {
|
||||
LoginVo loginVo = new LoginVo();
|
||||
return R.ok(loginVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮件登录
|
||||
*
|
||||
* @param body 登录信息
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping("/emailLogin")
|
||||
public R<LoginVo> emailLogin(@Validated @RequestBody EmailLoginBody body) {
|
||||
LoginVo loginVo = new LoginVo();
|
||||
// 生成令牌
|
||||
String token = loginService.emailLogin(body.getTenantId(), body.getEmail(), body.getEmailCode());
|
||||
loginVo.setToken(token);
|
||||
return R.ok(loginVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
@PostMapping("/logout")
|
||||
public R<Void> logout() {
|
||||
loginService.logout();
|
||||
return R.ok("退出成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
*/
|
||||
@PostMapping("/register")
|
||||
public R<Void> register(@Validated @RequestBody RegisterBody user, HttpServletRequest request) {
|
||||
String domainName = request.getServerName();
|
||||
user.setDomainName(domainName);
|
||||
registerService.register(user);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置密码
|
||||
*/
|
||||
@PostMapping("/reset/password")
|
||||
@SaIgnore
|
||||
public R<Void> resetPassWord(@Validated @RequestBody RegisterBody user) {
|
||||
registerService.resetPassWord(user);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录页面租户下拉框
|
||||
*
|
||||
* @return 租户列表
|
||||
*/
|
||||
@GetMapping("/tenant/list")
|
||||
public R<LoginTenantVo> tenantList(HttpServletRequest request) throws Exception {
|
||||
List<SysTenantVo> tenantList = tenantService.queryList(new SysTenantBo());
|
||||
List<TenantListVo> voList = MapstructUtils.convert(tenantList, TenantListVo.class);
|
||||
// 获取域名
|
||||
String host = new URL(request.getRequestURL().toString()).getHost();
|
||||
// 根据域名进行筛选
|
||||
List<TenantListVo> list = StreamUtils.filter(voList, vo -> StringUtils.equals(vo.getDomain(), host));
|
||||
// 返回对象
|
||||
LoginTenantVo vo = new LoginTenantVo();
|
||||
vo.setVoList(CollUtil.isNotEmpty(list) ? list : voList);
|
||||
vo.setTenantEnabled(TenantHelper.isEnable());
|
||||
return R.ok(vo);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package org.ruoyi.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.hutool.captcha.AbstractCaptcha;
|
||||
import cn.hutool.captcha.generator.CodeGenerator;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import org.ruoyi.common.core.constant.Constants;
|
||||
import org.ruoyi.common.core.constant.GlobalConstants;
|
||||
import org.ruoyi.common.core.domain.R;
|
||||
import org.ruoyi.common.core.exception.ServiceException;
|
||||
import org.ruoyi.common.core.service.ConfigService;
|
||||
import org.ruoyi.common.core.utils.SpringUtils;
|
||||
import org.ruoyi.common.core.utils.StringUtils;
|
||||
import org.ruoyi.common.core.utils.reflect.ReflectUtils;
|
||||
import org.ruoyi.common.mail.utils.MailUtils;
|
||||
import org.ruoyi.common.redis.utils.RedisUtils;
|
||||
import org.ruoyi.common.sms.config.properties.SmsProperties;
|
||||
import org.ruoyi.common.sms.core.SmsTemplate;
|
||||
import org.ruoyi.common.sms.entity.SmsResult;
|
||||
import org.ruoyi.common.web.config.properties.CaptchaProperties;
|
||||
import org.ruoyi.common.web.enums.CaptchaType;
|
||||
import org.ruoyi.system.domain.request.EmailRequest;
|
||||
import org.ruoyi.system.domain.vo.CaptchaVo;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 验证码操作处理
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SaIgnore
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
public class CaptchaController {
|
||||
|
||||
private final CaptchaProperties captchaProperties;
|
||||
private final SmsProperties smsProperties;
|
||||
private final ConfigService configService;
|
||||
|
||||
/**
|
||||
* 短信验证码
|
||||
*
|
||||
* @param phonenumber 用户手机号
|
||||
*/
|
||||
@GetMapping("/resource/sms/code")
|
||||
public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) {
|
||||
if (!smsProperties.getEnabled()) {
|
||||
return R.fail("当前系统没有开启短信功能!");
|
||||
}
|
||||
String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber;
|
||||
String code = RandomUtil.randomNumbers(4);
|
||||
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||
// 验证码模板id 自行处理 (查数据库或写死均可)
|
||||
String templateId = "";
|
||||
Map<String, String> map = new HashMap<>(1);
|
||||
map.put("code", code);
|
||||
SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
|
||||
SmsResult result = smsTemplate.send(phonenumber, templateId, map);
|
||||
if (!result.isSuccess()) {
|
||||
log.error("验证码短信发送异常 => {}", result);
|
||||
return R.fail(result.getMessage());
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮箱验证码
|
||||
*
|
||||
* @param emailRequest 用户邮箱
|
||||
*/
|
||||
@PostMapping("/resource/email/code")
|
||||
public R<Void> emailCode(@RequestBody @Valid EmailRequest emailRequest) {
|
||||
String key = GlobalConstants.CAPTCHA_CODE_KEY + emailRequest.getUsername();
|
||||
String code = RandomUtil.randomNumbers(4);
|
||||
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||
// 检验邮箱后缀
|
||||
String suffix = configService.getConfigValue("mail", "suffix");
|
||||
String prompt = configService.getConfigValue("mail", "prompt");
|
||||
if(StringUtils.isNotEmpty(suffix)){
|
||||
// 动态的域名列表
|
||||
String[] invalidDomains = suffix.split(",");
|
||||
for (String domain : invalidDomains) {
|
||||
if (emailRequest.getUsername().endsWith(domain)) {
|
||||
throw new ServiceException(prompt);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 自定义邮箱模板
|
||||
String model = configService.getConfigValue("mail", "mailModel");
|
||||
String mailTitle = configService.getConfigValue("mail", "mailTitle");
|
||||
String replacedModel = model.replace("{code}", code);
|
||||
try {
|
||||
MailUtils.sendHtml(emailRequest.getUsername(), mailTitle, replacedModel);
|
||||
} catch (Exception e) {
|
||||
log.error("邮箱验证码发送异常 => {}", e.getMessage());
|
||||
return R.fail(e.getMessage());
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成验证码
|
||||
*/
|
||||
@GetMapping("/auth/code")
|
||||
public R<CaptchaVo> getCode() {
|
||||
CaptchaVo captchaVo = new CaptchaVo();
|
||||
boolean captchaEnabled = captchaProperties.getEnable();
|
||||
if (!captchaEnabled) {
|
||||
captchaVo.setCaptchaEnabled(false);
|
||||
return R.ok(captchaVo);
|
||||
}
|
||||
// 保存验证码信息
|
||||
String uuid = IdUtil.simpleUUID();
|
||||
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + uuid;
|
||||
// 生成验证码
|
||||
CaptchaType captchaType = captchaProperties.getType();
|
||||
boolean isMath = CaptchaType.MATH == captchaType;
|
||||
Integer length = isMath ? captchaProperties.getNumberLength() : captchaProperties.getCharLength();
|
||||
CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), length);
|
||||
AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
|
||||
captcha.setGenerator(codeGenerator);
|
||||
captcha.createCode();
|
||||
String code = captcha.getCode();
|
||||
if (isMath) {
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
Expression exp = parser.parseExpression(StringUtils.remove(code, "="));
|
||||
code = exp.getValue(String.class);
|
||||
}
|
||||
RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||
captchaVo.setUuid(uuid);
|
||||
captchaVo.setImg(captcha.getImageBase64());
|
||||
return R.ok(captchaVo);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.ruoyi.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
/**
|
||||
* 首页
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SaIgnore
|
||||
@RequiredArgsConstructor
|
||||
@Controller
|
||||
public class IndexController {
|
||||
|
||||
/**
|
||||
* 访问首页,提示语
|
||||
*/
|
||||
@GetMapping("/")
|
||||
public String index() {
|
||||
return "index.html";
|
||||
}
|
||||
|
||||
@GetMapping("/success")
|
||||
public String success(){
|
||||
return "paySuccess.html";
|
||||
}
|
||||
|
||||
@GetMapping("/cancel")
|
||||
public String cancel(){
|
||||
return "cancel";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -47,41 +47,9 @@ spring:
|
||||
master:
|
||||
type: ${spring.datasource.type}
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
|
||||
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
||||
url: ${DB_URL}
|
||||
username: ${DB_USERNAME}
|
||||
password: ${DB_PASSWORD}
|
||||
|
||||
|
||||
# 从库数据源
|
||||
# slave:
|
||||
# lazy: true
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
# username:
|
||||
# password:
|
||||
# oracle:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: oracle.jdbc.OracleDriver
|
||||
# url: jdbc:oracle:thin:@//localhost:1521/XE
|
||||
# username: ROOT
|
||||
# password: root
|
||||
# hikari:
|
||||
# connectionTestQuery: SELECT 1 FROM DUAL
|
||||
# postgres:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: org.postgresql.Driver
|
||||
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
|
||||
# username: root
|
||||
# password: root
|
||||
# sqlserver:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
|
||||
# username: SA
|
||||
# password: root
|
||||
url: jdbc:mysql://43.139.70.230:3306/ruoyi-ai?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
username: ruoyi-ai
|
||||
password: TZ7yaGtSRWeeBaBJ
|
||||
hikari:
|
||||
# 最大连接池数量
|
||||
maxPoolSize: 20
|
||||
@@ -104,15 +72,15 @@ spring:
|
||||
spring.data:
|
||||
redis:
|
||||
# 地址
|
||||
host: ${REDIS_HOST}
|
||||
host: 127.0.0.1
|
||||
# 端口,默认为6379
|
||||
port: ${REDIS_PORT}
|
||||
port: 6379
|
||||
# 数据库索引
|
||||
database: 0
|
||||
# 密码(如没有密码请注释掉)
|
||||
# password:
|
||||
#password:
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
timeout: 10S
|
||||
# 是否开启ssl
|
||||
ssl: false
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
|
||||
# 项目相关配置
|
||||
ruoyi:
|
||||
# 名称
|
||||
name: "xmzs"
|
||||
name: "ruoyi"
|
||||
# 版本
|
||||
version: ${revision}
|
||||
# 版权年份
|
||||
@@ -48,7 +49,7 @@ server:
|
||||
# 日志配置
|
||||
logging:
|
||||
level:
|
||||
com.xmzs: '@logging.level@'
|
||||
org.ruoyi: @logging.level@
|
||||
org.springframework: warn
|
||||
config: classpath:logback-plus.xml
|
||||
|
||||
@@ -69,14 +70,14 @@ spring:
|
||||
# 国际化资源文件路径
|
||||
basename: i18n/messages
|
||||
profiles:
|
||||
active: '@profiles.active@'
|
||||
active: @profiles.active@
|
||||
# 文件上传
|
||||
servlet:
|
||||
multipart:
|
||||
# 单个文件大小
|
||||
max-file-size: 10MB
|
||||
max-file-size: 50MB
|
||||
# 设置总上传的文件大小
|
||||
max-request-size: 20MB
|
||||
max-request-size: 200MB
|
||||
mvc:
|
||||
format:
|
||||
date-time: yyyy-MM-dd HH:mm:ss
|
||||
@@ -117,8 +118,7 @@ sa-token:
|
||||
security:
|
||||
# 排除路径
|
||||
excludes:
|
||||
# 修改用户头像
|
||||
- /system/user/edit/avatar
|
||||
# 支付回调
|
||||
- /pay/returnUrl
|
||||
- /pay/notifyUrl
|
||||
# 上传文件
|
||||
@@ -160,11 +160,11 @@ tenant:
|
||||
mybatis-plus:
|
||||
# 不支持多包, 如有需要可在注解配置 或 提升扫包等级
|
||||
# 例如 com.**.**.mapper
|
||||
mapperPackage: com.xmzs.**.mapper
|
||||
mapperPackage: org.ruoyi.**.mapper
|
||||
# 对应的 XML 文件位置
|
||||
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||
# 实体扫描,多个package用逗号或者分号分隔
|
||||
typeAliasesPackage: com.xmzs.**.domain
|
||||
typeAliasesPackage: org.ruoyi.**.domain
|
||||
# 启动时是否检查 MyBatis XML 文件的存在,默认不检查
|
||||
checkConfigLocation: false
|
||||
configuration:
|
||||
@@ -245,13 +245,13 @@ springdoc:
|
||||
#这里定义了两个分组,可定义多个,也可以不定义
|
||||
group-configs:
|
||||
- group: 1.演示模块
|
||||
packages-to-scan: com.xmzs.demo
|
||||
packages-to-scan: org.ruoyi.demo
|
||||
- group: 2.通用模块
|
||||
packages-to-scan: com.xmzs.web
|
||||
packages-to-scan: org.ruoyi.web
|
||||
- group: 3.系统模块
|
||||
packages-to-scan: com.xmzs.system
|
||||
packages-to-scan: org.ruoyi.system
|
||||
- group: 4.代码生成模块
|
||||
packages-to-scan: com.xmzs.generator
|
||||
packages-to-scan: org.ruoyi.generator
|
||||
|
||||
# 防止XSS攻击
|
||||
xss:
|
||||
@@ -290,9 +290,9 @@ management:
|
||||
logfile:
|
||||
external-file: ./logs/sys-console.log
|
||||
|
||||
--- # websocket
|
||||
# websocket
|
||||
websocket:
|
||||
enabled: false
|
||||
enabled: true
|
||||
# 路径
|
||||
path: ''
|
||||
# 设置访问源地址
|
||||
@@ -307,83 +307,72 @@ wx:
|
||||
token: #微信小程序消息服务器配置的token
|
||||
aesKey: #微信小程序消息服务器配置的EncodingAESKey
|
||||
msgDataFormat: JSON
|
||||
baidu:
|
||||
# 是否开启文本审核
|
||||
enabled: false
|
||||
# 文本审核
|
||||
textReview:
|
||||
apiKey: '' # apiKey
|
||||
secretKey: '' # secretKey
|
||||
appKey: xxxxxxxxxxxxxxxxx
|
||||
secretKey: xxxxxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
wechat:
|
||||
# 是否使用微信 true/false
|
||||
enable: true
|
||||
# 生成的登录二维码路径 默认与项目同级
|
||||
qrPath: "./"
|
||||
# 知识库配置
|
||||
chain:
|
||||
split:
|
||||
chunk:
|
||||
endspliter: "<STOP>"
|
||||
# 分块文本大小
|
||||
size: 500
|
||||
overlay: 0
|
||||
qaspliter: "######"
|
||||
# 知识库中检索的条数
|
||||
limits: 5
|
||||
vectorization:
|
||||
type: openai
|
||||
openai:
|
||||
model: 'text-embedding-3-small'
|
||||
baidu:
|
||||
model: bge-large-zh
|
||||
zhipu:
|
||||
model: embedding-2
|
||||
# 智普API KEY
|
||||
token: xx
|
||||
vector:
|
||||
store:
|
||||
type: weaviate
|
||||
weaviate:
|
||||
protocol: http
|
||||
host: 127.0.0.1:6038
|
||||
classname: LocalKnowledge
|
||||
milvus:
|
||||
host: 127.0.0.1
|
||||
port: 19530
|
||||
dimension: 1536
|
||||
collection: LocalKnowledge
|
||||
llm:
|
||||
openai:
|
||||
token: sk-xx
|
||||
model: gpt-4-1106-preview
|
||||
chatglm:
|
||||
baseurl: http://127.0.0.1:8000/
|
||||
model: chatglm2-6b
|
||||
baidu:
|
||||
appKey: xx
|
||||
secretKey: xx
|
||||
model: ernie_bot
|
||||
zhipu:
|
||||
model: glm-4
|
||||
audio:
|
||||
type: openai
|
||||
text:
|
||||
type: openai
|
||||
function:
|
||||
type: baidu
|
||||
vision:
|
||||
type: openai
|
||||
image:
|
||||
type: openai
|
||||
|
||||
keyword:
|
||||
# 重置会话指令
|
||||
reset: "重置会话"
|
||||
# ai画图指令(DALL·E模型 https://platform.openai.com/docs/models/dall-e)
|
||||
# generation 根据关键词生成图片(https://platform.openai.com/docs/guides/images/generations)
|
||||
image: "ai画图"
|
||||
# ai语音指令(TTS模型 https://platform.openai.com/docs/api-reference/audio)
|
||||
audio: "ai语音"
|
||||
upload:
|
||||
path: /data/upload
|
||||
|
||||
#绘画价格配置(元)
|
||||
mj:
|
||||
# 放大
|
||||
upsample: 0.1
|
||||
# 变化
|
||||
change: 0.3
|
||||
# 图生图
|
||||
blend: 0.3
|
||||
# 图生文
|
||||
describe: 0.1
|
||||
# 文生图
|
||||
imagine: 0.3
|
||||
# 局部重绘
|
||||
inpaint: 0.3
|
||||
# 提示词分析
|
||||
shorten: 0.1
|
||||
# 换脸
|
||||
faceSwapping: 0.3
|
||||
proxy:
|
||||
socket:
|
||||
host: 127.0.0.1
|
||||
port: 7890
|
||||
|
||||
--- # mail 邮件发送
|
||||
mail:
|
||||
enabled: true
|
||||
host: smtp.163.com
|
||||
port: 465
|
||||
# 是否需要用户名密码验证
|
||||
auth: true
|
||||
# 发送方,遵循RFC-822标准
|
||||
from: ageerle@163.com
|
||||
# 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
|
||||
user: ageerle@163.com
|
||||
# 密码(填写授权码)
|
||||
pass: ${MAIL_PASS}
|
||||
# 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
|
||||
starttlsEnable: true
|
||||
# 使用SSL安全连接
|
||||
sslEnable: true
|
||||
# SMTP超时时长,单位毫秒,缺省值不超时
|
||||
timeout: 0
|
||||
# Socket连接超时值,单位毫秒,缺省值不超时
|
||||
connectionTimeout: 0
|
||||
resource:
|
||||
domain: http://127.0.0.1:${server.port}/resources
|
||||
|
||||
# chatgpt和mj共用一个key
|
||||
chat:
|
||||
apiKey: ${CHAT_API_KEY}
|
||||
apiHost: ${CHAT_API_HOST}
|
||||
# 支付配置信息
|
||||
pay:
|
||||
pid: ${PAY_PID}
|
||||
key: ${PAY_KEY}
|
||||
payUrl: 'https://pay.pandarobot.chat/mapi.php'
|
||||
notify_url: 'https://www.pandarobot.chat/pay/returnUrl'
|
||||
return_url: 'https://www.pandarobot.chat/pay/notifyUrl'
|
||||
type: 'wxpay'
|
||||
device: 'pc'
|
||||
sign_type: 'MD5'
|
||||
|
||||
@@ -1,9 +1,2 @@
|
||||
Application Version: ${revision}
|
||||
Spring Boot Version: ${spring-boot.version}
|
||||
██ ██ ██ ██
|
||||
██████ ░██ ░██ ░██ █████ ██████ ░██
|
||||
░██░░░██ ██████ ███████ ░██ ██████ █████ ░██ ██████ ██████ ██░░░██░██░░░██ ██████
|
||||
░██ ░██ ░░░░░░██ ░░██░░░██ ██████ ░░░░░░██ █████ ██░░░██░██████ ░░░░░░██ ░░░██░ ░██ ░██░██ ░██░░░██░
|
||||
░██████ ███████ ░██ ░██ ██░░░██ ███████ ░░░░░ ░██ ░░ ░██░░░██ ███████ ░██ ░░██████░██████ ░██
|
||||
░██░░░ ██░░░░██ ░██ ░██░██ ░██ ██░░░░██ ░██ ██░██ ░██ ██░░░░██ ░██ ░░░░░██░██░░░ ░██
|
||||
░██ ░░████████ ███ ░██░░██████░░████████ ░░█████ ░██ ░██░░████████ ░░██ █████ ░██ ░░██
|
||||
|
||||
46
ruoyi-admin/src/main/resources/static/.gitignore
vendored
Normal file
46
ruoyi-admin/src/main/resources/static/.gitignore
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
######################################################################
|
||||
# Build Tools
|
||||
|
||||
.gradle
|
||||
/build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
######################################################################
|
||||
# IDE
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### JRebel ###
|
||||
rebel.xml
|
||||
|
||||
### NetBeans ###
|
||||
nbproject/private/
|
||||
build/*
|
||||
nbbuild/
|
||||
nbdist/
|
||||
.nb-gradle/
|
||||
|
||||
######################################################################
|
||||
# Others
|
||||
*.log
|
||||
*.xml.versionsBackup
|
||||
*.swp
|
||||
|
||||
!*/build/*.java
|
||||
!*/build/*.html
|
||||
!*/build/*.xml
|
||||
0
ruoyi-admin/src/main/resources/static/.nojekyll
Normal file
0
ruoyi-admin/src/main/resources/static/.nojekyll
Normal file
1
ruoyi-admin/src/main/resources/static/CNAME
Normal file
1
ruoyi-admin/src/main/resources/static/CNAME
Normal file
@@ -0,0 +1 @@
|
||||
plus-doc.dromara.org
|
||||
74
ruoyi-admin/src/main/resources/static/README.md
Normal file
74
ruoyi-admin/src/main/resources/static/README.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# 框架介绍
|
||||
- - -
|
||||
- `RuoYi-Vue-Plus` 分布式集群框架 [文档跳转](/ruoyi-vue-plus/home.md)
|
||||
- `RuoYi-Cloud-Plus` 微服务框架 [文档跳转](/ruoyi-cloud-plus/home.md)
|
||||
- `plus-ui` 统一 Vue3 前端项目 [文档跳转](/plus-ui/home.md)
|
||||
- `plus-doc` 统一文档项目
|
||||
|
||||
## 特别赞助
|
||||
|
||||
<a href="https://gitee.com/dromara/MaxKey"><img src="https://foruda.gitee.com/images/1700187453544179968/7342304a_1766278.png" width="400px" height="100px"></a>
|
||||
<a href="http://ccflow.org/?frm=ryPlus"><img src="https://foruda.gitee.com/images/1704162419429172656/d0521e59_1766278.png" width="400px" height="100px"></a>
|
||||
<br>
|
||||
<a href="http://www.shuduokeji.com"><img src="https://foruda.gitee.com/images/1705569347386939952/3f187980_1766278.jpeg" width="400px" height="100px"></a>
|
||||
<a href="https://www.jnpfsoft.com/index.html?from=plus-doc"><img src="https://foruda.gitee.com/images/1711681233267310022/2ffbcff2_1766278.png" width="400px" height="100px"></a>
|
||||
<br>
|
||||
<a href="https://item.jd.com/13928958.html?from=plus-doc"><img src="https://foruda.gitee.com/images/1723791569938403230/769e98da_1766278.jpeg" width="400px" height="100px"></a>
|
||||
|
||||
[如何成为赞助商 加群联系作者详谈](/common/add_group.md)
|
||||
|
||||
## 代码地址
|
||||
|
||||
| 介绍 | 项目名 | 项目地址 | 注意事项 |
|
||||
|------------|:-----------------|------------------------------------------------------------------------------------------------------------------------|----------------------------|
|
||||
| 🔥 分布式集群框架 | RuoYi-Vue-Plus | - [Gitee](https://gitee.com/dromara/RuoYi-Vue-Plus)<br> - [GitHub](https://github.com/dromara/RuoYi-Vue-Plus) | 重写RuoYi-Vue全方位升级(不兼容原框架) |
|
||||
| 🔥 微服务框架 | RuoYi-Cloud-Plus | - [Gitee](https://gitee.com/dromara/RuoYi-Cloud-Plus)<br>- [GitHub](https://github.com/dromara/RuoYi-Cloud-Plus) | 重写RuoYi-Cloud全方位升级(不兼容原框架) |
|
||||
| 🔥 统一前端项目 | plus-ui | - [Gitee](https://gitee.com/JavaLionLi/plus-ui)<br>- [GitHub](https://github.com/JavaLionLi/plus-ui) | Vue与Cloud项目通用前端 |
|
||||
| 🔥 统一文档项目 | plus-doc | - [Gitee](https://gitee.com/dromara/plus-doc)<br>- [GitHub](https://github.com/dromara/plus-doc) | 通用文档 |
|
||||
|
||||
|
||||
## 业务功能
|
||||
|
||||
| 功能 | 介绍 |
|
||||
|-------|---------------------------------------|
|
||||
| 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能。 |
|
||||
| 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置。 |
|
||||
| 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 |
|
||||
| 岗位管理 | 配置系统用户所属担任职务。 |
|
||||
| 菜单管理 | 配置系统菜单,操作权限,按钮权限标识等。 |
|
||||
| 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分。 |
|
||||
| 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护。 |
|
||||
| 参数管理 | 对系统动态配置常用参数。 |
|
||||
| 通知公告 | 系统通知公告信息发布维护。 |
|
||||
| 操作日志 | 系统正常操作日志记录和查询;系统异常信息日志记录和查询。 |
|
||||
| 登录日志 | 系统登录日志记录查询包含登录异常。 |
|
||||
| 文件管理 | 系统文件上传、下载等管理。 |
|
||||
| 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志。 |
|
||||
| 代码生成 | 前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 |
|
||||
| 系统接口 | 根据业务代码自动生成相关的api接口文档。 |
|
||||
| 服务监控 | 监视集群系统CPU、内存、磁盘、堆栈、在线日志、Spring相关配置等。 |
|
||||
| 缓存监控 | 对系统的缓存信息查询,命令统计等。 |
|
||||
| 在线构建器 | 拖动表单元素生成相应的HTML代码。 |
|
||||
| 使用案例 | 系统的一些功能案例 |
|
||||
|
||||
## 关注作者
|
||||
|
||||
作者博客: [https://lionli.blog.csdn.net/?type=blog](https://lionli.blog.csdn.net/?type=blog)
|
||||
|
||||
公众号: **<狮子领域 程序圈>**
|
||||
<br>
|
||||

|
||||
|
||||
## 捐献作者
|
||||
|
||||
**作者为兼职做开源,平时还需要工作,如果帮到了您可以请作者吃个盒饭**
|
||||
<br>
|
||||
<img src="https://foruda.gitee.com/images/1725259663554875162/bd86a165_1766278.png" width="300px" height="450px" /><img src="https://foruda.gitee.com/images/1725259708005620620/22833e19_1766278.jpeg" width="300px" height="450px" />
|
||||
|
||||
## Dromara 全家福
|
||||
|
||||
社区仓库地址: [dromara开源社区](https://gitee.com/organizations/dromara/projects)
|
||||
|
||||

|
||||
|
||||
|
||||
32
ruoyi-admin/src/main/resources/static/_coverpage.md
Normal file
32
ruoyi-admin/src/main/resources/static/_coverpage.md
Normal file
@@ -0,0 +1,32 @@
|
||||
<!-- _coverpage.md -->
|
||||
<html>
|
||||
<img src="./static/image/logo2.png" width="260px" height="260px">
|
||||
<div style="display: flex; align-content:center; justify-content: center;">
|
||||
<div >
|
||||
<div style="font-weight: bold; font-size: 40px;">百搭AI</div>
|
||||
<!-- <div style="font-weight: bold; font-size: 40px;margin-bottom: 30px;">多租户权限管理系统</div> -->
|
||||
|
||||
[](https://gitee.com/ageerle/ruoyi-ai)
|
||||
[](https://github.com/dromara/RuoYi-Vue-Plus)
|
||||
[](https://gitee.com/ageerle/ruoyi-ai/blob/master/LICENSE)
|
||||
<br>
|
||||
[](https://gitee.com/ageerle/ruoyi-ai)
|
||||
[]()
|
||||
|
||||
</div>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</html>
|
||||
|
||||
> 百搭AI是一个整合了多种大语言模型API的开源平台,实现了AI对话、绘图、声音克隆和私有知识库等功能。
|
||||
>
|
||||
> 平台配备管理后台,支持微信支付、微信公众号、微信多开、Stripe国际支付和百度文本审核等运营功能。
|
||||
>
|
||||
> 项目采用Java+Vue+Vben5技术栈构建,遵循MIT License,允许二次开发并用于商业销售。
|
||||
|
||||
Copyright © 2023-2024 版权所有:ageerle@163.com 备案号:<a href="https://beian.miit.gov.cn/">鄂ICP备2023007672号</a>
|
||||
|
||||
[开始使用 Let's Go](/README.md)
|
||||
2
ruoyi-admin/src/main/resources/static/_footer.md
Normal file
2
ruoyi-admin/src/main/resources/static/_footer.md
Normal file
@@ -0,0 +1,2 @@
|
||||
<!-- _footer.md 页脚配置 -->
|
||||
对文档有疑问?欢迎您帮助我们 [完善此文档](https://gitee.com/JavaLionLi/plus-doc) !
|
||||
9
ruoyi-admin/src/main/resources/static/_navbar.md
Normal file
9
ruoyi-admin/src/main/resources/static/_navbar.md
Normal file
@@ -0,0 +1,9 @@
|
||||
<!-- _navbar.md -->
|
||||
|
||||
* [文档导航](/README.md)
|
||||
* [Vue版本](/ruoyi-vue-plus/home.md)
|
||||
* [Cloud版本](/ruoyi-cloud-plus/home.md)
|
||||
* [前端文档](/plus-ui/home.md)
|
||||
* [常见问题](/questions/lombok.md)
|
||||
* [视频教程](/common/video.md)
|
||||
* [演示系统](/common/demo_system.md)
|
||||
16
ruoyi-admin/src/main/resources/static/_sidebar.md
Normal file
16
ruoyi-admin/src/main/resources/static/_sidebar.md
Normal file
@@ -0,0 +1,16 @@
|
||||
<!-- _sidebar.md -->
|
||||
- **特别赞助**
|
||||
- [](http://ccflow.org/?frm=ryPlus)
|
||||
- [](http://www.shuduokeji.com)
|
||||
- [](https://www.jnpfsoft.com/index.html?from=plus-doc)
|
||||
|
||||
- **开始**
|
||||
- [框架介绍](/README.md)
|
||||
- [演示系统](/common/demo_system.md)
|
||||
- [官方视频教程](/common/video.md)
|
||||
- [粉丝专栏](/common/column.md)
|
||||
- [参与贡献项目](/common/contribution.md)
|
||||
- [如何提交PR](/common/pr.md)
|
||||
- [如何加群](/common/add_group.md)
|
||||
- [使用者登记](/common/user_register.md)
|
||||
- [黑名单](/common/blacklist.md)
|
||||
27
ruoyi-admin/src/main/resources/static/common/add_group.md
Normal file
27
ruoyi-admin/src/main/resources/static/common/add_group.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# 加群方式
|
||||
- - -
|
||||
### 交流群(不提供任何问题解答 纯交流)
|
||||
|
||||
**加 <小助手> 微信备注 <加群>**<br>
|
||||
**视频课程咨询或其他问题咨询请查看下方信息(小助手是机器人)**
|
||||
|
||||
<img src="https://foruda.gitee.com/images/1680762410689884638/60b546ca_1766278.png" width="300" height="300">
|
||||
|
||||
### VIP群(付费加群 提供问题解答、技术支持、技术分享)
|
||||
|
||||
首先感谢 `RuoYi` 提供分享开源 框架基于 `RuoYi` 重写大部分功能实现<br>
|
||||
项目代码、文档 均开源免费可商用 遵循开源协议在项目中保留开源协议文件即可<br>
|
||||
VIP群是作者提供的私人服务 不代表着项目收费
|
||||
|
||||
> 问问题等于做习题 听作者解答问题等于习题讲解<br>
|
||||
> 一个人接触的问题有限 一群人接触的问题无限 早进群早接触更多的问题(每天99+)<br>
|
||||
> 承诺: 看见必回复 让你感受作者有多话痨<br>
|
||||
|
||||
两种途径:
|
||||
1. 购买官方视频进群 [官方视频](/common/video.md)
|
||||
2. 扫描下方二维码付款进群(无视频)
|
||||
|
||||
支付后申请加群即可 QQ群号 : **<637757165>**<br>
|
||||
|
||||
**加群扫码**<br>
|
||||
<img src="https://foruda.gitee.com/images/1725259839682556495/2897bc86_1766278.png" width="300px" height="450px" /><img src="https://foruda.gitee.com/images/1725259806547656944/f870a5c7_1766278.jpeg" width="300px" height="450px" />
|
||||
@@ -0,0 +1,7 @@
|
||||
# 黑名单
|
||||
- - -
|
||||
|
||||
地址: https://github.com/QNAV/RuoYi-X-Plus
|
||||
<br>
|
||||
上榜缘由 使用本框架二次开源并未有任何声明与标注 将所有代码的作者名全都改成了自己 剽窃本框架代码
|
||||
|
||||
18
ruoyi-admin/src/main/resources/static/common/column.md
Normal file
18
ruoyi-admin/src/main/resources/static/common/column.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# 粉丝专栏
|
||||
- - -
|
||||
**由上到下 从易到难**
|
||||
|
||||
> 粉丝整理 欢迎投稿
|
||||
|
||||
| 作者 | 文档地址 | 说明 |
|
||||
|---------------|---------------------------------------------------------------|--------------------|
|
||||
| 抓蛙师 | https://www.bilibili.com/video/BV1TG41157Ef/ | 学会问问题(小白必看) |
|
||||
| 抓蛙师 | https://www.bilibili.com/video/BV1mr4y1j75M | Vue框架基础视频专栏(新人必看) |
|
||||
| 抓蛙师 | https://www.bilibili.com/video/BV1Na411u7eC | Vue框架改造视频专栏(新人必看) |
|
||||
| 抓蛙师 | https://www.bilibili.com/video/BV1te4y1D7hi | 小程序鉴权与uniapp联动 |
|
||||
| 抓蛙师 | https://www.bilibili.com/video/BV1zt4y137UP | 公众号集成 |
|
||||
| mayuanfei | https://note.youdao.com/s/XpvKnxAb | 入门专栏(新人必看) |
|
||||
| 程序猿一枚_ | https://blog.csdn.net/zhaozhiqiang1981/category_12221291.html | 玩转RuoYi-Cloud-Plus |
|
||||
| 程序猿一枚_ | https://www.bilibili.com/video/BV1yA411r7ji/ | Cloud环境搭建以及进阶开发 |
|
||||
| MichelleChung | https://blog.csdn.net/michelle_zhong/category_11109741.html | 源码解析专栏(进阶必看) |
|
||||
| MichelleChung | https://blog.csdn.net/michelle_zhong/category_12058476.html | Cloud源码解析专栏 |
|
||||
69
ruoyi-admin/src/main/resources/static/common/contribution.md
Normal file
69
ruoyi-admin/src/main/resources/static/common/contribution.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# 参与贡献的方式
|
||||
- - -
|
||||
参与贡献开源的方式有很多种 听作者来介绍
|
||||
|
||||
## 为开源项目点一个Star
|
||||
|
||||
> Star的多少关系到项目能否被更多人看到
|
||||
<br>
|
||||
同时Star也是作者前进的动力(作者每天都在盯着Star 涨了会开心 跌了会失落)
|
||||
<br>
|
||||
<br>
|
||||
> 大家在寻找开源项目的时候, 大多数情况也是会先看Star比较多的项目
|
||||
<br>
|
||||
所以请给您觉得好的开源项目点一个小小的Star, 让好的项目能够被更多人看到
|
||||
<br>
|
||||
|
||||

|
||||
<br>
|
||||
<font size="4">Vue版本: [Gitee我要点Star](https://gitee.com/dromara/RuoYi-Vue-Plus/stargazers) [Github我要点Star](https://github.com/dromara/RuoYi-Vue-Plus)</font>
|
||||
<br>
|
||||
<font size="4">Cloud版本: [Gitee我要点Star](https://gitee.com/dromara/RuoYi-Cloud-Plus/stargazers) [Github我要点Star](https://github.com/dromara/RuoYi-Cloud-Plus)</font>
|
||||
|
||||
## 为社区处理问题
|
||||
|
||||
> Issue是社区的交流地 大家会在这里提出自己的问题 或者是项目的功能异常
|
||||
|
||||
> 提问的规范在Issue的模板里已经写好了 按照模板填写有助于作者或者其他社区人员快速有效的回答问题
|
||||

|
||||
|
||||
> 为提出问题的小伙伴答疑 可以有效降的帮助别人<br>
|
||||
> 而且可以降低社区人员的精力分散 使精力全部投入到项目设计研发中
|
||||

|
||||
|
||||
## 改进社区文档
|
||||
|
||||
> 大家都知道 我们程序员都不擅长写作<br>
|
||||
> 有时候作者把文档写完了也不知道用户是什么感觉 是否能看懂<br>
|
||||
|
||||
> 所以参与社区文档建设绝对是一件意义重大的事情<br>
|
||||
> 大家可以在Issue提出观后感 觉得哪看不懂 觉得哪应该详细说明<br>
|
||||
> 当然了 大家也可以对文档进行改进后提交PR修改申请
|
||||
|
||||
<font size="6">文档仓库: [plus-doc](https://gitee.com/JavaLionLi/plus-doc) 👈点他点他</font>
|
||||

|
||||
|
||||
## 贡献代码
|
||||
|
||||
> 想参与贡献代码的小伙伴 重点来了: 作者会经常在Issue里发布需求认领<br>
|
||||
> 觉得自己能做的可以在Issue里跟作者讨论 如需求还不够清晰 或者做的过程中遇到了什么问题
|
||||
|
||||
<img src="https://foruda.gitee.com/images/1678936513184771725/f26349dd_1766278.png" width="550px" height="450px" />
|
||||
|
||||
> 需求确定了以后就可以开始专注的写代码了<br>
|
||||
> 但在开始写代码之前 一定要先看一下如何正确的提交PR
|
||||
|
||||
<font size="4">一点要仔细看: [如何提交PR](/common/pr.md) 👈点他点他</font>
|
||||
|
||||
## 如何成为项目成员
|
||||
|
||||
> 1.对框架有重大贡献者(由作者与团队成员判定)<br>
|
||||
> 2.完成社区发布的两项复杂任务<br>
|
||||
> 3.持续完成社区发布的简单任务若干(作者会关注到)<br>
|
||||
> 4.持续为社区优化文档或处理issue若干(作者会关注到)<br>
|
||||
|
||||
## 项目成员待遇
|
||||
|
||||
> 1.可免费进入vip收费群<br>
|
||||
> 2.每年还会发放IDEA正版授权<br>
|
||||
|
||||
13
ruoyi-admin/src/main/resources/static/common/demo_system.md
Normal file
13
ruoyi-admin/src/main/resources/static/common/demo_system.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# 系统演示(请大家不要乱改数据 影响他人体验 谢谢配合)
|
||||
- - -
|
||||
**感谢 `孤舟烟雨` 贡献的演示服务器**
|
||||
|
||||
**1核2G 小服务器 经不起压测 请理性操作 违者直接封IP**
|
||||
|
||||
> 访问地址: [http://43.138.9.96/](http://43.138.9.96/)
|
||||
|
||||
> 登录账户 admin/admin123
|
||||
|
||||
> Admin监控中心 ruoyi/123456
|
||||
|
||||
> 任务调度中心 admin/123456
|
||||
37
ruoyi-admin/src/main/resources/static/common/pr.md
Normal file
37
ruoyi-admin/src/main/resources/static/common/pr.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# 如何提交PR贡献代码
|
||||
- - -
|
||||
### 步骤一 Fork项目到自己仓库
|
||||
|
||||

|
||||
|
||||
### 步骤二 基于dev分支 新建一个此PR功能点的专属分支
|
||||
|
||||

|
||||

|
||||
|
||||
### 步骤三 使用Git工具 将自己仓库的项目拉去到本地做代码编写
|
||||
|
||||

|
||||
|
||||
### 步骤四 使用Idea打开项目 切换到新建的功能分支
|
||||
|
||||

|
||||
|
||||
### 步骤五 将编写好的代码 提交到自己的远程仓库
|
||||
|
||||

|
||||
|
||||
### 步骤六 创建PR申请(此操作在自己仓库或者要PR的仓库都可以)
|
||||
|
||||

|
||||

|
||||
|
||||
### 步骤七 等待作者评审 按要求更改 直到没有问题后被作者合并
|
||||
|
||||

|
||||
|
||||
### 评审期间 如需对PR内容做更改 直接在新功能分支提交代码即可
|
||||
### 无需重复提交PR申请 这边会自动比对两个分支的差异
|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# 使用者登记
|
||||
- - -
|
||||
**使用此开源项目的公司或者组织**
|
||||
> Vue版本登记地址: https://gitee.com/dromara/RuoYi-Vue-Plus/issues/I4QP39
|
||||
|
||||
> Cloud版本登记地址: https://gitee.com/dromara/RuoYi-Cloud-Plus/issues/I4VJ7G
|
||||
|
||||
| 公司名 | 官网 | LOGO |
|
||||
|-------------------|:-------------------------------|----------------------------------------------------------------------------------------------------------------|
|
||||
| 中国联通(长春分公司) | http://www.10010.com | <img src="https://foruda.gitee.com/images/1679554727740431371/bd179d0f_1766278.png" width="300" height="200"> |
|
||||
| 中国电信(湖南分公司) | http://www.189.cn/hn/ | <img src="https://foruda.gitee.com/images/1699838764871886313/61b44b7d_1766278.png" width="300" height="200"> |
|
||||
| 南京感知信息技术有限公司 | https://njgzxx.cn/ | <img src="https://foruda.gitee.com/images/1725589695335847776/10bb2088_1766278.png" width="400" height="200"> |
|
||||
| 陕西骏景索道运营管理有限公司 | https://www.junjingsuodao.com/ | <img src="https://foruda.gitee.com/images/1724394959451680041/24ac17ff_7408092.png" width="300" height="200"> |
|
||||
| 悠码科技有限公司 | https://orise.trytowish.cn/ | <img src="https://foruda.gitee.com/images/1722916054523975884/686ee49e_8929785.png" width="200" height="200"> |
|
||||
| 苏州龙的信息系统股份有限公司 | http://www.longdayinfo.com/ | <img src="https://foruda.gitee.com/images/1721182313605689705/f676882a_2113976.png" width="400" height="200"> |
|
||||
| 北京数通智达科技有限公司 | http://www.bzdtech.com/ | <img src="https://foruda.gitee.com/images/1717744899576682096/7d6cf41f_1766278.png" width="400" height="200"> |
|
||||
| 广州六六七七科技有限公司 | https://artiversehub.ai/ | <img src="https://foruda.gitee.com/images/1716976454631958575/44abbb05_1766278.png" width="300" height="200"> |
|
||||
| 宁波三品软件科技有限公司 | http://nbsanpin.com/ | <img src="https://foruda.gitee.com/images/1715845257022437822/1a096edc_14415359.png" width="300" height="200"> |
|
||||
| 北京御一科技信息技术有限公司 | https://www.yudoctor.com | <img src="https://foruda.gitee.com/images/1715157943995574211/09aa2229_1766278.png" width="400" height="200"> |
|
||||
| 成都卡恩特医疗科技有限公司 | http://www.scknot.com | <img src="https://foruda.gitee.com/images/1711091474880818044/96ddef90_1766278.png" width="400" height="200"> |
|
||||
| 无锡科艾思科技有限公司 | https://www.kyoeis.com | <img src="https://foruda.gitee.com/images/1710929131545545232/a87f838e_1766278.png" width="400" height="200"> |
|
||||
| 深圳市海联天下科技有限公司 | www.sealinkin.com | <img src="https://foruda.gitee.com/images/1709870697911145583/453db298_1766278.png" width="400" height="200"> |
|
||||
| 上海非定义旅游服务有限公司 | http://www.anonymity.love/ | <img src="https://foruda.gitee.com/images/1706165274431234456/f4be93d3_1766278.png" width="400" height="200"> |
|
||||
| 重庆威爱云科技有限公司 | https://www.51vive.com | <img src="https://foruda.gitee.com/images/1700460635019084607/f073724d_1766278.png" width="400" height="200"> |
|
||||
| 中城智联(成都)创新科技有限公司 | http://www.zc-zl.com/ | <img src="https://foruda.gitee.com/images/1699841115050735040/0d6893d1_1766278.png" width="300" height="200"> |
|
||||
| 浙江海亮股份有限公司 | https://www.hailiangstock.com | <img src="https://foruda.gitee.com/images/1699841174631804104/fd3466fd_1766278.png" width="300" height="200"> |
|
||||
| 河北雄安山禾咨询工程有限公司 | https://shanheqei.club/ | <img src="https://foruda.gitee.com/images/1699855302878416881/6bfdb2d5_1766278.png" width="300" height="200"> |
|
||||
| 数舵(河北雄安)信息科技有限公司 | http://www.shuduokeji.com | <img src="https://foruda.gitee.com/images/1698888517162767014/8a2840ff_1766278.png" width="400" height="200"> |
|
||||
| 南昌鼎欣科技股份有限公司 | https://www.openzt.com | <img src="https://foruda.gitee.com/images/1697701810520579719/4da9666e_1766278.png" width="400" height="200"> |
|
||||
| 东莞市码载网络科技有限公司 | https://www.codeload.top | <img src="https://foruda.gitee.com/images/1697618746817506398/57af2eaa_10583761.png" width="400" height="200"> |
|
||||
| 北京农信通科技有限责任公司 | http://www.nxt.com.cn | <img src="https://foruda.gitee.com/images/1696428611360166577/72e7f7c4_971517.png" width="400" height="200"> |
|
||||
| 中康腾华网络科技(重庆)有限公司 | https://www.zkthwlkj.com/ | <img src="https://foruda.gitee.com/images/1695112845600729239/a16e34e2_1766278.png" width="200" height="100"> |
|
||||
| 杭州码恒信息科技有限公司 | http://www.mh-barcode.com/ | <img src="https://foruda.gitee.com/images/1690881482450489558/2d689bc1_1766278.png" width="400" height="200"> |
|
||||
| 南京晶益科技有限公司 | https://www.nanjingjingyi.com/ | <img src="https://foruda.gitee.com/images/1689576488369281878/bec504ce_1766278.png" width="400" height="200"> |
|
||||
| 合肥智享亿云科技有限公司 | http://www.izxyy.com | <img src="https://foruda.gitee.com/images/1685096398913604988/e6c16816_1766278.png" width="300" height="200"> |
|
||||
| 锡简科技 | https://www.xj-fast.com | <img src="https://foruda.gitee.com/images/1683858424104223718/172f2c2e_1766278.png" width="300" height="200"> |
|
||||
| 福建亘前科技有限公司 | https://genqian.top | <img src="https://foruda.gitee.com/images/1683170298723703161/891feff4_1766278.png" width="400" height="200"> |
|
||||
| 北京联宇信通科技有限公司 | http://www.lyxtkj.com/ | <img src="https://foruda.gitee.com/images/1680068618387237935/5e195ad8_1766278.png" width="400" height="200"> |
|
||||
| 厦门市熵时光科技有限公司 | https://www.xetsoft.com | <img src="https://foruda.gitee.com/images/1672299365177532128/f0e78c26_1766278.png" width="400" height="200"> |
|
||||
| 广州润沁教育科技有限公司 | https://www.ca163.net | <img src="https://foruda.gitee.com/images/1678976000893686992/1acbda54_1766278.png" width="400" height="200"> |
|
||||
| 广东乐善智能装备股份有限公司 | https://www.china-leshan.com/ | <img src="https://foruda.gitee.com/images/1672299473733272899/2065e28c_1766278.png" width="400" height="200"> |
|
||||
| 数字江西科技有限公司 | https://www.digitaljx.com/ | <img src="https://foruda.gitee.com/images/1660527156328976445/屏幕截图.png" width="300" height="200"> |
|
||||
| 上海极锐星瀚传感技术有限公司 | http://www.jrsensing.com/ | <img src="https://foruda.gitee.com/images/1669694597446652604/6997f99a_1766278.png" width="400" height="100"> |
|
||||
| 北京数影互联科技有限公司 | http://www.dataflying.top/ | <img src="https://foruda.gitee.com/images/1686118090145603656/46dbe579_1766278.png" width="200" height="100"> |
|
||||
| 广州创服信息科技有限公司 | https://www.cfkjcloud.com | <img src="https://foruda.gitee.com/images/1678975960889135530/85fa904f_1766278.png" width="400" height="200"> |
|
||||
| 茂名云智科技有限公司 | http://www.winzkj.com | <img src="https://foruda.gitee.com/images/1678975967691323451/6343e6b7_1766278.png" width="400" height="200"> |
|
||||
| 成都时光旅迹科技有限公司 | https://www.ttmup.com/ | <img src="https://foruda.gitee.com/images/1678975973935607983/a0f8dce2_1766278.png" width="400" height="200"> |
|
||||
| 成都炫影全息科技有限公司 | http://xyqxgs.com | <img src="https://foruda.gitee.com/images/1678975979873588062/e34db081_1766278.png" width="400" height="200"> |
|
||||
| 中山厚德快速模具有限公司 | http://hordrt.com | <img src="https://foruda.gitee.com/images/1678975986213675141/7436dcb9_1766278.png" width="400" height="200"> |
|
||||
| 深圳市深南夙星科技有限公司 | http://www.szsnsx.com/ | <img src="https://foruda.gitee.com/images/1678975994674685698/a2c05a6e_1766278.png" width="400" height="200"> |
|
||||
| 陕西华恒军创信息科技有限公司 | http://hhjc.cc | <img src="https://foruda.gitee.com/images/1678976006389002991/3786a1bc_1766278.png" width="400" height="200"> |
|
||||
| 河南小牛信息科技有限公司 | http://www.hnxn888.com/ | <img src="https://foruda.gitee.com/images/1681106560964010687/d8969ed2_1766278.png" width="200" height="100"> |
|
||||
| 武汉华智讯网络信息技术有限公司 | http://www.xun188.com | <img src="https://foruda.gitee.com/images/1678975944577016382/93c4541d_1766278.png" width="200" height="100"> |
|
||||
| 易税信息技术有限公司 | https://www.etax.top | <img src="https://foruda.gitee.com/images/1678975950137235651/211a63c4_1766278.png" width="200" height="100"> |
|
||||
| 广西华景城建筑设计有限公司 | http://www.hjcadc.com | <img src="https://foruda.gitee.com/images/1678975955216975234/e83c8c6e_1766278.png" width="200" height="100"> |
|
||||
| 铭创科技有限公司 | https://www.mcck.cn/ | <img src="https://foruda.gitee.com/images/1693967206668467582/8c234a6d_1766278.png" width="200" height="100"> |
|
||||
| 西安鼎慧网络科技有限公司 | | <img src="https://foruda.gitee.com/images/1721271356660437424/b85c5754_8776295.jpeg" width="400" height="200"> |
|
||||
| 营口鼎瑞网络科技有限公司 | | <img src="https://foruda.gitee.com/images/1715836865319520119/5dc34a5f_8693506.png" width="400" height="200"> |
|
||||
| 南昌漫库书店有限公司 | | <img src="https://foruda.gitee.com/images/1687656369793887183/ce1a33f6_1766278.png" width="200" height="100"> |
|
||||
| 广西文韬智能科技有限公司 | | <img src="https://foruda.gitee.com/images/1678976034543683491/8d8a1ebe_1766278.png" width="200" height="100"> |
|
||||
| 贵州亿瑞祺科技有限公司 | |
|
||||
| 贵州新绿视界环保科技有限公司 | |
|
||||
| 湖南智才伯乐数据科技有限公司 | |
|
||||
| 德州商储超市有限公司 | |
|
||||
| 曲沃亿分科技中心 | |
|
||||
| 南京杰度信息技术有限公司 | |
|
||||
| 武汉忆秋科技有限公司 | |
|
||||
| 济南千惠网络科技有限公司 | |
|
||||
| 江苏泛联科技有限公司 | |
|
||||
| 沈阳市果冻网络信息科技有限责任公司 | |
|
||||
| 灵劲科技有限公司 | |
|
||||
| 亿世达餐饮管理(北京)有限公司 | |
|
||||
| 深圳市凯帝电子商务有限公司 | |
|
||||
| 成都数智源蓉卡科技有限公司 | |
|
||||
| 上海振福信息科技有限公司 | |
|
||||
| 重庆六客会科技有限公司 | |
|
||||
| 无限创优(西安)科技有限公司 | |
|
||||
| 惠族网络科技发展有限公司 | |
|
||||
| 纳森科技有限公司 | |
|
||||
|
||||
85
ruoyi-admin/src/main/resources/static/common/video.md
Normal file
85
ruoyi-admin/src/main/resources/static/common/video.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# 视频教程(联合出品)
|
||||
|
||||
### 主讲与后期剪辑: `抓蛙师`
|
||||
|
||||
抓蛙师简介: B站知名UP主 B站首页: https://space.bilibili.com/520725002
|
||||
|
||||
### 知识点统筹与内容审核: `疯狂的狮子Li`
|
||||
|
||||
疯狂的狮子Li简介: RuoYi-Vue-Plus 与 RuoYi-Cloud-Plus 作者
|
||||
|
||||
## 已完结🎉🎉🎉 优惠价: 598(仅限前500名) ~~原价: 698~~
|
||||
|
||||
**注意: 视频采用 RuoYi-Vue-Plus 版本 4.X 分支讲解!!! (内容为通用技术与版本关联性不大)**<br>
|
||||
**内容为框架内所用到的技术与设计原理(打破不知道、不会用、不知应用场景等问题)**
|
||||
|
||||
课程简介: https://www.bilibili.com/video/BV16j411D7BX/
|
||||
<br>
|
||||
试看课程: https://www.bilibili.com/video/BV1uS411P7JD/
|
||||
<br>
|
||||
试看课程: https://www.bilibili.com/video/BV1vLbNeuESn/
|
||||
<br>
|
||||
试看课程: https://www.bilibili.com/video/BV1xV4y127KM/
|
||||
<br>
|
||||
试看课程: https://www.bilibili.com/video/BV1W5v8eBEgs/
|
||||
<br>
|
||||
课程总结: https://www.bilibili.com/video/BV1734y1g7fk/
|
||||
<br>
|
||||
|
||||
## 购买方式
|
||||
|
||||
**小本生意 用心录制 拒绝砍价 已更新到 236 集 课程完结**<br>
|
||||
> 课程咨询或购买请联系 价格598<br>
|
||||
> QQ: 906670865 (疯狂的狮子Li)<br>
|
||||
> QQ: 770492966 (抓蛙师)
|
||||
|
||||
## 购买前常见问题答疑
|
||||
> 问题1: 购买后是否有群可以解答问题<br>
|
||||
> 答: 购买后有专属课程付费群(千人大群)讲师在线答疑
|
||||
>
|
||||
> 问题2: 是否持续更新 如新版本功能<br>
|
||||
> 答: 课程目录即为全部课程内容 以课程目录为准 明年大概会出二期来讲新版本内容<br>
|
||||
> 因为持续更新会导致前面的技术老旧 新购买的人无法及时学习新技术<br>
|
||||
> 故而采用分期出课程制度 已经购买过的老客户 再次购买下一次会给力度非常大的折扣
|
||||
>
|
||||
> 问题3: 目前视频未全部录制完成 后续更新是否二次收费<br>
|
||||
> 答: 视频目录即为全部视频内容 一次收费后续更新仍然可看直到视频全部更新完成(明年出二期课程不算在内)
|
||||
>
|
||||
> 问题4: 视频如何下载如何观看<br>
|
||||
> 答: 视频文件已加密 采用专门的播放器(播放器只限制截图录屏等不限制其他软件使用) 由管理员发放授权码观看<br>
|
||||
> 支持通过 百度云 或者 阿里云 网盘下载视频资源
|
||||
>
|
||||
> 问题5: 视频平均时长和总时长大概多久<br>
|
||||
> 答: 视频每集短的大概10分钟以上 长的大概40个分钟左右 平均时长20多分钟每集<br>
|
||||
> 目前已经录制了236集总时长为80多个小时
|
||||
>
|
||||
> 问题6: 是否有讲解 Cloud 版本相关内容<br>
|
||||
> 答: 视频主要讲解内容为框架内所用到的技术与设计原理 无论什么版本 功能和设计都是一样的<br>
|
||||
> Cloud 版本只是多了 alibaba 的几个组件完全可以B站自学
|
||||
|
||||
## 课程目录
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
## 学员观后感
|
||||
|
||||
| | |
|
||||
|---------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
@@ -1,104 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Meta, title, CSS, favicons, etc. -->
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="Padna Home">
|
||||
<meta name="keywords" content="Padna,Homepage">
|
||||
<meta name="author" content="Padna">
|
||||
<title>熊猫助手</title>
|
||||
<link rel="stylesheet" type="text/css" href="./assets/css/onlinewebfonts.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="./assets/css/vno.css">
|
||||
<link rel="stylesheet" type="text/css" href="./assets/css/iconfont.css">
|
||||
<link rel="icon" href="./assets/svg/favicon.svg">
|
||||
<meta charset="UTF-8">
|
||||
<title>plus-doc</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
|
||||
<meta name="description" content="Description">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<!-- 设置浏览器图标 -->
|
||||
<link rel="icon" href="./static/image/favicon.ico" type="image/x-icon"/>
|
||||
<link rel="shortcut icon" href="./static/image/favicon.ico" type="image/x-icon"/>
|
||||
<meta charset="UTF-8">
|
||||
<!-- 默认主题 -->
|
||||
<link rel="stylesheet" href="./static/css/vue.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<span class="mobile btn-mobile-menu">
|
||||
<i class="social iconfont icon-list btn-mobile-menu__icon"></i>
|
||||
<i class="social iconfont icon-angleup btn-mobile-close__icon hidden"></i>
|
||||
</span>
|
||||
<header id="panel" class="panel-cover">
|
||||
<div class="panel-main">
|
||||
<div class="panel-main__inner panel-inverted">
|
||||
<div class="panel-main__content">
|
||||
<div class="ih-item circle effect right_to_left">
|
||||
<a href="#" title="" class="blog-button">
|
||||
<div>
|
||||
<img src="./assets/img/logo1.jpg" alt="img" class="js-avatar iUp profilepic"></div>
|
||||
</a>
|
||||
</div>
|
||||
<h1 class="panel-cover__title panel-title iUp">
|
||||
<a href="#" title="Dmego Home">ageerle</a>
|
||||
</h1>
|
||||
<p class="panel-cover__subtitle panel-subtitle iUp">Code Create Life</p>
|
||||
<hr class="panel-cover__divider iUp" />
|
||||
<p id="description" class="panel-cover__description iUp">如何得与凉风约, 不共尘沙一并来!
|
||||
<br/>
|
||||
<strong>-「中牟道中」</strong>
|
||||
</p>
|
||||
<div class="navigation-wrapper iUp">
|
||||
<div>
|
||||
<nav class="cover-navigation cover-navigation--primary">
|
||||
<ul class="navigation">
|
||||
<li class="navigation__item">
|
||||
<a href="#" class="blog-button">首页</a>
|
||||
</li>
|
||||
<li class="navigation__item">
|
||||
<a href="#" class="blog-button" target="_blank">博客</a>
|
||||
</li>
|
||||
<li class="navigation__item">
|
||||
<a href="#" class="blog-button" target="_blank">简历</a>
|
||||
</li>
|
||||
<li class="navigation__item">
|
||||
<a href="#" class="blog-button" target="_blank">关于</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="iUp">
|
||||
<nav class="cover-navigation navigation--social">
|
||||
<ul class="navigation">
|
||||
<li class="navigation__item">
|
||||
<a href="https://github.com/ageerle/ruoyi-ai" title="github" target="_blank">
|
||||
<i class='social iconfont icon-github'></i>
|
||||
<span class="label">github</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="navigation__item">
|
||||
<a href="https://blog.csdn.net/weixin_42416319" title="csdn" target="_blank">
|
||||
<i class='social iconfont icon-csdn'></i>
|
||||
<span class="label">csdn</span>
|
||||
</a>
|
||||
</li>
|
||||
<div id="app"></div>
|
||||
<script>
|
||||
window.$docsify = {
|
||||
// 项目名称
|
||||
name: 'ruoyi-ai',
|
||||
// 仓库地址,点击右上角的Github章鱼猫头像会跳转到此地址
|
||||
repo: 'https://gitee.com/ruoyi-ai',
|
||||
// 侧边栏支持,默认加载的是项目根目录下的_sidebar.md文件
|
||||
loadSidebar: true,
|
||||
// 导航栏支持,默认加载的是项目根目录下的_navbar.md文件
|
||||
loadNavbar: true,
|
||||
// 封面支持,默认加载的是项目根目录下的_coverpage.md文件
|
||||
coverpage: true,
|
||||
// 最大支持渲染的标题层级
|
||||
maxLevel: 5,
|
||||
// 自定义侧边栏后默认不会再生成目录,设置生成目录的最大层级(建议配置为2-4)
|
||||
subMaxLevel: 4,
|
||||
// 小屏设备下合并导航栏到侧边栏
|
||||
mergeNavbar: true,
|
||||
// 页脚支持,默认加载的是 _footer.md
|
||||
loadFooter: true,
|
||||
// 首页只展示封面(默认为false,与README.md进行拼接)
|
||||
onlyCover: true,
|
||||
search: {
|
||||
maxAge: 86400000,// 过期时间,单位毫秒,默认一天
|
||||
paths: 'auto',// 注意:仅适用于 paths: 'auto' 模式
|
||||
placeholder: '👉👉👉在这里搜索关键字👈👈👈',
|
||||
noData: '找不到结果',
|
||||
depth: 4,
|
||||
hideOtherSidebarContent: false,
|
||||
namespace: 'Docsify-Guide',
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<!-- docsify的js依赖 -->
|
||||
<script src="./static/js/docsify.min.js"></script>
|
||||
<!-- emoji表情支持 -->
|
||||
<script src="./static/js/emoji.min.js"></script>
|
||||
<!-- 图片放大缩小支持 -->
|
||||
<script src="./static/js/zoom-image.min.js"></script>
|
||||
<!-- 搜索功能支持 -->
|
||||
<script src="./static/js/search.min.js"></script>
|
||||
<!--在所有的代码块上添加一个简单的Click to copy按钮来允许用户从你的文档中轻易地复制代码-->
|
||||
<script src="./static/js/docsify-copy-code.min.js"></script>
|
||||
|
||||
<li class="navigation__item">
|
||||
<a href="https://gitee.com/ageerle/ruoyi-ai" title="gitee" target="_blank">
|
||||
<i class='social iconfont icon-cnblogs'></i>
|
||||
<span class="label">gitee</span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- 回到顶部 -->
|
||||
<script src="./static/js/docsify-scroll-to-top.min.js"></script>
|
||||
<!-- 分页导航 -->
|
||||
<script src="./static/js/docsify-pagination.min.js"></script>
|
||||
<!-- 页脚-->
|
||||
<script src="./static/js/docsify-footer.min.js"></script>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-cover--overlay cover-slate">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="remark iUp">
|
||||
<p class="power" >
|
||||
Copyright © 2023-2024 版权所有:xmzs 备案号:<a href="https://beian.miit.gov.cn/">鄂ICP备20231008611号</a>
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
<script type="text/javascript" src="./assets/js/main.js"></script>
|
||||
<script type="text/javascript" src="./assets/json/images.json?cb=getBingImages"></script>
|
||||
<!-- 代码高亮 -->
|
||||
<script src="./static/js/prism-typescript.min.js"></script>
|
||||
<script src="./static/js/prism-bash.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
22
ruoyi-admin/src/main/resources/static/plus-ui/_sidebar.md
Normal file
22
ruoyi-admin/src/main/resources/static/plus-ui/_sidebar.md
Normal file
@@ -0,0 +1,22 @@
|
||||
<!-- _sidebar.md -->
|
||||
- **特别赞助**
|
||||
- [](http://ccflow.org/?frm=ryPlus)
|
||||
- [](http://www.shuduokeji.com)
|
||||
- [](https://www.jnpfsoft.com/index.html?from=plus-doc)
|
||||
|
||||
|
||||
* **简介**
|
||||
* [项目简介](/plus-ui/home.md)
|
||||
* **开发文档**
|
||||
* [通用方法](/plus-ui/devdoc/common_func.md)
|
||||
* [开发规范](/plus-ui/devdoc/dev_norm.md)
|
||||
* [请求流程](/plus-ui/devdoc/request_process.md)
|
||||
* [路由使用](/plus-ui/devdoc/router_use.md)
|
||||
* [组件使用](/plus-ui/devdoc/component_use.md)
|
||||
* [权限使用](/plus-ui/devdoc/permissions_use.md)
|
||||
* [页签缓存](/plus-ui/devdoc/page_cache.md)
|
||||
* [使用图标](/plus-ui/devdoc/icon_use.md)
|
||||
* [使用字典](/plus-ui/devdoc/dict_use.md)
|
||||
* [使用参数](/plus-ui/devdoc/param_use.md)
|
||||
* [异常处理](/plus-ui/devdoc/exception_handling.md)
|
||||
* [内容复制](/plus-ui/devdoc/content_copy.md)
|
||||
@@ -0,0 +1,234 @@
|
||||
# 通用方法
|
||||
- - -
|
||||
|
||||
### $tab对象
|
||||
> `$tab`对象用于做页签操作、刷新页签、关闭页签、打开页签、修改页签等,它定义在`plugins/tab.ts`文件中,它有如下方法
|
||||
* 打开页签
|
||||
|
||||
```typescript
|
||||
// 打开页签
|
||||
proxy?.$tab.openPage('/system/user');
|
||||
// 打开页签并指定页签标题
|
||||
proxy?.$tab.openPage('/system/user', '用户管理');
|
||||
proxy?.$tab.openPage('/system/user', '用户管理').then(() => {
|
||||
// 执行结束的逻辑
|
||||
})
|
||||
```
|
||||
|
||||
* 修改页签
|
||||
|
||||
```typescript
|
||||
// 修改当前页签
|
||||
const obj = Object.assign({}, route, { title: '自定义标题' });
|
||||
proxy?.$tab.updatePage(obj);
|
||||
```
|
||||
* 关闭页签
|
||||
|
||||
```typescript
|
||||
// 关闭当前
|
||||
proxy?.$tab.closePage();
|
||||
// 关闭指定页签
|
||||
const obj = { path: "/system/user", name: "User" };
|
||||
proxy?.$tab.closePage(obj);
|
||||
|
||||
proxy?.$tab.closePage(obj).then(() => {
|
||||
// 执行结束的逻辑
|
||||
})
|
||||
```
|
||||
|
||||
* 刷新页签
|
||||
|
||||
```typescript
|
||||
// 刷新当前页签
|
||||
proxy?.$tab.refreshPage();
|
||||
|
||||
// 刷新指定页签
|
||||
const obj = { path: "/system/user", name: "User" };
|
||||
proxy?.$tab.refreshPage(obj);
|
||||
|
||||
proxy?.$tab.refreshPage(obj).then(() => {
|
||||
// 执行结束的逻辑
|
||||
})
|
||||
```
|
||||
|
||||
* 关闭所有页签
|
||||
|
||||
```typescript
|
||||
proxy?.$tab.closeAllPage();
|
||||
|
||||
proxy?.$tab.closeAllPage().then(() => {
|
||||
// 执行结束的逻辑
|
||||
})
|
||||
```
|
||||
|
||||
* 关闭左侧页签
|
||||
|
||||
```typescript
|
||||
// 关闭当前页签的左侧页签
|
||||
proxy?.$tab.closeLeftPage();
|
||||
|
||||
// 关闭指定页签的左侧页签
|
||||
const obj = { path: "/system/user", name: "User" };
|
||||
proxy?.$tab.closeLeftPage(obj);
|
||||
|
||||
proxy?.$tab.closeLeftPage(obj).then(() => {
|
||||
// 执行结束的逻辑
|
||||
})
|
||||
```
|
||||
|
||||
* 关闭右侧页签
|
||||
|
||||
```typescript
|
||||
// 关闭当前页签的右侧页签
|
||||
proxy?.$tab.closeRightPage();
|
||||
|
||||
// 关闭指定页签的右侧页签
|
||||
const obj = { path: "/system/user", name: "User" };
|
||||
proxy?.$tab.closeRightPage(obj);
|
||||
|
||||
proxy?.$tab.closeRightPage(obj).then(() => {
|
||||
// 执行结束的逻辑
|
||||
})
|
||||
```
|
||||
|
||||
* 关闭其他页签
|
||||
|
||||
```typescript
|
||||
proxy?.$tab.closeOtherPage();
|
||||
|
||||
const obj = { path: "/system/user", name: "User" };
|
||||
proxy?.$tab.closeOtherPage(obj);
|
||||
|
||||
proxy?.$tab.closeOtherPage(obj).then(() => {
|
||||
// 执行结束的逻辑
|
||||
})
|
||||
```
|
||||
|
||||
### $modal对象
|
||||
> `$modal`对象用于做消息提示、通知提示、对话框提醒、二次确认、遮罩等,它定义在`plugins/modal.ts`文件中,它有如下方法
|
||||
|
||||
* 提供成功、警告和错误等反馈信息
|
||||
|
||||
```typescript
|
||||
proxy?.$modal.msg("默认反馈");
|
||||
proxy?.$modal.msgError("错误反馈");
|
||||
proxy?.$modal.msgSuccess("成功反馈");
|
||||
proxy?.$modal.msgWarning("警告反馈");
|
||||
```
|
||||
|
||||
* 提供成功、警告和错误等提示信息
|
||||
|
||||
```typescript
|
||||
proxy?.$modal.alert("默认提示");
|
||||
proxy?.$modal.alertError("错误提示");
|
||||
proxy?.$modal.alertSuccess("成功提示");
|
||||
proxy?.$modal.alertWarning("警告提示");
|
||||
```
|
||||
|
||||
* 提供成功、警告和错误等通知信息
|
||||
|
||||
```typescript
|
||||
proxy?.$modal.notify("默认通知");
|
||||
proxy?.$modal.notifyError("错误通知");
|
||||
proxy?.$modal.notifySuccess("成功通知");
|
||||
proxy?.$modal.notifyWarning("警告通知");
|
||||
```
|
||||
|
||||
* 提供确认窗体信息
|
||||
|
||||
```typescript
|
||||
proxy?.$modal.confirm('确认信息').then(function() {
|
||||
...
|
||||
}).then(() => {
|
||||
...
|
||||
}).catch(() => {});
|
||||
```
|
||||
|
||||
* 提供遮罩层信息
|
||||
|
||||
```typescript
|
||||
// 打开遮罩层
|
||||
proxy?.$modal.loading("正在导出数据,请稍后...");
|
||||
|
||||
// 关闭遮罩层
|
||||
proxy?.$modal.closeLoading();
|
||||
```
|
||||
|
||||
### $auth对象
|
||||
> `$auth`对象用于验证用户是否拥有某(些)权限或角色,它定义在`plugins/auth.ts`文件中,它有如下方法
|
||||
|
||||
* 验证用户权限
|
||||
|
||||
```typescript
|
||||
// 验证用户是否具备某权限
|
||||
proxy?.$auth.hasPermi("system:user:add");
|
||||
// 验证用户是否含有指定权限,只需包含其中一个
|
||||
proxy?.$auth.hasPermiOr(["system:user:add", "system:user:update"]);
|
||||
// 验证用户是否含有指定权限,必须全部拥有
|
||||
proxy?.$auth.hasPermiAnd(["system:user:add", "system:user:update"]);
|
||||
```
|
||||
|
||||
* 验证用户角色
|
||||
|
||||
```typescript
|
||||
// 验证用户是否具备某角色
|
||||
proxy?.$auth.hasRole("admin");
|
||||
// 验证用户是否含有指定角色,只需包含其中一个
|
||||
proxy?.$auth.hasRoleOr(["admin", "common"]);
|
||||
// 验证用户是否含有指定角色,必须全部拥有
|
||||
proxy?.$auth.hasRoleAnd(["admin", "common"]);
|
||||
```
|
||||
|
||||
### $cache对象
|
||||
> `$cache`对象用于处理缓存。我们并不建议您直接使用`sessionStorage`或`localStorage`(vue3版本推荐使用useStorage),因为项目的缓存策略可能发生变化,通过`$cache`对象做一层调用代理则是一个不错的选择。`$cache`提供`session`和`local`两种级别的缓存,如下:
|
||||
|
||||
| 对象名称 | 缓存类型 |
|
||||
| -------- | ---------------------------------- |
|
||||
| session | 会话级缓存,通过sessionStorage实现 |
|
||||
| local | 本地级缓存,通过localStorage实现 |
|
||||
|
||||
|
||||
**示例**
|
||||
|
||||
```typescript
|
||||
// local 普通值
|
||||
proxy?.$cache.local.set('key', 'local value')
|
||||
console.log(proxy?.$cache.local.get('key')) // 输出'local value'
|
||||
|
||||
// session 普通值
|
||||
proxy?.$cache.session.set('key', 'session value')
|
||||
console.log(proxy?.$cache.session.get('key')) // 输出'session value'
|
||||
|
||||
// local JSON值
|
||||
proxy?.$cache.local.setJSON('jsonKey', { localProp: 1 })
|
||||
console.log(proxy?.$cache.local.getJSON('jsonKey')) // 输出'{localProp: 1}'
|
||||
|
||||
// session JSON值
|
||||
proxy?.$cache.session.setJSON('jsonKey', { sessionProp: 1 })
|
||||
console.log(proxy?.$cache.session.getJSON('jsonKey')) // 输出'{sessionProp: 1}'
|
||||
|
||||
// 删除值
|
||||
proxy?.$cache.local.remove('key')
|
||||
proxy?.$cache.session.remove('key')
|
||||
```
|
||||
|
||||
### $download对象
|
||||
|
||||
> `$download`对象用于文件下载,它定义在`plugins/download.ts`文件中,它有如下方法
|
||||
|
||||
* 通过ossId从存储中下载文件
|
||||
|
||||
``` typescript
|
||||
// 默认下载方法
|
||||
proxy?.$download.oss(ossId);
|
||||
```
|
||||
|
||||
* 根据请求地址下载zip包
|
||||
|
||||
```typescript
|
||||
const url = '/tool/gen/batchGenCode?tables=' + tableNames;
|
||||
const name = 'ruoyi';
|
||||
|
||||
// 默认方法
|
||||
proxy?.$download.zip(url, name);
|
||||
```
|
||||
@@ -0,0 +1,55 @@
|
||||
# 组件使用
|
||||
- - -
|
||||
|
||||
vue 注册组件的两种方式
|
||||
在 `@/components` 下创建的.vue文件自动为全局组件,可直接在任意位置使用。
|
||||
|
||||
### 局部注册
|
||||
在对应页使用`components`注册组件。
|
||||
```typescript
|
||||
<script setup lang=ts>
|
||||
import ComponentA from './ComponentA.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ComponentA />
|
||||
</template>
|
||||
```
|
||||
|
||||
### 全局注册
|
||||
我们可以使用[ Vue 应用实例](https://cn.vuejs.org/guide/essentials/application.html)的 `.component()` 方法,让组件在当前 Vue 应用中全局可用。
|
||||
```typescript
|
||||
import { createApp } from 'vue'
|
||||
|
||||
const app = createApp({})
|
||||
|
||||
app.component(
|
||||
// 注册的名字
|
||||
'MyComponent',
|
||||
// 组件的实现
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
)
|
||||
```
|
||||
如果使用单文件组件,你可以注册被导入的 `.vue` 文件:
|
||||
```typescript
|
||||
import MyComponent from './App.vue'
|
||||
|
||||
app.component('MyComponent', MyComponent)
|
||||
```
|
||||
`.component()` 方法可以被链式调用:
|
||||
```typescript
|
||||
app
|
||||
.component('ComponentA', ComponentA)
|
||||
.component('ComponentB', ComponentB)
|
||||
.component('ComponentC', ComponentC)
|
||||
```
|
||||
全局注册的组件可以在此应用的任意组件的模板中使用:
|
||||
```Typescript
|
||||
// 这在当前应用的任意组件中都可用
|
||||
<ComponentA/>
|
||||
<ComponentB/>
|
||||
<ComponentC/>
|
||||
```
|
||||
所有的子组件也可以使用全局注册的组件,这意味着这三个组件也都可以在彼此内部使用。
|
||||
@@ -0,0 +1,4 @@
|
||||
# 内容复制
|
||||
- - -
|
||||
|
||||
文档建设中
|
||||
@@ -0,0 +1,16 @@
|
||||
# 开发规范
|
||||
- - -
|
||||
|
||||
### 新增view
|
||||
> 在`@/views`文件下创建对应的文件夹,一般性一个路由对应一个文件, 该模块下的功能就建议在本文件夹下创建一个新文件夹,各个功能模块维护自己的`utils`或`components`组件。
|
||||
|
||||
### 新增api
|
||||
> 在`@/api`文件夹下创建本模块对应的api服务。
|
||||
> 在api服务同级创建`types.ts`类型声明文件。
|
||||
|
||||
### 新增组件
|
||||
> 在全局的`@/components`写一些全局的组件,如富文本,各种搜索组件,封装的分页组件等等能被公用的组件。 每个页面或者模块特定的业务组件则会写在当前`@/views`下面。
|
||||
如:`@/views/system/user/components/xxx.vue`。这样拆分大大减轻了维护成本。
|
||||
|
||||
### 新增样式
|
||||
> 页面的样式和组件是一个道理,全局的`@/style`放置一下全局公用的样式,每一个页面的样式就写在当前 views下面,请记住加上scoped 就只会作用在当前组件内了,避免造成全局的样式污染。
|
||||
@@ -0,0 +1,4 @@
|
||||
# 使用字典
|
||||
- - -
|
||||
|
||||
文档建设中
|
||||
@@ -0,0 +1,4 @@
|
||||
# 异常处理
|
||||
- - -
|
||||
|
||||
文档建设中
|
||||
@@ -0,0 +1,4 @@
|
||||
# 使用图标
|
||||
- - -
|
||||
|
||||
文档建设中
|
||||
@@ -0,0 +1,4 @@
|
||||
# 页签缓存
|
||||
- - -
|
||||
|
||||
文档建设中
|
||||
@@ -0,0 +1,4 @@
|
||||
# 使用参数
|
||||
- - -
|
||||
|
||||
文档建设中
|
||||
@@ -0,0 +1,4 @@
|
||||
# 权限使用
|
||||
- - -
|
||||
|
||||
文档建设中
|
||||
@@ -0,0 +1,65 @@
|
||||
# 请求流程
|
||||
- - -
|
||||
|
||||
### 交互流程
|
||||
一个完整的前端UI交互到服务器端处理流程是这样的:
|
||||
|
||||
1. UI 组件交互操作;
|
||||
2. 调用统一管理的 api service 请求函数;
|
||||
3. 使用封装的 request.js 发送请求;
|
||||
4. 获取服务端返回;
|
||||
5. 更新 data;
|
||||
|
||||
为了方便管理维护,统一的请求处理都放在`@/src/api`文件夹中,并且一般按照`model`维度进行拆分文件,如:
|
||||
```
|
||||
api/
|
||||
system/
|
||||
user/
|
||||
index.ts
|
||||
types.ts
|
||||
role/
|
||||
index.ts
|
||||
types.ts
|
||||
monitor/
|
||||
operlog/
|
||||
index.ts
|
||||
types.ts
|
||||
logininfor/
|
||||
index.ts
|
||||
types.ts
|
||||
...
|
||||
```
|
||||
> **提示**
|
||||
> 其中`@/src/utils/request.ts`是基于 axios 的封装,便于统一处理 POST,GET 等请求参数,请求头,以及错误提示信息等。 它封装了全局request拦截器、response拦截器、统一的错误处理、统一做了超时处理、baseURL设置等。
|
||||
|
||||
### 请求示例
|
||||
```typescript
|
||||
// @/api/system/user/index.ts
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { UserQuery, UserVO } from './types';
|
||||
|
||||
export const listUser = (query: UserQuery): AxiosPromise<UserVO[]> => {
|
||||
return request({
|
||||
url: '/system/user/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
// @/views/system/user/index.vue
|
||||
import api from '@/api/system/user';
|
||||
const res = await api.listUser(proxy?.addDateRange(queryParams.value, dateRange.value));
|
||||
```
|
||||
> **提示**
|
||||
> 如果有不同的`baseURL`,直接通过覆盖的方式,让它具有不同的`baseURL`。
|
||||
> ```typescript
|
||||
> export const listUser = (query: UserQuery): AxiosPromise<UserVO[]> => {
|
||||
> return request({
|
||||
> url: '/system/user/list',
|
||||
> method: 'get',
|
||||
> params: query,
|
||||
> baseURL: process.env.BASE_API
|
||||
> });
|
||||
> };
|
||||
> ```
|
||||
@@ -0,0 +1,82 @@
|
||||
# 路由使用
|
||||
- - -
|
||||
|
||||
框架的核心是通过路由自动生成对应导航,所以除了路由的基本配置,还需要了解框架提供了哪些配置项。
|
||||
### 路由配置
|
||||
```typescript
|
||||
// 当设置 true 的时候该路由不会在侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1
|
||||
hidden: true // (默认 false)
|
||||
|
||||
//当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
|
||||
redirect: 'noRedirect'
|
||||
|
||||
// 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面
|
||||
// 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面
|
||||
// 若你想不管路由下面的 children 声明的个数都显示你的根路由
|
||||
// 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由
|
||||
alwaysShow: true
|
||||
|
||||
name: 'router-name' // 设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题
|
||||
query: '{"id": 1, "name": "ry"}' // 访问路由的默认传递参数
|
||||
roles: ['admin', 'common'] // 访问路由的角色权限
|
||||
permissions: ['a:a:a', 'b:b:b'] // 访问路由的菜单权限
|
||||
|
||||
meta: {
|
||||
title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字
|
||||
icon: 'svg-name' // 设置该路由的图标,支持 svg-class,也支持 el-icon-x element-ui 的 icon
|
||||
noCache: true // 如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
|
||||
breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示(默认 true)
|
||||
affix: true // 如果设置为true,它则会固定在tags-view中(默认 false)
|
||||
|
||||
// 当路由设置了该属性,则会高亮相对应的侧边栏。
|
||||
// 这在某些场景非常有用,比如:一个文章的列表页路由为:/article/list
|
||||
// 点击文章进入文章详情页,这时候路由为/article/1,但你想在侧边栏高亮文章列表的路由,就可以进行如下设置
|
||||
activeMenu: '/article/list'
|
||||
}
|
||||
```
|
||||
**普通示例**
|
||||
```json
|
||||
{
|
||||
path: '/system/test',
|
||||
component: Layout,
|
||||
redirect: 'noRedirect',
|
||||
hidden: false,
|
||||
alwaysShow: true,
|
||||
meta: { title: '系统管理', icon : "system" },
|
||||
children: [{
|
||||
path: 'index',
|
||||
component: (resolve) => require(['@/views/index'], resolve),
|
||||
name: 'Test',
|
||||
meta: {
|
||||
title: '测试管理',
|
||||
icon: 'user'
|
||||
}
|
||||
}]
|
||||
}
|
||||
```
|
||||
**外链示例**
|
||||
```json
|
||||
{
|
||||
path: 'http://ruoyi.vip',
|
||||
meta: { title: '若依官网', icon : "guide" }
|
||||
}
|
||||
```
|
||||
### 静态路由
|
||||
代表那些不需要动态判断权限的路由,如登录页、404、等通用页面,在`@/router/index.ts`配置对应的公共路由。
|
||||
### 动态路由
|
||||
代表那些需要根据用户动态判断权限并通过addRoutes动态添加的页面,在`@/store/modules/permission.ts`加载后端接口路由配置。
|
||||
> **提示**
|
||||
> * 动态路由可以在系统管理-菜单管理进行新增和修改操作,前端加载会自动请求接口获取菜单信息并转换成前端对应的路由。
|
||||
> * 动态路由在生产环境下会默认使用路由懒加载,实现方式参考loadView方法的判断。
|
||||
### 常用方法
|
||||
想要跳转到不同的页面,使用`router.push`方法
|
||||
```Typescript
|
||||
const router = useRouter();
|
||||
router.push({ path: "/system/user" });
|
||||
```
|
||||
跳转页面并设置请求参数,使用`query`属性
|
||||
```Typescript
|
||||
const router = useRouter();
|
||||
router.push({ path: "/system/user", query: {id: "1", name: "若依"} });
|
||||
```
|
||||
更多使用可以参考[vue-router](https://router.vuejs.org/zh/)官方文档。
|
||||
53
ruoyi-admin/src/main/resources/static/plus-ui/home.md
Normal file
53
ruoyi-admin/src/main/resources/static/plus-ui/home.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 项目简介
|
||||
|
||||
---
|
||||
|
||||
## 平台简介
|
||||
|
||||
- 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。
|
||||
- 配套后端代码仓库地址
|
||||
- [RuoYi-Vue-Plus 5.X(注意版本号)](https://gitee.com/dromara/RuoYi-Vue-Plus)
|
||||
- [RuoYi-Cloud-Plus 2.X(注意版本号)](https://gitee.com/dromara/RuoYi-Cloud-Plus)
|
||||
|
||||
## 前端运行
|
||||
|
||||
```bash
|
||||
# 克隆项目
|
||||
git clone https://gitee.com/JavaLionLi/plus-ui.git
|
||||
|
||||
# 安装依赖
|
||||
npm install --registry=https://registry.npmmirror.com
|
||||
|
||||
# 启动服务
|
||||
npm run dev
|
||||
|
||||
# 推荐使用yarn或pnpm包管理工具
|
||||
# 构建测试环境 yarn build:stage
|
||||
# 构建生产环境 yarn build:prod
|
||||
# 前端访问地址 http://localhost:80
|
||||
```
|
||||
|
||||
## 后端改造
|
||||
|
||||
参考后端代码内 `ruoyi-gen/resources/vm/vue/v3/readme.txt` 说明
|
||||
|
||||
## 内置功能
|
||||
|
||||
1. 租户管理:配置系统租户,支持 SaaS 场景下的多租户功能。
|
||||
2. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
|
||||
3. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
|
||||
4. 岗位管理:配置系统用户所属担任职务。
|
||||
5. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
|
||||
6. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
|
||||
7. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
|
||||
8. 参数管理:对系统动态配置常用参数。
|
||||
9. 通知公告:系统通知公告信息发布维护。
|
||||
10. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
||||
11. 登录日志:系统登录日志记录查询包含登录异常。
|
||||
12. 在线用户:当前系统中活跃用户状态监控。
|
||||
13. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
|
||||
14. 代码生成:前后端代码的生成(java、html、xml、sql)支持 CRUD 下载 。
|
||||
15. 系统接口:根据业务代码自动生成相关的 api 接口文档。
|
||||
16. 服务监控:监视当前系统 CPU、内存、磁盘、堆栈等相关信息。
|
||||
17. 缓存监控:对系统的缓存信息查询,命令统计等。
|
||||
18. 在线构建器:拖动表单元素生成相应的 HTML 代码。(TS 版本正在开发中。)
|
||||
34
ruoyi-admin/src/main/resources/static/questions/_sidebar.md
Normal file
34
ruoyi-admin/src/main/resources/static/questions/_sidebar.md
Normal file
@@ -0,0 +1,34 @@
|
||||
<!-- _sidebar.md -->
|
||||
- **特别赞助**
|
||||
- [](http://ccflow.org/?frm=ryPlus)
|
||||
- [](http://www.shuduokeji.com)
|
||||
- [](https://www.jnpfsoft.com/index.html?from=plus-doc)
|
||||
|
||||
|
||||
|
||||
* **常见问题**
|
||||
* [Lombok注解爆红](/questions/lombok.md)
|
||||
* [如何使用Tomcat](/questions/use_tomcat.md)
|
||||
* [如何使用druid连接池](/questions/use_druid.md)
|
||||
* [vue与boot整合部署](/questions/deploy_vue.md)
|
||||
* [导入excel实体类为空](/questions/import_excel.md)
|
||||
* [如何同步项目更新](/questions/synchronous_update.md)
|
||||
* [ParseException SQL解析异常](/questions/parse_exception.md)
|
||||
* [swagger相关问题](/questions/swagger.md)
|
||||
* [实体bean为空问题](/questions/bean_null.md)
|
||||
* [Redis 报错 Permission denied](/questions/permission_denied.md)
|
||||
* [关于HTTPS配置](/questions/https_config.md)
|
||||
* [放行接口提示认证失败](/questions/identify_fail.md)
|
||||
* [打包jar运行报错](/questions/jar_run_fail.md)
|
||||
* [如何指定dubbo注册ip](/questions/dubbo_ip.md)
|
||||
* [Sentinel页面404问题](/questions/sentinel_404.md)
|
||||
* [无法读取nacos配置](/questions/nacos_read_fail.md)
|
||||
* [接口文档对接knife4j](/questions/kinfe4j.md)
|
||||
* [不支持ST请求](/questions/st_not_support.md)
|
||||
* [Only one connection receive subscriber allowed](/questions/only_one_subscriber.md)
|
||||
* [nacos 报错 The Raft Group [naming_instance_metadata]](/questions/nacos_naming_instance_metadata.md)
|
||||
* [unable to read meta-data for class xxx](/questions/read_metadata.md)
|
||||
* [JCE cannot authenticate the provider BC](/questions/jce_cannot.md)
|
||||
* [关于请求响应参数解密](/questions/api_encrypt.md)
|
||||
* [关于登录调试步骤](/questions/login_step.md)
|
||||
* [如何对接国产数据库](/questions/domestic_databases.md)
|
||||
148
ruoyi-admin/src/main/resources/static/questions/api_encrypt.md
Normal file
148
ruoyi-admin/src/main/resources/static/questions/api_encrypt.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# 关于请求响应参数解密
|
||||
---
|
||||
## 1:前端加密请求
|
||||
|
||||

|
||||
|
||||
通过控制台获取加密结果:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
加密密钥:
|
||||
|
||||
```
|
||||
PAg/fZzpV/cz0T1fMUJMJo/LEZvwVLb4bZgtCHkbB6FQAJWlLm/RLKtQ5fOo1blMjAkY+9ryWhsAfCqoMPTU4w==
|
||||
```
|
||||
|
||||
请求参数加密结果:
|
||||
|
||||
```
|
||||
F+Qxq6PzShcudDsUZHhp50lA67eBeTe63x5uGbdm/HJGgcDmjKncUk5VQm0evD8pz1sbmCbmmSl3X1D07K/qgHvP1YhjYSRBJf/M0GTfMkfOZqIkOtvfE5Z6fSFd8RYf6ji/qYxAmCiRmP/uADyJUAoBY1gMi5+zuvyHH3In/FyoFeD0rmJWvO4o4fn3n5GElHMWbP0O/HWPfgHFfg1F7bZQPuf4zAuDKQIqUG3jJTem3O97kAbTWw6lSSuYi1/8tV4cE9rq8SMSjx36/ZLSog==
|
||||
```
|
||||
|
||||
### 解密步骤
|
||||
|
||||
1. 使用配置文件私钥对加密密钥解密
|
||||
|
||||
```java
|
||||
// 参数说明:
|
||||
// requestKey:即请求标头加密密钥
|
||||
// privateKey:application.yml 配置文件私钥
|
||||
String decryptByRsa = EncryptUtils.decryptByRsa(requestKey, privateKey);
|
||||
```
|
||||
|
||||
2. 对步骤一结果进行 Base64 解密,得到 AES 加密密钥
|
||||
|
||||
```java
|
||||
String aesPassword = EncryptUtils.decryptByBase64(decryptByRsa);
|
||||
```
|
||||
|
||||
3. 使用步骤二得到的密钥,对请求参数进行解密
|
||||
|
||||
```java
|
||||
String decryptBody = EncryptUtils.decryptByAes(requestBody, aesPassword);
|
||||
```
|
||||
|
||||
得到解密请求参数(已格式化):
|
||||
|
||||
```json
|
||||
{
|
||||
"tenantId": "000000",
|
||||
"username": "admin",
|
||||
"password": "admin123",
|
||||
"rememberMe": false,
|
||||
"uuid": "a39962b22c874f60872ef5db1cd811f5",
|
||||
"code": "5",
|
||||
"clientId": "e5cd7e4891bf95d1d19206ce24a7b32e",
|
||||
"grantType": "password"
|
||||
}
|
||||
```
|
||||
|
||||
|参数名|说明|
|
||||
|---|---|
|
||||
|tenantId| 租户id |
|
||||
|username| 用户名 |
|
||||
|password| 密码 |
|
||||
|rememberMe| 记住密码 |
|
||||
|uuid| - |
|
||||
|code| 验证码结果 |
|
||||
|clientId| 客户端id(表 sys_client) |
|
||||
|grantType| 授权类型(表 sys_client) |
|
||||
|
||||
## 2:后端加密响应
|
||||
|
||||
对请求使用了注解 `@ApiEncrypt(response = true)`
|
||||
|
||||

|
||||
|
||||
通过控制台获取加密结果:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
加密密钥:
|
||||
|
||||
```
|
||||
MXnKYnXcXeFYWKZg8utuhDtbz54cPDcov11E1KT5l19/vMt37d4NhzzwBWnqug72SOgOK5URGaWPJSs9VdaP0Q==
|
||||
```
|
||||
|
||||
响应参数加密结果:
|
||||
|
||||
```
|
||||
70 O63EMmwvbAyWPqDDmVOGTy+BOQnIVgKInMFNRtp8Zwzs8DEL20VgL2IslYrL8bc1u7lPhYNU/6 Q3iTYebm4EokwiG+styaT+LO3M9bUimggoAGpBTW8gCRF/34 kJaOITSRqYqYcXIJKn73+Gqn7jevyKUHyRXog/3 q/PlBdmUjNiB4gtxlOO/Vm+4 o+0 W4jcEe0xwwzV91+Ze3S6Eu/1 XN21g0iOsYT34emv/vhd9Hy3p5LfJlAHvn96x/c3MQBQUU32uM3Vkk3o6IpVHjJljE64gnGximSwB9vrmMA21xX+fq9HYioumknmDDbaY/JAKh32CDgn5M5hdaIklf08sU38r1IyvipySzrHX+ci9GmOZhP2ttCtoZ7SGvFFbNEuyojssxwxXEmJHAsG/OhIAeRXMUr3+dzDJ++XvvMuMgNJR0BMldNydFAjNOQEszgcVM1QEGwxfW5rElW8VxQaaqPyDATX+y2JrK1vdKxxdI/hF5dGpQMdU4FAEhHIftoIbD/FH4XcWJamZjJpbVtZvTkFYpbhiU7sz9MICSuKwaoSFJ8JGANc0bDdVoWpA8sXi7a27IM0pDzk9gD/FADcFGHXxPYUhENkXiUcnmg5LSdigiY4J6HrqEJdH6zNSwoGubcsXhiPdlB3V0DqcLAHFt+GYj5lcxZeqUAmixGVGCV7gSBWNiyo9/NnXcynA/EIlV3OZIvgzjWxiKzcVJ1HOKoXGEcg3Q54QNh5pCqEa7AtqVkKO7/Ffgg8nSEeCdJPzTV7zmr3n94Hn671OL8A==
|
||||
```
|
||||
|
||||
### 解密步骤
|
||||
|
||||
1. 使用前端配置文件私钥对加密密钥解密
|
||||
|
||||
```java
|
||||
// 参数说明:
|
||||
// responseKey:即响应标头加密密钥
|
||||
// privateKey:前端 .env.development | .env.production 配置文件私钥,注意和后端私钥区分
|
||||
String decryptByRsa = EncryptUtils.decryptByRsa(responseKey, privateKey);
|
||||
```
|
||||
|
||||
2. 对步骤一结果进行 Base64 解密,得到 AES 加密密钥
|
||||
|
||||
```java
|
||||
String aesPassword = EncryptUtils.decryptByBase64(decryptByRsa);
|
||||
```
|
||||
|
||||
3. 使用步骤二得到的密钥,对响应参数进行解密
|
||||
|
||||
```java
|
||||
String decryptBody = EncryptUtils.decryptByAes(responseBody, aesPassword);
|
||||
```
|
||||
|
||||
得到解密请求参数(已格式化):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"scope": null,
|
||||
"openid": null,
|
||||
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJjOVNWU1hRRVY4QVhFRkt4b2FrbndSSWxPczd4ajdRZCIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MTAzLCJkZXB0TmFtZSI6IueglOWPkemDqOmXqCJ9.YuaXPu6eTzJVkLyQC3ekzmPS_jXp50ykaIB2nWy11qM",
|
||||
"refresh_token": null,
|
||||
"expire_in": 604799,
|
||||
"refresh_expire_in": null,
|
||||
"client_id": "e5cd7e4891bf95d1d19206ce24a7b32e"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|参数名|说明|
|
||||
|---|---|
|
||||
|scope| 令牌权限 |
|
||||
|openid| 用户 openid |
|
||||
|access_token| 授权令牌 |
|
||||
|refresh_token| 刷新令牌 |
|
||||
|expire_in| 授权令牌 access_token 的有效期 |
|
||||
|refresh_expire_in| 刷新令牌 refresh_token 的有效期 |
|
||||
|clientId| 客户端id(表 sys_client) |
|
||||
10
ruoyi-admin/src/main/resources/static/questions/bean_null.md
Normal file
10
ruoyi-admin/src/main/resources/static/questions/bean_null.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# 实体bean为空问题
|
||||
- - -
|
||||
### 问题排查
|
||||
|
||||
检查是否存在 `链式调用` 注解 `@Accessors(chain = true)` 删除即可
|
||||
|
||||
### 原因
|
||||
java 规范 set 返回值为 `void` 链式调用 set 返回值为 `this`<br>
|
||||
故多数框架底层使用 jdk 工具导致找不到 set 方法<br>
|
||||
例如: `easyexcel` `cglib` `mybatis` 等
|
||||
@@ -0,0 +1,13 @@
|
||||
# 关于vue与boot整合部署
|
||||
- - -
|
||||
* [前端静态资源如何整合到后端访问](https://doc.ruoyi.vip/ruoyi-vue/other/faq.html#前端静态资源如何整合到后端访问)
|
||||
|
||||
3.X 需在 `pom.xml` 增加资源过滤排除
|
||||
|
||||
```xml
|
||||
<resource>
|
||||
<directory>src/main/resources/页面目录</directory>
|
||||
<!-- 关闭过滤 -->
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
```
|
||||
@@ -0,0 +1,41 @@
|
||||
# 如何对接国产数据库
|
||||
|
||||
> 1. 框架采用 mybatis-plus 几乎支持大部分市面上的数据库且框架内几乎没有sql语句存在
|
||||
<br>
|
||||
所以不用担心兼容性问题(顶多就是有一些关键字什么的 对接很简单)
|
||||
<br>
|
||||
> 2. 国产数据库大多都兼容主流三大数据库 mysql oracle postgresql
|
||||
<br>
|
||||
例如 达梦兼容oracle 人大金仓兼容mysql oceanbase兼容mysql 等等
|
||||
|
||||
# 对接方式
|
||||
|
||||
### 这里用 `达梦` 数据库为例
|
||||
|
||||
1.首先增加 jdbc依赖包 `vue版本在ruoyi-admin模块下` `cloud版本在ruoyi-common-mybatis模块下`
|
||||
|
||||

|
||||
|
||||
2.在配置文件yml内配置数据库连接
|
||||
|
||||

|
||||
|
||||
3.sql脚本使用框架内自带的sql文件根据兼容的数据库模式 例如 达梦用oracle的sql脚本
|
||||
|
||||

|
||||
|
||||
4.在代码生成器内 增加对应的数据库生成器依赖 代码生成器使用 anyline 支持几百种数据库只需要增加对应的依赖即可
|
||||
|
||||

|
||||
|
||||
这样基本就完成了所有需要做的事可以尝试启动项目了
|
||||
|
||||
5.如果项目启或者运行动过程中有sql报错 不要慌基本上都是一些关键字引起的
|
||||
<br>
|
||||
例如 达梦内的`domain`就是关键字 在我们的`SysOssConfig`表内使用`domain`进行自定义的域名存储
|
||||
<br>
|
||||
我们只需要在`SysOssConfig`实体类的`domain`属性增加一个注解即可解决此问题
|
||||
<br>
|
||||
**注意: 各种数据库处理关键字的标识符不一样注意替换**
|
||||
|
||||

|
||||
18
ruoyi-admin/src/main/resources/static/questions/dubbo_ip.md
Normal file
18
ruoyi-admin/src/main/resources/static/questions/dubbo_ip.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# 如何指定dubbo注册ip
|
||||
- - -
|
||||
## 重点说明
|
||||
以下方法指定IP必须是本地有网卡的自己可以访问的IP 不可以随意乱写<br>
|
||||
(云服务器公网IP是没有网卡的)
|
||||
|
||||
## 在`nacos`指定协议IP地址(全局生效)
|
||||
```yml
|
||||
dubbo:
|
||||
protocol:
|
||||
# 指定dubbo协议注册ip
|
||||
host: 192.168.0.100
|
||||
```
|
||||
|
||||
## docker指定dubbo环境变量(单服务生效)
|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# 关于HTTPS配置
|
||||
- - -
|
||||
### 后端 HTTPS 改造
|
||||
|
||||
将申请的 `https` 证书放置到 `nginx` 对应目录内<br>
|
||||
根据框架 `nginx https` 示例 更改后端代理为 `https`<br>
|
||||
|
||||

|
||||
|
||||
### 监控中心 与 任务调度中心 改造
|
||||
|
||||
`监控中心` 与 `任务调度中心` 属于系统管控服务<br>
|
||||
应在内网使用 不应该暴漏到外网 也无需配置 `https`
|
||||
|
||||
更改 `系统 -> 菜单管理 -> 监控中心 与 任务调度中心` 菜单配置<br>
|
||||
将其改为 `外链访问` 访问路径为 **注意: 如果是外网使用 url需配置为 http://外网ip:端口**
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
`nginx` 配置 `独立的端口` 进行反向代理即可访问(代理编写方式参考后端反向代理)
|
||||
|
||||
### Minio https 改造
|
||||
|
||||
下方链接包含 minio+nginx 与 minio本身配置https 两种方案<br>
|
||||
[终极版minio配置https教程](https://blog.csdn.net/Michelle_Zhong/article/details/126484358)
|
||||
@@ -0,0 +1,10 @@
|
||||
# 放行接口提示认证失败
|
||||
- - -
|
||||
## 可能的原因
|
||||
接口放行后不需要token即可访问<br>
|
||||
但是没有token也就无法获取用户信息与鉴权
|
||||
|
||||
## 解决方案
|
||||
删除接口上的鉴权注解<br>
|
||||
删除接口内获取用户信息功能<br>
|
||||
删除数据库实体类 自动注入 `createBy` `updateBy` 因为会获取用户数据
|
||||
@@ -0,0 +1,4 @@
|
||||
# 关于导入excel实体类为空
|
||||
- - -
|
||||
* 禁止在导入实体使用 `lombok` 链式调用注解 `@Accessors(chain = true)`
|
||||
* 会导致找不到 `set` 方法无法注入内容
|
||||
@@ -0,0 +1,12 @@
|
||||
# 打包jar运行报错问题
|
||||
- - -
|
||||
|
||||
**常见于 windows 平台以命令方式启动**
|
||||
|
||||
windows 平台默认编码为 GBK 所以读取到所有的配置都是乱码
|
||||
|
||||
## 解决方案
|
||||
|
||||
需要在命令增加 `-Dfile.encoding=utf-8` 指定文件编码
|
||||
|
||||
例如: `java -Dfile.encoding=utf-8 -jar ruoyi-xxx.jar`
|
||||
@@ -0,0 +1,3 @@
|
||||
# 问题说明 由于 OracleJDK 强校验加密证书导致
|
||||
|
||||
解决方案 禁止使用 oraclejdk 更换为其他例如 openjdk
|
||||
66
ruoyi-admin/src/main/resources/static/questions/kinfe4j.md
Normal file
66
ruoyi-admin/src/main/resources/static/questions/kinfe4j.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# 对接前声明
|
||||
|
||||
经常有小伙伴希望可以对接 knife4j
|
||||
|
||||
那么这里将介绍如何使用 框架生成的 openapi 对接 knife4j
|
||||
|
||||
# 如何对接
|
||||
|
||||
**重点声明: 本框架生成标准openapi结构 如对接后遇到不好用等问题 皆与本框架无关**
|
||||
|
||||
knife4j 本身提供了独立的文档中间件 可以零成本的介入 openapi
|
||||
|
||||
文档地址: https://doc.xiaominfo.com/docs/middleware-sources
|
||||
|
||||
**注意: 此组件应单独搞一个boot项目 不要往框架里做任何代码上的更改**
|
||||
|
||||
使用文档提供的 Cloud 模式 对接咱们框架的 openapi 地址即可完成对接
|
||||
|
||||

|
||||
|
||||
vue版本对接配置如下:
|
||||
|
||||
```yml
|
||||
knife4j:
|
||||
enable-aggregation: true
|
||||
cloud:
|
||||
enable: true
|
||||
routes:
|
||||
- name: 演示模块
|
||||
uri: localhost:8080
|
||||
location: /v3/api-docs/1.演示模块
|
||||
- name: 系统模块
|
||||
uri: localhost:8080
|
||||
location: /v3/api-docs/2.系统模块
|
||||
- name: 代码生成模块
|
||||
uri: localhost:8080
|
||||
location: /v3/api-docs/3.代码生成模块
|
||||
```
|
||||
|
||||
cloud版本对接配置如下:
|
||||
|
||||
```yml
|
||||
knife4j:
|
||||
enable-aggregation: true
|
||||
cloud:
|
||||
enable: true
|
||||
routes:
|
||||
- name: 演示模块
|
||||
uri: localhost:8080
|
||||
location: /demo/v3/api-docs
|
||||
- name: 认证服务
|
||||
uri: localhost:8080
|
||||
location: /auth/v3/api-docs
|
||||
- name: 资源服务
|
||||
uri: localhost:8080
|
||||
location: /resource/v3/api-docs
|
||||
- name: 系统服务
|
||||
uri: localhost:8080
|
||||
location: /system/v3/api-docs
|
||||
- name: 监控服务
|
||||
uri: localhost:8080
|
||||
location: /monitor/v3/api-docs
|
||||
- name: 代码生成服务
|
||||
uri: localhost:8080
|
||||
location: /gen/v3/api-docs
|
||||
```
|
||||
@@ -0,0 +1,69 @@
|
||||
# 关于登录调试步骤
|
||||
|
||||
## 1:关闭 api 接口加密
|
||||
|
||||
1. 修改后端配置文件 `application.yml`
|
||||
|
||||

|
||||
|
||||
2. 修改前端配置文件 `.env.development` | `.env.production`
|
||||
|
||||

|
||||
|
||||
## 2:登录参数
|
||||
|
||||

|
||||
|
||||
|参数名|说明|
|
||||
|---|---|
|
||||
|tenantId| 租户id |
|
||||
|username| 用户名 |
|
||||
|password| 密码 |
|
||||
|rememberMe| 记住密码 |
|
||||
|uuid| - |
|
||||
|code| 验证码结果 |
|
||||
|clientId| 客户端id(表 sys_client) |
|
||||
|grantType| 授权类型(表 sys_client) |
|
||||
|
||||
## 3:使用接口文档调试
|
||||
|
||||
### 3.1:使用接口文档请求
|
||||
|
||||
1. 配置接口文档([参考文档](/ruoyi-vue-plus/framework/association/doc))
|
||||
2. 请求接口 `http://localhost:8080/auth/login`
|
||||
|
||||

|
||||
|
||||
### 3.2:使用 idea 请求
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### 3.3:获取验证码以及 uuid
|
||||
|
||||
!> 验证码以及 uuid 获取方式: Redis | 控制台
|
||||
|
||||
方式一、Redis:
|
||||
|
||||

|
||||
|
||||
> **如果没有验证码相关 key,说明已经过期被清理了,去前端页面刷新一下即可。**
|
||||
|
||||
方式二、控制台:
|
||||
|
||||

|
||||
|
||||
### 3.4:关闭验证码
|
||||
|
||||
如果嫌验证码太麻烦,可以关闭,修改后端配置文件 `application.yml`
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
请求参数:
|
||||
|
||||

|
||||
@@ -0,0 +1,4 @@
|
||||
# 关于lombok注解爆红
|
||||
- - -
|
||||
* 已知 lombok 插件与 idea中文插件 存在兼容性问题
|
||||
* 移除中文插件或手动关闭idea检查
|
||||
@@ -0,0 +1,35 @@
|
||||
# nacos 报错 The Raft Group [naming_instance_metadata]
|
||||
- - -
|
||||
## Nacos 服务下线报错问题
|
||||
|
||||
问题描述:
|
||||
|
||||
Nacos 服务管理 > 服务列表 > 详情 > 下线 报错
|
||||
|
||||
|
||||
|
||||
报错详情:
|
||||
|
||||
```
|
||||
caused: errCode: 500, errMsg: do metadata operation failed ;caused: com.alibaba.nacos.consistency.exception.ConsistencyException: The Raft Group [naming_instance_metadata] did not find the Leader node;caused: The Raft Group [naming_instance_metadata] did not find the Leader node;
|
||||
```
|
||||
|
||||
|
||||
|
||||
解决方案:
|
||||
|
||||
**删除 Nacos 根目录下 data 文件夹下的 protocol 文件夹**
|
||||
|
||||
(推荐使用全局搜索软件查询,windows 环境根目录一般在 C:\Users\用户名\nacos)
|
||||
|
||||
|
||||
|
||||
问题原因:
|
||||
|
||||
> Nacos 采用 raft 算法来计算 Leader,并且会记录上次启动的集群地址,所以当我们自己的服务器 IP 改变时(网络环境不稳定,如WIFI, IP 地址也经常变化),导致 raft 记录的集群地址失效,导致选 Leader 出现问题。
|
||||
|
||||
|
||||
|
||||
参考目录:
|
||||
|
||||
[解决疑难问题之服务下线报:The Raft Group naming_instance_metadata\] did not find the Leader node; - 嘉美祥瑞 - 博客园 (cnblogs.com)](https://www.cnblogs.com/whl-jx911/p/16736625.html)
|
||||
@@ -0,0 +1,15 @@
|
||||
# 无法读取nacos配置
|
||||
- - -
|
||||
### 检查 `group` 与 `namespace` 是否一致
|
||||
|
||||
如果未使用框架自带 `ry-config.sql` 文件进行配置 会导致 `namespace` 不一致 无法查询配置
|
||||
|
||||
### 检查 `8848` `9848` `9849` 端口是否开启可用
|
||||
|
||||
### 检查配置文件名是否一致 例如: "xxx" 与 "xxx.yml" 的区别
|
||||
|
||||
### 检查是否手动改过 `nacos` 数据库数据
|
||||
|
||||
`nacos` 数据表层层关联 不要自作聪明手动改数据库
|
||||
|
||||
已经改过的 需要重新导入 `ry-config.sql` 之后在页面进行改数据操作
|
||||
@@ -0,0 +1,11 @@
|
||||
# Only one connection receive subscriber allowed
|
||||
- - -
|
||||
## 问题原因
|
||||
**经多人反馈 共同点为全都是做`小程序开发`使用的`uniapp`发送的网络请求而出现这种问题**
|
||||
|
||||
`uniapp` 错误设置 `Content-Type` 将所有请求类型全都设置成了 `json` 导致不该读body的请求也读取了body 最终导致报错
|
||||
|
||||
## 解决方案
|
||||
|
||||
方案1: 升级 1.4.0 已经对这种不合规发的请求做了兼容处理(被迫)<br>
|
||||
方案2: `uniapp` 内的请求设置正确的 `Content-Type`
|
||||
@@ -0,0 +1,40 @@
|
||||
# ParseException SQL解析异常
|
||||
- - -
|
||||
## 异常内容
|
||||
|
||||
`net.sf.jsqlparser.parser.ParseException: Encountered unexpected token:`
|
||||
|
||||

|
||||
|
||||
此异常为 SQL 解析异常, 应检查 SQL 语句内是否包含 SQL 关键字
|
||||
|
||||
异常通常都会提供坐标
|
||||
|
||||

|
||||
|
||||
检查报错 SQL 相关坐标位置
|
||||
|
||||

|
||||
|
||||
## 异常由来
|
||||
由 Mybatis-Plus 拦截器进行 SQL 解析导致<br>
|
||||
常见拦截器导致问题 `TenantLineInnerInterceptor` `DataPermissionInterceptor`
|
||||
|
||||
## 解决方案
|
||||
|
||||
> 将关键字增加标识符区别开
|
||||
|
||||
1.实体类字段处理(以下仅限于mysql 其他数据库方法各不相同)
|
||||
|
||||

|
||||
|
||||
2.自定义 SQL 或 XML 处理
|
||||
|
||||

|
||||
|
||||
3.Mapper排除
|
||||
> 查看具体使用了哪些拦截器导致问题 使用忽略注解依次进行排除即可
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Redis 报错 Permission denied
|
||||
- - -
|
||||
### 此报错为无权限
|
||||
|
||||
需确保 redis 数据存储文件夹具有写权限
|
||||
|
||||
```shell
|
||||
chmod 777 /docker/redis/data
|
||||
```
|
||||
|
||||
没有写权限无法对数据进行存储
|
||||
|
||||
### 关于RDB报错 `/etc` 无权限问题
|
||||
|
||||
增加redis密码校验 无密码导致配置不安全
|
||||
@@ -0,0 +1,11 @@
|
||||
# unable to read meta-data for class xxx
|
||||
- - -
|
||||
## 问题原因
|
||||
|
||||
此问题由改包名导致框架内组件 spring 的 spi 配置文件包名被改乱套
|
||||
|
||||
## 解决方案
|
||||
|
||||
更正组件包下的 spring spi 配置文件内的类包名
|
||||
|
||||

|
||||
@@ -0,0 +1,8 @@
|
||||
# Sentinel页面404问题
|
||||
- - -
|
||||
## 原因
|
||||
检查 `webapp` 目录是否为资源目录 低版本 `idea` 不会自动解析
|
||||
## 解决方案
|
||||
手动设置 `webapp` 为资源目录即可<br>
|
||||
|
||||

|
||||
@@ -0,0 +1,11 @@
|
||||
# 不支持ST请求
|
||||
- - -
|
||||
## 问题原因
|
||||
**经多人反馈 共同点为全都是做`小程序开发`使用的`uniapp`发送的网络请求而出现这种问题**
|
||||
|
||||
`uniapp` 错误设置 `Content-Type` 将所有请求类型全都设置成了 `json` 导致不该读body的请求也读取了body 最终导致报错
|
||||
|
||||
## 解决方案
|
||||
|
||||
方案1: 升级 1.4.0 已经对这种不合规发的请求做了兼容处理(被迫)<br>
|
||||
方案2: `uniapp` 内的请求设置正确的 `Content-Type`
|
||||
@@ -0,0 +1,3 @@
|
||||
# 框架内没有任何swagger
|
||||
|
||||
想使用接口文档功能 请查看框架接口文档说明
|
||||
@@ -0,0 +1,3 @@
|
||||
# 如何同步项目更新
|
||||
- - -
|
||||
参考文章: [关于如何同步更新开源项目](https://blog.csdn.net/qq_31360283/article/details/118345795)
|
||||
20
ruoyi-admin/src/main/resources/static/questions/use_druid.md
Normal file
20
ruoyi-admin/src/main/resources/static/questions/use_druid.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# 如何使用druid连接池
|
||||
- - -
|
||||
## 为何移除druid
|
||||
|
||||
性能低下 bug频发 内含fastjson问题众多 监控不支持集群(鸡肋) 不支持一些高版本数据库 社区活跃度冰点
|
||||
|
||||
### 性能对比图
|
||||

|
||||
### 包大小对比图
|
||||

|
||||

|
||||
|
||||
## 为何使用hikari(中文: 光)
|
||||
|
||||
spring默认自带 代码量少结构简单 稳定可靠 性能突出(自行百度一堆测评)
|
||||
|
||||
## 参考提交记录反向操作即可
|
||||
|
||||
https://gitee.com/dromara/RuoYi-Vue-Plus/commit/1f42bd3d22c104aaa2d780c20a555b5e467858bf <br>
|
||||
https://gitee.com/dromara/RuoYi-Vue-Plus/commit/a63abbf268e4c0a60344f63b5cba828a1347e178
|
||||
@@ -0,0 +1,9 @@
|
||||
# 关于如何使用Tomcat
|
||||
- - -
|
||||
### 查看ruoyi-framework模块的pom.xml文件,根据注释更改依赖
|
||||
|
||||

|
||||
|
||||
### 查看ruoyi-admin模块中的application.yml文件,根据注释更改配置
|
||||
|
||||

|
||||
@@ -0,0 +1,70 @@
|
||||
<!-- _sidebar.md -->
|
||||
- **特别赞助**
|
||||
- [](http://ccflow.org/?frm=ryPlus)
|
||||
- [](http://www.shuduokeji.com)
|
||||
- [](https://www.jnpfsoft.com/index.html?from=plus-doc)
|
||||
|
||||
|
||||
* **简介**
|
||||
* [项目简介](/ruoyi-cloud-plus/home.md)
|
||||
* [更新日志](/ruoyi-cloud-plus/changlog.md)
|
||||
* **快速开始**
|
||||
* [项目初始化](/ruoyi-cloud-plus/quickstart/init.md)
|
||||
* [1.X项目初始化](/ruoyi-cloud-plus/quickstart/1.Xinit.md)
|
||||
* [工作流初始化](/ruoyi-cloud-plus/quickstart/worker_init.md)
|
||||
* [idea环境配置](/ruoyi-cloud-plus/quickstart/idea_environment.md)
|
||||
* [应用部署](/ruoyi-cloud-plus/quickstart/deploy.md)
|
||||
* [扩展项目](/ruoyi-cloud-plus/quickstart/extend_project.md)
|
||||
* [搭建SnailJob调度中心](/ruoyi-cloud-plus/quickstart/snail_job_init.md)
|
||||
* [(废弃)搭建PowerJob调度中心](/ruoyi-cloud-plus/quickstart/power_job_init.md)
|
||||
* **框架功能**
|
||||
* [项目结构](/ruoyi-cloud-plus/framework/tree.md)
|
||||
* [软件架构图](/ruoyi-cloud-plus/framework/architecture_diagram.md)
|
||||
* 框架相关
|
||||
* [创建新服务](/ruoyi-cloud-plus/framework/association/new_module.md)
|
||||
* [修改包名](/ruoyi-cloud-plus/framework/association/update_package_name.md)
|
||||
* [接口文档](/ruoyi-cloud-plus/framework/association/doc.md)
|
||||
* [修改应用路径](/ruoyi-cloud-plus/framework/association/update_url.md)
|
||||
* [国际化](/ruoyi-cloud-plus/framework/association/i18n.md)
|
||||
* [多团队开发](/ruoyi-cloud-plus/framework/association/collaboration.md)
|
||||
* [内网鉴权](/ruoyi-cloud-plus/framework/association/inner_authentication.md)
|
||||
* 基础功能
|
||||
* [系统用户相关](/ruoyi-cloud-plus/framework/basic/user.md)
|
||||
* [权限控制](/ruoyi-cloud-plus/framework/basic/permissions_control.md)
|
||||
* [导出功能](/ruoyi-cloud-plus/framework/basic/export.md)
|
||||
* [导入功能](/ruoyi-cloud-plus/framework/basic/import.md)
|
||||
* [参数校验](/ruoyi-cloud-plus/framework/basic/param_check.md)
|
||||
* [代码生成](/ruoyi-cloud-plus/framework/basic/code_generate.md)
|
||||
* [分页功能](/ruoyi-cloud-plus/framework/basic/page.md)
|
||||
* [OSS功能](/ruoyi-cloud-plus/framework/basic/oss.md)
|
||||
* [数据权限](/ruoyi-cloud-plus/framework/basic/permissions.md)
|
||||
* [网关路由与放行](/ruoyi-cloud-plus/framework/basic/router_release.md)
|
||||
* [多租户功能](/ruoyi-cloud-plus/framework/basic/tenant.md)
|
||||
* [第三方授权功能](/ruoyi-cloud-plus/framework/basic/social.md)
|
||||
* [客户端管理功能](/ruoyi-cloud-plus/framework/basic/client.md)
|
||||
* 扩展功能
|
||||
* [多数据源](/ruoyi-cloud-plus/framework/extend/dynamic_datasource.md)
|
||||
* [短信模块](/ruoyi-cloud-plus/framework/extend/sms.md)
|
||||
* [邮件功能](/ruoyi-cloud-plus/framework/extend/mail.md)
|
||||
* [防重幂等](/ruoyi-cloud-plus/framework/extend/idempotent.md)
|
||||
* [数据脱敏](/ruoyi-cloud-plus/framework/extend/sensitive.md)
|
||||
* [API加解密](/ruoyi-cloud-plus/framework/extend/api_encrypt.md)
|
||||
* [数据加解密](/ruoyi-cloud-plus/framework/extend/encrypt.md)
|
||||
* [翻译功能](/ruoyi-cloud-plus/framework/extend/translation.md)
|
||||
* [WebSocket功能](/ruoyi-cloud-plus/framework/extend/websocket.md)
|
||||
* 功能说明
|
||||
* [事务相关](/ruoyi-cloud-plus/framework/explain/transaction.md)
|
||||
* [单元测试](/ruoyi-cloud-plus/framework/explain/test.md)
|
||||
* [主键使用说明](/ruoyi-cloud-plus/framework/explain/key.md)
|
||||
* [关于多表查询](/ruoyi-cloud-plus/framework/explain/about_join.md)
|
||||
* **扩展功能**
|
||||
* [ELK搭建](/ruoyi-cloud-plus/extend-function/elk.md)
|
||||
* [ES搜索引擎](/ruoyi-cloud-plus/extend-function/es.md)
|
||||
* [RabbitMQ搭建](/ruoyi-cloud-plus/extend-function/rabbitmq.md)
|
||||
* [RocketMQ搭建](/ruoyi-cloud-plus/extend-function/rocketmq.md)
|
||||
* [Kafka搭建](/ruoyi-cloud-plus/extend-function/kafka.md)
|
||||
* [Nacos集群搭建](/ruoyi-cloud-plus/extend-function/nacos.md)
|
||||
* [SkyWalking搭建与集成](/ruoyi-cloud-plus/extend-function/skywalking.md)
|
||||
* [Prometheus+Grafana搭建](/ruoyi-cloud-plus/extend-function/prometheus_grafana.md)
|
||||
* [Sharding-Proxy搭建分库分表](/ruoyi-cloud-plus/extend-function/shardingproxy.md)
|
||||
* [对接MaxKey单点登录](/ruoyi-cloud-plus/extend-function/maxkey.md)
|
||||
1385
ruoyi-admin/src/main/resources/static/ruoyi-cloud-plus/changlog.md
Normal file
1385
ruoyi-admin/src/main/resources/static/ruoyi-cloud-plus/changlog.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
# ELK搭建
|
||||
- - -
|
||||
# 环境搭建
|
||||
|
||||
项目内置 `ELK` 的 `docker-compose` 编排 可查看 `/docker/docker-compose.yml` 文件下方扩展编排
|
||||
|
||||
**注意: `/docker/elk/elasticsearch/` 目录下所有文件夹 均需要写权限**
|
||||
|
||||
`chmod 777 /docker/elk/elasticsearch/data`<br>
|
||||
`chmod 777 /docker/elk/elasticsearch/logs`<br>
|
||||
`chmod 777 /docker/elk/elasticsearch/plugins`<br>
|
||||
**注意: es插件需要解压后放入 `plugins` 目录**
|
||||
|
||||
# 运行命令
|
||||
|
||||
```shell
|
||||
docker-compose up -d elasticsearch kibana logstash
|
||||
```
|
||||
|
||||
# 参考文章
|
||||
[docker-compose 搭建 ELK 7.X 并整合 SpringBoot](https://lionli.blog.csdn.net/article/details/125743132)
|
||||
|
||||
# 项目内配置
|
||||
|
||||
服务引入依赖项
|
||||
|
||||
```xml
|
||||
<!-- ELK 日志收集 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-logstash</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
更改主 `pom` 文件 `logstash.address` 地址<br>
|
||||
|
||||

|
||||
@@ -0,0 +1,26 @@
|
||||
# ES搜索引擎
|
||||
- - -
|
||||
## 环境搭建(如果已经搭建了ELK则跳过)
|
||||
|
||||
项目内置 `ELK` 的 `docker-compose` 编排 可查看 `/docker/docker-compose.yml` 文件下方扩展编排
|
||||
|
||||
**注意: `/docker/elk/elasticsearch/` 目录下所有文件夹 均需要写权限**
|
||||
|
||||
`chmod 777 /docker/elk/elasticsearch/data`<br>
|
||||
`chmod 777 /docker/elk/elasticsearch/logs`<br>
|
||||
`chmod 777 /docker/elk/elasticsearch/plugins`<br>
|
||||
**注意: es插件需要解压后放入 `plugins` 目录**
|
||||
|
||||
## 运行命令
|
||||
|
||||
```shell
|
||||
docker-compose up -d elasticsearch
|
||||
```
|
||||
|
||||
## Easy-ES 文档
|
||||
[Easy-ES 文档](https://www.easy-es.cn/)
|
||||
|
||||
## 用法
|
||||
|
||||
基本配置和用法可参考 `ruoyi-demo` 模块 更多高级用法请参考 Easy-ES 文档<br>
|
||||

|
||||
@@ -0,0 +1,9 @@
|
||||
# Kafka搭建
|
||||
- - -
|
||||
## 环境搭建
|
||||
参考文章: [docker-compose 安装 Kafka 3.X 附带可视化界面](https://lionli.blog.csdn.net/article/details/125855550)
|
||||
|
||||
## 用法参考
|
||||
参考 `ruoyi-stream-mq` 模块内的测试案例
|
||||
|
||||

|
||||
@@ -0,0 +1,20 @@
|
||||
# 对接 MaxKey 单点登录
|
||||
- - -
|
||||
|
||||
# 安装 MaxKey 应用服务
|
||||
|
||||
参考 MaxKey 官方文档安装 [MaxKey安装部署](http://www.maxkey.top/doc/docs/intro/)
|
||||
|
||||
# 配置应用 OAuth2.0 认证注册
|
||||
|
||||

|
||||
|
||||
# 配置后端服务
|
||||
|
||||
找到 `Nacos` 内的 `ruoyi-auth.yml` 配置文件
|
||||
|
||||
修改 `maxkey` 对应的 `client-id` 与 `client-secret`
|
||||
|
||||

|
||||
|
||||

|
||||
@@ -0,0 +1,13 @@
|
||||
# Nacos集群搭建
|
||||
- - -
|
||||
## 集群搭建两种方式
|
||||
### 文件寻址集群
|
||||
[【RuoYi-Cloud-Plus】学习笔记 02 - Nacos(二)寻址机制之文件寻址分析](https://blog.csdn.net/Michelle_Zhong/article/details/127423521)
|
||||
|
||||
### 地址服务器寻址集群(推荐)
|
||||
[【RuoYi-Cloud-Plus】学习笔记 03 - Nacos(三)使用 Nginx 实现地址服务器寻址及其原理分析](https://blog.csdn.net/Michelle_Zhong/article/details/127474238)
|
||||
|
||||
## 集群路由代理设置
|
||||
[【RuoYi-Cloud-Plus】学习笔记 04 - Nacos(四)使用 Nginx 简单实现 Nacos 集群负载均衡](https://blog.csdn.net/Michelle_Zhong/article/details/127486350)
|
||||
|
||||
设置好代理之后 跟单机用法一致 后端nacos地址写代理 `ip:端口` 即可
|
||||
@@ -0,0 +1,45 @@
|
||||
# Prometheus+Grafana搭建
|
||||
- - -
|
||||
## 基础搭建
|
||||
|
||||
参考文章: https://lionli.blog.csdn.net/article/details/127959009
|
||||
|
||||
## 框架内扩展
|
||||
|
||||
框架已经包含了 docker-compose 编排 执行如下命令启动容器即可
|
||||
|
||||
```shell
|
||||
docker-compose up -d prometheus grafana
|
||||
```
|
||||
|
||||
## 应用配置
|
||||
|
||||
各个服务引入 `ruoyi-common-prometheus` 模块
|
||||
|
||||

|
||||
|
||||
修改 `prometheus.yml` 配置采集数据源
|
||||
|
||||

|
||||
|
||||
修改 `Nacos` 地址 与 `SpringBoot-Admin` 监控地址 用于数据采集<br>
|
||||
如都为本地应用则无需更改
|
||||
|
||||

|
||||
|
||||
## 导入框架特制模板
|
||||
**注意: 此处数据源名称必须与图片保持一致 不然会和模板对应不上导致无法读取数据**<br>
|
||||

|
||||
|
||||
> 找到框架内的特制模板json文件 在grafana点击上传json文件 导入模板<br>
|
||||
|
||||
<br>
|
||||

|
||||
|
||||
## 选择查看监控
|
||||
|
||||
点击右侧菜单浏览 选择想要查看的监控即可
|
||||
|
||||
<br>
|
||||
<br>
|
||||

|
||||
@@ -0,0 +1,10 @@
|
||||
# RabbitMQ搭建
|
||||
- - -
|
||||
## 环境搭建
|
||||
|
||||
参考文章: [docker-compose 安装 RabbitMQ 3.X 附带延迟队列插件](https://lionli.blog.csdn.net/article/details/125855177)
|
||||
|
||||
## 用法参考
|
||||
参考 `ruoyi-stream-mq` 模块内的测试案例
|
||||
|
||||

|
||||
@@ -0,0 +1,9 @@
|
||||
# RocketMQ搭建
|
||||
- - -
|
||||
## 环境搭建
|
||||
参考文章: [docker-compose 安装 RocketMQ 4.9.X (apache官方镜像) namesrv broker 与可视化控制台 console](https://lionli.blog.csdn.net/article/details/125798865)
|
||||
|
||||
## 用法参考
|
||||
参考 `ruoyi-stream-mq` 模块内的测试案例
|
||||
|
||||

|
||||
@@ -0,0 +1,75 @@
|
||||
# Sharding-Proxy搭建分库分表
|
||||
- - -
|
||||
|
||||
# 如何使用
|
||||
|
||||
查看 `ruoyi-demo` 服务 `TestShardingController`
|
||||
|
||||

|
||||
|
||||
## 首先在 MySQL 创建两个库
|
||||
|
||||
创建两个库 `data-center_0` `data-center_1` 分别执行如下SQL
|
||||
|
||||
```sql
|
||||
CREATE TABLE `t_order_0` (
|
||||
`order_id` bigint(20) UNSIGNED NOT NULL COMMENT '主键ID',
|
||||
`user_id` bigint(20) UNSIGNED NOT NULL COMMENT '用户ID',
|
||||
`total_money` int(10) UNSIGNED NOT NULL COMMENT '订单总金额',
|
||||
PRIMARY KEY (`order_id`),
|
||||
KEY `idx_user_id` (`user_id`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单总表';
|
||||
|
||||
CREATE TABLE `t_order_1` (
|
||||
`order_id` bigint(20) UNSIGNED NOT NULL COMMENT '主键ID',
|
||||
`user_id` bigint(20) UNSIGNED NOT NULL COMMENT '用户ID',
|
||||
`total_money` int(10) UNSIGNED NOT NULL COMMENT '订单总金额',
|
||||
PRIMARY KEY (`order_id`),
|
||||
KEY `idx_user_id` (`user_id`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单总表';
|
||||
|
||||
CREATE TABLE `t_order_item_0` (
|
||||
`order_item_id` bigint(20) UNSIGNED NOT NULL COMMENT '子订单ID',
|
||||
`order_id` bigint(20) UNSIGNED NOT NULL COMMENT '主键ID',
|
||||
`user_id` bigint(20) UNSIGNED NOT NULL COMMENT '用户ID',
|
||||
`money` int(10) UNSIGNED NOT NULL COMMENT '子订单金额',
|
||||
PRIMARY KEY (`order_item_id`),
|
||||
KEY `idx_order_id` (`order_id`) USING BTREE,
|
||||
KEY `idx_user_id` (`user_id`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单子表';
|
||||
|
||||
CREATE TABLE `t_order_item_1` (
|
||||
`order_item_id` bigint(20) UNSIGNED NOT NULL COMMENT '子订单ID',
|
||||
`order_id` bigint(20) UNSIGNED NOT NULL COMMENT '主键ID',
|
||||
`user_id` bigint(20) UNSIGNED NOT NULL COMMENT '用户ID',
|
||||
`money` int(10) UNSIGNED NOT NULL COMMENT '子订单金额',
|
||||
PRIMARY KEY (`order_item_id`),
|
||||
KEY `idx_order_id` (`order_id`) USING BTREE,
|
||||
KEY `idx_user_id` (`user_id`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单子表';
|
||||
|
||||
```
|
||||
|
||||
## 然后更改配置文件
|
||||
|
||||
更改 `config-sharding.yaml` 配置文件内的数据库连接地址与用户名密码
|
||||
|
||||
## 服务搭建
|
||||
|
||||
参考部署文档上传 docker 文件夹 内部包含 `shardingproxy` 配置文件
|
||||
|
||||

|
||||
|
||||
框架已经包含了 docker-compose 编排 执行如下命令启动容器即可
|
||||
|
||||
```shell
|
||||
docker-compose up -d shardingproxy
|
||||
```
|
||||
|
||||
## 最后运行 demo
|
||||
|
||||
运行 demo 提供的 controller 代码查看数据库内数据即可
|
||||
|
||||
## 用法参考视频(略有不同 理性观看)
|
||||
|
||||
用法参考视频: https://www.bilibili.com/video/BV1XN411A7Tv/
|
||||
@@ -0,0 +1,41 @@
|
||||
# SkyWalking搭建与集成
|
||||
- - -
|
||||
## 服务搭建
|
||||
参考文章: [SpringBoot 整合 SkyWalking 8.X (包含 Logback 日志采集)](https://lionli.blog.csdn.net/article/details/127656534)
|
||||
|
||||
框架已经包含了 docker-compose 编排 执行如下命令启动容器即可
|
||||
|
||||
```shell
|
||||
docker-compose up -d elasticsearch sky-oap sky-ui
|
||||
```
|
||||
|
||||
### 本地开发使用
|
||||
参考上方文章
|
||||
|
||||
### docker部署使用
|
||||
上传探针到服务器 `/docker/skywalking/agent` 目录<br>
|
||||
**不要使用网上下载的 请使用框架自带的 内含一些官网没有的插件**<br>
|
||||

|
||||
|
||||
在对应服务的`dockerfile`内 打开 `skywalking` 相关参数注释<br>
|
||||

|
||||
|
||||
服务编排增加探针路径映射<br>
|
||||

|
||||
|
||||
|
||||
### 对接日志推送(不推荐 建议使用ELK收集日志)
|
||||
|
||||
框架已经封装好了对应的依赖和配置 在服务内添加如下依赖
|
||||
|
||||
```xml
|
||||
<!-- skywalking 日志收集 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common-skylog</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
在 `logback.xml` 日志配置文件内引入 `skylog` 配置文件
|
||||
|
||||

|
||||
@@ -0,0 +1,3 @@
|
||||
# 软件架构图
|
||||
- - -
|
||||

|
||||
@@ -0,0 +1,27 @@
|
||||
# 多团队开发
|
||||
- - -
|
||||
## 功能介绍
|
||||
|
||||
> 多人员/团队开发往往会出现 调试程序 被负载均衡到别人那里 自己抓不到请求等问题<br>
|
||||
> 正确团队开发模式 `测试机一台` 公共服务都放到测试机上<br>
|
||||
> 本地开发人员 需启动 `ruoyi-gateway` 与 其他 调试的业务模块<br>
|
||||
> 将所有服务都统一指向同一个 Nacos 服务<br>
|
||||
> 前端连接本机 `ruoyi-gateway` 网关调试程序<br>
|
||||
|
||||
框架提供了 `ruoyi-common-loadbalancer` 多团队 负载均衡模块 可以将网关的请求锁定到与网关相同的IP服务
|
||||
|
||||
需要在 `ruoyi-gateway` `ruoyi-auth` `ruoyi-modules` 引入 `ruoyi-common-loadbalancer` 模块
|
||||
|
||||

|
||||
|
||||
启动前端访问本机 `ruoyi-gateway` 网关在请求转发 和 `dubbo` 进行 RPC 调用时<br>
|
||||
会获取与本机IP地址相同的服务优先调用(如未找到 会随机返回)
|
||||
|
||||
# 重点说明
|
||||
|
||||
请检查本机是否有虚机网卡IP 如有多网卡获取IP地址会不准确
|
||||
|
||||
可使用如下代码检查本机IP是否正常
|
||||
```java
|
||||
InetAddress.getLocalHost().getHostAddress()
|
||||
```
|
||||
@@ -0,0 +1,88 @@
|
||||
# 接口文档
|
||||
- - -
|
||||
## 版本 >= `1.2.0`
|
||||
## 说明
|
||||
由于 `springfox` 与 `knife4j` 均停止维护 bug众多<br>
|
||||
故从 `1.2.0` 开始 迁移到 `springdoc` 框架<br>
|
||||
基于 `javadoc` 无注解零入侵生成规范的 `openapi` 结构体<br>
|
||||
由于框架自带文档UI功能单一扩展性差 故移除自带UI 建议使用外置文档工具
|
||||
|
||||
## 文档工具使用
|
||||
由于框架采用 `openapi` 行业规范 故市面上大部分的框架均支持 可自行选择<br>
|
||||
例如: `apifox` `apipost` `postman` `torna` `knife4j` 等 根据对应工具的文档接入即可
|
||||
|
||||
## Swagger升级SpringDoc指南
|
||||
|
||||
常见功能如下 其他功能自行挖掘<br>
|
||||
**注意: `javadoc` 只能替换基础功能 特殊功能还需要使用注解实现**
|
||||
|
||||
| swagger | springdoc | javadoc |
|
||||
|----------------------------------|---------------------------------|--------------------|
|
||||
| @Api(name = "xxx") | @Tag(name = "xxx") | java类注释第一行 |
|
||||
| @Api(description= "xxx") | @Tag(description= "xxx") | java类注释 |
|
||||
| @ApiOperation | @Operation | java方法注释 |
|
||||
| @ApiIgnore | @Hidden | 无 |
|
||||
| @ApiParam | @Parameter | java方法@param参数注释 |
|
||||
| @ApiImplicitParam | @Parameter | java方法@param参数注释 |
|
||||
| @ApiImplicitParams | @Parameters | 多个@param参数注释 |
|
||||
| @ApiModel | @Schema | java实体类注释 |
|
||||
| @ApiModelProperty | @Schema | java属性注释 |
|
||||
| @ApiModelProperty(hidden = true) | @Schema(accessMode = READ_ONLY) | 无 |
|
||||
| @ApiResponse | @ApiResponse | java方法@return返回值注释 |
|
||||
|
||||
# 建议使用 `Apifox`(常见问题有其他对接方式)
|
||||
|
||||
官网连接: [https://www.apifox.cn/](https://www.apifox.cn/)<br>
|
||||
视频教程: [springdoc与apifox配合使用](https://www.bilibili.com/video/BV1mr4y1j75M?p=8&vd_source=8f52c77be3233dbdd1c5e332d4d45bfb)
|
||||
|
||||

|
||||
|
||||
支持 文档编写 接口调试 Mock 接口压测 自动化测试 等一系列功能
|
||||
|
||||
### 接入框架
|
||||
|
||||
> 1.下载或使用web在线版 创建一个自己的项目<br>
|
||||
|
||||

|
||||
|
||||
> 2.进入项目 选择项目设置 找到自动同步<br>
|
||||
|
||||

|
||||
|
||||
> 3.根据项目内所有文档组完成所有数据源创建(拉取后端`openapi`结构体)<br>
|
||||
数据源URL格式 `http://网关ip:端口/服务路径/v3/api-docs`<br>
|
||||
项目内所需:<br>
|
||||
`http://localhost:8080/demo/v3/api-docs` 演示服务<br>
|
||||
`http://localhost:8080/auth/v3/api-docs` 认证服务<br>
|
||||
`http://localhost:8080/resource/v3/api-docs` 资源服务<br>
|
||||
`http://localhost:8080/system/v3/api-docs` 系统服务<br>
|
||||
`http://localhost:8080/code/v3/api-docs` 代码生成服务<br>
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
> 4.选择 接口管理 项目概览 点击立即导入 并等待导入完成<br>
|
||||
后续会根据策略每3个小时自动导入一次<br>
|
||||
每次重新进入apifox也会自动同步一次<br>
|
||||
后端有改动也可以手动点击导入<br>
|
||||
|
||||

|
||||
|
||||
> 5.(注意版本号)设置鉴权 选择接口管理 项目概览 找到Auth 按照如下配置<br>
|
||||
|
||||
**版本号: >= 2.X**
|
||||
|
||||

|
||||
|
||||
**版本号: 1.X**
|
||||
|
||||

|
||||
|
||||
> key对应项目配置 默认为 `Authorization`<br>
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# 国际化方案
|
||||
- - -
|
||||
* 前端国际化参考 [ruoyi前端国际化文档](http://doc.ruoyi.vip/ruoyi-vue/document/htsc.html#前端国际化流程)<br>
|
||||
* 参考 `demo` 模块 `TestI18nController` 国际化演示案例
|
||||
在 `Header` 请求头 增加上下文语言参数 `content-language` 参数需与国际化配置文件后缀对应
|
||||
如 `zh_CN` `en_US` 等<br>
|
||||
|
||||

|
||||
|
||||
## 获取 `code` 对应国际化内容
|
||||
|
||||
<br>
|
||||
<br>
|
||||

|
||||
|
||||
## 使用 `Validator` 框架校验 `controller` 参数返回国际化
|
||||
|
||||
`controller` 校验接口参数 需要在类增加 `@Validated` 注解<br>
|
||||
<br>
|
||||
参数对应校验注解 使用 `{code}` 形式标注使用国际化处理<br>
|
||||
<br>
|
||||
<br>
|
||||

|
||||
|
||||
## 使用 `Validator` 框架校验 `Bean` 返回国际化
|
||||
|
||||
`Bean` 校验需要在接口校验 `Bean` 参数使用 `@Validated` 注解<br>
|
||||
<br>
|
||||
`Bean` 内属性校验注解 使用 `{code}` 形式标注使用国际化处理<br>
|
||||
<br>
|
||||

|
||||
@@ -0,0 +1,19 @@
|
||||
# 内网鉴权
|
||||
- - -
|
||||
## 功能介绍
|
||||
|
||||
此功能用于防止外部请求访问内部服务应用<br>
|
||||
在请求经过 `gateway网关` 会生成一个 `id-token` 携带到后续服务进行校验<br>
|
||||
若未经过 `gateway网关` 调用内网服务 会出现 `id-token无效` 异常<br>
|
||||
有效防止非法请求直接访问内网服务<br>
|
||||
|
||||
## 开启/关闭内网鉴权
|
||||
|
||||
更改 `application-common.yml` 配置文件的 `sa-token.check-id-token` 配置即可
|
||||
|
||||

|
||||
|
||||
## 放行内网鉴权
|
||||
进入 `ruoyi-common-security` 模块找到 `SecurityConfiguration` 类 增加排除路径即可
|
||||
|
||||

|
||||
@@ -0,0 +1,39 @@
|
||||
# 创建新服务
|
||||
- - -
|
||||
### 最简单的方式
|
||||
> 找个配置好的 例如 `ruoyi-system` 直接copy一份
|
||||
|
||||
> 将 `pom` 名称改掉<br>
|
||||
|
||||

|
||||
|
||||
> 服务启动类 名称改掉<br>
|
||||
|
||||

|
||||
|
||||
> `application.yml` 配置服务应用名 改掉<br>
|
||||
|
||||

|
||||
|
||||
> `nacos` 新建一份新的 对应新模块名称的 配置文件<br>
|
||||

|
||||
|
||||
更改 `nacos` 上的 `ruoyi-gateway.yml` 增加新服务路由<br>
|
||||
新服务访问路径 `网关ip:端口/服务路径/controller路径/接口路径`<br>
|
||||
例子: `http://localhost:8080/system/user/list` <br>
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### 注意事项
|
||||
如果是两个不同包名的模块 需要修改如下配置
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
如果新服务需要使用 `seata` 分布式事务<br>
|
||||
需要在 `nacos` 上的 `seata-server.properties` 文件内增加服务组
|
||||
|
||||

|
||||
@@ -0,0 +1,33 @@
|
||||
# 关于修改包名
|
||||
- - -
|
||||
|
||||
**注意: 老包名为 com.ruoyi**
|
||||
|
||||
## 1.随便找个地方新建 org.dromara 包
|
||||

|
||||
|
||||
## 2.在包上右键选择 refactor -> rename 选择 All Directories
|
||||

|
||||

|
||||
|
||||
**因为dromara组织下有很多依赖导致idea无法识别完整包名**
|
||||
<br>
|
||||

|
||||
|
||||
**需要先将dromara修改为 例如: ruoyi 然后重复上述步骤 这样就可以整包修改了**
|
||||
<br>
|
||||

|
||||
|
||||
## 3.使用IDEA全局替换 org.dromara 替换为 com.xxx
|
||||
|
||||

|
||||
|
||||
**注意: 由于dromara组织下项目很多 非本框架的依赖模块 请勿修改 例如上图中的 org.dromara.sms4j**
|
||||
|
||||
## 4.如有需要 将所有模块名逐一修改即可
|
||||
|
||||
## 5.修改完成后需查看所有common包下模块spi文件是否修改正确
|
||||
|
||||
**老版本idea或者未按照教程修改包名可能导致文件丢包问题**
|
||||
|
||||

|
||||
@@ -0,0 +1,25 @@
|
||||
# 修改应用路径
|
||||
- - -
|
||||
# 修改访问后端接口路径
|
||||
|
||||
更改 前端环境配置文件 `VITE_APP_BASE_API` 代理路径
|
||||
|
||||
 <br>
|
||||
|
||||

|
||||
|
||||
`prod` 生产环境需修改 `nginx.conf` 后端代理路径(上述配置文件也要改)
|
||||
|
||||

|
||||
|
||||
# 修改前端页面访问路径
|
||||
修改对应环境的 `.env.环境` 文件内的 `VITE_APP_CONTEXT_PATH` 应用访问路径即可
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
生产环境 `nginx.conf` 与之对应修改即可 <br>
|
||||
**注意: 文件真实目录为 `/usr/share/nginx/html/admin/index.html` 此功能一般为多项目部署需要 故会增加一层目录 如不需要可以自行修改** <br>
|
||||
|
||||

|
||||
@@ -0,0 +1,85 @@
|
||||
# 客户端管理功能
|
||||
- - -
|
||||
## 版本 >= 2.X
|
||||
|
||||
## 客户端管理页面
|
||||
|
||||

|
||||
|
||||
### 客户端管理字段说明
|
||||
| 字段名称 | 取值说明 | 注意事项 |
|
||||
|----------------|----------------------------|--------------------------------|
|
||||
| 客户端id | 由后端生成,用于前端登录校验以及接口数据加密 | 无法修改,不要删除默认数据,否则会报错 |
|
||||
| 客户端key | 前端自定义 | 无法修改,不要删除默认数据,否则会报错 |
|
||||
| 客户端秘钥 | 前端自定义 | 无法修改,不要删除默认数据,否则会报错 |
|
||||
| 授权类型 | 密码认证、短信认证、邮件认证、小程序认证、第三方认证 | 根据授权类型判断当前客户端是否支持该登录方式 |
|
||||
| 设备类型 | PC端、APP端 | |
|
||||
| Token活跃超时时间 | 自定义 | 指定时间无操作则过期(单位:秒),默认30分钟(1800秒) |
|
||||
| Token固定超时时间 | 自定义 | 指定时间必定过期(单位:秒),默认七天(604800秒) |
|
||||
|
||||
### 前后端使用新的客户端id
|
||||
|
||||
步骤如下:
|
||||
1. 前端管理页面生成新的客户端id。
|
||||
2. 将新的客户端id复制到前端配置文件。
|
||||
|
||||

|
||||
|
||||
## 新增自定义客户端
|
||||
|
||||
### 步骤一:新增客户端数据(例如增加小程序端)
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### 步骤二:配置前端请求头信息
|
||||
|
||||
需要在全局请求头 header 中增加 cientid <br>
|
||||
确保客户端所有请求都携带此id 可参考项目 `request.ts`
|
||||
|
||||

|
||||
|
||||
`VITE_APP_CLIENT_ID` 即配置文件中的客户端id。
|
||||
|
||||
**重点:不同客户端登录获取到的token不同与其他端不互通(例如: app登录获取到的token无法用于pc端接口查询)**
|
||||
|
||||
## 新增自定义登录方式授权类型
|
||||
|
||||
**重点说明: 不要单独增加登录接口 系统全局统一只有一个登录接口 只需增加不同的鉴权方式即可**
|
||||
|
||||
如何调试使用登录看这里 -> [关于登录调试步骤](/questions/login_step.md)
|
||||
|
||||
### 步骤一:新增字典数据
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### 步骤二:新增/修改客户端数据
|
||||
|
||||
### 步骤三:后端新增认证策略
|
||||
|
||||
新增策略实现类实现 `IAuthStrategy` 接口。<br>
|
||||
|
||||

|
||||
|
||||
参照已有策略实现类实现自定义参数校验登录方法逻辑。<br>
|
||||
|
||||

|
||||
|
||||
**注意修改 `@Service` 名称保证规范性**
|
||||
|
||||

|
||||
|
||||
`LoginBody` 校验参数(可自定义)<br>
|
||||
|
||||

|
||||
|
||||
例如 扩展小程序登录参数 只需要继承 `LoginBody <br>
|
||||
|
||||
`
|
||||
|
||||
校验分组(可自定义)<br>
|
||||
|
||||

|
||||
@@ -0,0 +1,86 @@
|
||||
# 代码生成
|
||||
- - -
|
||||
## 功能介绍
|
||||
|
||||
### 数据源配置
|
||||
|
||||

|
||||
|
||||
<font size="4">**项目适配多种类型数据库 可以在代码生成页面切换**</font><br>
|
||||
|
||||
> 填写对应的数据源名称 点击搜索按钮 即可切换到对应的数据源<br>
|
||||
|
||||

|
||||
|
||||
<font size="4">**>= 2.2.1版本 项目支持100+种数据库适配 在代码生成模块增加对应的数据库依赖即可**</font><br>
|
||||
|
||||

|
||||
|
||||
|
||||
### 导入数据表
|
||||
|
||||
> 点击导入按钮 会加载系统数据库所有的表<br>
|
||||
|
||||

|
||||
|
||||
> 选择需要的表 点击确定即可<br>
|
||||
|
||||
<br>
|
||||

|
||||
|
||||
### 编辑表生成结构
|
||||
|
||||
> 点击表对应的编辑按钮<br>
|
||||
|
||||

|
||||
|
||||
> 更改要生成表的数据<br>
|
||||
|
||||
<br>
|
||||

|
||||
|
||||
### 生成条件影响
|
||||
|
||||

|
||||
|
||||
|
||||
* `插入` `编辑` 影响生成 BO 类 与 前端添加编辑页面 是否有该字段
|
||||
* `列表` 影响生成 VO 类 与 前端列表页面展示 是否有该字段
|
||||
* `查询` 影响 前端页面是否有该字段的搜索框 与 后端代码是否生成对应的查询条件
|
||||
* `查询方式` 影响生成查询条件的类型
|
||||
* `必填` 影响 BO 类 与 页面是否强制校验
|
||||
* `显示类型` 影响生成页面使用何种展示组件
|
||||
* `字典类型` 影响页面是否生成与字典的关联
|
||||
|
||||
### 树表配置
|
||||
|
||||
> 编辑表生成信息 生成模板为 `树表` 填写对应数据即可<br>
|
||||
|
||||

|
||||
|
||||
### 主子表说明
|
||||
|
||||
框架不支持也不推荐使用主子表<br>
|
||||
原因一般业务场景 基本都是一对N表 多表关联场景<br>
|
||||
还有一些 主 => 子 <= 主 场景 需求很复杂 很少有单纯主子表场景出现<br>
|
||||
另外主子表关联 很容易出现 笛卡尔积 或者数据错乱等问题 需要自行sql调优场景<br>
|
||||
所以建议大家都按照 单表生成 自行编写业务逻辑
|
||||
|
||||
### 预览功能
|
||||
|
||||
> 配置好生成信息后 可以点击预览按钮<br>
|
||||
|
||||

|
||||
|
||||
> 系统会根据已经配置好的数据 生成对应的代码预览<br>
|
||||
> 可以再此处观察代码的生成结构和数据是否正确等<br>
|
||||
|
||||

|
||||
|
||||
|
||||
### 代码结构同步
|
||||
|
||||
> 实际开发中 难免会有表结构更改的需求<br>
|
||||
> 这时可以使用 同步功能 点击同步按钮 即可与实时数据库表进行字段同步<br>
|
||||
|
||||

|
||||
@@ -0,0 +1,250 @@
|
||||
# 导出功能
|
||||
|
||||
- - -
|
||||
|
||||
在本框架中引入了 `Easy Excel` 依赖(对 `Apache POI`进行了封装以及扩展),可以对数据进行导出操作(即写 Excel)。
|
||||
|
||||
[EasyExcel 文档地址](https://easyexcel.opensource.alibaba.com/)
|
||||
|
||||
## 导出功能使用流程说明
|
||||
|
||||
### 步骤一:定义导出实体对象
|
||||
|
||||
以框架中 `SysUserExportVo` 为例:
|
||||
|
||||
```Java
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@ExcelProperty(value = "用户序号")
|
||||
private Long userId;
|
||||
|
||||
// .......................
|
||||
|
||||
/**
|
||||
* 用户性别
|
||||
*/
|
||||
@ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "sys_user_sex")
|
||||
private String sex;
|
||||
|
||||
/**
|
||||
* 帐号状态(0正常 1停用)
|
||||
*/
|
||||
@ExcelProperty(value = "帐号状态", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "sys_normal_disable")
|
||||
private String status;
|
||||
```
|
||||
|
||||
> 说明:<br>
|
||||
> 1. 使用 `@ExcelProperty` 注解标注需要导出的属性。
|
||||
> 2. 注解 `@ExcelProperty` 中 `value` 属性代表表格头部标题字段,`converter` 代表使用的转换器,后面会详细说明。
|
||||
> 3. 注解 `@ExcelDictFormat` 为自定义注解,与自定义转换器结合使用,同样在后面进行详细说明。
|
||||
|
||||
### 步骤二:使用导出方法
|
||||
|
||||
以框架中 `SysUserController#export` 方法为例:
|
||||
|
||||
```Java
|
||||
/**
|
||||
* 导出用户列表
|
||||
*/
|
||||
@PostMapping("/export")
|
||||
public void export(SysUserBo user, HttpServletResponse response) {
|
||||
// 根据参数查询导出的用户列表数据
|
||||
List<SysUserVo> list = userService.selectUserList(user);
|
||||
// 将列表转换为导出对象列表
|
||||
List<SysUserExportVo> listVo = MapstructUtils.convert(list, SysUserExportVo.class);
|
||||
// 导出方法
|
||||
ExcelUtil.exportExcel(listVo, "用户数据", SysUserExportVo.class, response);
|
||||
}
|
||||
```
|
||||
|
||||
> 说明:<br>
|
||||
> 使用 `ExcelUtil.exportExcel` 方法完成导出功能,上述 Demo 传入参数分别是:导出对象集合,Excel sheet 表名称,导出对象类型,response。
|
||||
|
||||
## 框架工具使用说明
|
||||
|
||||
### 1:字典转换器
|
||||
|
||||
字典转换器 `ExcelDictConvert` 与自定义注解 `@ExcelDictFormat` 结合使用,标注在需要转换的属性上。
|
||||
|
||||
使用方式一:
|
||||
|
||||
```Java
|
||||
/**
|
||||
* 用户性别
|
||||
*/
|
||||
@ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "sys_user_sex")
|
||||
private String sex;
|
||||
```
|
||||
|
||||
使用方式二:
|
||||
|
||||
```Java
|
||||
/**
|
||||
* 用户性别
|
||||
*/
|
||||
@ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp="0=男,1=女,2=未知", separator=",")
|
||||
private String sex;
|
||||
```
|
||||
|
||||
`@ExcelDictFormat` 注解属性说明:
|
||||
|
||||
| 属性名称 | 属性类型 | 默认值 | 说明 |
|
||||
|------------------|--------|-----|-----------------------------------|
|
||||
| dictType | String | "" | 字典的type值 (如: sys_user_sex) |
|
||||
| readConverterExp | String | "" | 读取内容转表达式 (如: 0=男,1=女,2=未知) |
|
||||
| separator | String | "," | 与 readConverterExp 属性结合使用,表达式的分隔符 |
|
||||
|
||||
### 2:枚举转换器
|
||||
|
||||
字典转换器 `ExcelEnumConvert` 与自定义注解 `@ExcelEnumFormat` 结合使用,标注在需要转换的属性上。
|
||||
|
||||
使用方式:
|
||||
|
||||
```Java
|
||||
/**
|
||||
* 用户类型
|
||||
* </p>
|
||||
* 使用ExcelEnumFormat注解需要进行下拉选的部分
|
||||
*/
|
||||
@ExcelProperty(value = "用户类型", index = 1, converter = ExcelEnumConvert.class)
|
||||
@ExcelEnumFormat(enumClass = UserStatus.class, textField = "info")
|
||||
private String userStatus;
|
||||
```
|
||||
|
||||
`@ExcelEnumFormat` 注解属性说明:
|
||||
|
||||
| 属性名称 | 属性类型 | 默认值 | 说明 |
|
||||
|-----------|------------|------|------------------------------|
|
||||
| enumClass | Enum Class | - | 字典枚举类型 |
|
||||
| codeField | String | code | 字典枚举类中对应的 code 属性名称,默认为 code |
|
||||
| textField | String | text | 字典枚举类中对应的 text 属性名称,默认为 text |
|
||||
|
||||
### 3:合并单元格
|
||||
|
||||
`@CellMerge` 注解用于合并相同的列数据,需要结合 `CellMergeStrategy` 策略使用,标注在需要转换的属性上。
|
||||
|
||||
使用方式:
|
||||
|
||||
步骤一:在属性标注 `@CellMerge` 注解:
|
||||
```Java
|
||||
/**
|
||||
* 部门id
|
||||
*/
|
||||
@CellMerge
|
||||
@ExcelProperty(value = "部门id")
|
||||
private Long deptId;
|
||||
```
|
||||
|
||||
`@CellMerge` 注解属性说明:
|
||||
|
||||
| 属性名称 | 属性类型 | 默认值 | 说明 |
|
||||
|---------|----------|-----|------------------------------|
|
||||
| index | int | -1 | 合并列的下标,建议使用默认值 |
|
||||
| mergeBy | String[] | {} | 合并需要依赖的其他字段名称(基于这个字段内容做合并条件) |
|
||||
|
||||
|
||||
步骤二:导出方法开启合并:
|
||||
```Java
|
||||
/**
|
||||
* 导出测试单表列表
|
||||
*/
|
||||
@PostMapping("/export")
|
||||
public void export(@Validated TestDemoBo bo, HttpServletResponse response) {
|
||||
List<TestDemoVo> list = testDemoService.queryList(bo);
|
||||
// 参数 true 表示开启合并单元格策略
|
||||
ExcelUtil.exportExcel(list, "测试单表", TestDemoVo.class, true, response);
|
||||
}
|
||||
```
|
||||

|
||||
|
||||
### 4:复杂 Excel 导出示例
|
||||
`TestExcelController` 提供了几种导出示例,如果需要可以参照相应方法进行导出。
|
||||
|
||||
#### 4.1:单列表多数据导出(模板导出)
|
||||
|
||||
模板内容:
|
||||
|
||||

|
||||
|
||||
模板位置:`ruoyi-example/ruoyi-demo/src/main/resources/excel/`
|
||||
|
||||
导出示例代码:参考 demo 模块 `TestExcelController` 模板写法请查看 `EasyExcel` 文档
|
||||
|
||||
导出结果:
|
||||
|
||||

|
||||
|
||||
#### 4.2:多列表多数据导出(模板导出)
|
||||
|
||||
模板内容:
|
||||
|
||||

|
||||
|
||||
模板位置:`ruoyi-example/ruoyi-demo/src/main/resources/excel/`
|
||||
|
||||
导出示例代码:参考 demo 模块 `TestExcelController` 模板写法请查看 `EasyExcel` 文档
|
||||
|
||||
导出结果:
|
||||
|
||||

|
||||
|
||||
#### 4.3:导出下拉框
|
||||
|
||||
`ExcelDictFormat` 注解指定的字典项默认都会转换成下拉框
|
||||
|
||||
自定义导出省市区下拉框示例代码:参考 demo 模块 `TestExcelController`
|
||||
|
||||
导出结果:
|
||||
|
||||

|
||||
|
||||
## Easy Excel 常用注解
|
||||
|
||||
`Easy Excel` 提供了丰富的注解可以对导出对象进行定制化操作,这里的注解说明针对的是原生注解,自定义注解会结合转换器一起进行说明。
|
||||
|
||||
| 类型 | 注解名称 | 使用举例 | 说明 |
|
||||
|-------|-------------------------|------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
|
||||
| 格式化注解 | @DateTimeFormat | @DateTimeFormat(value=格式化值) | 对字符串进行日期格式化 (参照 `java.text.SimpleDateFormat` 书写即可) |
|
||||
| 格式化注解 | @NumberFormat | @NumberFormat(value=格式化值, roundingMode=舍入模式) | 对字符串进行数值格式化 (参照 `java.text.DecimalFormat` 书写即可, `roundingMode` 默认 `RoundingMode.HALF_UP`) |
|
||||
| 样式注解 | @ColumnWidth | @ColumnWidth(value=值) | 设置列宽 |
|
||||
| 样式注解 | @ContentFontStyle | @ContentFontStyle(color=颜色) | 可以设置字体类型,颜色,粗细,是否斜体,下划线等,具体可查看注解 `@ContentFontStyle` |
|
||||
| 样式注解 | @ContentLoopMerge | @ContentLoopMerge(eachRow=行值, columnExtend=列值) | 设置循环合并的区域 |
|
||||
| 样式注解 | @ContentRowHeight | @ContentRowHeight(value=值) | 设置内容行高 |
|
||||
| 样式注解 | @ContentStyle | - | 设置单元格样式,具体可查看注解 `@ContentStyle` |
|
||||
| 样式注解 | @HeadFontStyle | @HeadFontStyle(color=颜色) | 设置表头字体格式,类似 `@ContentFontStyle`,具体可查看注解 `@HeadFontStyle` |
|
||||
| 样式注解 | @HeadRowHeight | @HeadRowHeight(value=值) | 设置表头行高 |
|
||||
| 样式注解 | @HeadStyle | - | 设置表头样式,具体可查看注解 `@HeadStyle` |
|
||||
| 样式注解 | @OnceAbsoluteMerge | @OnceAbsoluteMerge(firstRowIndex=开始行下标, lastRowIndex=结束行下标, firstColumnIndex=开始列下标, lastColumnIndex=结束列下标) | 根据设置值合并单元格 |
|
||||
| 属性注解 | @ExcelIgnore | @ExcelIgnore | 导出忽略该字段 |
|
||||
| 属性注解 | @ExcelIgnoreUnannotated | @ExcelIgnoreUnannotated | 默认不管加不加 `@ExcelProperty` 的注解的所有字段都会参与读写,加了 `@ExcelIgnoreUnannotated` 注解以后,不加 `@ExcelProperty` 注解的字段就不会参与 |
|
||||
| 属性注解 | @ExcelProperty | @ExcelProperty(value=值, order=排序值, index=下标, converter=转换器) | 默认按照对象属性顺序导出,如果设置了 `order` 以及 `index`,优先级 `index` > `order` > 默认;converter 可以自定义 |
|
||||
|
||||
## 扩展说明
|
||||
|
||||
### 自定义转换器实现
|
||||
|
||||
由于业务需要,原生注解不一定能够符合需要,因而衍生出了自定义转换器。能够实现定制化的内容转换需要。
|
||||
以下以框架中的字典转换器 `ExcelDictConvert` 为例进行说明。
|
||||
|
||||
字典转换器 `ExcelDictConvert`,字典转换器使用了自定义注解 `@ExcelDictFormat` 配合使用。
|
||||
|
||||
_**注:自定义转换器并非一定需要自定义注解,也可以针对已有的注解进行自定义转换实现。**_
|
||||
|
||||
#### 实现方式
|
||||
|
||||
自定义转换器需要实现 `com.alibaba.excel.converters.Converter` 接口,实现接口中的方法。
|
||||
|
||||

|
||||
|
||||
转换方法 `ExcelDictConvert#convertToExcelData` :
|
||||
|
||||

|
||||
|
||||
## 更多功能
|
||||
|
||||
更多导出功能使用可以参照 `Easy Excel` [官方文档](https://easyexcel.opensource.alibaba.com/docs/current/api/write)。
|
||||
@@ -0,0 +1,202 @@
|
||||
# 导入功能
|
||||
- - -
|
||||
|
||||
在本框架中引入了 `Easy Excel` 依赖(对 `Apache POI`进行了封装以及扩展),可以对数据进行导入操作(即读 Excel)。
|
||||
|
||||
## 导入功能使用流程说明
|
||||
|
||||
### 步骤一:定义导入实体对象
|
||||
|
||||
以框架中 `SysUserImportVo` 为例:
|
||||
|
||||
```java
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@ExcelProperty(value = "用户序号")
|
||||
private Long userId;
|
||||
|
||||
// .......................
|
||||
|
||||
/**
|
||||
* 用户性别
|
||||
*/
|
||||
@ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "sys_user_sex")
|
||||
private String sex;
|
||||
|
||||
/**
|
||||
* 帐号状态(0正常 1停用)
|
||||
*/
|
||||
@ExcelProperty(value = "帐号状态", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "sys_normal_disable")
|
||||
private String status;
|
||||
```
|
||||
|
||||
> 说明:<br>
|
||||
> 1. 使用 `@ExcelProperty` 注解标注需要导入的属性。
|
||||
> 2. 注解 `@ExcelProperty` 中 `value` 属性代表表格头部标题字段,`converter` 代表使用的转换器,后面会详细说明。
|
||||
> 3. 注解 `@ExcelDictFormat` 为自定义注解,与自定义转换器结合使用,同样在后面进行详细说明。
|
||||
> 4. 对象禁止使用链式注解 `@Accessors(chain = true)`,会找不到set方法。
|
||||
|
||||
### 步骤二:使用导入方法
|
||||
|
||||
以框架中 `SysUserController#importData` 方法为例:
|
||||
|
||||
```Java
|
||||
/**
|
||||
* 导入数据
|
||||
*
|
||||
* @param file 导入文件
|
||||
* @param updateSupport 是否更新已存在数据
|
||||
*/
|
||||
@Log(title = "用户管理", businessType = BusinessType.IMPORT)
|
||||
@SaCheckPermission("system:user:import")
|
||||
@PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
|
||||
// 导入方法
|
||||
ExcelResult<SysUserImportVo> result = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class, new SysUserImportListener(updateSupport));
|
||||
return R.ok(result.getAnalysis());
|
||||
}
|
||||
```
|
||||
> 说明:<br>
|
||||
> 使用 `ExcelUtil.importExcel` 方法完成导出功能,上述 Demo 传入参数分别是:导入文件流,导入对象类型,导入监听器 `SysUserImportListener`。
|
||||
|
||||
## 框架工具使用说明
|
||||
|
||||
### 1:字典转换器
|
||||
|
||||
字典转换器 `ExcelDictConvert` 与自定义注解 `@ExcelDictFormat` 结合使用,标注在需要转换的属性上。
|
||||
|
||||
使用方式一:
|
||||
|
||||
```Java
|
||||
/**
|
||||
* 用户性别
|
||||
*/
|
||||
@ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "sys_user_sex")
|
||||
private String sex;
|
||||
```
|
||||
|
||||
使用方式二:
|
||||
|
||||
```Java
|
||||
/**
|
||||
* 用户性别
|
||||
*/
|
||||
@ExcelProperty(value = "用户性别", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp="0=男,1=女,2=未知", separator=",")
|
||||
private String sex;
|
||||
```
|
||||
|
||||
`@ExcelDictFormat` 注解属性说明:
|
||||
|
||||
| 属性名称 | 属性类型 | 默认值 | 说明 |
|
||||
|------------------|--------|-----|-----------------------------------|
|
||||
| dictType | String | "" | 字典的type值 (如: sys_user_sex) |
|
||||
| readConverterExp | String | "" | 读取内容转表达式 (如: 0=男,1=女,2=未知) |
|
||||
| separator | String | "," | 与 readConverterExp 属性结合使用,表达式的分隔符 |
|
||||
|
||||
### 2:枚举转换器
|
||||
|
||||
字典转换器 `ExcelEnumConvert` 与自定义注解 `@ExcelEnumFormat` 结合使用,标注在需要转换的属性上。
|
||||
|
||||
使用方式:
|
||||
|
||||
```Java
|
||||
/**
|
||||
* 用户类型
|
||||
* </p>
|
||||
* 使用ExcelEnumFormat注解需要进行下拉选的部分
|
||||
*/
|
||||
@ExcelProperty(value = "用户类型", index = 1, converter = ExcelEnumConvert.class)
|
||||
@ExcelEnumFormat(enumClass = UserStatus.class, textField = "info")
|
||||
private String userStatus;
|
||||
```
|
||||
|
||||
`@ExcelEnumFormat` 注解属性说明:
|
||||
|
||||
| 属性名称 | 属性类型 | 默认值 | 说明 |
|
||||
|-----------|------------|------|------------------------------|
|
||||
| enumClass | Enum Class | - | 字典枚举类型 |
|
||||
| codeField | String | code | 字典枚举类中对应的 code 属性名称,默认为 code |
|
||||
| textField | String | text | 字典枚举类中对应的 text 属性名称,默认为 text |
|
||||
|
||||
|
||||
### 3:导入监听器
|
||||
|
||||
#### 3.1:ExcelListener 监听器接口
|
||||
|
||||
`ExcelListener` 扩展了 `ReadListener` 接口,增加了获取结果方法。
|
||||
|
||||

|
||||
|
||||
#### 3.2:DefaultExcelListener 默认监听器
|
||||
|
||||
`DefaultExcelListener` 默认监听器在读 Excel 时调用,主要对数据进行校验、解析、异常处理、返回结果等。导入操作时如果没有特别指定则使用该监听器。
|
||||
|
||||
#### 3.3:SysUserImportListener 用户导入监听器
|
||||
|
||||
`SysUserImportListener` 用户导入监听器是在用户导入时调用的监听器。
|
||||
|
||||
该监听器重写了 `invoke` 反射接口,对导入的用户数据进行了校验;重写了 `getExcelResult` 获取结果接口,返回结果数据。
|
||||
|
||||
#### 3.4:ExportDemoListener 带下拉框的导入监听器
|
||||
|
||||
`ExportDemoListener` 是对带有下拉框的 Excel 进行处理的导入监听器。
|
||||
|
||||
## Easy Excel 常用注解
|
||||
|
||||
`Easy Excel` 提供了丰富的注解可以对导出对象进行定制化操作,这里的注解说明针对的是原生注解。
|
||||
|
||||
| 类型 | 注解名称 | 使用举例 | 说明 |
|
||||
|-------|-------------------------|------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
|
||||
| 格式化注解 | @DateTimeFormat | @DateTimeFormat(value=格式化值) | 对字符串进行日期格式化 (参照 `java.text.SimpleDateFormat` 书写即可) |
|
||||
| 格式化注解 | @NumberFormat | @NumberFormat(value=格式化值, roundingMode=舍入模式) | 对字符串进行数值格式化 (参照 `java.text.DecimalFormat` 书写即可, `roundingMode` 默认 `RoundingMode.HALF_UP`) |
|
||||
| 属性注解 | @ExcelIgnore | @ExcelIgnore | 导出忽略该字段 |
|
||||
| 属性注解 | @ExcelIgnoreUnannotated | @ExcelIgnoreUnannotated | 默认不管加不加 `@ExcelProperty` 的注解的所有字段都会参与读写,加了 `@ExcelIgnoreUnannotated` 注解以后,不加 `@ExcelProperty` 注解的字段就不会参与 |
|
||||
| 属性注解 | @ExcelProperty | @ExcelProperty(value=值, order=排序值, index=下标, converter=转换器) | 默认按照对象属性顺序导出,如果设置了 `order` 以及 `index`,优先级 `index` > `order` > 默认;converter 可以自定义 |
|
||||
|
||||
## 扩展使用
|
||||
|
||||
### 扩展一:自定义转换器实现
|
||||
|
||||
由于业务需要,原生注解不一定能够符合需要,因而衍生出了自定义转换器。能够实现定制化的内容转换需要。
|
||||
以下以框架中的字典转换器 `ExcelDictConvert` 为例进行说明。
|
||||
|
||||
字典转换器 `ExcelDictConvert`,字典转换器使用了自定义注解 `@ExcelDictFormat` 配合使用。
|
||||
|
||||
_**注:自定义转换器并非一定需要自定义注解,也可以针对已有的注解进行自定义转换实现。**_
|
||||
|
||||
#### 实现方式
|
||||
|
||||
自定义转换器需要实现 `com.alibaba.excel.converters.Converter` 接口,实现接口中的方法。
|
||||
|
||||

|
||||
|
||||
转换方法 `ExcelDictConvert#convertToJavaData` :
|
||||
|
||||

|
||||
|
||||
### 扩展二:自定义监听器实现
|
||||
|
||||
自定义监听器主要用于在读取解析 Excel 数据时进行自定义操作。
|
||||
以下以框架中的用户导入监听器 `SysUserImportListener` 为例进行说明。
|
||||
|
||||
#### 实现方式
|
||||
1. 继承分析事件监听器 `AnalysisEventListener` 以及实现 Excel 监听器 `ExcelListener`。
|
||||
|
||||

|
||||
|
||||
2. 显示使用构造函数,否则将导致空指针。
|
||||
|
||||

|
||||
|
||||
3. 实现 `invoke` 方法,对数据进行解析操作,可以在此方法对数据进行合法性判断。
|
||||
|
||||
4. 实现 `getExcelResult` 方法,对结果进行操作,例如返回成功、失败的统计数据。
|
||||
|
||||
## 更多功能
|
||||
|
||||
更多导入功能使用可以参照 `Easy Excel` [官方文档](https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read)。
|
||||
@@ -0,0 +1,124 @@
|
||||
# 关于OSS模块使用
|
||||
- - -
|
||||
## 重点注意事项
|
||||
|
||||
`桶/存储区域` 系统会根据配置自行创建分配权限<br>
|
||||
~~如手动配置需要设置 `公有读` 权限 否则文件无法访问~~(`aliyun` 还需开通跨域配置)<br>
|
||||
1.4.0 版本支持配置`公有/私有`权限(`aliyun` 还需开通跨域配置)<br>
|
||||
访问站点 后严禁携带其他 `url` 例如: `/`, `/ruoyi` 等<br>
|
||||
**阿里云与腾讯云SDK访问站点中不能包含桶名 系统会自动处理** <br>
|
||||
**minio 站点不允许使用 localhost 请使用 127.0.0.1** <br>
|
||||
**访问站点与自定义域名 都不要包含 `http` `https` 前缀 设置`https`请使用选项处理**
|
||||
|
||||
## 代码使用
|
||||
|
||||
> 参考 `SysOssService.upload` 用法 <br>
|
||||
> 使用 `OssFactory.instance()` 获取当前启用的 `OssClient` 实例<br>
|
||||
> 进行功能调用 获取返回值后 存储到对应的业务表
|
||||
|
||||

|
||||
|
||||
|
||||
## 功能配置
|
||||
|
||||
### 配置OSS
|
||||
|
||||
> 进入 `系统管理 -> 文件管理 -> 配置管理` 填写对应的OSS服务相关配置<br>
|
||||
|
||||
<br>
|
||||
<br
|
||||

|
||||
|
||||
<font size="6">**重点说明**</font>
|
||||
|
||||
> 云厂商只需修改 `访问站点`对应的域 切勿乱改(云厂商强烈建议绑定自定义域名使用 七牛云必须绑定[官方规定])<br>
|
||||
|
||||

|
||||
|
||||
> 七牛云 访问站点<br>
|
||||
|
||||
|
||||
<br>
|
||||

|
||||
|
||||
> 阿里云 访问站点
|
||||
|
||||

|
||||
|
||||
> 腾讯云 访问站点
|
||||
|
||||

|
||||
|
||||
### MinIO 使用 https访问站点
|
||||
|
||||
**注意:S3 API 签名计算算法不支持托管 MinIO Server API 的代理方案**
|
||||
|
||||
[ minio https 配置方式](https://blog.csdn.net/Michelle_Zhong/article/details/126484358)
|
||||
|
||||
### 切换OSS
|
||||
|
||||
> 再配置列表点击 `状态` 按钮开启即可(注意: 只能开启一个OSS默认配置)<br>
|
||||
> 手动使用 `OssFactory.instance("configKey")` <br>
|
||||
|
||||

|
||||
|
||||
### 扩展分类
|
||||
|
||||
> 如有文件分类 建议创建多个 oss配置 进行切换存储<br>
|
||||
|
||||
例如: 创建一个 图片存储的 oss配置<br>
|
||||
指定唯一的 `configKey` 与 `前缀目录` 或 直接使用独立的`桶`<br>
|
||||
独立桶的特点 可以自定义访问权限<br>
|
||||
例如: 创建一个私有文件存储桶 不对外开放<br>
|
||||
|
||||

|
||||
|
||||
> 指定需要使用的配置<br>
|
||||
> 使用 `OssFactory.instance("image")` 获取的 `OssClient` 会加载上图的配置 从而达到上传不同的目录或桶
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
### 上传图片或文件
|
||||
|
||||
> 进入 `系统管理 -> 文件管理` 点击 `上传文件` 或 `上传图片` 根据选项选择即可 会对应上传到配置开启的OSS内<br>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||

|
||||
|
||||
### 列表展示
|
||||
|
||||
> 默认展示图片(可预览) 文件会展示路径<br>
|
||||
|
||||
<br>
|
||||

|
||||
|
||||
> 可以点击 `预览禁用启用` 按钮对是否展示进行更改
|
||||
|
||||

|
||||
|
||||
> 点击禁用后 图片会变成路径展示
|
||||
|
||||

|
||||
|
||||
> 也可再 `参数设置` 更改预览状态 将 `OSS预览列表资源` 改为 `false` 即可关闭预览
|
||||
|
||||

|
||||
|
||||
### 删除功能
|
||||
|
||||
> 点击列表上方或后方 `删除` 按钮 会根据OSS服务商类型 调用对应的删除(注意: 需确保对应的服务商配置正确)<br>
|
||||
> 可勾选多服务商类型的文件进行删除 系统会自动判断
|
||||
|
||||

|
||||

|
||||
|
||||
### 下载功能
|
||||
|
||||
> 点击列表后方对应资源的 `下载` 按钮 根据需求填写文件名 点击确认即可完成下载
|
||||
|
||||

|
||||

|
||||
@@ -0,0 +1,29 @@
|
||||
# 分页功能
|
||||
- - -
|
||||
|
||||
## 重点说明
|
||||
|
||||
> 项目使用 `mybatis-plus` 分页插件 实现分页功能 大致用法与 MP 一致 [MP分页文档](https://baomidou.com/pages/97710a/) <br>
|
||||
> 项目已配置分页合理化 页数溢出 例如: 一共5页 查了第6页 默认返回第一页 <br>
|
||||
|
||||

|
||||
|
||||
## 代码用法
|
||||
|
||||
> `Controller` 使用 `PageQuery` 接收分页参数 具体参数参考 `PageQuery`
|
||||
|
||||

|
||||
|
||||
> 构建 `Mybatis-Plus` 分页对象 <br>
|
||||
> 使用 `PageQuery#build()` 方法 可快速(基于当前对象数据)构建 `MP` 分页对象
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
具体用法与 `MP` 一致
|
||||
|
||||
> 自定义 `SQL` 方法分页 <br>
|
||||
> 只需在 `Mapper` 方法第一个参数和返回值 重点: 第一个参数 标注分页对象
|
||||
|
||||
<br>
|
||||

|
||||
@@ -0,0 +1,158 @@
|
||||
# 参数校验
|
||||
- - -
|
||||
|
||||
参数校验在日常开发中十分常见,在本框架中引入了 `spring-boot-starter-validation` 依赖,底层基于 `hibernate-validator`,可以对参数进行校验。
|
||||
|
||||
## 参数校验使用
|
||||
|
||||
### 方法一:使用 `@Validated` 注解
|
||||
|
||||
#### 步骤一:标注 `@Validated`
|
||||
|
||||
`@Validated` 可以标注在类上,或者是参数前。
|
||||
|
||||
```Java
|
||||
/** 标注在类上 **/
|
||||
@Validated
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
public class AuthController {
|
||||
|
||||
@PostMapping("/login")
|
||||
public R<LoginVo> login(@RequestBody LoginBody body) {
|
||||
// ...
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
```Java
|
||||
/** 标注在参数前 **/
|
||||
@PostMapping
|
||||
public R<Void> add(@Validated @RequestBody SysUserBo user) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 步骤二:标注校验注解
|
||||
|
||||
在参数中加入校验注解。
|
||||
|
||||
```Java
|
||||
public class SysUserBo {
|
||||
|
||||
@NotBlank(message = "用户账号不能为空")
|
||||
@Size(min = 0, max = 30, message = "用户账号长度不能超过{max}个字符")
|
||||
private String userName;
|
||||
|
||||
@NotBlank(message = "用户昵称不能为空")
|
||||
@Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符")
|
||||
private String nickName;
|
||||
|
||||
@Email(message = "邮箱格式不正确")
|
||||
@Size(min = 0, max = 50, message = "邮箱长度不能超过{max}个字符")
|
||||
private String email;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
常见校验注解见文末附表。
|
||||
|
||||
_注:message 支持 EL 表达式,{max} 直接读取前面的参数值。_
|
||||
|
||||
### 方法二:使用校验工具类 `ValidatorUtils`
|
||||
|
||||
`org.dromara.common.core.utils.ValidatorUtils`
|
||||
|
||||

|
||||
|
||||
使用方式 1:校验所有带有校验注解的属性
|
||||
|
||||
```Java
|
||||
// 校验所有带有校验注解的属性
|
||||
ValidatorUtils.validate(object);
|
||||
```
|
||||
|
||||
使用方式 2:按照分组校验属性(可以传多个分组)
|
||||
|
||||
```Java
|
||||
// 按照分组校验属性(可以传多个分组)
|
||||
ValidatorUtils.validate(object, group);
|
||||
```
|
||||
|
||||
## 扩展使用
|
||||
|
||||
### 扩展一:自定义校验注解
|
||||
|
||||
除了已有的校验注解以外,可以结合业务进行自定义。
|
||||
|
||||
以框架中的 `@Xss` 注解为例进行说明。
|
||||
|
||||
```Java
|
||||
@Xss(message = "用户账号不能包含脚本字符")
|
||||
@NotBlank(message = "用户账号不能为空")
|
||||
@Size(min = 0, max = 30, message = "用户账号长度不能超过{max}个字符")
|
||||
private String userName;
|
||||
```
|
||||
|
||||
#### 1:新增 `@Xss` 注解
|
||||
|
||||
`org.dromara.common.core.xss.Xss`
|
||||
|
||||

|
||||
|
||||
#### 2:自定义校验器
|
||||
|
||||
自定义校验器实现 `jakarta.validation.ConstraintValidator` 接口。
|
||||
|
||||
`org.dromara.common.core.xss.XssValidator`
|
||||
|
||||

|
||||
|
||||
### 扩展二:自定义分组校验
|
||||
|
||||
同一个对象在不同的请求中需要校验的参数不同,则可以使用分组校验。
|
||||
|
||||
#### 1:自定义分组
|
||||
|
||||

|
||||
|
||||
#### 2:`@Validated` 注解指定分组
|
||||
|
||||

|
||||
|
||||
#### 3:校验注解中指定分组
|
||||
|
||||

|
||||
|
||||
## 附录:常用校验注解
|
||||
|
||||
| 注解 | 使用(只列举特殊参数值) | 参数类型 | 说明 |
|
||||
|------------------|--------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------|
|
||||
| @AssertFalse | @AssertFalse | boolean / Boolean | 元素值必须为 false |
|
||||
| @AssertTrue | @AssertTrue | boolean / Boolean | 元素值必须为 true |
|
||||
| @DecimalMax | @DecimalMax(value=值) | - BigDecimal <br> - BigInteger <br> - CharSequence <br> - byte, short, int, long 及其包装类 | 元素必须是一个数字,其值必须小于或等于指定的最大值 |
|
||||
| @DecimalMin | @DecimalMin(value=值) | - BigDecimal <br> - BigInteger <br> - CharSequence <br> - byte, short, int, long 及其包装类 | 元素必须是一个数字,其值必须大于或等于指定的最小值 |
|
||||
| @Digits | @Digits(integer=整数位值, fraction=小数位值) | - BigDecimal <br> - BigInteger <br> - CharSequence <br> - byte, short, int, long 及其包装类 | 元素必须符合整数位以及小数位范围值 |
|
||||
| @Email | @Email(regexp=正则表达式, flags=标志) | CharSequence | 元素是否符合正则表达式(正则表达式非必传) |
|
||||
| @Future | @Future | - java.util.Date <br> - java.util.Calendar <br> - java.time.Instant <br> - java.time.LocalDate <br> - java.time.LocalDateTime <br> - java.time.LocalTime <br> - java.time.MonthDay <br> - java.time.OffsetDateTime <br> - java.time.OffsetTime <br> - java.time.Year <br> - java.time.YearMonth <br> - java.time.ZonedDateTime <br> - java.time.chrono.HijrahDate <br> - java.time.chrono.JapaneseDate <br> - java.time.chrono.MinguoDate <br> - java.time.chrono.ThaiBuddhistDate | 元素必须是未来的时刻、日期或时间 |
|
||||
| @FutureOrPresent | @FutureOrPresent | 同 @Future | 元素必须是当前或未来的时刻、日期或时间 |
|
||||
| @Length | @Length(min=最小值, max=最大值) | - CharSequence | 验证字符串是否在包含的 min 和 max 之间 |
|
||||
| @Max | @Max(value=值) | - BigDecimal <br> - BigInteger <br> - byte, short, int, long 及其包装类 | 元素必须是一个数字,其值必须小于或等于指定的最大值 |
|
||||
| @Min | @Min(value=值) | - BigDecimal <br> - BigInteger <br> - byte, short, int, long 及其包装类 | 元素必须是一个数字,其值必须大于或等于指定的最小值 |
|
||||
| @Negative | @Negative | - BigDecimal <br> - BigInteger <br> - byte,short,int,long,float,double 及其包装类 | 元素必须是一个严格的负数(即 0 被视为无效值) |
|
||||
| @NegativeOrZero | @NegativeOrZero | - BigDecimal <br> - BigInteger <br> - byte,short,int,long,float,double 及其包装类 | 元素必须为负数或 0 |
|
||||
| @NotBlank | @NotBlank | CharSequence | 元素不能为 null,并且必须至少包含一个非空白字符 |
|
||||
| @NotEmpty | @NotEmpty | - CharSequence <br> - Collection <br> - Map <br> - Array | 元素不能为 null 或空集合 |
|
||||
| @NotNull | @NotNull | 不限类型 | 元素不能为 null |
|
||||
| @Null | @Null | 不限类型 | 元素必须为 null |
|
||||
| @Past | @Past | 同 @Future | 元素必须是过去的瞬间、日期或时间 |
|
||||
| @PastOrPresent | @PastOrPresent | 同 @Future | 元素必须是过去或现在的瞬间、日期或时间 |
|
||||
| @Pattern | @Pattern(regexp=正则表达式, flags=标志) | CharSequence | 元素必须与指定的正则表达式匹配(正则表达式遵循 Java 正则表达式约定) |
|
||||
| @Positive | @Positive | - BigDecimal <br> - BigInteger <br> - byte,short,int,long,float,double 及其包装类 | 元素必须是一个严格的正数(即 0 被视为无效值) |
|
||||
| @PositiveOrZero | @PositiveOrZero | - BigDecimal <br> - BigInteger <br> - byte,short,int,long,float,double 及其包装类 | 元素必须为正数或 0 |
|
||||
| @Range | @Range(min=最小值, max=最大值) | - BigDecimal <br> - BigInteger <br> - CharSequence <br> - byte, short, int, long 及其包装类 | 验证元素是否在包含的 min 和 max 之间 |
|
||||
| @Size | @Size(min=最小值, max=最大值) | - CharSequence <br> - Collection <br> - Map <br> - Array | 验证元素是否在包含的 min 和 max 之间 |
|
||||
| @Valid | @Valid | 对象 | 级联验证 |
|
||||
|
||||
更多注解可参考包: `org.hibernate.validator`
|
||||
@@ -0,0 +1,144 @@
|
||||
# 关于数据权限
|
||||
- - -
|
||||
* 参考 demo 模块用法(需导入 test.sql 文件)
|
||||
|
||||
### 新版数据权限功能:
|
||||
1.支持自动注入 sql 数据过滤<br>
|
||||
2.查询、更新、删除 限制<br>
|
||||
3.支持自定义数据字段过滤<br>
|
||||
4.模板支持 spel 语法实现动态 Bean 处理<br>
|
||||
5.支持与菜单权限标识符联合使用(2.2.X新功能)
|
||||
|
||||
### 数据权限相关代码
|
||||
|
||||
| 类 | 说明 | 功能 |
|
||||
|-------------------------------|-----------------|----------------------------------------|
|
||||
| DataScopeType | 数据权限模板定义 | 用于定义数据权限模板 |
|
||||
| DataPermission | 数据权限组注解 | 用于标注开启数据权限 (默认过滤部门权限) |
|
||||
| DataColumn | 具体的数据权限字段标注 | 用于替换数据权限模板内的 key 变量 |
|
||||
| PlusDataPermissionInterceptor | 数据权限 sql 拦截器 | 用于拦截所有 sql 检查是否标注了 `DataPermission` 注解 |
|
||||
| PlusDataPermissionHandler | 数据权限处理器 | 用于处理被拦截到的 sql 为其添加数据权限过滤条件 |
|
||||
| DataPermissionHelper | 数据权限助手 | 操作数据权限上下文变量 |
|
||||
| SysDataScopeService | 自定义 Bean 处理数据权限 | 用于自定义扩展 |
|
||||
|
||||
## 忽略数据权限
|
||||
|
||||
1.如果需要指定单独 SQL 不开启过滤,可在对应的 Mapper 接口添加如下忽略注解:
|
||||
```
|
||||
@InterceptorIgnore(dataPermission = "true")
|
||||
```
|
||||
|
||||
2.如果需要在业务层忽略数据权限,可调用以下方法:
|
||||
```
|
||||
# 无返回值
|
||||
DataPermissionHelper.ignore(() -> { 业务代码 });
|
||||
# 有返回值
|
||||
Class result = DataPermissionHelper.ignore(() -> { return 业务代码 });
|
||||
```
|
||||
|
||||
### 使用方式 `参考demo模块`
|
||||
数据权限体系 `用户 -> 多角色 => 角色 -> 单数据权限`
|
||||
> 例子: 用户A 拥有两个角色<br>
|
||||
> 角色A 部门经理 可查看 本部门及以下部门的数据<br>
|
||||
> 角色B 兼职开发 可查看 仅自己的数据
|
||||
|
||||
> 创建角色 test1 为 本部门及以下
|
||||
|
||||

|
||||
|
||||
> 创建角色 test2 为 仅本人
|
||||
|
||||

|
||||
|
||||
> 将其分配给用户 test
|
||||
|
||||

|
||||
|
||||
### 编写列表查询(注意: 数据权限注解只能在 Mapper 层使用)
|
||||
|
||||
> 标注数据权限注解 `dept_id` 为过滤部门字段 `user_id` 为过滤创建用户
|
||||
|
||||

|
||||
|
||||
### 重点注意: 如下情况不生效
|
||||
|
||||
> 有自定义实现方法 最终执行的mapper不是这个方法 所以无法生效
|
||||
>
|
||||
> 解决方案: 一直往下点 找到最终的执行mapper重写即可
|
||||
|
||||

|
||||
|
||||
### 编写数据权限模板
|
||||
|
||||

|
||||
|
||||
1.`code` 为关联角色的数据权限 `code`<br>
|
||||
2.`sqlTemplate` 为 sql 模板<br>
|
||||
`#{#deptName}` 为模板变量 对应权限注解的 `key`<br>
|
||||
`#{@sdss}` 为模板 Bean 调用 调用其 Bean 的处理方法<br>
|
||||
3.`elseSql` 为兜底 sql 处理当前角色与标注的注解 无对应的情况<br>
|
||||
例如 数据权限为仅本人 且 方法并未标注具体过滤注解 则 填充 `1 = 0` 使条件不满足 不允许查看<br>
|
||||
更详细用法可以参考 `DataScopeType` 注释
|
||||
|
||||
### 测试代码
|
||||
|
||||
> 使用 `管理员` 用户优先测试
|
||||
|
||||

|
||||
|
||||
> 使用 `test` 用户测试
|
||||
|
||||

|
||||
|
||||
> 使用 `test` 删除一条不属于自己的数据
|
||||
> sql执行为不满足条件 不允许删除
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
> 使用 `test` 修改与删除同理<br>
|
||||
> 具体实现为 更新和删除方法 标注数据权限注解
|
||||
|
||||

|
||||
|
||||
### 自定义SQL模板
|
||||
|
||||
> 1.首先在角色管理 数据权限下拉框 添加自定义模板<br>
|
||||
> 为什么不放置到系统字典问题: 因数据权限与模板绑定 不应随意改动 最好事先定义好
|
||||
|
||||

|
||||
|
||||
> 2.代码 `DataScopeType` 自定义一个SQL模板
|
||||
|
||||

|
||||
|
||||
> 3.标注权限注解
|
||||
|
||||

|
||||
|
||||
> 4.设置数据权限变量
|
||||
|
||||

|
||||
|
||||
> 5.测试
|
||||
|
||||

|
||||
|
||||
### mybatis-plus 原生方法 增加数据权限过滤
|
||||
|
||||
> 首先查看需要重写的方法源码 重点`方法源码` `方法源码` `方法源码`<br>
|
||||
> 例如重写 `selectPage` 方法<br>
|
||||
|
||||

|
||||
|
||||
> 复制源码到自己的 `Mapper` 并增加数据权限注解 注意左边出现重写图标 即为重写成功<br>
|
||||
|
||||

|
||||
|
||||
### 支持类标注
|
||||
|
||||
> 获取规则 `方法 > 类` 注意: 类标注后 所有方法(包括父类方法) 都会进行数据权限过滤
|
||||
|
||||

|
||||
@@ -0,0 +1,178 @@
|
||||
# 权限控制
|
||||
- - -
|
||||
|
||||
本文采用 `Sa-Token` 框架实现权限控制。[官方文档传送门](https://sa-token.cc/doc.html#/)
|
||||
|
||||
## 权限校验
|
||||
权限校验指的是校验用户是否拥有访问某个 API 的能力。
|
||||
|
||||
通常情况下,一个 API 对应一个权限码,如果用户具备当前 API 的权限码,即代表有能力访问该 API。
|
||||
|
||||
### 1:权限标识
|
||||
在本系统中,每一个菜单功能都有对应的权限标识,可以在菜单管理中进行设置。
|
||||
|
||||
> 注:
|
||||
> 1. 前后端的权限标识要保持一致。
|
||||
> 2. 权限标识可以使用通配符`*`。
|
||||
|
||||

|
||||
|
||||
|
||||
### 2:校验方法
|
||||
#### 2.1:使用 `@SaCheckPermission` 注解进行校验
|
||||
`@SaCheckPermission` 注解是由 `Sa-Token` 框架提供的角色校验注解,可以标注在方法上或类上。
|
||||
|
||||
- 单个权限校验:
|
||||
|
||||
```Java
|
||||
@SaCheckPermission("system:user:list")
|
||||
```
|
||||
|
||||
- 多个权限校验(或模式,满足任意一个权限即可):
|
||||
|
||||
```Java
|
||||
@SaCheckPermission(
|
||||
value = {
|
||||
"system:user:list",
|
||||
"system:user:query"
|
||||
},
|
||||
mode = SaMode.OR
|
||||
)
|
||||
```
|
||||
|
||||
- 多个权限校验(与模式,必须满足所有权限):
|
||||
|
||||
```Java
|
||||
@SaCheckPermission(
|
||||
value = {
|
||||
"system:user:list",
|
||||
"system:user:query"
|
||||
},
|
||||
mode = SaMode.AND
|
||||
)
|
||||
```
|
||||
|
||||
#### 2.2:使用 `StpUtil` 工具类校验
|
||||
`StpUtil` 工具类是由 `Sa-Token` 框架提供的权限工具类,提供了常用的校验方法。
|
||||
|
||||
- 判断当前用户是否拥有某个权限(返回 `boolean`):
|
||||
|
||||
```Java
|
||||
StpUtil.hasPermission("system:user:list");
|
||||
```
|
||||
|
||||
- 单个权限校验:
|
||||
|
||||
```Java
|
||||
StpUtil.checkPermission("system:user:list");
|
||||
```
|
||||
如果验证未通过,则抛出异常: `NotPermissionException`
|
||||
|
||||
- 多个权限校验(或模式,满足任意一个权限即可):
|
||||
|
||||
```Java
|
||||
StpUtil.checkPermissionOr("system:user:list", "system:user:query");
|
||||
```
|
||||
如果验证未通过,则抛出异常: `NotPermissionException`
|
||||
|
||||
- 多个权限校验(与模式,必须满足所有权限):
|
||||
|
||||
```Java
|
||||
StpUtil.checkPermissionAnd("system:user:list", "system:user:query");
|
||||
```
|
||||
如果验证未通过,则抛出异常: `NotPermissionException`
|
||||
|
||||
## 角色校验
|
||||
角色校验指的是校验用户是否拥有某个指定角色。
|
||||
|
||||
### 1:权限标识
|
||||
在本系统中,每个角色都拥有唯一的权限字符。
|
||||
|
||||
除了超级管理员角色外,其他角色的权限字符可以通过角色管理进行设置。
|
||||
|
||||

|
||||
|
||||
### 2:校验方法
|
||||
#### 2.1:使用 `@SaCheckRole` 注解校验
|
||||
`@SaCheckRole` 注解是由 `Sa-Token` 框架提供的角色校验注解,可以标注在方法上或类上。
|
||||
|
||||
- 单个角色校验
|
||||
|
||||
```Java
|
||||
@SaCheckRole("superadmin")
|
||||
```
|
||||
|
||||
- 多个角色校验(或模式,满足任意一个角色即可):
|
||||
|
||||
```Java
|
||||
@SaCheckRole(
|
||||
value = {
|
||||
"superadmin",
|
||||
"admin"
|
||||
},
|
||||
mode = SaMode.OR
|
||||
)
|
||||
```
|
||||
|
||||
- 多个角色校验(与模式,必须满足所有角色):
|
||||
|
||||
```Java
|
||||
@SaCheckRole(
|
||||
value = {
|
||||
"superadmin",
|
||||
"admin"
|
||||
},
|
||||
mode = SaMode.AND
|
||||
)
|
||||
```
|
||||
|
||||
#### 2.2:使用 `StpUtil` 工具类校验
|
||||
`StpUtil` 工具类是由 `Sa-Token` 框架提供的权限工具类,提供了常用的校验方法。
|
||||
|
||||
- 判断当前用户是否拥有某个角色(返回 `boolean`):
|
||||
|
||||
```Java
|
||||
StpUtil.hasRole("superadmin")
|
||||
```
|
||||
|
||||
- 单个权限校验:
|
||||
|
||||
```Java
|
||||
StpUtil.checkRole("system:user:list");
|
||||
```
|
||||
如果验证未通过,则抛出异常: `NotRoleException`
|
||||
|
||||
- 多个权限校验(或模式,满足任意一个角色即可):
|
||||
|
||||
```Java
|
||||
StpUtil.checkRoleOr("system:user:list", "system:user:query");
|
||||
```
|
||||
如果验证未通过,则抛出异常: `NotRoleException`
|
||||
|
||||
- 多个权限校验(与模式,必须满足所有角色):
|
||||
|
||||
```Java
|
||||
StpUtil.checkRoleAnd("system:user:list", "system:user:query");
|
||||
```
|
||||
如果验证未通过,则抛出异常: `NotRoleException`
|
||||
|
||||
## 角色权限双重 `OR` 校验
|
||||
除了分开校验以外,权限和角色也可以进行组合,表示备选校验。
|
||||
|
||||
简单举个例子:
|
||||
|
||||
假设某个 API 的权限码为 `system:user:list`,角色 `admin` 可以调用,则可以这样写:
|
||||
|
||||
```Java
|
||||
@SaCheckPermission(value = "system:user:list", orRole = "admin")
|
||||
```
|
||||
|
||||
以上权限只需要满足任意一项即可。更多写法可以参考 `Sa-Token` [官方文档](https://sa-token.cc/doc.html#/use/at-check?id=_4%e3%80%81%e8%a7%92%e8%89%b2%e6%9d%83%e9%99%90%e5%8f%8c%e9%87%8d-or%e6%a0%a1%e9%aa%8c)。
|
||||
|
||||
## 当前用户的所有权限
|
||||
本系统中实现了 `StpInterface` 接口,可以对用户的权限以及角色进行管理,并且可以根据不同的用户类型进行设置。
|
||||
|
||||
具体参考类:`org.dromara.common.satoken.core.service.SaPermissionImpl`
|
||||
|
||||
## 忽略权限校验
|
||||
请参考文档:[网关路由与放行](/ruoyi-cloud-plus/framework/basic/router_release?id=网关路由与放行)
|
||||
@@ -0,0 +1,26 @@
|
||||
# 网关路由与放行
|
||||
- - -
|
||||
|
||||
## 新增路由
|
||||
`ruoyi-gateway.yml` 配置文件 增加 `routers` 配置<br>
|
||||
**注意: 路径格式为 `/服务路径/controller路径/接口方法路径` `*代表任意一级 **代表任意所有级`**<br>
|
||||
下图代表 `resource/**` 将所有 `resource开头的路径` 都路由到 `ruoyi-resource` 服务<br>
|
||||
例如: `/resource/sms/code` `resource路由到ruoyi-resource服务` `sms路由到对应的contrller` `code 路由到对应的接口`<br>
|
||||
<br>
|
||||

|
||||
|
||||
## 放行使用方式
|
||||
nacos 中 `ruoyi-gateway.yml` 白名单放行<br>
|
||||
**注意: 放行路径格式为 `/服务路径/controller路径/接口方法路径` `*代表任意一级 **代表任意所有级`**<br>
|
||||
示例: `/resource/sms/code` 代表 `ruoyi-resource服务 sms的controller code接口`<br>
|
||||

|
||||
|
||||
## 注意事项
|
||||
|
||||
接口放行后不需要token即可访问<br>
|
||||
但是没有token也就无法获取用户信息与鉴权
|
||||
|
||||
### 解决方案
|
||||
删除接口上的鉴权注解<br>
|
||||
删除接口内获取用户信息功能<br>
|
||||
删除数据库实体类 自动注入 `createBy` `updateBy` 因为会获取用户数据
|
||||
@@ -0,0 +1,68 @@
|
||||
# 第三方授权功能
|
||||
- - -
|
||||
## 版本 >= 2.X
|
||||
|
||||
## 前置说明
|
||||
1. 该功能基于 `JustAuth` 实现,支持多家平台实现第三方授权登录。
|
||||
2. 以 `Gitee` 授权登录为例进行本功能的使用说明。
|
||||
3. 其他第三方授权配置信息获取方式可参考 `JustAuth` [官方文档](https://www.justauth.cn/guide/)。<br>
|
||||
|
||||

|
||||
|
||||
## 第三方授权配置
|
||||
|
||||
### 申请三方应用(以gitee为例)
|
||||
|
||||

|
||||
|
||||
### 更改后端配置 `application-dev.yml`
|
||||
|
||||

|
||||
|
||||
**注:内网地址无法回调,请使用外网可以访问的地址。**
|
||||
|
||||

|
||||
|
||||
### 更改前端配置 `login.vue`
|
||||
|
||||

|
||||
|
||||
## 授权登录(未绑定第三方平台)
|
||||
|
||||
### 步骤一:个人中心授权第三方应用
|
||||
|
||||

|
||||
|
||||
### 步骤二:同意授权
|
||||
|
||||

|
||||
|
||||
顶部出现授权成功,并跳转到系统首页。<br>
|
||||
|
||||
<br>
|
||||
|
||||

|
||||
|
||||
查看第三方应用可看到授权成功的个人信息。<br>
|
||||
|
||||

|
||||
|
||||
## 授权登录(已绑定第三方平台)
|
||||
|
||||
### 步骤一:点击登录页面图标
|
||||
|
||||

|
||||
|
||||
### 步骤二:同意授权
|
||||
|
||||

|
||||
|
||||
## 解除授权绑定
|
||||
|
||||
### 步骤一:个人中心点击解绑第三方应用
|
||||
|
||||

|
||||
|
||||
### 步骤二:点击确定完成解绑
|
||||
|
||||

|
||||
@@ -0,0 +1,121 @@
|
||||
# 多租户功能
|
||||
- - -
|
||||
## 版本 >= 2.X
|
||||
|
||||
## 前置说明(重要)
|
||||
1. 本框架多租户功能的实现是基于 [MyBatis-Plus 多租户插件](https://baomidou.com/pages/aef2f2/#tenantlineinnerinterceptor) 的,只支持最简单的隔离。
|
||||
2. 本系统默认开启多租户功能。
|
||||
3. 多租户业务表建表需要加上租户id `tenant_id`,可参考其他系统表。
|
||||
4. 非多租户表可在配置文件进行配置排除。
|
||||
5. 只有超级管理员支持切换租户。
|
||||
|
||||
## 多租户使用流程(先说结论再展开!)
|
||||
0. 开启多租户配置(系统默认已经开启)
|
||||
1. 登录界面(可以选择不同租户)
|
||||
> 注:如果为租户设置了绑定域名,则只能选择当前域名相关的租户列表。
|
||||
2. 设置多租户套餐
|
||||
3. 新增/修改租户(需要选择套餐)
|
||||
4. 切换租户(仅超级管理员可操作)
|
||||
|
||||
## 多租户配置
|
||||
`application-common.yml`<br>
|
||||
|
||||
> 开关 `enable` 节点不用废话。 <br>
|
||||
> 如果不需要过滤租户的表可在 `excludes` 节点下添加。
|
||||
|
||||
**注意: 如果已经基于租户模式启动了程序 关闭租户必须删除mysql与redis内的相关数据重新导入sql**
|
||||
|
||||

|
||||
|
||||
## 忽略租户
|
||||
|
||||
1.如果需要指定单独 SQL 不开启过滤,可在对应的 Mapper 接口添加如下忽略注解:
|
||||
```
|
||||
@InterceptorIgnore(tenantLine = "true", dataPermission = "false")
|
||||
```
|
||||
**此处注意事项 使用此注解如果需要开启数据权限 dataPermission = "false" 必须添加 mp的注解默认是忽略数据权限的 会导致数据权限失效**
|
||||
|
||||
2.如果需要在业务层忽略多租户,可调用以下方法(推荐使用):
|
||||
```
|
||||
# 无返回值
|
||||
TenantHelper.ignore(() -> { 业务代码 });
|
||||
# 有返回值
|
||||
Class result = TenantHelper.ignore(() -> { return 业务代码 });
|
||||
```
|
||||
|
||||
## 动态切换租户
|
||||
|
||||
**仅适用于特殊需求业务(例如: 创建租户时, 对该租户操作一些数据, 或者需要去其他租户查一些数据等) 禁止乱用后果自负**
|
||||
|
||||
```
|
||||
# 无返回值
|
||||
TenantHelper.dynamic(租户id, () -> { 业务代码 });
|
||||
# 有返回值
|
||||
Class result = TenantHelper.dynamic(租户id, () -> { return 业务代码 });
|
||||
```
|
||||
|
||||
## 登录界面
|
||||
|
||||

|
||||
|
||||
> 注:如果为租户设置了绑定域名,则只能选择当前域名相关的租户列表。
|
||||
|
||||
## 租户套餐管理
|
||||
### 租户套餐新增
|
||||

|
||||
|
||||

|
||||
|
||||
> 注:
|
||||
> 1、先新增套餐再新增租户,因为租户新增之后无法修改所选套餐。
|
||||
> 2、租户所关联的套餐如果后续有修改可以进行同步。
|
||||
|
||||
|
||||
## 租户管理
|
||||
### 默认租户
|
||||
> 注:默认租户无法修改
|
||||
|
||||

|
||||
|
||||
### 新增租户
|
||||
#### 填写表单
|
||||

|
||||
|
||||
#### 选择新增的租户套餐
|
||||

|
||||
|
||||
#### 新增完成
|
||||

|
||||
|
||||
#### 登录租户
|
||||

|
||||
|
||||

|
||||
|
||||
### 修改租户
|
||||
#### 配置域名
|
||||

|
||||
|
||||

|
||||
|
||||
#### 没有配置域名
|
||||

|
||||
|
||||
#### 强调一下:这不是bug!
|
||||
> 注:域名的配置就是为了绑定特定租户!
|
||||
|
||||
### 同步套餐
|
||||
应用场景:租户套餐进行了修改,配置的菜单需要同步到特定租户。
|
||||
(不是所有租户都有更新套餐的权利, 这是跟钱挂钩的)
|
||||
|
||||
> 点一下按钮的事,图略。
|
||||
|
||||
## 切换租户(仅超级管理员)
|
||||
> 注:管理员切换租户不是切换用户,切换的只是数据,管理员拥有所有权限。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
# 系统用户相关
|
||||
- - -
|
||||
|
||||
> 框架采用sa-token控制权限 并对sa-token的api做了一定的业务封装<br>
|
||||
|
||||
## 用户登录
|
||||
|
||||
> 参考自带多种登录实现 不限制用户数据来源 只需要构建 LoginUser 即可完成登录<br>
|
||||
> 例如: `同表不同类型` `不同表` `同表+扩展表`<br>
|
||||
|
||||

|
||||
|
||||
## 获取用户信息
|
||||
|
||||
> 完成登录后会生成登录token返回给前端 前端需要再请求头携带token 后端方可获取到对应的用户信息
|
||||
|
||||
请求头传递格式: `Authorization: Bearer token`
|
||||
|
||||
后端获取用户信息:
|
||||
```java
|
||||
LoginUser user = LoginHelper.getLoginUser();
|
||||
```
|
||||
|
||||
## 获取用户信息(基于token)
|
||||
```java
|
||||
LoginUser user = LoginHelper.getLoginUser(token);
|
||||
```
|
||||
|
||||
## 获取登录用户id
|
||||
```java
|
||||
Long userId = LoginHelper.getUserId();
|
||||
```
|
||||
|
||||
## 获取登录用户账户名
|
||||
```java
|
||||
String username = LoginHelper.getUsername();
|
||||
```
|
||||
|
||||
## 获取登录用户所属租户id
|
||||
```java
|
||||
String tenantId = LoginHelper.getTenantId();
|
||||
```
|
||||
|
||||
## 获取登录用户所属部门id
|
||||
```java
|
||||
Long deptId = LoginHelper.getDeptId();
|
||||
```
|
||||
|
||||
## 获取登录用户类型
|
||||
```java
|
||||
UserType userType = LoginHelper.getUserType();
|
||||
```
|
||||
|
||||
## 获取登录用户其他扩展属性
|
||||
```java
|
||||
Object obj = LoginHelper.getExtra(key);
|
||||
```
|
||||
|
||||
## 设置登录用户其他扩展属性
|
||||
|
||||
参考登录设置 `clientId` 属性
|
||||
|
||||

|
||||
|
||||
## 判断用户是否为超级管理员
|
||||
|
||||
```java
|
||||
// 判断当前登录用户
|
||||
boolean b = LoginHelper.isSuperAdmin();
|
||||
// 判断用户基于id
|
||||
boolean b = LoginHelper.isSuperAdmin(userId);
|
||||
```
|
||||
|
||||
## 判断用户是否为租户管理员
|
||||
|
||||
```java
|
||||
// 判断当前登录用户
|
||||
boolean b = LoginHelper.isTenantAdmin();
|
||||
// 判断用户基于角色组
|
||||
boolean b = LoginHelper.isSuperAdmin(rolePermission);
|
||||
```
|
||||
|
||||
## 其他更多操作
|
||||
[Sa-Token 官方文档 - 登录认证](https://sa-token.cc/doc.html#/use/login-auth)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# 关于多表查询
|
||||
- - -
|
||||
## 建议单表查询
|
||||
|
||||
文章连接: [大连接查询分解好处](https://java.isture.com/db/mysql/mysql-x-optimize-decompose-connection.html)
|
||||
|
||||

|
||||
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
**(上图出自 <高性能MySql>)**
|
||||
@@ -0,0 +1,19 @@
|
||||
# 主键使用说明
|
||||
- - -
|
||||
## 关于如何使用分布式id或雪花id
|
||||
|
||||
参考 `MybatisPlusConfig` 如需自定义 修改 `Bean` 实现即可
|
||||
|
||||

|
||||
|
||||
框架默认集成 雪花ID 只需全局更改 主键类型即可
|
||||
|
||||

|
||||
|
||||
如单表使用 可单独配置注解
|
||||
|
||||

|
||||
|
||||
### 重点说明
|
||||
* 由于雪花id位数过长 `Long` 类型在前端会失真
|
||||
* 框架已配置序列化方案 超越 `JS` 最大值自动转字符串 参考 `BigNumberSerializer` 类
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user