@llryiop/avatar-boot-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +309 -0
- package/bin/cli.js +3 -0
- package/docs/plans/2026-03-12-avatar-boot-cli-design.md +73 -0
- package/docs/plans/2026-03-12-avatar-boot-cli-plan.md +681 -0
- package/package.json +28 -0
- package/src/index.js +78 -0
- package/src/prompts.js +78 -0
- package/src/template.js +37 -0
- package/src/transform.js +172 -0
- package/src/utils.js +34 -0
- package/templates/.claude/rules/architecture-redlines.md +146 -0
- package/templates/.claude/rules/code-review-standards.md +137 -0
- package/templates/.claude/rules/coding-standards.md +56 -0
- package/templates/.claude/rules/git-commit.md +59 -0
- package/templates/.claude/rules/layered-architecture.md +201 -0
- package/templates/.claude/rules/mybatis-plus.md +263 -0
- package/templates/.claude/rules/tech-stack.md +41 -0
- package/templates/.claude/rules/version.md +467 -0
- package/templates/.claude/settings.local.json +18 -0
- package/templates/.claude/skills/ai-tool-guide/SKILL.md +314 -0
- package/templates/.claude/skills/api-design/SKILL.md +200 -0
- package/templates/.claude/skills/api-doc-generator/SKILL.md +380 -0
- package/templates/.claude/skills/api-service-module-creator/SKILL.md +1114 -0
- package/templates/.claude/skills/avatar-boot-starter-feign/SKILL.md +243 -0
- package/templates/.claude/skills/avatar-boot-starter-job/SKILL.md +437 -0
- package/templates/.claude/skills/avatar-boot-starter-kafka/SKILL.md +580 -0
- package/templates/.claude/skills/avatar-boot-starter-mysql/SKILL.md +572 -0
- package/templates/.claude/skills/avatar-boot-starter-nacos/SKILL.md +901 -0
- package/templates/.claude/skills/avatar-boot-starter-oss/SKILL.md +594 -0
- package/templates/.claude/skills/avatar-boot-starter-redis/SKILL.md +586 -0
- package/templates/.claude/skills/avatar-boot-starter-rocketmq/SKILL.md +662 -0
- package/templates/.claude/skills/avatar-boot-starter-web/SKILL.md +1007 -0
- package/templates/.claude/skills/changelog-generator/SKILL.md +114 -0
- package/templates/.claude/skills/code-review/SKILL.md +239 -0
- package/templates/.claude/skills/crud-generator/SKILL.md +824 -0
- package/templates/.claude/skills/database-design/SKILL.md +377 -0
- package/templates/.claude/skills/deployment-config/SKILL.md +277 -0
- package/templates/.claude/skills/incident-analysis/SKILL.md +241 -0
- package/templates/.claude/skills/integration-test-generator/SKILL.md +496 -0
- package/templates/.claude/skills/prompt-engineering/SKILL.md +249 -0
- package/templates/.claude/skills/requirement-management/SKILL.md +244 -0
- package/templates/.claude/skills/security-audit/SKILL.md +330 -0
- package/templates/.claude/skills/test-case-design/SKILL.md +257 -0
- package/templates/.claude/skills/testing-workflow/SKILL.md +68 -0
- package/templates/.claude/skills/troubleshooting/SKILL.md +240 -0
- package/templates/CLAUDE.md +173 -0
- package/templates/README.md +303 -0
- package/templates/avatar-scaffold-api/pom.xml +41 -0
- package/templates/avatar-scaffold-api/src/main/java/com/iflytek/avatar/login/api/LoginFeignClient.java +40 -0
- package/templates/avatar-scaffold-api/src/main/java/com/iflytek/avatar/login/constant/LoginConstant.java +21 -0
- package/templates/avatar-scaffold-api/src/main/java/com/iflytek/avatar/login/dto/request/LoginRequest.java +17 -0
- package/templates/avatar-scaffold-api/src/main/java/com/iflytek/avatar/login/dto/request/RefreshTokenRequest.java +14 -0
- package/templates/avatar-scaffold-api/src/main/java/com/iflytek/avatar/login/dto/response/LoginResponse.java +31 -0
- package/templates/avatar-scaffold-api/src/main/java/com/iflytek/avatar/login/dto/response/TokenInfoResponse.java +25 -0
- package/templates/avatar-scaffold-api/src/main/java/com/iflytek/avatar/login/enums/LoginTypeEnum.java +23 -0
- package/templates/avatar-scaffold-api/src/main/java/com/iflytek/avatar/login/exception/LoginException.java +23 -0
- package/templates/avatar-scaffold-service/k8s-app/Dockerfile +14 -0
- package/templates/avatar-scaffold-service/k8s-app/Dockerfile-arm64 +14 -0
- package/templates/avatar-scaffold-service/packaging/assembly.xml +16 -0
- package/templates/avatar-scaffold-service/pom.xml +150 -0
- package/templates/avatar-scaffold-service/src/main/java/com/iflytek/avatar/Application.java +21 -0
- package/templates/avatar-scaffold-service/src/main/java/com/iflytek/avatar/login/config/LoginConfig.java +20 -0
- package/templates/avatar-scaffold-service/src/main/java/com/iflytek/avatar/login/controller/LoginController.java +37 -0
- package/templates/avatar-scaffold-service/src/main/java/com/iflytek/avatar/login/converter/LoginConverter.java +54 -0
- package/templates/avatar-scaffold-service/src/main/java/com/iflytek/avatar/login/feign/DemoFeign.java +21 -0
- package/templates/avatar-scaffold-service/src/main/java/com/iflytek/avatar/login/repository/entity/UserLoginEntity.java +33 -0
- package/templates/avatar-scaffold-service/src/main/java/com/iflytek/avatar/login/repository/entity/UserTokenEntity.java +39 -0
- package/templates/avatar-scaffold-service/src/main/java/com/iflytek/avatar/login/repository/mapper/UserLoginMapper.java +20 -0
- package/templates/avatar-scaffold-service/src/main/java/com/iflytek/avatar/login/service/LoginService.java +22 -0
- package/templates/avatar-scaffold-service/src/main/java/com/iflytek/avatar/login/service/impl/LoginServiceImpl.java +43 -0
- package/templates/avatar-scaffold-service/src/main/java/com/iflytek/avatar/login/utils/LoginUtils.java +31 -0
- package/templates/avatar-scaffold-service/src/main/resources/application-dev.yaml +29 -0
- package/templates/avatar-scaffold-service/src/main/resources/application-local.yaml +61 -0
- package/templates/avatar-scaffold-service/src/main/resources/application-prod.yaml +28 -0
- package/templates/avatar-scaffold-service/src/main/resources/application-test.yaml +28 -0
- package/templates/avatar-scaffold-service/src/main/resources/application.yaml +12 -0
- package/templates/pom.xml +98 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
3
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
4
|
+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
5
|
+
<modelVersion>4.0.0</modelVersion>
|
|
6
|
+
<parent>
|
|
7
|
+
<groupId>com.iflytek.avatar</groupId>
|
|
8
|
+
<artifactId>avatar-template</artifactId>
|
|
9
|
+
<version>1.0.0-SNAPSHOT</version>
|
|
10
|
+
<relativePath>../pom.xml</relativePath>
|
|
11
|
+
</parent>
|
|
12
|
+
|
|
13
|
+
<artifactId>avatar-template-service</artifactId>
|
|
14
|
+
|
|
15
|
+
<properties>
|
|
16
|
+
<maven.compiler.source>21</maven.compiler.source>
|
|
17
|
+
<maven.compiler.target>21</maven.compiler.target>
|
|
18
|
+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
19
|
+
</properties>
|
|
20
|
+
|
|
21
|
+
<dependencies>
|
|
22
|
+
<dependency>
|
|
23
|
+
<groupId>com.iflytek.avatar</groupId>
|
|
24
|
+
<artifactId>avatar-template-api</artifactId>
|
|
25
|
+
<version>1.0.0-SNAPSHOT</version>
|
|
26
|
+
</dependency>
|
|
27
|
+
<dependency>
|
|
28
|
+
<groupId>com.iflytek.avatar.boot</groupId>
|
|
29
|
+
<artifactId>avatar-boot-starter-web</artifactId>
|
|
30
|
+
</dependency>
|
|
31
|
+
<dependency>
|
|
32
|
+
<groupId>com.iflytek.avatar.boot</groupId>
|
|
33
|
+
<artifactId>avatar-boot-starter-nacos</artifactId>
|
|
34
|
+
</dependency>
|
|
35
|
+
<!-- <dependency>-->
|
|
36
|
+
<!-- <groupId>com.iflytek.avatar.boot</groupId>-->
|
|
37
|
+
<!-- <artifactId>avatar-boot-starter-mysql</artifactId>-->
|
|
38
|
+
<!-- </dependency>-->
|
|
39
|
+
<!-- <dependency>-->
|
|
40
|
+
<!-- <groupId>com.iflytek.avatar.boot</groupId>-->
|
|
41
|
+
<!-- <artifactId>avatar-boot-starter-redis</artifactId>-->
|
|
42
|
+
<!-- </dependency>-->
|
|
43
|
+
</dependencies>
|
|
44
|
+
|
|
45
|
+
<build>
|
|
46
|
+
<plugins>
|
|
47
|
+
<plugin>
|
|
48
|
+
<groupId>org.springframework.boot</groupId>
|
|
49
|
+
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
50
|
+
<version>3.5.3</version>
|
|
51
|
+
</plugin>
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
<plugin>
|
|
55
|
+
<groupId>org.codehaus.mojo</groupId>
|
|
56
|
+
<artifactId>appassembler-maven-plugin</artifactId>
|
|
57
|
+
<version>1.10</version>
|
|
58
|
+
<configuration>
|
|
59
|
+
<repositoryLayout>flat</repositoryLayout>
|
|
60
|
+
<!-- 在脚本的classpath开始增加配置文件路径 -->
|
|
61
|
+
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
|
|
62
|
+
<!-- 生成配置文件路径 -->
|
|
63
|
+
<configurationDirectory>conf</configurationDirectory>
|
|
64
|
+
<!-- 配置文件原路径 -->
|
|
65
|
+
<configurationSourceDirectory>src/main/resources</configurationSourceDirectory>
|
|
66
|
+
<!-- 从原配置文件复制 -->
|
|
67
|
+
<copyConfigurationDirectory>true</copyConfigurationDirectory>
|
|
68
|
+
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
|
|
69
|
+
|
|
70
|
+
<!-- 生成哪几种平台的脚本 -->
|
|
71
|
+
<platforms>
|
|
72
|
+
<platform>unix</platform>
|
|
73
|
+
<platform>windows</platform>
|
|
74
|
+
</platforms>
|
|
75
|
+
<!-- 生成脚本的后缀 -->
|
|
76
|
+
<binFileExtensions>
|
|
77
|
+
<unix>.sh</unix>
|
|
78
|
+
<windows>.bat</windows>
|
|
79
|
+
</binFileExtensions>
|
|
80
|
+
<!-- 使用classpath通配符 -->
|
|
81
|
+
<useWildcardClassPath>true</useWildcardClassPath>
|
|
82
|
+
<!-- JVM参数 -->
|
|
83
|
+
<!-- <extraJvmArguments>-Xms512m -Xmx2048m</extraJvmArguments>-->
|
|
84
|
+
<!-- 依赖包目录 -->
|
|
85
|
+
<repositoryName>lib</repositoryName>
|
|
86
|
+
<programs>
|
|
87
|
+
<program>
|
|
88
|
+
<name>startup</name>
|
|
89
|
+
<mainClass>com.iflytek.avatar.Application</mainClass>
|
|
90
|
+
</program>
|
|
91
|
+
</programs>
|
|
92
|
+
</configuration>
|
|
93
|
+
<!-- 绑定生命周期 -->
|
|
94
|
+
<executions>
|
|
95
|
+
<execution>
|
|
96
|
+
<id>appassembler</id>
|
|
97
|
+
<phase>package</phase>
|
|
98
|
+
<goals>
|
|
99
|
+
<goal>assemble</goal>
|
|
100
|
+
</goals>
|
|
101
|
+
</execution>
|
|
102
|
+
</executions>
|
|
103
|
+
</plugin>
|
|
104
|
+
<plugin>
|
|
105
|
+
<artifactId>maven-assembly-plugin</artifactId>
|
|
106
|
+
<configuration>
|
|
107
|
+
<appendAssemblyId>false</appendAssemblyId>
|
|
108
|
+
<descriptors>
|
|
109
|
+
<descriptor>packaging/assembly.xml</descriptor>
|
|
110
|
+
</descriptors>
|
|
111
|
+
</configuration>
|
|
112
|
+
<executions>
|
|
113
|
+
<execution>
|
|
114
|
+
<id>make-assembly</id>
|
|
115
|
+
<phase>package</phase>
|
|
116
|
+
<goals>
|
|
117
|
+
<goal>single</goal>
|
|
118
|
+
</goals>
|
|
119
|
+
</execution>
|
|
120
|
+
</executions>
|
|
121
|
+
</plugin>
|
|
122
|
+
|
|
123
|
+
<plugin>
|
|
124
|
+
<groupId>org.apache.maven.plugins</groupId>
|
|
125
|
+
<artifactId>maven-compiler-plugin</artifactId>
|
|
126
|
+
<version>3.13.0</version>
|
|
127
|
+
<configuration>
|
|
128
|
+
<source>${java.version}</source>
|
|
129
|
+
<target>${java.version}</target>
|
|
130
|
+
<encoding>${project.build.sourceEncoding}</encoding>
|
|
131
|
+
</configuration>
|
|
132
|
+
</plugin>
|
|
133
|
+
|
|
134
|
+
<!-- 设置程序启动的Main Class -->
|
|
135
|
+
<plugin>
|
|
136
|
+
<groupId>org.apache.maven.plugins</groupId>
|
|
137
|
+
<artifactId>maven-jar-plugin</artifactId>
|
|
138
|
+
<version>3.0.2</version>
|
|
139
|
+
<configuration>
|
|
140
|
+
<excludes>
|
|
141
|
+
<!--以类路径目录为基础-->
|
|
142
|
+
<exclude>*.yml</exclude>
|
|
143
|
+
<exclude>*.properties</exclude>
|
|
144
|
+
</excludes>
|
|
145
|
+
</configuration>
|
|
146
|
+
</plugin>
|
|
147
|
+
</plugins>
|
|
148
|
+
</build>
|
|
149
|
+
|
|
150
|
+
</project>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package com.iflytek.avatar;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import org.springframework.boot.SpringApplication;
|
|
5
|
+
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
6
|
+
import org.springframework.cloud.openfeign.EnableFeignClients;
|
|
7
|
+
|
|
8
|
+
@EnableFeignClients
|
|
9
|
+
@SpringBootApplication
|
|
10
|
+
public class Application {
|
|
11
|
+
|
|
12
|
+
public static void main(String[] args) {
|
|
13
|
+
// 禁用 Nacos 客户端的文件日志输出,解决 Logback appender 冲突问题
|
|
14
|
+
// 参考: https://github.com/alibaba/spring-cloud-alibaba/issues/4004
|
|
15
|
+
// 参考: https://github.com/alibaba/spring-cloud-alibaba/issues/3995
|
|
16
|
+
System.setProperty("nacos.logging.default.config.enabled", "false");
|
|
17
|
+
System.setProperty("nacos.logging.config", "");
|
|
18
|
+
|
|
19
|
+
SpringApplication.run(Application.class, args);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package com.iflytek.avatar.login.config;
|
|
2
|
+
|
|
3
|
+
import com.iflytek.avatar.login.constant.LoginConstant;
|
|
4
|
+
import org.springframework.context.annotation.Bean;
|
|
5
|
+
import org.springframework.context.annotation.Configuration;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 登录模块配置
|
|
9
|
+
*/
|
|
10
|
+
@Configuration
|
|
11
|
+
public class LoginConfig {
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Token 过期时间(秒),可从配置文件读取,此处为 Demo 默认值
|
|
15
|
+
*/
|
|
16
|
+
@Bean
|
|
17
|
+
public int loginTokenExpireSeconds() {
|
|
18
|
+
return LoginConstant.DEFAULT_TOKEN_EXPIRE_SECONDS;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
package com.iflytek.avatar.login.controller;
|
|
2
|
+
|
|
3
|
+
import com.iflytek.avatar.boot.entity.response.Result;
|
|
4
|
+
import com.iflytek.avatar.login.api.LoginFeignClient;
|
|
5
|
+
import com.iflytek.avatar.login.dto.request.LoginRequest;
|
|
6
|
+
import com.iflytek.avatar.login.dto.request.RefreshTokenRequest;
|
|
7
|
+
import com.iflytek.avatar.login.dto.response.LoginResponse;
|
|
8
|
+
import com.iflytek.avatar.login.dto.response.TokenInfoResponse;
|
|
9
|
+
import com.iflytek.avatar.login.service.LoginService;
|
|
10
|
+
import jakarta.validation.Valid;
|
|
11
|
+
import lombok.RequiredArgsConstructor;
|
|
12
|
+
import org.springframework.web.bind.annotation.RequestMapping;
|
|
13
|
+
import org.springframework.web.bind.annotation.RestController;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 登录 REST 控制器,实现 {@link LoginFeignClient} 契约。
|
|
17
|
+
* 对外暴露的路径与 Feign 客户端一致(/api/login),供其他服务通过 Feign 调用。
|
|
18
|
+
*/
|
|
19
|
+
@RestController
|
|
20
|
+
@RequestMapping("/api/login")
|
|
21
|
+
@RequiredArgsConstructor
|
|
22
|
+
public class LoginController implements LoginFeignClient {
|
|
23
|
+
|
|
24
|
+
private final LoginService loginService;
|
|
25
|
+
|
|
26
|
+
@Override
|
|
27
|
+
public Result<LoginResponse> login(@Valid LoginRequest request) {
|
|
28
|
+
LoginResponse response = loginService.login(request);
|
|
29
|
+
return Result.success(response);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@Override
|
|
33
|
+
public Result<TokenInfoResponse> refreshToken(@Valid RefreshTokenRequest request) {
|
|
34
|
+
TokenInfoResponse response = loginService.refreshToken(request);
|
|
35
|
+
return Result.success(response);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
package com.iflytek.avatar.login.converter;
|
|
2
|
+
|
|
3
|
+
import com.iflytek.avatar.login.dto.response.LoginResponse;
|
|
4
|
+
import com.iflytek.avatar.login.dto.response.TokenInfoResponse;
|
|
5
|
+
import com.iflytek.avatar.login.repository.entity.UserTokenEntity;
|
|
6
|
+
|
|
7
|
+
import java.time.LocalDateTime;
|
|
8
|
+
import java.time.ZoneId;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 登录模块对象转换器(Entity <-> DTO)
|
|
12
|
+
*/
|
|
13
|
+
public final class LoginConverter {
|
|
14
|
+
|
|
15
|
+
private LoginConverter() {}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* UserTokenEntity -> LoginResponse
|
|
19
|
+
*/
|
|
20
|
+
public static LoginResponse toLoginResponse(UserTokenEntity entity, String username) {
|
|
21
|
+
if (entity == null) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
long expireMs = toEpochMilli(entity.getExpireTime());
|
|
25
|
+
return LoginResponse.builder()
|
|
26
|
+
.token(entity.getToken())
|
|
27
|
+
.refreshToken(entity.getRefreshToken())
|
|
28
|
+
.userId(entity.getUserId())
|
|
29
|
+
.username(username)
|
|
30
|
+
.expireTime(expireMs)
|
|
31
|
+
.build();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* UserTokenEntity -> TokenInfoResponse
|
|
36
|
+
*/
|
|
37
|
+
public static TokenInfoResponse toTokenInfoResponse(UserTokenEntity entity) {
|
|
38
|
+
if (entity == null) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return TokenInfoResponse.builder()
|
|
42
|
+
.token(entity.getToken())
|
|
43
|
+
.refreshToken(entity.getRefreshToken())
|
|
44
|
+
.expireTime(toEpochMilli(entity.getExpireTime()))
|
|
45
|
+
.build();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private static long toEpochMilli(LocalDateTime dateTime) {
|
|
49
|
+
if (dateTime == null) {
|
|
50
|
+
return 0L;
|
|
51
|
+
}
|
|
52
|
+
return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package com.iflytek.avatar.login.feign;
|
|
2
|
+
|
|
3
|
+
import com.iflytek.avatar.boot.config.FeignLoggingConfiguration;
|
|
4
|
+
import org.springframework.cloud.openfeign.FeignClient;
|
|
5
|
+
import org.springframework.web.bind.annotation.GetMapping;
|
|
6
|
+
import org.springframework.web.bind.annotation.PostMapping;
|
|
7
|
+
import org.springframework.web.bind.annotation.RequestBody;
|
|
8
|
+
import org.springframework.web.bind.annotation.RequestParam;
|
|
9
|
+
|
|
10
|
+
import java.util.Map;
|
|
11
|
+
|
|
12
|
+
@FeignClient(name = "demo", url = "http://127.0.0.1:8888", configuration = FeignLoggingConfiguration.class)
|
|
13
|
+
public interface DemoFeign {
|
|
14
|
+
|
|
15
|
+
@GetMapping("/demo")
|
|
16
|
+
String demo(@RequestParam String name);
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@PostMapping("/demo")
|
|
20
|
+
String demo2(@RequestBody Map<String, String> map);
|
|
21
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package com.iflytek.avatar.login.repository.entity;
|
|
2
|
+
|
|
3
|
+
import lombok.AllArgsConstructor;
|
|
4
|
+
import lombok.Builder;
|
|
5
|
+
import lombok.Data;
|
|
6
|
+
import lombok.NoArgsConstructor;
|
|
7
|
+
|
|
8
|
+
import java.time.LocalDateTime;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 用户登录表实体(对应 user_login 表)
|
|
12
|
+
*/
|
|
13
|
+
@Data
|
|
14
|
+
@Builder
|
|
15
|
+
@NoArgsConstructor
|
|
16
|
+
@AllArgsConstructor
|
|
17
|
+
public class UserLoginEntity {
|
|
18
|
+
|
|
19
|
+
/** 主键 */
|
|
20
|
+
private Long id;
|
|
21
|
+
|
|
22
|
+
/** 用户 ID */
|
|
23
|
+
private Long userId;
|
|
24
|
+
|
|
25
|
+
/** 用户名 */
|
|
26
|
+
private String username;
|
|
27
|
+
|
|
28
|
+
/** 登录时间 */
|
|
29
|
+
private LocalDateTime loginTime;
|
|
30
|
+
|
|
31
|
+
/** 登录 IP(可选) */
|
|
32
|
+
private String loginIp;
|
|
33
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package com.iflytek.avatar.login.repository.entity;
|
|
2
|
+
|
|
3
|
+
import lombok.AllArgsConstructor;
|
|
4
|
+
import lombok.Builder;
|
|
5
|
+
import lombok.Data;
|
|
6
|
+
import lombok.NoArgsConstructor;
|
|
7
|
+
|
|
8
|
+
import java.time.LocalDateTime;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 用户 Token 表实体(对应 user_token 表)
|
|
12
|
+
*/
|
|
13
|
+
@Data
|
|
14
|
+
@Builder
|
|
15
|
+
@NoArgsConstructor
|
|
16
|
+
@AllArgsConstructor
|
|
17
|
+
public class UserTokenEntity {
|
|
18
|
+
|
|
19
|
+
/** 主键 */
|
|
20
|
+
private Long id;
|
|
21
|
+
|
|
22
|
+
/** 用户 ID */
|
|
23
|
+
private Long userId;
|
|
24
|
+
|
|
25
|
+
/** 访问令牌 */
|
|
26
|
+
private String token;
|
|
27
|
+
|
|
28
|
+
/** 刷新令牌 */
|
|
29
|
+
private String refreshToken;
|
|
30
|
+
|
|
31
|
+
/** 过期时间 */
|
|
32
|
+
private LocalDateTime expireTime;
|
|
33
|
+
|
|
34
|
+
/** 创建时间 */
|
|
35
|
+
private LocalDateTime createTime;
|
|
36
|
+
|
|
37
|
+
/** 更新时间 */
|
|
38
|
+
private LocalDateTime updateTime;
|
|
39
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package com.iflytek.avatar.login.repository.mapper;
|
|
2
|
+
|
|
3
|
+
import com.iflytek.avatar.login.repository.entity.UserLoginEntity;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 用户登录 Mapper(MyBatis)
|
|
7
|
+
* 启用 avatar-boot-starter-mysql 后添加 @Mapper 并编写 XML/注解 SQL;当前为 Demo 接口定义。
|
|
8
|
+
*/
|
|
9
|
+
public interface UserLoginMapper {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 插入登录记录
|
|
13
|
+
*/
|
|
14
|
+
int insert(UserLoginEntity entity);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 按用户 ID 查询最近一次登录记录
|
|
18
|
+
*/
|
|
19
|
+
UserLoginEntity selectLatestByUserId(Long userId);
|
|
20
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package com.iflytek.avatar.login.service;
|
|
2
|
+
|
|
3
|
+
import com.iflytek.avatar.login.dto.request.LoginRequest;
|
|
4
|
+
import com.iflytek.avatar.login.dto.request.RefreshTokenRequest;
|
|
5
|
+
import com.iflytek.avatar.login.dto.response.LoginResponse;
|
|
6
|
+
import com.iflytek.avatar.login.dto.response.TokenInfoResponse;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 登录业务接口
|
|
10
|
+
*/
|
|
11
|
+
public interface LoginService {
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 用户登录
|
|
15
|
+
*/
|
|
16
|
+
LoginResponse login(LoginRequest request);
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 刷新 Token
|
|
20
|
+
*/
|
|
21
|
+
TokenInfoResponse refreshToken(RefreshTokenRequest request);
|
|
22
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
package com.iflytek.avatar.login.service.impl;
|
|
2
|
+
|
|
3
|
+
import com.iflytek.avatar.login.dto.request.LoginRequest;
|
|
4
|
+
import com.iflytek.avatar.login.dto.request.RefreshTokenRequest;
|
|
5
|
+
import com.iflytek.avatar.login.dto.response.LoginResponse;
|
|
6
|
+
import com.iflytek.avatar.login.dto.response.TokenInfoResponse;
|
|
7
|
+
import com.iflytek.avatar.login.service.LoginService;
|
|
8
|
+
import org.springframework.stereotype.Service;
|
|
9
|
+
|
|
10
|
+
import java.util.concurrent.atomic.AtomicLong;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 登录业务实现(Demo:返回模拟数据)
|
|
14
|
+
*/
|
|
15
|
+
@Service
|
|
16
|
+
public class LoginServiceImpl implements LoginService {
|
|
17
|
+
|
|
18
|
+
private static final long TOKEN_EXPIRE_MS = 7200_000L;
|
|
19
|
+
private static final AtomicLong USER_ID_SEQ = new AtomicLong(1);
|
|
20
|
+
|
|
21
|
+
@Override
|
|
22
|
+
public LoginResponse login(LoginRequest request) {
|
|
23
|
+
long userId = USER_ID_SEQ.getAndIncrement();
|
|
24
|
+
long expireTime = System.currentTimeMillis() + TOKEN_EXPIRE_MS;
|
|
25
|
+
return LoginResponse.builder()
|
|
26
|
+
.token("demo-token-" + userId)
|
|
27
|
+
.refreshToken("demo-refresh-" + userId)
|
|
28
|
+
.userId(userId)
|
|
29
|
+
.username(request.getUsername())
|
|
30
|
+
.expireTime(expireTime)
|
|
31
|
+
.build();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Override
|
|
35
|
+
public TokenInfoResponse refreshToken(RefreshTokenRequest request) {
|
|
36
|
+
long expireTime = System.currentTimeMillis() + TOKEN_EXPIRE_MS;
|
|
37
|
+
return TokenInfoResponse.builder()
|
|
38
|
+
.token("demo-token-refreshed")
|
|
39
|
+
.refreshToken(request.getRefreshToken())
|
|
40
|
+
.expireTime(expireTime)
|
|
41
|
+
.build();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
package com.iflytek.avatar.login.utils;
|
|
2
|
+
|
|
3
|
+
import java.security.SecureRandom;
|
|
4
|
+
import java.util.Base64;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 登录模块工具类
|
|
8
|
+
*/
|
|
9
|
+
public final class LoginUtils {
|
|
10
|
+
|
|
11
|
+
private static final SecureRandom RANDOM = new SecureRandom();
|
|
12
|
+
private static final int TOKEN_BYTES = 24;
|
|
13
|
+
|
|
14
|
+
private LoginUtils() {}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 生成随机 Token 字符串(Demo 用,生产环境建议使用 JWT 等)
|
|
18
|
+
*/
|
|
19
|
+
public static String generateToken() {
|
|
20
|
+
byte[] bytes = new byte[TOKEN_BYTES];
|
|
21
|
+
RANDOM.nextBytes(bytes);
|
|
22
|
+
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 生成带前缀的 token,便于区分类型
|
|
27
|
+
*/
|
|
28
|
+
public static String generateTokenWithPrefix(String prefix) {
|
|
29
|
+
return prefix + generateToken();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
spring:
|
|
2
|
+
config:
|
|
3
|
+
import:
|
|
4
|
+
# 使用 optional: 前缀,Nacos 不可用时不会阻止启动
|
|
5
|
+
- optional:nacos:${spring.application.name}.yaml?group=${NACOS_GROUP:AVATAR_PLATFORM}&refreshEnabled=true
|
|
6
|
+
- optional:nacos:common-database.yaml?group=SHARED_GROUP&refreshEnabled=true
|
|
7
|
+
- optional:nacos:common-redis.yaml?group=SHARED_GROUP&refreshEnabled=true
|
|
8
|
+
|
|
9
|
+
# nacos 配置
|
|
10
|
+
cloud:
|
|
11
|
+
nacos:
|
|
12
|
+
server-addr: ${NACOS_SERVER_ADDR:172.29.242.247:8848}
|
|
13
|
+
namespace: ${NACOS_NAMESPACE:dev}
|
|
14
|
+
username: ${NACOS_USERNAME:nacos}
|
|
15
|
+
password: ${NACOS_PASSWORD:Xnrpt@2026}
|
|
16
|
+
|
|
17
|
+
config:
|
|
18
|
+
enabled: true
|
|
19
|
+
file-extension: yaml
|
|
20
|
+
group: ${NACOS_GROUP:AVATAR_PLATFORM}
|
|
21
|
+
|
|
22
|
+
discovery:
|
|
23
|
+
enabled: true
|
|
24
|
+
register-enabled: true
|
|
25
|
+
ephemeral: true
|
|
26
|
+
group: ${NACOS_GROUP:AVATAR_PLATFORM}
|
|
27
|
+
metadata:
|
|
28
|
+
version: 1.0.0
|
|
29
|
+
environment: dev
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# 本地开发配置(Nacos 不可用时使用)
|
|
2
|
+
# 使用方式: --spring.profiles.active=local
|
|
3
|
+
|
|
4
|
+
spring:
|
|
5
|
+
# 禁用 Nacos 配置导入
|
|
6
|
+
cloud:
|
|
7
|
+
nacos:
|
|
8
|
+
# 完全禁用 Nacos
|
|
9
|
+
config:
|
|
10
|
+
enabled: false
|
|
11
|
+
discovery:
|
|
12
|
+
enabled: false
|
|
13
|
+
|
|
14
|
+
# ============================================
|
|
15
|
+
# 本地数据库配置
|
|
16
|
+
# ============================================
|
|
17
|
+
datasource:
|
|
18
|
+
driver-class-name: com.mysql.cj.jdbc.Driver
|
|
19
|
+
url: jdbc:mysql://localhost:3306/avatar_scaffold?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
|
20
|
+
username: ${DB_USERNAME:root}
|
|
21
|
+
password: ${DB_PASSWORD:root}
|
|
22
|
+
type: com.zaxxer.hikari.HikariDataSource
|
|
23
|
+
hikari:
|
|
24
|
+
minimum-idle: 5
|
|
25
|
+
maximum-pool-size: 20
|
|
26
|
+
connection-timeout: 30000
|
|
27
|
+
idle-timeout: 600000
|
|
28
|
+
max-lifetime: 1800000
|
|
29
|
+
|
|
30
|
+
# ============================================
|
|
31
|
+
# 本地 Redis 配置
|
|
32
|
+
# ============================================
|
|
33
|
+
data:
|
|
34
|
+
redis:
|
|
35
|
+
host: ${REDIS_HOST:localhost}
|
|
36
|
+
port: ${REDIS_PORT:6379}
|
|
37
|
+
password: ${REDIS_PASSWORD:}
|
|
38
|
+
database: 0
|
|
39
|
+
timeout: 3000ms
|
|
40
|
+
lettuce:
|
|
41
|
+
pool:
|
|
42
|
+
max-active: 8
|
|
43
|
+
max-idle: 8
|
|
44
|
+
min-idle: 0
|
|
45
|
+
max-wait: -1ms
|
|
46
|
+
|
|
47
|
+
# MyBatis Plus 配置
|
|
48
|
+
mybatis-plus:
|
|
49
|
+
mapper-locations: classpath*:/mapper/**/*.xml
|
|
50
|
+
type-aliases-package: com.iflytek.avatar.scaffold.**.dao.beans
|
|
51
|
+
configuration:
|
|
52
|
+
map-underscore-to-camel-case: true
|
|
53
|
+
cache-enabled: false
|
|
54
|
+
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
|
|
55
|
+
|
|
56
|
+
# 日志配置
|
|
57
|
+
logging:
|
|
58
|
+
level:
|
|
59
|
+
com.iflytek.avatar: DEBUG
|
|
60
|
+
com.alibaba.nacos: ERROR
|
|
61
|
+
com.alibaba.cloud.nacos: ERROR
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
spring:
|
|
2
|
+
config:
|
|
3
|
+
import:
|
|
4
|
+
- optional:nacos:${spring.application.name}.yaml?group=${NACOS_GROUP:AVATAR_PLATFORM}&refreshEnabled=true
|
|
5
|
+
- optional:nacos:common-database.yaml?group=SHARED_GROUP&refreshEnabled=true
|
|
6
|
+
- optional:nacos:common-redis.yaml?group=SHARED_GROUP&refreshEnabled=true
|
|
7
|
+
|
|
8
|
+
# nacos 配置
|
|
9
|
+
cloud:
|
|
10
|
+
nacos:
|
|
11
|
+
server-addr: ${NACOS_SERVER_ADDR:172.29.242.247:8848}
|
|
12
|
+
namespace: ${NACOS_NAMESPACE:prod}
|
|
13
|
+
username: ${NACOS_USERNAME:nacos}
|
|
14
|
+
password: ${NACOS_PASSWORD:nacos}
|
|
15
|
+
|
|
16
|
+
config:
|
|
17
|
+
enabled: true
|
|
18
|
+
file-extension: yaml
|
|
19
|
+
group: ${NACOS_GROUP:AVATAR_PLATFORM}
|
|
20
|
+
|
|
21
|
+
discovery:
|
|
22
|
+
enabled: true
|
|
23
|
+
register-enabled: true
|
|
24
|
+
ephemeral: true
|
|
25
|
+
group: ${NACOS_GROUP:AVATAR_PLATFORM}
|
|
26
|
+
metadata:
|
|
27
|
+
version: 1.0.0
|
|
28
|
+
environment: prod
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
spring:
|
|
2
|
+
config:
|
|
3
|
+
import:
|
|
4
|
+
- optional:nacos:${spring.application.name}.yaml?group=${NACOS_GROUP:AVATAR_PLATFORM}&refreshEnabled=true
|
|
5
|
+
- optional:nacos:common-database.yaml?group=SHARED_GROUP&refreshEnabled=true
|
|
6
|
+
- optional:nacos:common-redis.yaml?group=SHARED_GROUP&refreshEnabled=true
|
|
7
|
+
|
|
8
|
+
# nacos 配置
|
|
9
|
+
cloud:
|
|
10
|
+
nacos:
|
|
11
|
+
server-addr: ${NACOS_SERVER_ADDR:172.29.242.247:8848}
|
|
12
|
+
namespace: ${NACOS_NAMESPACE:test}
|
|
13
|
+
username: ${NACOS_USERNAME:nacos}
|
|
14
|
+
password: ${NACOS_PASSWORD:nacos}
|
|
15
|
+
|
|
16
|
+
config:
|
|
17
|
+
enabled: true
|
|
18
|
+
file-extension: yaml
|
|
19
|
+
group: ${NACOS_GROUP:AVATAR_PLATFORM}
|
|
20
|
+
|
|
21
|
+
discovery:
|
|
22
|
+
enabled: true
|
|
23
|
+
register-enabled: true
|
|
24
|
+
ephemeral: true
|
|
25
|
+
group: ${NACOS_GROUP:AVATAR_PLATFORM}
|
|
26
|
+
metadata:
|
|
27
|
+
version: 1.0.0
|
|
28
|
+
environment: test
|