feat: 新增找回密码功能
This commit is contained in:
@@ -9,11 +9,11 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
||||
public class DiscussGetListOutputDto : EntityDto<Guid>
|
||||
{
|
||||
/// <summary>
|
||||
/// <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD>۴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 是否禁止评论创建功能
|
||||
/// </summary>
|
||||
public bool IsDisableCreateComment { get; set; }
|
||||
/// <summary>
|
||||
/// <EFBFBD>Ƿ<EFBFBD><EFBFBD>ѵ<EFBFBD><EFBFBD>ޣ<EFBFBD>Ĭ<EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 是否已点赞,默认未登录不点赞
|
||||
/// </summary>
|
||||
public bool IsAgree { get; set; } = false;
|
||||
public string Title { get; set; }
|
||||
@@ -23,26 +23,26 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
||||
public int AgreeNum { get; set; }
|
||||
public int SeeNum { get; set; }
|
||||
|
||||
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܿ<EFBFBD><EFBFBD><EFBFBD>
|
||||
//批量查询,不给内容,性能考虑
|
||||
//public string Content { get; set; }
|
||||
public string? Color { get; set; }
|
||||
|
||||
public Guid PlateId { get; set; }
|
||||
|
||||
//<EFBFBD>Ƿ<EFBFBD><EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD>false
|
||||
//是否置顶,默认false
|
||||
public bool IsTop { get; set; }
|
||||
|
||||
public DiscussPermissionTypeEnum PermissionType { get; set; }
|
||||
//<EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD>false
|
||||
//是否禁止,默认false
|
||||
public bool IsBan { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// 封面
|
||||
/// </summary>
|
||||
public string? Cover { get; set; }
|
||||
|
||||
//˽<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ж<EFBFBD>codeȨ<EFBFBD><EFBFBD>
|
||||
//私有需要判断code权限
|
||||
public string? PrivateCode { get; set; }
|
||||
public DateTime CreationTime { get; set; }
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
||||
Title = DiscussConst.Privacy;
|
||||
Introduction = "";
|
||||
Cover = null;
|
||||
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ
|
||||
//被禁止
|
||||
IsBan = true;
|
||||
}
|
||||
}
|
||||
@@ -73,14 +73,14 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
||||
case DiscussPermissionTypeEnum.Public:
|
||||
break;
|
||||
case DiscussPermissionTypeEnum.Oneself:
|
||||
//<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD>ɼ<EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD>ǰ<EFBFBD><EFBFBD>¼<EFBFBD>û<EFBFBD>
|
||||
//当前主题是仅自己可见,同时不是当前登录用户
|
||||
if (dto.User.Id != userId)
|
||||
{
|
||||
dto.SetBan();
|
||||
}
|
||||
break;
|
||||
case DiscussPermissionTypeEnum.User:
|
||||
//<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>ֿɼ<EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD>ǰ<EFBFBD><EFBFBD>¼<EFBFBD>û<EFBFBD> Ҳ <20><><EFBFBD>ڿɼ<DABF><C9BC>û<EFBFBD><C3BB>б<EFBFBD><D0B1><EFBFBD>
|
||||
//当前主题为部分可见,同时不是当前登录用户 也 不在可见用户列表中
|
||||
if (dto.User.Id != userId && !dto.PermissionUserIds.Contains(userId))
|
||||
{
|
||||
dto.SetBan();
|
||||
|
||||
@@ -17,9 +17,11 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
||||
public class BbsForumAnalyseService : ApplicationService, IApplicationService
|
||||
{
|
||||
private ForumManager _forumManager;
|
||||
public BbsForumAnalyseService(ForumManager forumManager)
|
||||
private ISqlSugarRepository<AgreeEntity> _agreeRepository;
|
||||
public BbsForumAnalyseService(ForumManager forumManager, ISqlSugarRepository<AgreeEntity> agreeRepository)
|
||||
{
|
||||
_forumManager = forumManager;
|
||||
_agreeRepository = agreeRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -38,7 +40,7 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
||||
.Select((discuss, user, info) => new DiscussGetListOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
// IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
|
||||
User = new BbsUserGetListOutputDto()
|
||||
{
|
||||
@@ -52,6 +54,26 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
||||
|
||||
}, true)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount);
|
||||
var discussId = output.Select(x => x.Id);
|
||||
//点赞字典,key为主题id,y为用户ids
|
||||
var agreeDic =
|
||||
(await _agreeRepository._DbQueryable.Where(x => discussId.Contains(x.DiscussId)).ToListAsync())
|
||||
.GroupBy(x => x.DiscussId)
|
||||
.ToDictionary(x => x.Key, y => y.Select(y => y.CreatorId).ToList());
|
||||
|
||||
//等级、是否点赞赋值
|
||||
output?.ForEach(x =>
|
||||
{
|
||||
if (CurrentUser.Id is not null)
|
||||
{
|
||||
//默认fasle
|
||||
if (agreeDic.TryGetValue(x.Id,out var userIds))
|
||||
{
|
||||
x.IsAgree = userIds.Contains(CurrentUser.Id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,19 +29,27 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
/// <summary>
|
||||
/// Discuss应用服务实现,用于参数校验、领域服务业务组合、日志记录、事务处理、账户信息
|
||||
/// </summary>
|
||||
public class DiscussService : YiCrudAppService<DiscussAggregateRoot, DiscussGetOutputDto, DiscussGetListOutputDto, Guid, DiscussGetListInputVo, DiscussCreateInputVo, DiscussUpdateInputVo>,
|
||||
IDiscussService
|
||||
public class DiscussService : YiCrudAppService<DiscussAggregateRoot, DiscussGetOutputDto, DiscussGetListOutputDto,
|
||||
Guid, DiscussGetListInputVo, DiscussCreateInputVo, DiscussUpdateInputVo>,
|
||||
IDiscussService
|
||||
{
|
||||
private ISqlSugarRepository<DiscussTopEntity> _discussTopEntityRepository;
|
||||
private ISqlSugarRepository<DiscussTopEntity> _discussTopRepository;
|
||||
private ISqlSugarRepository<AgreeEntity> _agreeRepository;
|
||||
private BbsUserManager _bbsUserManager;
|
||||
public DiscussService(BbsUserManager bbsUserManager, ForumManager forumManager, ISqlSugarRepository<DiscussTopEntity> discussTopEntityRepository, ISqlSugarRepository<PlateAggregateRoot> plateEntityRepository, ILocalEventBus localEventBus) : base(forumManager._discussRepository)
|
||||
|
||||
public DiscussService(BbsUserManager bbsUserManager, ForumManager forumManager,
|
||||
ISqlSugarRepository<DiscussTopEntity> discussTopRepository,
|
||||
ISqlSugarRepository<PlateAggregateRoot> plateEntityRepository, ILocalEventBus localEventBus,
|
||||
ISqlSugarRepository<AgreeEntity> agreeRepository) : base(forumManager._discussRepository)
|
||||
{
|
||||
_forumManager = forumManager;
|
||||
_plateEntityRepository = plateEntityRepository;
|
||||
_localEventBus = localEventBus;
|
||||
_discussTopEntityRepository = discussTopEntityRepository;
|
||||
_bbsUserManager=bbsUserManager;
|
||||
_agreeRepository = agreeRepository;
|
||||
_discussTopRepository = discussTopRepository;
|
||||
_bbsUserManager = bbsUserManager;
|
||||
}
|
||||
|
||||
private readonly ILocalEventBus _localEventBus;
|
||||
private ForumManager _forumManager { get; set; }
|
||||
|
||||
@@ -49,8 +57,6 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
private ISqlSugarRepository<PlateAggregateRoot> _plateEntityRepository { get; set; }
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 单查
|
||||
/// </summary>
|
||||
@@ -58,42 +64,43 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
/// <returns></returns>
|
||||
public async override Task<DiscussGetOutputDto> GetAsync(Guid id)
|
||||
{
|
||||
|
||||
//查询主题发布 浏览主题 事件,浏览数+1
|
||||
var item = await _forumManager._discussRepository._DbQueryable.LeftJoin<UserAggregateRoot>((discuss, user) => discuss.CreatorId == user.Id)
|
||||
var item = await _forumManager._discussRepository._DbQueryable
|
||||
.LeftJoin<UserAggregateRoot>((discuss, user) => discuss.CreatorId == user.Id)
|
||||
.LeftJoin<BbsUserExtraInfoEntity>((discuss, user, info) => user.Id == info.UserId)
|
||||
.LeftJoin<PlateAggregateRoot>((discuss, user, info, plate) => plate.Id == discuss.PlateId)
|
||||
.Select((discuss, user, info, plate) => new DiscussGetOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
User = new BbsUserGetListOutputDto()
|
||||
{
|
||||
UserName = user.UserName,
|
||||
Nick = user.Nick,
|
||||
Icon = user.Icon,
|
||||
Id = user.Id,
|
||||
Level = info.Level,
|
||||
UserLimit = info.UserLimit,
|
||||
Money=info.Money,
|
||||
Experience=info.Experience
|
||||
},
|
||||
Plate = new Contracts.Dtos.Plate.PlateGetOutputDto()
|
||||
{
|
||||
Name = plate.Name,
|
||||
Id = plate.Id,
|
||||
Code = plate.Code,
|
||||
Introduction = plate.Introduction,
|
||||
Logo = plate.Logo
|
||||
|
||||
}
|
||||
}, true)
|
||||
.SingleAsync(discuss => discuss.Id == id);
|
||||
.Select((discuss, user, info, plate) => new DiscussGetOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null,
|
||||
x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
User = new BbsUserGetListOutputDto()
|
||||
{
|
||||
UserName = user.UserName,
|
||||
Nick = user.Nick,
|
||||
Icon = user.Icon,
|
||||
Id = user.Id,
|
||||
Level = info.Level,
|
||||
UserLimit = info.UserLimit,
|
||||
Money = info.Money,
|
||||
Experience = info.Experience
|
||||
},
|
||||
Plate = new Contracts.Dtos.Plate.PlateGetOutputDto()
|
||||
{
|
||||
Name = plate.Name,
|
||||
Id = plate.Id,
|
||||
Code = plate.Code,
|
||||
Introduction = plate.Introduction,
|
||||
Logo = plate.Logo
|
||||
}
|
||||
}, true)
|
||||
.SingleAsync(discuss => discuss.Id == id);
|
||||
|
||||
if (item is not null)
|
||||
{
|
||||
await VerifyDiscussPermissionAsync(item.Id);
|
||||
await _localEventBus.PublishAsync(new SeeDiscussEventArgs { DiscussId = item.Id, OldSeeNum = item.SeeNum });
|
||||
await _localEventBus.PublishAsync(new SeeDiscussEventArgs
|
||||
{ DiscussId = item.Id, OldSeeNum = item.SeeNum });
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -105,49 +112,65 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<PagedResultDto<DiscussGetListOutputDto>> GetListAsync([FromQuery] DiscussGetListInputVo input)
|
||||
public override async Task<PagedResultDto<DiscussGetListOutputDto>> GetListAsync(
|
||||
[FromQuery] DiscussGetListInputVo input)
|
||||
{
|
||||
//需要关联创建者用户
|
||||
RefAsync<int> total = 0;
|
||||
var items = await _forumManager._discussRepository._DbQueryable
|
||||
.WhereIF(!string.IsNullOrEmpty(input.Title), x => x.Title.Contains(input.Title))
|
||||
.WhereIF(input.PlateId is not null, x => x.PlateId == input.PlateId)
|
||||
.WhereIF(input.IsTop is not null, x => x.IsTop == input.IsTop)
|
||||
.WhereIF(input.UserId is not null,x=>x.CreatorId==input.UserId)
|
||||
.LeftJoin<UserAggregateRoot>((discuss, user) => discuss.CreatorId == user.Id)
|
||||
.WhereIF(input.UserName is not null, (discuss, user)=>user.UserName==input.UserName!)
|
||||
|
||||
.LeftJoin<BbsUserExtraInfoEntity>((discuss, user, info) => user.Id == info.UserId)
|
||||
|
||||
.OrderByDescending(discuss => discuss.OrderNum)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.New, discuss => discuss.CreationTime, OrderByType.Desc)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.Host, discuss => discuss.SeeNum, OrderByType.Desc)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.Suggest, discuss => discuss.AgreeNum, OrderByType.Desc)
|
||||
|
||||
.Select((discuss, user, info) => new DiscussGetListOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
|
||||
User = new BbsUserGetListOutputDto()
|
||||
{
|
||||
Id = user.Id,
|
||||
UserName = user.UserName,
|
||||
Nick = user.Nick,
|
||||
Icon = user.Icon,
|
||||
Level = info.Level,
|
||||
UserLimit = info.UserLimit,
|
||||
Money = info.Money,
|
||||
Experience = info.Experience
|
||||
}
|
||||
|
||||
}, true)
|
||||
.WhereIF(!string.IsNullOrEmpty(input.Title), x => x.Title.Contains(input.Title))
|
||||
.WhereIF(input.PlateId is not null, x => x.PlateId == input.PlateId)
|
||||
.WhereIF(input.IsTop is not null, x => x.IsTop == input.IsTop)
|
||||
.WhereIF(input.UserId is not null, x => x.CreatorId == input.UserId)
|
||||
.LeftJoin<UserAggregateRoot>((discuss, user) => discuss.CreatorId == user.Id)
|
||||
.WhereIF(input.UserName is not null, (discuss, user) => user.UserName == input.UserName!)
|
||||
.LeftJoin<BbsUserExtraInfoEntity>((discuss, user, info) => user.Id == info.UserId)
|
||||
.OrderByDescending(discuss => discuss.OrderNum)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.New, discuss => discuss.CreationTime, OrderByType.Desc)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.Host, discuss => discuss.SeeNum, OrderByType.Desc)
|
||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.Suggest, discuss => discuss.AgreeNum, OrderByType.Desc)
|
||||
.Select((discuss, user, info) => new DiscussGetListOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
// 优化查询,不使用子查询
|
||||
// IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
User = new BbsUserGetListOutputDto()
|
||||
{
|
||||
Id = user.Id,
|
||||
UserName = user.UserName,
|
||||
Nick = user.Nick,
|
||||
Icon = user.Icon,
|
||||
Level = info.Level,
|
||||
UserLimit = info.UserLimit,
|
||||
Money = info.Money,
|
||||
Experience = info.Experience
|
||||
}
|
||||
}, true)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
var discussId = items.Select(x => x.Id);
|
||||
|
||||
//点赞字典,key为主题id,y为用户ids
|
||||
var agreeDic =
|
||||
(await _agreeRepository._DbQueryable.Where(x => discussId.Contains(x.DiscussId)).ToListAsync())
|
||||
.GroupBy(x => x.DiscussId)
|
||||
.ToDictionary(x => x.Key, y => y.Select(y => y.CreatorId).ToList());
|
||||
|
||||
//查询完主题之后,要过滤一下私有的主题信息
|
||||
items.ApplyPermissionTypeFilter(CurrentUser.Id ?? Guid.Empty);
|
||||
|
||||
items?.ForEach(x => x.User.LevelName = _bbsUserManager._levelCacheDic[x.User.Level].Name);
|
||||
//等级、是否点赞赋值
|
||||
items?.ForEach(x =>
|
||||
{
|
||||
x.User.LevelName = _bbsUserManager._levelCacheDic[x.User.Level].Name;
|
||||
if (CurrentUser.Id is not null)
|
||||
{
|
||||
//默认fasle
|
||||
if (agreeDic.TryGetValue(x.Id,out var userIds))
|
||||
{
|
||||
x.IsAgree = userIds.Contains(CurrentUser.Id);
|
||||
}
|
||||
}
|
||||
});
|
||||
return new PagedResultDto<DiscussGetListOutputDto>(total, items);
|
||||
}
|
||||
|
||||
@@ -157,14 +180,16 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
/// <returns></returns>
|
||||
public async Task<List<DiscussGetListOutputDto>> GetListTopAsync()
|
||||
{
|
||||
var output = await _discussTopEntityRepository._DbQueryable.LeftJoin<DiscussAggregateRoot>((top, discuss) => top.DiscussId == discuss.Id)
|
||||
var output = await _discussTopRepository._DbQueryable
|
||||
.LeftJoin<DiscussAggregateRoot>((top, discuss) => top.DiscussId == discuss.Id)
|
||||
.LeftJoin<UserAggregateRoot>((top, discuss, user) => discuss.CreatorId == user.Id)
|
||||
.LeftJoin<BbsUserExtraInfoEntity>((top, discuss, user, info) => user.Id == info.UserId)
|
||||
.OrderByDescending(top => top.OrderNum)
|
||||
.Select((top, discuss, user, info) => new DiscussGetListOutputDto
|
||||
{
|
||||
Id = discuss.Id,
|
||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null,
|
||||
x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||
User = new BbsUserGetListOutputDto
|
||||
{
|
||||
Id = user.Id,
|
||||
@@ -206,6 +231,11 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
throw new UserFriendlyException(PlateConst.No_Exist);
|
||||
}
|
||||
|
||||
if (await _forumManager._discussRepository.IsAnyAsync(x => x.Title == input.Title))
|
||||
{
|
||||
throw new UserFriendlyException(DiscussConst.Repeat);
|
||||
}
|
||||
|
||||
//如果开启了禁用创建主题
|
||||
if (plate.IsDisableCreateDiscuss == true)
|
||||
{
|
||||
@@ -233,6 +263,7 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
{
|
||||
throw new UserFriendlyException(DiscussConst.No_Exist);
|
||||
}
|
||||
|
||||
if (discuss.PermissionType == DiscussPermissionTypeEnum.Oneself)
|
||||
{
|
||||
if (discuss.CreatorId != CurrentUser.Id)
|
||||
@@ -240,13 +271,15 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
||||
throw new UserFriendlyException(DiscussConst.Privacy);
|
||||
}
|
||||
}
|
||||
|
||||
if (discuss.PermissionType == DiscussPermissionTypeEnum.User)
|
||||
{
|
||||
if (discuss.CreatorId != CurrentUser.Id && !discuss.PermissionUserIds.Contains(CurrentUser.Id ?? Guid.Empty))
|
||||
if (discuss.CreatorId != CurrentUser.Id &&
|
||||
!discuss.PermissionUserIds.Contains(CurrentUser.Id ?? Guid.Empty))
|
||||
{
|
||||
throw new UserFriendlyException(DiscussConst.Privacy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ namespace Yi.Framework.Bbs.Domain.Shared.Consts
|
||||
/// </summary>
|
||||
public class DiscussConst
|
||||
{
|
||||
public const string Repeat = "创建主题重复";
|
||||
public const string No_Exist = "传入的主题id不存在";
|
||||
|
||||
public const string Privacy = "【私密】您无该主题权限,可联系作者申请开放";
|
||||
|
||||
@@ -184,22 +184,24 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("captcha-phone")]
|
||||
[HttpPost("account/captcha-phone")]
|
||||
[AllowAnonymous]
|
||||
public async Task<object> PostCaptchaPhoneForRegisterAsync(PhoneCaptchaImageDto input)
|
||||
{
|
||||
return await PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.Register, input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 手机验证码-找回密码
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("captcha-phone/repassword")]
|
||||
[HttpPost("account/captcha-phone/repassword")]
|
||||
public async Task<object> PostCaptchaPhoneForRetrievePasswordAsync(PhoneCaptchaImageDto input)
|
||||
{
|
||||
return await PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.RetrievePassword, input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 手机验证码
|
||||
/// </summary>
|
||||
@@ -223,7 +225,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
var uuid = Guid.NewGuid();
|
||||
await _aliyunManger.SendSmsAsync(input.Phone, code);
|
||||
|
||||
await _phoneCache.SetAsync(new CaptchaPhoneCacheKey(ValidationPhoneTypeEnum.Register, input.Phone),
|
||||
await _phoneCache.SetAsync(new CaptchaPhoneCacheKey(ValidationPhoneTypeEnum.RetrievePassword, input.Phone),
|
||||
new CaptchaPhoneCacheItem(code),
|
||||
new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(10) });
|
||||
return new
|
||||
@@ -255,14 +257,11 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
/// <param name="input"></param>
|
||||
[AllowAnonymous]
|
||||
[UnitOfWork]
|
||||
public async Task PostRetrievePasswordAsync(RetrievePasswordDto input)
|
||||
public async Task<string> PostRetrievePasswordAsync(RetrievePasswordDto input)
|
||||
{
|
||||
if (_rbacOptions.EnableCaptcha)
|
||||
{
|
||||
//校验验证码,根据电话号码获取 value,比对验证码已经uuid
|
||||
await ValidationPhoneCaptchaAsync(ValidationPhoneTypeEnum.RetrievePassword, input.Phone, input.Code);
|
||||
}
|
||||
|
||||
//校验验证码,根据电话号码获取 value,比对验证码已经uuid
|
||||
await ValidationPhoneCaptchaAsync(ValidationPhoneTypeEnum.RetrievePassword, input.Phone, input.Code);
|
||||
|
||||
var entity = await _userRepository.GetFirstAsync(x => x.Phone == input.Phone);
|
||||
if (entity is null)
|
||||
{
|
||||
@@ -270,6 +269,8 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
}
|
||||
|
||||
await _accountManager.RestPasswordAsync(entity.Id, input.Password);
|
||||
|
||||
return entity.UserName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new UserFriendlyException("文件不存在",code:"404");
|
||||
return new NotFoundResult();
|
||||
// throw new UserFriendlyException("文件不存在",code:"404");
|
||||
}
|
||||
|
||||
|
||||
@@ -66,12 +67,6 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
// path = $"wwwroot/{FileTypeEnum.Thumbnail}/{file.Id}{Path.GetExtension(file.FileName)}";
|
||||
//}
|
||||
//路径为: 文件路径/文件id+文件扩展名
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new UserFriendlyException("本地文件不存在", "404");
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,4 +7,7 @@ VITE_APP_URL="http://localhost:19001/api/app"
|
||||
|
||||
# ws/开发环境
|
||||
VITE_APP_BASE_WS = '/dev-ws'
|
||||
VITE_APP_BASE_URL_WS="http://localhost:19001/hub"
|
||||
VITE_APP_BASE_URL_WS="http://localhost:19001/hub"
|
||||
|
||||
# 是否开启ICP备案模式
|
||||
VITE_APP_ICP = true
|
||||
@@ -6,4 +6,7 @@ VITE_APP_URL="http://ccnetcore.com:19001/api/app"
|
||||
|
||||
# ws
|
||||
VITE_APP_BASE_WS = '/prod-ws'
|
||||
VITE_APP_BASE_URL_WS="http://ccnetcore.com:19001/hub"
|
||||
VITE_APP_BASE_URL_WS="http://ccnetcore.com:19001/hub"
|
||||
|
||||
# 是否开启ICP备案模式
|
||||
VITE_APP_ICP = true
|
||||
@@ -4,20 +4,22 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>.Net意社区</title>
|
||||
<link rel="stylesheet" href="/src/assets/loading.css" />
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5453339688995325"
|
||||
crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="Loading">
|
||||
<div class="loader JS_on">
|
||||
<span class="binary"></span>
|
||||
<span class="binary"></span>
|
||||
<span class="getting-there">意社区很大,你要等一下...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
<!--<title>.Net意社区</title>-->
|
||||
<!-- 为了,icp备案-->
|
||||
<title>个人成果展示</title>
|
||||
<link rel="stylesheet" href="/src/assets/loading.css" />
|
||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5453339688995325"
|
||||
crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="Loading">
|
||||
<div class="loader JS_on">
|
||||
<span class="binary"></span>
|
||||
<span class="binary"></span>
|
||||
<span class="getting-there">意社区很大,你要等一下...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -18,6 +18,24 @@ export function login(username, password, code, uuid) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//找回密码
|
||||
export function retrievePassword(password, phone, code, uuid) {
|
||||
const data = {
|
||||
password,
|
||||
phone,
|
||||
code,
|
||||
uuid,
|
||||
};
|
||||
return request({
|
||||
url: "/account/retrieve-password",
|
||||
headers: {
|
||||
isToken: false,
|
||||
},
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
// 注册方法
|
||||
export function register(userName, password, phone, code, uuid) {
|
||||
const data = {
|
||||
@@ -76,3 +94,15 @@ export function getCodePhone(phone) {
|
||||
data: { phone },
|
||||
});
|
||||
}
|
||||
// 获取短信验证码-为了重置密码
|
||||
export function getCodePhoneForRetrievePassword(phone) {
|
||||
return request({
|
||||
url: "/account/captcha-phone/repassword",
|
||||
headers: {
|
||||
isToken: false,
|
||||
},
|
||||
method: "post",
|
||||
timeout: 20000,
|
||||
data: { phone },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import request from "@/config/axios/service";
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @param {*} data 账号密码
|
||||
@@ -23,6 +22,17 @@ export function userRegister(data) {
|
||||
data,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 用户找回密码
|
||||
* @param {*} data 账号密码
|
||||
*/
|
||||
export function userRetrievePassword(data) {
|
||||
return request({
|
||||
url: `/account/retrieve-password`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户详细信息
|
||||
@@ -44,15 +54,6 @@ export function userLogout() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取验证码
|
||||
*/
|
||||
export function getCodeImg() {
|
||||
return request({
|
||||
url: `/account/captcha-image`,
|
||||
method: "get",
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取短信验证码
|
||||
*/
|
||||
|
||||
@@ -103,13 +103,18 @@ height: 25px;
|
||||
.left-lable
|
||||
{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
}
|
||||
.left-lable label{
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.right-forgot{
|
||||
cursor: pointer;
|
||||
}
|
||||
.right-forgot:hover{
|
||||
color: #7f438c;
|
||||
}
|
||||
.bottom-div
|
||||
{
|
||||
font-size: 12px;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
@@ -7,7 +7,7 @@ import {
|
||||
userLogin,
|
||||
getUserDetailInfo,
|
||||
userLogout,
|
||||
userRegister,
|
||||
userRegister, userRetrievePassword,
|
||||
} from "@/apis/auth";
|
||||
const TokenKey = "AccessToken";
|
||||
export const AUTH_MENUS = "AUTH_MENUS";
|
||||
@@ -182,6 +182,20 @@ const currentUserInfo=computed(()=>{
|
||||
// }
|
||||
};
|
||||
|
||||
// 找回密码
|
||||
const retrievePasswordFun = async (params) => {
|
||||
// try {
|
||||
const {data}=await userRetrievePassword(params);
|
||||
ElMessage({
|
||||
message: `恭喜!账号:${data},找回成功!密码已重置,请登录!`,
|
||||
type: "success",
|
||||
duration: 8000
|
||||
});
|
||||
// } catch (error) {
|
||||
// console.log(error);
|
||||
// }
|
||||
};
|
||||
|
||||
return {
|
||||
getToken,
|
||||
setToken,
|
||||
@@ -189,6 +203,7 @@ const currentUserInfo=computed(()=>{
|
||||
loginFun,
|
||||
getUserInfo,
|
||||
logoutFun,
|
||||
retrievePasswordFun,
|
||||
clearStorage,
|
||||
registerFun,
|
||||
loginSuccess,
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
<div class="image">
|
||||
<img class="img-icon" src="@/assets/common/icons/logo.ico" />
|
||||
</div>
|
||||
<div class="text">{{ configStore.name }}</div>
|
||||
|
||||
<div class="text">{{ isIcp===true?"个人成果展示":configStore.name }}</div>
|
||||
</div>
|
||||
<div class="tab">
|
||||
<el-menu :default-active="activeIndex" mode="horizontal" :ellipsis="false" @select="handleSelect">
|
||||
@@ -152,6 +153,8 @@ const searchText = ref("");
|
||||
const noticeForNoReadCount = computed(() => {
|
||||
return noticeList.value.filter(x => x.isRead == false).length;
|
||||
})
|
||||
|
||||
const isIcp=import.meta.env.VITE_APP_ICP==="true";
|
||||
//加载初始化离线消息
|
||||
onMounted(async () => {
|
||||
//登录了才去判断消息通知
|
||||
|
||||
@@ -26,13 +26,18 @@ const router = createRouter({
|
||||
name: "login",
|
||||
path: "/login",
|
||||
// component: () => import("../views/Login.vue"),
|
||||
component: () => import("../views/login/index.vue"),
|
||||
component: () => import("../views/login/login.vue"),
|
||||
},
|
||||
{
|
||||
name: "register",
|
||||
path: "/register",
|
||||
component: () => import("../views/login/register.vue"),
|
||||
},
|
||||
{
|
||||
name: "forgotPassword",
|
||||
path: "/forgotPassword",
|
||||
component: () => import("../views/login/forgotPassword.vue"),
|
||||
},
|
||||
{
|
||||
name: "auth",
|
||||
path: "/auth/:type",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { login, logout, register } from "@/apis/accountApi";
|
||||
import { login, logout, register,retrievePassword } from "@/apis/accountApi";
|
||||
import { getUserDetailInfo, getLoginCode } from "@/apis/auth";
|
||||
import useAuths from "@/hooks/useAuths";
|
||||
import { defineStore } from "pinia";
|
||||
@@ -122,6 +122,23 @@ const useUserStore = defineStore("user", {
|
||||
});
|
||||
});
|
||||
},
|
||||
//找回密码
|
||||
retrievePassword(userInfo)
|
||||
{
|
||||
const password = userInfo.password.trim();
|
||||
const phone = userInfo.phone;
|
||||
const uuid = userInfo.uuid;
|
||||
const code = userInfo.code;
|
||||
return new Promise((resolve, reject) => {
|
||||
retrievePassword(password, phone, code, uuid)
|
||||
.then((response) => {
|
||||
resolve(response);
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
// 重置用户信息
|
||||
resetInfo() {
|
||||
this.roles = [];
|
||||
|
||||
@@ -4,7 +4,26 @@
|
||||
<el-col :span="17">
|
||||
<div class="chat-hub">
|
||||
<!-- <p @click="onClickToChatHub">点击前往-最新上线<span>《聊天室》 </span>,现已支持<span>Ai助手</span>,希望能帮助大家</p>-->
|
||||
<p @click="onClickToWeChat">点击关注-最新上线<span>《意.Net官方微信公众号》 </span>,分享有<span>深度</span>的.Net知识,希望能帮助大家</p>
|
||||
|
||||
<p v-if="isIcp"
|
||||
style="font-size: 25px;
|
||||
color: blue;
|
||||
background: red;
|
||||
/* height: 80px; */
|
||||
font-weight: 900;
|
||||
text-align: center;
|
||||
margin: 10px auto;">
|
||||
本站点为个人内容分享,全部资料免费开源学习,所有数据为假数据
|
||||
<br/>
|
||||
不涉及企业、团体、论坛和经营销售等内容,只做简单的成果展示
|
||||
<br/>
|
||||
富强、民主、文明、和谐、自由、平等
|
||||
<br/>
|
||||
公正、法治、爱国、敬业、诚信、友善
|
||||
</p>
|
||||
<p v-else @click="onClickToWeChat">点击关注-最新上线<span>《意.Net官方微信公众号》 </span>,分享有<span>深度</span>的.Net知识,希望能帮助大家</p>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="scrollbar">
|
||||
<ScrollbarInfo/>
|
||||
@@ -272,7 +291,7 @@ const activeList = [
|
||||
{name: "开始", path: "/start", icon: "Position"},
|
||||
{name: "聊天室", path: "/chat", icon: "ChatRound"},
|
||||
];
|
||||
|
||||
const isIcp=import.meta.env.VITE_APP_ICP==="true";
|
||||
//主题查询参数
|
||||
const query = reactive({
|
||||
skipCount: 1,
|
||||
@@ -622,7 +641,7 @@ const onClickToWeChat=()=>{
|
||||
display: flex;
|
||||
align-content: center;
|
||||
flex-wrap: wrap;
|
||||
height: 30px;
|
||||
min-height: 30px;
|
||||
|
||||
p {
|
||||
margin: 0 auto;
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
153
Yi.Bbs.Vue3/src/views/login/forgotPassword.vue
Normal file
153
Yi.Bbs.Vue3/src/views/login/forgotPassword.vue
Normal file
@@ -0,0 +1,153 @@
|
||||
<script setup>
|
||||
|
||||
// 注册逻辑
|
||||
import {reactive, ref} from "vue";
|
||||
import {getCodePhoneForRetrievePassword} from "@/apis/accountApi";
|
||||
import useAuths from "@/hooks/useAuths";
|
||||
import { useRouter} from "vue-router";
|
||||
const { retrievePasswordFun } = useAuths();
|
||||
const router = useRouter();
|
||||
const retrievePasswordFormRef = ref();
|
||||
|
||||
|
||||
// 确认密码
|
||||
const passwordConfirm = ref("");
|
||||
const registerForm = reactive({
|
||||
phone: "",
|
||||
password: "",
|
||||
uuid: "",
|
||||
code: ""
|
||||
});
|
||||
const registerRules = reactive({
|
||||
phone: [{ required: true, message: "请输入手机号", trigger: "blur" }],
|
||||
code: [{ required: true, message: "请输入验证码", trigger: "blur" }],
|
||||
password: [
|
||||
{ required: true, message: "请输入新的密码", trigger: "blur" },
|
||||
{ min: 6, message: "密码需大于六位", trigger: "blur" },
|
||||
],
|
||||
});
|
||||
|
||||
const retrievePassword = async (formEl) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate(async (valid) => {
|
||||
|
||||
if (valid) {
|
||||
try {
|
||||
if (registerForm.password != passwordConfirm.value) {
|
||||
ElMessage.error("两次密码输入不一致");
|
||||
return;
|
||||
}
|
||||
await retrievePasswordFun(registerForm);
|
||||
//注册成功返回登录
|
||||
handleSignInNow();
|
||||
} catch (error) {
|
||||
ElMessage({
|
||||
message: error.message,
|
||||
type: "error",
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
//验证码
|
||||
const codeInfo = ref("发送短信");
|
||||
const isDisabledCode = ref(false);
|
||||
|
||||
//前往登录
|
||||
const handleSignInNow=()=>{
|
||||
router.push("/login");
|
||||
}
|
||||
const captcha = async () => {
|
||||
if (registerForm.phone !== "") {
|
||||
const { data } = await getCodePhoneForRetrievePassword(registerForm.phone);
|
||||
registerForm.uuid = data.uuid;
|
||||
ElMessage({
|
||||
message: `已向${registerForm.phone}发送验证码,请注意查收`,
|
||||
type: "success",
|
||||
});
|
||||
isDisabledCode.value = true;
|
||||
let time = 60; //定义剩下的秒数
|
||||
let timer = setInterval(function () {
|
||||
if (time == 0) {
|
||||
//清除定时器和复原按钮
|
||||
clearInterval(timer);
|
||||
codeInfo.value = "发送验证码";
|
||||
time = 60; //这个10是重新开始
|
||||
} else {
|
||||
codeInfo.value = "剩余" + time + "秒";
|
||||
time--;
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
ElMessage({
|
||||
message: `请先输入手机号`,
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container">
|
||||
<!-- 找回密码 -->
|
||||
<div class="div-content">
|
||||
<div class="div-right-register">
|
||||
<img class="div-img" src="@/assets/login.png"/>
|
||||
</div>
|
||||
<div class="div-left-register">
|
||||
<div class="left-container">
|
||||
<p class="title register-title">Find Password!</p>
|
||||
<el-form
|
||||
class="registerForm"
|
||||
ref="retrievePasswordFormRef"
|
||||
:model="registerForm"
|
||||
:rules="registerRules"
|
||||
>
|
||||
<div class="input-content">
|
||||
|
||||
<div class="input" style="margin-top: 0">
|
||||
<p>*电话</p>
|
||||
<el-form-item prop="phone">
|
||||
<div class="phone-code">
|
||||
<input class="phone-code-input" type="text" v-model.trim="registerForm.phone">
|
||||
<button type="button" class="phone-code-btn" @click="captcha()">{{codeInfo}}</button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="input">
|
||||
<p>*短信验证码</p>
|
||||
<el-form-item prop="code" >
|
||||
<input :disabled="!isDisabledCode" type="text" v-model.trim="registerForm.code">
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="input">
|
||||
<p>*新的密码</p>
|
||||
<el-form-item prop="password">
|
||||
<input :disabled="!isDisabledCode" type="password" v-model.trim="registerForm.password">
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="input">
|
||||
<p>*确认密码</p>
|
||||
<el-form-item>
|
||||
<input :disabled="!isDisabledCode" type="password" v-model.trim="passwordConfirm">
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</el-form>
|
||||
<div class="left-btn">
|
||||
<button type="button" class="btn-login" @click="retrievePassword(retrievePasswordFormRef)">确认重置密码</button>
|
||||
<button type="button" class="btn-reg" @click="handleSignInNow">前往登录</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style src="@/assets/styles/login.css" scoped>
|
||||
</style>
|
||||
@@ -1,145 +1,153 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<!-- 登录 -->
|
||||
<div class="div-content">
|
||||
<div class="div-left">
|
||||
<div class="left-container">
|
||||
<p class="title title-1">Hello,<span @click="guestlogin">you can go to homepage >></span></p>
|
||||
<p class="title title-2">Welcome to Yi!</p>
|
||||
<el-form
|
||||
ref="loginFormRef"
|
||||
:model="loginForm"
|
||||
:rules="rules"
|
||||
>
|
||||
|
||||
<div class="input-content">
|
||||
<div class="input">
|
||||
<p>用户名</p>
|
||||
<el-form-item prop="userName">
|
||||
<input type="text" v-model="loginForm.userName">
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="input">
|
||||
<p>密码</p>
|
||||
<el-form-item prop="password">
|
||||
<input type="password" v-model="loginForm.password">
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="input">
|
||||
<p>验证码</p>
|
||||
<el-form-item prop="code">
|
||||
<div class="code">
|
||||
<input class="code-input" type="text" v-model.trim="loginForm.code">
|
||||
<img class="code-img" alt="加载中" @click="handleGetCodeImage" :src="codeImageURL">
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
<div class="left-lable">
|
||||
<input type="checkbox">
|
||||
<label>记住我</label>
|
||||
</div>
|
||||
|
||||
<div class="left-btn">
|
||||
<button type="button" class="btn-login" @click="login(loginFormRef)">登录</button>
|
||||
<button type="button" class="btn-reg" @click="handleRegister">前往注册</button>
|
||||
</div>
|
||||
<div class="bottom-div">
|
||||
<p>其他方式: <span @click="handleQQLogin"><img src="@/assets/login_images/qq-setting.png" alt="QQ" /></span> <span @click="handleGiteeLogin"><img src="@/assets/login_images/gitee-setting.png" alt="Gitee" /></span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="div-right">
|
||||
<img class="div-img" src="@/assets/login.png" alt=""/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, computed } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import useAuths from "@/hooks/useAuths";
|
||||
import useUserStore from "@/stores/user";
|
||||
const { loginFun, loginSuccess } = useAuths();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const loginFormRef = ref();
|
||||
const rules = reactive({
|
||||
userName: [{ required: true, message: "请输入用户名", trigger: "blur" }],
|
||||
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
|
||||
});
|
||||
const loginForm = reactive({
|
||||
userName: "",
|
||||
password: "",
|
||||
uuid: "",
|
||||
code: "",
|
||||
});
|
||||
//前往注册
|
||||
const handleRegister=()=>{
|
||||
router.push("/register");
|
||||
}
|
||||
//直接进入首页
|
||||
const guestlogin = () => {
|
||||
const redirect = route.query?.redirect ?? "/index";
|
||||
router.push(redirect);
|
||||
};
|
||||
const codeUUid = computed(() => useUserStore().codeUUid);
|
||||
const login = async (formEl) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
try {
|
||||
loginForm.uuid = codeUUid.value;
|
||||
loginFun(loginForm);
|
||||
} catch (error) {
|
||||
console.log(error.message, "error.message");
|
||||
ElMessage({
|
||||
message: error.message,
|
||||
type: "error",
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 获取图片验证码
|
||||
const codeImageURL = computed(() => useUserStore().codeImageURL);
|
||||
const handleGetCodeImage = () => {
|
||||
useUserStore().updateCodeImage();
|
||||
};
|
||||
onMounted(async () => {
|
||||
await useUserStore().updateCodeImage();
|
||||
});
|
||||
|
||||
|
||||
const handleQQLogin = () => {
|
||||
window.open(
|
||||
"https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=102087446&redirect_uri=https://ccnetcore.com/auth/qq&state=0&scope=get_user_info",
|
||||
undefined,
|
||||
"width=500,height=500,left=50,top=50"
|
||||
);
|
||||
};
|
||||
|
||||
const handleGiteeLogin = () => {
|
||||
window.open(
|
||||
"https://gitee.com/oauth/authorize?client_id=949f3519969adc5cfe82c209b71300e8e0868e8536f3d7f59195c8f1e5b72502&redirect_uri=https%3A%2F%2Fccnetcore.com%2Fauth%2Fgitee&state=0&response_type=code",
|
||||
undefined,
|
||||
"width=500,height=500,left=50,top=50"
|
||||
);
|
||||
};
|
||||
|
||||
window.addEventListener("message", async (e) => {
|
||||
const { authData, type } = e.data;
|
||||
console.log(authData, "传到登录页的值");
|
||||
if (authData) {
|
||||
await loginSuccess({ data: JSON.parse(authData) });
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style src="@/assets/styles/login.css" scoped>
|
||||
<template>
|
||||
<div class="container">
|
||||
<!-- 登录 -->
|
||||
<div class="div-content">
|
||||
<div class="div-left">
|
||||
<div class="left-container">
|
||||
<p class="title title-1">Hello,<span @click="guestlogin">you can go to homepage >></span></p>
|
||||
<p class="title title-2">Welcome to Yi!</p>
|
||||
<el-form
|
||||
ref="loginFormRef"
|
||||
:model="loginForm"
|
||||
:rules="rules"
|
||||
>
|
||||
|
||||
<div class="input-content">
|
||||
<div class="input">
|
||||
<p>用户名</p>
|
||||
<el-form-item prop="userName">
|
||||
<input type="text" v-model="loginForm.userName">
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="input">
|
||||
<p>密码</p>
|
||||
<el-form-item prop="password">
|
||||
<input type="password" v-model="loginForm.password">
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="input">
|
||||
<p>验证码</p>
|
||||
<el-form-item prop="code">
|
||||
<div class="code">
|
||||
<input class="code-input" type="text" v-model.trim="loginForm.code">
|
||||
<img class="code-img" alt="加载中" @click="handleGetCodeImage" :src="codeImageURL">
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
<div class="left-lable">
|
||||
<div>
|
||||
<input type="checkbox">
|
||||
<label>记住我</label>
|
||||
</div>
|
||||
|
||||
<span class="right-forgot" @click="handleForgotPassword">忘记密码?点击找回</span>
|
||||
</div>
|
||||
|
||||
<div class="left-btn">
|
||||
<button type="button" class="btn-login" @click="login(loginFormRef)">登录</button>
|
||||
<button type="button" class="btn-reg" @click="handleRegister">前往注册</button>
|
||||
</div>
|
||||
<div class="bottom-div">
|
||||
<p>其他方式: <span @click="handleQQLogin"><img src="@/assets/login_images/qq-setting.png" alt="QQ" /></span> <span @click="handleGiteeLogin"><img src="@/assets/login_images/gitee-setting.png" alt="Gitee" /></span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="div-right">
|
||||
<img class="div-img" src="@/assets/login.png" alt=""/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, computed } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import useAuths from "@/hooks/useAuths";
|
||||
import useUserStore from "@/stores/user";
|
||||
const { loginFun, loginSuccess } = useAuths();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const loginFormRef = ref();
|
||||
const rules = reactive({
|
||||
userName: [{ required: true, message: "请输入用户名", trigger: "blur" }],
|
||||
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
|
||||
});
|
||||
const loginForm = reactive({
|
||||
userName: "",
|
||||
password: "",
|
||||
uuid: "",
|
||||
code: "",
|
||||
});
|
||||
//前往注册
|
||||
const handleRegister=()=>{
|
||||
router.push("/register");
|
||||
}
|
||||
//前往忘记密码
|
||||
const handleForgotPassword = () => {
|
||||
router.push("/forgotPassword");
|
||||
}
|
||||
//直接进入首页
|
||||
const guestlogin = () => {
|
||||
const redirect = route.query?.redirect ?? "/index";
|
||||
router.push(redirect);
|
||||
};
|
||||
const codeUUid = computed(() => useUserStore().codeUUid);
|
||||
const login = async (formEl) => {
|
||||
if (!formEl) return;
|
||||
await formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
try {
|
||||
loginForm.uuid = codeUUid.value;
|
||||
loginFun(loginForm);
|
||||
} catch (error) {
|
||||
console.log(error.message, "error.message");
|
||||
ElMessage({
|
||||
message: error.message,
|
||||
type: "error",
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 获取图片验证码
|
||||
const codeImageURL = computed(() => useUserStore().codeImageURL);
|
||||
const handleGetCodeImage = () => {
|
||||
useUserStore().updateCodeImage();
|
||||
};
|
||||
onMounted(async () => {
|
||||
await useUserStore().updateCodeImage();
|
||||
});
|
||||
|
||||
|
||||
const handleQQLogin = () => {
|
||||
window.open(
|
||||
"https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=102087446&redirect_uri=https://ccnetcore.com/auth/qq&state=0&scope=get_user_info",
|
||||
undefined,
|
||||
"width=500,height=500,left=50,top=50"
|
||||
);
|
||||
};
|
||||
|
||||
const handleGiteeLogin = () => {
|
||||
window.open(
|
||||
"https://gitee.com/oauth/authorize?client_id=949f3519969adc5cfe82c209b71300e8e0868e8536f3d7f59195c8f1e5b72502&redirect_uri=https%3A%2F%2Fccnetcore.com%2Fauth%2Fgitee&state=0&response_type=code",
|
||||
undefined,
|
||||
"width=500,height=500,left=50,top=50"
|
||||
);
|
||||
};
|
||||
|
||||
window.addEventListener("message", async (e) => {
|
||||
const { authData, type } = e.data;
|
||||
console.log(authData, "传到登录页的值");
|
||||
if (authData) {
|
||||
await loginSuccess({ data: JSON.parse(authData) });
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style src="@/assets/styles/login.css" scoped>
|
||||
</style>
|
||||
Reference in New Issue
Block a user