feat: 新增找回密码功能
This commit is contained in:
@@ -9,11 +9,11 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
|||||||
public class DiscussGetListOutputDto : EntityDto<Guid>
|
public class DiscussGetListOutputDto : EntityDto<Guid>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD>۴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
/// 是否禁止评论创建功能
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsDisableCreateComment { get; set; }
|
public bool IsDisableCreateComment { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <EFBFBD>Ƿ<EFBFBD><EFBFBD>ѵ<EFBFBD><EFBFBD>ޣ<EFBFBD>Ĭ<EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
/// 是否已点赞,默认未登录不点赞
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsAgree { get; set; } = false;
|
public bool IsAgree { get; set; } = false;
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
@@ -23,26 +23,26 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
|||||||
public int AgreeNum { get; set; }
|
public int AgreeNum { get; set; }
|
||||||
public int SeeNum { 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 Content { get; set; }
|
||||||
public string? Color { get; set; }
|
public string? Color { get; set; }
|
||||||
|
|
||||||
public Guid PlateId { get; set; }
|
public Guid PlateId { get; set; }
|
||||||
|
|
||||||
//<EFBFBD>Ƿ<EFBFBD><EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD>false
|
//是否置顶,默认false
|
||||||
public bool IsTop { get; set; }
|
public bool IsTop { get; set; }
|
||||||
|
|
||||||
public DiscussPermissionTypeEnum PermissionType { get; set; }
|
public DiscussPermissionTypeEnum PermissionType { get; set; }
|
||||||
//<EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD>false
|
//是否禁止,默认false
|
||||||
public bool IsBan { get; set; }
|
public bool IsBan { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
/// 封面
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Cover { get; set; }
|
public string? Cover { get; set; }
|
||||||
|
|
||||||
//˽<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ж<EFBFBD>codeȨ<EFBFBD><EFBFBD>
|
//私有需要判断code权限
|
||||||
public string? PrivateCode { get; set; }
|
public string? PrivateCode { get; set; }
|
||||||
public DateTime CreationTime { get; set; }
|
public DateTime CreationTime { get; set; }
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
|||||||
Title = DiscussConst.Privacy;
|
Title = DiscussConst.Privacy;
|
||||||
Introduction = "";
|
Introduction = "";
|
||||||
Cover = null;
|
Cover = null;
|
||||||
//<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ
|
//被禁止
|
||||||
IsBan = true;
|
IsBan = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,14 +73,14 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.Discuss
|
|||||||
case DiscussPermissionTypeEnum.Public:
|
case DiscussPermissionTypeEnum.Public:
|
||||||
break;
|
break;
|
||||||
case DiscussPermissionTypeEnum.Oneself:
|
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)
|
if (dto.User.Id != userId)
|
||||||
{
|
{
|
||||||
dto.SetBan();
|
dto.SetBan();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DiscussPermissionTypeEnum.User:
|
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))
|
if (dto.User.Id != userId && !dto.PermissionUserIds.Contains(userId))
|
||||||
{
|
{
|
||||||
dto.SetBan();
|
dto.SetBan();
|
||||||
|
|||||||
@@ -17,9 +17,11 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
|||||||
public class BbsForumAnalyseService : ApplicationService, IApplicationService
|
public class BbsForumAnalyseService : ApplicationService, IApplicationService
|
||||||
{
|
{
|
||||||
private ForumManager _forumManager;
|
private ForumManager _forumManager;
|
||||||
public BbsForumAnalyseService(ForumManager forumManager)
|
private ISqlSugarRepository<AgreeEntity> _agreeRepository;
|
||||||
|
public BbsForumAnalyseService(ForumManager forumManager, ISqlSugarRepository<AgreeEntity> agreeRepository)
|
||||||
{
|
{
|
||||||
_forumManager = forumManager;
|
_forumManager = forumManager;
|
||||||
|
_agreeRepository = agreeRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -38,7 +40,7 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
|||||||
.Select((discuss, user, info) => new DiscussGetListOutputDto
|
.Select((discuss, user, info) => new DiscussGetListOutputDto
|
||||||
{
|
{
|
||||||
Id = discuss.Id,
|
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()
|
User = new BbsUserGetListOutputDto()
|
||||||
{
|
{
|
||||||
@@ -52,6 +54,26 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
|||||||
|
|
||||||
}, true)
|
}, true)
|
||||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount);
|
.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;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,19 +29,27 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Discuss应用服务实现,用于参数校验、领域服务业务组合、日志记录、事务处理、账户信息
|
/// Discuss应用服务实现,用于参数校验、领域服务业务组合、日志记录、事务处理、账户信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DiscussService : YiCrudAppService<DiscussAggregateRoot, DiscussGetOutputDto, DiscussGetListOutputDto, Guid, DiscussGetListInputVo, DiscussCreateInputVo, DiscussUpdateInputVo>,
|
public class DiscussService : YiCrudAppService<DiscussAggregateRoot, DiscussGetOutputDto, DiscussGetListOutputDto,
|
||||||
IDiscussService
|
Guid, DiscussGetListInputVo, DiscussCreateInputVo, DiscussUpdateInputVo>,
|
||||||
|
IDiscussService
|
||||||
{
|
{
|
||||||
private ISqlSugarRepository<DiscussTopEntity> _discussTopEntityRepository;
|
private ISqlSugarRepository<DiscussTopEntity> _discussTopRepository;
|
||||||
|
private ISqlSugarRepository<AgreeEntity> _agreeRepository;
|
||||||
private BbsUserManager _bbsUserManager;
|
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;
|
_forumManager = forumManager;
|
||||||
_plateEntityRepository = plateEntityRepository;
|
_plateEntityRepository = plateEntityRepository;
|
||||||
_localEventBus = localEventBus;
|
_localEventBus = localEventBus;
|
||||||
_discussTopEntityRepository = discussTopEntityRepository;
|
_agreeRepository = agreeRepository;
|
||||||
_bbsUserManager=bbsUserManager;
|
_discussTopRepository = discussTopRepository;
|
||||||
|
_bbsUserManager = bbsUserManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly ILocalEventBus _localEventBus;
|
private readonly ILocalEventBus _localEventBus;
|
||||||
private ForumManager _forumManager { get; set; }
|
private ForumManager _forumManager { get; set; }
|
||||||
|
|
||||||
@@ -49,8 +57,6 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
|||||||
private ISqlSugarRepository<PlateAggregateRoot> _plateEntityRepository { get; set; }
|
private ISqlSugarRepository<PlateAggregateRoot> _plateEntityRepository { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 单查
|
/// 单查
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -58,42 +64,43 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async override Task<DiscussGetOutputDto> GetAsync(Guid id)
|
public async override Task<DiscussGetOutputDto> GetAsync(Guid id)
|
||||||
{
|
{
|
||||||
|
|
||||||
//查询主题发布 浏览主题 事件,浏览数+1
|
//查询主题发布 浏览主题 事件,浏览数+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<BbsUserExtraInfoEntity>((discuss, user, info) => user.Id == info.UserId)
|
||||||
.LeftJoin<PlateAggregateRoot>((discuss, user, info, plate) => plate.Id == discuss.PlateId)
|
.LeftJoin<PlateAggregateRoot>((discuss, user, info, plate) => plate.Id == discuss.PlateId)
|
||||||
.Select((discuss, user, info, plate) => new DiscussGetOutputDto
|
.Select((discuss, user, info, plate) => new DiscussGetOutputDto
|
||||||
{
|
{
|
||||||
Id = discuss.Id,
|
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,
|
||||||
User = new BbsUserGetListOutputDto()
|
x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||||
{
|
User = new BbsUserGetListOutputDto()
|
||||||
UserName = user.UserName,
|
{
|
||||||
Nick = user.Nick,
|
UserName = user.UserName,
|
||||||
Icon = user.Icon,
|
Nick = user.Nick,
|
||||||
Id = user.Id,
|
Icon = user.Icon,
|
||||||
Level = info.Level,
|
Id = user.Id,
|
||||||
UserLimit = info.UserLimit,
|
Level = info.Level,
|
||||||
Money=info.Money,
|
UserLimit = info.UserLimit,
|
||||||
Experience=info.Experience
|
Money = info.Money,
|
||||||
},
|
Experience = info.Experience
|
||||||
Plate = new Contracts.Dtos.Plate.PlateGetOutputDto()
|
},
|
||||||
{
|
Plate = new Contracts.Dtos.Plate.PlateGetOutputDto()
|
||||||
Name = plate.Name,
|
{
|
||||||
Id = plate.Id,
|
Name = plate.Name,
|
||||||
Code = plate.Code,
|
Id = plate.Id,
|
||||||
Introduction = plate.Introduction,
|
Code = plate.Code,
|
||||||
Logo = plate.Logo
|
Introduction = plate.Introduction,
|
||||||
|
Logo = plate.Logo
|
||||||
}
|
}
|
||||||
}, true)
|
}, true)
|
||||||
.SingleAsync(discuss => discuss.Id == id);
|
.SingleAsync(discuss => discuss.Id == id);
|
||||||
|
|
||||||
if (item is not null)
|
if (item is not null)
|
||||||
{
|
{
|
||||||
await VerifyDiscussPermissionAsync(item.Id);
|
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;
|
return item;
|
||||||
@@ -105,49 +112,65 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input"></param>
|
/// <param name="input"></param>
|
||||||
/// <returns></returns>
|
/// <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;
|
RefAsync<int> total = 0;
|
||||||
var items = await _forumManager._discussRepository._DbQueryable
|
var items = await _forumManager._discussRepository._DbQueryable
|
||||||
.WhereIF(!string.IsNullOrEmpty(input.Title), x => x.Title.Contains(input.Title))
|
.WhereIF(!string.IsNullOrEmpty(input.Title), x => x.Title.Contains(input.Title))
|
||||||
.WhereIF(input.PlateId is not null, x => x.PlateId == input.PlateId)
|
.WhereIF(input.PlateId is not null, x => x.PlateId == input.PlateId)
|
||||||
.WhereIF(input.IsTop is not null, x => x.IsTop == input.IsTop)
|
.WhereIF(input.IsTop is not null, x => x.IsTop == input.IsTop)
|
||||||
.WhereIF(input.UserId is not null,x=>x.CreatorId==input.UserId)
|
.WhereIF(input.UserId is not null, x => x.CreatorId == input.UserId)
|
||||||
.LeftJoin<UserAggregateRoot>((discuss, user) => discuss.CreatorId == user.Id)
|
.LeftJoin<UserAggregateRoot>((discuss, user) => discuss.CreatorId == user.Id)
|
||||||
.WhereIF(input.UserName is not null, (discuss, user)=>user.UserName==input.UserName!)
|
.WhereIF(input.UserName is not null, (discuss, user) => user.UserName == input.UserName!)
|
||||||
|
.LeftJoin<BbsUserExtraInfoEntity>((discuss, user, info) => user.Id == info.UserId)
|
||||||
.LeftJoin<BbsUserExtraInfoEntity>((discuss, user, info) => user.Id == info.UserId)
|
.OrderByDescending(discuss => discuss.OrderNum)
|
||||||
|
.OrderByIF(input.Type == QueryDiscussTypeEnum.New, discuss => discuss.CreationTime, OrderByType.Desc)
|
||||||
.OrderByDescending(discuss => discuss.OrderNum)
|
.OrderByIF(input.Type == QueryDiscussTypeEnum.Host, discuss => discuss.SeeNum, OrderByType.Desc)
|
||||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.New, discuss => discuss.CreationTime, OrderByType.Desc)
|
.OrderByIF(input.Type == QueryDiscussTypeEnum.Suggest, discuss => discuss.AgreeNum, OrderByType.Desc)
|
||||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.Host, discuss => discuss.SeeNum, OrderByType.Desc)
|
.Select((discuss, user, info) => new DiscussGetListOutputDto
|
||||||
.OrderByIF(input.Type == QueryDiscussTypeEnum.Suggest, discuss => discuss.AgreeNum, OrderByType.Desc)
|
{
|
||||||
|
Id = discuss.Id,
|
||||||
.Select((discuss, user, info) => new DiscussGetListOutputDto
|
// 优化查询,不使用子查询
|
||||||
{
|
// IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
||||||
Id = discuss.Id,
|
User = new BbsUserGetListOutputDto()
|
||||||
IsAgree = SqlFunc.Subqueryable<AgreeEntity>().WhereIF(CurrentUser.Id != null, x => x.CreatorId == CurrentUser.Id && x.DiscussId == discuss.Id).Any(),
|
{
|
||||||
|
Id = user.Id,
|
||||||
User = new BbsUserGetListOutputDto()
|
UserName = user.UserName,
|
||||||
{
|
Nick = user.Nick,
|
||||||
Id = user.Id,
|
Icon = user.Icon,
|
||||||
UserName = user.UserName,
|
Level = info.Level,
|
||||||
Nick = user.Nick,
|
UserLimit = info.UserLimit,
|
||||||
Icon = user.Icon,
|
Money = info.Money,
|
||||||
Level = info.Level,
|
Experience = info.Experience
|
||||||
UserLimit = info.UserLimit,
|
}
|
||||||
Money = info.Money,
|
}, true)
|
||||||
Experience = info.Experience
|
|
||||||
}
|
|
||||||
|
|
||||||
}, true)
|
|
||||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
.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.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);
|
return new PagedResultDto<DiscussGetListOutputDto>(total, items);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,14 +180,16 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<List<DiscussGetListOutputDto>> GetListTopAsync()
|
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<UserAggregateRoot>((top, discuss, user) => discuss.CreatorId == user.Id)
|
||||||
.LeftJoin<BbsUserExtraInfoEntity>((top, discuss, user, info) => user.Id == info.UserId)
|
.LeftJoin<BbsUserExtraInfoEntity>((top, discuss, user, info) => user.Id == info.UserId)
|
||||||
.OrderByDescending(top => top.OrderNum)
|
.OrderByDescending(top => top.OrderNum)
|
||||||
.Select((top, discuss, user, info) => new DiscussGetListOutputDto
|
.Select((top, discuss, user, info) => new DiscussGetListOutputDto
|
||||||
{
|
{
|
||||||
Id = discuss.Id,
|
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
|
User = new BbsUserGetListOutputDto
|
||||||
{
|
{
|
||||||
Id = user.Id,
|
Id = user.Id,
|
||||||
@@ -206,6 +231,11 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
|||||||
throw new UserFriendlyException(PlateConst.No_Exist);
|
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)
|
if (plate.IsDisableCreateDiscuss == true)
|
||||||
{
|
{
|
||||||
@@ -233,6 +263,7 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
|||||||
{
|
{
|
||||||
throw new UserFriendlyException(DiscussConst.No_Exist);
|
throw new UserFriendlyException(DiscussConst.No_Exist);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (discuss.PermissionType == DiscussPermissionTypeEnum.Oneself)
|
if (discuss.PermissionType == DiscussPermissionTypeEnum.Oneself)
|
||||||
{
|
{
|
||||||
if (discuss.CreatorId != CurrentUser.Id)
|
if (discuss.CreatorId != CurrentUser.Id)
|
||||||
@@ -240,13 +271,15 @@ namespace Yi.Framework.Bbs.Application.Services.Forum
|
|||||||
throw new UserFriendlyException(DiscussConst.Privacy);
|
throw new UserFriendlyException(DiscussConst.Privacy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (discuss.PermissionType == DiscussPermissionTypeEnum.User)
|
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);
|
throw new UserFriendlyException(DiscussConst.Privacy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,7 @@ namespace Yi.Framework.Bbs.Domain.Shared.Consts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DiscussConst
|
public class DiscussConst
|
||||||
{
|
{
|
||||||
|
public const string Repeat = "创建主题重复";
|
||||||
public const string No_Exist = "传入的主题id不存在";
|
public const string No_Exist = "传入的主题id不存在";
|
||||||
|
|
||||||
public const string Privacy = "【私密】您无该主题权限,可联系作者申请开放";
|
public const string Privacy = "【私密】您无该主题权限,可联系作者申请开放";
|
||||||
|
|||||||
@@ -184,22 +184,24 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input"></param>
|
/// <param name="input"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost("captcha-phone")]
|
[HttpPost("account/captcha-phone")]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public async Task<object> PostCaptchaPhoneForRegisterAsync(PhoneCaptchaImageDto input)
|
public async Task<object> PostCaptchaPhoneForRegisterAsync(PhoneCaptchaImageDto input)
|
||||||
{
|
{
|
||||||
return await PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.Register, input);
|
return await PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.Register, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 手机验证码-找回密码
|
/// 手机验证码-找回密码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input"></param>
|
/// <param name="input"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost("captcha-phone/repassword")]
|
[HttpPost("account/captcha-phone/repassword")]
|
||||||
public async Task<object> PostCaptchaPhoneForRetrievePasswordAsync(PhoneCaptchaImageDto input)
|
public async Task<object> PostCaptchaPhoneForRetrievePasswordAsync(PhoneCaptchaImageDto input)
|
||||||
{
|
{
|
||||||
return await PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.RetrievePassword, input);
|
return await PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.RetrievePassword, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 手机验证码
|
/// 手机验证码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -223,7 +225,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
var uuid = Guid.NewGuid();
|
var uuid = Guid.NewGuid();
|
||||||
await _aliyunManger.SendSmsAsync(input.Phone, code);
|
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 CaptchaPhoneCacheItem(code),
|
||||||
new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(10) });
|
new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(10) });
|
||||||
return new
|
return new
|
||||||
@@ -255,14 +257,11 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
/// <param name="input"></param>
|
/// <param name="input"></param>
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[UnitOfWork]
|
[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);
|
var entity = await _userRepository.GetFirstAsync(x => x.Phone == input.Phone);
|
||||||
if (entity is null)
|
if (entity is null)
|
||||||
{
|
{
|
||||||
@@ -270,6 +269,8 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
await _accountManager.RestPasswordAsync(entity.Id, input.Password);
|
await _accountManager.RestPasswordAsync(entity.Id, input.Password);
|
||||||
|
|
||||||
|
return entity.UserName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
|
|
||||||
if (!File.Exists(path))
|
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)}";
|
// path = $"wwwroot/{FileTypeEnum.Thumbnail}/{file.Id}{Path.GetExtension(file.FileName)}";
|
||||||
//}
|
//}
|
||||||
//路径为: 文件路径/文件id+文件扩展名
|
//路径为: 文件路径/文件id+文件扩展名
|
||||||
|
|
||||||
if (!File.Exists(path))
|
|
||||||
{
|
|
||||||
throw new UserFriendlyException("本地文件不存在", "404");
|
|
||||||
}
|
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,4 +7,7 @@ VITE_APP_URL="http://localhost:19001/api/app"
|
|||||||
|
|
||||||
# ws/开发环境
|
# ws/开发环境
|
||||||
VITE_APP_BASE_WS = '/dev-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
|
# ws
|
||||||
VITE_APP_BASE_WS = '/prod-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" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<title>.Net意社区</title>
|
<!--<title>.Net意社区</title>-->
|
||||||
<link rel="stylesheet" href="/src/assets/loading.css" />
|
<!-- 为了,icp备案-->
|
||||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5453339688995325"
|
<title>个人成果展示</title>
|
||||||
crossorigin="anonymous"></script>
|
<link rel="stylesheet" href="/src/assets/loading.css" />
|
||||||
</head>
|
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5453339688995325"
|
||||||
<body>
|
crossorigin="anonymous"></script>
|
||||||
<div id="Loading">
|
</head>
|
||||||
<div class="loader JS_on">
|
<body>
|
||||||
<span class="binary"></span>
|
<div id="Loading">
|
||||||
<span class="binary"></span>
|
<div class="loader JS_on">
|
||||||
<span class="getting-there">意社区很大,你要等一下...</span>
|
<span class="binary"></span>
|
||||||
</div>
|
<span class="binary"></span>
|
||||||
</div>
|
<span class="getting-there">意社区很大,你要等一下...</span>
|
||||||
<div id="app"></div>
|
</div>
|
||||||
<script type="module" src="/src/main.js"></script>
|
</div>
|
||||||
</body>
|
<div id="app"></div>
|
||||||
</html>
|
<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) {
|
export function register(userName, password, phone, code, uuid) {
|
||||||
const data = {
|
const data = {
|
||||||
@@ -76,3 +94,15 @@ export function getCodePhone(phone) {
|
|||||||
data: { 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";
|
import request from "@/config/axios/service";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户登录
|
* 用户登录
|
||||||
* @param {*} data 账号密码
|
* @param {*} data 账号密码
|
||||||
@@ -23,6 +22,17 @@ export function userRegister(data) {
|
|||||||
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
|
.left-lable
|
||||||
{
|
{
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
justify-content: space-between;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
.left-lable label{
|
.left-lable label{
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
.right-forgot{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.right-forgot:hover{
|
||||||
|
color: #7f438c;
|
||||||
|
}
|
||||||
.bottom-div
|
.bottom-div
|
||||||
{
|
{
|
||||||
font-size: 12px;
|
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,
|
userLogin,
|
||||||
getUserDetailInfo,
|
getUserDetailInfo,
|
||||||
userLogout,
|
userLogout,
|
||||||
userRegister,
|
userRegister, userRetrievePassword,
|
||||||
} from "@/apis/auth";
|
} from "@/apis/auth";
|
||||||
const TokenKey = "AccessToken";
|
const TokenKey = "AccessToken";
|
||||||
export const AUTH_MENUS = "AUTH_MENUS";
|
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 {
|
return {
|
||||||
getToken,
|
getToken,
|
||||||
setToken,
|
setToken,
|
||||||
@@ -189,6 +203,7 @@ const currentUserInfo=computed(()=>{
|
|||||||
loginFun,
|
loginFun,
|
||||||
getUserInfo,
|
getUserInfo,
|
||||||
logoutFun,
|
logoutFun,
|
||||||
|
retrievePasswordFun,
|
||||||
clearStorage,
|
clearStorage,
|
||||||
registerFun,
|
registerFun,
|
||||||
loginSuccess,
|
loginSuccess,
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
<div class="image">
|
<div class="image">
|
||||||
<img class="img-icon" src="@/assets/common/icons/logo.ico" />
|
<img class="img-icon" src="@/assets/common/icons/logo.ico" />
|
||||||
</div>
|
</div>
|
||||||
<div class="text">{{ configStore.name }}</div>
|
|
||||||
|
<div class="text">{{ isIcp===true?"个人成果展示":configStore.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab">
|
<div class="tab">
|
||||||
<el-menu :default-active="activeIndex" mode="horizontal" :ellipsis="false" @select="handleSelect">
|
<el-menu :default-active="activeIndex" mode="horizontal" :ellipsis="false" @select="handleSelect">
|
||||||
@@ -152,6 +153,8 @@ const searchText = ref("");
|
|||||||
const noticeForNoReadCount = computed(() => {
|
const noticeForNoReadCount = computed(() => {
|
||||||
return noticeList.value.filter(x => x.isRead == false).length;
|
return noticeList.value.filter(x => x.isRead == false).length;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const isIcp=import.meta.env.VITE_APP_ICP==="true";
|
||||||
//加载初始化离线消息
|
//加载初始化离线消息
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
//登录了才去判断消息通知
|
//登录了才去判断消息通知
|
||||||
|
|||||||
@@ -26,13 +26,18 @@ const router = createRouter({
|
|||||||
name: "login",
|
name: "login",
|
||||||
path: "/login",
|
path: "/login",
|
||||||
// component: () => import("../views/Login.vue"),
|
// component: () => import("../views/Login.vue"),
|
||||||
component: () => import("../views/login/index.vue"),
|
component: () => import("../views/login/login.vue"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "register",
|
name: "register",
|
||||||
path: "/register",
|
path: "/register",
|
||||||
component: () => import("../views/login/register.vue"),
|
component: () => import("../views/login/register.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "forgotPassword",
|
||||||
|
path: "/forgotPassword",
|
||||||
|
component: () => import("../views/login/forgotPassword.vue"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "auth",
|
name: "auth",
|
||||||
path: "/auth/:type",
|
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 { getUserDetailInfo, getLoginCode } from "@/apis/auth";
|
||||||
import useAuths from "@/hooks/useAuths";
|
import useAuths from "@/hooks/useAuths";
|
||||||
import { defineStore } from "pinia";
|
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() {
|
resetInfo() {
|
||||||
this.roles = [];
|
this.roles = [];
|
||||||
|
|||||||
@@ -4,7 +4,26 @@
|
|||||||
<el-col :span="17">
|
<el-col :span="17">
|
||||||
<div class="chat-hub">
|
<div class="chat-hub">
|
||||||
<!-- <p @click="onClickToChatHub">点击前往-最新上线<span>《聊天室》 </span>,现已支持<span>Ai助手</span>,希望能帮助大家</p>-->
|
<!-- <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>
|
||||||
<div class="scrollbar">
|
<div class="scrollbar">
|
||||||
<ScrollbarInfo/>
|
<ScrollbarInfo/>
|
||||||
@@ -272,7 +291,7 @@ const activeList = [
|
|||||||
{name: "开始", path: "/start", icon: "Position"},
|
{name: "开始", path: "/start", icon: "Position"},
|
||||||
{name: "聊天室", path: "/chat", icon: "ChatRound"},
|
{name: "聊天室", path: "/chat", icon: "ChatRound"},
|
||||||
];
|
];
|
||||||
|
const isIcp=import.meta.env.VITE_APP_ICP==="true";
|
||||||
//主题查询参数
|
//主题查询参数
|
||||||
const query = reactive({
|
const query = reactive({
|
||||||
skipCount: 1,
|
skipCount: 1,
|
||||||
@@ -622,7 +641,7 @@ const onClickToWeChat=()=>{
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
height: 30px;
|
min-height: 30px;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0 auto;
|
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>
|
<template>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<!-- 登录 -->
|
<!-- 登录 -->
|
||||||
<div class="div-content">
|
<div class="div-content">
|
||||||
<div class="div-left">
|
<div class="div-left">
|
||||||
<div class="left-container">
|
<div class="left-container">
|
||||||
<p class="title title-1">Hello,<span @click="guestlogin">you can go to homepage >></span></p>
|
<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>
|
<p class="title title-2">Welcome to Yi!</p>
|
||||||
<el-form
|
<el-form
|
||||||
ref="loginFormRef"
|
ref="loginFormRef"
|
||||||
:model="loginForm"
|
:model="loginForm"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
>
|
>
|
||||||
|
|
||||||
<div class="input-content">
|
<div class="input-content">
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<p>用户名</p>
|
<p>用户名</p>
|
||||||
<el-form-item prop="userName">
|
<el-form-item prop="userName">
|
||||||
<input type="text" v-model="loginForm.userName">
|
<input type="text" v-model="loginForm.userName">
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<p>密码</p>
|
<p>密码</p>
|
||||||
<el-form-item prop="password">
|
<el-form-item prop="password">
|
||||||
<input type="password" v-model="loginForm.password">
|
<input type="password" v-model="loginForm.password">
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<p>验证码</p>
|
<p>验证码</p>
|
||||||
<el-form-item prop="code">
|
<el-form-item prop="code">
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<input class="code-input" type="text" v-model.trim="loginForm.code">
|
<input class="code-input" type="text" v-model.trim="loginForm.code">
|
||||||
<img class="code-img" alt="加载中" @click="handleGetCodeImage" :src="codeImageURL">
|
<img class="code-img" alt="加载中" @click="handleGetCodeImage" :src="codeImageURL">
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div class="left-lable">
|
<div class="left-lable">
|
||||||
<input type="checkbox">
|
<div>
|
||||||
<label>记住我</label>
|
<input type="checkbox">
|
||||||
</div>
|
<label>记住我</label>
|
||||||
|
</div>
|
||||||
<div class="left-btn">
|
|
||||||
<button type="button" class="btn-login" @click="login(loginFormRef)">登录</button>
|
<span class="right-forgot" @click="handleForgotPassword">忘记密码?点击找回</span>
|
||||||
<button type="button" class="btn-reg" @click="handleRegister">前往注册</button>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="bottom-div">
|
<div class="left-btn">
|
||||||
<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>
|
<button type="button" class="btn-login" @click="login(loginFormRef)">登录</button>
|
||||||
</div>
|
<button type="button" class="btn-reg" @click="handleRegister">前往注册</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="bottom-div">
|
||||||
<div class="div-right">
|
<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>
|
||||||
<img class="div-img" src="@/assets/login.png" alt=""/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="div-right">
|
||||||
</div>
|
<img class="div-img" src="@/assets/login.png" alt=""/>
|
||||||
</template>
|
</div>
|
||||||
<script setup>
|
</div>
|
||||||
import { ref, reactive, onMounted, computed } from "vue";
|
|
||||||
import { useRouter, useRoute } from "vue-router";
|
</div>
|
||||||
import useAuths from "@/hooks/useAuths";
|
</template>
|
||||||
import useUserStore from "@/stores/user";
|
<script setup>
|
||||||
const { loginFun, loginSuccess } = useAuths();
|
import { ref, reactive, onMounted, computed } from "vue";
|
||||||
const router = useRouter();
|
import { useRouter, useRoute } from "vue-router";
|
||||||
const route = useRoute();
|
import useAuths from "@/hooks/useAuths";
|
||||||
const loginFormRef = ref();
|
import useUserStore from "@/stores/user";
|
||||||
const rules = reactive({
|
const { loginFun, loginSuccess } = useAuths();
|
||||||
userName: [{ required: true, message: "请输入用户名", trigger: "blur" }],
|
const router = useRouter();
|
||||||
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
|
const route = useRoute();
|
||||||
});
|
const loginFormRef = ref();
|
||||||
const loginForm = reactive({
|
const rules = reactive({
|
||||||
userName: "",
|
userName: [{ required: true, message: "请输入用户名", trigger: "blur" }],
|
||||||
password: "",
|
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
|
||||||
uuid: "",
|
});
|
||||||
code: "",
|
const loginForm = reactive({
|
||||||
});
|
userName: "",
|
||||||
//前往注册
|
password: "",
|
||||||
const handleRegister=()=>{
|
uuid: "",
|
||||||
router.push("/register");
|
code: "",
|
||||||
}
|
});
|
||||||
//直接进入首页
|
//前往注册
|
||||||
const guestlogin = () => {
|
const handleRegister=()=>{
|
||||||
const redirect = route.query?.redirect ?? "/index";
|
router.push("/register");
|
||||||
router.push(redirect);
|
}
|
||||||
};
|
//前往忘记密码
|
||||||
const codeUUid = computed(() => useUserStore().codeUUid);
|
const handleForgotPassword = () => {
|
||||||
const login = async (formEl) => {
|
router.push("/forgotPassword");
|
||||||
if (!formEl) return;
|
}
|
||||||
await formEl.validate((valid) => {
|
//直接进入首页
|
||||||
if (valid) {
|
const guestlogin = () => {
|
||||||
try {
|
const redirect = route.query?.redirect ?? "/index";
|
||||||
loginForm.uuid = codeUUid.value;
|
router.push(redirect);
|
||||||
loginFun(loginForm);
|
};
|
||||||
} catch (error) {
|
const codeUUid = computed(() => useUserStore().codeUUid);
|
||||||
console.log(error.message, "error.message");
|
const login = async (formEl) => {
|
||||||
ElMessage({
|
if (!formEl) return;
|
||||||
message: error.message,
|
await formEl.validate((valid) => {
|
||||||
type: "error",
|
if (valid) {
|
||||||
duration: 2000,
|
try {
|
||||||
});
|
loginForm.uuid = codeUUid.value;
|
||||||
}
|
loginFun(loginForm);
|
||||||
}
|
} catch (error) {
|
||||||
});
|
console.log(error.message, "error.message");
|
||||||
};
|
ElMessage({
|
||||||
|
message: error.message,
|
||||||
// 获取图片验证码
|
type: "error",
|
||||||
const codeImageURL = computed(() => useUserStore().codeImageURL);
|
duration: 2000,
|
||||||
const handleGetCodeImage = () => {
|
});
|
||||||
useUserStore().updateCodeImage();
|
}
|
||||||
};
|
}
|
||||||
onMounted(async () => {
|
});
|
||||||
await useUserStore().updateCodeImage();
|
};
|
||||||
});
|
|
||||||
|
// 获取图片验证码
|
||||||
|
const codeImageURL = computed(() => useUserStore().codeImageURL);
|
||||||
const handleQQLogin = () => {
|
const handleGetCodeImage = () => {
|
||||||
window.open(
|
useUserStore().updateCodeImage();
|
||||||
"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,
|
onMounted(async () => {
|
||||||
"width=500,height=500,left=50,top=50"
|
await useUserStore().updateCodeImage();
|
||||||
);
|
});
|
||||||
};
|
|
||||||
|
|
||||||
const handleGiteeLogin = () => {
|
const handleQQLogin = () => {
|
||||||
window.open(
|
window.open(
|
||||||
"https://gitee.com/oauth/authorize?client_id=949f3519969adc5cfe82c209b71300e8e0868e8536f3d7f59195c8f1e5b72502&redirect_uri=https%3A%2F%2Fccnetcore.com%2Fauth%2Fgitee&state=0&response_type=code",
|
"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,
|
undefined,
|
||||||
"width=500,height=500,left=50,top=50"
|
"width=500,height=500,left=50,top=50"
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener("message", async (e) => {
|
const handleGiteeLogin = () => {
|
||||||
const { authData, type } = e.data;
|
window.open(
|
||||||
console.log(authData, "传到登录页的值");
|
"https://gitee.com/oauth/authorize?client_id=949f3519969adc5cfe82c209b71300e8e0868e8536f3d7f59195c8f1e5b72502&redirect_uri=https%3A%2F%2Fccnetcore.com%2Fauth%2Fgitee&state=0&response_type=code",
|
||||||
if (authData) {
|
undefined,
|
||||||
await loginSuccess({ data: JSON.parse(authData) });
|
"width=500,height=500,left=50,top=50"
|
||||||
}
|
);
|
||||||
});
|
};
|
||||||
</script>
|
|
||||||
<style src="@/assets/styles/login.css" scoped>
|
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>
|
</style>
|
||||||
Reference in New Issue
Block a user