Pre Merge pull request !445 from 中科嘉迪/dev

pull/445/MERGE
中科嘉迪 2025-12-23 08:44:11 +00:00 committed by Gitee
commit aa326f6326
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
126 changed files with 7212 additions and 3695 deletions

View File

@ -1,11 +1,11 @@
<p align="center"> <p align="center">
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png"> <img alt="logo" src="https://oscimg.oschina.net/oscnet/up-b99b286755aef70355a7084753f89cdb7c9.png">
</p> </p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.7</h1> <h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.6.5.0.9</h1>
<h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4> <h4 align="center">基于 Vue/Element UI 和 Spring Boot/Spring Cloud & Alibaba 前后端分离的分布式微服务架构</h4>
<p align="center"> <p align="center">
<a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud/stargazers"><img src="https://gitee.com/y_project/RuoYi-Cloud/badge/star.svg?theme=dark"></a>
<a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.7-brightgreen.svg"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud"><img src="https://img.shields.io/badge/RuoYi-v3.6.5.0.9-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a> <a href="https://gitee.com/y_project/RuoYi-Cloud/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p> </p>

78
pom.xml
View File

@ -6,14 +6,14 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url> <url>http://www.ruoyi.vip</url>
<description>若依微服务系统</description> <description>若依微服务系统</description>
<properties> <properties>
<ruoyi.version>3.6.7</ruoyi.version> <ruoyi.version>3.6.5.0.9</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
@ -24,20 +24,22 @@
<tobato.version>1.27.2</tobato.version> <tobato.version>1.27.2</tobato.version>
<kaptcha.version>2.3.3</kaptcha.version> <kaptcha.version>2.3.3</kaptcha.version>
<pagehelper.boot.version>2.0.0</pagehelper.boot.version> <pagehelper.boot.version>2.0.0</pagehelper.boot.version>
<druid.version>1.2.27</druid.version> <druid.version>1.2.23</druid.version>
<dynamic-ds.version>4.3.1</dynamic-ds.version> <dynamic-ds.version>4.3.1</dynamic-ds.version>
<commons.io.version>2.21.0</commons.io.version> <commons.io.version>2.19.0</commons.io.version>
<velocity.version>2.3</velocity.version> <velocity.version>2.3</velocity.version>
<fastjson.version>2.0.60</fastjson.version> <fastjson.version>2.0.53</fastjson.version>
<jjwt.version>0.9.1</jjwt.version> <jjwt.version>0.9.1</jjwt.version>
<minio.version>8.2.2</minio.version> <minio.version>8.2.2</minio.version>
<poi.version>4.1.2</poi.version> <poi.version>4.1.2</poi.version>
<springdoc.version>1.6.9</springdoc.version> <springdoc.version>1.6.9</springdoc.version>
<transmittable-thread-local.version>2.14.4</transmittable-thread-local.version> <transmittable-thread-local.version>2.14.4</transmittable-thread-local.version>
<!-- override dependency version --> <!-- override dependency version -->
<tomcat.version>9.0.112</tomcat.version> <tomcat.version>9.0.105</tomcat.version>
<logback.version>1.2.13</logback.version> <logback.version>1.2.13</logback.version>
<spring-framework.version>5.3.39</spring-framework.version> <spring-framework.version>5.3.39</spring-framework.version>
<kotlin.version>2.0.0</kotlin.version>
<spring-boot-admin>2.7.9</spring-boot-admin>
</properties> </properties>
<!-- 依赖声明 --> <!-- 依赖声明 -->
@ -251,7 +253,11 @@
<artifactId>ruoyi-api-system</artifactId> <artifactId>ruoyi-api-system</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
@ -271,10 +277,47 @@
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId> <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<!-- 指定多个源代码目录、多个资源文件目录 -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/java</source>
<source>src/main/kotlin</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
@ -284,6 +327,27 @@
<encoding>${project.build.sourceEncoding}</encoding> <encoding>${project.build.sourceEncoding}</encoding>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins> </plugins>
<pluginManagement> <pluginManagement>
<plugins> <plugins>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api</artifactId> <artifactId>ruoyi-api</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -22,7 +22,41 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-core</artifactId> <artifactId>ruoyi-common-core</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.zkjiadi</groupId>
<artifactId>zkjiadi-mall-api</artifactId>
<version>1.0.7</version>
<exclusions>
<exclusion>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project> </project>

View File

@ -1,5 +1,6 @@
package com.ruoyi.system.api; package com.ruoyi.system.api;
import com.ruoyi.system.api.inner.InnerRemoteUserService;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@ -20,7 +21,7 @@ import com.ruoyi.system.api.model.LoginUser;
* @author ruoyi * @author ruoyi
*/ */
@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class) @FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteUserService public interface RemoteUserService extends InnerRemoteUserService
{ {
/** /**
* *
@ -51,4 +52,10 @@ public interface RemoteUserService
*/ */
@PutMapping("/user/recordlogin") @PutMapping("/user/recordlogin")
public R<Boolean> recordUserLogin(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); public R<Boolean> recordUserLogin(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* go
*/
@PostMapping("/user/syncGO")
public R<Boolean> syncGO(@RequestBody SysUser sysUser);
} }

View File

@ -81,6 +81,12 @@ public class SysUser extends BaseEntity
}) })
private SysDept dept; private SysDept dept;
/** 部门对象 */
@Excels({
@Excel(name = "微信UnionId", targetAttr = "wxUnionId", type = Type.EXPORT)
})
private KSysUserAccount sysUserAccount;
/** 角色对象 */ /** 角色对象 */
private List<SysRole> roles; private List<SysRole> roles;
@ -271,6 +277,14 @@ public class SysUser extends BaseEntity
this.dept = dept; this.dept = dept;
} }
public KSysUserAccount getSysUserAccount() {
return sysUserAccount;
}
public void setSysUserAccount(KSysUserAccount sysUserAccount) {
this.sysUserAccount = sysUserAccount;
}
public List<SysRole> getRoles() public List<SysRole> getRoles()
{ {
return roles; return roles;
@ -334,6 +348,7 @@ public class SysUser extends BaseEntity
.append("updateTime", getUpdateTime()) .append("updateTime", getUpdateTime())
.append("remark", getRemark()) .append("remark", getRemark())
.append("dept", getDept()) .append("dept", getDept())
.append("userAccount", getSysUserAccount())
.toString(); .toString();
} }
} }

View File

@ -1,5 +1,8 @@
package com.ruoyi.system.api.factory; package com.ruoyi.system.api.factory;
import com.github.pagehelper.Page;
import com.ruoyi.system.api.domain.KSysUserAccount;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory; import org.springframework.cloud.openfeign.FallbackFactory;
@ -25,12 +28,34 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
log.error("用户服务调用失败:{}", throwable.getMessage()); log.error("用户服务调用失败:{}", throwable.getMessage());
return new RemoteUserService() return new RemoteUserService()
{ {
@NotNull
@Override
public R<LoginUser> getById_Inner(Long userId, @NotNull String source) {
return R.fail("获取用户失败:" + throwable.getMessage());
}
@Override
public R<LoginUser> getByWxUnionId_Inner(String unionid, String source) {
return R.fail("获取用户失败:" + throwable.getMessage());
}
@Override @Override
public R<LoginUser> getUserInfo(String username, String source) public R<LoginUser> getUserInfo(String username, String source)
{ {
return R.fail("获取用户失败:" + throwable.getMessage()); return R.fail("获取用户失败:" + throwable.getMessage());
} }
@NotNull
@Override
public R<LoginUser> getByPhoneNumber_Inner(@NotNull String phoneNumber, @NotNull String source) {
return R.fail("获取用户失败:" + throwable.getMessage());
}
@Override
public R<Page<SysUser>> findByPhoneNumberStartingWith_Inner(String phoneNumber, String source) {
return R.fail("获取用户失败:" + throwable.getMessage());
}
@Override @Override
public R<Boolean> registerUserInfo(SysUser sysUser, String source) public R<Boolean> registerUserInfo(SysUser sysUser, String source)
{ {
@ -42,6 +67,27 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
{ {
return R.fail("记录用户登录信息失败:" + throwable.getMessage()); return R.fail("记录用户登录信息失败:" + throwable.getMessage());
} }
@Override
public R<Boolean> syncGO(SysUser sysUser) {
return R.fail("同步用户信息至GO失败:" + throwable.getMessage());
}
@NotNull
@Override
public R<LoginUser> edit_Inner(@NotNull LoginUser user, @NotNull String source) {
return R.fail("修改用户信息失败:" + throwable.getMessage());
}
@Override
public R<Boolean> registerUserBySysUserAccount_Inner(KSysUserAccount sysUserAccount, Long deptId, String source) {
return R.fail("注册用户失败:" + throwable.getMessage());
}
@Override
public R<Boolean> unbindWeixin_Inner(Long userId, String source) {
return R.fail("解绑微信失败:" + throwable.getMessage());
}
}; };
} }
} }

View File

@ -0,0 +1,77 @@
package com.ruoyi.system.api.inner;
import com.github.pagehelper.Page;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.domain.KSysUserAccount;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
public interface InnerRemoteUserService {
/**
* ID
*
* @param userId ID
* @param source
* @return
*/
@GetMapping("/inner/user/detail/{userId}")
R<LoginUser> getById_Inner(@PathVariable("userId") Long userId, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* ID
*
* @param unionid unionid
* @param source
* @return
*/
@GetMapping("/inner/user/detail/wx/unionid/{unionid}")
R<LoginUser> getByWxUnionId_Inner(@PathVariable("unionid") String unionid, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
*
*
* @param phoneNumber
* @param source
* @return
*/
@GetMapping("/inner/user/info/phoneNumber/{phoneNumber:\\d+}")
R<LoginUser> getByPhoneNumber_Inner(@PathVariable("phoneNumber") String phoneNumber, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
*
*
* @param phoneNumber
* @param source
* @return
*/
@GetMapping("/inner/user/list/phoneNumber/{phoneNumber:\\d+}")
R<Page<SysUser>> findByPhoneNumberStartingWith_Inner(@PathVariable("phoneNumber") String phoneNumber, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
@PutMapping("/inner/user")
R<LoginUser> edit_Inner(@RequestBody LoginUser user, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
*
*
* @param sysUserAccount unionId
* @param deptId ID
* @param source
* @return
*/
@PostMapping("/inner/user/register/dept/{deptId}/wx/unionid")
R<Boolean> registerUserBySysUserAccount_Inner(@RequestBody KSysUserAccount sysUserAccount, @PathVariable("deptId") Long deptId, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
*
*
* @param userId ID
* @param source
* @return
*/
@PutMapping("/inner/user/{userId}/unbind/weixin")
R<Boolean> unbindWeixin_Inner(@PathVariable("userId") Long userId, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}

View File

@ -0,0 +1,19 @@
package com.ruoyi.system.api
import com.ruoyi.common.core.constant.ServiceNameConstants
import com.ruoyi.system.api.factory.RemoteUserFallbackFactory
import com.ruoyi.system.api.inner.InnerRemoteSysNoticeService
import org.springframework.cloud.openfeign.FeignClient
/**
* 公告服务
* @author 栾成伟
*/
@FeignClient(
contextId = "remoteSysNoticeService",
value = ServiceNameConstants.SYSTEM_SERVICE,
fallbackFactory = RemoteUserFallbackFactory::class
)
interface RemoteSysNoticeService : InnerRemoteSysNoticeService {
}

View File

@ -0,0 +1,21 @@
package com.ruoyi.system.api.domain
import com.cyl.manager.ums.domain.entity.MemberWechat
open class KSysUserAccount : MemberWechat() {
/** 用户ID */
open var userId: Long? = null
set(value) {
memberId = value
field = value
}
get() = memberId
/** 微信UnionId */
open var wxUnionId: String? = null
set(value) {
unionid = value
field = value
}
get() = unionid
}

View File

@ -0,0 +1,24 @@
package com.ruoyi.system.api.factory
import com.ruoyi.common.core.domain.R
import com.ruoyi.system.api.RemoteSysNoticeService
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.cloud.openfeign.FallbackFactory
import org.springframework.stereotype.Component
@Component
open class RemoteSysNoticeFallbackFactory : FallbackFactory<RemoteSysNoticeService> {
companion object {
var log: Logger = LoggerFactory.getLogger(RemoteSysNoticeFallbackFactory::class.java)
}
override fun create(throwable: Throwable): RemoteSysNoticeService {
log.error("公告服务调用失败:{}", throwable.message)
return object : RemoteSysNoticeService {
override fun getById_Inner(noticeId: Long, source: String): R<Any> {
return R.fail("获取公告失败")
}
}
}
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.system.api.inner
import com.ruoyi.common.core.constant.SecurityConstants
import com.ruoyi.common.core.domain.R
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RequestParam
interface InnerRemoteSysNoticeService {
/**
* 根据公告ID查询公告信息
* @param noticeId 公告ID
* @return 公告信息
*/
@GetMapping("/inner/notice/detail")
fun getById_Inner(
@RequestParam("noticeId") noticeId: Long,
@RequestHeader(SecurityConstants.FROM_SOURCE) source: String
): R<Any>
}

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -51,7 +51,10 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-security</artifactId> <artifactId>ruoyi-common-security</artifactId>
</dependency> </dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -1,11 +1,11 @@
package com.ruoyi.auth.controller; package com.ruoyi.auth.controller;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.auth.form.LoginBody; import com.ruoyi.auth.form.LoginBody;
import com.ruoyi.auth.form.RegisterBody; import com.ruoyi.auth.form.RegisterBody;
import com.ruoyi.auth.service.SysLoginService; import com.ruoyi.auth.service.SysLoginService;
@ -46,11 +46,16 @@ public class TokenController
String token = SecurityUtils.getToken(request); String token = SecurityUtils.getToken(request);
if (StringUtils.isNotEmpty(token)) if (StringUtils.isNotEmpty(token))
{ {
try{
String username = JwtUtils.getUserName(token); String username = JwtUtils.getUserName(token);
// 删除用户缓存记录 // 删除用户缓存记录
AuthUtil.logoutByToken(token); AuthUtil.logoutByToken(token);
// 记录用户退出日志 // 记录用户退出日志
sysLoginService.logout(username); sysLoginService.logout(username);
}catch (Exception e){
System.out.println(e.getMessage());
return R.ok();
}
} }
return R.ok(); return R.ok();
} }
@ -75,4 +80,18 @@ public class TokenController
sysLoginService.register(registerBody.getUsername(), registerBody.getPassword()); sysLoginService.register(registerBody.getUsername(), registerBody.getPassword());
return R.ok(); return R.ok();
} }
/**
*
*
*
* @return ResponseEntity:
*/
@RequestMapping("verify")
public ResponseEntity<?> verifyToken(HttpServletResponse response) {
response.setHeader("X-User-ID", String.valueOf(SecurityUtils.getUserId()));
// 返回一个HTTP 200 OK响应表示令牌有效
return ResponseEntity.ok().build();
}
} }

View File

@ -0,0 +1,140 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.autoconfigure.endpoint.web;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* Configuration properties for web management endpoints.
*
* @author Madhura Bhave
* @author Phillip Webb
* @since 2.0.0
*/
@ConfigurationProperties(prefix = "management.endpoints.web")
public class WebEndpointProperties {
private final Exposure exposure = new Exposure();
/**
* Base path for Web endpoints. Relative to the servlet context path
* (server.servlet.context-path) or WebFlux base path (spring.webflux.base-path) when
* the management server is sharing the main server port. Relative to the management
* server base path (management.server.base-path) when a separate management server
* port (management.server.port) is configured.
*/
private String basePath = "/actuator";
private String baseUrl = null;
/**
* Mapping between endpoint IDs and the path that should expose them.
*/
private final Map<String, String> pathMapping = new LinkedHashMap<>();
private final Discovery discovery = new Discovery();
public Exposure getExposure() {
return this.exposure;
}
public String getBasePath() {
return this.basePath;
}
public void setBasePath(String basePath) {
Assert.isTrue(basePath.isEmpty() || basePath.startsWith("/"), "Base path must start with '/' or be empty");
this.basePath = cleanBasePath(basePath);
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
private String cleanBasePath(String basePath) {
if (StringUtils.hasText(basePath) && basePath.endsWith("/")) {
return basePath.substring(0, basePath.length() - 1);
}
return basePath;
}
public Map<String, String> getPathMapping() {
return this.pathMapping;
}
public Discovery getDiscovery() {
return this.discovery;
}
public static class Exposure {
/**
* Endpoint IDs that should be included or '*' for all.
*/
private Set<String> include = new LinkedHashSet<>();
/**
* Endpoint IDs that should be excluded or '*' for all.
*/
private Set<String> exclude = new LinkedHashSet<>();
public Set<String> getInclude() {
return this.include;
}
public void setInclude(Set<String> include) {
this.include = include;
}
public Set<String> getExclude() {
return this.exclude;
}
public void setExclude(Set<String> exclude) {
this.exclude = exclude;
}
}
public static class Discovery {
/**
* Whether the discovery page is enabled.
*/
private boolean enabled = true;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
}

View File

@ -0,0 +1,113 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.endpoint.web.servlet;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.util.pattern.PathPatternParser;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
/**
* A custom {@link HandlerMapping} that makes web endpoints available over HTTP using
* Spring MVC.
*
* @author Andy Wilkinson
* @author Phillip Webb
* @since 2.0.0
*/
public class WebMvcEndpointHandlerMapping extends AbstractWebMvcEndpointHandlerMapping {
private final EndpointLinksResolver linksResolver;
@Lazy
@Resource
private WebEndpointProperties webEndpointProperties;
/**
* Creates a new {@code WebMvcEndpointHandlerMapping} instance that provides mappings
* for the given endpoints.
* @param endpointMapping the base mapping for all endpoints
* @param endpoints the web endpoints
* @param endpointMediaTypes media types consumed and produced by the endpoints
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
* @param linksResolver resolver for determining links to available endpoints
* @param shouldRegisterLinksMapping whether the links endpoint should be registered
*/
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
EndpointLinksResolver linksResolver, boolean shouldRegisterLinksMapping) {
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, shouldRegisterLinksMapping);
this.linksResolver = linksResolver;
setOrder(-100);
}
/**
* Creates a new {@code WebMvcEndpointHandlerMapping} instance that provides mappings
* for the given endpoints.
* @param endpointMapping the base mapping for all endpoints
* @param endpoints the web endpoints
* @param endpointMediaTypes media types consumed and produced by the endpoints
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
* @param linksResolver resolver for determining links to available endpoints
* @param shouldRegisterLinksMapping whether the links endpoint should be registered
* @param pathPatternParser the path pattern parser
*/
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
EndpointLinksResolver linksResolver, boolean shouldRegisterLinksMapping,
PathPatternParser pathPatternParser) {
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, shouldRegisterLinksMapping,
pathPatternParser);
this.linksResolver = linksResolver;
setOrder(-100);
}
@Override
protected LinksHandler getLinksHandler() {
return new WebMvcLinksHandler();
}
/**
* Handler for root endpoint providing links.
*/
class WebMvcLinksHandler implements LinksHandler {
@Override
@ResponseBody
public Map<String, Map<String, Link>> links(HttpServletRequest request, HttpServletResponse response) {
return Collections.singletonMap("_links",
WebMvcEndpointHandlerMapping.this.linksResolver.resolveLinks(ObjectUtils.isEmpty(webEndpointProperties.getBaseUrl())?request.getRequestURL().toString():(webEndpointProperties.getBaseUrl()+webEndpointProperties.getBasePath())));
}
@Override
public String toString() {
return "Actuator root web endpoint";
}
}
}

View File

@ -0,0 +1,33 @@
# Tomcat
server:
port: 9200
#测试环境
spring:
application:
# 应用名称
name: ruoyi-auth
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
logging:
file:
name: prod-ruoyi-auth.log
pattern:
file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"

View File

@ -0,0 +1,33 @@
# Tomcat
server:
port: 9200
# Spring
spring:
application:
# 应用名称
name: ruoyi-auth
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
logging:
file:
name: dev-ruoyi-auth.log
pattern:
file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"

View File

@ -0,0 +1,34 @@
# Tomcat
server:
port: 9200
#测试环境
spring:
application:
# 应用名称
name: ruoyi-auth
cloud:
nacos:
discovery:
ip: 8.155.60.167
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: e2708b29-ca15-4f63-a919-d33932ebdfda
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: e2708b29-ca15-4f63-a919-d33932ebdfda
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
logging:
file:
name: prod-ruoyi-auth.log
pattern:
file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"

View File

@ -0,0 +1,33 @@
# Tomcat
server:
port: 9200
#测试环境
spring:
application:
# 应用名称
name: ruoyi-auth
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 45c724b0-9b42-4ff2-bff2-9220a1788392
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 45c724b0-9b42-4ff2-bff2-9220a1788392
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
logging:
file:
name: test-ruoyi-auth.log
pattern:
file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"

View File

@ -1,25 +1,4 @@
# Tomcat # Spring默认环境配置
server:
port: 9200
# Spring
spring: spring:
application:
# 应用名称
name: ruoyi-auth
profiles: profiles:
# 环境配置
active: dev active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -12,6 +12,20 @@ public class SecurityConstants
*/ */
public static final String DETAILS_USER_ID = "user_id"; public static final String DETAILS_USER_ID = "user_id";
/**
* ID
*/
public static final String DETAILS_SUB = "sub";
/**
* ID
*/
public static final String DETAILS_IAT= "iat";
/**
* ID
*/
public static final String DETAILS_EXP= "exp";
/** /**
* *
*/ */
@ -22,6 +36,11 @@ public class SecurityConstants
*/ */
public static final String AUTHORIZATION_HEADER = "Authorization"; public static final String AUTHORIZATION_HEADER = "Authorization";
/**
* WEBSOCKET
*/
public final static String WEBSOCKET_HEADER = "Sec-WebSocket-Key";
/** /**
* *
*/ */

View File

@ -16,5 +16,4 @@ public class TokenConstants
* *
*/ */
public final static String SECRET = "abcdefghijklmnopqrstuvwxyz"; public final static String SECRET = "abcdefghijklmnopqrstuvwxyz";
} }

View File

@ -1,13 +1,18 @@
package com.ruoyi.common.core.utils; package com.ruoyi.common.core.utils;
import java.util.Base64;
import java.util.Map; import java.util.Map;
import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.TokenConstants; import com.ruoyi.common.core.constant.TokenConstants;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.core.text.Convert;
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts; import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.SignatureAlgorithm;
import javax.naming.AuthenticationException;
import javax.servlet.http.HttpServletResponse;
/** /**
* Jwt * Jwt
* *
@ -15,7 +20,7 @@ import io.jsonwebtoken.SignatureAlgorithm;
*/ */
public class JwtUtils public class JwtUtils
{ {
public static String secret = TokenConstants.SECRET; public static String secret = Base64.getEncoder().encodeToString(TokenConstants.SECRET.getBytes()) ;
/** /**
* *

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -1,9 +1,15 @@
package com.ruoyi.common.security.service; package com.ruoyi.common.security.service;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.impl.DefaultClaims;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -61,7 +67,10 @@ public class TokenService
claimsMap.put(SecurityConstants.USER_KEY, token); claimsMap.put(SecurityConstants.USER_KEY, token);
claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId); claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId);
claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName); claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName);
claimsMap.put(SecurityConstants.DETAILS_SUB,userId);
int now = Math.toIntExact(System.currentTimeMillis() / 1000);
claimsMap.put(SecurityConstants.DETAILS_IAT,now);
claimsMap.put(SecurityConstants.DETAILS_EXP,now+TOKEN_EXPIRE_TIME*60);
// 接口返回信息 // 接口返回信息
Map<String, Object> rspMap = new HashMap<String, Object>(); Map<String, Object> rspMap = new HashMap<String, Object>();
rspMap.put("access_token", JwtUtils.createToken(claimsMap)); rspMap.put("access_token", JwtUtils.createToken(claimsMap));

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -76,6 +76,27 @@
<artifactId>ruoyi-common-redis</artifactId> <artifactId>ruoyi-common-redis</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.12.13</version>
</dependency>
<dependency>
<groupId>com.ujcms</groupId>
<artifactId>ujcms-commons</artifactId>
<version>9.6.0.0.1</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Springdoc --> <!-- Springdoc -->
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>org.springdoc</groupId>
@ -83,6 +104,14 @@
<version>${springdoc.version}</version> <version>${springdoc.version}</version>
</dependency> </dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework</groupId>-->
<!-- <artifactId>spring-webmvc</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -99,6 +128,38 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>

View File

@ -1,10 +1,13 @@
package com.ruoyi.gateway.config; package com.ruoyi.gateway.config;
import java.util.Properties; import java.util.Properties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config; import com.google.code.kaptcha.util.Config;
import static com.google.code.kaptcha.Constants.*; import static com.google.code.kaptcha.Constants.*;
/** /**
@ -13,11 +16,12 @@ import static com.google.code.kaptcha.Constants.*;
* @author ruoyi * @author ruoyi
*/ */
@Configuration @Configuration
public class CaptchaConfig public class CaptchaConfig {
{ @Value("${" + KAPTCHA_TEXTPRODUCER_CHAR_LENGTH + "}")
private String textProducerCharLength;
@Bean(name = "captchaProducer") @Bean(name = "captchaProducer")
public DefaultKaptcha getKaptchaBean() public DefaultKaptcha getKaptchaBean() {
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties(); Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yesno // 是否有边框 默认为true 我们可以自己设置yesno
@ -33,19 +37,18 @@ public class CaptchaConfig
// KAPTCHA_SESSION_KEY // KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
// 验证码文本字符长度 默认为5 // 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, textProducerCharLength);
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, com.google.code.kaptcha.impl.ShadowGimpy.class.getName());
Config config = new Config(properties); Config config = new Config(properties);
defaultKaptcha.setConfig(config); defaultKaptcha.setConfig(config);
return defaultKaptcha; return defaultKaptcha;
} }
@Bean(name = "captchaProducerMath") @Bean(name = "captchaProducerMath")
public DefaultKaptcha getKaptchaBeanMath() public DefaultKaptcha getKaptchaBeanMath() {
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties(); Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yesno // 是否有边框 默认为true 我们可以自己设置yesno
@ -63,7 +66,7 @@ public class CaptchaConfig
// KAPTCHA_SESSION_KEY // KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath"); properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
// 验证码文本生成器 // 验证码文本生成器
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.gateway.config.KaptchaTextCreator"); properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, com.ruoyi.gateway.config.KaptchaTextCreator.class.getName());
// 验证码文本字符间距 默认为2 // 验证码文本字符间距 默认为2
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3"); properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
// 验证码文本字符长度 默认为5 // 验证码文本字符长度 默认为5
@ -73,9 +76,38 @@ public class CaptchaConfig
// 验证码噪点颜色 默认为Color.BLACK // 验证码噪点颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_NOISE_COLOR, "white"); properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
// 干扰实现类 // 干扰实现类
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); properties.setProperty(KAPTCHA_NOISE_IMPL, com.google.code.kaptcha.impl.NoNoise.class.getName());
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, com.google.code.kaptcha.impl.ShadowGimpy.class.getName());
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
@Bean(name = "captchaProducerNumber")
public DefaultKaptcha getKaptchaBeanNumber() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yesno
properties.setProperty(KAPTCHA_BORDER, "yes");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
// 验证码文本生成器
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, com.ruoyi.gateway.config.KaptchaNumberCreator.class.getName());
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, textProducerCharLength);
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, com.google.code.kaptcha.impl.ShadowGimpy.class.getName());
Config config = new Config(properties); Config config = new Config(properties);
defaultKaptcha.setConfig(config); defaultKaptcha.setConfig(config);
return defaultKaptcha; return defaultKaptcha;

View File

@ -0,0 +1,17 @@
package com.ruoyi.gateway.config;
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
import com.ujcms.commons.security.Secures;
/**
*
*
* @author hsdllcw
*/
public class KaptchaNumberCreator extends DefaultTextCreator {
@Override
public String getText() {
return Secures.randomNumeric(getConfig().getTextProducerCharLength());
}
}

View File

@ -43,4 +43,42 @@ public class CaptchaProperties
{ {
this.type = type; this.type = type;
} }
public static class SMS {
@RefreshScope
@Configuration
@ConfigurationProperties(prefix = "security.captcha.sms.aliyuncs")
public static class Aliyuncs {
private String accessKeyId;
private String accessKeySecret;
private String signName;
private String templateCode;
public String getAccessKeyId() {
return accessKeyId;
}
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public String getAccessKeySecret() {
return accessKeySecret;
}
public void setAccessKeySecret(String accessKeySecret) {
this.accessKeySecret = accessKeySecret;
}
public String getSignName() {
return signName;
}
public void setSignName(String signName) {
this.signName = signName;
}
public String getTemplateCode() {
return templateCode;
}
public void setTemplateCode(String templateCode) {
this.templateCode = templateCode;
}
}
}
} }

View File

@ -44,7 +44,6 @@ public class AuthFilter implements GlobalFilter, Ordered
{ {
ServerHttpRequest request = exchange.getRequest(); ServerHttpRequest request = exchange.getRequest();
ServerHttpRequest.Builder mutate = request.mutate(); ServerHttpRequest.Builder mutate = request.mutate();
String url = request.getURI().getPath(); String url = request.getURI().getPath();
// 跳过不需要验证的路径 // 跳过不需要验证的路径
if (StringUtils.matches(url, ignoreWhite.getWhites())) if (StringUtils.matches(url, ignoreWhite.getWhites()))
@ -56,10 +55,18 @@ public class AuthFilter implements GlobalFilter, Ordered
{ {
return unauthorizedResponse(exchange, "令牌不能为空"); return unauthorizedResponse(exchange, "令牌不能为空");
} }
Claims claims = JwtUtils.parseToken(token); /*Claims claims = JwtUtils.parseToken(token);
if (claims == null) if (claims == null)
{ {
return unauthorizedResponse(exchange, "令牌已过期或验证不正确!"); return unauthorizedResponse(exchange, "令牌已过期或验证不正确!");
}*/
Claims claims;
try{
claims = JwtUtils.parseToken(token);
if (claims == null)
return unauthorizedResponse(exchange, "令牌已过期或验证不正确!");
}catch (Exception e){
return unauthorizedResponse(exchange, "令牌已过期或验证不正确!");
} }
String userkey = JwtUtils.getUserKey(claims); String userkey = JwtUtils.getUserKey(claims);
boolean islogin = redisService.hasKey(getTokenKey(userkey)); boolean islogin = redisService.hasKey(getTokenKey(userkey));

View File

@ -34,7 +34,6 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler
} }
String msg; String msg;
if (ex instanceof NotFoundException) if (ex instanceof NotFoundException)
{ {
msg = "服务未找到"; msg = "服务未找到";

View File

@ -1,6 +1,9 @@
package com.ruoyi.gateway.handler; package com.ruoyi.gateway.handler;
import java.io.IOException; import java.io.IOException;
import java.util.Objects;
import com.ruoyi.common.core.utils.uuid.IdUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -30,8 +33,19 @@ public class ValidateCodeHandler implements HandlerFunction<ServerResponse>
AjaxResult ajax; AjaxResult ajax;
try try
{ {
switch (serverRequest.queryParam("type").orElse("image")) {
case "sms":
if (Objects.nonNull(serverRequest.queryParam("receiver").orElse(null))) {
ajax = validateCodeService.createSMSCaptcha(
serverRequest.queryParam("receiver").orElse(null),
serverRequest.queryParam("uuid").orElse(IdUtils.simpleUUID())
);
break;
}
default:
ajax = validateCodeService.createCaptcha(); ajax = validateCodeService.createCaptcha();
} }
}
catch (CaptchaException | IOException e) catch (CaptchaException | IOException e)
{ {
return Mono.error(e); return Mono.error(e);

View File

@ -12,10 +12,15 @@ import com.ruoyi.common.core.web.domain.AjaxResult;
public interface ValidateCodeService public interface ValidateCodeService
{ {
/** /**
* *
*/ */
public AjaxResult createCaptcha() throws IOException, CaptchaException; public AjaxResult createCaptcha() throws IOException, CaptchaException;
/**
*
*/
public AjaxResult createSMSCaptcha(String receiver,String uuid) throws IOException, CaptchaException;
/** /**
* *
*/ */

View File

@ -2,10 +2,15 @@ package com.ruoyi.gateway.service.impl;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import com.alibaba.fastjson2.JSONObject;
import com.ujcms.commons.sms.AliyunUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.FastByteArrayOutputStream; import org.springframework.util.FastByteArrayOutputStream;
import com.google.code.kaptcha.Producer; import com.google.code.kaptcha.Producer;
@ -34,12 +39,21 @@ public class ValidateCodeServiceImpl implements ValidateCodeService
@Resource(name = "captchaProducerMath") @Resource(name = "captchaProducerMath")
private Producer captchaProducerMath; private Producer captchaProducerMath;
@Resource(name = "captchaProducerNumber")
private Producer captchaProducerNumber;
@Autowired @Autowired
private RedisService redisService; private RedisService redisService;
@Autowired @Autowired
private CaptchaProperties captchaProperties; private CaptchaProperties captchaProperties;
@Autowired
private CaptchaProperties.SMS.Aliyuncs smsAliyuncs;
@Autowired
private Environment environment;
/** /**
* *
*/ */
@ -63,18 +77,25 @@ public class ValidateCodeServiceImpl implements ValidateCodeService
String captchaType = captchaProperties.getType(); String captchaType = captchaProperties.getType();
// 生成验证码 // 生成验证码
if ("math".equals(captchaType)) switch (captchaType) {
{ case "number": {
capStr = code = captchaProducerNumber.createText();
image = captchaProducerNumber.createImage(capStr);
}
break;
case "math": {
String capText = captchaProducerMath.createText(); String capText = captchaProducerMath.createText();
capStr = capText.substring(0, capText.lastIndexOf("@")); capStr = capText.substring(0, capText.lastIndexOf("@"));
code = capText.substring(capText.lastIndexOf("@") + 1); code = capText.substring(capText.lastIndexOf("@") + 1);
image = captchaProducerMath.createImage(capStr); image = captchaProducerMath.createImage(capStr);
} }
else if ("char".equals(captchaType)) break;
{ default: {
capStr = code = captchaProducer.createText(); capStr = code = captchaProducer.createText();
image = captchaProducer.createImage(capStr); image = captchaProducer.createImage(capStr);
} }
break;
}
redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
// 转换流信息写出 // 转换流信息写出
@ -93,6 +114,40 @@ public class ValidateCodeServiceImpl implements ValidateCodeService
return ajax; return ajax;
} }
@Override
public AjaxResult createSMSCaptcha(String receiver, String uuid) throws IOException, CaptchaException {
AjaxResult ajax = AjaxResult.success();
boolean captchaEnabled = captchaProperties.getEnabled();
ajax.put("captchaEnabled", captchaEnabled);
if (!captchaEnabled) {
return ajax;
}
// 保存验证码信息
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + receiver + ":" + uuid;
long expire = redisService.getExpire(verifyKey);
if (expire <= 0) {
String code = captchaProducerNumber.createText();
redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
expire = redisService.getExpire(verifyKey);
if (Arrays.stream(environment.getActiveProfiles()).toList().contains("prod")) {
AliyunUtils.sendSms(
smsAliyuncs.getAccessKeyId(),
smsAliyuncs.getAccessKeySecret(),
smsAliyuncs.getSignName(),
smsAliyuncs.getTemplateCode(),
JSONObject.of("code", code),
receiver
);
} else {
ajax.put("captchaCode",code);
}
ajax.put("codeLength", code.length());
}
ajax.put("expire", expire);
ajax.put("uuid", uuid);
return ajax;
}
/** /**
* *
*/ */

View File

@ -0,0 +1,39 @@
package com.ruoyi.gateway.config
import org.apache.commons.lang3.ObjectUtils
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.HttpMethod
import org.springframework.http.HttpStatus
import org.springframework.web.server.WebFilter
@Configuration
open class CorsConfig {
@Value("\${cors.orgins}")
private val corsOrgins: String? = null
@Bean
open fun corsFilter(): WebFilter {
return WebFilter { exchange, chain ->
val response = exchange.response
val request = exchange.request
if (!ObjectUtils.isEmpty(corsOrgins)) {
response.headers["Access-Control-Allow-Origin"] = corsOrgins
} else {
response.headers["Access-Control-Allow-Origin"] = "*"
}
response.headers["Access-Control-Expose-Headers"] = "*"
response.headers["Access-Control-Allow-Credentials"] = "true"
response.headers["Access-Control-Max-Age"] = "3600"
response.headers["Access-Control-Allow-Methods"] = "GET,POST,PUT,DELETE,OPTIONS,HEAD"
response.headers["Access-Control-Allow-Headers"] = "*"
if (HttpMethod.OPTIONS.equals(request.method)) {
response.statusCode = HttpStatus.OK
chain.filter(exchange)
}
chain.filter(exchange.mutate().request(request.mutate().build()).build())
}
}
}

View File

@ -0,0 +1,48 @@
# Tomcat
server:
port: 8080
# Spring
spring:
application:
# 应用名称
name: ruoyi-gateway
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
sentinel:
# 取消控制台懒加载
eager: true
transport:
# 控制台地址
dashboard: nacos.zkjiadi.cc:8718
# nacos配置持久化
datasource:
ds1:
nacos:
server-addr: nacos.zkjiadi.cc
dataId: sentinel-ruoyi-gateway
groupId: DEFAULT_GROUP
data-type: json
rule-type: gw-flow
logging:
file:
name: dev-ruoyi-gateway.log
pattern:
file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"

View File

@ -0,0 +1,49 @@
# Tomcat
server:
port: 8080
# Spring
spring:
application:
# 应用名称
name: ruoyi-gateway
cloud:
nacos:
discovery:
ip: 8.155.60.167
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: e2708b29-ca15-4f63-a919-d33932ebdfda
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: e2708b29-ca15-4f63-a919-d33932ebdfda
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
sentinel:
# 取消控制台懒加载
eager: true
transport:
# 控制台地址
dashboard: nacos.zkjiadi.cc:8718
# nacos配置持久化
datasource:
ds1:
nacos:
server-addr: nacos.zkjiadi.cc
dataId: sentinel-ruoyi-gateway
groupId: DEFAULT_GROUP
data-type: json
rule-type: gw-flow
logging:
file:
name: prod-ruoyi-gateway.log
pattern:
file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"

View File

@ -0,0 +1,48 @@
# Tomcat
server:
port: 8080
# Spring
spring:
application:
# 应用名称
name: ruoyi-gateway
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 45c724b0-9b42-4ff2-bff2-9220a1788392
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 45c724b0-9b42-4ff2-bff2-9220a1788392
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
sentinel:
# 取消控制台懒加载
eager: true
transport:
# 控制台地址
dashboard: nacos.zkjiadi.cc:8718
# nacos配置持久化
datasource:
ds1:
nacos:
server-addr: nacos.zkjiadi.cc
dataId: sentinel-ruoyi-gateway
groupId: DEFAULT_GROUP
data-type: json
rule-type: gw-flow
logging:
file:
name: test-ruoyi-gateway.log
pattern:
file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"

View File

@ -1,40 +1,4 @@
# Tomcat # Spring默认环境配置
server:
port: 8080
# Spring
spring: spring:
application:
# 应用名称
name: ruoyi-gateway
profiles: profiles:
# 环境配置
active: dev active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
sentinel:
# 取消控制台懒加载
eager: true
transport:
# 控制台地址
dashboard: 127.0.0.1:8718
# nacos配置持久化
datasource:
ds1:
nacos:
server-addr: 127.0.0.1:8848
dataId: sentinel-ruoyi-gateway
groupId: DEFAULT_GROUP
data-type: json
rule-type: gw-flow

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -66,6 +66,10 @@
<artifactId>ruoyi-api-system</artifactId> <artifactId>ruoyi-api-system</artifactId>
</dependency> </dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,140 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.autoconfigure.endpoint.web;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* Configuration properties for web management endpoints.
*
* @author Madhura Bhave
* @author Phillip Webb
* @since 2.0.0
*/
@ConfigurationProperties(prefix = "management.endpoints.web")
public class WebEndpointProperties {
private final Exposure exposure = new Exposure();
/**
* Base path for Web endpoints. Relative to the servlet context path
* (server.servlet.context-path) or WebFlux base path (spring.webflux.base-path) when
* the management server is sharing the main server port. Relative to the management
* server base path (management.server.base-path) when a separate management server
* port (management.server.port) is configured.
*/
private String basePath = "/actuator";
private String baseUrl = null;
/**
* Mapping between endpoint IDs and the path that should expose them.
*/
private final Map<String, String> pathMapping = new LinkedHashMap<>();
private final Discovery discovery = new Discovery();
public Exposure getExposure() {
return this.exposure;
}
public String getBasePath() {
return this.basePath;
}
public void setBasePath(String basePath) {
Assert.isTrue(basePath.isEmpty() || basePath.startsWith("/"), "Base path must start with '/' or be empty");
this.basePath = cleanBasePath(basePath);
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
private String cleanBasePath(String basePath) {
if (StringUtils.hasText(basePath) && basePath.endsWith("/")) {
return basePath.substring(0, basePath.length() - 1);
}
return basePath;
}
public Map<String, String> getPathMapping() {
return this.pathMapping;
}
public Discovery getDiscovery() {
return this.discovery;
}
public static class Exposure {
/**
* Endpoint IDs that should be included or '*' for all.
*/
private Set<String> include = new LinkedHashSet<>();
/**
* Endpoint IDs that should be excluded or '*' for all.
*/
private Set<String> exclude = new LinkedHashSet<>();
public Set<String> getInclude() {
return this.include;
}
public void setInclude(Set<String> include) {
this.include = include;
}
public Set<String> getExclude() {
return this.exclude;
}
public void setExclude(Set<String> exclude) {
this.exclude = exclude;
}
}
public static class Discovery {
/**
* Whether the discovery page is enabled.
*/
private boolean enabled = true;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
}

View File

@ -0,0 +1,113 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.endpoint.web.servlet;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.util.pattern.PathPatternParser;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
/**
* A custom {@link HandlerMapping} that makes web endpoints available over HTTP using
* Spring MVC.
*
* @author Andy Wilkinson
* @author Phillip Webb
* @since 2.0.0
*/
public class WebMvcEndpointHandlerMapping extends AbstractWebMvcEndpointHandlerMapping {
private final EndpointLinksResolver linksResolver;
@Lazy
@Resource
private WebEndpointProperties webEndpointProperties;
/**
* Creates a new {@code WebMvcEndpointHandlerMapping} instance that provides mappings
* for the given endpoints.
* @param endpointMapping the base mapping for all endpoints
* @param endpoints the web endpoints
* @param endpointMediaTypes media types consumed and produced by the endpoints
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
* @param linksResolver resolver for determining links to available endpoints
* @param shouldRegisterLinksMapping whether the links endpoint should be registered
*/
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
EndpointLinksResolver linksResolver, boolean shouldRegisterLinksMapping) {
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, shouldRegisterLinksMapping);
this.linksResolver = linksResolver;
setOrder(-100);
}
/**
* Creates a new {@code WebMvcEndpointHandlerMapping} instance that provides mappings
* for the given endpoints.
* @param endpointMapping the base mapping for all endpoints
* @param endpoints the web endpoints
* @param endpointMediaTypes media types consumed and produced by the endpoints
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
* @param linksResolver resolver for determining links to available endpoints
* @param shouldRegisterLinksMapping whether the links endpoint should be registered
* @param pathPatternParser the path pattern parser
*/
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
EndpointLinksResolver linksResolver, boolean shouldRegisterLinksMapping,
PathPatternParser pathPatternParser) {
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, shouldRegisterLinksMapping,
pathPatternParser);
this.linksResolver = linksResolver;
setOrder(-100);
}
@Override
protected LinksHandler getLinksHandler() {
return new WebMvcLinksHandler();
}
/**
* Handler for root endpoint providing links.
*/
class WebMvcLinksHandler implements LinksHandler {
@Override
@ResponseBody
public Map<String, Map<String, Link>> links(HttpServletRequest request, HttpServletResponse response) {
return Collections.singletonMap("_links",
WebMvcEndpointHandlerMapping.this.linksResolver.resolveLinks(ObjectUtils.isEmpty(webEndpointProperties.getBaseUrl())?request.getRequestURL().toString():(webEndpointProperties.getBaseUrl()+webEndpointProperties.getBasePath())));
}
@Override
public String toString() {
return "Actuator root web endpoint";
}
}
}

View File

@ -0,0 +1,28 @@
# Tomcat
server:
port: 9300
# Spring
spring:
application:
# 应用名称
name: ruoyi-file
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA

View File

@ -0,0 +1,29 @@
# Tomcat
server:
port: 9300
# Spring
spring:
application:
# 应用名称
name: ruoyi-file
cloud:
nacos:
discovery:
ip: 8.155.60.167
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: e2708b29-ca15-4f63-a919-d33932ebdfda
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: e2708b29-ca15-4f63-a919-d33932ebdfda
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA

View File

@ -0,0 +1,28 @@
# Tomcat
server:
port: 9300
# Spring
spring:
application:
# 应用名称
name: ruoyi-file
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 45c724b0-9b42-4ff2-bff2-9220a1788392
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 45c724b0-9b42-4ff2-bff2-9220a1788392
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA

View File

@ -1,25 +1,4 @@
# Tomcat # Spring默认环境配置
server:
port: 9300
# Spring
spring: spring:
application:
# 应用名称
name: ruoyi-file
profiles: profiles:
# 环境配置
active: dev active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -65,6 +65,10 @@
<artifactId>ruoyi-common-swagger</artifactId> <artifactId>ruoyi-common-swagger</artifactId>
</dependency> </dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,140 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.autoconfigure.endpoint.web;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* Configuration properties for web management endpoints.
*
* @author Madhura Bhave
* @author Phillip Webb
* @since 2.0.0
*/
@ConfigurationProperties(prefix = "management.endpoints.web")
public class WebEndpointProperties {
private final Exposure exposure = new Exposure();
/**
* Base path for Web endpoints. Relative to the servlet context path
* (server.servlet.context-path) or WebFlux base path (spring.webflux.base-path) when
* the management server is sharing the main server port. Relative to the management
* server base path (management.server.base-path) when a separate management server
* port (management.server.port) is configured.
*/
private String basePath = "/actuator";
private String baseUrl = null;
/**
* Mapping between endpoint IDs and the path that should expose them.
*/
private final Map<String, String> pathMapping = new LinkedHashMap<>();
private final Discovery discovery = new Discovery();
public Exposure getExposure() {
return this.exposure;
}
public String getBasePath() {
return this.basePath;
}
public void setBasePath(String basePath) {
Assert.isTrue(basePath.isEmpty() || basePath.startsWith("/"), "Base path must start with '/' or be empty");
this.basePath = cleanBasePath(basePath);
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
private String cleanBasePath(String basePath) {
if (StringUtils.hasText(basePath) && basePath.endsWith("/")) {
return basePath.substring(0, basePath.length() - 1);
}
return basePath;
}
public Map<String, String> getPathMapping() {
return this.pathMapping;
}
public Discovery getDiscovery() {
return this.discovery;
}
public static class Exposure {
/**
* Endpoint IDs that should be included or '*' for all.
*/
private Set<String> include = new LinkedHashSet<>();
/**
* Endpoint IDs that should be excluded or '*' for all.
*/
private Set<String> exclude = new LinkedHashSet<>();
public Set<String> getInclude() {
return this.include;
}
public void setInclude(Set<String> include) {
this.include = include;
}
public Set<String> getExclude() {
return this.exclude;
}
public void setExclude(Set<String> exclude) {
this.exclude = exclude;
}
}
public static class Discovery {
/**
* Whether the discovery page is enabled.
*/
private boolean enabled = true;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
}

View File

@ -0,0 +1,113 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.endpoint.web.servlet;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.util.pattern.PathPatternParser;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
/**
* A custom {@link HandlerMapping} that makes web endpoints available over HTTP using
* Spring MVC.
*
* @author Andy Wilkinson
* @author Phillip Webb
* @since 2.0.0
*/
public class WebMvcEndpointHandlerMapping extends AbstractWebMvcEndpointHandlerMapping {
private final EndpointLinksResolver linksResolver;
@Lazy
@Resource
private WebEndpointProperties webEndpointProperties;
/**
* Creates a new {@code WebMvcEndpointHandlerMapping} instance that provides mappings
* for the given endpoints.
* @param endpointMapping the base mapping for all endpoints
* @param endpoints the web endpoints
* @param endpointMediaTypes media types consumed and produced by the endpoints
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
* @param linksResolver resolver for determining links to available endpoints
* @param shouldRegisterLinksMapping whether the links endpoint should be registered
*/
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
EndpointLinksResolver linksResolver, boolean shouldRegisterLinksMapping) {
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, shouldRegisterLinksMapping);
this.linksResolver = linksResolver;
setOrder(-100);
}
/**
* Creates a new {@code WebMvcEndpointHandlerMapping} instance that provides mappings
* for the given endpoints.
* @param endpointMapping the base mapping for all endpoints
* @param endpoints the web endpoints
* @param endpointMediaTypes media types consumed and produced by the endpoints
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
* @param linksResolver resolver for determining links to available endpoints
* @param shouldRegisterLinksMapping whether the links endpoint should be registered
* @param pathPatternParser the path pattern parser
*/
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
EndpointLinksResolver linksResolver, boolean shouldRegisterLinksMapping,
PathPatternParser pathPatternParser) {
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, shouldRegisterLinksMapping,
pathPatternParser);
this.linksResolver = linksResolver;
setOrder(-100);
}
@Override
protected LinksHandler getLinksHandler() {
return new WebMvcLinksHandler();
}
/**
* Handler for root endpoint providing links.
*/
class WebMvcLinksHandler implements LinksHandler {
@Override
@ResponseBody
public Map<String, Map<String, Link>> links(HttpServletRequest request, HttpServletResponse response) {
return Collections.singletonMap("_links",
WebMvcEndpointHandlerMapping.this.linksResolver.resolveLinks(ObjectUtils.isEmpty(webEndpointProperties.getBaseUrl())?request.getRequestURL().toString():(webEndpointProperties.getBaseUrl()+webEndpointProperties.getBasePath())));
}
@Override
public String toString() {
return "Actuator root web endpoint";
}
}
}

View File

@ -0,0 +1,28 @@
# Tomcat
server:
port: 9202
# Spring
spring:
application:
# 应用名称
name: ruoyi-gen
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA

View File

@ -0,0 +1,29 @@
# Tomcat
server:
port: 9202
# Spring
spring:
application:
# 应用名称
name: ruoyi-gen
cloud:
nacos:
discovery:
ip: 8.155.60.167
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: e2708b29-ca15-4f63-a919-d33932ebdfda
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: e2708b29-ca15-4f63-a919-d33932ebdfda
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA

View File

@ -0,0 +1,28 @@
# Tomcat
server:
port: 9202
# Spring
spring:
application:
# 应用名称
name: ruoyi-gen
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 45c724b0-9b42-4ff2-bff2-9220a1788392
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 45c724b0-9b42-4ff2-bff2-9220a1788392
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA

View File

@ -1,25 +1,4 @@
# Tomcat # Spring默认环境配置
server:
port: 9202
# Spring
spring: spring:
application:
# 应用名称
name: ruoyi-gen
profiles: profiles:
# 环境配置
active: dev active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -71,6 +71,22 @@
<artifactId>ruoyi-common-swagger</artifactId> <artifactId>ruoyi-common-swagger</artifactId>
</dependency> </dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.12.13</version>
</dependency>
<dependency>
<groupId>com.ujcms</groupId>
<artifactId>ujcms-commons</artifactId>
<version>9.6.0.0.1</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,23 @@
package com.ruoyi.job.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
/**
*
*
* @author ruoyi
*/
@Data
@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "security.sms.aliyuncs")
public class SmsConfig
{
private String accessKeyId;
private String accessKeySecret;
private String signName;
private String templateCode;
}

View File

@ -0,0 +1,78 @@
package com.ruoyi.job.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ruoyi.common.core.web.domain.BaseEntity;
import com.ruoyi.job.util.ProgressFormatterUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.data.annotation.Id;
import java.math.BigDecimal;
/**
*
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class ScClassUserInfo extends BaseEntity {
@Id
private Long id;
//@ExcelIgnore // 不导出该字段
private Long userId;
//@ExcelIgnore // 不导出该字段
private Long classId;
//@ColumnWidth(25)
// @ExcelProperty("名称(报名时)")
private String name;
//@ColumnWidth(25)
//@ExcelProperty("单位")
private String firm;
//@ColumnWidth(25)
//@ExcelProperty("专业")
private String specialized;
//@ColumnWidth(35)
//@ExcelProperty("手机号")
private String phonenumber;
//@ColumnWidth(35)
//@ExcelProperty("昵称")
private String nickName;
/**
*
*/
//@ExcelProperty("客户订单编号")
private String userSn;
//@ExcelIgnore
private Boolean todayAttendanceIs;
@JsonIgnore
// @ExcelProperty("是否打卡")
private String attendanceIs;
//@ExcelProperty("签到次数")
private Integer attendanceCount;
//@ExcelIgnore
private BigDecimal progress;
//@ExcelProperty("总学习进度")
private String progressPercent;
public String getAttendanceIs() {
return attendanceCount.compareTo(0) > 0 ? "是" : "否";
}
public String getProgressPercent() {
return ProgressFormatterUtil.format(this.progress.multiply(BigDecimal.valueOf(100)));
}
}

View File

@ -0,0 +1,14 @@
package com.ruoyi.job.mapper;
import com.ruoyi.job.domain.ScClassUserInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
//@Mapper
//public interface ScClassUserInfoMapper extends tk.mybatis.mapper.common.Mapper<ScClassUserInfo>
public interface ScClassUserInfoMapper
{
List<ScClassUserInfo> waitNoticeCourseUser();
}

View File

@ -0,0 +1,16 @@
package com.ruoyi.job.service;
import com.ruoyi.common.core.exception.CaptchaException;
/**
*
*
* @author ruoyi
*/
public interface SmsService
{
/**
*
*/
public void sendStudyNoticeSms(String phone) throws CaptchaException;
}

View File

@ -0,0 +1,35 @@
package com.ruoyi.job.service.impl;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.exception.CaptchaException;
import com.ruoyi.job.config.SmsConfig;
import com.ruoyi.job.service.SmsService;
import com.ujcms.commons.sms.AliyunUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
*
*
* @author ruoyi
*/
@Service
public class SmsServiceImpl implements SmsService
{
@Autowired
private SmsConfig smsConfig;
/**
*
*/
@Override
public void sendStudyNoticeSms(String phone) throws CaptchaException {
AliyunUtils.sendSms(smsConfig.getAccessKeyId(),
smsConfig.getAccessKeySecret(),
smsConfig.getSignName(),
smsConfig.getTemplateCode(),
JSONObject.of(),
phone
);
}
}

View File

@ -0,0 +1,36 @@
package com.ruoyi.job.task;
import com.ruoyi.job.config.SmsConfig;
import com.ruoyi.job.domain.ScClassUserInfo;
import com.ruoyi.job.mapper.ScClassUserInfoMapper;
import com.ruoyi.job.service.SmsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
@Slf4j
@Component("liveTask")
public class LiveTask {
@Resource
ScClassUserInfoMapper scClassUserInfoMapper;
@Autowired
private SmsService smsAliyuncs;
@Autowired
private SmsConfig smsConfig;
/**
*
*/
public void CourseSmsNotice(){
List<ScClassUserInfo> list = scClassUserInfoMapper.waitNoticeCourseUser();
list.forEach(item->{
if (item.getPhonenumber() != null && !item.getPhonenumber().trim().isEmpty()){
log.info("发送打卡提醒 {} {} {}",item.getUserId(),item.getNickName(),item.getPhonenumber());
smsAliyuncs.sendStudyNoticeSms(item.getPhonenumber());
}
});
}
}

View File

@ -0,0 +1,18 @@
package com.ruoyi.job.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
public class ProgressFormatterUtil {
public static String format(BigDecimal progress ) {
if (progress == null) return "0";
// 保留两位小数(四舍五入)
BigDecimal scaled = progress.setScale(2, RoundingMode.HALF_UP);
// 去除末尾零和小数点
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(0);
return nf.format(scaled) + "%";
}
}

View File

@ -0,0 +1,140 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.autoconfigure.endpoint.web;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* Configuration properties for web management endpoints.
*
* @author Madhura Bhave
* @author Phillip Webb
* @since 2.0.0
*/
@ConfigurationProperties(prefix = "management.endpoints.web")
public class WebEndpointProperties {
private final Exposure exposure = new Exposure();
/**
* Base path for Web endpoints. Relative to the servlet context path
* (server.servlet.context-path) or WebFlux base path (spring.webflux.base-path) when
* the management server is sharing the main server port. Relative to the management
* server base path (management.server.base-path) when a separate management server
* port (management.server.port) is configured.
*/
private String basePath = "/actuator";
private String baseUrl = null;
/**
* Mapping between endpoint IDs and the path that should expose them.
*/
private final Map<String, String> pathMapping = new LinkedHashMap<>();
private final Discovery discovery = new Discovery();
public Exposure getExposure() {
return this.exposure;
}
public String getBasePath() {
return this.basePath;
}
public void setBasePath(String basePath) {
Assert.isTrue(basePath.isEmpty() || basePath.startsWith("/"), "Base path must start with '/' or be empty");
this.basePath = cleanBasePath(basePath);
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
private String cleanBasePath(String basePath) {
if (StringUtils.hasText(basePath) && basePath.endsWith("/")) {
return basePath.substring(0, basePath.length() - 1);
}
return basePath;
}
public Map<String, String> getPathMapping() {
return this.pathMapping;
}
public Discovery getDiscovery() {
return this.discovery;
}
public static class Exposure {
/**
* Endpoint IDs that should be included or '*' for all.
*/
private Set<String> include = new LinkedHashSet<>();
/**
* Endpoint IDs that should be excluded or '*' for all.
*/
private Set<String> exclude = new LinkedHashSet<>();
public Set<String> getInclude() {
return this.include;
}
public void setInclude(Set<String> include) {
this.include = include;
}
public Set<String> getExclude() {
return this.exclude;
}
public void setExclude(Set<String> exclude) {
this.exclude = exclude;
}
}
public static class Discovery {
/**
* Whether the discovery page is enabled.
*/
private boolean enabled = true;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
}

View File

@ -0,0 +1,113 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.endpoint.web.servlet;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.util.pattern.PathPatternParser;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
/**
* A custom {@link HandlerMapping} that makes web endpoints available over HTTP using
* Spring MVC.
*
* @author Andy Wilkinson
* @author Phillip Webb
* @since 2.0.0
*/
public class WebMvcEndpointHandlerMapping extends AbstractWebMvcEndpointHandlerMapping {
private final EndpointLinksResolver linksResolver;
@Lazy
@Resource
private WebEndpointProperties webEndpointProperties;
/**
* Creates a new {@code WebMvcEndpointHandlerMapping} instance that provides mappings
* for the given endpoints.
* @param endpointMapping the base mapping for all endpoints
* @param endpoints the web endpoints
* @param endpointMediaTypes media types consumed and produced by the endpoints
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
* @param linksResolver resolver for determining links to available endpoints
* @param shouldRegisterLinksMapping whether the links endpoint should be registered
*/
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
EndpointLinksResolver linksResolver, boolean shouldRegisterLinksMapping) {
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, shouldRegisterLinksMapping);
this.linksResolver = linksResolver;
setOrder(-100);
}
/**
* Creates a new {@code WebMvcEndpointHandlerMapping} instance that provides mappings
* for the given endpoints.
* @param endpointMapping the base mapping for all endpoints
* @param endpoints the web endpoints
* @param endpointMediaTypes media types consumed and produced by the endpoints
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
* @param linksResolver resolver for determining links to available endpoints
* @param shouldRegisterLinksMapping whether the links endpoint should be registered
* @param pathPatternParser the path pattern parser
*/
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
EndpointLinksResolver linksResolver, boolean shouldRegisterLinksMapping,
PathPatternParser pathPatternParser) {
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, shouldRegisterLinksMapping,
pathPatternParser);
this.linksResolver = linksResolver;
setOrder(-100);
}
@Override
protected LinksHandler getLinksHandler() {
return new WebMvcLinksHandler();
}
/**
* Handler for root endpoint providing links.
*/
class WebMvcLinksHandler implements LinksHandler {
@Override
@ResponseBody
public Map<String, Map<String, Link>> links(HttpServletRequest request, HttpServletResponse response) {
return Collections.singletonMap("_links",
WebMvcEndpointHandlerMapping.this.linksResolver.resolveLinks(ObjectUtils.isEmpty(webEndpointProperties.getBaseUrl())?request.getRequestURL().toString():(webEndpointProperties.getBaseUrl()+webEndpointProperties.getBasePath())));
}
@Override
public String toString() {
return "Actuator root web endpoint";
}
}
}

View File

@ -0,0 +1,28 @@
# Tomcat
server:
port: 9203
# Spring
spring:
application:
# 应用名称
name: ruoyi-job
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA

View File

@ -0,0 +1,29 @@
# Tomcat
server:
port: 9203
# Spring
spring:
application:
# 应用名称
name: ruoyi-job
cloud:
nacos:
discovery:
ip: 8.155.60.167
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: e2708b29-ca15-4f63-a919-d33932ebdfda
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: e2708b29-ca15-4f63-a919-d33932ebdfda
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA

View File

@ -0,0 +1,28 @@
# Tomcat
server:
port: 9203
# Spring
spring:
application:
# 应用名称
name: ruoyi-job
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 45c724b0-9b42-4ff2-bff2-9220a1788392
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 45c724b0-9b42-4ff2-bff2-9220a1788392
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA

View File

@ -1,25 +1,4 @@
# Tomcat # Spring默认环境配置
server:
port: 9203
# Spring
spring: spring:
application:
# 应用名称
name: ruoyi-job
profiles: profiles:
# 环境配置
active: dev active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

View File

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.ruoyi.job.mapper.ScClassUserInfoMapper">
<resultMap id="scClassUserInfo" type="com.ruoyi.job.domain.ScClassUserInfo">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="firm" property="firm"/>
<result column="specialized" property="specialized"/>
<result column="nick_name" property="nickName"/>
<result column="todayAttendanceIs" property="todayAttendanceIs"/>
<result column="attendanceCount" property="attendanceCount"/>
<result column="progress" property="progress"/>
</resultMap>
<select id="waitNoticeCourseUser" resultMap="scClassUserInfo">
SELECT
progress.id,
progress.userId,
progress.classId,
progress.`name`,
progress.email,
progress.phonenumber,
progress.userSn,
progress.firm,
progress.posts,
progress.areas_of_focus,
progress.issue,
progress.specialized,
progress.nick_name,
attendance.todayAttendanceIs,
attendance.attendanceCount,
progress.progress
FROM
(
SELECT
scui.id,
COUNT( sua_today.id ) AS todayAttendanceIs,
COUNT( sua_count.id ) AS attendanceCount
FROM
sc_class_user_info scui
LEFT JOIN sc_user_attendance sua_today ON (
sua_today.class_info_id = scui.class_id
AND sua_today.user_id = scui.user_id
AND sua_today.`status` = 1
AND to_days( sua_today.create_time ) = to_days(
now())
)
LEFT JOIN sc_user_attendance sua_count ON ( sua_count.class_info_id = scui.class_id AND sua_count.user_id = scui.user_id AND sua_count.`status` = 1 )
WHERE
scui.`status` = 1
AND scui.end_time > now()
AND ( scui.delete_flag != scui.id OR scui.delete_flag IS NULL )
GROUP BY
scui.id
) attendance
INNER JOIN (
SELECT
scui.id,
scui.user_id AS userId,
scui.class_id AS classId,
scui.`name`,
scui.email,
scui.phonenumber,
scui.user_sn AS userSn,
scui.firm,
scui.posts,
scui.areas_of_focus,
scui.issue,
scui.specialized,
y.nick_name,
CASE
WHEN COUNT( DISTINCT video.id ) = 0 THEN
0 ELSE (
COUNT(
DISTINCT
CASE
WHEN ( TIME_TO_SEC( video.duration ) = 0 AND record.type_id IS NOT NULL )
OR (
record.total_duration >= 0.8 * TIME_TO_SEC( video.duration )) THEN
video.id
END
)
) / COUNT(DISTINCT video.id )
END AS progress
FROM
sc_class_user_info scui
INNER JOIN sys_user y ON scui.user_id = y.user_id
LEFT JOIN sc_video video ON ( video.class_info_id = scui.class_id AND video.`status` = 1 )
LEFT JOIN sc_class_user_record_info record ON ( record.type = 'ScVideo' AND record.type_id = video.id AND scui.user_id = record.user_id )
WHERE
scui.`status` = 1
AND scui.end_time > now()
AND ( scui.delete_flag != scui.id OR scui.delete_flag IS NULL )
GROUP BY
scui.id
) progress ON attendance.id = progress.id WHERE progress.progress &lt; 1 GROUP BY progress.userId
</select>
</mapper>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>
<version>3.6.7</version> <version>3.6.5.0.9</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -71,11 +71,36 @@
<artifactId>ruoyi-common-swagger</artifactId> <artifactId>ruoyi-common-swagger</artifactId>
</dependency> </dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>${project.artifactId}</finalName> <finalName>${project.artifactId}</finalName>
<plugins> <plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>

View File

@ -89,4 +89,13 @@ public class SysNoticeController extends BaseController
{ {
return toAjax(noticeService.deleteNoticeByIds(noticeIds)); return toAjax(noticeService.deleteNoticeByIds(noticeIds));
} }
/**
*
*/
@GetMapping("/no-login/{noticeTitle}")
public AjaxResult getInfo(@PathVariable String noticeTitle)
{
return success(noticeService.selectNoticeByNoticeTitle(noticeTitle));
}
} }

View File

@ -163,7 +163,17 @@ public class SysUserController extends BaseController
@PutMapping("/recordlogin") @PutMapping("/recordlogin")
public R<Boolean> recordlogin(@RequestBody SysUser sysUser) public R<Boolean> recordlogin(@RequestBody SysUser sysUser)
{ {
return R.ok(userService.updateLoginInfo(sysUser)); return R.ok(userService.updateUserProfile(sysUser));
}
/**
*IP
*/
@InnerAuth
@PutMapping("/syncGO")
public R<Boolean> syncGO(@RequestBody SysUser sysUser)
{
return R.ok(userService.syncGO(sysUser));
} }
/** /**

View File

@ -0,0 +1,17 @@
package com.ruoyi.system.domain;
import lombok.Data;
@Data
public class SyncGoUser {
private Integer userId;
private String nickname;
private String username;
private String mobile;
private String lastIp;
private String remark;
private String avatar;
private Integer status;
private String openId;
private String unionId;
}

View File

@ -57,4 +57,12 @@ public interface SysNoticeMapper
* @return * @return
*/ */
public int deleteNoticeByIds(Long[] noticeIds); public int deleteNoticeByIds(Long[] noticeIds);
/**
*
*
* @param noticeTitle
* @return
*/
public SysNotice selectNoticeByNoticeTitle(String noticeTitle);
} }

View File

@ -1,6 +1,8 @@
package com.ruoyi.system.mapper; package com.ruoyi.system.mapper;
import java.util.List; import java.util.List;
import com.github.pagehelper.Page;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.api.domain.SysUser;
@ -43,6 +45,22 @@ public interface SysUserMapper
*/ */
public SysUser selectUserByUserName(String userName); public SysUser selectUserByUserName(String userName);
/**
*
*
* @param phoneNumber
* @return
*/
public SysUser selectUserByPhoneNumber(String phoneNumber);
/**
*
*
* @param phoneNumber
* @return
*/
public Page<SysUser> findByPhoneNumberStartingWith(String phoneNumber);
/** /**
* ID * ID
* *
@ -70,37 +88,20 @@ public interface SysUserMapper
/** /**
* *
* *
* @param userId ID * @param userName
* @param avatar * @param avatar
* @return * @return
*/ */
public int updateUserAvatar(@Param("userId") Long userId, @Param("avatar") String avatar); public int updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar);
/**
*
*
* @param userId ID
* @param status
* @return
*/
public int updateUserStatus(@Param("userId") Long userId, @Param("status") String status);
/**
* IP
*
* @param user
* @return
*/
public int updateLoginInfo(SysUser user);
/** /**
* *
* *
* @param userId ID * @param userName
* @param password * @param password
* @return * @return
*/ */
public int resetUserPwd(@Param("userId") Long userId, @Param("password") String password); public int resetUserPwd(@Param("userName") String userName, @Param("password") String password);
/** /**
* ID * ID

View File

@ -57,4 +57,12 @@ public interface ISysNoticeService
* @return * @return
*/ */
public int deleteNoticeByIds(Long[] noticeIds); public int deleteNoticeByIds(Long[] noticeIds);
/**
*
*
* @param noticeTitle
* @return
*/
public SysNotice selectNoticeByNoticeTitle(String noticeTitle);
} }

View File

@ -1,6 +1,8 @@
package com.ruoyi.system.service; package com.ruoyi.system.service;
import java.util.List; import java.util.List;
import com.github.pagehelper.Page;
import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.api.domain.SysUser;
/** /**
@ -42,6 +44,14 @@ public interface ISysUserService
*/ */
public SysUser selectUserByUserName(String userName); public SysUser selectUserByUserName(String userName);
/**
*
*
* @param phoneNumber
* @return
*/
public SysUser selectUserByPhoneNumber(String phoneNumber);
/** /**
* ID * ID
* *
@ -50,6 +60,14 @@ public interface ISysUserService
*/ */
public SysUser selectUserById(Long userId); public SysUser selectUserById(Long userId);
/**
*
*
* @param phoneNumber
* @return
*/
public Page<SysUser> findByPhoneNumberStartingWith(String phoneNumber);
/** /**
* ID * ID
* *
@ -153,21 +171,21 @@ public interface ISysUserService
public boolean updateUserProfile(SysUser user); public boolean updateUserProfile(SysUser user);
/** /**
* *
*
* @param userId ID
* @param avatar
* @return
*/
public boolean updateUserAvatar(Long userId, String avatar);
/**
* IP
* *
* @param user * @param user
* @return * @return
*/ */
public boolean updateLoginInfo(SysUser user); public boolean syncGO(SysUser user);
/**
*
*
* @param userName
* @param avatar
* @return
*/
public boolean updateUserAvatar(String userName, String avatar);
/** /**
* *
@ -180,11 +198,11 @@ public interface ISysUserService
/** /**
* *
* *
* @param userId ID * @param userName
* @param password * @param password
* @return * @return
*/ */
public int resetUserPwd(Long userId, String password); public int resetUserPwd(String userName, String password);
/** /**
* ID * ID

View File

@ -89,4 +89,15 @@ public class SysNoticeServiceImpl implements ISysNoticeService
{ {
return noticeMapper.deleteNoticeByIds(noticeIds); return noticeMapper.deleteNoticeByIds(noticeIds);
} }
/**
*
*
* @param noticeTitle
* @return
*/
@Override
public SysNotice selectNoticeByNoticeTitle(String noticeTitle) {
return noticeMapper.selectNoticeByNoticeTitle(noticeTitle);
}
} }

View File

@ -2,11 +2,22 @@ package com.ruoyi.system.service.impl;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.validation.Validator; import javax.validation.Validator;
import cn.hutool.system.UserInfo;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.ruoyi.system.api.domain.KSysUserAccount;
import com.ruoyi.system.domain.SyncGoUser;
import com.ruoyi.system.service.IKSysUserService;
import org.apache.http.client.methods.HttpPost;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@ -30,6 +41,7 @@ import com.ruoyi.system.mapper.SysUserRoleMapper;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDeptService; import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
import org.springframework.web.client.RestTemplate;
/** /**
* *
@ -39,11 +51,19 @@ import com.ruoyi.system.service.ISysUserService;
@Service @Service
public class SysUserServiceImpl implements ISysUserService public class SysUserServiceImpl implements ISysUserService
{ {
@Value("${go.host}")
private String goHost;
@Value("${go.accessKey}")
private String accessKey;
private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class); private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);
@Autowired @Autowired
private SysUserMapper userMapper; private SysUserMapper userMapper;
@Autowired
private IKSysUserService kSysUserService;
@Autowired @Autowired
private SysRoleMapper roleMapper; private SysRoleMapper roleMapper;
@ -65,6 +85,7 @@ public class SysUserServiceImpl implements ISysUserService
@Autowired @Autowired
protected Validator validator; protected Validator validator;
/** /**
* *
* *
@ -116,6 +137,28 @@ public class SysUserServiceImpl implements ISysUserService
return userMapper.selectUserByUserName(userName); return userMapper.selectUserByUserName(userName);
} }
/**
*
*
* @param phoneNumber
* @return
*/
@Override
public SysUser selectUserByPhoneNumber(String phoneNumber) {
return userMapper.selectUserByPhoneNumber(phoneNumber);
}
/**
*
*
* @param phoneNumber
* @return
*/
@Override
public Page<SysUser> findByPhoneNumberStartingWith(String phoneNumber) {
return userMapper.findByPhoneNumberStartingWith(phoneNumber);
}
/** /**
* ID * ID
* *
@ -278,7 +321,9 @@ public class SysUserServiceImpl implements ISysUserService
@Override @Override
public boolean registerUser(SysUser user) public boolean registerUser(SysUser user)
{ {
return userMapper.insertUser(user) > 0; boolean res = userMapper.insertUser(user) > 0;
this.syncGO(user);
return res;
} }
/** /**
@ -289,8 +334,7 @@ public class SysUserServiceImpl implements ISysUserService
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public int updateUser(SysUser user) public int updateUser(SysUser user) {
{
Long userId = user.getUserId(); Long userId = user.getUserId();
// 删除用户与角色关联 // 删除用户与角色关联
userRoleMapper.deleteUserRoleByUserId(userId); userRoleMapper.deleteUserRoleByUserId(userId);
@ -300,6 +344,13 @@ public class SysUserServiceImpl implements ISysUserService
userPostMapper.deleteUserPostByUserId(userId); userPostMapper.deleteUserPostByUserId(userId);
// 新增用户与岗位管理 // 新增用户与岗位管理
insertUserPost(user); insertUserPost(user);
// 更新微信信息
if (Objects.nonNull(user.getSysUserAccount())) {
if (Objects.nonNull(user.getSysUserAccount().getWxUnionId())) {
kSysUserService.updateSysUserAccount(user.getSysUserAccount());
}
}
this.syncGO(user);
return userMapper.updateUser(user); return userMapper.updateUser(user);
} }
@ -326,7 +377,8 @@ public class SysUserServiceImpl implements ISysUserService
@Override @Override
public int updateUserStatus(SysUser user) public int updateUserStatus(SysUser user)
{ {
return userMapper.updateUserStatus(user.getUserId(), user.getStatus()); this.syncGO(user);
return userMapper.updateUser(user);
} }
/** /**
@ -338,31 +390,54 @@ public class SysUserServiceImpl implements ISysUserService
@Override @Override
public boolean updateUserProfile(SysUser user) public boolean updateUserProfile(SysUser user)
{ {
this.syncGO(user);
return userMapper.updateUser(user) > 0; return userMapper.updateUser(user) > 0;
} }
/**
*
*
* @param user
* @return
*/
@Override
public boolean syncGO(SysUser user){
RestTemplate restTemplate = new RestTemplate();
String url = goHost + "/api/v2/mini/user/zkSyncUser/"+accessKey;
SyncGoUser syncGoUser = new SyncGoUser();
syncGoUser.setUserId(Math.toIntExact(user.getUserId()));
syncGoUser.setNickname(user.getNickName());
syncGoUser.setUsername(user.getUserName());
syncGoUser.setMobile(user.getPhonenumber());
syncGoUser.setLastIp(user.getLoginIp());
syncGoUser.setRemark(user.getRemark());
syncGoUser.setAvatar(user.getAvatar());
syncGoUser.setStatus(Objects.equals(user.getStatus(), "1") ?1:0);
if (user.getSysUserAccount() != null) {
syncGoUser.setUnionId(user.getSysUserAccount().getWxUnionId());
syncGoUser.setOpenId(user.getSysUserAccount().getRoutineOpenid());
}
ResponseEntity<String> response = restTemplate.postForEntity(url, syncGoUser, String.class);
// 检查响应状态码
if (response.getStatusCode().is2xxSuccessful()) {
System.out.println("响应内容:" + response.getBody());
} else {
System.out.println("请求失败,状态码:" + response.getStatusCode());
}
return true;
}
/** /**
* *
* *
* @param userId ID * @param userName
* @param avatar * @param avatar
* @return * @return
*/ */
@Override @Override
public boolean updateUserAvatar(Long userId, String avatar) public boolean updateUserAvatar(String userName, String avatar)
{ {
return userMapper.updateUserAvatar(userId, avatar) > 0; return userMapper.updateUserAvatar(userName, avatar) > 0;
}
/**
* IP
*
* @param user
* @return
*/
public boolean updateLoginInfo(SysUser user)
{
return userMapper.updateLoginInfo(user) > 0;
} }
/** /**
@ -374,20 +449,20 @@ public class SysUserServiceImpl implements ISysUserService
@Override @Override
public int resetPwd(SysUser user) public int resetPwd(SysUser user)
{ {
return userMapper.resetUserPwd(user.getUserId(), user.getPassword()); return userMapper.updateUser(user);
} }
/** /**
* *
* *
* @param userId ID * @param userName
* @param password * @param password
* @return * @return
*/ */
@Override @Override
public int resetUserPwd(Long userId, String password) public int resetUserPwd(String userName, String password)
{ {
return userMapper.resetUserPwd(userId, password); return userMapper.resetUserPwd(userName, password);
} }
/** /**
@ -528,7 +603,6 @@ public class SysUserServiceImpl implements ISysUserService
checkUserDataScope(u.getUserId()); checkUserDataScope(u.getUserId());
deptService.checkDeptDataScope(user.getDeptId()); deptService.checkDeptDataScope(user.getDeptId());
user.setUserId(u.getUserId()); user.setUserId(u.getUserId());
user.setDeptId(u.getDeptId());
user.setUpdateBy(operName); user.setUpdateBy(operName);
userMapper.updateUser(user); userMapper.updateUser(user);
successNum++; successNum++;

View File

@ -0,0 +1,140 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.autoconfigure.endpoint.web;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* Configuration properties for web management endpoints.
*
* @author Madhura Bhave
* @author Phillip Webb
* @since 2.0.0
*/
@ConfigurationProperties(prefix = "management.endpoints.web")
public class WebEndpointProperties {
private final Exposure exposure = new Exposure();
/**
* Base path for Web endpoints. Relative to the servlet context path
* (server.servlet.context-path) or WebFlux base path (spring.webflux.base-path) when
* the management server is sharing the main server port. Relative to the management
* server base path (management.server.base-path) when a separate management server
* port (management.server.port) is configured.
*/
private String basePath = "/actuator";
private String baseUrl = null;
/**
* Mapping between endpoint IDs and the path that should expose them.
*/
private final Map<String, String> pathMapping = new LinkedHashMap<>();
private final Discovery discovery = new Discovery();
public Exposure getExposure() {
return this.exposure;
}
public String getBasePath() {
return this.basePath;
}
public void setBasePath(String basePath) {
Assert.isTrue(basePath.isEmpty() || basePath.startsWith("/"), "Base path must start with '/' or be empty");
this.basePath = cleanBasePath(basePath);
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
private String cleanBasePath(String basePath) {
if (StringUtils.hasText(basePath) && basePath.endsWith("/")) {
return basePath.substring(0, basePath.length() - 1);
}
return basePath;
}
public Map<String, String> getPathMapping() {
return this.pathMapping;
}
public Discovery getDiscovery() {
return this.discovery;
}
public static class Exposure {
/**
* Endpoint IDs that should be included or '*' for all.
*/
private Set<String> include = new LinkedHashSet<>();
/**
* Endpoint IDs that should be excluded or '*' for all.
*/
private Set<String> exclude = new LinkedHashSet<>();
public Set<String> getInclude() {
return this.include;
}
public void setInclude(Set<String> include) {
this.include = include;
}
public Set<String> getExclude() {
return this.exclude;
}
public void setExclude(Set<String> exclude) {
this.exclude = exclude;
}
}
public static class Discovery {
/**
* Whether the discovery page is enabled.
*/
private boolean enabled = true;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
}

View File

@ -0,0 +1,113 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.endpoint.web.servlet;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.util.pattern.PathPatternParser;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
/**
* A custom {@link HandlerMapping} that makes web endpoints available over HTTP using
* Spring MVC.
*
* @author Andy Wilkinson
* @author Phillip Webb
* @since 2.0.0
*/
public class WebMvcEndpointHandlerMapping extends AbstractWebMvcEndpointHandlerMapping {
private final EndpointLinksResolver linksResolver;
@Lazy
@Resource
private WebEndpointProperties webEndpointProperties;
/**
* Creates a new {@code WebMvcEndpointHandlerMapping} instance that provides mappings
* for the given endpoints.
* @param endpointMapping the base mapping for all endpoints
* @param endpoints the web endpoints
* @param endpointMediaTypes media types consumed and produced by the endpoints
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
* @param linksResolver resolver for determining links to available endpoints
* @param shouldRegisterLinksMapping whether the links endpoint should be registered
*/
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
EndpointLinksResolver linksResolver, boolean shouldRegisterLinksMapping) {
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, shouldRegisterLinksMapping);
this.linksResolver = linksResolver;
setOrder(-100);
}
/**
* Creates a new {@code WebMvcEndpointHandlerMapping} instance that provides mappings
* for the given endpoints.
* @param endpointMapping the base mapping for all endpoints
* @param endpoints the web endpoints
* @param endpointMediaTypes media types consumed and produced by the endpoints
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
* @param linksResolver resolver for determining links to available endpoints
* @param shouldRegisterLinksMapping whether the links endpoint should be registered
* @param pathPatternParser the path pattern parser
*/
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping, Collection<ExposableWebEndpoint> endpoints,
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
EndpointLinksResolver linksResolver, boolean shouldRegisterLinksMapping,
PathPatternParser pathPatternParser) {
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, shouldRegisterLinksMapping,
pathPatternParser);
this.linksResolver = linksResolver;
setOrder(-100);
}
@Override
protected LinksHandler getLinksHandler() {
return new WebMvcLinksHandler();
}
/**
* Handler for root endpoint providing links.
*/
class WebMvcLinksHandler implements LinksHandler {
@Override
@ResponseBody
public Map<String, Map<String, Link>> links(HttpServletRequest request, HttpServletResponse response) {
return Collections.singletonMap("_links",
WebMvcEndpointHandlerMapping.this.linksResolver.resolveLinks(ObjectUtils.isEmpty(webEndpointProperties.getBaseUrl())?request.getRequestURL().toString():(webEndpointProperties.getBaseUrl()+webEndpointProperties.getBasePath())));
}
@Override
public String toString() {
return "Actuator root web endpoint";
}
}
}

View File

@ -0,0 +1,30 @@
package com.ruoyi.system.controller.inner
import com.ruoyi.common.core.domain.R
import com.ruoyi.common.core.web.controller.BaseController
import com.ruoyi.common.security.annotation.InnerAuth
import com.ruoyi.system.service.ISysNoticeService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
/**
* 内部调用公告信息
*/
@RestController
@RequestMapping("/inner/notice")
open class InnerSysNoticeController : BaseController() {
@Autowired
open lateinit var noticeService: ISysNoticeService
/**
* 根据ID获取公告信息
*/
@InnerAuth
@GetMapping("/detail")
fun infoById(@RequestParam("noticeId") noticeId: Long): R<Any> {
return R.ok(noticeService.selectNoticeById(noticeId))
}
}

View File

@ -0,0 +1,178 @@
package com.ruoyi.system.controller.inner
import com.github.pagehelper.Page
import com.ruoyi.common.core.domain.R
import com.ruoyi.common.core.utils.StringUtils
import com.ruoyi.common.core.utils.ip.IpUtils
import com.ruoyi.common.core.web.controller.BaseController
import com.ruoyi.common.core.web.domain.AjaxResult
import com.ruoyi.common.log.annotation.Log
import com.ruoyi.common.log.enums.BusinessType
import com.ruoyi.common.security.annotation.InnerAuth
import com.ruoyi.common.security.service.TokenService
import com.ruoyi.common.security.utils.SecurityUtils
import com.ruoyi.system.api.domain.KSysUserAccount
import com.ruoyi.system.api.domain.SysUser
import com.ruoyi.system.api.model.LoginUser
import com.ruoyi.system.service.IKSysUserService
import com.ruoyi.system.service.ISysConfigService
import com.ruoyi.system.service.ISysPermissionService
import com.ruoyi.system.service.ISysUserService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*
/**
* 用户信息
*
* @author hsdllcw
*/
@RestController
@RequestMapping("/inner/user")
open class InnerSysUserController : BaseController() {
@Autowired
open lateinit var userService: ISysUserService
@Autowired
open lateinit var kSysUserService: IKSysUserService
@Autowired
open lateinit var permissionService: ISysPermissionService
@Autowired
open lateinit var tokenService: TokenService
@Autowired
open lateinit var configService: ISysConfigService
/**
* 获取当前用户信息
*/
@InnerAuth
@GetMapping("/info/phoneNumber/{phoneNumber:\\d+}")
fun infoByPhone(@PathVariable("phoneNumber") phoneNumber: String?): R<LoginUser> {
val sysUser: SysUser = userService.selectUserByPhoneNumber(phoneNumber)
if (StringUtils.isNull(sysUser)) {
return R.fail("用户名或密码错误")
}
// 角色集合
val roles: Set<String> = permissionService.getRolePermission(sysUser)
// 权限集合
val permissions: Set<String> = permissionService.getMenuPermission(sysUser)
val sysUserVo = LoginUser()
sysUserVo.sysUser = sysUser
sysUserVo.roles = roles
sysUserVo.permissions = permissions
return R.ok(sysUserVo)
}
/**
* 获取当前用户信息
*/
@InnerAuth
@GetMapping("/list/phoneNumber/{phoneNumber:\\d+}")
fun findByPhoneNumberStartingWith(@PathVariable("phoneNumber") phoneNumber: String?): R<Page<SysUser>> {
return R.ok(userService.findByPhoneNumberStartingWith(phoneNumber))
}
/**
* 根据ID获取用户信息
*/
@InnerAuth
@GetMapping("/detail/{userId}")
fun infoById(@PathVariable("userId") userId: Long): R<LoginUser> {
val sysUser: SysUser = userService.selectUserById(userId)
// 角色集合
val roles: Set<String> = permissionService.getRolePermission(sysUser)
// 权限集合
val permissions: Set<String> = permissionService.getMenuPermission(sysUser)
val sysUserVo = LoginUser()
sysUserVo.sysUser = sysUser
sysUserVo.roles = roles
sysUserVo.permissions = permissions
return R.ok(sysUserVo)
}
/**
* 根据微信unionid获取用户信息
*/
@InnerAuth
@GetMapping("/detail/wx/unionid/{unionid}")
fun infoByWxUnionId(@PathVariable("unionid") unionid: String): R<LoginUser> {
val sysUser = kSysUserService.selectUserByWxUnionId(unionid)
if (StringUtils.isNull(sysUser)) {
return R.fail("unionid错误")
}
// 角色集合
val roles: Set<String> = permissionService.getRolePermission(sysUser)
// 权限集合
val permissions: Set<String> = permissionService.getMenuPermission(sysUser)
val sysUserVo = LoginUser()
sysUserVo.userid = sysUser?.userId
sysUserVo.ipaddr = IpUtils.getIpAddr()
sysUserVo.sysUser = sysUser
sysUserVo.roles = roles
sysUserVo.permissions = permissions
return R.ok(sysUserVo)
}
/**
* 修改用户
*/
@InnerAuth
@PutMapping
@Log(title = "用户修改本人信息", businessType = BusinessType.UPDATE)
fun edit(@Validated @RequestBody loginUser: LoginUser): AjaxResult {
val targetUser = loginUser.sysUser
if (!userService.checkUserNameUnique(targetUser)) {
return error("修改用户'" + targetUser.userName + "'失败,登录账号已存在")
} else if (StringUtils.isNotEmpty(targetUser.phonenumber) && !userService.checkPhoneUnique(targetUser)) {
return error("修改用户'" + targetUser.userName + "'失败,手机号码已存在")
} else if (StringUtils.isNotEmpty(targetUser.email) && !userService.checkEmailUnique(targetUser)) {
return error("修改用户'" + targetUser.userName + "'失败,邮箱账号已存在")
}
val originUser = userService.selectUserById(targetUser.userId)
originUser.userName = targetUser.userName ?: originUser.userName
originUser.nickName = targetUser.nickName ?: originUser.nickName
originUser.phonenumber = targetUser.phonenumber ?: originUser.phonenumber
originUser.email = targetUser.email ?: originUser.email
originUser.avatar = targetUser.avatar ?: originUser.avatar
originUser.sex = targetUser.sex ?: originUser.sex
originUser.updateBy = originUser.userName
if (loginUser.sysUser.sysUserAccount != null){
originUser.sysUserAccount = loginUser.sysUser.sysUserAccount.apply { this.userId = originUser.userId }
}
userService.updateUser(originUser)
// 更新缓存用户信息
tokenService.setLoginUser(loginUser)
return success(loginUser)
}
/**
* 注册用户信息
*/
@InnerAuth
@PostMapping("/register/dept/{deptId}/wx/unionid")
fun registerUserBySysUserAccount(@RequestBody sysUserAccount: KSysUserAccount, @PathVariable deptId: Long): R<Boolean> {
if ("true" != configService.selectConfigByKey("sys.account.registerUser")) {
return R.fail("当前系统没有开启注册功能!")
}
if (sysUserAccount.wxUnionId == null) return R.fail("微信unionid不存在无法注册")
if (!kSysUserService.checkWxUnionIdUnique(sysUserAccount.wxUnionId!!)) {
return R.fail("保存用户'$sysUserAccount.wxUnionId'失败,注册账号已存在")
}
return R.ok(kSysUserService.registerUserBySysUserAccount(sysUserAccount, deptId))
}
@InnerAuth
@PutMapping("/{userId}/unbind/weixin")
@Log(title = "解绑微信", businessType = BusinessType.UPDATE)
fun unbindWeChat(@PathVariable("userId") userId: Long): AjaxResult {
val loginUser = SecurityUtils.getLoginUser()
kSysUserService.unBindWxByUserId(userId)
// 更新缓存用户信息
tokenService.loginUser = loginUser
return success(loginUser)
}
}

View File

@ -0,0 +1,42 @@
package com.ruoyi.system.mapper
import com.ruoyi.system.api.domain.KSysUserAccount
import com.ruoyi.system.api.domain.SysUser
import org.apache.ibatis.annotations.Param
/**
* 用户表 数据层
*
* @author hsdllcw
*/
interface KSysUserMapper {
/**
* 通过id查询用户
*
* @param userId
* @return 用户对象信息
*/
fun selectUserById(userId: Long): KSysUserAccount?
/**
* 通过用户名查询用户
*
* @param wxUnionId 微信unionid
* @return 用户对象信息
*/
fun selectUserByWxUnionId(wxUnionId: String): SysUser?
/**
* 校验微信unionid是否唯一
*
* @param wxUnionId 微信unionid
* @return 结果
*/
fun checkWxUnionIdUnique(wxUnionId: String): SysUser?
fun insertSysUserAccount(sysUserAccount: KSysUserAccount): Int
fun updateSysUserAccount(sysUserAccount: KSysUserAccount): Int
fun unBindWxByUserId(@Param("userId") userId: Long): Int
}

View File

@ -0,0 +1,48 @@
package com.ruoyi.system.service
import com.ruoyi.system.api.domain.KSysUserAccount
import com.ruoyi.system.api.domain.SysUser
interface IKSysUserService {
fun getISysUserService(): ISysUserService
/**
* 通过id查询用户
*
* @param userId
* @return 用户对象信息
*/
fun selectUserById(userId: Long): KSysUserAccount?
/**
* 通过微信unionid查询用户
*
* @param wxUnionId 微信unionid
* @return 用户对象信息
*/
fun selectUserByWxUnionId(wxUnionId: String): SysUser?
/**
* 校验微信unionid是否唯一
*
* @param wxUnionId 微信unionid
* @return 用户对象信息
*/
fun checkWxUnionIdUnique(wxUnionId: String): Boolean
/**
* 注册用户信息
*
* @param sysUserAccount 包含微信unionId
* @return 结果
*/
fun registerUserBySysUserAccount(sysUserAccount: KSysUserAccount, deptId: Long): Boolean
/**
* 绑定微信
*/
fun updateSysUserAccount(sysUserAccount: KSysUserAccount): Int
/**
* 解绑微信
*/
fun unBindWxByUserId(userId: Long): Int
}

View File

@ -0,0 +1,56 @@
package com.ruoyi.system.service.impl
import com.ruoyi.common.core.constant.UserConstants
import com.ruoyi.common.core.utils.uuid.IdUtils
import com.ruoyi.common.security.utils.SecurityUtils
import com.ruoyi.system.api.domain.KSysUserAccount
import com.ruoyi.system.api.domain.SysUser
import com.ruoyi.system.mapper.KSysUserMapper
import com.ruoyi.system.service.IKSysUserService
import com.ruoyi.system.service.ISysUserService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service
@Service
open class KSysUserServiceImpl : IKSysUserService {
@Lazy
@Autowired
lateinit var sysUserService: ISysUserService
@Autowired
lateinit var kSysUserMapper: KSysUserMapper
override fun getISysUserService() = sysUserService
override fun selectUserById(userId: Long) = kSysUserMapper.selectUserById(userId)
override fun selectUserByWxUnionId(wxUnionId: String) = kSysUserMapper.selectUserByWxUnionId(wxUnionId)
override fun checkWxUnionIdUnique(wxUnionId: String) =
kSysUserMapper.checkWxUnionIdUnique(wxUnionId)?.run { UserConstants.NOT_UNIQUE } ?: UserConstants.UNIQUE
/**
* 注册用户信息
*
* @param sysUserAccount 包含微信unionId
* @param deptId 部门ID
* @return 结果
*/
override fun registerUserBySysUserAccount(sysUserAccount: KSysUserAccount, deptId: Long): Boolean {
val user = SysUser().apply {
userName = IdUtils.randomUUID().replace("-".toRegex(), "").substring(0, 30)
nickName = "嘉迪微信用户"
password = SecurityUtils.encryptPassword(IdUtils.randomUUID())
this.deptId = deptId
}
return sysUserService.registerUser(user).apply {
sysUserAccount.memberId = sysUserService.selectUserByUserName(user.userName).userId
kSysUserMapper.insertSysUserAccount(sysUserAccount)
}
}
override fun updateSysUserAccount(sysUserAccount: KSysUserAccount): Int {
return kSysUserMapper.updateSysUserAccount(sysUserAccount)
}
override fun unBindWxByUserId(userId: Long): Int {
return kSysUserMapper.unBindWxByUserId(userId)
}
}

View File

@ -0,0 +1,33 @@
# Tomcat
server:
port: 9201
# Spring
spring:
application:
# 应用名称
name: ruoyi-system
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 78a7f41e-46cc-437a-9716-735888227693
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
logging:
file:
name: dev-ruoyi-system.log
pattern:
file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"

View File

@ -0,0 +1,33 @@
# Tomcat
server:
port: 9201
#测试环境
spring:
application:
# 应用名称
name: ruoyi-system
cloud:
nacos:
discovery:
ip: 8.155.60.167
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: e2708b29-ca15-4f63-a919-d33932ebdfda
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: e2708b29-ca15-4f63-a919-d33932ebdfda
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
logging:
file:
name: prod-ruoyi-system.log
pattern:
file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"

View File

@ -0,0 +1,32 @@
# Tomcat
server:
port: 9201
#测试环境
spring:
application:
# 应用名称
name: ruoyi-system
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: nacos.zkjiadi.cc
namespace: 45c724b0-9b42-4ff2-bff2-9220a1788392
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
config:
# 配置中心地址
server-addr: nacos.zkjiadi.cc
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: 45c724b0-9b42-4ff2-bff2-9220a1788392
username: nacos
password: u0uM2RIp3Xle9VVFWtpzoz9ZdNbwG6PpWsjrOVphXzlDc0jA
logging:
file:
name: test-ruoyi-system.log
pattern:
file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx"

View File

@ -1,25 +1,4 @@
# Tomcat # Spring默认环境配置
server:
port: 9201
# Spring
spring: spring:
application:
# 应用名称
name: ruoyi-system
profiles: profiles:
# 环境配置
active: dev active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

Some files were not shown because too many files have changed in this diff Show More