feat: allow editing community post content

This commit is contained in:
hajimi
2026-08-02 20:11:15 +08:00
parent 115a859dd3
commit 71f3b1c6d7
7 changed files with 125 additions and 2 deletions
+5
View File
@@ -10,6 +10,11 @@ export function communityPostDetail(params: any) {
return request.get({ url: '/community.communityPost/detail', params })
}
// 编辑帖子内容
export function communityPostEditContent(params: any) {
return request.post({ url: '/community.communityPost/editContent', params })
}
// 帖子审核状态
export function communityPostStatus(params: any) {
return request.post({ url: '/community.communityPost/updateStatus', params })
+54 -1
View File
@@ -129,12 +129,16 @@
</template>
</el-table-column>
<el-table-column label="发布时间" prop="create_time" min-width="150" />
<el-table-column label="操作" width="230" fixed="right">
<el-table-column label="操作" width="280" fixed="right">
<template #default="{ row }">
<el-button v-perms="['community.communityPost/detail']" type="primary" link
@click="handleDetail(row.id)">
详情
</el-button>
<el-button v-perms="['community.communityPost/editContent']" type="primary" link
@click="handleEdit(row)">
编辑
</el-button>
<el-button v-if="row.status === 0" v-perms="['community.communityPost/updateStatus']"
type="success" link @click="handleAudit(row.id, 1)">
通过
@@ -199,12 +203,27 @@
<el-button @click="showDetail = false">关闭</el-button>
</template>
</el-dialog>
<el-dialog v-model="showEdit" title="编辑帖子内容" width="700px" destroy-on-close>
<el-form label-position="top">
<el-form-item label="帖子内容">
<el-input v-model="editData.content" type="textarea" :rows="14" :maxlength="16000"
show-word-limit resize="vertical" placeholder="请输入帖子内容" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="showEdit = false">取消</el-button>
<el-button type="primary" :loading="editSubmitLoading" @click="handleSubmitEdit">
保存
</el-button>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup name="communityPost">
import {
communityPostLists,
communityPostDetail,
communityPostEditContent,
communityPostStatus,
communityPostSetTop,
communityPostSetHot,
@@ -315,6 +334,40 @@ const handleDetail = async (id: number) => {
}
}
const showEdit = ref(false)
const editSubmitLoading = ref(false)
const editData = reactive({
id: 0,
content: ''
})
const handleEdit = (post: any) => {
showEdit.value = true
editData.id = post.id
editData.content = post.content || ''
}
const handleSubmitEdit = async () => {
if (!editData.content.trim()) {
feedback.msgError('请输入帖子内容')
return
}
editSubmitLoading.value = true
try {
await communityPostEditContent({
id: editData.id,
content: editData.content
})
showEdit.value = false
if (detailData.value.id === editData.id) {
detailData.value.content = editData.content
}
getLists()
} finally {
editSubmitLoading.value = false
}
}
const loadCategories = async () => {
try {
const categories = await communityCategoryAll()
@@ -204,6 +204,7 @@ FROM (
SELECT '设置推荐' AS `name`, 'community.communityPost/setRecommend' AS `perms`
UNION ALL SELECT '设置话题', 'community.communityPost/setTopic'
UNION ALL SELECT '设置分类', 'community.communityPost/setCategory'
UNION ALL SELECT '编辑内容', 'community.communityPost/editContent'
) permission
WHERE @post_menu_id IS NOT NULL
AND NOT EXISTS (
@@ -222,7 +223,8 @@ WHERE menu.`perms` IN (
'community.communityCategory/delete',
'community.communityPost/setRecommend',
'community.communityPost/setTopic',
'community.communityPost/setCategory'
'community.communityPost/setCategory',
'community.communityPost/editContent'
)
AND NOT EXISTS (
SELECT 1
@@ -0,0 +1,24 @@
SET @post_menu_id = COALESCE(
(SELECT `id` FROM `la_system_menu` WHERE `perms` = 'community.communityPost/lists' LIMIT 1),
(SELECT `id` FROM `la_system_menu` WHERE `component` = 'community/post/index' LIMIT 1)
);
INSERT INTO `la_system_menu`
(`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`, `selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`)
SELECT
@post_menu_id, 'A', '编辑内容', '', 0, 'community.communityPost/editContent', '', '', '', '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE @post_menu_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM `la_system_menu` WHERE `perms` = 'community.communityPost/editContent'
);
INSERT INTO `la_system_role_menu` (`role_id`, `menu_id`)
SELECT 1, menu.`id`
FROM `la_system_menu` menu
WHERE menu.`perms` = 'community.communityPost/editContent'
AND NOT EXISTS (
SELECT 1
FROM `la_system_role_menu` role_menu
WHERE role_menu.`role_id` = 1
AND role_menu.`menu_id` = menu.`id`
);
@@ -21,6 +21,16 @@ class CommunityPostController extends BaseAdminController
return $this->data($result);
}
public function editContent()
{
$params = (new CommunityPostValidate())->post()->goCheck('editContent');
$result = CommunityPostLogic::editContent($params);
if (true === $result) {
return $this->success('保存成功', [], 1, 1);
}
return $this->fail(CommunityPostLogic::getError());
}
public function updateStatus()
{
$params = (new CommunityPostValidate())->post()->goCheck('status');
@@ -50,6 +50,27 @@ class CommunityPostLogic extends BaseLogic
}
}
public static function editContent(array $params): bool
{
$post = CommunityPost::findOrEmpty($params['id']);
if ($post->isEmpty()) {
self::setError('帖子不存在');
return false;
}
try {
$post->content = (string) $params['content'];
$post->save();
if ((int) $post->status === 1) {
KbSyncService::enqueue('post', 'post', (int) $post->id, 'upsert', 30);
}
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
public static function setTop(array $params): bool
{
try {
@@ -17,11 +17,14 @@ class CommunityPostValidate extends BaseValidate
'sort' => 'require|integer|egt:0|elt:1000000',
'is_topic' => 'require|in:0,1',
'category_id' => 'require|integer|egt:0|checkCategory',
'content' => 'require|max:16000',
];
protected $message = [
'id.require' => '帖子id不能为空',
'status.require' => '状态不能为空',
'content.require' => '帖子内容不能为空',
'content.max' => '帖子内容不能超过16000个字符',
];
public function sceneDetail()
@@ -39,6 +42,11 @@ class CommunityPostValidate extends BaseValidate
return $this->only(['id', 'status']);
}
public function sceneEditContent()
{
return $this->only(['id', 'content']);
}
public function sceneTop()
{
return $this->only(['id', 'is_top']);