197 lines
9.8 KiB
C#
197 lines
9.8 KiB
C#
using Model.Entity.System;
|
||
using ORM;
|
||
|
||
namespace Service.Implement
|
||
{
|
||
/// <summary>
|
||
/// RBAC 数据种子:预定义 4 个系统角色 + 6 个权限 + 默认管理员账号(admin/admin123)
|
||
/// 幂等:按 Code 查存在性,存在则跳过;可重复执行
|
||
/// </summary>
|
||
public static class DataSeeder
|
||
{
|
||
/// <summary>数据范围:1=全部, 2=本实验室</summary>
|
||
public const byte DataScopeAll = 1;
|
||
public const byte DataScopeLab = 2;
|
||
|
||
/// <summary>7 个系统权限编码</summary>
|
||
public static readonly (string Code, string Name, string Group)[] Permissions =
|
||
{
|
||
("device:view", "查看设备", "device"),
|
||
("device:edit", "编辑设备", "device"),
|
||
("device:control", "控制设备", "device"),
|
||
("alert:confirm", "确认告警", "alert"),
|
||
("inspection:manage", "巡检管理", "inspection"),
|
||
("user:manage", "用户管理", "user"),
|
||
("system:manage", "系统配置管理", "system")
|
||
};
|
||
|
||
/// <summary>
|
||
/// 4 个预定义角色:超级管理员(全部) / 实验室管理员(本实验室) / 设备操作员(本实验室) / 维修工程师(本实验室)
|
||
/// 权限矩阵严格按需求文档
|
||
/// </summary>
|
||
public static readonly (string Code, string Name, byte DataScope, string[] Permissions)[] Roles =
|
||
{
|
||
("superadmin", "超级管理员", DataScopeAll, new[] { "device:view", "device:edit", "device:control", "alert:confirm", "inspection:manage", "user:manage", "system:manage" }),
|
||
("labadmin", "实验室管理员", DataScopeLab, new[] { "device:view", "device:edit", "device:control", "alert:confirm", "inspection:manage", "system:manage" }),
|
||
("operator", "设备操作员", DataScopeLab, new[] { "device:view", "inspection:manage" }),
|
||
("maintengineer", "维修工程师", DataScopeLab, new[] { "device:view", "device:edit", "device:control", "alert:confirm" })
|
||
};
|
||
|
||
public static void Seed()
|
||
{
|
||
try
|
||
{
|
||
var db = SqlSugarContext.DbContext;
|
||
var now = DateTime.Now;
|
||
|
||
// 1. 权限种子
|
||
var permIdByCode = new Dictionary<string, long>();
|
||
foreach (var (code, name, group) in Permissions)
|
||
{
|
||
var existing = db.Queryable<PermissionEntity>().Where(x => x.Code == code).First();
|
||
if (existing != null) { permIdByCode[code] = existing.Id; continue; }
|
||
var perm = new PermissionEntity
|
||
{
|
||
Code = code, Name = name, Group = group, IsSystem = 1,
|
||
Sort = Array.FindIndex(Permissions, p => p.Code == code),
|
||
CreateTime = now
|
||
};
|
||
var id = db.Insertable(perm).ExecuteReturnSnowflakeId();
|
||
permIdByCode[code] = id;
|
||
}
|
||
|
||
// 2. 角色种子 + 角色-权限关联
|
||
foreach (var (code, name, scope, perms) in Roles)
|
||
{
|
||
var role = db.Queryable<RoleEntity>().Where(x => x.Code == code).First();
|
||
long roleId;
|
||
if (role == null)
|
||
{
|
||
role = new RoleEntity
|
||
{
|
||
Code = code, Name = name, DataScope = scope, IsSystem = 1,
|
||
Sort = Array.FindIndex(Roles, r => r.Code == code),
|
||
Remark = "系统预定义角色",
|
||
CreateTime = now
|
||
};
|
||
roleId = db.Insertable(role).ExecuteReturnSnowflakeId();
|
||
}
|
||
else
|
||
{
|
||
roleId = role.Id;
|
||
}
|
||
|
||
// 补齐角色-权限关联(只加不删,避免覆盖管理员自定义调整)
|
||
foreach (var permCode in perms)
|
||
{
|
||
if (!permIdByCode.TryGetValue(permCode, out var permId)) continue;
|
||
var linkExists = db.Queryable<RolePermissionEntity>()
|
||
.Where(x => x.RoleId == roleId && x.PermissionId == permId).Any();
|
||
if (!linkExists)
|
||
{
|
||
db.Insertable(new RolePermissionEntity { RoleId = roleId, PermissionId = permId, CreateTime = now }).ExecuteCommand();
|
||
}
|
||
}
|
||
}
|
||
|
||
// 3. 默认管理员账号(admin/admin123,挂在超级管理员角色)
|
||
var adminExists = db.Queryable<UserEntity>().Where(x => x.UserName == "admin" && x.IsDel == 0).Any();
|
||
if (!adminExists)
|
||
{
|
||
var superAdmin = db.Queryable<RoleEntity>().Where(x => x.Code == "superadmin").First();
|
||
var admin = new UserEntity
|
||
{
|
||
UserName = "admin",
|
||
PasswordHash = PasswordHelper.Hash("admin123"),
|
||
RealName = "系统管理员",
|
||
IsEnabled = 1,
|
||
Remark = "系统默认管理员(首次登录后请修改密码)",
|
||
CreateTime = now
|
||
};
|
||
var adminId = db.Insertable(admin).ExecuteReturnSnowflakeId();
|
||
if (superAdmin != null)
|
||
{
|
||
db.Insertable(new UserRoleEntity { UserId = adminId, RoleId = superAdmin.Id, CreateTime = now }).ExecuteCommand();
|
||
}
|
||
}
|
||
|
||
// 4. 系统参数种子(一期 4 个内置参数,幂等:按 ParamKey 跳过已存在)
|
||
SeedSystemParams(db, now);
|
||
|
||
// 5. 默认本地文件存储配置(幂等:仅当无任何配置时插入一条默认 Local 通道)
|
||
SeedDefaultFileStorage(db, now);
|
||
}
|
||
catch (Exception)
|
||
{
|
||
// 种子失败不阻断启动(例如表刚建好并发场景),下次启动会重试
|
||
throw;
|
||
}
|
||
}
|
||
|
||
private static void SeedDefaultFileStorage(SqlSugar.ISqlSugarClient db, DateTime now)
|
||
{
|
||
var hasAny = db.Queryable<FileStorageConfigEntity>().Where(x => x.IsDel == 0).Any();
|
||
if (hasAny) return;
|
||
var entity = new FileStorageConfigEntity
|
||
{
|
||
Provider = "local",
|
||
Name = "本地存储",
|
||
Endpoint = "/uploads",
|
||
AccessKey = null,
|
||
SecretKey = null,
|
||
Bucket = null,
|
||
Region = null,
|
||
BasePath = "wwwroot/uploads",
|
||
MaxSizeMB = 10,
|
||
AllowedExts = null, // 不限制扩展名;如需限制填 [".jpg",".png",".pdf",".xlsx"]
|
||
IsDefault = 1,
|
||
Status = 1,
|
||
Remark = "系统默认本地存储通道(文件落 wwwroot/uploads,通过 /uploads 静态访问)",
|
||
CreateTime = now
|
||
};
|
||
db.Insertable(entity).ExecuteReturnSnowflakeId();
|
||
}
|
||
|
||
/// <summary>一期 4 个内置系统参数(IsSystem=1,禁止删除,仅允许改 Value/Remark)</summary>
|
||
/// <remarks>Group 与 ParamType 约定:0=int,1=text,2=enum,3=json</remarks>
|
||
private static readonly (string Key, string Name, string? Value, byte Type, string? Options, string? Unit, string Group, int Sort, string? Remark)[] SystemParams =
|
||
{
|
||
("data_collect_default_frequency", "数据采集默认频率", "5", 0, null, "秒", "数据采集", 1, "设备数据采集的默认间隔(秒),新建设备时作为默认值"),
|
||
("alert_notify_method", "告警通知方式", "feishu", 2,
|
||
"[{\"value\":\"feishu\",\"label\":\"飞书\"},{\"value\":\"dingtalk\",\"label\":\"钉钉\"},{\"value\":\"wecom\",\"label\":\"企业微信\"},{\"value\":\"email\",\"label\":\"邮件\"}]",
|
||
null, "告警", 2, "默认告警通知渠道(多选需在告警规则内单独配置)"),
|
||
("work_order_code_rule", "工单编号规则", "WO{yyyyMMddHHmmss}", 1, null, null, "工单", 3,
|
||
"工单编号生成模板,支持占位符:{yyyy}年 {MM}月 {dd}日 {HH}时 {mm}分 {ss}秒,序列号用 {seq4} 表示 4 位顺序号"),
|
||
("file_upload_limit", "文件上传限制", "10", 2,
|
||
"[{\"value\":\"5\",\"label\":\"5MB\"},{\"value\":\"10\",\"label\":\"10MB\"},{\"value\":\"20\",\"label\":\"20MB\"},{\"value\":\"50\",\"label\":\"50MB\"}]",
|
||
"MB", "文件", 4, "单个文件上传大小上限(MB)")
|
||
};
|
||
|
||
private static void SeedSystemParams(SqlSugar.ISqlSugarClient db, DateTime now)
|
||
{
|
||
foreach (var (key, name, value, type, options, unit, group, sort, remark) in SystemParams)
|
||
{
|
||
var exists = db.Queryable<SystemParamEntity>().Where(x => x.ParamKey == key).Any();
|
||
if (exists) continue;
|
||
var entity = new SystemParamEntity
|
||
{
|
||
ParamKey = key,
|
||
ParamName = name,
|
||
ParamValue = value,
|
||
ParamType = type,
|
||
ParamOptions = options,
|
||
Unit = unit,
|
||
Group = group,
|
||
Sort = sort,
|
||
Remark = remark,
|
||
IsSystem = 1,
|
||
LastUpdateUser = "system",
|
||
LastUpdateTime = now,
|
||
CreateTime = now
|
||
};
|
||
db.Insertable(entity).ExecuteReturnSnowflakeId();
|
||
}
|
||
}
|
||
}
|
||
}
|