diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/.idea/misc.xml b/.idea/misc.xml
index a8fc129..7496a8d 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,5 +8,5 @@
-
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index e21284b..a5d3e78 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
org.springframework.boot
spring-boot-starter-parent
- 3.2.0
+ 3.0.4
@@ -19,7 +19,7 @@
17
- 1.9.3
+ 1.11.0
@@ -39,18 +39,22 @@
com.mybatis-flex
- mybatis-flex-spring-boot-starter
+ mybatis-flex-spring-boot3-starter
${mybatis-flex.version}
-
+
+
com.mybatis-flex
mybatis-flex-processor
- ${mybatis-flex.version}
+ 1.11.0
provided
-
+
+ com.zaxxer
+ HikariCP
+
org.springframework.boot
@@ -94,6 +98,16 @@
org.springframework.boot
spring-boot-starter-mail
+
+ org.springframework
+ spring-tx
+
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.5.0
+
diff --git a/src/main/java/com/yundage/chat/ChatApplication.java b/src/main/java/com/yundage/chat/ChatApplication.java
index b0f5376..984166b 100644
--- a/src/main/java/com/yundage/chat/ChatApplication.java
+++ b/src/main/java/com/yundage/chat/ChatApplication.java
@@ -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 {
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 201a5d1..191656a 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -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
\ No newline at end of file
+ com.mybatisflex: debug
+# org.springframework: DEBUG
+#debug: true
\ No newline at end of file
diff --git a/src/main/resources/mapper/PasswordResetTokenMapper.xml b/src/main/resources/mapper/PasswordResetTokenMapper.xml
new file mode 100644
index 0000000..5f3790b
--- /dev/null
+++ b/src/main/resources/mapper/PasswordResetTokenMapper.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/mapper/UserMapper.xml b/src/main/resources/mapper/UserMapper.xml
new file mode 100644
index 0000000..6b41dd3
--- /dev/null
+++ b/src/main/resources/mapper/UserMapper.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/target/classes/application.yml b/target/classes/application.yml
deleted file mode 100644
index 201a5d1..0000000
--- a/target/classes/application.yml
+++ /dev/null
@@ -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
\ No newline at end of file
diff --git a/target/classes/schema.sql b/target/classes/schema.sql
deleted file mode 100644
index f2bd854..0000000
--- a/target/classes/schema.sql
+++ /dev/null
@@ -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);
\ No newline at end of file
diff --git a/target/generated-sources/annotations/com/yundage/chat/entity/table/PasswordResetTokenTableDef.java b/target/generated-sources/annotations/com/yundage/chat/entity/table/PasswordResetTokenTableDef.java
deleted file mode 100644
index 9d6754e..0000000
--- a/target/generated-sources/annotations/com/yundage/chat/entity/table/PasswordResetTokenTableDef.java
+++ /dev/null
@@ -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));
- }
-
-}
diff --git a/target/generated-sources/annotations/com/yundage/chat/entity/table/UserTableDef.java b/target/generated-sources/annotations/com/yundage/chat/entity/table/UserTableDef.java
deleted file mode 100644
index a2b1855..0000000
--- a/target/generated-sources/annotations/com/yundage/chat/entity/table/UserTableDef.java
+++ /dev/null
@@ -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));
- }
-
-}