diff --git a/Yi.Framework.Net6/Yi.Framework.ApiMicroservice/Config/SwaggerDoc.xml b/Yi.Framework.Net6/Yi.Framework.ApiMicroservice/Config/SwaggerDoc.xml index 822a145c..614f74b5 100644 --- a/Yi.Framework.Net6/Yi.Framework.ApiMicroservice/Config/SwaggerDoc.xml +++ b/Yi.Framework.Net6/Yi.Framework.ApiMicroservice/Config/SwaggerDoc.xml @@ -162,6 +162,25 @@ + + + 获取文章的全部一级评论 + + + + + + 获取一级评论详情 + + + + + + + 回复文章或回复评论 + + + 动态条件分页查询 diff --git a/Yi.Framework.Net6/Yi.Framework.ApiMicroservice/Controllers/Community/CommentController.cs b/Yi.Framework.Net6/Yi.Framework.ApiMicroservice/Controllers/Community/CommentController.cs index 872c6c74..5a4e76de 100644 --- a/Yi.Framework.Net6/Yi.Framework.ApiMicroservice/Controllers/Community/CommentController.cs +++ b/Yi.Framework.Net6/Yi.Framework.ApiMicroservice/Controllers/Community/CommentController.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Authorization; +using AutoMapper; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; @@ -6,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Yi.Framework.Common.Models; +using Yi.Framework.DTOModel.Vo; using Yi.Framework.Interface; using Yi.Framework.Model.Models; using Yi.Framework.Repository; @@ -20,19 +22,24 @@ namespace Yi.Framework.ApiMicroservice.Controllers public class CommentController : BaseSimpleCrudController { private ICommentService _iCommentService; - public CommentController(ILogger logger, ICommentService iCommentService) : base(logger, iCommentService) + private IMapper _mapper; + public CommentController(ILogger logger, ICommentService iCommentService, IMapper mapper) : base(logger, iCommentService) { _iCommentService = iCommentService; + _mapper = mapper; } /// - /// 获取全部一级评论 + /// 获取文章的全部一级评论 /// /// - public override async Task GetList() + [HttpGet] + [Route("{articleId}")] + public async Task GetListByArticleId(long articleId) { - var data = await _repository.GetListAsync(u=>u.UserId==null); - return Result.Success().SetData(data); + //一级评论被回复的用户id为空 + var data = await _repository._DbQueryable.Where(u => u.ParentId == 0 && u.ArticleId == articleId).Includes(u => u.CreateUserInfo).OrderByDescending(u=>u.CreateTime).ToListAsync(); + return Result.Success().SetData(_mapper.Map>(data)); } /// @@ -40,9 +47,10 @@ namespace Yi.Framework.ApiMicroservice.Controllers /// /// /// - public override Task GetById([FromRoute] long id) + public override async Task GetById([FromRoute] long id) { - return base.GetById(id); + var data = await _repository._DbQueryable.Includes(u => u.CreateUserInfo).Includes(u => u.UserInfo).FirstAsync(u => u.Id == id); + return Result.Success().SetData(_mapper.Map(data)); } /// @@ -50,9 +58,9 @@ namespace Yi.Framework.ApiMicroservice.Controllers /// /// [HttpPost] - public async Task Comment() - { - + public override async Task Add(CommentEntity comment) + { + return Result.Success().SetStatus(await _iCommentService.AddAsync(comment)); } } } diff --git a/Yi.Framework.Net6/Yi.Framework.ApiMicroservice/yi-sqlsugar-dev.db b/Yi.Framework.Net6/Yi.Framework.ApiMicroservice/yi-sqlsugar-dev.db index 158e772c..92ccd29f 100644 Binary files a/Yi.Framework.Net6/Yi.Framework.ApiMicroservice/yi-sqlsugar-dev.db and b/Yi.Framework.Net6/Yi.Framework.ApiMicroservice/yi-sqlsugar-dev.db differ diff --git a/Yi.Framework.Net6/Yi.Framework.Core/Yi.Framework.Core.csproj b/Yi.Framework.Net6/Yi.Framework.Core/Yi.Framework.Core.csproj index 52c81d84..a28444ff 100644 --- a/Yi.Framework.Net6/Yi.Framework.Core/Yi.Framework.Core.csproj +++ b/Yi.Framework.Net6/Yi.Framework.Core/Yi.Framework.Core.csproj @@ -4,6 +4,12 @@ net6.0 + + + + + + @@ -22,8 +28,4 @@ - - - - diff --git a/Yi.Framework.Net6/Yi.Framework.DTOModel/Vo/CommentVo.cs b/Yi.Framework.Net6/Yi.Framework.DTOModel/Vo/CommentVo.cs new file mode 100644 index 00000000..598e438a --- /dev/null +++ b/Yi.Framework.Net6/Yi.Framework.DTOModel/Vo/CommentVo.cs @@ -0,0 +1,61 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.DTOModel.Vo +{ + public class CommentVo + { + public long Id { get; set; } + + /// + /// 评论内容 + /// + public string Content { get; set; } + /// + /// 点赞数 + /// + public int? AgreeNum { get; set; } + + /// + /// 创建时间 + /// + public DateTime? CreateTime { get; set; } + /// + /// 是否删除 + /// + public bool? IsDeleted { get; set; } + /// + /// 租户Id + /// + public long? TenantId { get; set; } + /// + /// 排序字段 + /// + + public int? OrderNum { get; set; } + /// + /// 描述 + /// + + public string Remark { get; set; } + /// + /// 子评论数 + /// + + public int? CommentNum { get; set; } + + /// + /// 被回复的用户信息 + /// + public UserVo? UserInfo { get; set; } + + /// + /// 创建评论的用户信息 + /// + public UserVo? CreateUserInfo { get; set; } + } +} diff --git a/Yi.Framework.Net6/Yi.Framework.Interface/ICommentService.cs b/Yi.Framework.Net6/Yi.Framework.Interface/ICommentService.cs new file mode 100644 index 00000000..a2743b97 --- /dev/null +++ b/Yi.Framework.Net6/Yi.Framework.Interface/ICommentService.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using Yi.Framework.Model.Models; +using Yi.Framework.Repository; + +namespace Yi.Framework.Interface +{ + public partial interface ICommentService + { + Task AddAsync(CommentEntity comment); + } +} diff --git a/Yi.Framework.Net6/Yi.Framework.Model/CommentEntity.cs b/Yi.Framework.Net6/Yi.Framework.Model/CommentEntity.cs new file mode 100644 index 00000000..5438c636 --- /dev/null +++ b/Yi.Framework.Net6/Yi.Framework.Model/CommentEntity.cs @@ -0,0 +1,24 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.Model.Models +{ + public partial class CommentEntity + { + /// + /// 被回复的用户信息 + /// + [Navigate(NavigateType.OneToOne,nameof(UserId),nameof(UserEntity.Id))] + public UserEntity? UserInfo { get; set; } + + /// + /// 创建评论的用户信息 + /// + [Navigate(NavigateType.OneToOne, nameof(CreateUser), nameof(UserEntity.Id))] + public UserEntity? CreateUserInfo { get; set; } + } +} diff --git a/Yi.Framework.Net6/Yi.Framework.Model/ModelsTemplate/CommentEntity.cs b/Yi.Framework.Net6/Yi.Framework.Model/ModelsTemplate/CommentEntity.cs index bcd20404..4b5c4a2b 100644 --- a/Yi.Framework.Net6/Yi.Framework.Model/ModelsTemplate/CommentEntity.cs +++ b/Yi.Framework.Net6/Yi.Framework.Model/ModelsTemplate/CommentEntity.cs @@ -14,6 +14,9 @@ namespace Yi.Framework.Model.Models public CommentEntity() { this.CreateTime = DateTime.Now; + this.AgreeNum= 0; + this.CommentNum = 0; + this.ParentId= 0; } [JsonConverter(typeof(ValueToStringConverter))] [SugarColumn(ColumnName="Id" ,IsPrimaryKey = true )] @@ -32,7 +35,7 @@ namespace Yi.Framework.Model.Models /// 评论内容 /// [SugarColumn(ColumnName="Content" )] - public string Content { get; set; } + public string? Content { get; set; } /// /// 点赞数 /// @@ -77,7 +80,7 @@ namespace Yi.Framework.Model.Models /// 描述 /// [SugarColumn(ColumnName="Remark" )] - public string Remark { get; set; } + public string? Remark { get; set; } /// /// 子评论数 /// diff --git a/Yi.Framework.Net6/Yi.Framework.Service/CommentService.cs b/Yi.Framework.Net6/Yi.Framework.Service/CommentService.cs new file mode 100644 index 00000000..5df77ca3 --- /dev/null +++ b/Yi.Framework.Net6/Yi.Framework.Service/CommentService.cs @@ -0,0 +1,30 @@ +using SqlSugar; +using System.Threading.Tasks; +using Yi.Framework.Interface; +using Yi.Framework.Model.Models; +using Yi.Framework.Repository; + +namespace Yi.Framework.Service +{ + public partial class CommentService : BaseService, ICommentService + { + //添加一个评论 + public async Task AddAsync(CommentEntity comment) + { + //如果是一级评论:不用处理 + + //如果是二级评论:ParentId父节点评论数+1 + return await _repository.UseTranAsync(async () => + { + if (comment.ParentId != 0) + { + var parentData = await _repository.GetByIdAsync(comment.ParentId); + parentData.CommentNum += 1; + await _repository.AsUpdateable(parentData).UpdateColumns(u => new { u.CommentNum }).ExecuteCommandAsync(); + } + await _repository.InsertReturnSnowflakeIdAsync(comment); + }); + + } + } +} diff --git a/Yi.Framework.Net6/Yi.Framework.WebCore/Mapper/Profile/AutoMapperProfile.cs b/Yi.Framework.Net6/Yi.Framework.WebCore/Mapper/Profile/AutoMapperProfile.cs index 0f1929e4..2b34431a 100644 --- a/Yi.Framework.Net6/Yi.Framework.WebCore/Mapper/Profile/AutoMapperProfile.cs +++ b/Yi.Framework.Net6/Yi.Framework.WebCore/Mapper/Profile/AutoMapperProfile.cs @@ -16,6 +16,7 @@ namespace Yi.Framework.WebCore.Mapper { CreateMap (); CreateMap(); + CreateMap(); } } diff --git a/Yi.Vue3.x.Vant/components.d.ts b/Yi.Vue3.x.Vant/components.d.ts index 72a77002..06b17dbb 100644 --- a/Yi.Vue3.x.Vant/components.d.ts +++ b/Yi.Vue3.x.Vant/components.d.ts @@ -18,7 +18,6 @@ declare module '@vue/runtime-core' { VanButton: typeof import('vant/es')['Button'] VanCellGroup: typeof import('vant/es')['CellGroup'] VanCol: typeof import('vant/es')['Col'] - VanDivider: typeof import('vant/es')['Divider'] VanField: typeof import('vant/es')['Field'] VanGrid: typeof import('vant/es')['Grid'] VanGridItem: typeof import('vant/es')['GridItem'] @@ -34,6 +33,5 @@ declare module '@vue/runtime-core' { VanTabbar: typeof import('vant/es')['Tabbar'] VanTabbarItem: typeof import('vant/es')['TabbarItem'] VanTabs: typeof import('vant/es')['Tabs'] - VanUploader: typeof import('vant/es')['Uploader'] } } diff --git a/Yi.Vue3.x.Vant/src/api/commentApi.ts b/Yi.Vue3.x.Vant/src/api/commentApi.ts new file mode 100644 index 00000000..edcf0079 --- /dev/null +++ b/Yi.Vue3.x.Vant/src/api/commentApi.ts @@ -0,0 +1,17 @@ +import myaxios from '@/utils/myaxios' + +export default { + add(data:any) { + return myaxios({ + url: `/comment/add`, + method: 'post', + data: data + }) + }, + getListByArticleId(articleId:any) { + return myaxios({ + url: `/comment/GetListByArticleId/${articleId}`, + method: 'get', + }) + } +} \ No newline at end of file diff --git a/Yi.Vue3.x.Vant/src/view/main/recommend.vue b/Yi.Vue3.x.Vant/src/view/main/recommend.vue index 7ebe74d0..cdf9e384 100644 --- a/Yi.Vue3.x.Vant/src/view/main/recommend.vue +++ b/Yi.Vue3.x.Vant/src/view/main/recommend.vue @@ -1,14 +1,24 @@ @@ -65,6 +112,7 @@ import AppCreateTime from "@/components/AppCreateTime.vue"; import AppUserIcon from "@/components/AppUserIcon.vue"; import articleApi from "@/api/articleApi"; import agreeApi from "@/api/agreeApi"; +import commentApi from "@/api/commentApi"; import { ArticleEntity } from "@/type/interface/ArticleEntity"; const VanImagePreview = ImagePreview.Component; const url = `${import.meta.env.VITE_APP_BASE_API}/file/`; @@ -77,14 +125,34 @@ const data = reactive({ isDeleted: false, }, }); -const { queryParams } = toRefs(data); +const commentData = reactive({ + content: "", + articleId:0 +}); +const sendComment=()=>{ + commentData.articleId=openCommentId.value; + commentApi.add(commentData).then(()=>{ + getCommentList(openCommentId.value); + commentData.content=""; + }) +} + +const { queryParams } = toRefs(data); +const {content}=toRefs(commentData); const articleList = ref([]); +const commentList = ref([]); const totol = ref(0); const imageShow = ref(false); -const commentShow = ref(false) +const commentShow = ref(false); const index = ref(0); let imagesPreview = ref([]); +const openCommentId=ref(0); +const openComment = (id: any) => { + commentShow.value = true; + openCommentId.value=id; + getCommentList(id); +}; const onChange = (newIndex: any) => { index.value = newIndex; @@ -140,6 +208,12 @@ onMounted(() => { // getList(); }); +const getCommentList = (id: any) => { + commentApi.getListByArticleId(id).then((response: any) => { + commentList.value = response.data; + }); +}; + const getList = () => { articleApi.pageList(queryParams.value).then((response: any) => { articleList.value.push(...response.data.data); @@ -150,16 +224,16 @@ const aggreeHand = (articleId: any) => { agreeApi.operate(articleId).then((response: any) => { //更改显示的值 if (response.status) { - articleList.value.filter(p => p.id == articleId)[0].agreeNum += 1 + articleList.value.filter((p) => p.id == articleId)[0].agreeNum += 1; } else { - articleList.value.filter(p => p.id == articleId)[0].agreeNum -= 1 + articleList.value.filter((p) => p.id == articleId)[0].agreeNum -= 1; } Toast({ message: response.message, - position: 'bottom', - }) - }) -} + position: "bottom", + }); + }); +};