This commit is contained in:
2021-07-05 09:52:42 +08:00
135 changed files with 4903 additions and 933 deletions

View File

@@ -82,7 +82,9 @@ WHERE 1=1";
if (!string.IsNullOrEmpty(input.SysEmpParam.OrgId)) if (!string.IsNullOrEmpty(input.SysEmpParam.OrgId))
{ {
sql += " AND (SO.Id = @OrgId OR SO.Pids Like CONCAT('%[', @OrgId, ']%'))"; var filter = " AND (SO.Id = @OrgId {0}) ";
filter = String.Format(filter, input.TreeNodeDataScope.GetValueOrDefault(1) == 2 ? " OR SO.Pids Like CONCAT('%[', @OrgId, ']%') " : "");
sql += filter;
param.Add("OrgId", input.SysEmpParam.OrgId); param.Add("OrgId", input.SysEmpParam.OrgId);
} }

View File

@@ -59,13 +59,13 @@ namespace Ewide.Core
/// 发布时间 /// 发布时间
/// </summary> /// </summary>
[Comment("发布时间")] [Comment("发布时间")]
public DateTime PublicTime { get; set; } public DateTime? PublicTime { get; set; }
/// <summary> /// <summary>
/// 撤回时间 /// 撤回时间
/// </summary> /// </summary>
[Comment("撤回时间")] [Comment("撤回时间")]
public DateTime CancelTime { get; set; } public DateTime? CancelTime { get; set; }
/// <summary> /// <summary>
/// 状态(字典 0草稿 1发布 2撤回 3删除 /// 状态(字典 0草稿 1发布 2撤回 3删除

View File

@@ -11,7 +11,7 @@ namespace Ewide.Core
/// </summary> /// </summary>
[Table("sys_notice_user")] [Table("sys_notice_user")]
[Comment("通知公告用户表")] [Comment("通知公告用户表")]
public class SysNoticeUser : IEntity, IEntityTypeBuilder<SysNoticeUser> public class SysNoticeUser : DEntityBase
{ {
/// <summary> /// <summary>
/// 通知公告Id /// 通知公告Id
@@ -31,7 +31,7 @@ namespace Ewide.Core
/// 阅读时间 /// 阅读时间
/// </summary> /// </summary>
[Comment("阅读时间")] [Comment("阅读时间")]
public DateTime ReadTime { get; set; } public DateTime? ReadTime { get; set; }
/// <summary> /// <summary>
/// 状态(字典 0未读 1已读 /// 状态(字典 0未读 1已读

View File

@@ -2674,6 +2674,11 @@
查询条件 查询条件
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.PageInputBase.TreeNodeDataScope">
<summary>
树节点数据范围 1"只看本级" 2"查看本级及以下"
</summary>
</member>
<member name="T:Ewide.Core.PageDataResult`1"> <member name="T:Ewide.Core.PageDataResult`1">
<summary> <summary>
小诺分页列表结果 小诺分页列表结果
@@ -3223,122 +3228,132 @@
</summary> </summary>
<example>123456</example> <example>123456</example>
</member> </member>
<member name="T:Ewide.Core.Service.LoginOutput"> <member name="P:Ewide.Core.Service.LoginPassInput.NewPassword">
<summary>
新密码
</summary>
</member>
<member name="P:Ewide.Core.Service.LoginPassInput.Confirm">
<summary>
确认密码
</summary>
</member>
<member name="T:Ewide.Core.Service.LoginUserOutput">
<summary> <summary>
用户登录输出参数 用户登录输出参数
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Id"> <member name="P:Ewide.Core.Service.LoginUserOutput.Id">
<summary> <summary>
主键 主键
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Account"> <member name="P:Ewide.Core.Service.LoginUserOutput.Account">
<summary> <summary>
账号 账号
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.SecurityLevel"> <member name="P:Ewide.Core.Service.LoginUserOutput.SecurityLevel">
<summary> <summary>
密码安全级别 密码安全级别
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.NickName"> <member name="P:Ewide.Core.Service.LoginUserOutput.NickName">
<summary> <summary>
昵称 昵称
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Name"> <member name="P:Ewide.Core.Service.LoginUserOutput.Name">
<summary> <summary>
姓名 姓名
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Avatar"> <member name="P:Ewide.Core.Service.LoginUserOutput.Avatar">
<summary> <summary>
头像 头像
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Birthday"> <member name="P:Ewide.Core.Service.LoginUserOutput.Birthday">
<summary> <summary>
生日 生日
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Sex"> <member name="P:Ewide.Core.Service.LoginUserOutput.Sex">
<summary> <summary>
性别(字典 1男 2女) 性别(字典 1男 2女)
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Email"> <member name="P:Ewide.Core.Service.LoginUserOutput.Email">
<summary> <summary>
邮箱 邮箱
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Phone"> <member name="P:Ewide.Core.Service.LoginUserOutput.Phone">
<summary> <summary>
手机 手机
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Tel"> <member name="P:Ewide.Core.Service.LoginUserOutput.Tel">
<summary> <summary>
电话 电话
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.AdminType"> <member name="P:Ewide.Core.Service.LoginUserOutput.AdminType">
<summary> <summary>
管理员类型0超级管理员 1非管理员 管理员类型0超级管理员 1非管理员
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.LastLoginIp"> <member name="P:Ewide.Core.Service.LoginUserOutput.LastLoginIp">
<summary> <summary>
最后登陆IP 最后登陆IP
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.LastLoginTime"> <member name="P:Ewide.Core.Service.LoginUserOutput.LastLoginTime">
<summary> <summary>
最后登陆时间 最后登陆时间
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.LastLoginAddress"> <member name="P:Ewide.Core.Service.LoginUserOutput.LastLoginAddress">
<summary> <summary>
最后登陆地址 最后登陆地址
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.LastLoginBrowser"> <member name="P:Ewide.Core.Service.LoginUserOutput.LastLoginBrowser">
<summary> <summary>
最后登陆所用浏览器 最后登陆所用浏览器
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.LastLoginOs"> <member name="P:Ewide.Core.Service.LoginUserOutput.LastLoginOs">
<summary> <summary>
最后登陆所用系统 最后登陆所用系统
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.LoginEmpInfo"> <member name="P:Ewide.Core.Service.LoginUserOutput.LoginEmpInfo">
<summary> <summary>
员工信息 员工信息
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Apps"> <member name="P:Ewide.Core.Service.LoginUserOutput.Apps">
<summary> <summary>
具备应用信息 具备应用信息
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Roles"> <member name="P:Ewide.Core.Service.LoginUserOutput.Roles">
<summary> <summary>
角色信息 角色信息
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Permissions"> <member name="P:Ewide.Core.Service.LoginUserOutput.Permissions">
<summary> <summary>
权限信息 权限信息
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.Menus"> <member name="P:Ewide.Core.Service.LoginUserOutput.Menus">
<summary> <summary>
登录菜单信息---AntDesign版本菜单 登录菜单信息---AntDesign版本菜单
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.LoginOutput.DataScopes"> <member name="P:Ewide.Core.Service.LoginUserOutput.DataScopes">
<summary> <summary>
数据范围(机构)信息 数据范围(机构)信息
</summary> </summary>
@@ -5536,6 +5551,12 @@
<param name="input"></param> <param name="input"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Ewide.Core.Service.Notice.SysNoticeService.GetUnreadCount">
<summary>
获取接收到的通知公告总数
</summary>
<returns></returns>
</member>
<member name="M:Ewide.Core.Service.Notice.SysNoticeService.UpdatePublicInfo(Ewide.Core.SysNotice)"> <member name="M:Ewide.Core.Service.Notice.SysNoticeService.UpdatePublicInfo(Ewide.Core.SysNotice)">
<summary> <summary>
更新发布信息 更新发布信息
@@ -6798,16 +6819,6 @@
账号 账号
</summary> </summary>
</member> </member>
<member name="P:Ewide.Core.Service.AddUserInput.Password">
<summary>
密码
</summary>
</member>
<member name="P:Ewide.Core.Service.AddUserInput.Confirm">
<summary>
确认密码
</summary>
</member>
<member name="P:Ewide.Core.Service.DeleteUserInput.Id"> <member name="P:Ewide.Core.Service.DeleteUserInput.Id">
<summary> <summary>
用户Id 用户Id

View File

@@ -76,6 +76,11 @@ namespace Ewide.Core
/// 查询条件 /// 查询条件
/// </summary> /// </summary>
public virtual SearchInfo[] SearchInfo { get; set; } public virtual SearchInfo[] SearchInfo { get; set; }
/// <summary>
/// 树节点数据范围 1"只看本级" 2"查看本级及以下"
/// </summary>
public virtual int? TreeNodeDataScope { get; set; }
} }
} }

View File

@@ -202,7 +202,7 @@ namespace Ewide.Core
.Select(u => u.Permission).ToListAsync(); .Select(u => u.Permission).ToListAsync();
#if DEBUG #if DEBUG
#else #else
await _sysCacheService.SetPermission(userId, permissions); // 缓存结果 await _sysCacheService.SetPermission(UserId, permissions); // 缓存结果
#endif #endif
} }
return permissions; return permissions;

View File

@@ -14,6 +14,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using UAParser; using UAParser;
@@ -68,20 +69,85 @@ namespace Ewide.Core.Service
/// <returns></returns> /// <returns></returns>
[HttpPost("/login")] [HttpPost("/login")]
[AllowAnonymous] [AllowAnonymous]
public async Task<string> LoginAsync([Required] LoginInput input) public async Task<LoginOutput> LoginAsync([Required] LoginInput input)
{ {
string pwd = RSAHandler.RSADecrypt(input.Password); var password = RSAHandler.RSADecrypt(input.Password);
// 获取加密后的密码
var encryptPasswod = MD5Encryption.Encrypt(pwd);
var user = await GetUser(input);
#if !DEBUG
// 验证密码强度
var pattern = App.Configuration.GetSection("SimplePassword:Pattern").Value;
if (!Regex.Match(password, pattern).Success)
{
return new LoginOutput
{
Passed = false,
Pattern = pattern,
Descriptions = App.Configuration.GetSection("SimplePassword:Descriptions").Value
};
}
#endif
return new LoginOutput
{
Passed = true,
Token = await HandlerLoginAsync(user)
};
}
[HttpPost("/loginPass")]
[AllowAnonymous]
public async Task<LoginOutput> LoginPassAsync([Required] LoginPassInput input)
{
var user = await GetUser(input);
var newPassword = RSAHandler.RSADecrypt(input.NewPassword);
// 验证新密码强度
var pattern = App.Configuration.GetSection("SimplePassword:Pattern").Value;
if (!Regex.Match(newPassword, pattern).Success)
{
throw Oops.Oh("新密码强度不符合规则");
}
newPassword = MD5Encryption.Encrypt(newPassword);
if (newPassword.Equals(user.Password))
throw Oops.Oh(ErrorCode.D10041);
user.Password = newPassword;
return new LoginOutput
{
Passed = true,
Token = await HandlerLoginAsync(user)
};
}
private async Task<SysUser> GetUser(LoginInput input)
{
var password = RSAHandler.RSADecrypt(input.Password);
// 获取加密后的密码
var encryptPasswod = MD5Encryption.Encrypt(password);
#if DEBUG
var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Account.Equals(input.Account) || u.Phone.Equals(input.Account) || u.Email.Equals(input.Account));
#else
// 判断用户名和密码是否正确 // 判断用户名和密码是否正确
var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Account.Equals(input.Account) && u.Password.Equals(encryptPasswod)); var user = await _sysUserRep.FirstOrDefaultAsync(u => (u.Account.Equals(input.Account) || u.Phone.Equals(input.Account) || u.Email.Equals(input.Account)) && u.Password.Equals(encryptPasswod));
_ = user ?? throw Oops.Oh(ErrorCode.D1000); _ = user ?? throw Oops.Oh(ErrorCode.D1000);
#endif
// 验证账号是否被冻结 // 验证账号是否被冻结
if (user.Status == CommonStatus.DISABLE) if (user.Status == CommonStatus.DISABLE)
throw Oops.Oh(ErrorCode.D1017); throw Oops.Oh(ErrorCode.D1017);
return user;
}
private async Task<string> HandlerLoginAsync(SysUser user)
{
// 生成Token令牌 // 生成Token令牌
//var accessToken = await _jwtBearerManager.CreateTokenAdmin(user); //var accessToken = await _jwtBearerManager.CreateTokenAdmin(user);
var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object> var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
@@ -102,38 +168,40 @@ namespace Ewide.Core.Service
_httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken; _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;
// 增加登录日志 // 增加登录日志
var loginOutput = user.Adapt<LoginOutput>(); var loginUserOutput = user.Adapt<LoginUserOutput>();
var clent = Parser.GetDefault().Parse(App.GetService<IHttpContextAccessor>().HttpContext.Request.Headers["User-Agent"]); var clent = Parser.GetDefault().Parse(App.GetService<IHttpContextAccessor>().HttpContext.Request.Headers["User-Agent"]);
loginOutput.LastLoginBrowser = clent.UA.Family + clent.UA.Major; loginUserOutput.LastLoginBrowser = clent.UA.Family + clent.UA.Major;
loginOutput.LastLoginOs = clent.OS.Family + clent.OS.Major; loginUserOutput.LastLoginOs = clent.OS.Family + clent.OS.Major;
await new SysLogVis await new SysLogVis
{ {
Name = "登录", Name = "登录",
Success = true, Success = true,
Message = "登录成功", Message = "登录成功",
Ip = loginOutput.LastLoginIp, Ip = loginUserOutput.LastLoginIp,
Browser = loginOutput.LastLoginBrowser, Browser = loginUserOutput.LastLoginBrowser,
Os = loginOutput.LastLoginOs, Os = loginUserOutput.LastLoginOs,
VisType = 1, VisType = 1,
VisTime = loginOutput.LastLoginTime, VisTime = loginUserOutput.LastLoginTime,
Account = loginOutput.Account Account = loginUserOutput.Account
}.InsertAsync(); }.InsertAsync();
return accessToken; return accessToken;
} }
/// <summary> /// <summary>
/// 获取当前登录用户信息 /// 获取当前登录用户信息
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpGet("/getLoginUser")] [HttpGet("/getLoginUser")]
public async Task<LoginOutput> GetLoginUserAsync() public async Task<LoginUserOutput> GetLoginUserAsync()
{ {
var user = _userManager.User; var user = _userManager.User;
var userId = user.Id; var userId = user.Id;
var httpContext = App.GetService<IHttpContextAccessor>().HttpContext; var httpContext = App.GetService<IHttpContextAccessor>().HttpContext;
var loginOutput = user.Adapt<LoginOutput>(); var loginOutput = user.Adapt<LoginUserOutput>();
// 隐藏手机号/邮箱中间几位 // 隐藏手机号/邮箱中间几位
loginOutput.Phone = String.IsNullOrEmpty(loginOutput.Phone) ? loginOutput.Phone loginOutput.Phone = String.IsNullOrEmpty(loginOutput.Phone) ? loginOutput.Phone
@@ -197,7 +265,7 @@ namespace Ewide.Core.Service
var userId = user.Id; var userId = user.Id;
var httpContext = App.GetService<IHttpContextAccessor>().HttpContext; var httpContext = App.GetService<IHttpContextAccessor>().HttpContext;
var loginOutput = user.Adapt<LoginOutput>(); var loginOutput = user.Adapt<LoginUserOutput>();
var ip = httpContext.Request.Headers["X-Real-IP"]; var ip = httpContext.Request.Headers["X-Real-IP"];

View File

@@ -1,4 +1,5 @@
using Furion.DependencyInjection; using Furion;
using Furion.DependencyInjection;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace Ewide.Core.Service namespace Ewide.Core.Service
@@ -14,13 +15,29 @@ namespace Ewide.Core.Service
/// </summary> /// </summary>
/// <example>superAdmin</example> /// <example>superAdmin</example>
[Required(ErrorMessage = "用户名不能为空"), MinLength(3, ErrorMessage = "用户名不能少于3位字符")] [Required(ErrorMessage = "用户名不能为空"), MinLength(3, ErrorMessage = "用户名不能少于3位字符")]
public string Account { get; set; } public virtual string Account { get; set; }
/// <summary> /// <summary>
/// 密码 /// 密码
/// </summary> /// </summary>
/// <example>123456</example> /// <example>123456</example>
[Required(ErrorMessage = "密码不能为空"), MinLength(5, ErrorMessage = "密码不能少于5位字符")] [Required(ErrorMessage = "密码不能为空"), MinLength(5, ErrorMessage = "密码不能少于5位字符")]
public string Password { get; set; } public virtual string Password { get; set; }
}
[SkipScan]
public class LoginPassInput : LoginInput
{
/// <summary>
/// 新密码
/// </summary>
[Required(ErrorMessage = "新密码不能为空")]
public string NewPassword { get; set; }
/// <summary>
/// 确认密码
/// </summary>
[Required(ErrorMessage = "确认密码不能为空"), Compare(nameof(NewPassword), ErrorMessage = "两次密码不一致")]
public string Confirm { get; set; }
} }
} }

View File

@@ -4,11 +4,20 @@ using System.Collections.Generic;
namespace Ewide.Core.Service namespace Ewide.Core.Service
{ {
[SkipScan]
public class LoginOutput
{
public bool Passed { get; set; }
public string Pattern { get; set; }
public string Descriptions { get; set; }
public string Token { get; set; }
}
/// <summary> /// <summary>
/// 用户登录输出参数 /// 用户登录输出参数
/// </summary> /// </summary>
[SkipScan] [SkipScan]
public class LoginOutput public class LoginUserOutput
{ {
/// <summary> /// <summary>
/// 主键 /// 主键

View File

@@ -7,8 +7,8 @@ namespace Ewide.Core.Service
{ {
Task<dynamic> GetCaptcha(); Task<dynamic> GetCaptcha();
Task<bool> GetCaptchaOpen(); Task<bool> GetCaptchaOpen();
Task<LoginOutput> GetLoginUserAsync(); Task<LoginUserOutput> GetLoginUserAsync();
Task<string> LoginAsync([Required] LoginInput input); Task<LoginOutput> LoginAsync([Required] LoginInput input);
Task LogoutAsync(); Task LogoutAsync();
Task<dynamic> VerificationCode(ClickWordCaptchaInput input); Task<dynamic> VerificationCode(ClickWordCaptchaInput input);
} }

View File

@@ -25,7 +25,7 @@ namespace Ewide.Core.Service
/// <summary> /// <summary>
/// 发布人Id /// 发布人Id
/// </summary> /// </summary>
public long PublicUserId { get; set; } public string PublicUserId { get; set; }
/// <summary> /// <summary>
/// 发布人姓名 /// 发布人姓名
@@ -35,7 +35,7 @@ namespace Ewide.Core.Service
/// <summary> /// <summary>
/// 发布机构Id /// 发布机构Id
/// </summary> /// </summary>
public long PublicOrgId { get; set; } public string PublicOrgId { get; set; }
/// <summary> /// <summary>
/// 发布机构名称 /// 发布机构名称

View File

@@ -39,6 +39,6 @@ namespace Ewide.Core.Service
/// <summary> /// <summary>
/// 阅读时间 /// 阅读时间
/// </summary> /// </summary>
public DateTime ReadTime { get; set; } public DateTime? ReadTime { get; set; }
} }
} }

View File

@@ -1,4 +1,6 @@
using Furion.DatabaseAccessor; using Dapper;
using Ewide.Core.Extension;
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions; using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection; using Furion.DependencyInjection;
using Furion.DynamicApiController; using Furion.DynamicApiController;
@@ -9,6 +11,7 @@ using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ewide.Core.Service.Notice namespace Ewide.Core.Service.Notice
@@ -26,15 +29,20 @@ namespace Ewide.Core.Service.Notice
private readonly ISysNoticeUserService _sysNoticeUserService; private readonly ISysNoticeUserService _sysNoticeUserService;
private readonly IDapperRepository _dapperRepository;
public SysNoticeService(IRepository<SysNotice> sysNoticeRep, public SysNoticeService(IRepository<SysNotice> sysNoticeRep,
IRepository<SysNoticeUser> sysNoticeUserRep, IRepository<SysNoticeUser> sysNoticeUserRep,
IUserManager userManager, IUserManager userManager,
ISysNoticeUserService sysNoticeUserService) ISysNoticeUserService sysNoticeUserService, IDapperRepository dapperRepository)
{ {
_sysNoticeRep = sysNoticeRep; _sysNoticeRep = sysNoticeRep;
_sysNoticeUserRep = sysNoticeUserRep; _sysNoticeUserRep = sysNoticeUserRep;
_userManager = userManager; _userManager = userManager;
_sysNoticeUserService = sysNoticeUserService; _sysNoticeUserService = sysNoticeUserService;
_dapperRepository = dapperRepository;
} }
/// <summary> /// <summary>
@@ -61,22 +69,26 @@ namespace Ewide.Core.Service.Notice
/// <param name="input"></param> /// <param name="input"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("/sysNotice/add")] [HttpPost("/sysNotice/add")]
[UnitOfWork]
public async Task AddNotice(AddNoticeInput input) public async Task AddNotice(AddNoticeInput input)
{ {
_sysNoticeRep.EnsureTransaction();
if (input.Status != (int)NoticeStatus.DRAFT && input.Status != (int)NoticeStatus.PUBLIC) if (input.Status != (int)NoticeStatus.DRAFT && input.Status != (int)NoticeStatus.PUBLIC)
throw Oops.Oh(ErrorCode.D7000); throw Oops.Oh(ErrorCode.D7000);
var notice = input.Adapt<SysNotice>(); var notice = input.Adapt<SysNotice>();
var id = System.Guid.NewGuid().ToString().ToLower();
notice.Id = id;
await UpdatePublicInfo(notice); await UpdatePublicInfo(notice);
// 如果是发布,则设置发布时间 // 如果是发布,则设置发布时间
if (input.Status == (int)NoticeStatus.PUBLIC) if (input.Status == (int)NoticeStatus.PUBLIC)
notice.PublicTime = DateTime.Now; notice.PublicTime = DateTime.Now;
var newItem = await notice.InsertNowAsync(); var newItem = await notice.InsertAsync();
// 通知到的人 // 通知到的人
var noticeUserIdList = input.NoticeUserIdList; var noticeUserIdList = input.NoticeUserIdList;
var noticeUserStatus = (int)NoticeUserStatus.UNREAD; var noticeUserStatus = (int)NoticeUserStatus.UNREAD;
await _sysNoticeUserService.Add(newItem.Entity.Id, noticeUserIdList, noticeUserStatus); await _sysNoticeUserService.Add(id, noticeUserIdList, noticeUserStatus);
} }
/// <summary> /// <summary>
@@ -146,7 +158,6 @@ namespace Ewide.Core.Service.Notice
var noticeUserRead = new NoticeUserRead var noticeUserRead = new NoticeUserRead
{ {
UserId = u.UserId, UserId = u.UserId,
UserName = _userManager.Name,
ReadStatus = u.ReadStatus, ReadStatus = u.ReadStatus,
ReadTime = u.ReadTime ReadTime = u.ReadTime
}; };
@@ -154,8 +165,11 @@ namespace Ewide.Core.Service.Notice
}); });
} }
var noticeResult = notice.Adapt<NoticeDetailOutput>(); var noticeResult = notice.Adapt<NoticeDetailOutput>();
noticeResult.NoticeUserIdList = noticeUserIdList; if (_userManager.SuperAdmin)
noticeResult.NoticeUserReadInfoList = noticeUserReadInfoList; {
noticeResult.NoticeUserIdList = noticeUserIdList;
noticeResult.NoticeUserReadInfoList = noticeUserReadInfoList;
}
// 如果该条通知公告为已发布,则将当前用户的该条通知公告设置为已读 // 如果该条通知公告为已发布,则将当前用户的该条通知公告设置为已读
if (notice.Status == (int)NoticeStatus.PUBLIC) if (notice.Status == (int)NoticeStatus.PUBLIC)
await _sysNoticeUserService.Read(notice.Id, _userManager.UserId, (int)NoticeUserStatus.READ); await _sysNoticeUserService.Read(notice.Id, _userManager.UserId, (int)NoticeUserStatus.READ);
@@ -193,18 +207,45 @@ namespace Ewide.Core.Service.Notice
/// </summary> /// </summary>
/// <param name="input"></param> /// <param name="input"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet("/sysNotice/received")] [HttpPost("/sysNotice/received")]
public async Task<dynamic> ReceivedNoticePageList([FromQuery] NoticeInput input) public async Task<dynamic> ReceivedNoticePageList([FromBody] NoticeInput input)
{ {
var searchValue = !string.IsNullOrEmpty(input.SearchValue?.Trim()); var sql = @"SELECT
var notices = await _sysNoticeRep.DetachedEntities.Join(_sysNoticeUserRep.DetachedEntities, u => u.Id, e => e.NoticeId, (u, e) => new { u, e }) SN.*,
.Where(u => u.e.UserId == _userManager.UserId) SU.Avatar
.Where(searchValue, u => EF.Functions.Like(u.u.Title, $"%{input.SearchValue.Trim()}%") || EF.Functions.Like(u.u.Content, $"%{input.SearchValue.Trim()}%")) FROM sys_notice SN
.Where(input.Type > 0, u => u.u.Type == input.Type) LEFT JOIN sys_notice_user SNU ON SN.Id = SNU.NoticeId
.Where(u => u.u.Status != (int)NoticeStatus.DELETED) LEFT JOIN sys_user SU ON SN.PublicUserId = SU.Id
.Select(u => u.u.Adapt<NoticeReceiveOutput>()) WHERE SNU.UserId = @UserId AND SN.Status <> @Status";
.ToPagedListAsync(input.PageIndex, input.PageSize);
return PageDataResult<NoticeReceiveOutput>.PageResult(notices); var data = await _dapperRepository.QueryPageDataDynamic(
sql,
input,
new
{
_userManager.UserId,
Status = (int)NoticeStatus.DELETED
}
);
data.Items = data.Items.Select(p => {
var r = p.Adapt<dynamic>();
r.Content = Regex.Replace(r.Content, @"<\/?.+?\/?>", "").Replace("\r\n", "");
return r;
});
return data;
}
/// <summary>
/// 获取接收到的通知公告总数
/// </summary>
/// <returns></returns>
[HttpGet("/sysNotice/unread")]
public async Task<int> GetUnreadCount()
{
return await _sysNoticeUserRep.Where(u => u.UserId == _userManager.UserId && u.ReadStatus == (int)NoticeUserStatus.UNREAD).CountAsync();
} }
/// <summary> /// <summary>

View File

@@ -1,9 +1,12 @@
using Furion.DatabaseAccessor; using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions; using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection; using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ewide.Core.Service.Notice namespace Ewide.Core.Service.Notice
@@ -11,13 +14,17 @@ namespace Ewide.Core.Service.Notice
/// <summary> /// <summary>
/// 通知公告用户 /// 通知公告用户
/// </summary> /// </summary>
public class SysNoticeUserService : ISysNoticeUserService, ITransient [ApiDescriptionSettings(Name = "NoticeUser", Order = 100)]
public class SysNoticeUserService : ISysNoticeUserService, IDynamicApiController, ITransient
{ {
private readonly IRepository<SysNoticeUser> _sysNoticeUserRep; // 通知公告用户表仓储 private readonly IRepository<SysNoticeUser> _sysNoticeUserRep; // 通知公告用户表仓储
private readonly IUserManager _userManager;
public SysNoticeUserService(IRepository<SysNoticeUser> sysNoticeUserRep) private readonly IRepository<SysNotice> _sysNoticeRep;
public SysNoticeUserService(IRepository<SysNoticeUser> sysNoticeUserRep, IUserManager userManager, IRepository<SysNotice> sysNoticeRep)
{ {
_sysNoticeUserRep = sysNoticeUserRep; _sysNoticeUserRep = sysNoticeUserRep;
_userManager = userManager;
_sysNoticeRep = sysNoticeRep;
} }
/// <summary> /// <summary>
@@ -27,18 +34,19 @@ namespace Ewide.Core.Service.Notice
/// <param name="noticeUserIdList"></param> /// <param name="noticeUserIdList"></param>
/// <param name="noticeUserStatus"></param> /// <param name="noticeUserStatus"></param>
/// <returns></returns> /// <returns></returns>
public Task Add(string noticeId, List<string> noticeUserIdList, int noticeUserStatus)
public async Task Add(string noticeId, List<string> noticeUserIdList, int noticeUserStatus)
{ {
noticeUserIdList.ForEach(u => foreach (var u in noticeUserIdList)
{ {
new SysNoticeUser await new SysNoticeUser
{ {
Id = Guid.NewGuid().ToString(),
NoticeId = noticeId, NoticeId = noticeId,
UserId = u, UserId = u,
ReadStatus = noticeUserStatus ReadStatus = noticeUserStatus
}.InsertAsync(); }.InsertAsync();
}); }
return Task.CompletedTask;
} }
/// <summary> /// <summary>

View File

@@ -59,8 +59,8 @@ namespace Ewide.Core.Service
var orgs = await _sysOrgRep.DetachedEntities var orgs = await _sysOrgRep.DetachedEntities
.Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")), // 根据机构名称模糊查询 .Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")), // 根据机构名称模糊查询
(id, u => u.Id == input.Id.Trim()), // 根据机构id查询 (id, u => u.Id == input.Id.Trim()), // 根据机构id查询
(pId, u => EF.Functions.Like(u.Pids, $"%[{input.Pid.Trim()}]%") (pId, u => input.TreeNodeDataScope.GetValueOrDefault(1) == 2 ? (EF.Functions.Like(u.Pids, $"%[{input.Pid.Trim()}]%")
|| u.Id == input.Pid.Trim())) // 根据父机构id查询 || u.Id == input.Pid.Trim()) : u.Id == input.Pid.Trim() )) // 根据父机构id查询
.Where(dataScopeList.Count > 0, u => dataScopeList.Contains(u.Id)) // 非管理员范围限制 .Where(dataScopeList.Count > 0, u => dataScopeList.Contains(u.Id)) // 非管理员范围限制
.Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort) .Where(u => u.Status != CommonStatus.DELETED).OrderBy(u => u.Sort)
.ToPageData<SysOrg,OrgOutput>(input); .ToPageData<SysOrg,OrgOutput>(input);

View File

@@ -84,17 +84,13 @@ namespace Ewide.Core.Service
[Required(ErrorMessage = "账号名称不能为空")] [Required(ErrorMessage = "账号名称不能为空")]
public override string Account { get; set; } public override string Account { get; set; }
/// <summary>
/// 密码
/// </summary>
[Required(ErrorMessage = "密码不能为空")]
public override string Password { get; set; }
/// <summary> //[Required(ErrorMessage = "密码不能为空")]
/// 确认密码 //public override string Password { get; set; }
/// </summary>
[Required(ErrorMessage = "确认密码不能为空"), Compare(nameof(Password), ErrorMessage = "两次密码不一致")]
public string Confirm { get; set; } //[Required(ErrorMessage = "确认密码不能为空"), Compare(nameof(Password), ErrorMessage = "两次密码不一致")]
//public string Confirm { get; set; }
} }
public class DeleteUserInput : UserInput public class DeleteUserInput : UserInput

View File

@@ -79,8 +79,8 @@ namespace Ewide.Core.Service
.Where(!string.IsNullOrEmpty(searchValue), x => (x.n.u.Account.Contains(input.SearchValue) || .Where(!string.IsNullOrEmpty(searchValue), x => (x.n.u.Account.Contains(input.SearchValue) ||
x.n.u.Name.Contains(input.SearchValue) || x.n.u.Name.Contains(input.SearchValue) ||
x.n.u.Phone.Contains(input.SearchValue))) x.n.u.Phone.Contains(input.SearchValue)))
.Where(!string.IsNullOrEmpty(pid), x => (x.n.e.OrgId == pid || .Where(!string.IsNullOrEmpty(pid), x => input.TreeNodeDataScope.GetValueOrDefault(1) == 2 ? (x.n.e.OrgId == pid ||
x.o.Pids.Contains($"[{pid.Trim()}]"))) x.o.Pids.Contains($"[{pid.Trim()}]")) : x.n.e.OrgId == pid )
.Where(input.SearchStatus >= 0, x => x.n.u.Status == input.SearchStatus) .Where(input.SearchStatus >= 0, x => x.n.u.Status == input.SearchStatus)
.Where(!superAdmin, x => x.n.u.AdminType != AdminType.SuperAdmin) .Where(!superAdmin, x => x.n.u.AdminType != AdminType.SuperAdmin)
.Where(!superAdmin && dataScopes.Count > 0, x => dataScopes.Contains(x.n.e.OrgId)) .Where(!superAdmin && dataScopes.Count > 0, x => dataScopes.Contains(x.n.e.OrgId))
@@ -111,9 +111,23 @@ namespace Ewide.Core.Service
// 数据范围检查 // 数据范围检查
await CheckDataScope(input); await CheckDataScope(input);
var isExist = await _sysUserRep.AnyAsync(u => u.Account == input.Account, false); var email = input.Email?.ToLower();
if (isExist) throw Oops.Oh(ErrorCode.D1003);
var isExist = await _sysUserRep.AnyAsync(u =>
input.Account.Equals(u.Account) ||
input.Account.Equals(u.Phone) ||
input.Account.Equals(u.Email) ||
(!string.IsNullOrWhiteSpace(input.Phone) && (
input.Phone.Equals(u.Account) ||
input.Phone.Equals(u.Phone)
)) ||
(!string.IsNullOrWhiteSpace(email) && (
email.Equals(u.Account) ||
email.Equals(u.Email)
))
, false);
if (isExist) throw Oops.Oh(ErrorCode.D1003);
input.Password = CommonConst.DEFAULT_PASSWORD;
var user = input.Adapt<SysUser>(); var user = input.Adapt<SysUser>();
user.Password = MD5Encryption.Encrypt(input.Password); user.Password = MD5Encryption.Encrypt(input.Password);
if (string.IsNullOrEmpty(user.Name)) if (string.IsNullOrEmpty(user.Name))
@@ -171,8 +185,22 @@ namespace Ewide.Core.Service
// 数据范围检查 // 数据范围检查
await CheckDataScope(input); await CheckDataScope(input);
var email = input.Email?.ToLower();
// 排除自己并且判断与其他是否相同 // 排除自己并且判断与其他是否相同
var isExist = await _sysUserRep.AnyAsync(u => u.Account == input.Account && u.Id != input.Id, false); var isExist = await _sysUserRep.AnyAsync(u =>
(input.Account.Equals(u.Account) && !input.Id.Equals(u.Id)) ||
input.Account.Equals(u.Phone) ||
input.Account.Equals(u.Email) ||
(!string.IsNullOrWhiteSpace(input.Phone) && (
input.Phone.Equals(u.Account) ||
(input.Phone.Equals(u.Phone) && !input.Id.Equals(u.Id))
)) ||
(!string.IsNullOrWhiteSpace(email) && (
email.Equals(u.Account) ||
(email.Equals(u.Email) && !input.Id.Equals(u.Id))
))
, false);
if (isExist) throw Oops.Oh(ErrorCode.D1003); if (isExist) throw Oops.Oh(ErrorCode.D1003);
var user = input.Adapt<SysUser>(); var user = input.Adapt<SysUser>();

View File

@@ -97,7 +97,15 @@
"sysFileInfo:preview", "sysFileInfo:preview",
"sysUser:updateInfo", "sysUser:updateInfo",
"sysUser:updatePwd", "sysUser:updatePwd",
"sysUser:updateAvatar" "sysUser:updateAvatar",
"sysNotice:received",
"sysNotice:unread",
"sysNotice:detail"
] ]
},
"SimplePassword": {
"Pattern": "(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])(?=.*[^a-zA-Z0-9]){8,}",
"Descriptions": "密码中必须包含大小字母、数字、特称字符至少8个字符"
} }
} }

1
web-react/.env Normal file
View File

@@ -0,0 +1 @@
GENERATE_SOURCEMAP=false

View File

@@ -23,12 +23,13 @@ module.exports = {
javascriptEnabled: true, javascriptEnabled: true,
}, },
}, },
importLoaders: 2
}, },
}, },
], ],
webpack: { webpack: {
plugins: [ plugins: [
// new MonacoWebpackPlugin() new MonacoWebpackPlugin()
] ]
} },
} }

View File

@@ -9,6 +9,7 @@
"@testing-library/user-event": "^12.1.10", "@testing-library/user-event": "^12.1.10",
"antd": "^4.16.2", "antd": "^4.16.2",
"axios": "^0.21.1", "axios": "^0.21.1",
"braft-editor": "^2.3.9",
"craco-less": "^1.17.1", "craco-less": "^1.17.1",
"crypto-js": "^4.0.0", "crypto-js": "^4.0.0",
"echarts": "^5.1.2", "echarts": "^5.1.2",
@@ -22,6 +23,7 @@
"react-color": "^2.19.3", "react-color": "^2.19.3",
"react-cropper": "^2.1.8", "react-cropper": "^2.1.8",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-infinite-scroller": "^1.2.4",
"react-json-view": "^1.21.3", "react-json-view": "^1.21.3",
"react-monaco-editor": "^0.43.0", "react-monaco-editor": "^0.43.0",
"react-router": "^5.2.0", "react-router": "^5.2.0",

View File

@@ -3,7 +3,6 @@ import { ConfigProvider } from 'antd'
import zhCN from 'antd/lib/locale/zh_CN' import zhCN from 'antd/lib/locale/zh_CN'
import moment from 'moment' import moment from 'moment'
import 'moment/locale/zh-cn' import 'moment/locale/zh-cn'
import './assets/style/app.less'
moment.locale('zh-cn') moment.locale('zh-cn')

View File

@@ -0,0 +1,11 @@
@import '~antd/dist/antd.dark.less';
@padding-xxs: 4px;
@padding-xl: 32px;
body {
line-height: 1.42857143;
}
#root {
transition: @animation-duration-slow opacity;
opacity: 1 !important;
}

View File

@@ -8,14 +8,6 @@
@import './lib/width-height.less'; @import './lib/width-height.less';
@import './lib/scrollbar.less'; @import './lib/scrollbar.less';
@import './main.less'; @import './main.less';
@import './frame/dark.less';
@import './frame/light.less';
.yo-nav-theme--dark {
.dark();
}
.yo-nav-theme--light {
.light();
}
@import './lib/button.less'; @import './lib/button.less';
@import './lib/card.less'; @import './lib/card.less';
@import './lib/table.less'; @import './lib/table.less';
@@ -39,5 +31,5 @@
@import './lib/anchor.less'; @import './lib/anchor.less';
@import './lib/disabled.less'; @import './lib/disabled.less';
@import './theme/primary.less'; @import './theme/primary.less';
// @import './lib/font-weight.less';
@import './public.less'; @import './public.less';
@import './pages/index.less';

View File

@@ -0,0 +1,14 @@
@import (reference) '../extend.less';
.ant-card {
margin-bottom: @padding-md;
}
.ant-card-grid-hoverable {
&:hover {
box-shadow: 1px 0 0 0 #303030,
0 1px 0 0 #303030,
1px 1px 0 0 #303030,
1px 0 0 0 #303030 inset,
0 1px 0 0 #303030 inset,
@card-shadow;
}
}

View File

@@ -0,0 +1,18 @@
@import (reference) '../extend.less';
.ant-select-dropdown {
.chrome-picker {
width: auto !important;
margin: -@padding-xxs 0;
border-radius: 0 !important;
background: transparent !important;
box-shadow: none !important;
}
}
.color-selector--palette {
width: 32px;
height: 32px;
border-radius: @border-radius-base;
box-shadow: inset 0 0 0 @border-width-base @border-color-base, inset 0 0 0 3px @black;
}

View File

@@ -4,7 +4,7 @@
>table { >table {
border-collapse: collapse; border-collapse: collapse;
background-color: @white; background-color: @component-background;
} }
} }
} }

View File

@@ -16,7 +16,7 @@
margin-bottom: 0; margin-bottom: 0;
padding: 0 @padding-md; padding: 0 @padding-md;
background-color: @white; background-color: @component-background;
&.ant-tabs-card-bar { &.ant-tabs-card-bar {
.ant-tabs-nav-container { .ant-tabs-nav-container {
@@ -121,7 +121,7 @@
padding: @padding-xs @padding-md; padding: @padding-xs @padding-md;
border: @border-width-base @border-style-base @border-color-split; border: @border-width-base @border-style-base @border-color-split;
background-color: fade(@white, 80%); background-color: fade(@component-background, 80%);
backdrop-filter: blur(5px); backdrop-filter: blur(5px);
@@ -164,6 +164,6 @@
&--header { &--header {
padding: @padding-md 0; padding: @padding-md 0;
background-color: @white; background-color: @component-background;
} }
} }

View File

@@ -0,0 +1,401 @@
@import (reference) '../extend.less';
.yo-form {
&--fixed {
width: 660px;
margin: 0 auto;
}
.h1,
.h2,
.h3,
.h4,
.h5,
.h6 {
color: darken(@white, 40%);
}
.h3 {
font-size: 16px;
}
.h4 {
font-size: 15px;
}
.yo-form-group {
margin-bottom: @padding-md;
}
.ant-form-item {
display: flex;
justify-content: space-between;
margin-bottom: -1px;
padding: @padding-xs @padding-md;
border: @border-width-base @border-style-base @border-color-split;
background-color: @component-background;
@box-shadow-focused: 0 0 0 2px fade(@primary-color, 50%);
@control-background: darken(@white, 95%) !important;
&::before,
&::after {
content: none;
}
.ant-form-item-control {
text-align: right;
}
.ant-input,
.ant-input-number,
.ant-mentions,
.ant-select-selector,
.ant-input-group-addon,
.ant-cascader-picker,
.ant-input-affix-wrapper,
.ant-picker {
z-index: 1;
text-align: left;
color: darken(@white, 10%);
border: 0;
background-color: @control-background;
}
.ant-mentions {
textarea {
background-color: @control-background;
}
}
.focus {
z-index: 2 !important;
box-shadow: @box-shadow-focused;
}
.unfoucs {
z-index: 1 !important;
box-shadow: none;
}
.ant-input {
&:focus {
.focus();
}
}
.ant-input-affix-wrapper {
>.ant-input {
&:focus {
.unfoucs();
}
}
}
.ant-input-number-focused,
.ant-mentions-focused {
.focus();
}
.ant-select-focused,
.ant-select-open {
z-index: 2;
.ant-select-selection {
.focus();
}
}
.ant-cascader-picker:focus {
.ant-cascader-input {
.focus();
}
}
.ant-input-affix-wrapper:focus,
.ant-input-affix-wrapper-focused {
.focus();
}
.ant-select-focused:not(.ant-select-disabled).ant-select:not(.ant-select-customize-input) {
.ant-select-selector {
.focus();
}
}
.ant-picker-focused {
.focus();
}
.ant-input-group {
.ant-row-flex {
.ant-select {
width: 100%;
}
}
.ant-input-group-addon {
z-index: 0;
}
}
.ant-cascader-picker-clear {
background-color: @control-background;
}
}
.ant-form-item-label {
overflow: hidden;
flex: 1 1 auto;
margin-right: @padding-md;
text-align: left;
text-overflow: ellipsis;
>label {
color: darken(@white, 10%);
&::after {
content: none;
}
}
}
.ant-form-item-control {
flex: 0 0 61.8%;
width: 61.8%;
min-width: 220px;
}
.yo-form--fluid {
.ant-form-item-control {
flex: 0 0 100%;
width: 100%;
text-align: inherit;
}
}
.yo-form--short {
.ant-form-item-control {
flex: 0 0 38.2%;
width: 38.2%;
}
}
// 上下布局
.yo-form--vertical {
display: block;
.ant-form-item-control {
text-align: left;
}
&-radio {
.ant-radio-wrapper {
line-height: @padding-lg;
display: block;
margin-right: 0;
+.ant-radio-wrapper {
margin-top: @padding-sm;
}
}
}
.ant-form-item-control-wrapper {
margin-left: @padding-lg;
}
.ant-form-explain {
margin-left: 0;
}
}
.yo-form-link {
display: flex;
align-items: center;
margin-bottom: -1px;
padding: @padding-md;
cursor: pointer;
border: @border-width-base @border-style-base @border-color-split;
background-color: @component-background;
&:hover {
background-color: lighten(@black, 1%);
}
&:active {
background-color: lighten(@black, 3%);
}
&--title {
font-size: @font-size-base + 1px;
flex: 1;
}
&--content {
flex: 1;
text-align: right;
color: fade(@black, 35%);
}
&--right-icon {
margin-left: @padding-xs;
color: fade(@black, 50%);
}
}
&.yo-form--no-border {
.ant-form-item {
padding: @padding-md 0;
border-right: 0;
border-left: 0;
&:first-child {
border-top: 0;
}
&:last-child {
border-bottom: 0;
}
}
.yo-form-group {
margin-bottom: 0;
}
}
}
.yo-modal-form {
.ant-modal-body {
padding: 0;
}
.yo-form {
h1,
h2,
h3,
h4,
h5 {
margin: 0;
padding: @padding-sm @padding-md @padding-xs;
}
.yo-form-group {
margin-bottom: 0;
}
.ant-form-item {
border-right: 0;
border-left: 0;
&:first-child {
margin-top: -1px;
}
}
}
}
.yo-drawer-form {
.ant-drawer-wrapper-body {
display: flex;
flex-direction: column;
}
.ant-drawer-header {
flex: 0 0 auto;
}
.ant-drawer-body {
position: relative;
flex: 1 1 100%;
padding: 0;
}
.yo-drawer-form--body {
position: absolute;
top: 0;
bottom: @border-width-base + 20px + @padding-md * 2;
overflow: auto;
width: 100%;
padding: @padding-lg;
}
.ant-drawer-footer {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
padding: 10px @padding-md;
text-align: right;
border-top: @border-width-base @border-style-base @border-color-split;
background: @component-background;
button+button {
margin-left: @padding-xs;
}
}
}
.ant-form {
fieldset {
margin-bottom: @padding-lg;
padding: @padding-md;
border: @border-width-base @border-style-base @border-color-split;
}
legend {
display: inline-block;
width: auto;
margin-bottom: 0;
padding: 0 @padding-md;
border: 0;
border-radius: @border-radius-base;
}
}
.ant-form-horizontal {
.ant-form-item-label {
line-height: 1.5;
margin-right: @padding-xs;
white-space: normal;
}
}
.ant-form-vertical {
.ant-form-item-label {
>label {
font-weight: bold;
}
}
}
.ant-form-item-required {
&::before {
content: '' !important;
vertical-align: middle;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
border-left: 5px solid @highlight-color;
background: none;
}
}
.yo-form-page {
.ant-form {
.ant-radio-button-wrapper {
margin-right: @padding-xs;
margin-bottom: @padding-xs;
border-left: @border-width-base @border-style-base @border-color-base;
&.ant-radio-button-wrapper-checked {
border-left-color: @primary-color;
}
&:not(:first-child) {
&::before {
content: none;
}
}
}
}
}
.yo-filter-item {
display: flex;
flex-flow: row wrap;
margin-bottom: 0;
.ant-tag-checkable {
font-size: @font-size-base;
}
.ant-radio-button-wrapper {
border: 0 !important;
background-color: transparent;
&:hover {
color: @red-6;
}
}
.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled) {
border-color: @red-6;
background-color: @red-6;
&:hover {
border-color: @red-5;
background-color: @red-5;
}
&:active {
border-color: @red-7;
background-color: @red-7;
box-shadow: none;
}
}
}

View File

@@ -7,16 +7,17 @@
.ant-modal-header { .ant-modal-header {
padding: @padding-sm @padding-md; padding: @padding-sm @padding-md;
border-bottom: 0;
background-color: transparent; background-color: transparent;
} }
.ant-modal-title { .ant-modal-title {
color: fade(@white, 85%); color: fade(@white, 85%);
} }
.ant-modal-body { .ant-modal-body {
background-color: @white; background-color: @component-background;
} }
.ant-modal-footer { .ant-modal-footer {
background-color: @white; background-color: @component-background;
} }
.ant-modal-close { .ant-modal-close {
top: 10px; top: 10px;
@@ -35,3 +36,6 @@
width: 26px; width: 26px;
height: 26px; height: 26px;
} }
.ant-modal-mask {
backdrop-filter: blur(3px);
}

View File

@@ -0,0 +1,14 @@
@import (reference) '../extend.less';
::-webkit-scrollbar {
width: 7px;
height: 7px;
background-color: fade(@white, 10%);
}
::-webkit-scrollbar-thumb {
border-radius: @border-radius-base;
background-color: fade(@white, 30%);
}
::-webkit-scrollbar-thumb:active {
background-color: fade(@white, 50%);
}

View File

@@ -75,6 +75,9 @@
.ant-table-sticky-scroll { .ant-table-sticky-scroll {
display: none; display: none;
} }
.ant-table-expanded-row>td {
border-right: @border-width-base @border-style-base @table-border-color !important;
}
.yo-table { .yo-table {
.ant-table { .ant-table {
margin: 0 !important; margin: 0 !important;
@@ -196,11 +199,13 @@
} }
} }
.ant-table-tbody { .ant-table-tbody {
>.ant-table-expanded-row-level-1>td { >.ant-table-expanded-row>td {
padding: 0; padding: 0;
border-right: none !important; border-right: none !important;
.ant-table-wrapper { .ant-table-wrapper {
margin-bottom: -1px;
border: none; border: none;
.ant-table { .ant-table {
margin: 0 !important; margin: 0 !important;
@@ -215,20 +220,17 @@
padding-left: @padding-md; padding-left: @padding-md;
} }
} }
.ant-table-expanded-row-level-1>td { .ant-table-tbody {
padding: @padding-sm @padding-xs @padding-sm @padding-xl; >tr {
&:last-child {
border-right: @border-width-base @border-style-base @table-border-color !important; >td {
.ant-card { border-bottom: @border-width-base @border-style-base @table-border-color;
max-width: fit-content; }
margin-bottom: 0; &:hover {
>td {
background: none; border-bottom-color: lighten(@primary-color, 30%);
.ant-card-grid { }
width: 300px; }
padding: @padding-xs @padding-sm;
background-color: @white;
} }
} }
} }
@@ -237,4 +239,17 @@
} }
} }
} }
.ant-card {
max-width: fit-content;
margin: @padding-sm @padding-xs @padding-sm @padding-xl;
background: none;
.ant-card-grid {
width: 300px;
height: 90px;
padding: @padding-xs @padding-sm;
background-color: @card-background;
}
}
} }

View File

@@ -22,10 +22,10 @@
color: @warning-color; color: @warning-color;
} }
.text-gray { .text-gray {
color: gray; color: fade(@white, 50%);
} }
.text-normal { .text-normal {
color: @normal-color; color: fade(@white, 30%);
} }
.text-white { .text-white {
color: @white; color: @white;

View File

@@ -0,0 +1,83 @@
@import (reference) '../extend.less';
@import (reference) './text-color.less';
.yo-tree-layout {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
.ant-layout-sider {
background-color: @component-background;
.ant-layout-header {
height: @layout-header-height - 20px;
background-color: @component-background;
.header-actions {
.ant-input-search {
margin: (@layout-header-height - 20px - 32px) / 2 @padding-md;
}
}
}
}
&--collapsed {
position: absolute;
top: 0;
left: 0;
bottom: 0;
z-index: 4;
transform: translateX(-100%);
&.open {
transform: translateX(0);
box-shadow: 2px 0 8px fade(@black , 20%);
}
}
&--bar {
line-height: 20px;
height: 20px;
padding: 0 @padding-md;
text-align: right;
>.anticon {
margin-left: @padding-xs;
cursor: pointer;
color: fade(@white, 50%);
&:hover {
color: fade(@white, 80%);
}
}
}
&--content {
position: absolute;
top: @layout-header-height;
left: 0;
bottom: 0;
overflow-y: auto;
width: 100%;
&::-webkit-scrollbar {
width: 5px;
height: 5px;
background-color: @component-background;
}
&::-webkit-scrollbar-thumb {
background-color: transparent;
}
&:hover::-webkit-scrollbar-thumb {
background-color: fade(@white, 30%);
}
&::-webkit-scrollbar-thumb:active {
background-color: fade(@white, 45%);
}
}
.ant-tree {
.text-gray();
}
}

View File

@@ -21,26 +21,25 @@
display: flex; display: flex;
} }
.ellipsis { .ellipsis {
display: block;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.ellipsis-2 { .ellipsis-line(@line) {
display: -webkit-box; display: -webkit-box;
overflow: hidden; overflow: hidden;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
text-overflow: ellipsis; text-overflow: ellipsis;
word-break: break-all;
-webkit-line-clamp: 2; -webkit-line-clamp: @line;
}
.ellipsis-2 {
.ellipsis-line(2);
} }
.ellipsis-3 { .ellipsis-3 {
display: -webkit-box; .ellipsis-line(3);
overflow: hidden;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
-webkit-line-clamp: 3;
} }

View File

@@ -0,0 +1,697 @@
@import (reference) './extend.less';
@import (reference) './lib/container.less';
@import (reference) './lib/text-color.less';
.yo-layout--spin {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: @layout-header-background;
>.ant-spin-nested-loading {
height: 100%;
>div>.ant-spin {
max-height: none;
@-webkit-keyframes borderScale {
0% {
border: 5px solid white;
}
50% {
border: 25px solid transparent;
}
100% {
border: 5px solid white;
}
}
@keyframes borderScale {
0% {
border: 5px solid white;
}
50% {
border: 25px solid transparent;
}
100% {
border: 5px solid white;
}
}
.loader-container {
position: absolute;
top: 50%;
left: 50%;
box-sizing: content-box;
width: 200px;
height: 200px;
margin: 0 auto;
margin-right: -50%;
transform: translate(-50%, -50%);
-webkit-animation: borderScale 1s infinite ease-in-out;
animation: borderScale 1s infinite ease-in-out;
color: white;
border: 5px solid transparent;
border-radius: 50%;
>p {
font-family: 'Raleway', sans-serif;
font-size: 2em;
font-weight: bold;
position: absolute;
top: 50%;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
}
}
}
>.ant-spin-container {
width: 100%;
height: 100%;
&.ant-spin-blur {
opacity: 0;
}
}
}
}
.ant-layout-header {
.header-actions {
display: flex;
.header-action {
display: inline-block;
padding: 0 @padding-md;
cursor: pointer;
transition: @animation-duration-slow;
transition-property: background-color;
.anticon {
font-size: @font-size-base + 6px;
transition: @animation-duration-slow;
transition-property: color;
}
&:active {
box-shadow: inset 1px 1px 10px rgba(0, 0, 0, .05);
}
// 特殊工具按钮
.theme-toggle {
position: relative;
overflow: hidden;
width: 20px;
height: 20px;
margin: 7px 0;
border-radius: 50%;
&--real {
position: relative;
width: 20px;
height: 20px;
transition: @animation-duration-slow background-color;
border-radius: 50%;
background-color: fade(@white, 60%);
&::before {
position: absolute;
top: 5px;
left: 5px;
width: 10px;
height: 10px;
content: '';
transition: @animation-duration-slow transform;
transform: scale(0);
border: 2px solid @layout-header-background;
border-radius: 50%;
}
}
&--imaginary {
position: absolute;
top: 6px;
right: -6px;
width: 18px;
height: 18px;
transition: @animation-duration-slow transform;
transform: rotate(45deg) scaleY(1);
transform-origin: top right;
border-radius: 50%;
background-color: @layout-header-background;
}
}
&:hover {
.theme-toggle {
&--real {
background-color: @white;
&::before {
transform: scale(1);
}
}
&--imaginary {
transform: rotate(45deg) scaleY(0);
}
}
}
}
.ant-select-auto-complete {
margin: (@layout-header-height - 10px - 30px) / 2 @padding-md;
.ant-input-affix-wrapper {
border: 0;
background-color: fade(@white, 15%);
&:focus,
&-focused {
background-color: fade(@white, 30%);
}
.ant-input {
color: fade(@white, 85%);
background-color: transparent;
}
.ant-input-suffix {
.anticon {
color: fade(@white, 60%);
}
}
}
}
}
.user-container {
z-index: 10;
width: 32px + @padding-sm * 2;
height: @layout-header-height - 24px;
margin: 2px 0;
transition: @animation-duration-slow;
.user-container-inner {
position: relative;
transition: @animation-duration-slow;
border-radius: @border-radius-base;
}
.user {
&--base {
line-height: @layout-header-height - 24px;
position: relative;
display: flex;
overflow: hidden;
align-items: center;
width: 100%;
height: @layout-header-height - 24px;
padding: 0 @padding-sm;
transition: @animation-duration-slow;
}
&--avatar {
box-shadow: 0 0 0 2px @white;
}
}
}
}
.ant-layout-content {
position: relative;
overflow-y: auto;
>.yo-tab-external-mount {
position: absolute;
top: 0;
left: 0;
bottom: 0;
display: flex;
flex-direction: column;
width: 100%;
>.ant-tabs {
z-index: 5;
overflow: visible;
>.ant-tabs-nav {
margin-bottom: 0;
border-bottom: 0;
background-color: @layout-header-background;
box-shadow: 0 2px 12px fade(@black, 8%);
&::before {
content: none;
}
.ant-tabs-nav-container {
height: 30px;
margin-bottom: 0;
}
.ant-tabs-tab {
line-height: 30px;
height: 30px;
margin-right: 0;
padding: 0;
transition: none;
border: 0;
background-color: transparent;
&:hover {
color: @white;
}
.ant-tabs-tab-btn {
transition: none;
}
&.ant-tabs-tab-active {
border-color: darken(@primary-color, 10%);
background-color: @primary-color;
.ant-tabs-tab-btn {
color: @white;
}
.ant-tabs-tab-remove {
color: fade(@white, 70%);
&:hover {
color: @white;
}
}
}
.yo-layout-tab-subtitle {
line-height: 1;
display: inline-block;
overflow: hidden;
max-width: 150px;
transform: translateY(1px);
white-space: nowrap;
text-overflow: ellipsis;
opacity: .75;
}
+.ant-tabs-tab {
margin-left: 0;
&::before {
position: absolute;
left: -.5px;
width: 1px;
height: 24px;
content: '';
transform: scaleX(.5);
background: linear-gradient(transparent, fade(@black, 30%), transparent);
}
}
.ant-dropdown-trigger {
padding: 0 @padding-md * 2 0 @padding-md;
}
.ant-tabs-tab-unclosable {
.ant-dropdown-trigger {
padding: 0 @padding-lg 0 @padding-md;
}
}
.ant-tabs-tab-remove {
line-height: 28px;
position: absolute;
top: 0;
right: 0;
margin: 0;
transition: none;
}
}
.ant-tabs-nav-more {
padding: 5px @padding-md;
}
}
}
>.yo-tab-external-mount-content {
position: relative;
height: 100%;
>.yo-tab-external-tabpane {
position: absolute;
top: 0;
left: 0;
overflow-x: hidden;
overflow-y: auto;
width: 100%;
height: 100%;
&.yo-tab-external-tabpane-inactive {
pointer-events: none;
opacity: 0;
}
>iframe {
display: block;
width: 100%;
height: 100%;
border: 0;
}
}
}
}
}
.ant-layout-sider {
.ant-menu-inline {
border-right: 0;
}
}
.yo-nav {
padding-top: @padding-lg;
padding-bottom: @padding-lg;
&--row {
padding: 1px 0;
column-gap: @padding-md;
column-count: 3;
}
&--col {
break-inside: avoid;
}
&--sub-item {
}
&--item-group {
font-size: @font-size-base;
line-height: 1.5;
margin-bottom: @padding-xs;
padding-top: @padding-xs * 2;
color: fade(@black, 35%);
border: @border-width-base @border-style-base transparent;
}
&--item {
font-size: @font-size-base;
line-height: 1.5;
position: relative;
margin-bottom: @padding-xs;
padding: @padding-xs @padding-sm;
cursor: pointer;
transition: @animation-duration-fast;
border: @border-width-base @border-style-base @border-color-split;
border-radius: @border-radius-base;
background-color: @white;
&:hover {
color: @white;
border-color: @primary-color;
background-color: @primary-color;
}
}
}
.yo-layout-sider {
height: 100%;
background-color: @layout-header-background;
.ant-layout-sider-children {
display: flex;
flex-direction: column;
}
.logo {
font-size: @font-size-lg * 1.5;
font-weight: 500;
line-height: @layout-header-height + 10px;
z-index: 11;
display: flex;
overflow: hidden;
align-items: center;
flex: 0 0 @layout-header-height + 10px;
height: @layout-header-height + 10px;
padding: 0 @padding-md 0 @padding-lg;
color: @white;
box-shadow: none;
img {
max-height: 100%;
}
span {
margin-left: @padding-sm;
transition: @animation-duration-slow;
transition-property: opacity;
}
}
&.ant-layout-sider-collapsed {
.logo {
span {
opacity: 0;
}
}
}
.yo-sider-nav {
position: relative;
z-index: 10;
flex: 1 1 100%;
box-shadow: 2px 0 8px fade(@black, 25%);
&--app {
font-size: @font-size-sm;
margin-top: @padding-sm;
padding: 0 @padding-md;
.text-gray();
}
.ant-menu {
background-color: @layout-header-background;
}
.ant-menu-sub.ant-menu-inline {
background-color: fade(@white, 4%);
}
}
.swiper-container {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100%;
.swiper-scrollbar {
transition: @animation-duration-slow;
transition-property: opacity;
opacity: 0;
}
.swiper-scrollbar-drag {
background-color: fade(@white, 30%);
}
&:hover {
.swiper-scrollbar {
opacity: 1;
}
}
}
.swiper-slide {
height: auto;
min-height: 100%;
>.ant-spin-nested-loading {
height: 100%;
.ant-spin-blur {
&::after {
opacity: 0;
}
}
}
}
}
.yo-layout--left-menu,
.yo-layout--right-menu {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
.ant-layout-header {
line-height: @layout-header-height - 20px;
z-index: 6;
height: @layout-header-height - 20px;
padding: 0;
background-color: @white;
>section {
display: flex;
justify-content: space-between;
}
.header-actions {
.header-action {
line-height: @layout-header-height - 16px;
height: @layout-header-height - 20px;
.anticon {
color: fade(@black, 35%);
}
&:hover {
background-color: fade(@black, 5%);
.anticon {
color: @icon-color-hover;
}
}
}
}
}
>section {
>.ant-layout-sider {
.yo-layout-sider();
}
}
}
.yo-layout--top-nav {
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
@layout-header-height: 54px;
.ant-layout-header {
line-height: @layout-header-height;
z-index: 11;
flex: 0 0 @layout-header-height;
height: @layout-header-height;
padding: 0;
background-color: @layout-header-background;
section {
display: flex;
justify-content: space-between;
height: 100%;
}
.header-actions {
.header-action {
.anticon {
color: fade(@white, 60%);
}
&:hover {
background-color: fade(@white, 20%);
.anticon {
color: @white;
}
}
}
}
.user-container {
margin: (@layout-header-height - 40px) / 2 0;
}
.logo {
font-size: @font-size-lg * 1.5;
font-weight: 500;
line-height: @layout-header-height - 10px;
display: flex;
overflow: hidden;
align-items: center;
height: @layout-header-height 10px;
margin: 5px @padding-lg 5px 0;
color: @white;
img {
max-height: 100%;
}
span {
margin-left: @padding-sm;
}
}
.ant-menu-horizontal {
line-height: @layout-header-height;
border-bottom: 0;
>.ant-menu-submenu {
top: 0;
border-bottom: 0;
}
}
.header-actions {
.header-action {
line-height: @layout-header-height - 16px;
margin: 10px 0;
}
}
}
&--container {
.ant-layout-header {
.ant-menu-horizontal {
width: 400px;
}
}
.ant-layout-content {
.yo-tab-external-mount {
>.ant-tabs {
>.ant-tabs-bar {
.ant-tabs-nav-container {
width: @container-width - @padding-md * 2;
margin: 0 auto;
}
}
}
}
}
}
&--container-fluid {
.ant-layout-header {
.ant-menu-horizontal {
width: 800px;
}
@media (max-width: 1400px) {
.ant-menu-horizontal {
width: 600px;
}
}
}
}
}
.yo-user-popover {
width: 280px;
padding-top: 0;
.ant-popover-arrow {
display: none;
}
.ant-popover-inner-content {
padding: 0;
}
}
.yo-popover-infinite-scroll {
.ant-popover-inner-content {
overflow-y: auto;
max-height: 300px;
}
}

View File

@@ -1,4 +1,4 @@
@import (reference) '~assets/style/app.less'; @import (reference) '../extend.less';
.yo-avatar-info { .yo-avatar-info {
position: relative; position: relative;

View File

@@ -1,9 +1,9 @@
@import (reference) 'assets/style/app.less'; @import (reference) '../extend.less';
.home-header { .home-header {
margin-bottom: @padding-md; margin-bottom: @padding-md;
padding: @padding-lg 0; padding: @padding-lg 0;
background-color: @white; background-color: @component-background;
} }
.home-header-row { .home-header-row {
display: flex; display: flex;

View File

@@ -0,0 +1,3 @@
@import './login.less';
@import './home.less';
@import './account-base.less';

View File

@@ -0,0 +1,89 @@
@import (reference) '../extend.less';
.yo-login {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
>img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
&::before {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: '';
background: fade(@black, 30%) url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABZJREFUeNpiMLJ0+w8EDIwgAgQAAgwAUdAHrAFSJ6cAAAAASUVORK5CYII=);
}
&--placeholder {
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: 0;
.container-sm {
display: flex;
align-items: center;
justify-content: flex-end;
height: 0;
}
}
.ant-form {
width: 300px;
padding: @padding-lg;
border-radius: @border-radius-base + 2px;
background: linear-gradient(45deg, @component-background, fade(@component-background, 80%));
}
.ant-form-item {
margin-bottom: 0;
}
.ant-form-item-label {
padding: @padding-xs 0 0 !important;
transition: @animation-duration-base;
transform: translate(0);
>label {
font-weight: normal !important;
color: fade(@white, 40%);
}
}
&--label {
.ant-form-item-label {
transform: translate(11px, 28px);
}
}
.ant-input,
.ant-input-affix-wrapper {
color: fade(@white, 85%);
border-width: 0 0 @border-width-base 0 !important;
border-color: fade(@white, 10%);
background-color: transparent;
}
.ant-input:hover,
.ant-input:focus,
.ant-input-affix-wrapper:not(.ant-input-affix-wrapper-disabled):hover,
.ant-input-affix-wrapper:focus,
.ant-input-affix-wrapper-focused {
border-width: 0 0 @border-width-base 0 !important;
border-color: @primary-color;
box-shadow: none !important;
}
.ant-input::placeholder {
font-size: @font-size-base;
}
}

View File

@@ -0,0 +1,45 @@
@import (reference) './extend.less';
.yo-map {
&-container {
position: relative;
padding: @padding-sm;
border: @border-width-base @border-style-base @border-color-split;
border-radius: @border-radius-base;
background-color: @component-background;
.amap-icon {
img {
width: 25px;
}
}
}
&--search {
position: absolute;
top: @padding-md;
left: @padding-md;
z-index: 20;
width: 25%;
min-width: 300px;
background-color: @component-background;
box-shadow: @box-shadow-base;
}
}
.yo-adorn {
&--house-top {
height: 65px;
background: url('~assets/image/adorn/house-top-01.png') no-repeat bottom right;
}
}
a.link-gray {
color: fade(@white, 50%);
&:hover {
color: @link-hover-color;
}
&:active {
color: @link-active-color;
}
}

View File

@@ -0,0 +1,5 @@
@import '../index.less';
@primary-color: #00a091;
@error-color: @red-7;
@font-size-base: 13px;
@border-radius-base: 0;

View File

@@ -4,3 +4,8 @@
body { body {
line-height: 1.42857143; line-height: 1.42857143;
} }
#root {
transition: @animation-duration-slow opacity;
opacity: 1 !important;
}

View File

@@ -0,0 +1,35 @@
@import './extend.less';
@import './lib/visibility.less';
@import './lib/container.less';
@import './lib/align.less';
@import './lib/font-size.less';
@import './lib/text-color.less';
@import './lib/margin.less';
@import './lib/width-height.less';
@import './lib/scrollbar.less';
@import './main.less';
@import './lib/button.less';
@import './lib/card.less';
@import './lib/table.less';
@import './lib/list.less';
@import './lib/form.less';
@import './lib/form-page.less';
@import './lib/page.less';
@import './lib/description.less';
@import './lib/input.less';
@import './lib/select.less';
@import './lib/checkbox.less';
@import './lib/radio.less';
@import './lib/cascader.less';
@import './lib/upload.less';
@import './lib/dropdown.less';
@import './lib/modal.less';
@import './lib/tree-layout.less';
@import './lib/authority-view.less';
@import './lib/icon-selector.less';
@import './lib/color-selector.less';
@import './lib/anchor.less';
@import './lib/disabled.less';
@import './theme/primary.less';
@import './public.less';
@import './pages/index.less';

View File

@@ -0,0 +1,9 @@
.text-left {
text-align: left !important;
}
.text-center {
text-align: center !important;
}
.text-right {
text-align: right !important;
}

View File

@@ -0,0 +1,11 @@
@import (reference) '../extend.less';
.ant-anchor-ink-ball {
width: 2px;
height: 28px;
transform: translate(-50%, -10px);
border: 0;
border-radius: 0;
background-color: @primary-color;
}

View File

@@ -0,0 +1,53 @@
@import (reference) '../extend.less';
.yo-authority-view {
&--container {
>.ant-descriptions-view {
border: 0;
}
}
.ant-descriptions-item-label {
width: 150px;
}
.ant-descriptions {
clear: both;
margin-bottom: @padding-sm;
.ant-descriptions-view {
overflow: visible;
}
&:last-child {
margin-bottom: 0;
}
}
.ant-descriptions-item-content {
padding: @padding-sm @padding-md;
.yo-authority-view--checkbox {
display: inline-block;
width: 150px;
margin: @padding-xxs 0;
.ant-checkbox-wrapper {
margin: 0;
}
}
}
.ant-card-grid {
width: 25%;
margin-bottom: @padding-sm;
padding: @padding-xs;
cursor: pointer;
}
.ant-card {
margin-bottom: 0;
background-color: transparent;
&-body {
margin: -1px 0 0 -1px;
padding: 0;
}
.ant-card-grid {
margin-bottom: 0;
}
}
}

View File

@@ -0,0 +1,4 @@
@import (reference) '../extend.less';
.ant-btn {
box-shadow: none;
}

View File

@@ -0,0 +1,6 @@
@import (reference) '../extend.less';
.ant-cascader-picker-arrow {
svg {
transform: scaleY(.75);
}
}

View File

@@ -0,0 +1,10 @@
@import (reference) '../extend.less';
.ant-checkbox-wrapper {
margin-right: @padding-xs;
&:last-child {
margin-right: 0;
}
+.ant-checkbox-wrapper {
margin-left: 0;
}
}

View File

@@ -0,0 +1,43 @@
@import (reference) '../extend.less';
@container-width: 1400px;
.container-base {
margin: 0 auto;
padding: 0 @padding-md;
}
.container {
width: @container-width;
.container-base();
}
@media (max-width: 1400px) {
.container {
width: auto;
}
}
.container-md {
width: @container-width - 200px;
.container-base();
}
.container-sm {
width: @container-width - 400px;
.container-base();
}
.container-xs {
width: @container-width - 600px;
.container-base();
}
.container-xxs {
width: @container-width - 700px;
.container-base();
}
.container-fluid {
.container-base();
}
.container-flex {
display: flex;
justify-content: space-between;
}

View File

@@ -0,0 +1,10 @@
@import (reference) '../extend.less';
.ant-descriptions-bordered {
.ant-descriptions-view {
>table {
border-collapse: collapse;
background-color: @component-background;
}
}
}

View File

@@ -0,0 +1,59 @@
@import (reference) '../extend.less';
.ant-btn-primary-disabled,
.ant-btn-primary.disabled,
.ant-btn-primary[disabled],
.ant-btn-primary-disabled:hover,
.ant-btn-primary.disabled:hover,
.ant-btn-primary[disabled]:hover,
.ant-btn-primary-disabled:focus,
.ant-btn-primary.disabled:focus,
.ant-btn-primary[disabled]:focus,
.ant-btn-primary-disabled:active,
.ant-btn-primary.disabled:active,
.ant-btn-primary[disabled]:active,
.ant-btn-primary-disabled.active,
.ant-btn-primary.disabled.active,
.ant-btn-primary[disabled].active {
opacity: .5;
color: @btn-primary-color;
border-color: @btn-primary-bg;
background-color: @btn-primary-bg;
box-shadow: @btn-primary-shadow;
text-shadow: @btn-text-shadow;
}
.ant-btn-danger-disabled,
.ant-btn-danger.disabled,
.ant-btn-danger[disabled],
.ant-btn-danger-disabled:hover,
.ant-btn-danger.disabled:hover,
.ant-btn-danger[disabled]:hover,
.ant-btn-danger-disabled:focus,
.ant-btn-danger.disabled:focus,
.ant-btn-danger[disabled]:focus,
.ant-btn-danger-disabled:active,
.ant-btn-danger.disabled:active,
.ant-btn-danger[disabled]:active,
.ant-btn-danger-disabled.active,
.ant-btn-danger.disabled.active,
.ant-btn-danger[disabled].active {
opacity: .5;
color: @btn-danger-color;
border-color: @btn-danger-border;
background-color: @btn-danger-bg;
box-shadow: @btn-primary-shadow;
text-shadow: @btn-text-shadow;
}
.ant-radio-button-wrapper-disabled,
.ant-radio-button-wrapper-disabled:first-child,
.ant-radio-button-wrapper-disabled:hover {
opacity: .5;
color: @radio-button-color;
background-color: @radio-button-bg;
}
.ant-radio-button-wrapper-disabled.ant-radio-button-wrapper-checked {
opacity: .5;
color: @btn-primary-color;
border-color: @btn-primary-bg;
background-color: @btn-primary-bg;
box-shadow: @btn-primary-shadow;
}

View File

@@ -0,0 +1,6 @@
@import (reference) '../extend.less';
.ant-dropdown-trigger {
.anticon-down {
transform: scaleY(.75);
}
}

View File

@@ -0,0 +1,25 @@
@import (reference) '../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: 16px;
}
h6,
.h6 {
font-size: 14px;
}

View File

@@ -0,0 +1,24 @@
@import (reference) '../extend.less';
body {
font-weight: 100;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 300;
}
@btn-font-weight: 100;
.ant-card-meta-title {
font-weight: inherit;
}
.ant-table-thead {
>tr {
>th {
font-weight: 500;
}
}
}

View File

@@ -0,0 +1,169 @@
@import (reference) '../extend.less';
.yo-form-page {
position: relative;
height: 100%;
.yo-tab-external-mount {
display: flex;
flex-direction: column;
height: 100%;
>.ant-tabs {
>.ant-tabs-nav {
margin-bottom: 0;
padding: 0 @padding-md;
background-color: @component-background;
&.ant-tabs-card-bar {
.ant-tabs-nav-container {
height: @tabs-card-height + @padding-xs;
padding: (@tabs-card-height + @padding-xs - @btn-height-base) / 2 @padding-md;
}
.ant-tabs-extra-content {
padding: (@tabs-card-height + @padding-xs - @btn-height-base) / 2 @padding-md;
}
.ant-tabs-tab {
transition: none;
.ant-btn();
&:hover {
border-color: @btn-default-border;
}
}
.ant-tabs-tab {
line-height: @btn-height-base;
margin-right: -1px;
}
.ant-tabs-tab-active {
z-index: 2;
color: @btn-primary-color;
border-color: @btn-primary-bg;
background-color: @btn-primary-bg;
&:hover {
color: @btn-primary-color;
border-color: color(~`colorPalette('@{btn-primary-bg}', 5) `);
background-color: color(~`colorPalette('@{btn-primary-bg}', 5) `);
}
}
}
}
}
>.yo-tab-external-mount-content {
position: relative;
flex: 1;
>.yo-tab-external-tabpane {
position: absolute;
top: 0;
left: 0;
overflow: auto;
width: 100%;
height: 100%;
&.yo-tab-external-tabpane-inactive {
pointer-events: none;
opacity: 0;
}
}
}
}
&--bar {
position: sticky;
bottom: 0;
z-index: 200;
&--with-tab {
position: absolute;
display: flex;
align-items: flex-end;
width: 100%;
height: 0;
padding-right: 7px;
>.container-fluid {
width: 100%;
}
~.yo-tab-external-mount {
>.yo-tab-external-mount-content {
>.yo-tab-external-tabpane {
padding-bottom: @padding-xs * 2 + @btn-height-base + @border-width-base * 2;
}
}
}
}
}
&--bar-inner {
display: flex;
justify-content: space-between;
padding: @padding-xs @padding-md;
border: @border-width-base @border-style-base @border-color-split;
background-color: fade(@component-background, 80%);
backdrop-filter: blur(5px);
>:first-child {
flex: 1;
}
.ant-btn {
margin-left: @padding-sm;
}
}
&--body {
>.ant-card-body {
padding: 0;
>section {
padding: @padding-lg;
>h5 {
padding-left: @padding-md;
border-left: @padding-xs @border-style-base @primary-color;
}
}
}
}
&-layout {
display: flex;
flex-direction: column;
height: 100%;
&--horizontal {
flex-direction: row;
}
}
&--header {
padding: @padding-md 0;
background-color: @component-background;
}
}

View File

@@ -29,7 +29,7 @@
padding: @padding-xs @padding-md; padding: @padding-xs @padding-md;
border: @border-width-base @border-style-base @border-color-split; border: @border-width-base @border-style-base @border-color-split;
background-color: @white; background-color: @component-background;
@box-shadow-focused: 0 0 0 2px fade(@primary-color, 50%); @box-shadow-focused: 0 0 0 2px fade(@primary-color, 50%);
@control-background: lighten(@black, 95%) !important; @control-background: lighten(@black, 95%) !important;
@@ -58,7 +58,7 @@
} }
.ant-mentions { .ant-mentions {
textarea { textarea {
background-color: lighten(@black, 95%); background-color: @control-background;
} }
} }
.focus { .focus {
@@ -151,6 +151,8 @@
flex: 0 0 100%; flex: 0 0 100%;
width: 100%; width: 100%;
text-align: inherit;
} }
} }
.yo-form--short { .yo-form--short {
@@ -299,7 +301,7 @@
text-align: right; text-align: right;
border-top: @border-width-base @border-style-base @border-color-split; border-top: @border-width-base @border-style-base @border-color-split;
background: @white; background: @component-background;
button+button { button+button {
margin-left: @padding-xs; margin-left: @padding-xs;
} }
@@ -346,7 +348,7 @@
border-top: 4px solid transparent; border-top: 4px solid transparent;
border-bottom: 4px solid transparent; border-bottom: 4px solid transparent;
border-left: 5px solid #f5222d; border-left: 5px solid @highlight-color;
background: none; background: none;
} }
} }
@@ -356,7 +358,7 @@
margin-right: @padding-xs; margin-right: @padding-xs;
margin-bottom: @padding-xs; margin-bottom: @padding-xs;
border-left: @border-width-base @border-style-base @normal-color; border-left: @border-width-base @border-style-base @border-color-base;
&.ant-radio-button-wrapper-checked { &.ant-radio-button-wrapper-checked {
border-left-color: @primary-color; border-left-color: @primary-color;
} }

View File

@@ -0,0 +1,59 @@
@import (reference) '../extend.less';
.yo-icon-selector {
.ant-drawer-wrapper-body {
display: flex;
flex-direction: column;
}
.ant-drawer-body {
position: relative;
flex: 1 1 100%;
padding: 0;
}
.ant-tabs {
height: 100%;
.ant-tabs-content-left {
position: relative;
height: 100%;
.ant-tabs-tabpane {
position: absolute;
top: 0;
left: 0;
overflow-y: auto;
width: 100%;
height: 100%;
padding: @padding-lg;
}
}
}
.ant-card {
margin: 0;
}
.ant-card-grid {
width: 25%;
text-align: center;
>span {
font-size: @font-size-sm;
display: block;
margin: @padding-xxs -@padding-lg 0;
white-space: nowrap;
color: fade(@black, 50%);
}
&.yo-icon--selected {
color: @white;
background-color: @primary-color;
>span {
color: fade(@white, 50%);
}
}
}
}

View File

@@ -0,0 +1,4 @@
@import (reference) '../extend.less';
.yo-addon {
padding: 0 @padding-xs;
}

View File

@@ -0,0 +1,95 @@
@import (reference) '../extend.less';
.ant-list-bordered {
border-color: @border-color-split;
background-color: @white;
}
.yo-list {
@title-color: lighten(@black, 70%);
@value-color: lighten(@black, 30%);
&-content--h {
display: flex;
align-items: center;
&--item {
margin-left: @padding-xl;
>span {
line-height: 20px;
color: @title-color;
}
>p {
line-height: 22px;
margin-top: @padding-xxs;
margin-bottom: 0;
color: @value-color;
}
}
}
.ant-pagination {
margin: @padding-md 0;
}
.ant-descriptions {
.ant-descriptions-item-label {
color: @title-color;
}
.ant-descriptions-item-content {
color: @value-color;
}
.ant-descriptions-row {
&:last-child {
>td {
padding-bottom: 0;
}
}
}
}
&--scroll {
position: relative;
overflow-x: auto;
}
.ant-list-items {
min-width: 1000px;
}
.ant-list-item {
transition: @animation-duration-slow;
transition-property: background, border-bottom-color;
&:hover {
border-bottom-color: lighten(@primary-color, 30%);
background: linear-gradient(90deg, transparent 10%, @background-color-light 70%, transparent);
}
}
&-container {
position: relative;
&::before,
&::after {
position: absolute;
top: 0;
bottom: 0;
z-index: 3;
width: 30px;
content: '';
transition: box-shadow @animation-duration-slow;
pointer-events: none;
}
&::before {
left: 0;
}
&::after {
right: 0;
}
&.yo-list--ping-left {
&::before {
box-shadow: inset 10px 0 8px -8px fade(@black, 15%);
}
}
&.yo-list--ping-right {
&::after {
box-shadow: inset -10px 0 8px -8px fade(@black, 15%);
}
}
}
}

View File

@@ -0,0 +1,68 @@
@import (reference) '../extend.less';
@margin-padding-position: ~'', ~'-top', ~'-left', ~'-right', ~'-bottom';
@margin-padding-position-name: ~'', ~'t', ~'l', ~'r', ~'b';
.margin-padding (@i) when (@i <=length(@margin-padding-position)) {
@position: extract(@margin-padding-position, @i);
@name: extract(@margin-padding-position-name, @i);
.m@{name}-xl {
margin@{position}: @padding-xl !important;
}
.m@{name}-lg {
margin@{position}: @padding-lg !important;
}
.m@{name}-md {
margin@{position}: @padding-md !important;
}
.m@{name}-sm {
margin@{position}: @padding-sm !important;
}
.m@{name}-xs {
margin@{position}: @padding-xs !important;
}
.m@{name}-xxs {
margin@{position}: @padding-xxs !important;
}
.p@{name}-xl {
padding@{position}: @padding-xl !important;
}
.p@{name}-lg {
padding@{position}: @padding-lg !important;
}
.p@{name}-md {
padding@{position}: @padding-md !important;
}
.p@{name}-sm {
padding@{position}: @padding-sm !important;
}
.p@{name}-xs {
padding@{position}: @padding-xs !important;
}
.p@{name}-xxs {
padding@{position}: @padding-xxs !important;
}
.m@{name}-none {
margin@{position}: 0 !important;
}
.p@{name}-none {
padding@{position}: 0 !important;
}
.margin-padding(@i + 1);
}
.margin-padding(1);

View File

@@ -0,0 +1,41 @@
@import (reference) '../extend.less';
.ant-modal-content {
background-color: fade(@primary-color, 50%);
backdrop-filter: blur(5px);
}
.ant-modal-header {
padding: @padding-sm @padding-md;
border-bottom: 0;
background-color: transparent;
}
.ant-modal-title {
color: fade(@white, 85%);
}
.ant-modal-body {
background-color: @component-background;
}
.ant-modal-footer {
background-color: @component-background;
}
.ant-modal-close {
top: 10px;
right: 10px;
color: fade(@white, 75%);
background-color: @error-color;
&:hover,
&:focus {
color: @white;
}
}
.ant-modal-close-x {
line-height: 26px;
width: 26px;
height: 26px;
}
.ant-modal-mask {
backdrop-filter: blur(3px);
}

View File

@@ -0,0 +1,8 @@
@import (reference) '../extend.less';
.yo-page {
&--header {
padding: @padding-md 0;
background-color: @white;
}
}

View File

@@ -0,0 +1,7 @@
@import (reference) '../extend.less';
.ant-radio-button-wrapper-checked {
&:not(.ant-radio-button-wrapper-disabled),
&:not(.ant-radio-button-wrapper-disabled):hover {
box-shadow: none;
}
}

View File

@@ -0,0 +1,6 @@
@import (reference) '../extend.less';
.ant-select-arrow {
.anticon-down {
transform: scaleY(.75);
}
}

View File

@@ -0,0 +1,255 @@
@import (reference) '../extend.less';
.yo-query-bar {
margin-bottom: @padding-xs;
.ant-form-inline {
.ant-form-item {
margin-bottom: @padding-xs;
}
}
}
.yo-action-bar {
display: flex;
justify-content: space-between;
margin-bottom: @padding-md;
&--actions {
>.ant-btn,
>.ant-btn-group {
+.ant-btn,
+.ant-btn-group {
margin-left: @padding-xs;
}
}
}
}
.ant-table {
.ant-table-container {
&::before,
&::after {
z-index: 3;
}
}
}
.ant-table-thead {
th.ant-table-column-has-sorters {
&:hover {
background-color: darken(@background-color-base, 5%);
}
}
}
.ant-table-tbody {
>tr {
>td {
transition-property: background, border-bottom-color;
}
}
>tr.ant-table-row:hover {
>td {
border-bottom-color: lighten(@primary-color, 30%);
}
}
}
.ant-table-small {
>.ant-table-content {
>.ant-table-body {
margin: 0;
>table {
>.ant-table-thead {
>tr {
>th {
background-color: @table-selected-row-bg;
}
}
}
}
}
}
}
.ant-table-thead {
>tr {
>th {
font-weight: bold;
}
}
}
.ant-table-sticky-scroll {
display: none;
}
.ant-table-expanded-row>td {
border-right: @border-width-base @border-style-base @table-border-color !important;
}
.yo-table {
.ant-table {
margin: 0 !important;
}
.border-right-none {
border-right-width: 0 !important;
&:last-child {
border-right-width: 1px !important;
}
}
.ant-table-content {
.ant-table-body {
overflow-x: auto !important;
>table {
>.ant-table-thead {
>tr {
>th {
.border-right-none();
}
}
}
>.ant-table-tbody {
>tr {
>td {
.border-right-none();
}
}
}
}
}
.ant-table-fixed-left {
.ant-table-thead {
>tr {
>th {
border-right-width: 0 !important;
}
}
}
.ant-table-tbody {
>tr {
>td {
border-right-width: 0 !important;
}
}
}
}
.ant-table-fixed-right {
.ant-table-fixed {
border-left-width: 0 !important;
}
.ant-table-thead {
>tr {
>th {
.border-right-none();
}
}
}
.ant-table-tbody {
>tr {
>td {
.border-right-none();
}
}
}
}
}
.ant-table-bordered {
>.ant-table-container {
border-top: @border-width-base @border-style-base @table-border-color;
}
}
&--row-no {
width: 30px !important;
background-color: @table-header-bg;
}
}
.yo-table-actions {
display: inline-block;
vertical-align: middle;
&--inner {
display: flex;
align-items: center;
height: 18px;
}
}
.yo-table--column-setting {
width: 240px;
.ant-dropdown-menu-item {
display: flex;
align-items: center;
justify-content: space-between;
}
.anticon-pushpin {
transition: @animation-duration-slow;
transform: rotate(45deg);
color: darken(@white, 40%);
}
.yo-table--fixed {
transform: rotate(-45deg);
}
}
.yo-menu-table {
.ant-table {
.ant-table-expand-icon-col {
width: 28px;
}
.ant-table-row-expand-icon-cell {
z-index: 1;
padding-right: 0 !important;
border-right: none !important;
+.ant-table-cell {
padding-left: 0;
}
}
.ant-table-tbody {
>.ant-table-expanded-row>td {
padding: 0;
border-right: none !important;
.ant-table-wrapper {
margin-bottom: -1px;
border: none;
.ant-table {
margin: 0 !important;
}
.ant-table-container {
border: none;
.ant-table-row-expand-icon-cell {
.ant-table-row-expand-icon {
left: @padding-md;
}
+.ant-table-cell {
padding-left: @padding-md;
}
}
.ant-table-tbody {
>tr {
&:last-child {
>td {
border-bottom: @border-width-base @border-style-base @table-border-color;
}
&:hover {
>td {
border-bottom-color: lighten(@primary-color, 30%);
}
}
}
}
}
}
}
}
}
}
.ant-card {
max-width: fit-content;
margin: @padding-sm @padding-xs @padding-sm @padding-xl;
background: none;
.ant-card-grid {
width: 300px;
height: 90px;
padding: @padding-xs @padding-sm;
background-color: @card-background;
}
}
}

View File

@@ -0,0 +1,35 @@
@import (reference) '../extend.less';
.text-primary {
color: @primary-color;
}
.text-info {
color: @info-color;
}
.text-success {
color: @success-color;
}
.text-processing {
color: @processing-color;
}
.text-error,
.text-danger {
color: @error-color;
}
.text-highlight {
color: @highlight-color;
}
.text-warning {
color: @warning-color;
}
.text-gray {
color: fade(@black, 50%);
}
.text-normal {
color: fade(@black, 30%);
}
.text-white {
color: @white;
}
.text-black {
color: @black;
}

View File

@@ -1,4 +1,5 @@
@import (reference) '../extend.less'; @import (reference) '../extend.less';
@import (reference) './text-color.less';
.yo-tree-layout { .yo-tree-layout {
position: absolute; position: absolute;
top: 0; top: 0;
@@ -7,11 +8,11 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
.ant-layout-sider { .ant-layout-sider {
background-color: @white; background-color: @component-background;
.ant-layout-header { .ant-layout-header {
height: @layout-header-height - 20px; height: @layout-header-height - 20px;
background-color: @white; background-color: @component-background;
.header-actions { .header-actions {
.ant-input-search { .ant-input-search {
margin: (@layout-header-height - 20px - 32px) / 2 @padding-md; margin: (@layout-header-height - 20px - 32px) / 2 @padding-md;
@@ -64,7 +65,7 @@
width: 5px; width: 5px;
height: 5px; height: 5px;
background-color: @white; background-color: @component-background;
} }
&::-webkit-scrollbar-thumb { &::-webkit-scrollbar-thumb {
background-color: transparent; background-color: transparent;
@@ -77,6 +78,6 @@
} }
} }
.ant-tree { .ant-tree {
color: fade(@black, 60%); .text-gray();
} }
} }

View File

@@ -0,0 +1,29 @@
@import (reference) '../extend.less';
.ant-upload-list-text {
display: flex;
flex-wrap: wrap;
.ant-upload-list-item {
height: auto;
margin-right: @padding-xs;
}
.ant-upload-list-item-info {
position: relative;
padding: @padding-xxs @padding-xs;
border: @border-width-base @border-style-base @border-color-split;
.anticon-paper-clip {
top: 7.5px;
}
>span {
display: flex;
}
}
.ant-upload-list-item-card-actions {
position: relative;
margin-left: @padding-xs;
white-space: nowrap;
}
}

View File

@@ -0,0 +1,45 @@
@import (reference) '../extend.less';
.hide {
visibility: hidden !important;
}
.hidden {
display: none !important;
}
.block {
display: block;
}
.inline-block {
display: inline-block;
}
.inline {
display: inline;
}
.inline-flex {
display: inline-flex;
}
.flex {
display: flex;
}
.ellipsis {
display: block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.ellipsis-line(@line) {
display: -webkit-box;
overflow: hidden;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
word-break: break-all;
-webkit-line-clamp: @line;
}
.ellipsis-2 {
.ellipsis-line(2);
}
.ellipsis-3 {
.ellipsis-line(3);
}

View File

@@ -0,0 +1,47 @@
@import (reference) '../extend.less';
.width-height (@i) when (@i <=20) {
@n : @i * 50;
@px : @n * 1px;
.w-@{n} {
width: @px !important;
}
.w-@{n}-min {
min-width: @px !important;
}
.w-@{n}-max {
max-width: @px !important;
}
.h-@{n} {
height: @px !important;
}
.h-@{n}-min {
min-height: @px !important;
}
.h-@{n}-max {
max-height: @px !important;
}
.w-@{n}-p {
width: @n * 1% !important;
}
.h-@{n}-p {
height: @n * 1% !important;
}
.width-height(@i + 1);
}
.width-height(0);
.flex-1 {
flex: 1;
}

View File

@@ -0,0 +1,691 @@
@import (reference) './extend.less';
@import (reference) './lib/container.less';
@import (reference) './lib/text-color.less';
.yo-layout--spin {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: @layout-header-background;
>.ant-spin-nested-loading {
height: 100%;
>div>.ant-spin {
max-height: none;
@-webkit-keyframes borderScale {
0% {
border: 5px solid white;
}
50% {
border: 25px solid transparent;
}
100% {
border: 5px solid white;
}
}
@keyframes borderScale {
0% {
border: 5px solid white;
}
50% {
border: 25px solid transparent;
}
100% {
border: 5px solid white;
}
}
.loader-container {
position: absolute;
top: 50%;
left: 50%;
box-sizing: content-box;
width: 200px;
height: 200px;
margin: 0 auto;
margin-right: -50%;
transform: translate(-50%, -50%);
-webkit-animation: borderScale 1s infinite ease-in-out;
animation: borderScale 1s infinite ease-in-out;
color: white;
border: 5px solid transparent;
border-radius: 50%;
>p {
font-family: 'Raleway', sans-serif;
font-size: 2em;
font-weight: bold;
position: absolute;
top: 50%;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
}
}
}
>.ant-spin-container {
width: 100%;
height: 100%;
&.ant-spin-blur {
opacity: 0;
}
}
}
}
.ant-layout-header {
.header-actions {
display: flex;
.header-action {
display: inline-block;
padding: 0 @padding-md;
cursor: pointer;
transition: @animation-duration-slow;
transition-property: background-color;
.anticon {
font-size: @font-size-base + 6px;
transition: @animation-duration-slow;
transition-property: color;
}
&:active {
box-shadow: inset 1px 1px 10px rgba(0, 0, 0, .05);
}
// 特殊工具按钮
.theme-toggle {
position: relative;
overflow: hidden;
width: 20px;
height: 20px;
margin: 7px 0;
border-radius: 50%;
&--real {
position: relative;
width: 100%;
height: 100%;
transition: @animation-duration-slow background-color;
border-radius: 50%;
background-color: fade(@white, 60%);
&::before {
position: absolute;
top: 5px;
left: 5px;
width: 10px;
height: 10px;
content: '';
transition: @animation-duration-slow transform;
transform: scale(1);
border: 2px solid @layout-header-background;
border-radius: 50%;
}
}
&--imaginary {
position: absolute;
top: 6px;
right: -6px;
width: 18px;
height: 18px;
transition: @animation-duration-slow transform;
transform: rotate(45deg) scaleY(0);
transform-origin: top right;
border-radius: 50%;
background-color: #334454;
}
}
&:hover {
.theme-toggle {
&--real {
background-color: @white;
&::before {
transform: scale(0);
}
}
&--imaginary {
transform: rotate(45deg) scaleY(1);
}
}
}
}
.ant-select-auto-complete {
margin: (@layout-header-height - 10px - 30px) / 2 @padding-md;
.ant-input-affix-wrapper {
border: 0;
background-color: fade(@white, 15%);
&:focus,
&-focused {
background-color: fade(@white, 30%);
}
.ant-input {
color: fade(@white, 85%);
background-color: transparent;
}
.ant-input-suffix {
.anticon {
color: fade(@white, 60%);
}
}
}
}
}
.user-container {
z-index: 10;
width: 32px + @padding-sm * 2;
height: @layout-header-height - 24px;
margin: 2px 0;
transition: @animation-duration-slow;
.user-container-inner {
position: relative;
transition: @animation-duration-slow;
border-radius: @border-radius-base;
}
.user {
&--base {
line-height: @layout-header-height - 24px;
position: relative;
display: flex;
overflow: hidden;
align-items: center;
width: 100%;
height: @layout-header-height - 24px;
padding: 0 @padding-sm;
transition: @animation-duration-slow;
}
&--avatar {
box-shadow: 0 0 0 2px @white;
}
}
}
}
.ant-layout-content {
position: relative;
overflow-y: auto;
>.yo-tab-external-mount {
position: absolute;
top: 0;
left: 0;
bottom: 0;
display: flex;
flex-direction: column;
width: 100%;
>.ant-tabs {
z-index: 5;
overflow: visible;
>.ant-tabs-nav {
margin-bottom: 0;
border-bottom: 0;
background-color: @card-background;
box-shadow: 0 2px 12px fade(@black, 8%);
&::before {
content: none;
}
.ant-tabs-nav-container {
height: 30px;
margin-bottom: 0;
}
.ant-tabs-tab {
line-height: 30px;
height: 30px;
margin-right: 0;
padding: 0;
transition: none;
border: 0;
background-color: transparent;
&:hover {
color: @black;
}
.ant-tabs-tab-btn {
transition: none;
}
&.ant-tabs-tab-active {
border-color: darken(@primary-color, 10%);
background-color: @primary-color;
.ant-tabs-tab-btn {
color: @white;
}
.ant-tabs-tab-remove {
color: fade(@white, 70%);
&:hover {
color: @white;
}
}
}
.yo-layout-tab-subtitle {
line-height: 1;
display: inline-block;
overflow: hidden;
max-width: 150px;
transform: translateY(1px);
white-space: nowrap;
text-overflow: ellipsis;
opacity: .75;
}
+.ant-tabs-tab {
margin-left: 0;
&::before {
position: absolute;
left: -.5px;
width: 1px;
height: 24px;
content: '';
transform: scaleX(.5);
background: linear-gradient(transparent, fade(@black, 30%), transparent);
}
}
.ant-dropdown-trigger {
padding: 0 @padding-md * 2 0 @padding-md;
}
.ant-tabs-tab-unclosable {
.ant-dropdown-trigger {
padding: 0 @padding-lg 0 @padding-md;
}
}
.ant-tabs-tab-remove {
line-height: 28px;
position: absolute;
top: 0;
right: 0;
margin: 0;
transition: none;
}
}
.ant-tabs-nav-more {
padding: 5px @padding-md;
}
}
}
>.yo-tab-external-mount-content {
position: relative;
height: 100%;
>.yo-tab-external-tabpane {
position: absolute;
top: 0;
left: 0;
overflow-x: hidden;
overflow-y: auto;
width: 100%;
height: 100%;
&.yo-tab-external-tabpane-inactive {
pointer-events: none;
opacity: 0;
}
>iframe {
display: block;
width: 100%;
height: 100%;
border: 0;
}
}
}
}
}
.ant-layout-sider {
.ant-menu-inline {
border-right: 0;
}
}
.yo-nav {
padding-top: @padding-lg;
padding-bottom: @padding-lg;
&--row {
padding: 1px 0;
column-gap: @padding-md;
column-count: 3;
}
&--col {
break-inside: avoid;
}
&--sub-item {
}
&--item-group {
font-size: @font-size-base;
line-height: 1.5;
margin-bottom: @padding-xs;
padding-top: @padding-xs * 2;
color: fade(@black, 35%);
border: @border-width-base @border-style-base transparent;
}
&--item {
font-size: @font-size-base;
line-height: 1.5;
position: relative;
margin-bottom: @padding-xs;
padding: @padding-xs @padding-sm;
cursor: pointer;
transition: @animation-duration-fast;
border: @border-width-base @border-style-base @border-color-split;
border-radius: @border-radius-base;
background-color: @white;
&:hover {
color: @white;
border-color: @primary-color;
background-color: @primary-color;
}
}
}
.yo-layout-sider {
height: 100%;
background-color: @white;
.ant-layout-sider-children {
display: flex;
flex-direction: column;
}
.logo {
font-size: @font-size-lg * 1.5;
font-weight: 500;
line-height: @layout-header-height + 10px;
z-index: 11;
display: flex;
overflow: hidden;
align-items: center;
flex: 0 0 @layout-header-height + 10px;
height: @layout-header-height + 10px;
padding: 0 @padding-md 0 @padding-lg;
color: @white;
box-shadow: none;
img {
max-height: 100%;
}
span {
margin-left: @padding-sm;
transition: @animation-duration-slow;
transition-property: opacity;
}
}
&.ant-layout-sider-collapsed {
.logo {
span {
opacity: 0;
}
}
}
.yo-sider-nav {
position: relative;
z-index: 10;
flex: 1 1 100%;
box-shadow: 2px 0 8px fade(@black, 25%);
&--app {
font-size: @font-size-sm;
margin-top: @padding-sm;
padding: 0 @padding-md;
.text-gray();
}
}
.swiper-container {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100%;
.swiper-scrollbar {
transition: @animation-duration-slow;
transition-property: opacity;
opacity: 0;
}
.swiper-scrollbar-drag {
background-color: fade(@white, 30%);
}
&:hover {
.swiper-scrollbar {
opacity: 1;
}
}
}
.swiper-slide {
height: auto;
min-height: 100%;
>.ant-spin-nested-loading {
height: 100%;
.ant-spin-blur {
&::after {
opacity: 0;
}
}
}
}
}
.yo-layout--left-menu,
.yo-layout--right-menu {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
.ant-layout-header {
line-height: @layout-header-height - 20px;
z-index: 6;
height: @layout-header-height - 20px;
padding: 0;
background-color: @white;
>section {
display: flex;
justify-content: space-between;
}
.header-actions {
.header-action {
line-height: @layout-header-height - 16px;
height: @layout-header-height - 20px;
.anticon {
color: fade(@black, 35%);
}
&:hover {
background-color: fade(@black, 5%);
.anticon {
color: @icon-color-hover;
}
}
}
}
}
>section {
>.ant-layout-sider {
.yo-layout-sider();
}
}
}
.yo-layout--top-nav {
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
@layout-header-height: 54px;
.ant-layout-header {
line-height: @layout-header-height;
z-index: 11;
flex: 0 0 @layout-header-height;
height: @layout-header-height;
padding: 0;
background-color: @layout-header-background;
section {
display: flex;
justify-content: space-between;
height: 100%;
}
.header-actions {
.header-action {
.anticon {
color: fade(@white, 60%);
}
&:hover {
background-color: fade(@white, 20%);
.anticon {
color: @white;
}
}
}
}
.user-container {
margin: (@layout-header-height - 40px) / 2 0;
}
.logo {
font-size: @font-size-lg * 1.5;
font-weight: 500;
line-height: @layout-header-height - 10px;
display: flex;
overflow: hidden;
align-items: center;
height: @layout-header-height 10px;
margin: 5px @padding-lg 5px 0;
color: @white;
img {
max-height: 100%;
}
span {
margin-left: @padding-sm;
}
}
.ant-menu-horizontal {
line-height: @layout-header-height;
border-bottom: 0;
>.ant-menu-submenu {
top: 0;
border-bottom: 0;
}
}
.header-actions {
.header-action {
line-height: @layout-header-height - 16px;
margin: 10px 0;
}
}
}
&--container {
.ant-layout-header {
.ant-menu-horizontal {
width: 400px;
}
}
.ant-layout-content {
.yo-tab-external-mount {
>.ant-tabs {
>.ant-tabs-bar {
.ant-tabs-nav-container {
width: @container-width - @padding-md * 2;
margin: 0 auto;
}
}
}
}
}
}
&--container-fluid {
.ant-layout-header {
.ant-menu-horizontal {
width: 800px;
}
@media (max-width: 1400px) {
.ant-menu-horizontal {
width: 600px;
}
}
}
}
}
.yo-user-popover {
width: 280px;
padding-top: 0;
.ant-popover-arrow {
display: none;
}
.ant-popover-inner-content {
padding: 0;
}
}
.yo-popover-infinite-scroll {
.ant-popover-inner-content {
overflow-y: auto;
max-height: 300px;
}
}

View File

@@ -0,0 +1,51 @@
@import (reference) '../extend.less';
.yo-avatar-info {
position: relative;
overflow: hidden;
width: 128px;
margin: 0 auto;
border-radius: 50%;
&--cover {
font-size: @font-size-lg * 2;
position: absolute;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
cursor: pointer;
transition: @animation-duration-slow;
opacity: 0;
color: @white;
background-color: fade(@black, 50%);
&:hover {
opacity: 1;
}
}
}
.yo-avatar-cropper {
overflow: hidden;
border-radius: @border-radius-base;
background-color: #ccc;
}
.yo-avatar-preview {
overflow: hidden;
width: 200px;
height: 200px;
margin: 0 auto;
border-radius: 50%;
background: #ccc;
}

View File

@@ -0,0 +1,42 @@
@import (reference) '../extend.less';
.home-header {
margin-bottom: @padding-md;
padding: @padding-lg 0;
background-color: @component-background;
}
.home-header-row {
display: flex;
}
.home-header-content {
margin-left: @padding-lg;
h4 {
span {
color: @primary-color;
}
}
p {
margin: 0;
}
}
.home-container {
.ant-card-meta-title {
font-size: @font-size-base + 1px;
display: -webkit-box;
-webkit-box-orient: vertical;
height: 42px;
white-space: normal;
-webkit-line-clamp: 2;
}
.ant-card-meta-description {
.ant-row {
line-height: 24px;
height: 24px;
}
}
}

View File

@@ -0,0 +1,3 @@
@import './login.less';
@import './home.less';
@import './account-base.less';

Some files were not shown because too many files have changed in this diff Show More