From 0211caf572e0f7aea42f66721bb91cbd26e4462a Mon Sep 17 00:00:00 2001 From: zpc Date: Sun, 16 Nov 2025 20:05:18 +0800 Subject: [PATCH] 0.0.1 --- .../Liveforum/Dto/T_PostsDto.cs | 26 ++ ZR.Service/Liveforum/T_PostsService.cs | 27 ++ ZR.Vue/src/views/liveforum/tcomments.vue | 32 +- ZR.Vue/src/views/liveforum/tposts.vue | 366 ++++++++++++++++-- 4 files changed, 406 insertions(+), 45 deletions(-) diff --git a/ZR.LiveForum.Model/Liveforum/Dto/T_PostsDto.cs b/ZR.LiveForum.Model/Liveforum/Dto/T_PostsDto.cs index aab9d36..d1662d6 100644 --- a/ZR.LiveForum.Model/Liveforum/Dto/T_PostsDto.cs +++ b/ZR.LiveForum.Model/Liveforum/Dto/T_PostsDto.cs @@ -111,5 +111,31 @@ namespace ZR.LiveForum.Model.Liveforum.Dto public string? IsTopLabel { get; set; } [ExcelColumn(Name = "帖子状态")] public string? StatusLabel { get; set; } + + /// + /// 帖子图片列表 + /// + public List Images { get; set; } = new List(); + } + + /// + /// 帖子图片简单DTO + /// + public class PostImageDto + { + /// + /// 图片ID + /// + public long Id { get; set; } + + /// + /// 图片URL + /// + public string ImageUrl { get; set; } + + /// + /// 排序顺序 + /// + public int SortOrder { get; set; } } } \ No newline at end of file diff --git a/ZR.Service/Liveforum/T_PostsService.cs b/ZR.Service/Liveforum/T_PostsService.cs index 493a9c9..fc31b99 100644 --- a/ZR.Service/Liveforum/T_PostsService.cs +++ b/ZR.Service/Liveforum/T_PostsService.cs @@ -64,6 +64,33 @@ namespace ZR.Service.Liveforum var resp = ToPage(response, parm); + // 批量查询并填充图片列表 + if (resp.Result != null && resp.Result.Any()) + { + var postIds = resp.Result.Select(x => x.Id).ToList(); + var images = Context.Queryable() + .Where(x => postIds.Contains(x.PostId)) + .OrderBy(x => x.SortOrder) + .ToList(); + + var imagesDict = images + .GroupBy(x => x.PostId) + .ToDictionary( + g => g.Key, + g => g.Select(x => new PostImageDto + { + Id = x.Id, + ImageUrl = x.ImageUrl, + SortOrder = x.SortOrder + }).ToList() + ); + + Context.ThenMapper(resp.Result, item => + { + item.Images = imagesDict.GetValueOrDefault(item.Id, new List()); + }); + } + return resp; } diff --git a/ZR.Vue/src/views/liveforum/tcomments.vue b/ZR.Vue/src/views/liveforum/tcomments.vue index 700e8e7..1427ef2 100644 --- a/ZR.Vue/src/views/liveforum/tcomments.vue +++ b/ZR.Vue/src/views/liveforum/tcomments.vue @@ -43,7 +43,7 @@ @selection-change="handleSelectionChange" > - + @@ -79,26 +79,26 @@ - - + + - + - + - + @@ -110,16 +110,16 @@ - - - + + + @@ -141,9 +141,9 @@ \ No newline at end of file + diff --git a/ZR.Vue/src/views/liveforum/tposts.vue b/ZR.Vue/src/views/liveforum/tposts.vue index ee69b1e..a1011fd 100644 --- a/ZR.Vue/src/views/liveforum/tposts.vue +++ b/ZR.Vue/src/views/liveforum/tposts.vue @@ -67,59 +67,73 @@ @selection-change="handleSelectionChange" > - - - - - + + + + + - - - - - - - + + + + + + + + + + - + - + - + - - + + - - - - + + + + - + @@ -224,6 +238,114 @@ {{ $t('btn.submit') }} + + + + + + + + {{ $t('btn.add') }} + + + + + {{ $t('btn.delete') }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -233,6 +355,10 @@ import { listtposts, updatetposts,gettposts, } from '@/api/liveforum/tposts.js' +import { listtpostimages, + addtpostimages, deltpostimages, + } +from '@/api/liveforum/tpostimages.js' const { proxy } = getCurrentInstance() const ids = ref([]) const loading = ref(false) @@ -253,18 +379,19 @@ const columns = ref([ { visible: true, align: 'center', type: '', prop: 'nickName', label: '用户昵称' ,showOverflowTooltip: true }, { visible: true, align: 'center', type: '', prop: 'title', label: '标题' ,showOverflowTooltip: true }, { visible: true, align: 'center', type: 'img', prop: 'coverImage', label: '封面图片' ,showOverflowTooltip: true }, + { visible: true, align: 'center', type: '', prop: 'images', label: '图片列表' ,showOverflowTooltip: false }, { visible: true, align: 'center', type: '', prop: 'content', label: '正文内容' ,showOverflowTooltip: true }, { visible: true, align: 'center', type: '', prop: 'categoryId', label: '分类ID' }, { visible: true, align: 'center', type: '', prop: 'viewCount', label: '浏览次数' }, { visible: true, align: 'center', type: '', prop: 'likeCount', label: '点赞数量' }, - { visible: false, align: 'center', type: '', prop: 'commentCount', label: '评论数量' }, + { visible: true, align: 'center', type: '', prop: 'commentCount', label: '评论数量' }, { visible: false, align: 'center', type: '', prop: 'shareCount', label: '分享次数' }, - { visible: false, align: 'center', type: 'dict', prop: 'isTop', label: '是否置顶' ,dictType: 'liveforum_action_bool' }, - { visible: false, align: 'center', type: 'dict', prop: 'isHot', label: '是否热门' ,dictType: 'liveforum_action_bool' }, - { visible: false, align: 'center', type: 'dict', prop: 'isEssence', label: '是否精华' ,dictType: 'liveforum_action_bool' }, - { visible: false, align: 'center', type: 'dict', prop: 'status', label: '帖子状态' ,dictType: 'liveforum_posts_status' }, - { visible: false, align: 'center', type: '', prop: 'publishTime', label: '发布时间' ,showOverflowTooltip: true }, - { visible: false, align: 'center', type: 'dict', prop: 'isDeleted', label: '是否已删除' ,dictType: 'liveforum_action_bool' }, + { visible: true, align: 'center', type: 'dict', prop: 'isTop', label: '是否置顶' ,dictType: 'liveforum_action_bool' }, + { visible: true, align: 'center', type: 'dict', prop: 'isHot', label: '是否热门' ,dictType: 'liveforum_action_bool' }, + { visible: true, align: 'center', type: 'dict', prop: 'isEssence', label: '是否精华' ,dictType: 'liveforum_action_bool' }, + { visible: true, align: 'center', type: 'dict', prop: 'status', label: '帖子状态' ,dictType: 'liveforum_posts_status' }, + { visible: true, align: 'center', type: '', prop: 'publishTime', label: '发布时间' ,showOverflowTooltip: true }, + { visible: true, align: 'center', type: 'dict', prop: 'isDeleted', label: '是否已删除' ,dictType: 'liveforum_action_bool' }, { visible: false, align: 'center', type: '', prop: 'deletedAt', label: '删除时间' ,showOverflowTooltip: true }, { visible: false, align: 'center', type: '', prop: 'createdAt', label: '创建时间' ,showOverflowTooltip: true }, { visible: false, align: 'center', type: '', prop: 'updatedAt', label: '更新时间' ,showOverflowTooltip: true }, @@ -275,6 +402,42 @@ const dataList = ref([]) const queryRef = ref() const defaultTime = ref([new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)]) +// 图片管理弹窗相关状态 +const imageManageDialogOpen = ref(false) +const currentPost = ref({ id: null, title: '' }) +const imageList = ref([]) +const imageTotal = ref(0) +const imageLoading = ref(false) +const imageQueryParams = reactive({ + pageNum: 1, + pageSize: 10, + sort: 'SortOrder', + sortType: 'asc', + postId: undefined, +}) +const imageIds = ref([]) +const imageSingle = ref(true) +const imageMultiple = ref(true) + +// 添加图片表单相关状态 +const imageFormOpen = ref(false) +const imageFormRef = ref() +const imageFormSubmitLoading = ref(false) +const imageForm = reactive({ + postId: null, + imageUrl: null, + thumbnailUrl: null, + imageWidth: null, + imageHeight: null, + fileSize: null, + sortOrder: 0, +}) +const imageFormRules = { + postId: [{ required: true, message: "帖子ID不能为空", trigger: "blur", type: "number" }], + imageUrl: [{ required: true, message: "图片不能为空", trigger: "blur" }], + sortOrder: [{ required: true, message: "排序顺序不能为空", trigger: "blur", type: "number" }], +} + var dictParams = [ "liveforum_action_bool", @@ -504,5 +667,150 @@ function handleExport() { }) } +/*************** 图片管理相关方法 ***************/ +// 打开图片管理弹窗 +function handleManageImages(row) { + currentPost.value = { + id: row.id, + title: row.title || '未命名帖子' + } + imageQueryParams.postId = row.id + imageQueryParams.pageNum = 1 + imageManageDialogOpen.value = true + getImageList() +} + +// 查询图片列表 +function getImageList() { + imageLoading.value = true + listtpostimages(imageQueryParams).then(res => { + const { code, data } = res + if (code == 200) { + imageList.value = data.result + imageTotal.value = data.totalNum + imageLoading.value = false + } + }) +} + +// 图片列表多选框选中数据 +function handleImageSelectionChange(selection) { + imageIds.value = selection.map((item) => item.id) + imageSingle.value = selection.length != 1 + imageMultiple.value = !selection.length +} + +// 打开添加图片表单 +function handleAddImage() { + resetImageForm() + imageForm.postId = currentPost.value.id + // 设置默认排序顺序为当前最大排序+1 + if (imageList.value && imageList.value.length > 0) { + const maxSort = Math.max(...imageList.value.map(img => img.sortOrder || 0)) + imageForm.sortOrder = maxSort + 1 + } else { + imageForm.sortOrder = 1 + } + imageFormOpen.value = true + imageFormSubmitLoading.value = false +} + +// 重置图片表单 +function resetImageForm() { + imageForm.postId = null + imageForm.imageUrl = null + imageForm.thumbnailUrl = null + imageForm.imageWidth = null + imageForm.imageHeight = null + imageForm.fileSize = null + imageForm.sortOrder = 0 + proxy.resetForm("imageFormRef") +} + +// 取消添加图片表单 +function cancelImageForm() { + imageFormOpen.value = false + resetImageForm() +} + +// 提交添加图片表单 +function submitImageForm() { + proxy.$refs["imageFormRef"].validate((valid) => { + if (valid) { + imageFormSubmitLoading.value = true + addtpostimages(imageForm).then((res) => { + proxy.$modal.msgSuccess("新增成功") + imageFormOpen.value = false + resetImageForm() + getImageList() + // 刷新帖子列表(更新图片列表显示) + getList() + }) + .finally(() => { + setTimeout(() => { + imageFormSubmitLoading.value = false + }, 800) + }) + } + }) +} + +// 删除单张图片 +function handleDeleteImage(row) { + const Ids = row.id + + proxy + .$confirm('是否确认删除该图片?', "警告", { + confirmButtonText: proxy.$t('common.ok'), + cancelButtonText: proxy.$t('common.cancel'), + type: "warning", + }) + .then(function () { + return deltpostimages(Ids) + }) + .then(() => { + getImageList() + // 刷新帖子列表(更新图片列表显示) + getList() + proxy.$modal.msgSuccess("删除成功") + }) +} + +// 批量删除图片 +function handleBatchDeleteImage() { + const Ids = imageIds.value + + if (!Ids || Ids.length === 0) { + proxy.$modal.msgWarning("请选择要删除的图片") + return + } + + proxy + .$confirm('是否确认删除选中的' + Ids.length + '张图片?', "警告", { + confirmButtonText: proxy.$t('common.ok'), + cancelButtonText: proxy.$t('common.cancel'), + type: "warning", + }) + .then(function () { + return deltpostimages(Ids.join(',')) + }) + .then(() => { + getImageList() + // 刷新帖子列表(更新图片列表显示) + getList() + proxy.$modal.msgSuccess("删除成功") + }) +} + +// 关闭图片管理弹窗 +function closeImageManageDialog() { + imageManageDialogOpen.value = false + currentPost.value = { id: null, title: '' } + imageQueryParams.postId = undefined + imageList.value = [] + imageTotal.value = 0 + imageIds.value = [] +} + handleQuery()