可以运行
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/target/
|
||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -8,5 +8,5 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="ms-17" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
26
pom.xml
26
pom.xml
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.0.4</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<mybatis-flex.version>1.9.3</mybatis-flex.version>
|
||||
<mybatis-flex.version>1.11.0</mybatis-flex.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -39,18 +39,22 @@
|
||||
<!-- MyBatis-Flex Spring Boot Starter -->
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
|
||||
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
|
||||
<version>${mybatis-flex.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- MyBatis-Flex Processor for APT -->
|
||||
|
||||
<!-- MyBatis‑Flex Core library (contains BaseMapper etc.) -->
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-processor</artifactId>
|
||||
<version>${mybatis-flex.version}</version>
|
||||
<version>1.11.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
</dependency>
|
||||
<!-- Spring Boot Test Starter -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -94,6 +98,16 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mail</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
<!-- OpenAPI 3 + Swagger-UI -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>2.5.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||
|
||||
@SpringBootApplication(exclude = {HibernateJpaAutoConfiguration.class})
|
||||
|
||||
@MapperScan("com.yundage.chat.mapper")
|
||||
public class ChatApplication {
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ mybatis-flex:
|
||||
configuration:
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
# Mapper XML location (optional)
|
||||
mapper-locations: classpath*:mapper/*.xml
|
||||
|
||||
mapper-locations: classpath*:mapper/*.xml
|
||||
# JWT configuration
|
||||
jwt:
|
||||
secret: mySecretKeyForJWTTokenGenerationAndValidation
|
||||
@@ -43,4 +43,6 @@ server:
|
||||
logging:
|
||||
level:
|
||||
com.yundage.chat: debug
|
||||
com.mybatisflex: debug
|
||||
com.mybatisflex: debug
|
||||
# org.springframework: DEBUG
|
||||
#debug: true
|
||||
21
src/main/resources/mapper/PasswordResetTokenMapper.xml
Normal file
21
src/main/resources/mapper/PasswordResetTokenMapper.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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.yundage.chat.mapper.PasswordResetTokenMapper">
|
||||
|
||||
<!-- 示例:根据 token 查询 -->
|
||||
<select id="selectByToken" resultType="com.yundage.chat.entity.PasswordResetToken">
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
token,
|
||||
expire_time,
|
||||
create_time
|
||||
FROM password_reset_token
|
||||
WHERE token = #{token}
|
||||
</select>
|
||||
|
||||
<!-- 你可以继续补充 insert / update / delete / resultMap 等 -->
|
||||
|
||||
</mapper>
|
||||
7
src/main/resources/mapper/UserMapper.xml
Normal file
7
src/main/resources/mapper/UserMapper.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?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.yundage.chat.mapper.UserMapper">
|
||||
|
||||
</mapper>
|
||||
@@ -1,46 +0,0 @@
|
||||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://101.200.154.78:3306/yunda_qa?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: mysql_Jt3yzh
|
||||
|
||||
# Mail configuration
|
||||
mail:
|
||||
host: smtp.gmail.com
|
||||
port: 587
|
||||
username: your-email@gmail.com
|
||||
password: your-app-password
|
||||
properties:
|
||||
mail:
|
||||
smtp:
|
||||
auth: true
|
||||
starttls:
|
||||
enable: true
|
||||
|
||||
# MyBatis-Flex configuration
|
||||
mybatis-flex:
|
||||
# Enable SQL logging
|
||||
configuration:
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
# Mapper XML location (optional)
|
||||
mapper-locations: classpath*:mapper/*.xml
|
||||
|
||||
# JWT configuration
|
||||
jwt:
|
||||
secret: mySecretKeyForJWTTokenGenerationAndValidation
|
||||
expiration: 86400000 # 24 hours in milliseconds
|
||||
|
||||
# App configuration
|
||||
app:
|
||||
reset-password-url: http://localhost:3000/reset-password
|
||||
|
||||
# Server configuration
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
# Logging configuration
|
||||
logging:
|
||||
level:
|
||||
com.yundage.chat: debug
|
||||
com.mybatisflex: debug
|
||||
@@ -1,113 +0,0 @@
|
||||
-- Create database
|
||||
CREATE DATABASE IF NOT EXISTS chat CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
USE chat;
|
||||
|
||||
-- 1. 用户主表
|
||||
CREATE TABLE users (
|
||||
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
|
||||
username VARCHAR(50) DEFAULT NULL COMMENT '昵称/展示名',
|
||||
password_hash VARCHAR(255) DEFAULT NULL COMMENT '哈希密码(可为空)',
|
||||
phone VARCHAR(20) UNIQUE DEFAULT NULL COMMENT '手机号',
|
||||
email VARCHAR(100)UNIQUE DEFAULT NULL COMMENT '邮箱',
|
||||
avatar_url VARCHAR(255) DEFAULT NULL,
|
||||
user_type ENUM('personal','enterprise','admin')
|
||||
NOT NULL DEFAULT 'personal' COMMENT '用户类型',
|
||||
membership_level_id SMALLINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '付费等级',
|
||||
status TINYINT NOT NULL DEFAULT 1 COMMENT '1=正常, 0=封禁',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
last_login_at DATETIME NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户主表';
|
||||
|
||||
-- 2. 第三方账号绑定表
|
||||
CREATE TABLE user_auth_accounts (
|
||||
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
provider ENUM('wechat_mini','wechat_open','google','github','apple','custom')
|
||||
NOT NULL COMMENT '登录方式',
|
||||
provider_user_id VARCHAR(100) NOT NULL COMMENT '第三方平台唯一ID',
|
||||
access_token VARCHAR(255) DEFAULT NULL,
|
||||
refresh_token VARCHAR(255) DEFAULT NULL,
|
||||
expires_at DATETIME DEFAULT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uq_provider_user (provider, provider_user_id),
|
||||
CONSTRAINT fk_auth_user FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='第三方登录账号绑定表';
|
||||
|
||||
-- 3. 会员等级表
|
||||
CREATE TABLE membership_levels (
|
||||
id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
price_month DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '月费',
|
||||
daily_msg_limit INT UNSIGNED NOT NULL DEFAULT 20,
|
||||
features JSON DEFAULT NULL COMMENT '权限 JSON',
|
||||
sort_order TINYINT NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员等级定义';
|
||||
|
||||
-- 4. 会话表(支持普通与研究模式)
|
||||
CREATE TABLE conversations (
|
||||
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
title VARCHAR(100) DEFAULT NULL,
|
||||
model_version VARCHAR(50) DEFAULT NULL COMMENT '使用模型版本',
|
||||
chat_mode ENUM('chat','research')
|
||||
NOT NULL DEFAULT 'chat' COMMENT 'chat=普通,research=深度研究',
|
||||
is_active TINYINT NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT fk_conv_user FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会话表';
|
||||
|
||||
-- 5. 深度研究扩展表
|
||||
CREATE TABLE conversation_research_meta (
|
||||
conversation_id BIGINT UNSIGNED PRIMARY KEY,
|
||||
topic VARCHAR(200) NOT NULL COMMENT '研究主题',
|
||||
goal TEXT DEFAULT NULL COMMENT '研究目标描述',
|
||||
progress_json JSON DEFAULT NULL COMMENT '阶段进度',
|
||||
draft_report_id BIGINT UNSIGNED DEFAULT NULL COMMENT '草稿报告 ID(预留)',
|
||||
cite_style ENUM('APA','IEEE','GB/T-7714') DEFAULT 'APA',
|
||||
tokens_consumed INT UNSIGNED NOT NULL DEFAULT 0,
|
||||
last_summary_at DATETIME DEFAULT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
CONSTRAINT fk_research_conv FOREIGN KEY (conversation_id)
|
||||
REFERENCES conversations(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='深度研究元数据';
|
||||
|
||||
-- 6. 消息表
|
||||
CREATE TABLE messages (
|
||||
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
|
||||
conversation_id BIGINT UNSIGNED NOT NULL,
|
||||
sequence_no INT UNSIGNED NOT NULL COMMENT '会话内顺序编号',
|
||||
role ENUM('user','assistant','system','tool')
|
||||
NOT NULL,
|
||||
content LONGTEXT NOT NULL,
|
||||
tokens INT UNSIGNED DEFAULT NULL,
|
||||
latency_ms INT UNSIGNED DEFAULT NULL COMMENT '响应耗时',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT fk_msg_conv FOREIGN KEY (conversation_id) REFERENCES conversations(id)
|
||||
ON DELETE CASCADE,
|
||||
UNIQUE KEY uq_conv_seq (conversation_id, sequence_no)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='消息表';
|
||||
|
||||
-- 7. 密码重置令牌表(用于密码重置功能)
|
||||
CREATE TABLE password_reset_tokens (
|
||||
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
token VARCHAR(255) NOT NULL UNIQUE,
|
||||
expires_at DATETIME NOT NULL,
|
||||
used TINYINT NOT NULL DEFAULT 0,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT fk_reset_user FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='密码重置令牌表';
|
||||
|
||||
-- 插入默认会员等级数据
|
||||
INSERT INTO membership_levels (id, name, price_month, daily_msg_limit, features, sort_order) VALUES
|
||||
(1, '免费版', 0.00, 20, '{"models": ["gpt-3.5"], "features": ["basic_chat"]}', 1),
|
||||
(2, '专业版', 29.99, 100, '{"models": ["gpt-3.5", "gpt-4"], "features": ["basic_chat", "research_mode"]}', 2),
|
||||
(3, '企业版', 99.99, 1000, '{"models": ["gpt-3.5", "gpt-4", "gpt-4-turbo"], "features": ["basic_chat", "research_mode", "priority_support"]}', 3);
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.yundage.chat.entity.table;
|
||||
|
||||
import com.mybatisflex.core.query.QueryColumn;
|
||||
import com.mybatisflex.core.table.TableDef;
|
||||
|
||||
// Auto generate by mybatis-flex, do not modify it.
|
||||
public class PasswordResetTokenTableDef extends TableDef {
|
||||
|
||||
public static final PasswordResetTokenTableDef PASSWORD_RESET_TOKEN = new PasswordResetTokenTableDef();
|
||||
|
||||
public final QueryColumn ID = new QueryColumn(this, "id");
|
||||
|
||||
public final QueryColumn USED = new QueryColumn(this, "used");
|
||||
|
||||
public final QueryColumn TOKEN = new QueryColumn(this, "token");
|
||||
|
||||
public final QueryColumn USER_ID = new QueryColumn(this, "user_id");
|
||||
|
||||
public final QueryColumn CREATED_AT = new QueryColumn(this, "created_at");
|
||||
|
||||
public final QueryColumn EXPIRES_AT = new QueryColumn(this, "expires_at");
|
||||
|
||||
/**
|
||||
* 所有字段。
|
||||
*/
|
||||
public final QueryColumn ALL_COLUMNS = new QueryColumn(this, "*");
|
||||
|
||||
/**
|
||||
* 默认字段,不包含逻辑删除或者 large 等字段。
|
||||
*/
|
||||
public final QueryColumn[] DEFAULT_COLUMNS = new QueryColumn[]{ID, USED, TOKEN, USER_ID, CREATED_AT, EXPIRES_AT};
|
||||
|
||||
public PasswordResetTokenTableDef() {
|
||||
super("", "password_reset_tokens");
|
||||
}
|
||||
|
||||
private PasswordResetTokenTableDef(String schema, String name, String alisa) {
|
||||
super(schema, name, alisa);
|
||||
}
|
||||
|
||||
public PasswordResetTokenTableDef as(String alias) {
|
||||
String key = getNameWithSchema() + "." + alias;
|
||||
return getCache(key, k -> new PasswordResetTokenTableDef("", "password_reset_tokens", alias));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package com.yundage.chat.entity.table;
|
||||
|
||||
import com.mybatisflex.core.query.QueryColumn;
|
||||
import com.mybatisflex.core.table.TableDef;
|
||||
|
||||
// Auto generate by mybatis-flex, do not modify it.
|
||||
public class UserTableDef extends TableDef {
|
||||
|
||||
public static final UserTableDef USER = new UserTableDef();
|
||||
|
||||
public final QueryColumn ID = new QueryColumn(this, "id");
|
||||
|
||||
public final QueryColumn EMAIL = new QueryColumn(this, "email");
|
||||
|
||||
public final QueryColumn PHONE = new QueryColumn(this, "phone");
|
||||
|
||||
public final QueryColumn STATUS = new QueryColumn(this, "status");
|
||||
|
||||
public final QueryColumn USER_TYPE = new QueryColumn(this, "user_type");
|
||||
|
||||
public final QueryColumn USERNAME = new QueryColumn(this, "username");
|
||||
|
||||
public final QueryColumn AVATAR_URL = new QueryColumn(this, "avatar_url");
|
||||
|
||||
public final QueryColumn CREATED_AT = new QueryColumn(this, "created_at");
|
||||
|
||||
public final QueryColumn UPDATED_AT = new QueryColumn(this, "updated_at");
|
||||
|
||||
public final QueryColumn LAST_LOGIN_AT = new QueryColumn(this, "last_login_at");
|
||||
|
||||
public final QueryColumn PASSWORD_HASH = new QueryColumn(this, "password_hash");
|
||||
|
||||
public final QueryColumn MEMBERSHIP_LEVEL_ID = new QueryColumn(this, "membership_level_id");
|
||||
|
||||
/**
|
||||
* 所有字段。
|
||||
*/
|
||||
public final QueryColumn ALL_COLUMNS = new QueryColumn(this, "*");
|
||||
|
||||
/**
|
||||
* 默认字段,不包含逻辑删除或者 large 等字段。
|
||||
*/
|
||||
public final QueryColumn[] DEFAULT_COLUMNS = new QueryColumn[]{ID, EMAIL, PHONE, STATUS, USER_TYPE, USERNAME, AVATAR_URL, CREATED_AT, UPDATED_AT, LAST_LOGIN_AT, PASSWORD_HASH, MEMBERSHIP_LEVEL_ID};
|
||||
|
||||
public UserTableDef() {
|
||||
super("", "users");
|
||||
}
|
||||
|
||||
private UserTableDef(String schema, String name, String alisa) {
|
||||
super(schema, name, alisa);
|
||||
}
|
||||
|
||||
public UserTableDef as(String alias) {
|
||||
String key = getNameWithSchema() + "." + alias;
|
||||
return getCache(key, k -> new UserTableDef("", "users", alias));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user