merge 冲突合并

This commit is contained in:
2021-04-28 13:52:10 +08:00
54 changed files with 23287 additions and 91 deletions

View File

@@ -40,5 +40,28 @@ namespace Ewide.Core.Entity
[Comment("排序")] [Comment("排序")]
public int Sort { get; set; } public int Sort { get; set; }
/// <summary>
/// 多个区域有多个用户绑定自定义数据
/// </summary>
public ICollection<SysUser> SysUsers { get; set; }
/// <summary>
/// 中间表
/// </summary>
public List<SysUserArea> SysUserAreas { get; set; }
/// <summary>
/// 多个区域有多个角色绑定权限数据
/// </summary>
public ICollection<SysRole> SysRoles { get; set; }
/// <summary>
/// 中间表
/// </summary>
public List<SysRoleArea> SysRoleAreas { get; set; }
/// <summary>
/// 一个区域有多个组织
/// </summary>
public ICollection<SysOrg> SysOrgs { get; set; }
} }
} }

View File

@@ -1,4 +1,5 @@
using Furion.DatabaseAccessor; using Ewide.Core.Entity;
using Furion.DatabaseAccessor;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System; using System;
@@ -70,6 +71,10 @@ namespace Ewide.Core
/// </summary> /// </summary>
public List<SysRoleDataScope> SysRoleDataScopes { get; set; } public List<SysRoleDataScope> SysRoleDataScopes { get; set; }
public ICollection<AreaNumber> AreaNumbers { get; set; }
public List<SysRoleArea> SysRoleAreas { get; set; }
/// <summary> /// <summary>
/// 多对多(菜单) /// 多对多(菜单)
/// </summary> /// </summary>
@@ -97,7 +102,15 @@ namespace Ewide.Core
{ {
u.HasKey(c => new { c.SysRoleId, c.SysOrgId }); u.HasKey(c => new { c.SysRoleId, c.SysOrgId });
}); });
entityBuilder.HasMany(p => p.AreaNumbers)
.WithMany(p => p.SysRoles)
.UsingEntity<SysRoleArea>(
u => u.HasOne(c => c.AreaNumber).WithMany(c => c.SysRoleAreas).HasForeignKey(c => c.AreaNumberCode),
u => u.HasOne(c => c.SysRole).WithMany(c => c.SysRoleAreas).HasForeignKey(c => c.SysRoleId),
u =>
{
u.HasKey(c => new { c.SysRoleId, c.AreaNumberCode });
});
entityBuilder.HasMany(p => p.SysMenus) entityBuilder.HasMany(p => p.SysMenus)
.WithMany(p => p.SysRoles) .WithMany(p => p.SysRoles)
.UsingEntity<SysRoleMenu>( .UsingEntity<SysRoleMenu>(

View File

@@ -1,4 +1,5 @@
using Furion.DatabaseAccessor; using Ewide.Core.Entity;
using Furion.DatabaseAccessor;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System; using System;
@@ -127,6 +128,11 @@ namespace Ewide.Core
/// </summary> /// </summary>
public List<SysUserDataScope> SysUserDataScopes { get; set; } public List<SysUserDataScope> SysUserDataScopes { get; set; }
public ICollection<AreaNumber> AreaNumbers { get; set; }
/// <summary>
/// 多对多中间表(用户-区域 数据范围)
/// </summary>
public List<SysUserArea> SysUserAreas { get; set; }
/// <summary> /// <summary>
/// 配置多对多关系 /// 配置多对多关系
/// </summary> /// </summary>
@@ -150,6 +156,13 @@ namespace Ewide.Core
{ {
u.HasKey(c => new { c.SysUserId, c.SysOrgId }); u.HasKey(c => new { c.SysUserId, c.SysOrgId });
}); });
entityBuilder.HasMany(p => p.AreaNumbers).WithMany(p => p.SysUsers).UsingEntity<SysUserArea>(
u => u.HasOne(c => c.AreaNumber).WithMany(c => c.SysUserAreas).HasForeignKey(c => c.AreaNumberCode),
u => u.HasOne(c => c.SysUser).WithMany(c => c.SysUserAreas).HasForeignKey(c => c.SysUserId),
u =>
{
u.HasKey(c => new { c.SysUserId, c.AreaNumberCode });
});
} }
} }
} }

View File

@@ -303,6 +303,31 @@
验证码缓存 验证码缓存
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Entity.AreaNumber.SysUsers">
<summary>
多个区域有多个用户绑定自定义数据
</summary>
</member>
<member name="P:Ewide.Core.Entity.AreaNumber.SysUserAreas">
<summary>
中间表
</summary>
</member>
<member name="P:Ewide.Core.Entity.AreaNumber.SysRoles">
<summary>
多个区域有多个角色绑定权限数据
</summary>
</member>
<member name="P:Ewide.Core.Entity.AreaNumber.SysRoleAreas">
<summary>
中间表
</summary>
</member>
<member name="P:Ewide.Core.Entity.AreaNumber.SysOrgs">
<summary>
一个区域有多个组织
</summary>
</member>
<member name="P:Ewide.Core.Entity.SysRoleArea.SysRoleId"> <member name="P:Ewide.Core.Entity.SysRoleArea.SysRoleId">
<summary> <summary>
角色Id 角色Id
@@ -1683,6 +1708,11 @@
多对多中间表(用户-机构 数据范围) 多对多中间表(用户-机构 数据范围)
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.SysUser.SysUserAreas">
<summary>
多对多中间表(用户-区域 数据范围)
</summary>
</member>
<member name="M:Ewide.Core.SysUser.Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder{Ewide.Core.SysUser},Microsoft.EntityFrameworkCore.DbContext,System.Type)"> <member name="M:Ewide.Core.SysUser.Configure(Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder{Ewide.Core.SysUser},Microsoft.EntityFrameworkCore.DbContext,System.Type)">
<summary> <summary>
配置多对多关系 配置多对多关系
@@ -2432,6 +2462,11 @@
授权数据 授权数据
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.XnInputBase.GrantAreaCodeList">
<summary>
授权区域
</summary>
</member>
<member name="T:Ewide.Core.PageInputBase"> <member name="T:Ewide.Core.PageInputBase">
<summary> <summary>
通用分页输入参数 通用分页输入参数
@@ -5508,10 +5543,11 @@
上一级Id 上一级Id
</summary> </summary>
</member> </member>
<member name="M:Ewide.Core.Service.ISysOrgService.GetAreaDataScopeIdList(System.String)"> <member name="M:Ewide.Core.Service.ISysOrgService.GetAreaDataScopeIdList(System.Int32,System.String)">
<summary> <summary>
根据区域信息获取单位id 根据区域信息获取单位id
</summary> </summary>
<param name="dataScopeType">代表区域范围的类型</param>
<param name="areaNumberCode">区域代码</param> <param name="areaNumberCode">区域代码</param>
<returns></returns> <returns></returns>
</member> </member>

View File

@@ -21,6 +21,10 @@ namespace Ewide.Core
/// 授权数据 /// 授权数据
/// </summary> /// </summary>
public virtual List<string> GrantOrgIdList { get; set; } = new List<string>(); public virtual List<string> GrantOrgIdList { get; set; } = new List<string>();
/// <summary>
/// 授权区域
/// </summary>
public virtual List<string> GrantAreaCodeList { get; set; } = new List<string>();
} }
/// <summary> /// <summary>

View File

@@ -0,0 +1,52 @@
using Ewide.Core.Entity;
using Ewide.Core.Service.Area.Dto;
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ewide.Core.Service.Area
{
public class AreaNumberService : IAreaNumberService, ITransient
{
private readonly IRepository<AreaNumber> _areaNumberRep;
private readonly ISysCacheService _sysCacheService;
public AreaNumberService(IRepository<AreaNumber> areaNumberRep, ISysCacheService sysCacheService)
{
_areaNumberRep = areaNumberRep;
_sysCacheService = sysCacheService;
}
public async Task AddAreaNumber(AreaNumberInput input)
{
await _areaNumberRep.InsertAsync(input.Adapt<AreaNumber>());
}
public async Task DeleteAreaNumber(DeleteAreaNumberInput input)
{
var areaNumber= await _areaNumberRep.FirstOrDefaultAsync(p=>p.Code==input.Code);
await areaNumber.DeleteAsync();
}
public async Task<AreaNumber> GetAreaNumber(string code)
{
return await _areaNumberRep.DetachedEntities.FirstOrDefaultAsync(a => a.Code == code);
}
public async Task<List<AreaNumber>> GetAreaNumberWithChildren(string code)
{
return await _areaNumberRep.DetachedEntities.Where(a => a.Code.StartsWith(code)).ToListAsync();
}
public async Task UpdateAreaNumber(AreaNumberInput input)
{
await _areaNumberRep.UpdateAsync(input.Adapt<AreaNumber>());
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ewide.Core.Service.Area.Dto
{
public class AreaNumberInput
{
public string Code { get; set; }
public string ShowCode { get; set; }
public string Name { get; set; }
public int LevelType { get; set; }
public string Note { get; set; }
public int Sort { get; set; }
}
public class DeleteAreaNumberInput
{
[Required(ErrorMessage ="区域代码不可为空")]
public string Code { get; set; }
}
}

View File

@@ -0,0 +1,19 @@
using Ewide.Core.Entity;
using Ewide.Core.Service.Area.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ewide.Core.Service.Area
{
public interface IAreaNumberService
{
Task AddAreaNumber(AreaNumberInput input);
Task DeleteAreaNumber(DeleteAreaNumberInput input);
Task UpdateAreaNumber(AreaNumberInput input);
Task<AreaNumber> GetAreaNumber(string code);
Task<List<AreaNumber>> GetAreaNumberWithChildren(string code);
}
}

View File

@@ -18,9 +18,10 @@ namespace Ewide.Core.Service
/// <summary> /// <summary>
/// 根据区域信息获取单位id /// 根据区域信息获取单位id
/// </summary> /// </summary>
/// <param name="dataScopeType">代表区域范围的类型</param>
/// <param name="areaNumberCode">区域代码</param> /// <param name="areaNumberCode">区域代码</param>
/// <returns></returns> /// <returns></returns>
Task<List<string>> GetAreaDataScopeIdList(string areaNumberCode); Task<List<string>> GetAreaDataScopeIdList(int dataScopeType,string areaNumberCode);
/// <summary> /// <summary>
/// 当前区域信息不包括子区域 /// 当前区域信息不包括子区域
/// </summary> /// </summary>

View File

@@ -346,11 +346,15 @@ namespace Ewide.Core.Service
return await App.GetService<ISysUserService>().GetUserDataScopeIdList(); return await App.GetService<ISysUserService>().GetUserDataScopeIdList();
} }
public async Task<List<string>> GetAreaDataScopeIdList(string areaNumberCode) public async Task<List<string>> GetAreaDataScopeIdList(int dataScopeType, string orgId)
{ {
return await _sysOrgRep.DetachedEntities.Where(p => p.AreaNumberCode.StartsWith(areaNumberCode)).Select(p=>p.Id).ToListAsync(); var org = await _sysOrgRep.FirstOrDefaultAsync(o => o.Id == orgId);
if (dataScopeType == (int)DataScopeType.AREA_WITH_CHILD)
return await _sysOrgRep.DetachedEntities.Where(p => p.AreaNumberCode.StartsWith(org.Code)).Select(p => p.Id).ToListAsync();
if (dataScopeType == (int)DataScopeType.AREA)
return await _sysOrgRep.DetachedEntities.Where(p => p.AreaNumberCode == org.Code).Select(p => p.Id).ToListAsync();
return new List<string>();
} }
public async Task<List<string>> GetAreaDataScopeIdListWithoutChildrenArea(string areaNumberCode) public async Task<List<string>> GetAreaDataScopeIdListWithoutChildrenArea(string areaNumberCode)
{ {
return await _sysOrgRep.DetachedEntities.Where(p => p.AreaNumberCode == areaNumberCode).Select(p => p.Id).ToListAsync(); return await _sysOrgRep.DetachedEntities.Where(p => p.AreaNumberCode == areaNumberCode).Select(p => p.Id).ToListAsync();

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ewide.Core.Service.Role
{
public interface ISysRoleAreaService
{
Task DeleteRoleAreaListByAreaCodeList(List<string> areaCodeList);
Task DeleteRoleAreaListByRoleId(string roleId);
Task<List<string>> GetRoleAreaCodeList(List<string> roleIdList);
Task GrantArea(UpdateRoleInput input);
}
}

View File

@@ -0,0 +1,66 @@
using Ewide.Core.Entity;
using Ewide.Core.Service.User;
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ewide.Core.Service.Role
{
public class SysRoleAreaService : ISysRoleAreaService,ITransient
{
public readonly IRepository<SysRoleArea> _sysRoleAreaRep;
public SysRoleAreaService(IRepository<SysRoleArea> sysRolleAreaRep)
{
_sysRoleAreaRep = sysRolleAreaRep;
}
public async Task DeleteRoleAreaListByAreaCodeList(List<string> areaCodeList)
{
var dataScopes = await _sysRoleAreaRep.DetachedEntities.Where(u => areaCodeList.Contains(u.AreaNumberCode)).ToListAsync();
dataScopes.ForEach(u =>
{
u.Delete();
});
}
public async Task DeleteRoleAreaListByRoleId(string roleId)
{
var dataScopes = await _sysRoleAreaRep.DetachedEntities.Where(u => roleId==u.SysRoleId).ToListAsync();
dataScopes.ForEach(u =>
{
u.Delete();
});
}
public async Task<List<string>> GetRoleAreaCodeList(List<string> roleIdList)
{
return await _sysRoleAreaRep.DetachedEntities.Where(u => roleIdList.Contains(u.SysRoleId)).Select(u=>u.AreaNumberCode).Distinct().ToListAsync();
}
public async Task GrantArea(UpdateRoleInput input)
{
var dataScopes = await _sysRoleAreaRep.Where(u => u.SysRoleId == input.Id).ToListAsync();
dataScopes.ForEach(u =>
{
u.Delete();
});
input.GrantAreaCodeList.ForEach(u =>
{
new SysRoleArea
{
SysRoleId = input.Id,
AreaNumberCode = u
}.Insert();
});
}
}
}

View File

@@ -243,6 +243,7 @@ namespace Ewide.Core.Service
{ {
// 定义角色中最大数据范围的类型目前按最大范围策略来如果你同时拥有ALL和SELF的权限最后按ALL返回 // 定义角色中最大数据范围的类型目前按最大范围策略来如果你同时拥有ALL和SELF的权限最后按ALL返回
int strongerDataScopeType = (int)DataScopeType.SELF; int strongerDataScopeType = (int)DataScopeType.SELF;
int strongerAreaType = (int)DataScopeType.SELF;
var customDataScopeRoleIdList = new List<string>(); var customDataScopeRoleIdList = new List<string>();
if (roleIdList != null && roleIdList.Count > 0) if (roleIdList != null && roleIdList.Count > 0)
@@ -252,6 +253,10 @@ namespace Ewide.Core.Service
{ {
if (u.DataScopeType == (int)DataScopeType.DEFINE) if (u.DataScopeType == (int)DataScopeType.DEFINE)
customDataScopeRoleIdList.Add(u.Id); customDataScopeRoleIdList.Add(u.Id);
if ((u.DataScopeType == (int)DataScopeType.AREA || u.DataScopeType == (int)DataScopeType.AREA_WITH_CHILD) && strongerAreaType < u.DataScopeType)
{
strongerDataScopeType = u.DataScopeType;
}
else if (u.DataScopeType <= strongerDataScopeType) else if (u.DataScopeType <= strongerDataScopeType)
strongerDataScopeType = u.DataScopeType; strongerDataScopeType = u.DataScopeType;
}); });
@@ -262,8 +267,9 @@ namespace Ewide.Core.Service
// 角色中拥有最大数据范围类型的数据范围 // 角色中拥有最大数据范围类型的数据范围
var dataScopeIdList = await _sysOrgService.GetDataScopeListByDataScopeType(strongerDataScopeType, orgId); var dataScopeIdList = await _sysOrgService.GetDataScopeListByDataScopeType(strongerDataScopeType, orgId);
//角色区域数据范围
return roleDataScopeIdList.Concat(dataScopeIdList).Distinct().ToList(); //并集 var areaOrgIdList = await _sysOrgService.GetAreaDataScopeIdList(strongerAreaType, orgId);
return roleDataScopeIdList.Concat(dataScopeIdList).Concat(areaOrgIdList).Distinct().ToList(); //并集
} }
/// <summary> /// <summary>

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ewide.Core.Service.Role
{
public interface ISysUserAreaService
{
Task DeleteUserAreaListByAreaCodeList(List<string> areaCodeList);
Task DeleteUserAreaListByUserId(string userId);
Task<List<string>> GetUserAreaIdList(string userId);
Task GrantData(UpdateUserInput input);
}
}

View File

@@ -0,0 +1,65 @@
using Ewide.Core.Entity;
using Ewide.Core.Service.Role;
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ewide.Core.Service.User
{
public class SysUserAreaService : ISysUserAreaService,ITransient
{
public readonly IRepository<SysUserArea> _sysUserAreaRep;
public SysUserAreaService(IRepository<SysUserArea> sysUserAreaRep)
{
_sysUserAreaRep = sysUserAreaRep;
}
public async Task DeleteUserAreaListByAreaCodeList(List<string> areaCodeList)
{
var areaList = await _sysUserAreaRep.DetachedEntities.Where(ua => areaCodeList.Contains(ua.AreaNumberCode)).ToListAsync();
foreach (var area in areaList)
{
area.Delete();
}
}
public async Task DeleteUserAreaListByUserId(string userId)
{
var areaList = await _sysUserAreaRep.DetachedEntities.Where(ua => ua.SysUserId == userId).ToListAsync();
foreach (var area in areaList)
{
area.Delete();
}
}
public async Task<List<string>> GetUserAreaIdList(string userId)
{
return await _sysUserAreaRep.DetachedEntities.Where(ua => ua.SysUserId == userId).Select(ua => ua.AreaNumberCode).ToListAsync();
}
public async Task GrantData(UpdateUserInput input)
{
var dataScopes = await _sysUserAreaRep.Where(u => u.SysUserId == input.Id).ToListAsync();
dataScopes.ForEach(u =>
{
u.Delete();
});
input.GrantAreaCodeList.ForEach(u =>
{
new SysUserArea
{
SysUserId = input.Id,
AreaNumberCode = u
}.Insert();
});
}
}
}

View File

@@ -1,4 +1,5 @@
using Furion.DatabaseAccessor; using Ewide.Core.Entity;
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions; using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection; using Furion.DependencyInjection;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@@ -14,10 +15,13 @@ namespace Ewide.Core.Service
public class SysUserDataScopeService : ISysUserDataScopeService, ITransient public class SysUserDataScopeService : ISysUserDataScopeService, ITransient
{ {
private readonly IRepository<SysUserDataScope> _sysUserDataScopeRep; // 用户数据范围表仓储 private readonly IRepository<SysUserDataScope> _sysUserDataScopeRep; // 用户数据范围表仓储
private readonly IRepository<SysUserArea> _sysUserAreaRep;
public SysUserDataScopeService(IRepository<SysUserDataScope> sysUserDataScopeRep) private readonly IRepository<SysOrg> _sysOrgRep;
public SysUserDataScopeService(IRepository<SysUserDataScope> sysUserDataScopeRep, IRepository<SysUserArea> sysUserAreaRep, IRepository<SysOrg> sysOrgRep)
{ {
_sysUserDataScopeRep = sysUserDataScopeRep; _sysUserDataScopeRep = sysUserDataScopeRep;
_sysUserAreaRep = sysUserAreaRep;
_sysOrgRep = sysOrgRep;
} }
/// <summary> /// <summary>
@@ -51,9 +55,18 @@ namespace Ewide.Core.Service
/// <returns></returns> /// <returns></returns>
public async Task<List<string>> GetUserDataScopeIdList(string userId) public async Task<List<string>> GetUserDataScopeIdList(string userId)
{ {
return await _sysUserDataScopeRep.DetachedEntities var areaList = await _sysUserAreaRep.DetachedEntities.Where(u => u.SysUserId == userId).Select(u => u.AreaNumberCode).ToListAsync();
//用户自定义的区域权限所对应的全部组织机构id
List<string> areaDataScopeIdList = new List<string>();
foreach (var areaNumberCode in areaList)
{
areaDataScopeIdList.AddRange(await _sysOrgRep.DetachedEntities.Where(p => p.AreaNumberCode == areaNumberCode).Select(p => p.Id).ToListAsync());
}
//用户自定义的组织权限
var orgIdList = await _sysUserDataScopeRep.DetachedEntities
.Where(u => u.SysUserId == userId) .Where(u => u.SysUserId == userId)
.Select(u => u.SysOrgId).ToListAsync(); .Select(u => u.SysOrgId).ToListAsync();
return areaDataScopeIdList.Concat(orgIdList).Distinct().ToList();
} }
/// <summary> /// <summary>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Ewide.Database.Migrations.Migrations
{
public partial class addAreaNumberRelation : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "AreaNumberCode",
table: "sys_org",
type: "varchar(10) CHARACTER SET utf8mb4",
nullable: true,
comment: "组织所在区域代码");
migrationBuilder.AddColumn<int>(
name: "UnbindParent",
table: "sys_menu",
type: "int",
nullable: false,
defaultValue: 0,
comment: "不关联菜单显示");
migrationBuilder.CreateIndex(
name: "IX_sys_org_AreaNumberCode",
table: "sys_org",
column: "AreaNumberCode");
migrationBuilder.AddForeignKey(
name: "FK_sys_org_ewide_area_number_AreaNumberCode",
table: "sys_org",
column: "AreaNumberCode",
principalTable: "ewide_area_number",
principalColumn: "Code",
onDelete: ReferentialAction.Restrict);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_sys_org_ewide_area_number_AreaNumberCode",
table: "sys_org");
migrationBuilder.DropIndex(
name: "IX_sys_org_AreaNumberCode",
table: "sys_org");
migrationBuilder.DropColumn(
name: "AreaNumberCode",
table: "sys_org");
migrationBuilder.DropColumn(
name: "UnbindParent",
table: "sys_menu");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,79 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Ewide.Database.Migrations.Migrations
{
public partial class areaCodemanytomany : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "sys_role_area",
columns: table => new
{
SysRoleId = table.Column<string>(type: "varchar(36)", nullable: false, comment: "角色Id"),
AreaNumberCode = table.Column<string>(type: "varchar(10) CHARACTER SET utf8mb4", maxLength: 10, nullable: false, comment: "系统使用的区域代码")
},
constraints: table =>
{
table.PrimaryKey("PK_sys_role_area", x => new { x.SysRoleId, x.AreaNumberCode });
table.ForeignKey(
name: "FK_sys_role_area_ewide_area_number_AreaNumberCode",
column: x => x.AreaNumberCode,
principalTable: "ewide_area_number",
principalColumn: "Code",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_sys_role_area_sys_role_SysRoleId",
column: x => x.SysRoleId,
principalTable: "sys_role",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
},
comment: "角色区域自定义数据");
migrationBuilder.CreateTable(
name: "sys_user_area",
columns: table => new
{
SysUserId = table.Column<string>(type: "varchar(36)", nullable: false, comment: "用户Id"),
AreaNumberCode = table.Column<string>(type: "varchar(10) CHARACTER SET utf8mb4", maxLength: 10, nullable: false, comment: "系统使用的区域代码")
},
constraints: table =>
{
table.PrimaryKey("PK_sys_user_area", x => new { x.SysUserId, x.AreaNumberCode });
table.ForeignKey(
name: "FK_sys_user_area_ewide_area_number_AreaNumberCode",
column: x => x.AreaNumberCode,
principalTable: "ewide_area_number",
principalColumn: "Code",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_sys_user_area_sys_user_SysUserId",
column: x => x.SysUserId,
principalTable: "sys_user",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
},
comment: "用户授权区域信息");
migrationBuilder.CreateIndex(
name: "IX_sys_role_area_AreaNumberCode",
table: "sys_role_area",
column: "AreaNumberCode");
migrationBuilder.CreateIndex(
name: "IX_sys_user_area_AreaNumberCode",
table: "sys_user_area",
column: "AreaNumberCode");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "sys_role_area");
migrationBuilder.DropTable(
name: "sys_user_area");
}
}
}

View File

@@ -13,6 +13,7 @@
"core-js": "^3.6.5", "core-js": "^3.6.5",
"crypto-js": "^4.0.0", "crypto-js": "^4.0.0",
"echarts": "^5.0.2", "echarts": "^5.0.2",
"highlight.js": "^10.7.2",
"less": "^3.12.2", "less": "^3.12.2",
"less-loader": "4.1.0", "less-loader": "4.1.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
@@ -20,6 +21,7 @@
"swiper": "^6.5.0", "swiper": "^6.5.0",
"vue": "^2.6.11", "vue": "^2.6.11",
"vue-awesome-swiper": "^4.1.1", "vue-awesome-swiper": "^4.1.1",
"vue-highlight.js": "^3.1.0",
"vue-router": "^3.5.1" "vue-router": "^3.5.1"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -0,0 +1,78 @@
<template>
<a-modal
:confirmLoading="confirmLoading"
:visible="visible"
@cancel="onCancel"
@ok="onOk"
class="yo-modal-form"
title="新增XX"
>
<FormBody ref="form-body" />
</a-modal>
</template>
<script>
import FormBody from './form';
export default {
components: {
FormBody,
},
data() {
return {
visible: false,
confirmLoading: false,
};
},
computed: {
formBody() {
return this.$refs['form-body'];
},
},
methods: {
/**
* 必要的方法
* 从外部调用打开本窗口
*/
async onOpen() {
this.visible = true;
this.$nextTick(() => {
this.formBody.onInit();
});
},
/**
* 必要的方法
* 点击保存时的操作
*/
onOk() {
this.formBody.onGetData().then((data) => {
this.confirmLoading = true;
this.$api
/** !!此处必须修改调用的接口方法 */
.testAddApi(data)
.then(({ success }) => {
if (success) {
this.$message.success('新增成功');
this.onCancel();
this.$emit('ok');
}
})
.finally(() => {
this.confirmLoading = false;
});
});
},
/**
* 必要的方法
* 关闭窗口时的操作
*/
onCancel() {
this.formBody.onResetFields();
this.visible = false;
},
},
};
</script>

View File

@@ -0,0 +1,79 @@
<template>
<a-modal
:confirmLoading="confirmLoading"
:visible="visible"
@cancel="onCancel"
@ok="onOk"
class="yo-modal-form"
title="编辑XX"
>
<FormBody ref="form-body" />
</a-modal>
</template>
<script>
import FormBody from './form';
export default {
components: {
FormBody,
},
data() {
return {
visible: false,
confirmLoading: false,
};
},
computed: {
formBody() {
return this.$refs['form-body'];
},
},
methods: {
/**
* 必要的方法
* 从外部调用打开本窗口,并填充外部传入的数据
*/
onOpen(record) {
this.visible = true;
this.$nextTick(async () => {
await this.formBody.onInit();
this.formBody.onFillData(record);
});
},
/**
* 必要的方法
* 点击保存时的操作
*/
onOk() {
this.formBody.onGetData().then((data) => {
this.confirmLoading = true;
this.$api
/** !!此处必须修改调用的接口方法 */
.testEditApi(data)
.then(({ success }) => {
if (success) {
this.$message.success('编辑成功');
this.onCancel();
this.$emit('ok');
}
})
.finally(() => {
this.confirmLoading = false;
});
});
},
/**
* 必要的方法
* 关闭窗口时的操作
*/
onCancel() {
this.formBody.onResetFields();
this.visible = false;
},
},
};
</script>

View File

@@ -0,0 +1,100 @@
<template>
<a-form-model :model="form" :rules="rules" class="yo-form" ref="form">
<a-spin :spinning="loading">
<a-icon slot="indicator" spin type="loading" />
<div class="yo-form-group">
<!-- 表单控件 -->
</div>
</a-spin>
</a-form-model>
</template>
<script>
export default {
data() {
return {
/** 表单数据 */
form: {},
/** 验证格式 */
rules: {},
/** 加载异步数据状态 */
loading: false,
/** 其他成员属性 */
/** ... */
};
},
methods: {
/**
* 必要的方法
* 在打开编辑页时允许填充数据
*/
onFillData(record) {
/** 将默认数据覆盖到form */
this.form = this.$_.cloneDeep({
...record,
/** 在此处添加默认数据转换 */
/** ... */
});
},
/**
* 必要方法
* 验证表单并获取表单数据
*/
onGetData() {
return new Promise((reslove, reject) => {
this.$refs.form.validate((valid) => {
if (valid) {
const record = this.$_.cloneDeep(this.form);
/** 验证通过后可以对数据进行转换得到想要提交的格式 */
/** ... */
reslove(record);
} else {
reject();
}
});
});
},
/**
* 必要的方法
* 在外部窗口进行保存时调用表单验证
*/
onValidate(callback) {
this.$refs.form.validate(callback);
},
/**
* 必要的方法
* 在外部窗口关闭或重置时对表单验证进行初始化
*/
onResetFields() {
setTimeout(() => {
this.$refs.form.resetFields();
/** 在这里可以初始化当前组件中其他属性 */
/** ... */
}, 300);
},
/**
* 必要方法
* 加载当前表单中所需要的异步数据
*/
async onInit() {
this.loading = true;
/** 可以在这里await获取一些异步数据 */
/** ...BEGIN */
/** ...END */
this.loading = false;
},
/** 当前组件的其他方法 */
/** ... */
},
};
</script>

View File

@@ -0,0 +1,189 @@
<template>
<container>
<br />
<a-card :bordered="false">
<Auth auth="authCode:page">
<div class="yo-query-bar">
<a-form-model :model="query" layout="inline">
<!-- 此处添加查询表单控件 -->
<a-form-model-item>
<a-button-group>
<a-button @click="onQuery" type="primary">查询</a-button>
<a-button @click="onResetQuery">重置</a-button>
</a-button-group>
</a-form-model-item>
</a-form-model>
</div>
</Auth>
<yo-table :columns="columns" :load-data="loadData" ref="table">
<Auth auth="authCode:add" slot="operator">
<a-button @click="onOpen('add-form')" icon="plus">新增XX</a-button>
</Auth>
<!-- 格式化字段内容 -->
<!-- 添加操作控件 -->
<span slot="action" slot-scope="text, record">
<yo-table-actions>
<Auth auth="authCode:edit">
<a @click="onOpen('edit-form', record)">编辑</a>
</Auth>
<Auth auth="authCode:delete">
<a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除">
<a>删除</a>
</a-popconfirm>
</Auth>
<!-- 可在此处添加其他操作控件 -->
</yo-table-actions>
</span>
</yo-table>
</a-card>
<br />
<add-form @ok="onReloadData" ref="add-form" />
<edit-form @ok="onReloadData" ref="edit-form" />
</container>
</template>
<script>
import AddForm from './addForm';
import EditForm from './editForm';
export default {
components: {
AddForm,
EditForm,
},
data() {
return {
query: {},
columns: [],
codes: {
code1: [],
code2: [],
},
};
},
created() {
this.onLoadCodes();
/** 根据权限添加操作列 */
const flag = this.$auth(/** ... */);
if (flag) {
this.columns.push({
title: '操作',
width: '150px',
dataIndex: 'action',
scopedSlots: { customRender: 'action' },
});
}
},
methods: {
/**
* 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构
*/
loadData(params) {
return (
this.$api
/** !!此处必须修改调用的接口方法 */
.testGetApi({
...params,
...this.query,
})
.then((res) => {
return res.data;
})
);
},
/**
* 有查询功能时的必要方法
* 加载数据时初始化分页信息
*/
onQuery() {
this.$refs.table.onReloadData(true);
},
/**
* 有查询功能时的必要方法
* 重置查询条件
*/
onResetQuery() {
/** 在这里重置查询条件时,可对特殊的字段做保留处理 */
this.query = {};
this.onQuery();
},
/**
* 必要方法
* 重新列表数据
*/
onReloadData() {
this.$refs.table.onReloadData();
},
/**
* 必要方法
* 加载字典数据
* 如果不需要获取相应的字典数据,此方法内容可空
*/
onLoadCodes() {
this.$api
.$queue([
this.$api.sysDictTypeDropDownWait({ code: 'code1' }),
this.$api.sysDictTypeDropDownWait({ code: 'code2' }),
])
.then(([code1, code2]) => {
this.codes.code1 = code1.data;
this.codes.code2 = code2.data;
});
},
/**
* 必要方法
* 绑定数据字典值
*/
bindCodeValue(code, name) {
const c = this.codes[name].find((p) => p.code == code);
if (c) {
return c.value;
}
return null;
},
/**
* 必要方法
* 从列表页调用窗口的打开方法
*/
onOpen(formName, record) {
this.$refs[formName].onOpen(record);
},
/**
* 必要方法
* 可以用做一系列操作的公共回调,此方法中会重新加载当前列表
*/
onResult(success, successMessage) {
if (success) {
this.$message.success(successMessage);
this.onReloadData();
}
},
/**
* 必要方法
* 删除时调用
*/
onDelete(record) {
this.$refs.table.onLoading();
this.$api
/** !!此处必须修改调用的接口方法 */
.testDeleteApi(record)
.then(({ success }) => {
this.onResult(success, '删除成功');
})
.finally(() => {
this.$refs.table.onLoaded();
});
},
},
};
</script>

View File

@@ -0,0 +1,9 @@
{
"seed-index.vue": {
"prefix": "seed.index",
"body": [
"<template>",
"</template>"
]
}
}

View File

@@ -9,10 +9,6 @@
<script> <script>
import zh_CN from 'ant-design-vue/es/locale/zh_CN'; import zh_CN from 'ant-design-vue/es/locale/zh_CN';
import moment from 'moment';
import 'moment/locale/zh-cn';
moment.locale('zh-cn');
export default { export default {
name: 'App', name: 'App',
data() { data() {

View File

@@ -1 +1,25 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
h1,
.h1 {
font-size: 36px;
}
h2,
.h2 {
font-size: 32px;
}
h3,
.h3 {
font-size: 24px;
}
h4,
.h4 {
font-size: 18px;
}
h5,
.h5 {
font-size: 14px;
}
h6,
.h6 {
font-size: 12px;
}

View File

@@ -1,17 +0,0 @@
body {
font-weight: 100;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 300;
}
.ant-card-meta-title {
font-weight: inherit;
}
.ant-table-thead > tr > th {
font-weight: 500;
}

View File

@@ -1,30 +1,20 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
.ant-modal-content { .ant-modal-content {
background-color: fade(@primary-color, 20%); background-color: fade(@white, 90%);
backdrop-filter: blur(10px); backdrop-filter: blur(5px);
} }
.ant-modal-header { .ant-modal-header {
padding: @padding-sm @padding-md; padding: @padding-sm @padding-md;
background-color: transparent; background-color: transparent;
} }
.ant-modal-title {
color: fade(@white, 85%);
}
.ant-modal-body { .ant-modal-body {
background-color: @white; background-color: @white;
} }
.ant-modal-footer { .ant-modal-footer {
background-color: @white; background-color: @white;
} }
.ant-modal-close {
color: fade(@white, 45%);
&:focus,
&:hover {
color: fade(@white, 75%);
}
}
.ant-modal-close-x { .ant-modal-close-x {
line-height: 46px; line-height: 46px;

View File

@@ -29,7 +29,7 @@
} }
.swiper-container { .swiper-container {
position: absolute; position: absolute;
top: @layout-header-height - 20px; top: @layout-header-height;
left: 0; left: 0;
bottom: 0; bottom: 0;
@@ -38,6 +38,32 @@
height: auto; height: auto;
min-height: 100%; min-height: 100%;
} }
.swiper-scrollbar {
transition: @animation-duration-slow opacity;
opacity: 0;
}
&:hover {
.swiper-scrollbar {
opacity: 1;
}
}
}
}
&--bar {
line-height: 20px;
height: 20px;
padding: 0 @padding-md;
text-align: right;
>.anticon {
cursor: pointer;
color: fade(@black, 50%);
&:hover {
color: fade(@black, 80%);
}
} }
} }
} }

View File

@@ -1,5 +1,14 @@
<template> <template>
<section :class="$root.global.settings.container || 'container-fluid'"> <section :class="mode || $root.global.settings.container || 'container-fluid'">
<slot /> <slot />
</section> </section>
</template> </template>
<script>
export default {
props: {
mode: {
type: String,
},
},
};
</script>

View File

@@ -122,6 +122,10 @@ export default {
this.onUpdateSwiper() this.onUpdateSwiper()
}, },
onUnexpandAll() {
this.expandedKeys = []
},
onSearch(value) { onSearch(value) {
const expandedKeys = this.list const expandedKeys = this.list
.map(p => { .map(p => {
@@ -136,6 +140,10 @@ export default {
this.expandedKeys = expandedKeys this.expandedKeys = expandedKeys
this.autoExpandParent = true this.autoExpandParent = true
this.$nextTick(() => {
this.onUpdateSwiper()
})
}, },
onSelect(selectedKeys) { onSelect(selectedKeys) {
@@ -238,6 +246,11 @@ export default {
<a-input-search allowClear={true} placeholder="请输入检索关键字" onSearch={this.onSearch} /> <a-input-search allowClear={true} placeholder="请输入检索关键字" onSearch={this.onSearch} />
</div> </div>
</a-layout-header> </a-layout-header>
<div class="yo-tree-layout--bar">
<a-tooltip placement="bottom" title="折叠全部">
<a-icon type="switcher" onClick={this.onUnexpandAll} />
</a-tooltip>
</div>
<div class="swiper-container" ref="swiper"> <div class="swiper-container" ref="swiper">
<div class="swiper-wrapper"> <div class="swiper-wrapper">
<div class="swiper-slide"> <div class="swiper-slide">

View File

@@ -25,6 +25,10 @@ import getAwesomeSwiper from 'vue-awesome-swiper/dist/exporter'
SwiperClass.use([Pagination, Mousewheel, Autoplay, Scrollbar]) SwiperClass.use([Pagination, Mousewheel, Autoplay, Scrollbar])
Vue.use(getAwesomeSwiper(SwiperClass)) Vue.use(getAwesomeSwiper(SwiperClass))
import hljs from 'highlight.js'
import 'highlight.js/styles/vs2015.css'
Vue.use(hljs.vuePlugin);
/** /**
* api全局化 * api全局化
*/ */
@@ -36,7 +40,30 @@ Vue.prototype.$api = api
*/ */
import _ from 'lodash' import _ from 'lodash'
Vue.prototype.$_ = _ Vue.prototype.$_ = _
/**
* moment全局化
*/
import moment from 'moment'
import 'moment/locale/zh-cn'
moment.updateLocale('zh-cn', {
meridiem: function (hour, minute, isLowercase) {
if (hour < 9) {
return '早上'
} else if (hour < 11) {
return '上午'
} else if (hour < 13) {
return '中午'
} else if (hour < 18) {
return '下午'
} else {
return '晚上'
}
}
})
Vue.prototype.$moment = moment
/**
* 权限验证全局化
*/
import { auth } from './components/authorized' import { auth } from './components/authorized'
Vue.prototype.$auth = auth Vue.prototype.$auth = auth

View File

@@ -1,3 +0,0 @@
<template>
<div></div>
</template>

View File

@@ -6,17 +6,14 @@
<a-col> <a-col>
<div class="home-header-row"> <div class="home-header-row">
<div class="home-header-avatar"> <div class="home-header-avatar">
<a-avatar <yo-image :id="$root.global.info.avatar" :size="64" type="avatar" />
:size="64"
src="https://gss0.baidu.com/7Ls0a8Sm2Q5IlBGlnYG/sys/portraith/item/tb.1.9f0e4392.Q2njD2SGV-9wBUKqKFoQqA?t=1507123743"
/>
</div> </div>
<div class="home-header-content"> <div class="home-header-content">
<h2> <h2>
上午 {{ $moment().format('A') }}
<span>软件开发人员</span>欢迎您登录系统 <span>{{ $root.global.info.nickName || $root.global.info.name }}</span>欢迎您登录系统
</h2> </h2>
<p>上次IP115.217.160.156 上次登录时间2021-04-06 13:10:13</p> <p>上次IP{{ $root.global.info.lastLoginIp }} 上次登录时间{{ $root.global.info.lastLoginTime }}</p>
</div> </div>
</div> </div>
</a-col> </a-col>

View File

@@ -3,7 +3,10 @@
<a href="#" slot="extra">更多</a> <a href="#" slot="extra">更多</a>
<a-list :data-source="data" item-layout="horizontal"> <a-list :data-source="data" item-layout="horizontal">
<a-list-item slot="renderItem" slot-scope="item"> <a-list-item slot="renderItem" slot-scope="item">
<a-list-item-meta :description="moment().format('YYYY-MM-DD HH:mm:ss')" :title="item.title"> <a-list-item-meta
:description="$moment().format('YYYY-MM-DD HH:mm:ss')"
:title="item.title"
>
<a-icon :style="{ fontSize: '18px' }" slot="avatar" theme="twoTone" type="message" /> <a-icon :style="{ fontSize: '18px' }" slot="avatar" theme="twoTone" type="message" />
</a-list-item-meta> </a-list-item-meta>
</a-list-item> </a-list-item>
@@ -11,8 +14,6 @@
</a-card> </a-card>
</template> </template>
<script> <script>
import moment from 'moment';
export default { export default {
data() { data() {
return { return {
@@ -23,8 +24,5 @@ export default {
], ],
}; };
}, },
methods: {
moment,
},
}; };
</script> </script>

View File

@@ -37,7 +37,6 @@
</a-form-model> </a-form-model>
</template> </template>
<script> <script>
import moment from 'moment';
export default { export default {
data() { data() {
return { return {
@@ -56,7 +55,6 @@ export default {
}; };
}, },
methods: { methods: {
moment,
/** /**
* 必要的方法 * 必要的方法
* 在打开编辑页时允许填充数据 * 在打开编辑页时允许填充数据

View File

@@ -0,0 +1,42 @@
export default {
props: {
code: {
type: String
}
},
methods: {
onCopy() {
try {
const $textarea = document.createElement('textarea')
$textarea.style = 'opacity: 0;position: fixed;top: -10000;left: -10000'
document.body.append($textarea)
$textarea.value = this.code
$textarea.select()
document.execCommand('copy')
$textarea.remove()
this.$message.success('已复制到剪贴板')
}
catch
{
this.$message.error('复制失败')
}
}
},
render() {
const props = {
...this.$props,
...this.$attrs,
}
return props.code && (
<section>
<highlightjs {...{ props }} style={{ maxHeight: '400px', overflow: 'auto' }} />
<div class="text-right">
<a-button size="small" type="dashed" onClick={this.onCopy} class="mb-xs">Copy</a-button>
</div>
</section>
)
}
}

View File

@@ -0,0 +1,112 @@
<template>
<a-card :bordered="false" class="mb-none">
<container>
<a-row :gutter="16" type="flex">
<a-col flex="auto">
<container mode="container">
<section :id="`doc-${index}`" :key="index" v-for="(doc, index) in docs">
<h1>{{ doc.title }}</h1>
<component :codes="codes" :is="doc.component" v-if="doc.name" />
<template v-if="doc.children">
<section
:id="`doc-${index}-${_index}`"
:key="_index"
v-for="(_doc, _index) in doc.children"
>
<h3>{{ _doc.title }}</h3>
<component :codes="codes" :is="_doc.component" v-if="_doc.name" />
</section>
</template>
</section>
</container>
</a-col>
<a-col flex="240px">
<a-anchor
:get-container="()=> $el.parentNode"
:offset-top="24"
:wrapper-style="{ backgroundColor: 'transparent' }"
>
<a-anchor-link
:href="`#doc-${index}`"
:key="index"
:title="doc.title"
v-for="(doc, index) in docs"
>
<template v-if="doc.children">
<a-anchor-link
:href="`#doc-${index}-${_index}`"
:key="_index"
:title="_doc.title"
v-for="(_doc, _index) in doc.children"
/>
</template>
</a-anchor-link>
</a-anchor>
</a-col>
</a-row>
</container>
</a-card>
</template>
<script>
export default {
data() {
return {
docs: [
{
title: '开始使用',
name: '/usage',
},
{
title: '窗口',
},
{
title: '种子',
name: '/seed',
children: [
{
title: '查询表格',
name: '/seed/query',
},
{
title: '编辑窗口',
name: '/seed/form',
},
],
},
],
codes: {},
};
},
mounted() {
this.docs.forEach((doc) => {
if (doc.name) {
this.$set(doc, 'component', () => import(`.${doc.name}`));
}
if (doc.children) {
doc.children.forEach((_doc) => {
this.$set(_doc, 'component', () => import(`.${_doc.name}`));
});
}
});
// 读取doc-code下所有文件内容
const files = require.context('@/../public/doc-code', true, /\.(js|html|vue|css|less|json)(\?.*)?$/);
const codes = {};
files.keys().forEach((p) => {
const fileName = p.slice(1);
const xhr = new XMLHttpRequest();
xhr.open('GET', `./doc-code${fileName}`, false);
xhr.overrideMimeType('text/plain;charset=utf-8');
xhr.send(null);
codes[fileName] = xhr.responseText;
});
console.log(codes);
this.codes = codes;
},
methods: {
container() {
return this.$el;
},
},
};
</script>

View File

@@ -0,0 +1,33 @@
<template>
<section>
<h4>
新增
<a-tag>1.0</a-tag>
</h4>
<Highlight :code="codes['/seed/addForm.vue']" language="html" />
<h4>
编辑
<a-tag>1.0</a-tag>
</h4>
<Highlight :code="codes['/seed/editForm.vue']" language="html" />
<h4>
表单主体
<a-tag>1.0</a-tag>
</h4>
<Highlight :code="codes['/seed/form.vue']" language="html" />
</section>
</template>
<script>
import Highlight from '../highlight';
export default {
components: {
Highlight,
},
props: {
codes: {
type: Object,
},
},
};
</script>

View File

@@ -0,0 +1,45 @@
<template>
<section>
<p>种子文件已经提供了业务组件通用的架构可以通过以下几种方式快速获取架构代码</p>
<ul>
<li>
<p>
<a-tag class="mr-none" color="orange">@/src/pages/system/_seed</a-tag>中找到并复制内容
</p>
</li>
<li>
<p>
<b>用户片段</b>达到快速生成的目的
</p>
<p>
在VSCode中选择
<a-breadcrumb separator=">">
<a-breadcrumb-item>文件</a-breadcrumb-item>
<a-breadcrumb-item>首选项</a-breadcrumb-item>
<a-breadcrumb-item>用户片段</a-breadcrumb-item>
</a-breadcrumb>输入
<a-tag class="mr-none" color="orange">vue.json</a-tag>并回车将会打开针对vue文件的用户片段配置JSON
</p>
</li>
</ul>
<Highlight :code="codes['/seed/vue.json']" language="json" />
<ul>
<li>在下方直接复制代码</li>
</ul>
</section>
</template>
<script>
import Highlight from '../highlight';
export default {
components: {
Highlight,
},
props: {
codes: {
type: Object,
},
},
};
</script>

View File

@@ -0,0 +1,19 @@
<template>
<section>
<Highlight :code="codes['/seed/query.vue']" language="html" />
</section>
</template>
<script>
import Highlight from '../highlight';
export default {
components: {
Highlight,
},
props: {
codes: {
type: Object,
},
},
};
</script>

View File

@@ -0,0 +1,17 @@
<template>
<section></section>
</template>
<script>
import Highlight from './highlight';
export default {
components: {
Highlight,
},
props: {
codes: {
type: Object,
},
},
};
</script>

View File

@@ -44,7 +44,7 @@
<a-range-picker <a-range-picker
:show-time="{ :show-time="{
hideDisabledOptions: true, hideDisabledOptions: true,
defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')], defaultValue: [$moment('00:00:00', 'HH:mm:ss'), $moment('23:59:59', 'HH:mm:ss')],
}" }"
format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss"
v-model="query.dates" v-model="query.dates"
@@ -84,8 +84,6 @@
</container> </container>
</template> </template>
<script> <script>
import moment from 'moment';
export default { export default {
data() { data() {
return { return {
@@ -133,8 +131,6 @@ export default {
this.onLoadCodes(); this.onLoadCodes();
}, },
methods: { methods: {
moment,
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
@@ -142,8 +138,8 @@ export default {
loadData(params) { loadData(params) {
const query = this.$_.cloneDeep(this.query); const query = this.$_.cloneDeep(this.query);
if (query.dates && query.dates.length) { if (query.dates && query.dates.length) {
query.searchBeginTime = moment(query.dates[0]).format('YYYY-MM-DD HH:mm:ss'); query.searchBeginTime = this.$moment(query.dates[0]).format('YYYY-MM-DD HH:mm:ss');
query.searchEndTime = moment(query.dates[1]).format('YYYY-MM-DD HH:mm:ss'); query.searchEndTime = this.$moment(query.dates[1]).format('YYYY-MM-DD HH:mm:ss');
delete query.dates; delete query.dates;
} }

View File

@@ -41,7 +41,7 @@
<a-range-picker <a-range-picker
:show-time="{ :show-time="{
hideDisabledOptions: true, hideDisabledOptions: true,
defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')], defaultValue: [$moment('00:00:00', 'HH:mm:ss'), $moment('23:59:59', 'HH:mm:ss')],
}" }"
format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss"
v-model="query.dates" v-model="query.dates"
@@ -76,8 +76,6 @@
</container> </container>
</template> </template>
<script> <script>
import moment from 'moment';
export default { export default {
data() { data() {
return { return {
@@ -125,8 +123,6 @@ export default {
this.onLoadCodes(); this.onLoadCodes();
}, },
methods: { methods: {
moment,
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
@@ -134,8 +130,8 @@ export default {
loadData(params) { loadData(params) {
const query = this.$_.cloneDeep(this.query); const query = this.$_.cloneDeep(this.query);
if (query.dates && query.dates.length) { if (query.dates && query.dates.length) {
query.searchBeginTime = moment(query.dates[0]).format('YYYY-MM-DD HH:mm:ss'); query.searchBeginTime = this.$moment(query.dates[0]).format('YYYY-MM-DD HH:mm:ss');
query.searchEndTime = moment(query.dates[1]).format('YYYY-MM-DD HH:mm:ss'); query.searchEndTime = this.$moment(query.dates[1]).format('YYYY-MM-DD HH:mm:ss');
delete query.dates; delete query.dates;
} }

View File

@@ -25,7 +25,7 @@
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="生日"> <a-form-model-item label="生日">
<a-date-picker <a-date-picker
@change="(date) => form.birthday = date ? moment(date).format('YYYY-MM-DD') : undefined" @change="(date) => form.birthday = date ? $moment(date).format('YYYY-MM-DD') : undefined"
class="w-100-p" class="w-100-p"
placeholder="请选择生日" placeholder="请选择生日"
v-model="form.birthday" v-model="form.birthday"
@@ -120,8 +120,6 @@
</a-form-model> </a-form-model>
</template> </template>
<script> <script>
import moment from 'moment';
const validateToNextPassword = (rule, value, callback) => { const validateToNextPassword = (rule, value, callback) => {
callback(); callback();
}; };
@@ -179,8 +177,6 @@ export default {
}; };
}, },
methods: { methods: {
moment,
/** /**
* 必要的方法 * 必要的方法
* 在打开编辑页时允许填充数据 * 在打开编辑页时允许填充数据
@@ -189,7 +185,7 @@ export default {
const form = this.$_.cloneDeep(record || {}); const form = this.$_.cloneDeep(record || {});
// 日期特殊处理 // 日期特殊处理
if (form.birthday) { if (form.birthday) {
form.birthday = moment(form.birthday).format('YYYY-MM-DD'); form.birthday = this.$moment(form.birthday).format('YYYY-MM-DD');
} }
// 提交的时候是"param",而获取下来却是"info",在这里转换一下 // 提交的时候是"param",而获取下来却是"info",在这里转换一下
if (form.sysEmpInfo) { if (form.sysEmpInfo) {

View File

@@ -260,6 +260,9 @@ export default {
} else { } else {
this.$message.error(message); this.$message.error(message);
} }
})
.finally(() => {
record.statusChanging = false;
}); });
}, },

View File

@@ -127,7 +127,7 @@ export default {
<template slot="dataSource"> <template slot="dataSource">
{this.renderSelect(this.searchResult)} {this.renderSelect(this.searchResult)}
</template> </template>
<a-input> <a-input allow-clear>
<a-icon slot="suffix" type="search" class="certain-category-icon" /> <a-icon slot="suffix" type="search" class="certain-category-icon" />
</a-input> </a-input>
</a-auto-complete> </a-auto-complete>

View File

@@ -3241,6 +3241,11 @@ destroy@~1.0.4:
resolved "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" resolved "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
detect-indent@^5.0.0:
version "5.0.0"
resolved "https://registry.nlark.com/detect-indent/download/detect-indent-5.0.0.tgz?cache=0&sync_timestamp=1618847240598&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdetect-indent%2Fdownload%2Fdetect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50=
detect-node@^2.0.4: detect-node@^2.0.4:
version "2.0.5" version "2.0.5"
resolved "https://registry.npm.taobao.org/detect-node/download/detect-node-2.0.5.tgz#9d270aa7eaa5af0b72c4c9d9b814e7f4ce738b79" resolved "https://registry.npm.taobao.org/detect-node/download/detect-node-2.0.5.tgz#9d270aa7eaa5af0b72c4c9d9b814e7f4ce738b79"
@@ -4418,6 +4423,11 @@ highlight.js@^10.0.0:
resolved "https://registry.npm.taobao.org/highlight.js/download/highlight.js-10.7.1.tgz#a8ec4152db24ea630c90927d6cae2a45f8ecb955" resolved "https://registry.npm.taobao.org/highlight.js/download/highlight.js-10.7.1.tgz#a8ec4152db24ea630c90927d6cae2a45f8ecb955"
integrity sha1-qOxBUtsk6mMMkJJ9bK4qRfjsuVU= integrity sha1-qOxBUtsk6mMMkJJ9bK4qRfjsuVU=
highlight.js@^10.7.2:
version "10.7.2"
resolved "https://registry.nlark.com/highlight.js/download/highlight.js-10.7.2.tgz?cache=0&sync_timestamp=1619160938319&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhighlight.js%2Fdownload%2Fhighlight.js-10.7.2.tgz#89319b861edc66c48854ed1e6da21ea89f847360"
integrity sha1-iTGbhh7cZsSIVO0ebaIeqJ+Ec2A=
hmac-drbg@^1.0.1: hmac-drbg@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.npm.taobao.org/hmac-drbg/download/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" resolved "https://registry.npm.taobao.org/hmac-drbg/download/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@@ -4688,6 +4698,11 @@ imurmurhash@^0.1.4:
resolved "https://registry.npm.taobao.org/imurmurhash/download/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" resolved "https://registry.npm.taobao.org/imurmurhash/download/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
indent-string@^3.0.0:
version "3.2.0"
resolved "https://registry.npm.taobao.org/indent-string/download/indent-string-3.2.0.tgz?cache=0&sync_timestamp=1618679561483&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Findent-string%2Fdownload%2Findent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
indent-string@^4.0.0: indent-string@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.npm.taobao.org/indent-string/download/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" resolved "https://registry.npm.taobao.org/indent-string/download/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
@@ -7054,6 +7069,14 @@ readdirp@~3.5.0:
dependencies: dependencies:
picomatch "^2.2.1" picomatch "^2.2.1"
redent@^2.0.0:
version "2.0.0"
resolved "https://registry.npm.taobao.org/redent/download/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa"
integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=
dependencies:
indent-string "^3.0.0"
strip-indent "^2.0.0"
regenerate-unicode-properties@^8.2.0: regenerate-unicode-properties@^8.2.0:
version "8.2.0" version "8.2.0"
resolved "https://registry.npm.taobao.org/regenerate-unicode-properties/download/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" resolved "https://registry.npm.taobao.org/regenerate-unicode-properties/download/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec"
@@ -8169,7 +8192,7 @@ tslib@2.0.3:
resolved "https://registry.npm.taobao.org/tslib/download/tslib-2.0.3.tgz?cache=0&sync_timestamp=1617647442601&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" resolved "https://registry.npm.taobao.org/tslib/download/tslib-2.0.3.tgz?cache=0&sync_timestamp=1617647442601&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c"
integrity sha1-jgdBrEX8DCJuWKF7/D5kubxsphw= integrity sha1-jgdBrEX8DCJuWKF7/D5kubxsphw=
tslib@^1.10.0, tslib@^1.9.0: tslib@^1.10.0, tslib@^1.9.0, tslib@^1.9.3:
version "1.14.1" version "1.14.1"
resolved "https://registry.npm.taobao.org/tslib/download/tslib-1.14.1.tgz?cache=0&sync_timestamp=1609887785854&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" resolved "https://registry.npm.taobao.org/tslib/download/tslib-1.14.1.tgz?cache=0&sync_timestamp=1609887785854&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha1-zy04vcNKE0vK8QkcQfZhni9nLQA= integrity sha1-zy04vcNKE0vK8QkcQfZhni9nLQA=
@@ -8482,6 +8505,15 @@ vue-eslint-parser@^7.0.0:
esquery "^1.4.0" esquery "^1.4.0"
lodash "^4.17.15" lodash "^4.17.15"
vue-highlight.js@^3.1.0:
version "3.1.0"
resolved "https://registry.npm.taobao.org/vue-highlight.js/download/vue-highlight.js-3.1.0.tgz#87b60b4931fd310b318f2b2c9116fe71b69dd053"
integrity sha1-h7YLSTH9MQsxjysskRb+cbad0FM=
dependencies:
detect-indent "^5.0.0"
redent "^2.0.0"
tslib "^1.9.3"
vue-hot-reload-api@^2.3.0: vue-hot-reload-api@^2.3.0:
version "2.3.4" version "2.3.4"
resolved "https://registry.npm.taobao.org/vue-hot-reload-api/download/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" resolved "https://registry.npm.taobao.org/vue-hot-reload-api/download/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"