commit 7554523f8d8530dc58e6c0058c1ca6d1f9e96b13 Author: Cxx0822 <1556464090@qq.com> Date: Wed Jun 17 19:56:40 2026 +0800 feat:初始化工程 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b7edd51 --- /dev/null +++ b/.gitignore @@ -0,0 +1,203 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017/2019/2022 cache/options directory +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config + +# NuGet Symbol Packages +*.snupkg + +# .NET Core SDK +project.fragment.lock.json +artifacts/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp \ No newline at end of file diff --git a/SweetChatService.sln b/SweetChatService.sln new file mode 100644 index 0000000..e73a0c1 --- /dev/null +++ b/SweetChatService.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36109.1 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SweetChatService", "SweetChatService\SweetChatService.csproj", "{9353E5F0-839A-427B-A27E-01207A59A87A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9353E5F0-839A-427B-A27E-01207A59A87A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9353E5F0-839A-427B-A27E-01207A59A87A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9353E5F0-839A-427B-A27E-01207A59A87A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9353E5F0-839A-427B-A27E-01207A59A87A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FDAF22F8-D354-4266-8823-C5457E887D4C} + EndGlobalSection +EndGlobal diff --git a/SweetChatService/Config/FreeSqlSetup.cs b/SweetChatService/Config/FreeSqlSetup.cs new file mode 100644 index 0000000..c8399b6 --- /dev/null +++ b/SweetChatService/Config/FreeSqlSetup.cs @@ -0,0 +1,19 @@ +using FreeSql; + +namespace SweetChatService.Config +{ + public class FreeSqlSetup + { + public static IFreeSql CreateFreeSql(string connectionString) + { + return new FreeSqlBuilder() + .UseConnectionString(DataType.MySql, connectionString) + .UseAutoSyncStructure(false) + .UseMonitorCommand(cmd => + { + Console.WriteLine(cmd.CommandText); + }) + .Build(); + } + } +} diff --git a/SweetChatService/Config/Startup.cs b/SweetChatService/Config/Startup.cs new file mode 100644 index 0000000..d6c92ec --- /dev/null +++ b/SweetChatService/Config/Startup.cs @@ -0,0 +1,21 @@ +namespace SweetChatService.Config +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + services.AddEndpointsApiExplorer(); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + app.UseRouting(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} diff --git a/SweetChatService/Controllers/AuthController.cs b/SweetChatService/Controllers/AuthController.cs new file mode 100644 index 0000000..baa24bf --- /dev/null +++ b/SweetChatService/Controllers/AuthController.cs @@ -0,0 +1,39 @@ +using Microsoft.AspNetCore.Mvc; +using SweetChatService.Dto; +using SweetChatService.Services; + +namespace SweetChatService.Controllers +{ + [ApiController] + [Route("api/[controller]")] + public class AuthController : ControllerBase + { + private readonly UserService _userService; + + public AuthController(UserService userService) + { + _userService = userService; + } + + [HttpPost("login")] + public IActionResult Login([FromBody] LoginDto dto) + { + var user = _userService.QueryUserByName(dto.UserName); + + if (user == null) + { + return Unauthorized(new + { + message = "用户名不存在" + }); + } + else + { + return Ok(new + { + userId = user.Id + }); + } + } + } +} diff --git a/SweetChatService/Dto/LoginDto.cs b/SweetChatService/Dto/LoginDto.cs new file mode 100644 index 0000000..93c45aa --- /dev/null +++ b/SweetChatService/Dto/LoginDto.cs @@ -0,0 +1,4 @@ +namespace SweetChatService.Dto +{ + public record LoginDto(string UserName, string Password); +} diff --git a/SweetChatService/Entity/User.cs b/SweetChatService/Entity/User.cs new file mode 100644 index 0000000..5d39689 --- /dev/null +++ b/SweetChatService/Entity/User.cs @@ -0,0 +1,29 @@ +using FreeSql.DataAnnotations; + +namespace SweetChatService.Entity +{ + [Table(Name = "user")] + public class User + { + [Column(Name = "id", IsPrimary = true, IsIdentity = true)] + public long Id { get; set; } + + [Column(Name = "phone", StringLength = 20)] + public string Phone { get; set; } = ""; + + [Column(Name = "nickname", StringLength = 50)] + public string Nickname { get; set; } = ""; + + [Column(Name = "avatar_url", StringLength = 255)] + public string AvatarUrl { get; set; } = ""; + + [Column(Name = "gender")] + public byte Gender { get; set; } = 0; + + [Column(Name = "create_time", ServerTime = DateTimeKind.Local, CanUpdate = false)] + public DateTime CreateTime { get; set; } + + [Column(Name = "update_time", ServerTime = DateTimeKind.Local)] + public DateTime UpdateTime { get; set; } + } +} diff --git a/SweetChatService/Handlers/WebSocketMessageHandler.cs b/SweetChatService/Handlers/WebSocketMessageHandler.cs new file mode 100644 index 0000000..3dfe0f9 --- /dev/null +++ b/SweetChatService/Handlers/WebSocketMessageHandler.cs @@ -0,0 +1,76 @@ +using Microsoft.AspNetCore.WebUtilities; +using Microsoft.Extensions.Logging; +using SuperSocket.WebSocket; +using SuperSocket.WebSocket.Server; +using SweetChatService.Models; +using SweetChatService.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace SweetChatService.Handlers +{ + internal class WebSocketMessageHandler(ILogger logger, + WebSocketSessionManager sessionManager, + UserService userService) + { + private readonly ILogger _logger = logger; + private readonly WebSocketSessionManager _sessionManager = sessionManager; + private readonly UserService _userService = userService; + + public async ValueTask HandleAsync(WebSocketSession session, WebSocketPackage package) + { + var query = QueryHelpers.ParseQuery(session.Path.TrimStart('/')); + + // 1. 判断url是否正确 + if (!query.TryGetValue("userId", out var userId)) + { + _logger.LogWarning("未知连接"); + await session.CloseAsync(); + return; + } + + // 2. 判断userId是否存在 + _logger.LogInformation($"[userId] {userId}"); + // _logger.LogInformation($"[WebSocket] {package.Message}"); + + // 3. 根据消息类型执行操作 + try + { + var message = JsonSerializer.Deserialize(package.Message); + await HandleImMessage(session, message); + } + catch (JsonException ex) + { + _logger.LogWarning($"未知消息: {ex.Message}"); + await session.CloseAsync(); + return; + } + } + + private async Task HandleImMessage(WebSocketSession session, ImMessage msg) + { + switch (msg.Type) + { + case ImMessageType.CHAT: + if (_sessionManager.TryGet(msg.To, out var toSession)) + { + await toSession.SendAsync(msg.Content); + } + break; + + case ImMessageType.ONLINE: + _sessionManager.Add(msg.From, session); + await session.SendAsync("ok"); + break; + + case ImMessageType.HEARTBEAT: + await session.SendAsync("ok"); + break; + } + } + } +} diff --git a/SweetChatService/Handlers/WebSocketSessionManager.cs b/SweetChatService/Handlers/WebSocketSessionManager.cs new file mode 100644 index 0000000..07e03e0 --- /dev/null +++ b/SweetChatService/Handlers/WebSocketSessionManager.cs @@ -0,0 +1,27 @@ +using SuperSocket.WebSocket.Server; +using System.Collections.Concurrent; + +namespace SweetChatService.Handlers +{ + internal class WebSocketSessionManager + { + private readonly ConcurrentDictionary _sessions = new(); + + public void Add(string userId, WebSocketSession session) + { + _sessions[userId] = session; + } + + public void Remove(string userId) + { + _sessions.TryRemove(userId, out _); + } + + public bool TryGet(string userId, out WebSocketSession? session) + { + return _sessions.TryGetValue(userId, out session); + } + + public IEnumerable All => _sessions.Values; + } +} diff --git a/SweetChatService/Models/ImMessage.cs b/SweetChatService/Models/ImMessage.cs new file mode 100644 index 0000000..ec334cc --- /dev/null +++ b/SweetChatService/Models/ImMessage.cs @@ -0,0 +1,19 @@ +using System.Text.Json.Serialization; + +namespace SweetChatService.Models +{ + internal class ImMessage + { + [JsonPropertyName("type")] + public ImMessageType Type { get; set; } + + [JsonPropertyName("from")] + public string From { get; set; } = default!; + + [JsonPropertyName("to")] + public string To { get; set; } = default!; + + [JsonPropertyName("content")] + public string Content { get; set; } = default!; + } +} diff --git a/SweetChatService/Models/ImMessageType.cs b/SweetChatService/Models/ImMessageType.cs new file mode 100644 index 0000000..4d8b959 --- /dev/null +++ b/SweetChatService/Models/ImMessageType.cs @@ -0,0 +1,14 @@ +using System.Text.Json.Serialization; + +namespace SweetChatService.Models +{ + [JsonConverter(typeof(JsonStringEnumConverter))] + internal enum ImMessageType + { + CHAT, + ONLINE, + HEARTBEAT, + SYSTEM, + NOTICE + } +} diff --git a/SweetChatService/NLog.config b/SweetChatService/NLog.config new file mode 100644 index 0000000..2483d17 --- /dev/null +++ b/SweetChatService/NLog.config @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SweetChatService/Program.cs b/SweetChatService/Program.cs new file mode 100644 index 0000000..b074071 --- /dev/null +++ b/SweetChatService/Program.cs @@ -0,0 +1,51 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using NLog.Extensions.Hosting; +using SuperSocket.Server.Host; +using SuperSocket.WebSocket.Server; +using SweetChatService.Config; +using SweetChatService.Handlers; +using SweetChatService.Services; +using System.IO; + +var host = Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }) + .ConfigureServices((context, services) => + { + services.AddSingleton(); + services.AddSingleton(); + + services.AddSingleton(FreeSqlSetup.CreateFreeSql(context.Configuration["ConnectionStrings:Default"])); + services.AddSingleton(); + }) + .AsMultipleServerHostBuilder() + .AddWebSocketServer(builder => + { + builder + //.UseSessionHandler(async (session) => + //{ + // Console.WriteLine($"Client connected: {session.SessionID}"); + //}, + //async (session, error) => + //{ + // Console.WriteLine($"Client disconnected: {session.SessionID}"); + //}) + .UseWebSocketMessageHandler(async (session, package) => + { + using var scope = session.Server.ServiceProvider.CreateScope(); + var handler = scope.ServiceProvider.GetRequiredService(); + + await handler.HandleAsync(session, package); + }) + .ConfigureServerOptions((ctx, config) => config.GetSection("WebSocketServer")); + }) + .ConfigureLogging(logging => logging.ClearProviders()) + .UseNLog() + .Build(); + +await host.RunAsync(); diff --git a/SweetChatService/Properties/launchSettings.json b/SweetChatService/Properties/launchSettings.json new file mode 100644 index 0000000..3fc5a9b --- /dev/null +++ b/SweetChatService/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "SweetChatService": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:2835;http://localhost:2836" + } + } +} \ No newline at end of file diff --git a/SweetChatService/Services/UserService.cs b/SweetChatService/Services/UserService.cs new file mode 100644 index 0000000..1cffa95 --- /dev/null +++ b/SweetChatService/Services/UserService.cs @@ -0,0 +1,18 @@ +using SweetChatService.Entity; + +namespace SweetChatService.Services +{ + public class UserService + { + private readonly IFreeSql _fsql; + + public UserService(IFreeSql fsql) => _fsql = fsql; + + public User QueryUserByName(string username) + { + return _fsql.Select() + .Where(u => u.Nickname == username) + .First(); + } + } +} diff --git a/SweetChatService/SweetChatService.csproj b/SweetChatService/SweetChatService.csproj new file mode 100644 index 0000000..396e04c --- /dev/null +++ b/SweetChatService/SweetChatService.csproj @@ -0,0 +1,28 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + + + Always + + + Always + + + + diff --git a/SweetChatService/appsettings.json b/SweetChatService/appsettings.json new file mode 100644 index 0000000..38e2d10 --- /dev/null +++ b/SweetChatService/appsettings.json @@ -0,0 +1,16 @@ +{ + "ConnectionStrings": { + "Default": "Server=localhost;Port=3306;Database=sweet_chat;Uid=root;Pwd=estun@medical;Charset=utf8mb4;" + }, + "serverOptions": { + "WebSocketServer": { + "name": "WebSocket", + "listeners": [ + { + "ip": "Any", + "port": 5050 + } + ] + } + } +} \ No newline at end of file diff --git a/SweetChatService/sweet_chat.sql b/SweetChatService/sweet_chat.sql new file mode 100644 index 0000000..eac411a --- /dev/null +++ b/SweetChatService/sweet_chat.sql @@ -0,0 +1,141 @@ +-- MySQL dump 10.13 Distrib 8.0.27, for Win64 (x86_64) +-- +-- Host: 127.0.0.1 Database: sweet_chat +-- ------------------------------------------------------ +-- Server version 8.0.27 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!50503 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `conversation` +-- + +DROP TABLE IF EXISTS `conversation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `conversation` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '会话ID', + `type` tinyint NOT NULL COMMENT '1单聊 2群聊', + `last_msg_id` bigint DEFAULT '0' COMMENT '最后一条消息ID', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会话表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `conversation` +-- + +LOCK TABLES `conversation` WRITE; +/*!40000 ALTER TABLE `conversation` DISABLE KEYS */; +INSERT INTO `conversation` VALUES (1,1,2,'2026-06-17 13:45:29','2026-06-17 13:50:21'); +/*!40000 ALTER TABLE `conversation` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `conversation_member` +-- + +DROP TABLE IF EXISTS `conversation_member`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `conversation_member` ( + `conversation_id` bigint NOT NULL COMMENT '会话ID', + `user_id` bigint NOT NULL COMMENT '用户ID', + `unread_count` int DEFAULT '0' COMMENT '未读消息数', + `last_read_msg_id` bigint DEFAULT '0' COMMENT '已读到最后一条消息ID', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`conversation_id`,`user_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会话成员表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `conversation_member` +-- + +LOCK TABLES `conversation_member` WRITE; +/*!40000 ALTER TABLE `conversation_member` DISABLE KEYS */; +INSERT INTO `conversation_member` VALUES (1,1,1,0,'2026-06-17 13:46:18','2026-06-17 13:50:36'),(1,2,1,0,'2026-06-17 13:46:18','2026-06-17 13:47:27'); +/*!40000 ALTER TABLE `conversation_member` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `message` +-- + +DROP TABLE IF EXISTS `message`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `message` ( + `msg_id` bigint NOT NULL AUTO_INCREMENT COMMENT '消息ID', + `conversation_id` bigint NOT NULL COMMENT '会话ID', + `sender_id` bigint NOT NULL COMMENT '发送者ID', + `content` text NOT NULL COMMENT '消息内容', + `msg_type` tinyint DEFAULT '1' COMMENT '1文本 2图片 3语音', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`msg_id`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='消息表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `message` +-- + +LOCK TABLES `message` WRITE; +/*!40000 ALTER TABLE `message` DISABLE KEYS */; +INSERT INTO `message` VALUES (1,1,1,'张三,在吗?',1,'2026-06-17 13:46:35','2026-06-17 13:46:35'),(2,1,2,'在,咋了?',1,'2026-06-17 13:49:48','2026-06-17 13:49:48'); +/*!40000 ALTER TABLE `message` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user` +-- + +DROP TABLE IF EXISTS `user`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `user` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID', + `phone` varchar(20) NOT NULL COMMENT '手机号', + `nickname` varchar(50) NOT NULL COMMENT '昵称', + `avatar_url` varchar(255) DEFAULT '' COMMENT '头像', + `gender` tinyint DEFAULT '0' COMMENT '0未知 1男 2女', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `phone` (`phone`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user` +-- + +LOCK TABLES `user` WRITE; +/*!40000 ALTER TABLE `user` DISABLE KEYS */; +INSERT INTO `user` VALUES (1,'13800000001','Cxx','',1,'2026-06-17 13:42:21','2026-06-17 13:42:21'),(2,'13800000002','Pjm','',1,'2026-06-17 13:42:21','2026-06-17 18:18:16'); +/*!40000 ALTER TABLE `user` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-06-17 19:53:25