Merge pull request '更新 📘 接口响应 Code 设计文档.md' (#7) from test into main

Reviewed-on: code/Chat#7
This commit is contained in:
西街长安 2025-10-12 20:56:22 +08:00 committed by nanxun
commit 52f5ad8eeb
60 changed files with 9583 additions and 1364 deletions

0
.gitignore vendored Normal file
View File

View File

@ -0,0 +1,30 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
!**/.gitignore
!.git/HEAD
!.git/config
!.git/packed-refs
!.git/refs/heads/**

3
backend/IM_API/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
bin/
obj/
.vs/

View File

@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Mvc;
namespace IM_API.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}

30
backend/IM_API/Dockerfile Normal file
View File

@ -0,0 +1,30 @@
# 请参阅 https://aka.ms/customizecontainer 以了解如何自定义调试容器,以及 Visual Studio 如何使用此 Dockerfile 生成映像以更快地进行调试。
# 此阶段用于在快速模式(默认为调试配置)下从 VS 运行时
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER $APP_UID
WORKDIR /app
EXPOSE 8080
EXPOSE 8081
# 此阶段用于生成服务项目
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["IM_API.csproj", "."]
RUN dotnet restore "./IM_API.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "./IM_API.csproj" -c $BUILD_CONFIGURATION -o /app/build
# 此阶段用于发布要复制到最终阶段的服务项目
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./IM_API.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
# 此阶段在生产中使用,或在常规模式下从 VS 运行时使用(在不使用调试配置时为默认值)
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "IM_API.dll"]

View File

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>3f396849-59bd-435f-a0cb-351ec0559e70</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerfileContext>.</DockerfileContext>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.21">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.21">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.22.1" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>http</ActiveDebugProfile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,6 @@
@IM_API_HostAddress = http://localhost:5202
GET {{IM_API_HostAddress}}/weatherforecast/
Accept: application/json
###

25
backend/IM_API/IM_API.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36408.4 d17.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IM_API", "IM_API.csproj", "{F001642C-3E66-4C2C-9A25-1AE5EE76CE97}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F001642C-3E66-4C2C-9A25-1AE5EE76CE97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F001642C-3E66-4C2C-9A25-1AE5EE76CE97}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F001642C-3E66-4C2C-9A25-1AE5EE76CE97}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F001642C-3E66-4C2C-9A25-1AE5EE76CE97}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EC36B0B9-6176-4BC7-BF88-33F923E3E777}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("admins")]
[Index("RoleId", Name = "RoleId")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Admin
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 用户名
/// </summary>
[StringLength(50)]
public string Username { get; set; } = null!;
/// <summary>
/// 密码
/// </summary>
[StringLength(50)]
public string Password { get; set; } = null!;
/// <summary>
/// 角色
/// </summary>
[Column(TypeName = "int(11)")]
public int RoleId { get; set; }
/// <summary>
/// 状态0:正常2封禁
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte State { get; set; }
/// <summary>
/// 创建时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created { get; set; }
/// <summary>
/// 更新时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Updated { get; set; }
[ForeignKey("RoleId")]
[InverseProperty("Admins")]
public virtual Role Role { get; set; } = null!;
}

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("conversations")]
[Index("Userid", Name = "Userid")]
[Index("LastMessageId", Name = "lastMessageId")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Conversation
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 用户
/// </summary>
[Column(TypeName = "int(11)")]
public int Userid { get; set; }
/// <summary>
/// 对方ID群聊为群聊ID单聊为单聊ID
/// </summary>
[Column(TypeName = "int(11)")]
public int Targetid { get; set; }
/// <summary>
/// 消息类型同Messages.MsgType
/// </summary>
[Column(TypeName = "int(11)")]
public int MsgType { get; set; }
/// <summary>
/// 最后一条消息ID
/// </summary>
[Column("lastMessageId", TypeName = "int(11)")]
public int LastMessageId { get; set; }
/// <summary>
/// 未读消息数
/// </summary>
[Column("unreadCount", TypeName = "int(11)")]
public int UnreadCount { get; set; }
[ForeignKey("LastMessageId")]
[InverseProperty("Conversations")]
public virtual Message LastMessage { get; set; } = null!;
[ForeignKey("Userid")]
[InverseProperty("Conversations")]
public virtual User User { get; set; } = null!;
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("devices")]
[Index("Userid", Name = "Userid")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Device
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 设备所属用户
/// </summary>
[Column(TypeName = "int(11)")]
public int Userid { get; set; }
/// <summary>
/// 设备类型(
/// 0:Android,1:Ios,2:PC,3Pad,4:未知)
/// </summary>
[Column("DType", TypeName = "tinyint(4)")]
public sbyte Dtype { get; set; }
/// <summary>
/// 最后一次登录
/// </summary>
[Column(TypeName = "datetime")]
public DateTime LastLogin { get; set; }
[ForeignKey("Userid")]
[InverseProperty("Devices")]
public virtual User User { get; set; } = null!;
}

View File

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("files")]
[Index("Messageld", Name = "Messageld")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class File
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 文件名
/// </summary>
[StringLength(50)]
public string Name { get; set; } = null!;
/// <summary>
/// 文件储存URL
/// </summary>
[Column("URL")]
[StringLength(100)]
public string Url { get; set; } = null!;
/// <summary>
/// 文件大小单位KB
/// </summary>
[Column(TypeName = "int(11)")]
public int Size { get; set; }
/// <summary>
/// 文件类型
/// </summary>
[StringLength(10)]
public string Type { get; set; } = null!;
/// <summary>
/// 关联消息ID
/// </summary>
[Column(TypeName = "int(11)")]
public int Messageld { get; set; }
/// <summary>
/// 创建时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created { get; set; }
[ForeignKey("Messageld")]
[InverseProperty("Files")]
public virtual Message MessageldNavigation { get; set; } = null!;
}

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("friends")]
[Index("Id", Name = "ID")]
[Index("Userld", "Friendld", Name = "Userld")]
[Index("Friendld", Name = "用户2id")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Friend
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 用户ID
/// </summary>
[Column(TypeName = "int(11)")]
public int Userld { get; set; }
/// <summary>
/// 用户2ID
/// </summary>
[Column(TypeName = "int(11)")]
public int Friendld { get; set; }
/// <summary>
/// 当前好友关系状态
/// 0待通过,1已添加,2已拒绝,3已拉黑
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte Status { get; set; }
/// <summary>
/// 好友关系创建时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created { get; set; }
[ForeignKey("Friendld")]
[InverseProperty("FriendFriendldNavigations")]
public virtual User FriendldNavigation { get; set; } = null!;
[ForeignKey("Userld")]
[InverseProperty("FriendUserldNavigations")]
public virtual User UserldNavigation { get; set; } = null!;
}

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("friendrequest")]
[Index("RequestUser", Name = "RequestUser")]
[Index("ResponseUser", Name = "ResponseUser")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Friendrequest
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 申请人
/// </summary>
[Column(TypeName = "int(11)")]
public int RequestUser { get; set; }
/// <summary>
/// 被申请人
/// </summary>
[Column(TypeName = "int(11)")]
public int ResponseUser { get; set; }
/// <summary>
/// 申请时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created { get; set; }
/// <summary>
/// 申请附言
/// </summary>
[Column(TypeName = "text")]
public string? Description { get; set; }
/// <summary>
/// 申请状态0待通过,1:拒绝,2:同意,3拉黑
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte State { get; set; }
[ForeignKey("RequestUser")]
[InverseProperty("FriendrequestRequestUserNavigations")]
public virtual User RequestUserNavigation { get; set; } = null!;
[ForeignKey("ResponseUser")]
[InverseProperty("FriendrequestResponseUserNavigations")]
public virtual User ResponseUserNavigation { get; set; } = null!;
}

View File

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("groups")]
[Index("GroupMaster", Name = "GroupMaster")]
[Index("Id", Name = "ID")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Group
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 群聊名称
/// </summary>
[StringLength(20)]
public string Name { get; set; } = null!;
/// <summary>
/// 群主
/// </summary>
[Column(TypeName = "int(11)")]
public int GroupMaster { get; set; }
/// <summary>
/// 群权限
/// 0需管理员同意,1任意人可加群,2不允许任何人加入
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte Auhority { get; set; }
/// <summary>
/// 全员禁言0允许发言2全员禁言
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte AllMembersBanned { get; set; }
/// <summary>
/// 群聊状态
/// (1正常,2封禁)
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte Status { get; set; }
/// <summary>
/// 群公告
/// </summary>
[Column(TypeName = "text")]
public string? Announcement { get; set; }
/// <summary>
/// 群聊创建时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created { get; set; }
[ForeignKey("GroupMaster")]
[InverseProperty("Groups")]
public virtual User GroupMasterNavigation { get; set; } = null!;
[InverseProperty("Group")]
public virtual ICollection<Groupinvite> Groupinvites { get; set; } = new List<Groupinvite>();
[InverseProperty("Group")]
public virtual ICollection<Grouprequest> Grouprequests { get; set; } = new List<Grouprequest>();
}

View File

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("groupinvite")]
[Index("GroupId", Name = "GroupId")]
[Index("InviteUser", Name = "InviteUser")]
[Index("InvitedUser", Name = "InvitedUser")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Groupinvite
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 群聊编号
/// </summary>
[Column(TypeName = "int(11)")]
public int GroupId { get; set; }
/// <summary>
/// 被邀请用户
/// </summary>
[Column(TypeName = "int(11)")]
public int? InvitedUser { get; set; }
/// <summary>
/// 邀请用户
/// </summary>
[Column(TypeName = "int(11)")]
public int? InviteUser { get; set; }
/// <summary>
/// 当前状态(0:待被邀请人同意
/// 1:被邀请人已同意)
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte? State { get; set; }
/// <summary>
/// 创建时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime? Created { get; set; }
[ForeignKey("GroupId")]
[InverseProperty("Groupinvites")]
public virtual Group Group { get; set; } = null!;
[ForeignKey("InviteUser")]
[InverseProperty("GroupinviteInviteUserNavigations")]
public virtual User? InviteUserNavigation { get; set; }
[ForeignKey("InvitedUser")]
[InverseProperty("GroupinviteInvitedUserNavigations")]
public virtual User? InvitedUserNavigation { get; set; }
}

View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("groupmember")]
[Index("Groupld", Name = "Groupld")]
[Index("Id", Name = "ID")]
[Index("Userld", Name = "Userld")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Groupmember
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 用户编号
/// </summary>
[Column(TypeName = "int(11)")]
public int Userld { get; set; }
/// <summary>
/// 群聊编号
/// </summary>
[Column(TypeName = "int(11)")]
public int Groupld { get; set; }
/// <summary>
/// 成员角色0:普通成员,1:管理员,2:群主)
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte Role { get; set; }
/// <summary>
/// 加入群聊时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created { get; set; }
[ForeignKey("Groupld")]
[InverseProperty("GroupmemberGroupldNavigations")]
public virtual User GroupldNavigation { get; set; } = null!;
[ForeignKey("Userld")]
[InverseProperty("GroupmemberUserldNavigations")]
public virtual User UserldNavigation { get; set; } = null!;
}

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("grouprequest")]
[Index("GroupId", Name = "GroupId")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Grouprequest
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 群聊编号
///
/// </summary>
[Column(TypeName = "int(11)")]
public int GroupId { get; set; }
/// <summary>
/// 申请人
/// </summary>
[Column(TypeName = "int(11)")]
public int UserId { get; set; }
/// <summary>
/// 申请状态0:待管理员同意,1:已拒绝,2已同意
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte State { get; set; }
/// <summary>
/// 入群附言
/// </summary>
[Column(TypeName = "text")]
public string Description { get; set; } = null!;
/// <summary>
/// 创建时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created { get; set; }
[ForeignKey("GroupId")]
[InverseProperty("Grouprequests")]
public virtual Group Group { get; set; } = null!;
[ForeignKey("GroupId")]
[InverseProperty("Grouprequests")]
public virtual User GroupNavigation { get; set; } = null!;
}

View File

@ -0,0 +1,343 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Pomelo.EntityFrameworkCore.MySql.Scaffolding.Internal;
namespace IM_API.Models;
public partial class IMDbContext : DbContext
{
public IMDbContext()
{
}
public IMDbContext(DbContextOptions<IMDbContext> options)
: base(options)
{
}
public virtual DbSet<Admin> Admins { get; set; }
public virtual DbSet<Conversation> Conversations { get; set; }
public virtual DbSet<Device> Devices { get; set; }
public virtual DbSet<File> Files { get; set; }
public virtual DbSet<Friend> Friends { get; set; }
public virtual DbSet<Friendrequest> Friendrequests { get; set; }
public virtual DbSet<Group> Groups { get; set; }
public virtual DbSet<Groupinvite> Groupinvites { get; set; }
public virtual DbSet<Groupmember> Groupmembers { get; set; }
public virtual DbSet<Grouprequest> Grouprequests { get; set; }
public virtual DbSet<LoginLog> LoginLogs { get; set; }
public virtual DbSet<Message> Messages { get; set; }
public virtual DbSet<Notification> Notifications { get; set; }
public virtual DbSet<Permission> Permissions { get; set; }
public virtual DbSet<Permissionarole> Permissionaroles { get; set; }
public virtual DbSet<Role> Roles { get; set; }
public virtual DbSet<User> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
=> optionsBuilder.UseMySql("server=192.168.5.100;port=3306;database=IM;user=root;password=768788Dyw", Microsoft.EntityFrameworkCore.ServerVersion.Parse("5.7.44-mysql"));
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.UseCollation("latin1_swedish_ci")
.HasCharSet("latin1");
modelBuilder.Entity<Admin>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Created).HasComment("创建时间 ");
entity.Property(e => e.Password).HasComment("密码");
entity.Property(e => e.RoleId).HasComment("角色");
entity.Property(e => e.State).HasComment("状态0:正常2封禁 ");
entity.Property(e => e.Updated).HasComment("更新时间 ");
entity.Property(e => e.Username).HasComment("用户名");
entity.HasOne(d => d.Role).WithMany(p => p.Admins)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("admins_ibfk_1");
});
modelBuilder.Entity<Conversation>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.LastMessageId).HasComment("最后一条消息ID ");
entity.Property(e => e.MsgType).HasComment("消息类型同Messages.MsgType ");
entity.Property(e => e.Targetid).HasComment("对方ID群聊为群聊ID单聊为单聊ID ");
entity.Property(e => e.UnreadCount).HasComment("未读消息数 ");
entity.Property(e => e.Userid).HasComment("用户");
entity.HasOne(d => d.LastMessage).WithMany(p => p.Conversations)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("conversations_ibfk_2");
entity.HasOne(d => d.User).WithMany(p => p.Conversations)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("conversations_ibfk_1");
});
modelBuilder.Entity<Device>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Dtype).HasComment("设备类型(\r\n0:Android,1:Ios,2:PC,3Pad,4:未知)");
entity.Property(e => e.LastLogin).HasComment("最后一次登录 ");
entity.Property(e => e.Userid).HasComment("设备所属用户 ");
entity.HasOne(d => d.User).WithMany(p => p.Devices)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("devices_ibfk_1");
});
modelBuilder.Entity<File>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Created).HasComment("创建时间 ");
entity.Property(e => e.Messageld).HasComment("关联消息ID ");
entity.Property(e => e.Name).HasComment("文件名 ");
entity.Property(e => e.Size).HasComment("文件大小单位KB ");
entity.Property(e => e.Type).HasComment("文件类型 ");
entity.Property(e => e.Url).HasComment("文件储存URL ");
entity.HasOne(d => d.MessageldNavigation).WithMany(p => p.Files)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("files_ibfk_1");
});
modelBuilder.Entity<Friend>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Created).HasComment("好友关系创建时间");
entity.Property(e => e.Friendld).HasComment("用户2ID");
entity.Property(e => e.Status).HasComment("当前好友关系状态\r\n0待通过,1已添加,2已拒绝,3已拉黑");
entity.Property(e => e.Userld).HasComment("用户ID");
entity.HasOne(d => d.FriendldNavigation).WithMany(p => p.FriendFriendldNavigations)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("用户2id");
entity.HasOne(d => d.UserldNavigation).WithMany(p => p.FriendUserldNavigations)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("用户id");
});
modelBuilder.Entity<Friendrequest>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Created).HasComment("申请时间 ");
entity.Property(e => e.Description).HasComment("申请附言 ");
entity.Property(e => e.RequestUser).HasComment("申请人 ");
entity.Property(e => e.ResponseUser).HasComment("被申请人 ");
entity.Property(e => e.State).HasComment("申请状态0待通过,1:拒绝,2:同意,3拉黑 ");
entity.HasOne(d => d.RequestUserNavigation).WithMany(p => p.FriendrequestRequestUserNavigations)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("friendrequest_ibfk_1");
entity.HasOne(d => d.ResponseUserNavigation).WithMany(p => p.FriendrequestResponseUserNavigations)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("friendrequest_ibfk_2");
});
modelBuilder.Entity<Group>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.AllMembersBanned).HasComment("全员禁言0允许发言2全员禁言");
entity.Property(e => e.Announcement).HasComment("群公告");
entity.Property(e => e.Auhority).HasComment("群权限\r\n0需管理员同意,1任意人可加群,2不允许任何人加入");
entity.Property(e => e.Created).HasComment("群聊创建时间");
entity.Property(e => e.GroupMaster).HasComment("群主");
entity.Property(e => e.Name).HasComment("群聊名称");
entity.Property(e => e.Status).HasComment("群聊状态\r\n(1正常,2封禁)");
entity.HasOne(d => d.GroupMasterNavigation).WithMany(p => p.Groups)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("groups_ibfk_1");
});
modelBuilder.Entity<Groupinvite>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Created).HasComment("创建时间");
entity.Property(e => e.GroupId).HasComment("群聊编号");
entity.Property(e => e.InviteUser).HasComment("邀请用户");
entity.Property(e => e.InvitedUser).HasComment("被邀请用户");
entity.Property(e => e.State).HasComment("当前状态(0:待被邀请人同意\r\n1:被邀请人已同意)");
entity.HasOne(d => d.Group).WithMany(p => p.Groupinvites)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("groupinvite_ibfk_2");
entity.HasOne(d => d.InviteUserNavigation).WithMany(p => p.GroupinviteInviteUserNavigations).HasConstraintName("groupinvite_ibfk_1");
entity.HasOne(d => d.InvitedUserNavigation).WithMany(p => p.GroupinviteInvitedUserNavigations).HasConstraintName("groupinvite_ibfk_3");
});
modelBuilder.Entity<Groupmember>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Created)
.HasDefaultValueSql("'1970-01-01 00:00:00'")
.HasComment("加入群聊时间");
entity.Property(e => e.Groupld).HasComment("群聊编号");
entity.Property(e => e.Role).HasComment("成员角色0:普通成员,1:管理员,2:群主)");
entity.Property(e => e.Userld).HasComment("用户编号");
entity.HasOne(d => d.GroupldNavigation).WithMany(p => p.GroupmemberGroupldNavigations)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("groupmember_ibfk_2");
entity.HasOne(d => d.UserldNavigation).WithMany(p => p.GroupmemberUserldNavigations)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("groupmember_ibfk_1");
});
modelBuilder.Entity<Grouprequest>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Created).HasComment("创建时间");
entity.Property(e => e.Description).HasComment("入群附言");
entity.Property(e => e.GroupId).HasComment("群聊编号\r\n");
entity.Property(e => e.State).HasComment("申请状态0:待管理员同意,1:已拒绝,2已同意");
entity.Property(e => e.UserId).HasComment("申请人 ");
entity.HasOne(d => d.Group).WithMany(p => p.Grouprequests)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("grouprequest_ibfk_1");
entity.HasOne(d => d.GroupNavigation).WithMany(p => p.Grouprequests)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("grouprequest_ibfk_2");
});
modelBuilder.Entity<LoginLog>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Dtype).HasComment("设备类型通Devices/DType ");
entity.Property(e => e.Logined).HasComment("登录时间 ");
entity.Property(e => e.State).HasComment("登录状态(0:登陆成功,1:未验证,2:已被拒绝) ");
entity.Property(e => e.Userld).HasComment("登录用户 ");
entity.HasOne(d => d.UserldNavigation).WithMany(p => p.LoginLogs)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("login_log_ibfk_1");
});
modelBuilder.Entity<Message>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.ChatType).HasComment("聊天类型\r\n0私聊,1群聊");
entity.Property(e => e.Content).HasComment("消息内容 ");
entity.Property(e => e.Created).HasComment("发送时间 ");
entity.Property(e => e.MsgType).HasComment("消息类型\r\n(0:文本,1图片,2语音,3视频,4文件5语音聊天,6视频聊天)");
entity.Property(e => e.Recipient).HasComment("接收者私聊为用户ID群聊为群聊ID ");
entity.Property(e => e.Sender).HasComment("发送者 ");
entity.Property(e => e.State).HasComment("消息状态(0:已发送,1:已撤回) ");
entity.HasOne(d => d.SenderNavigation).WithMany(p => p.Messages)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("messages_ibfk_1");
});
modelBuilder.Entity<Notification>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Content).HasComment("通知内容");
entity.Property(e => e.Created).HasComment("创建时间");
entity.Property(e => e.Ntype).HasComment("通知类型(0文本)");
entity.Property(e => e.Title).HasComment("通知标题");
entity.Property(e => e.Userld).HasComment("接收人(为空为全体通知)");
entity.HasOne(d => d.UserldNavigation).WithMany(p => p.Notifications)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("notifications_ibfk_1");
});
modelBuilder.Entity<Permission>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Code).HasComment("权限编码 ");
entity.Property(e => e.Created).HasComment("创建时间 ");
entity.Property(e => e.Name).HasComment("权限名称 ");
entity.Property(e => e.Ptype).HasComment("权限类型(0:增,1:删,2:改,3:查) ");
});
modelBuilder.Entity<Permissionarole>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Id).ValueGeneratedNever();
entity.Property(e => e.Permissionld).HasComment("权限 ");
entity.Property(e => e.Roleld).HasComment("角色 ");
entity.HasOne(d => d.PermissionldNavigation).WithMany(p => p.Permissionaroles)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("permissionarole_ibfk_2");
entity.HasOne(d => d.RoleldNavigation).WithMany(p => p.Permissionaroles)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("permissionarole_ibfk_1");
});
modelBuilder.Entity<Role>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Created).HasComment("创建时间 ");
entity.Property(e => e.Description).HasComment("角色描述 ");
entity.Property(e => e.Name).HasComment("角色名称 ");
});
modelBuilder.Entity<User>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Created)
.HasDefaultValueSql("'1970-01-01 00:00:00'")
.HasComment("创建时间");
entity.Property(e => e.IsDeleted).HasComment("软删除标识\r\n0账号正常\r\n1账号已删除");
entity.Property(e => e.NickName).HasComment("用户昵称");
entity.Property(e => e.OlineStatus).HasComment("用户在线状态\r\n0默认不在线\r\n1在线");
entity.Property(e => e.Password).HasComment("密码");
entity.Property(e => e.Status)
.HasDefaultValueSql("'1'")
.HasComment("账户状态\r\n(0未激活,1正常,2封禁)");
entity.Property(e => e.Updated).HasComment("修改时间");
entity.Property(e => e.Username).HasComment("唯一用户名");
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}

View File

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("login_log")]
[Index("Userld", Name = "Userld")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class LoginLog
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 设备类型通Devices/DType
/// </summary>
[Column("DType", TypeName = "tinyint(4)")]
public sbyte Dtype { get; set; }
/// <summary>
/// 登录时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Logined { get; set; }
/// <summary>
/// 登录用户
/// </summary>
[Column(TypeName = "int(11)")]
public int Userld { get; set; }
/// <summary>
/// 登录状态(0:登陆成功,1:未验证,2:已被拒绝)
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte State { get; set; }
[ForeignKey("Userld")]
[InverseProperty("LoginLogs")]
public virtual User UserldNavigation { get; set; } = null!;
}

View File

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("messages")]
[Index("Sender", Name = "Sender")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Message
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 聊天类型
/// 0私聊,1群聊
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte ChatType { get; set; }
/// <summary>
/// 消息类型
/// (0:文本,1图片,2语音,3视频,4文件5语音聊天,6视频聊天)
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte MsgType { get; set; }
/// <summary>
/// 消息内容
/// </summary>
[Column(TypeName = "text")]
public string Content { get; set; } = null!;
/// <summary>
/// 发送者
/// </summary>
[Column(TypeName = "int(11)")]
public int Sender { get; set; }
/// <summary>
/// 接收者私聊为用户ID群聊为群聊ID
/// </summary>
[Column(TypeName = "int(11)")]
public int Recipient { get; set; }
/// <summary>
/// 消息状态(0:已发送,1:已撤回)
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte State { get; set; }
/// <summary>
/// 发送时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created { get; set; }
[InverseProperty("LastMessage")]
public virtual ICollection<Conversation> Conversations { get; set; } = new List<Conversation>();
[InverseProperty("MessageldNavigation")]
public virtual ICollection<File> Files { get; set; } = new List<File>();
[ForeignKey("Sender")]
[InverseProperty("Messages")]
public virtual User SenderNavigation { get; set; } = null!;
}

View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("notifications")]
[Index("Userld", Name = "Userld")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Notification
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 接收人(为空为全体通知)
/// </summary>
[Column(TypeName = "int(11)")]
public int Userld { get; set; }
/// <summary>
/// 通知类型(0文本)
/// </summary>
[Column("NType", TypeName = "tinyint(4)")]
public sbyte Ntype { get; set; }
/// <summary>
/// 通知标题
/// </summary>
[StringLength(40)]
public string Title { get; set; } = null!;
/// <summary>
/// 通知内容
/// </summary>
[Column(TypeName = "text")]
public string Content { get; set; } = null!;
/// <summary>
/// 创建时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created { get; set; }
[ForeignKey("Userld")]
[InverseProperty("Notifications")]
public virtual User UserldNavigation { get; set; } = null!;
}

View File

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("permissions")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Permission
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 权限类型(0:增,1:删,2:改,3:查)
/// </summary>
[Column("PType", TypeName = "int(11)")]
public int Ptype { get; set; }
/// <summary>
/// 权限名称
/// </summary>
[StringLength(50)]
public string Name { get; set; } = null!;
/// <summary>
/// 权限编码
/// </summary>
[Column(TypeName = "int(11)")]
public int Code { get; set; }
/// <summary>
/// 创建时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created { get; set; }
[InverseProperty("PermissionldNavigation")]
public virtual ICollection<Permissionarole> Permissionaroles { get; set; } = new List<Permissionarole>();
}

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("permissionarole")]
[Index("Permissionld", Name = "Permissionld")]
[Index("Roleld", Name = "Roleld")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Permissionarole
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 角色
/// </summary>
[Column(TypeName = "int(11)")]
public int Roleld { get; set; }
/// <summary>
/// 权限
/// </summary>
[Column(TypeName = "int(11)")]
public int Permissionld { get; set; }
[ForeignKey("Permissionld")]
[InverseProperty("Permissionaroles")]
public virtual Permission PermissionldNavigation { get; set; } = null!;
[ForeignKey("Roleld")]
[InverseProperty("Permissionaroles")]
public virtual Role RoleldNavigation { get; set; } = null!;
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("roles")]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class Role
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 角色名称
/// </summary>
[StringLength(20)]
public string Name { get; set; } = null!;
/// <summary>
/// 角色描述
/// </summary>
[Column(TypeName = "text")]
public string Description { get; set; } = null!;
/// <summary>
/// 创建时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created { get; set; }
[InverseProperty("Role")]
public virtual ICollection<Admin> Admins { get; set; } = new List<Admin>();
[InverseProperty("RoleldNavigation")]
public virtual ICollection<Permissionarole> Permissionaroles { get; set; } = new List<Permissionarole>();
}

View File

@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace IM_API.Models;
[Table("users")]
[Index("Id", Name = "ID")]
[Index("Username", Name = "Username", IsUnique = true)]
[MySqlCharSet("utf8mb4")]
[MySqlCollation("utf8mb4_general_ci")]
public partial class User
{
[Key]
[Column("ID", TypeName = "int(11)")]
public int Id { get; set; }
/// <summary>
/// 唯一用户名
/// </summary>
[StringLength(50)]
public string Username { get; set; } = null!;
/// <summary>
/// 密码
/// </summary>
[StringLength(50)]
public string Password { get; set; } = null!;
/// <summary>
/// 用户昵称
/// </summary>
[StringLength(50)]
public string NickName { get; set; } = null!;
/// <summary>
/// 用户在线状态
/// 0默认不在线
/// 1在线
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte OlineStatus { get; set; }
/// <summary>
/// 创建时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime Created { get; set; }
/// <summary>
/// 修改时间
/// </summary>
[Column(TypeName = "datetime")]
public DateTime? Updated { get; set; }
/// <summary>
/// 账户状态
/// (0未激活,1正常,2封禁)
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte Status { get; set; }
/// <summary>
/// 软删除标识
/// 0账号正常
/// 1账号已删除
/// </summary>
[Column(TypeName = "tinyint(4)")]
public sbyte IsDeleted { get; set; }
[InverseProperty("User")]
public virtual ICollection<Conversation> Conversations { get; set; } = new List<Conversation>();
[InverseProperty("User")]
public virtual ICollection<Device> Devices { get; set; } = new List<Device>();
[InverseProperty("FriendldNavigation")]
public virtual ICollection<Friend> FriendFriendldNavigations { get; set; } = new List<Friend>();
[InverseProperty("UserldNavigation")]
public virtual ICollection<Friend> FriendUserldNavigations { get; set; } = new List<Friend>();
[InverseProperty("RequestUserNavigation")]
public virtual ICollection<Friendrequest> FriendrequestRequestUserNavigations { get; set; } = new List<Friendrequest>();
[InverseProperty("ResponseUserNavigation")]
public virtual ICollection<Friendrequest> FriendrequestResponseUserNavigations { get; set; } = new List<Friendrequest>();
[InverseProperty("InviteUserNavigation")]
public virtual ICollection<Groupinvite> GroupinviteInviteUserNavigations { get; set; } = new List<Groupinvite>();
[InverseProperty("InvitedUserNavigation")]
public virtual ICollection<Groupinvite> GroupinviteInvitedUserNavigations { get; set; } = new List<Groupinvite>();
[InverseProperty("GroupldNavigation")]
public virtual ICollection<Groupmember> GroupmemberGroupldNavigations { get; set; } = new List<Groupmember>();
[InverseProperty("UserldNavigation")]
public virtual ICollection<Groupmember> GroupmemberUserldNavigations { get; set; } = new List<Groupmember>();
[InverseProperty("GroupNavigation")]
public virtual ICollection<Grouprequest> Grouprequests { get; set; } = new List<Grouprequest>();
[InverseProperty("GroupMasterNavigation")]
public virtual ICollection<Group> Groups { get; set; } = new List<Group>();
[InverseProperty("UserldNavigation")]
public virtual ICollection<LoginLog> LoginLogs { get; set; } = new List<LoginLog>();
[InverseProperty("SenderNavigation")]
public virtual ICollection<Message> Messages { get; set; } = new List<Message>();
[InverseProperty("UserldNavigation")]
public virtual ICollection<Notification> Notifications { get; set; } = new List<Notification>();
}

36
backend/IM_API/Program.cs Normal file
View File

@ -0,0 +1,36 @@
namespace IM_API
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
}
}

View File

@ -0,0 +1,52 @@
{
"profiles": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:5202"
},
"https": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:7157;http://localhost:5202"
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Container (Dockerfile)": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"environmentVariables": {
"ASPNETCORE_HTTPS_PORTS": "8081",
"ASPNETCORE_HTTP_PORTS": "8080"
},
"publishAllPorts": true,
"useSSL": true
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:39786",
"sslPort": 44308
}
}
}

View File

@ -0,0 +1,13 @@
namespace IM_API
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@ -70,6 +70,7 @@
| 2101 | 好友关系不存在 | 不是好友 |
| 2102 | 已经是好友 | 重复添加 |
| 2103 | 好友请求被拒绝 | 被对方拒绝 |
| 2104 | 无法申请加好友 | 被对方拉黑 |
------

View File

@ -0,0 +1,8 @@
[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}]
charset = utf-8
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = lf
max_line_length = 100

1
frontend/web/.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
* text=auto eol=lf

30
frontend/web/.gitignore vendored Normal file
View File

@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.tsbuildinfo

View File

@ -0,0 +1,6 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"singleQuote": true,
"printWidth": 100
}

9
frontend/web/.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"recommendations": [
"Vue.volar",
"vitest.explorer",
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
"esbenp.prettier-vscode"
]
}

50
frontend/web/README.md Normal file
View File

@ -0,0 +1,50 @@
# web
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
## Recommended Browser Setup
- Chromium-based browsers (Chrome, Edge, Brave, etc.):
- [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
- [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters)
- Firefox:
- [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/)
- [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/)
## Customize configuration
See [Vite Configuration Reference](https://vite.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Compile and Minify for Production
```sh
npm run build
```
### Run Unit Tests with [Vitest](https://vitest.dev/)
```sh
npm run test:unit
```
### Lint with [ESLint](https://eslint.org/)
```sh
npm run lint
```

View File

@ -0,0 +1,32 @@
import { defineConfig, globalIgnores } from 'eslint/config'
import globals from 'globals'
import js from '@eslint/js'
import pluginVue from 'eslint-plugin-vue'
import pluginVitest from '@vitest/eslint-plugin'
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
export default defineConfig([
{
name: 'app/files-to-lint',
files: ['**/*.{js,mjs,jsx,vue}'],
},
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
{
languageOptions: {
globals: {
...globals.browser,
},
},
},
js.configs.recommended,
...pluginVue.configs['flat/essential'],
{
...pluginVitest.configs.recommended,
files: ['src/**/__tests__/*'],
},
skipFormatting,
])

13
frontend/web/index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

6334
frontend/web/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

37
frontend/web/package.json Normal file
View File

@ -0,0 +1,37 @@
{
"name": "web",
"version": "0.0.0",
"private": true,
"type": "module",
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"test:unit": "vitest",
"lint": "eslint . --fix",
"format": "prettier --write src/"
},
"dependencies": {
"pinia": "^3.0.3",
"vue": "^3.5.22",
"vue-router": "^4.5.1"
},
"devDependencies": {
"@eslint/js": "^9.33.0",
"@vitejs/plugin-vue": "^6.0.1",
"@vitest/eslint-plugin": "^1.3.13",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/test-utils": "^2.4.6",
"eslint": "^9.33.0",
"eslint-plugin-vue": "~10.4.0",
"globals": "^16.3.0",
"jsdom": "^27.0.0",
"prettier": "3.6.2",
"vite": "^7.1.7",
"vite-plugin-vue-devtools": "^8.0.2",
"vitest": "^3.2.4"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

11
frontend/web/src/App.vue Normal file
View File

@ -0,0 +1,11 @@
<script setup></script>
<template>
<h1>You did it!</h1>
<p>
Visit <a href="https://vuejs.org/" target="_blank" rel="noopener">vuejs.org</a> to read the
documentation
</p>
</template>
<style scoped></style>

View File

@ -0,0 +1,11 @@
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import App from '../App.vue'
describe('App', () => {
it('mounts renders properly', () => {
const wrapper = mount(App)
expect(wrapper.text()).toContain('You did it!')
})
})

12
frontend/web/src/main.js Normal file
View File

@ -0,0 +1,12 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')

View File

@ -0,0 +1,8 @@
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [],
})
export default router

View File

@ -0,0 +1,12 @@
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})

View File

@ -0,0 +1,18 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
})

View File

@ -0,0 +1,14 @@
import { fileURLToPath } from 'node:url'
import { mergeConfig, defineConfig, configDefaults } from 'vitest/config'
import viteConfig from './vite.config'
export default mergeConfig(
viteConfig,
defineConfig({
test: {
environment: 'jsdom',
exclude: [...configDefaults.exclude, 'e2e/**'],
root: fileURLToPath(new URL('./', import.meta.url)),
},
}),
)