mirror of
https://gitee.com/ccnetcore/Yi
synced 2026-03-14 21:46:38 +08:00
Compare commits
13 Commits
watermelon
...
abp-dev-10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
998d97b669 | ||
|
|
453d95a460 | ||
|
|
d55545849a | ||
|
|
22ba44c271 | ||
|
|
ae2cc7ad9b | ||
|
|
c880f32d33 | ||
|
|
7b20b68b6a | ||
|
|
974f264272 | ||
|
|
bcbb2b5139 | ||
|
|
e09aaa2dc7 | ||
|
|
e3178d7579 | ||
|
|
b59dfbc3fd | ||
|
|
0f21688b3c |
@@ -109,6 +109,7 @@ namespace Yi.Framework.AuditLogging.Domain.Entities
|
|||||||
|
|
||||||
public virtual string? Url { get; protected set; }
|
public virtual string? Url { get; protected set; }
|
||||||
|
|
||||||
|
[SugarColumn(ColumnDataType = StaticConfig.CodeFirst_BigString)]
|
||||||
public virtual string? Exceptions { get; protected set; }
|
public virtual string? Exceptions { get; protected set; }
|
||||||
|
|
||||||
public virtual string? Comments { get; protected set; }
|
public virtual string? Comments { get; protected set; }
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ using Microsoft.Extensions.Configuration;
|
|||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Volo.Abp.Caching;
|
using Volo.Abp.Caching;
|
||||||
using Volo.Abp.DependencyInjection;
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.EventBus;
|
||||||
using Yi.Framework.Bbs.Domain.Shared.Caches;
|
using Yi.Framework.Bbs.Domain.Shared.Caches;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||||
|
|
||||||
namespace Yi.Framework.Bbs.Application.Extensions;
|
namespace Yi.Framework.Bbs.Application.Extensions;
|
||||||
|
|
||||||
@@ -14,6 +16,29 @@ namespace Yi.Framework.Bbs.Application.Extensions;
|
|||||||
/// 需考虑一致性问题,又不能上锁影响性能
|
/// 需考虑一致性问题,又不能上锁影响性能
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AccessLogMiddleware : IMiddleware, ITransientDependency
|
public class AccessLogMiddleware : IMiddleware, ITransientDependency
|
||||||
|
{
|
||||||
|
private static int _accessLogNumber = 0;
|
||||||
|
|
||||||
|
internal static void ResetAccessLogNumber()
|
||||||
|
{
|
||||||
|
_accessLogNumber = 0;
|
||||||
|
}
|
||||||
|
internal static int GetAccessLogNumber()
|
||||||
|
{
|
||||||
|
return _accessLogNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
|
||||||
|
{
|
||||||
|
await next(context);
|
||||||
|
|
||||||
|
Interlocked.Increment(ref _accessLogNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AccessLogResetEventHandler : ILocalEventHandler<AccessLogResetArgs>,
|
||||||
|
ITransientDependency
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 缓存前缀
|
/// 缓存前缀
|
||||||
@@ -39,13 +64,28 @@ public class AccessLogMiddleware : IMiddleware, ITransientDependency
|
|||||||
return redisEnabled.IsNullOrEmpty() || bool.Parse(redisEnabled);
|
return redisEnabled.IsNullOrEmpty() || bool.Parse(redisEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
|
//该事件由job定时10秒触发
|
||||||
|
public async Task HandleEventAsync(AccessLogResetArgs eventData)
|
||||||
{
|
{
|
||||||
await next(context);
|
|
||||||
if (EnableRedisCache)
|
if (EnableRedisCache)
|
||||||
{
|
{
|
||||||
await RedisClient.IncrByAsync($"{CacheKeyPrefix}:{AccessLogCacheConst.Key}:{DateTime.Now.Date}", 1);
|
//分布式锁
|
||||||
|
if (await RedisClient.SetNxAsync("AccessLogLock",true,TimeSpan.FromSeconds(5)))
|
||||||
|
{
|
||||||
|
//自增长数
|
||||||
|
var incrNumber= AccessLogMiddleware.GetAccessLogNumber();
|
||||||
|
//立即重置,开始计算,方式丢失
|
||||||
|
AccessLogMiddleware.ResetAccessLogNumber();
|
||||||
|
if (incrNumber>0)
|
||||||
|
{
|
||||||
|
await RedisClient.IncrByAsync(
|
||||||
|
$"{CacheKeyPrefix}{AccessLogCacheConst.Key}:{DateTime.Now.Date:yyyyMMdd}", incrNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using FreeRedis;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Quartz;
|
||||||
|
using Volo.Abp.BackgroundWorkers.Quartz;
|
||||||
|
using Volo.Abp.Caching;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.Domain.Entities;
|
||||||
|
using Volo.Abp.EventBus.Local;
|
||||||
|
using Yi.Framework.Bbs.Domain.Entities;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Caches;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||||
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Bbs.Application.Jobs;
|
||||||
|
|
||||||
|
public class AccessLogCacheJob : QuartzBackgroundWorkerBase
|
||||||
|
{
|
||||||
|
private readonly ILocalEventBus _localEventBus;
|
||||||
|
|
||||||
|
public AccessLogCacheJob(ILocalEventBus localEventBus)
|
||||||
|
{
|
||||||
|
_localEventBus = localEventBus;
|
||||||
|
JobDetail = JobBuilder.Create<AccessLogCacheJob>().WithIdentity(nameof(AccessLogCacheJob))
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
//每10秒执行一次,将本地缓存转入redis,防止丢数据
|
||||||
|
Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogCacheJob))
|
||||||
|
.WithSimpleSchedule((schedule) => { schedule.WithInterval(TimeSpan.FromSeconds(10)).RepeatForever();; })
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
await _localEventBus.PublishAsync(new AccessLogResetArgs());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,7 +62,7 @@ public class AccessLogStoreJob : QuartzBackgroundWorkerBase
|
|||||||
{
|
{
|
||||||
//当天的访问量
|
//当天的访问量
|
||||||
var number =
|
var number =
|
||||||
await RedisClient.GetAsync<long>($"{CacheKeyPrefix}:{AccessLogCacheConst.Key}:{DateTime.Now.Date}");
|
await RedisClient.GetAsync<long>($"{CacheKeyPrefix}{AccessLogCacheConst.Key}:{DateTime.Now.Date:yyyyMMdd}");
|
||||||
|
|
||||||
|
|
||||||
var entity = await _repository._DbQueryable.Where(x => x.AccessLogType == AccessLogTypeEnum.Request)
|
var entity = await _repository._DbQueryable.Where(x => x.AccessLogType == AccessLogTypeEnum.Request)
|
||||||
@@ -81,7 +81,7 @@ public class AccessLogStoreJob : QuartzBackgroundWorkerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
//删除前一天的缓存
|
//删除前一天的缓存
|
||||||
await RedisClient.DelAsync($"{CacheKeyPrefix}:{AccessLogCacheConst.Key}:{DateTime.Now.Date.AddDays(-1)}");
|
await RedisClient.DelAsync($"{CacheKeyPrefix}{AccessLogCacheConst.Key}:{DateTime.Now.Date.AddDays(-1):yyyyMMdd}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||||
|
|
||||||
|
public class AccessLogResetArgs
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,5 +4,7 @@
|
|||||||
{
|
{
|
||||||
public Guid Uuid { get; set; } = Guid.Empty;
|
public Guid Uuid { get; set; } = Guid.Empty;
|
||||||
public byte[] Img { get; set; }
|
public byte[] Img { get; set; }
|
||||||
|
|
||||||
|
public bool IsEnableCaptcha { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,5 +3,9 @@
|
|||||||
public class PhoneCaptchaImageDto
|
public class PhoneCaptchaImageDto
|
||||||
{
|
{
|
||||||
public string Phone { get; set; }
|
public string Phone { get; set; }
|
||||||
|
|
||||||
|
public string? Uuid { get; set; }
|
||||||
|
|
||||||
|
public string? Code { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Menu
|
|||||||
public string? Remark { get; set; }
|
public string? Remark { get; set; }
|
||||||
public string? Component { get; set; }
|
public string? Component { get; set; }
|
||||||
public string? Query { get; set; }
|
public string? Query { get; set; }
|
||||||
|
public string? RouterName { get; set; }
|
||||||
public int OrderNum { get; set; }
|
public int OrderNum { get; set; }
|
||||||
//public List<MenuEntity>? Children { get; set; }
|
//public List<MenuEntity>? Children { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Menu
|
|||||||
|
|
||||||
public int OrderNum { get; set; }
|
public int OrderNum { get; set; }
|
||||||
|
|
||||||
|
public string? RouterName { get; set; }
|
||||||
|
|
||||||
//public List<MenuEntity>? Children { get; set; }
|
//public List<MenuEntity>? Children { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,12 +82,12 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
/// 校验图片登录验证码,无需和账号绑定
|
/// 校验图片登录验证码,无需和账号绑定
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
private void ValidationImageCaptcha(LoginInputVo input)
|
private void ValidationImageCaptcha(string? uuid,string? code )
|
||||||
{
|
{
|
||||||
if (_rbacOptions.EnableCaptcha)
|
if (_rbacOptions.EnableCaptcha)
|
||||||
{
|
{
|
||||||
//登录不想要验证码 ,可不校验
|
//登录不想要验证码 ,可不校验
|
||||||
if (!_captcha.Validate(input.Uuid, input.Code))
|
if (!_captcha.Validate(uuid, code))
|
||||||
{
|
{
|
||||||
throw new UserFriendlyException("验证码错误");
|
throw new UserFriendlyException("验证码错误");
|
||||||
}
|
}
|
||||||
@@ -109,7 +109,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
//校验验证码
|
//校验验证码
|
||||||
ValidationImageCaptcha(input);
|
ValidationImageCaptcha(input.Uuid,input.Code);
|
||||||
|
|
||||||
UserAggregateRoot user = new();
|
UserAggregateRoot user = new();
|
||||||
//校验
|
//校验
|
||||||
@@ -157,7 +157,8 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
{
|
{
|
||||||
var uuid = _guidGenerator.Create();
|
var uuid = _guidGenerator.Create();
|
||||||
var captcha = _captcha.Generate(uuid.ToString());
|
var captcha = _captcha.Generate(uuid.ToString());
|
||||||
return new CaptchaImageDto { Img = captcha.Bytes, Uuid = uuid };
|
var enableCaptcha = _rbacOptions.EnableCaptcha;
|
||||||
|
return new CaptchaImageDto { Img = captcha.Bytes, Uuid = uuid,IsEnableCaptcha= enableCaptcha };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -198,12 +199,15 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 手机验证码
|
/// 手机验证码-需通过图形验证码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task<object> PostCaptchaPhoneAsync(ValidationPhoneTypeEnum validationPhoneType,
|
private async Task<object> PostCaptchaPhoneAsync(ValidationPhoneTypeEnum validationPhoneType,
|
||||||
PhoneCaptchaImageDto input)
|
PhoneCaptchaImageDto input)
|
||||||
{
|
{
|
||||||
|
//验证uuid 和 验证码
|
||||||
|
ValidationImageCaptcha(input.Uuid,input.Code);
|
||||||
|
|
||||||
await ValidationPhone(input.Phone);
|
await ValidationPhone(input.Phone);
|
||||||
|
|
||||||
//注册的手机号验证,是不能已经注册过的
|
//注册的手机号验证,是不能已经注册过的
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ namespace Yi.Framework.Rbac.Application.Services.RecordLog
|
|||||||
public override async Task<PagedResultDto<LoginLogGetListOutputDto>> GetListAsync(LoginLogGetListInputVo input)
|
public override async Task<PagedResultDto<LoginLogGetListOutputDto>> GetListAsync(LoginLogGetListInputVo input)
|
||||||
{
|
{
|
||||||
RefAsync<int> total = 0;
|
RefAsync<int> total = 0;
|
||||||
if (input.Sorting.IsNullOrWhiteSpace())
|
//if (input.Sorting.IsNullOrWhiteSpace())
|
||||||
input.Sorting = $"{nameof(LoginLogAggregateRoot.CreationTime)} Desc";
|
// input.Sorting = $"{nameof(LoginLogAggregateRoot.CreationTime)} Desc";
|
||||||
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.LoginIp), x => x.LoginIp.Contains(input.LoginIp!))
|
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.LoginIp), x => x.LoginIp.Contains(input.LoginIp!))
|
||||||
.WhereIF(!string.IsNullOrEmpty(input.LoginUser), x => x.LoginUser!.Contains(input.LoginUser!))
|
.WhereIF(!string.IsNullOrEmpty(input.LoginUser), x => x.LoginUser!.Contains(input.LoginUser!))
|
||||||
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
|
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
|
||||||
.OrderBy(input.Sorting)
|
.OrderByDescending(it => it.CreationTime) //降序
|
||||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||||
return new PagedResultDto<LoginLogGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
return new PagedResultDto<LoginLogGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ namespace Yi.Framework.Rbac.Application.Services.RecordLog
|
|||||||
public override async Task<PagedResultDto<OperationLogGetListOutputDto>> GetListAsync(OperationLogGetListInputVo input)
|
public override async Task<PagedResultDto<OperationLogGetListOutputDto>> GetListAsync(OperationLogGetListInputVo input)
|
||||||
{
|
{
|
||||||
RefAsync<int> total = 0;
|
RefAsync<int> total = 0;
|
||||||
if (input.Sorting.IsNullOrWhiteSpace())
|
//if (input.Sorting.IsNullOrWhiteSpace())
|
||||||
input.Sorting = $"{nameof(OperationLogEntity.CreationTime)} Desc";
|
// input.Sorting = $"{nameof(OperationLogEntity.CreationTime)} Desc";
|
||||||
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.OperUser), x => x.OperUser.Contains(input.OperUser!))
|
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.OperUser), x => x.OperUser.Contains(input.OperUser!))
|
||||||
.WhereIF(input.OperType is not null, x => x.OperType == input.OperType)
|
.WhereIF(input.OperType is not null, x => x.OperType == input.OperType)
|
||||||
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
|
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
|
||||||
.OrderBy(input.Sorting)
|
.OrderByDescending(it => it.CreationTime) //降序
|
||||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||||
return new PagedResultDto<OperationLogGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
return new PagedResultDto<OperationLogGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,12 +63,12 @@ namespace Yi.Framework.Rbac.Domain.Entities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 部门名称
|
/// 部门名称
|
||||||
///</summary>
|
///</summary>
|
||||||
public string DeptName { get; set; } = string.Empty;
|
public string DeptName { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 部门编码
|
/// 部门编码
|
||||||
///</summary>
|
///</summary>
|
||||||
[SugarColumn(ColumnName = "DeptCode")]
|
[SugarColumn(ColumnName = "DeptCode")]
|
||||||
public string DeptCode { get; set; } = string.Empty;
|
public string DeptCode { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 负责人
|
/// 负责人
|
||||||
///</summary>
|
///</summary>
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
|||||||
|
|
||||||
DeptAggregateRoot shenzhenDept = new DeptAggregateRoot(_guidGenerator.Create())
|
DeptAggregateRoot shenzhenDept = new DeptAggregateRoot(_guidGenerator.Create())
|
||||||
{
|
{
|
||||||
|
DeptCode = "SZ",
|
||||||
DeptName = "深圳总公司",
|
DeptName = "深圳总公司",
|
||||||
OrderNum = 100,
|
OrderNum = 100,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
@@ -52,7 +52,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
|||||||
|
|
||||||
DeptAggregateRoot jiangxiDept = new DeptAggregateRoot(_guidGenerator.Create())
|
DeptAggregateRoot jiangxiDept = new DeptAggregateRoot(_guidGenerator.Create())
|
||||||
{
|
{
|
||||||
|
DeptCode = "JX",
|
||||||
DeptName = "江西总公司",
|
DeptName = "江西总公司",
|
||||||
OrderNum = 100,
|
OrderNum = 100,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
@@ -64,7 +64,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
|||||||
|
|
||||||
DeptAggregateRoot szDept1 = new DeptAggregateRoot(_guidGenerator.Create())
|
DeptAggregateRoot szDept1 = new DeptAggregateRoot(_guidGenerator.Create())
|
||||||
{
|
{
|
||||||
|
DeptCode = "YF",
|
||||||
DeptName = "研发部门",
|
DeptName = "研发部门",
|
||||||
OrderNum = 100,
|
OrderNum = 100,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
@@ -74,7 +74,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
|||||||
|
|
||||||
DeptAggregateRoot szDept2 = new DeptAggregateRoot(_guidGenerator.Create())
|
DeptAggregateRoot szDept2 = new DeptAggregateRoot(_guidGenerator.Create())
|
||||||
{
|
{
|
||||||
|
DeptCode = "SC",
|
||||||
DeptName = "市场部门",
|
DeptName = "市场部门",
|
||||||
OrderNum = 100,
|
OrderNum = 100,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
@@ -84,7 +84,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
|||||||
|
|
||||||
DeptAggregateRoot szDept3 = new DeptAggregateRoot(_guidGenerator.Create())
|
DeptAggregateRoot szDept3 = new DeptAggregateRoot(_guidGenerator.Create())
|
||||||
{
|
{
|
||||||
|
DeptCode = "CS",
|
||||||
DeptName = "测试部门",
|
DeptName = "测试部门",
|
||||||
OrderNum = 100,
|
OrderNum = 100,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
@@ -94,7 +94,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
|||||||
|
|
||||||
DeptAggregateRoot szDept4 = new DeptAggregateRoot(_guidGenerator.Create())
|
DeptAggregateRoot szDept4 = new DeptAggregateRoot(_guidGenerator.Create())
|
||||||
{
|
{
|
||||||
|
DeptCode = "CW",
|
||||||
DeptName = "财务部门",
|
DeptName = "财务部门",
|
||||||
OrderNum = 100,
|
OrderNum = 100,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
@@ -104,7 +104,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
|||||||
|
|
||||||
DeptAggregateRoot szDept5 = new DeptAggregateRoot(_guidGenerator.Create())
|
DeptAggregateRoot szDept5 = new DeptAggregateRoot(_guidGenerator.Create())
|
||||||
{
|
{
|
||||||
|
DeptCode = "YW",
|
||||||
DeptName = "运维部门",
|
DeptName = "运维部门",
|
||||||
OrderNum = 100,
|
OrderNum = 100,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
@@ -115,7 +115,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
|||||||
|
|
||||||
DeptAggregateRoot jxDept1 = new DeptAggregateRoot(_guidGenerator.Create())
|
DeptAggregateRoot jxDept1 = new DeptAggregateRoot(_guidGenerator.Create())
|
||||||
{
|
{
|
||||||
|
DeptCode = "SC",
|
||||||
DeptName = "市场部门",
|
DeptName = "市场部门",
|
||||||
OrderNum = 100,
|
OrderNum = 100,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
@@ -126,7 +126,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
|||||||
|
|
||||||
DeptAggregateRoot jxDept2 = new DeptAggregateRoot(_guidGenerator.Create())
|
DeptAggregateRoot jxDept2 = new DeptAggregateRoot(_guidGenerator.Create())
|
||||||
{
|
{
|
||||||
|
DeptCode = "CW2",
|
||||||
DeptName = "财务部门",
|
DeptName = "财务部门",
|
||||||
OrderNum = 100,
|
OrderNum = 100,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
|
|||||||
@@ -227,7 +227,22 @@ namespace Yi.Framework.Rbac.SqlSugarCore.DataSeeds
|
|||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
};
|
};
|
||||||
entities.Add(swagger);
|
entities.Add(swagger);
|
||||||
|
|
||||||
|
//表单构建
|
||||||
|
MenuAggregateRoot builder = new MenuAggregateRoot(_guidGenerator.Create(), tool.Id)
|
||||||
|
{
|
||||||
|
MenuName = "表单生成器",
|
||||||
|
MenuType = MenuTypeEnum.Menu,
|
||||||
|
Router = "build",
|
||||||
|
IsShow = true,
|
||||||
|
IsLink = false,
|
||||||
|
MenuIcon = "form",
|
||||||
|
Component = "tool/build/index",
|
||||||
|
IsCache = true,
|
||||||
|
OrderNum = 101,
|
||||||
|
IsDeleted = false,
|
||||||
|
};
|
||||||
|
entities.Add(builder);
|
||||||
|
|
||||||
// //ERP
|
// //ERP
|
||||||
// MenuAggregateRoot erp = new MenuAggregateRoot(_guidGenerator.Create())
|
// MenuAggregateRoot erp = new MenuAggregateRoot(_guidGenerator.Create())
|
||||||
|
|||||||
@@ -91,13 +91,28 @@ defineExpose({ getRef });
|
|||||||
<re-col
|
<re-col
|
||||||
v-show="newFormInline.menuType !== 2"
|
v-show="newFormInline.menuType !== 2"
|
||||||
:value="24"
|
:value="24"
|
||||||
:xs="24"
|
:xs="12"
|
||||||
:sm="24"
|
:sm="12"
|
||||||
>
|
>
|
||||||
<el-form-item label="菜单图标">
|
<el-form-item label="菜单图标">
|
||||||
<IconSelect v-model="newFormInline.menuIcon" class="w-full" />
|
<IconSelect v-model="newFormInline.menuIcon" class="w-full" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</re-col>
|
</re-col>
|
||||||
|
<re-col
|
||||||
|
v-show="newFormInline.menuType !== 2"
|
||||||
|
:value="24"
|
||||||
|
:xs="12"
|
||||||
|
:sm="12"
|
||||||
|
>
|
||||||
|
<el-form-item label="路由名称">
|
||||||
|
<el-input
|
||||||
|
v-model="newFormInline.routerName"
|
||||||
|
clearable
|
||||||
|
placeholder="请输入菜单名称"
|
||||||
|
class="w-full"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</re-col>
|
||||||
<re-col :value="12" :xs="24" :sm="24">
|
<re-col :value="12" :xs="24" :sm="24">
|
||||||
<el-form-item label="菜单名称" prop="menuName">
|
<el-form-item label="菜单名称" prop="menuName">
|
||||||
<el-input
|
<el-input
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export function useMenu() {
|
|||||||
{
|
{
|
||||||
label: "显示",
|
label: "显示",
|
||||||
prop: "isShow",
|
prop: "isShow",
|
||||||
formatter: ({ isShow }) => (isShow ? "否" : "是"),
|
formatter: ({ isShow }) => (isShow ? "是" : "否"),
|
||||||
width: 100
|
width: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,7 +32,8 @@
|
|||||||
"typeface-roboto": "^1.1.13",
|
"typeface-roboto": "^1.1.13",
|
||||||
"vue": "3.4.21",
|
"vue": "3.4.21",
|
||||||
"vue-cropper": "1.0.3",
|
"vue-cropper": "1.0.3",
|
||||||
"vue-router": "4.3.0"
|
"vue-router": "4.3.0",
|
||||||
|
"vform3-builds": "^3.0.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.0.4",
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import App from './App'
|
|||||||
import store from './store'
|
import store from './store'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import directive from './directive' // directive
|
import directive from './directive' // directive
|
||||||
|
import VForm3 from 'vform3-builds'
|
||||||
|
import 'vform3-builds/dist/designer.style.css' //引入VForm3样式
|
||||||
|
|
||||||
|
|
||||||
// 注册指令
|
// 注册指令
|
||||||
@@ -77,5 +79,6 @@ app.use(ElementPlus, {
|
|||||||
// 支持 large、default、small
|
// 支持 large、default、small
|
||||||
size: Cookies.get('size') || 'default'
|
size: Cookies.get('size') || 'default'
|
||||||
})
|
})
|
||||||
|
app.use(VForm3)
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ const loginRules = {
|
|||||||
const codeUrl = ref("");
|
const codeUrl = ref("");
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
// 验证码开关
|
// 验证码开关
|
||||||
const captchaEnabled = ref(true);
|
const captchaEnabled = ref(false);
|
||||||
// 注册开关
|
// 注册开关
|
||||||
const register = ref(false);
|
const register = ref(false);
|
||||||
const redirect = ref(undefined);
|
const redirect = ref(undefined);
|
||||||
@@ -157,7 +157,7 @@ function handleLogin() {
|
|||||||
function getCode() {
|
function getCode() {
|
||||||
|
|
||||||
getCodeImg().then(res => {
|
getCodeImg().then(res => {
|
||||||
captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled;
|
captchaEnabled.value = res.data.isEnableCaptcha === undefined ? true : res.data.isEnableCaptcha;
|
||||||
if (captchaEnabled.value) {
|
if (captchaEnabled.value) {
|
||||||
codeUrl.value = "data:image/gif;base64," + res.data.img;
|
codeUrl.value = "data:image/gif;base64," + res.data.img;
|
||||||
loginForm.value.uuid = res.data.uuid;
|
loginForm.value.uuid = res.data.uuid;
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ function handleRegister() {
|
|||||||
|
|
||||||
function getCode() {
|
function getCode() {
|
||||||
getCodeImg().then(res => {
|
getCodeImg().then(res => {
|
||||||
captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled;
|
captchaEnabled.value = res.data.isEnableCaptcha === undefined ? true : res.data.isEnableCaptcha;
|
||||||
if (captchaEnabled.value) {
|
if (captchaEnabled.value) {
|
||||||
codeUrl.value = "data:image/gif;base64," + res.img;
|
codeUrl.value = "data:image/gif;base64," + res.img;
|
||||||
registerForm.value.uuid = res.uuid;
|
registerForm.value.uuid = res.uuid;
|
||||||
|
|||||||
@@ -9,6 +9,14 @@
|
|||||||
@keyup.enter="handleQuery"
|
@keyup.enter="handleQuery"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="部门编号" prop="deptCode">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.deptCode"
|
||||||
|
placeholder="请输入部门编号"
|
||||||
|
clearable
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="状态" prop="state">
|
<el-form-item label="状态" prop="state">
|
||||||
<el-select v-model="queryParams.state" placeholder="部门状态" clearable>
|
<el-select v-model="queryParams.state" placeholder="部门状态" clearable>
|
||||||
<el-option
|
<el-option
|
||||||
@@ -55,6 +63,7 @@
|
|||||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||||
>
|
>
|
||||||
<el-table-column prop="deptName" label="部门名称" width="260"></el-table-column>
|
<el-table-column prop="deptName" label="部门名称" width="260"></el-table-column>
|
||||||
|
<el-table-column prop="deptCode" label="部门编号" width="200"></el-table-column>
|
||||||
<el-table-column prop="orderNum" label="排序" width="200"></el-table-column>
|
<el-table-column prop="orderNum" label="排序" width="200"></el-table-column>
|
||||||
<el-table-column prop="state" label="状态" width="100">
|
<el-table-column prop="state" label="状态" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -112,6 +121,11 @@
|
|||||||
<el-input v-model="form.deptName" placeholder="请输入部门名称" />
|
<el-input v-model="form.deptName" placeholder="请输入部门名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="部门编号" prop="deptCode">
|
||||||
|
<el-input v-model="form.deptCode" placeholder="部门编号" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="显示排序" prop="orderNum">
|
<el-form-item label="显示排序" prop="orderNum">
|
||||||
<el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
|
<el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
|
||||||
@@ -173,11 +187,13 @@ const refreshTable = ref(true);
|
|||||||
const data = reactive({
|
const data = reactive({
|
||||||
form: {},
|
form: {},
|
||||||
queryParams: {
|
queryParams: {
|
||||||
|
deptCode:undefined,
|
||||||
deptName: undefined,
|
deptName: undefined,
|
||||||
state: undefined
|
state: undefined
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
parentId: [{ required: true, message: "上级部门不能为空", trigger: "blur" }],
|
parentId: [{ required: true, message: "上级部门不能为空", trigger: "blur" }],
|
||||||
|
deptCode: [{ required: true, message: "部门编号不能为空", trigger: "blur" }],
|
||||||
deptName: [{ required: true, message: "部门名称不能为空", trigger: "blur" }],
|
deptName: [{ required: true, message: "部门名称不能为空", trigger: "blur" }],
|
||||||
orderNum: [{ required: true, message: "显示排序不能为空", trigger: "blur" }],
|
orderNum: [{ required: true, message: "显示排序不能为空", trigger: "blur" }],
|
||||||
email: [{ type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
|
email: [{ type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
|
||||||
|
|||||||
@@ -1,3 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<div> 表单构建 <svg-icon icon-class="build" /> </div>
|
<div ref="box">
|
||||||
</template>
|
<v-form-designer ></v-form-designer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {ref,onMounted} from "vue";
|
||||||
|
|
||||||
|
const box = ref<Element>()
|
||||||
|
onMounted(() =>
|
||||||
|
{
|
||||||
|
box.value?.firstChild?.classList.add("not-margin")
|
||||||
|
box.value?.firstChild?.children[0].remove()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
div {
|
||||||
|
margin: 0; /* 如果页面出现垂直滚动条,则加入此行CSS以消除之 */
|
||||||
|
}
|
||||||
|
.not-margin{
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="body">
|
|
||||||
<div class="head"></div>
|
|
||||||
<div class="content">
|
|
||||||
<router-view></router-view>
|
|
||||||
<router-view name="market"></router-view>
|
|
||||||
</div>
|
|
||||||
<div class="bottom"></div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.body{
|
|
||||||
display: flex;
|
|
||||||
background-color: #cdcdcd;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="page-body">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
<style scoped>
|
|
||||||
.page-body{
|
|
||||||
min-height: 1000px;
|
|
||||||
min-width: 500px;
|
|
||||||
background-color: #1482f0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { createRouter, createWebHistory } from "vue-router";
|
|
||||||
import Layout from "../layout/Index.vue";
|
|
||||||
// import NotFound from "../views/error/404.vue";
|
|
||||||
const router = createRouter({
|
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
|
||||||
scrollBehavior(to, from, savedPosition) {
|
|
||||||
// 始终滚动到顶部
|
|
||||||
return { top: 0 };
|
|
||||||
},
|
|
||||||
routes: [
|
|
||||||
{
|
|
||||||
path: "/",
|
|
||||||
name: "layout",
|
|
||||||
component: Layout,
|
|
||||||
redirect: "/index",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: "index",
|
|
||||||
path: "/index",
|
|
||||||
components:{
|
|
||||||
default: ()=>import("../views/home/Index.vue"),
|
|
||||||
market: ()=>import("../views/market/Index.vue"),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// { path: "/:pathMatch(.*)*", name: "NotFound", component: NotFound },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
export default router;
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="errPage-container">
|
|
||||||
<el-button icon="arrow-left" class="pan-back-btn" @click="back">
|
|
||||||
返回
|
|
||||||
</el-button>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="12">
|
|
||||||
<h1 class="text-jumbo text-ginormous">
|
|
||||||
401错误!
|
|
||||||
</h1>
|
|
||||||
<h2>您没有访问权限!</h2>
|
|
||||||
<h6>对不起,您没有访问权限,请不要进行非法操作!您可以返回主页面</h6>
|
|
||||||
<ul class="list-unstyled">
|
|
||||||
<li class="link-type">
|
|
||||||
<router-link to="/">
|
|
||||||
回首页
|
|
||||||
</router-link>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<img :src="errGif" width="313" height="428" alt="Girl has dropped her ice cream.">
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
|
|
||||||
import errImage from "@/assets/401_images/401.gif";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
|
|
||||||
let { proxy } = getCurrentInstance();
|
|
||||||
const router=useRouter();
|
|
||||||
|
|
||||||
const errGif = ref(errImage + "?" + +new Date());
|
|
||||||
|
|
||||||
function back() {
|
|
||||||
if (proxy.$route.query.noGoBack) {
|
|
||||||
router.push({ path: "/" });
|
|
||||||
} else {
|
|
||||||
router.go(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.errPage-container {
|
|
||||||
width: 800px;
|
|
||||||
max-width: 100%;
|
|
||||||
margin: 100px auto;
|
|
||||||
.pan-back-btn {
|
|
||||||
background: #008489;
|
|
||||||
color: #fff;
|
|
||||||
border: none !important;
|
|
||||||
}
|
|
||||||
.pan-gif {
|
|
||||||
margin: 0 auto;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.pan-img {
|
|
||||||
display: block;
|
|
||||||
margin: 0 auto;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.text-jumbo {
|
|
||||||
font-size: 60px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #484848;
|
|
||||||
}
|
|
||||||
.list-unstyled {
|
|
||||||
font-size: 14px;
|
|
||||||
li {
|
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #008489;
|
|
||||||
text-decoration: none;
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="wscn-http404-container">
|
|
||||||
<div class="wscn-http404">
|
|
||||||
<div class="pic-404">
|
|
||||||
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
|
|
||||||
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
|
|
||||||
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
|
|
||||||
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
|
|
||||||
</div>
|
|
||||||
<div class="bullshit">
|
|
||||||
<div class="bullshit__oops">
|
|
||||||
404错误!
|
|
||||||
</div>
|
|
||||||
<div class="bullshit__headline">
|
|
||||||
{{ message }}
|
|
||||||
</div>
|
|
||||||
<div class="bullshit__info">
|
|
||||||
对不起,您正在寻找的页面不存在。尝试检查URL的错误,然后按浏览器上的刷新按钮或尝试在我们的应用程序中找到其他内容。
|
|
||||||
</div>
|
|
||||||
<router-link to="/index" class="bullshit__return-home">
|
|
||||||
返回首页
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import {computed} from 'vue'
|
|
||||||
let message = computed(() => {
|
|
||||||
return '找不到网页!'
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.wscn-http404-container{
|
|
||||||
transform: translate(-50%,-50%);
|
|
||||||
position: absolute;
|
|
||||||
top: 40%;
|
|
||||||
left: 50%;
|
|
||||||
}
|
|
||||||
.wscn-http404 {
|
|
||||||
position: relative;
|
|
||||||
width: 1200px;
|
|
||||||
padding: 0 50px;
|
|
||||||
overflow: hidden;
|
|
||||||
.pic-404 {
|
|
||||||
position: relative;
|
|
||||||
float: left;
|
|
||||||
width: 600px;
|
|
||||||
overflow: hidden;
|
|
||||||
&__parent {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
&__child {
|
|
||||||
position: absolute;
|
|
||||||
&.left {
|
|
||||||
width: 80px;
|
|
||||||
top: 17px;
|
|
||||||
left: 220px;
|
|
||||||
opacity: 0;
|
|
||||||
animation-name: cloudLeft;
|
|
||||||
animation-duration: 2s;
|
|
||||||
animation-timing-function: linear;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
animation-delay: 1s;
|
|
||||||
}
|
|
||||||
&.mid {
|
|
||||||
width: 46px;
|
|
||||||
top: 10px;
|
|
||||||
left: 420px;
|
|
||||||
opacity: 0;
|
|
||||||
animation-name: cloudMid;
|
|
||||||
animation-duration: 2s;
|
|
||||||
animation-timing-function: linear;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
animation-delay: 1.2s;
|
|
||||||
}
|
|
||||||
&.right {
|
|
||||||
width: 62px;
|
|
||||||
top: 100px;
|
|
||||||
left: 500px;
|
|
||||||
opacity: 0;
|
|
||||||
animation-name: cloudRight;
|
|
||||||
animation-duration: 2s;
|
|
||||||
animation-timing-function: linear;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
animation-delay: 1s;
|
|
||||||
}
|
|
||||||
@keyframes cloudLeft {
|
|
||||||
0% {
|
|
||||||
top: 17px;
|
|
||||||
left: 220px;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
20% {
|
|
||||||
top: 33px;
|
|
||||||
left: 188px;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
80% {
|
|
||||||
top: 81px;
|
|
||||||
left: 92px;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
top: 97px;
|
|
||||||
left: 60px;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes cloudMid {
|
|
||||||
0% {
|
|
||||||
top: 10px;
|
|
||||||
left: 420px;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
20% {
|
|
||||||
top: 40px;
|
|
||||||
left: 360px;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
70% {
|
|
||||||
top: 130px;
|
|
||||||
left: 180px;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
top: 160px;
|
|
||||||
left: 120px;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes cloudRight {
|
|
||||||
0% {
|
|
||||||
top: 100px;
|
|
||||||
left: 500px;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
20% {
|
|
||||||
top: 120px;
|
|
||||||
left: 460px;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
80% {
|
|
||||||
top: 180px;
|
|
||||||
left: 340px;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
top: 200px;
|
|
||||||
left: 300px;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.bullshit {
|
|
||||||
position: relative;
|
|
||||||
float: left;
|
|
||||||
width: 300px;
|
|
||||||
padding: 30px 0;
|
|
||||||
overflow: hidden;
|
|
||||||
&__oops {
|
|
||||||
font-size: 32px;
|
|
||||||
font-weight: bold;
|
|
||||||
line-height: 40px;
|
|
||||||
color: #1482f0;
|
|
||||||
opacity: 0;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
animation-name: slideUp;
|
|
||||||
animation-duration: 0.5s;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
}
|
|
||||||
&__headline {
|
|
||||||
font-size: 20px;
|
|
||||||
line-height: 24px;
|
|
||||||
color: #222;
|
|
||||||
font-weight: bold;
|
|
||||||
opacity: 0;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
animation-name: slideUp;
|
|
||||||
animation-duration: 0.5s;
|
|
||||||
animation-delay: 0.1s;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
}
|
|
||||||
&__info {
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: 21px;
|
|
||||||
color: grey;
|
|
||||||
opacity: 0;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
animation-name: slideUp;
|
|
||||||
animation-duration: 0.5s;
|
|
||||||
animation-delay: 0.2s;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
}
|
|
||||||
&__return-home {
|
|
||||||
display: block;
|
|
||||||
float: left;
|
|
||||||
width: 110px;
|
|
||||||
height: 36px;
|
|
||||||
background: #1482f0;
|
|
||||||
border-radius: 100px;
|
|
||||||
text-align: center;
|
|
||||||
color: #ffffff;
|
|
||||||
opacity: 0;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 36px;
|
|
||||||
cursor: pointer;
|
|
||||||
animation-name: slideUp;
|
|
||||||
animation-duration: 0.5s;
|
|
||||||
animation-delay: 0.3s;
|
|
||||||
animation-fill-mode: forwards;
|
|
||||||
}
|
|
||||||
@keyframes slideUp {
|
|
||||||
0% {
|
|
||||||
transform: translateY(60px);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<template>
|
|
||||||
首页,大西瓜
|
|
||||||
</template>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
市场
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
Reference in New Issue
Block a user