新增MES模块,包含供应商、客户、车辆和地磅数据记录管理功能,支持免密接口和数据同步。更新相关控制器、实体、服务和数据库配置,优化权限管理和数据字典支持,确保系统的灵活性和可扩展性。
This commit is contained in:
@@ -1,13 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using YY.Admin.Core;
|
||||
using YY.Admin.Services;
|
||||
|
||||
namespace YY.Admin.Services.Service.Menu
|
||||
namespace YY.Admin.Services.Service.Menu;
|
||||
|
||||
public interface ISysMenuService
|
||||
{
|
||||
public interface ISysMenuService
|
||||
{
|
||||
Task<List<MenuOutput>> GetLoginMenuTree();
|
||||
}
|
||||
Task<List<MenuOutput>> GetLoginMenuTree();
|
||||
|
||||
/// <summary>
|
||||
/// 菜单管理:加载全部菜单(含按钮类型),按排序与 Id 排序
|
||||
/// </summary>
|
||||
Task<List<SysMenu>> GetAllMenusForManageAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 新增菜单并可选关联当前用户租户
|
||||
/// </summary>
|
||||
Task<(bool ok, string message, long id)> CreateMenuAsync(SysMenu input);
|
||||
|
||||
/// <summary>
|
||||
/// 更新菜单
|
||||
/// </summary>
|
||||
Task<(bool ok, string message)> UpdateMenuAsync(SysMenu input);
|
||||
|
||||
/// <summary>
|
||||
/// 删除菜单(无子节点时)
|
||||
/// </summary>
|
||||
Task<(bool ok, string message)> DeleteMenuAsync(long id);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
using Mapster;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using YY.Admin.Core;
|
||||
using YY.Admin.Core.Session;
|
||||
using YY.Admin.Services.Service.Role;
|
||||
using YY.Admin.Services.Service.User;
|
||||
@@ -132,5 +128,137 @@ namespace YY.Admin.Services.Service.Menu
|
||||
.ToTreeAsync(u => u.Children, u => u.Pid, 0);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<List<SysMenu>> GetAllMenusForManageAsync()
|
||||
{
|
||||
return await _dbContext.Queryable<SysMenu>()
|
||||
.OrderBy(m => m.OrderNo)
|
||||
.OrderBy(m => m.Id)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<(bool ok, string message, long id)> CreateMenuAsync(SysMenu input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input.Title))
|
||||
return (false, "菜单名称不能为空", 0);
|
||||
|
||||
var all = await GetAllMenusForManageAsync();
|
||||
if (input.Pid != 0 && all.All(m => m.Id != input.Pid))
|
||||
return (false, "父级菜单不存在", 0);
|
||||
|
||||
var id = SnowflakeId.Next();
|
||||
input.Id = id;
|
||||
input.CreateTime = DateTime.Now;
|
||||
input.UpdateTime = null;
|
||||
input.Children = new List<SysMenu>();
|
||||
|
||||
var n = await _dbContext.Insertable(input).ExecuteCommandAsync();
|
||||
if (n <= 0)
|
||||
return (false, "保存失败", 0);
|
||||
|
||||
await TryLinkCurrentTenantMenuAsync(id);
|
||||
return (true, "保存成功", id);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<(bool ok, string message)> UpdateMenuAsync(SysMenu input)
|
||||
{
|
||||
if (input.Id <= 0)
|
||||
return (false, "无效的菜单 Id");
|
||||
if (string.IsNullOrWhiteSpace(input.Title))
|
||||
return (false, "菜单名称不能为空");
|
||||
|
||||
var all = await GetAllMenusForManageAsync();
|
||||
var existing = all.FirstOrDefault(m => m.Id == input.Id);
|
||||
if (existing == null)
|
||||
return (false, "菜单不存在");
|
||||
|
||||
if (input.Pid != 0 && all.All(m => m.Id != input.Pid))
|
||||
return (false, "父级菜单不存在");
|
||||
|
||||
if (NewParentIsInsideMenuSubtree(input.Id, input.Pid, all))
|
||||
return (false, "不能将父级设为当前菜单或其子菜单");
|
||||
|
||||
existing.Pid = input.Pid;
|
||||
existing.Type = input.Type;
|
||||
existing.Name = input.Name;
|
||||
existing.Path = input.Path;
|
||||
existing.Component = input.Component;
|
||||
existing.Redirect = input.Redirect;
|
||||
existing.Permission = input.Permission;
|
||||
existing.Title = input.Title.Trim();
|
||||
existing.Icon = input.Icon;
|
||||
existing.IsIframe = input.IsIframe;
|
||||
existing.OutLink = input.OutLink;
|
||||
existing.IsHide = input.IsHide;
|
||||
existing.IsKeepAlive = input.IsKeepAlive;
|
||||
existing.IsAffix = input.IsAffix;
|
||||
existing.OrderNo = input.OrderNo;
|
||||
existing.Status = input.Status;
|
||||
existing.Remark = input.Remark;
|
||||
existing.UpdateTime = DateTime.Now;
|
||||
|
||||
var n = await _dbContext.Updateable(existing).ExecuteCommandAsync();
|
||||
return n > 0 ? (true, "保存成功") : (false, "更新失败");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<(bool ok, string message)> DeleteMenuAsync(long id)
|
||||
{
|
||||
if (id <= 0)
|
||||
return (false, "无效的菜单 Id");
|
||||
|
||||
var childCount = await _dbContext.Queryable<SysMenu>().Where(m => m.Pid == id).CountAsync();
|
||||
if (childCount > 0)
|
||||
return (false, "存在子菜单,请先删除子节点");
|
||||
|
||||
await _dbContext.Deleteable<SysRoleMenu>().Where(r => r.MenuId == id).ExecuteCommandAsync();
|
||||
await _dbContext.Deleteable<SysTenantMenu>().Where(t => t.MenuId == id).ExecuteCommandAsync();
|
||||
var n = await _dbContext.Deleteable<SysMenu>().Where(m => m.Id == id).ExecuteCommandAsync();
|
||||
return n > 0 ? (true, "已删除") : (false, "删除失败");
|
||||
}
|
||||
|
||||
private async Task TryLinkCurrentTenantMenuAsync(long menuId)
|
||||
{
|
||||
var tenantId = AppSession.CurrentUser?.TenantId;
|
||||
if (tenantId == null || tenantId <= 0)
|
||||
return;
|
||||
|
||||
var exists = await _dbContext.Queryable<SysTenantMenu>()
|
||||
.AnyAsync(t => t.TenantId == tenantId && t.MenuId == menuId);
|
||||
if (exists)
|
||||
return;
|
||||
|
||||
await _dbContext.Insertable(new SysTenantMenu
|
||||
{
|
||||
Id = SnowflakeId.Next(),
|
||||
TenantId = tenantId.Value,
|
||||
MenuId = menuId
|
||||
}).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断 newPid 是否位于以 menuId 为根的子树内(含自身),用于防止环状父级
|
||||
/// </summary>
|
||||
private static bool NewParentIsInsideMenuSubtree(long menuId, long newPid, List<SysMenu> all)
|
||||
{
|
||||
if (newPid == 0)
|
||||
return false;
|
||||
if (newPid == menuId)
|
||||
return true;
|
||||
|
||||
var cur = all.FirstOrDefault(x => x.Id == newPid);
|
||||
for (var i = 0; i < 5000 && cur != null; i++)
|
||||
{
|
||||
if (cur.Pid == menuId)
|
||||
return true;
|
||||
if (cur.Pid == 0)
|
||||
return false;
|
||||
cur = all.FirstOrDefault(x => x.Id == cur.Pid);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user