完成帖子编辑操作

This commit is contained in:
柏码の讲师 2023-10-27 18:37:00 +08:00
parent 9777bc26cc
commit 863a1d4f0f
8 changed files with 125 additions and 29 deletions

View File

@ -3,6 +3,7 @@ package com.example.controller;
import com.example.entity.RestBean;
import com.example.entity.dto.Interact;
import com.example.entity.vo.request.TopicCreateVO;
import com.example.entity.vo.request.TopicUpdateVO;
import com.example.entity.vo.response.*;
import com.example.service.TopicService;
import com.example.service.WeatherService;
@ -67,8 +68,9 @@ public class ForumController {
}
@GetMapping("/topic")
public RestBean<TopicDetailVO> topic(@RequestParam @Min(0) int tid){
return RestBean.success(topicService.getTopic(tid));
public RestBean<TopicDetailVO> topic(@RequestParam @Min(0) int tid,
@RequestAttribute(Const.ATTR_USER_ID) int id){
return RestBean.success(topicService.getTopic(tid, id));
}
@GetMapping("/interact")
@ -84,4 +86,11 @@ public class ForumController {
public RestBean<List<TopicPreviewVO>> collects(@RequestAttribute(Const.ATTR_USER_ID) int id){
return RestBean.success(topicService.listCollectTopic(id));
}
@PostMapping("/update-topic")
public RestBean<Void> updateTopic(@Valid @RequestBody TopicUpdateVO vo,
@RequestAttribute(Const.ATTR_USER_ID) int id) {
topicService.updateTopic(id, vo);
return RestBean.success();
}
}

View File

@ -0,0 +1,19 @@
package com.example.entity.vo.request;
import com.alibaba.fastjson2.JSONObject;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
@Data
public class TopicUpdateVO {
@Min(0)
int id;
@Min(1)
@Max(5)
int type;
@Length(max = 30)
String title;
JSONObject content;
}

View File

@ -6,6 +6,7 @@ import java.util.Date;
@Data
public class AccountVO {
int id;
String username;
String email;
String role;

View File

@ -5,6 +5,7 @@ import com.example.entity.dto.Interact;
import com.example.entity.dto.Topic;
import com.example.entity.dto.TopicType;
import com.example.entity.vo.request.TopicCreateVO;
import com.example.entity.vo.request.TopicUpdateVO;
import com.example.entity.vo.response.TopicPreviewVO;
import com.example.entity.vo.response.TopicTopVO;
import com.example.entity.vo.response.TopicDetailVO;
@ -14,9 +15,10 @@ import java.util.List;
public interface TopicService extends IService<Topic> {
List<TopicType> listType();
String createTopic(int uid, TopicCreateVO vo);
void updateTopic(int uid, TopicUpdateVO vo);
List<TopicPreviewVO> listTopicByPage(int pageNumber, int type);
List<TopicTopVO> topTopics();
TopicDetailVO getTopic(int tid);
TopicDetailVO getTopic(int tid, int uid);
void interact(Interact interact, boolean state);
List<TopicPreviewVO> listCollectTopic(int uid);
}

View File

@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.dto.*;
import com.example.entity.vo.request.TopicCreateVO;
import com.example.entity.vo.request.TopicUpdateVO;
import com.example.entity.vo.response.TopicDetailVO;
import com.example.entity.vo.response.TopicPreviewVO;
import com.example.entity.vo.response.TopicTopVO;
@ -54,6 +55,17 @@ public class TopicServiceImpl extends ServiceImpl<TopicMapper, Topic> implements
return typeMapper.selectList(null);
}
@Override
public void updateTopic(int uid, TopicUpdateVO vo) {
baseMapper.update(null, Wrappers.<Topic>update()
.eq("uid", uid)
.eq("id", vo.getId())
.set("title", vo.getTitle())
.set("content", vo.getContent().toString())
.set("type", vo.getType())
);
}
@Override
public String createTopic(int uid, TopicCreateVO vo) {
if(!this.textLimitCheck(vo.getContent()))
@ -116,13 +128,13 @@ public class TopicServiceImpl extends ServiceImpl<TopicMapper, Topic> implements
}
@Override
public TopicDetailVO getTopic(int tid) {
public TopicDetailVO getTopic(int tid, int uid) {
TopicDetailVO vo = new TopicDetailVO();
Topic topic = baseMapper.selectById(tid);
BeanUtils.copyProperties(topic, vo);
TopicDetailVO.Interact interact = new TopicDetailVO.Interact(
hasInteract(tid, topic.getUid(), "like"),
hasInteract(tid, topic.getUid(), "collect")
hasInteract(tid, uid, "like"),
hasInteract(tid, uid, "collect")
);
vo.setInteract(interact);
TopicDetailVO.User user = new TopicDetailVO.User();

View File

@ -1,6 +1,6 @@
<script setup>
import {Document} from "@element-plus/icons-vue";
import {QuillEditor, Quill} from "@vueup/vue-quill";
import {QuillEditor, Quill, Delta} from "@vueup/vue-quill";
import {computed, reactive, ref} from "vue";
import '@vueup/vue-quill/dist/vue-quill.snow.css';
import {accessHeader, post} from "@/net";
@ -10,9 +10,39 @@ import ImageResize from "quill-image-resize-vue";
import { ImageExtend, QuillWatch } from "quill-image-super-solution-module";
import {useStore} from "@/store";
defineProps({ show: Boolean })
const props = defineProps({
show: Boolean,
defaultTitle: {
default: '',
type: String
},
defaultText: {
default: '',
type: String
},
defaultType: {
default: 1,
type: Number
},
submitButton: {
default: '立即发布',
type: String
},
submit: {
default: (editor, success) => {
post('/api/forum/create-topic', {
type: editor.type,
title: editor.title,
content: editor.text
}, () => {
ElMessage.success("帖子发表成功!")
success()
})
},
type: Function
}
})
const emit = defineEmits(['close', 'created'])
const store = useStore()
const refEditor = ref()
@ -24,9 +54,12 @@ const editor = reactive({
})
function initEditor() {
refEditor.value.setContents('', 'user')
editor.title = ''
editor.type = 1
if(props.defaultText)
editor.text = new Delta(JSON.parse(props.defaultText))
else
refEditor.value.setContents('', 'user')
editor.title = props.defaultTitle
editor.type = props.defaultType
}
function submitTopic(){
@ -43,14 +76,7 @@ function submitTopic(){
ElMessage.warning('请选择一个合适的帖子类型!')
return
}
post('/api/forum/create-topic', {
type: editor.type,
title: editor.title,
content: editor.text
}, () => {
ElMessage.success("帖子发表成功!")
emit('created')
})
props.submit(editor, () => emit('created'))
}
function deltaToText(delta) {
@ -154,7 +180,7 @@ const editorOption = {
当前字数: {{ contentLength }}最大支持20000字
</div>
<div>
<el-button @click="submitTopic" type="success" plain>立即发布</el-button>
<el-button @click="submitTopic" type="success" plain>{{submitButton}}</el-button>
</div>
</div>
</el-drawer>

View File

@ -5,6 +5,7 @@ export const useStore = defineStore('general', {
state: () => {
return {
user: {
id: -1,
username: '',
email: '',
role: '',

View File

@ -1,9 +1,9 @@
<script setup>
import {useRoute} from "vue-router";
import {get} from "@/net";
import {computed, reactive} from "vue";
import {get, post} from "@/net";
import {computed, reactive, ref} from "vue";
import axios from "axios";
import {ArrowLeft, CircleCheck, Female, Male, Star} from "@element-plus/icons-vue";
import {ArrowLeft, CircleCheck, EditPen, Female, Male, Star} from "@element-plus/icons-vue";
import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html';
import {useStore} from "@/store";
import Card from "@/components/Card.vue";
@ -11,6 +11,7 @@ import router from "@/router";
import InteractButton from "@/components/InteractButton.vue";
import {ElMessage} from "element-plus";
import TopicTag from "@/components/TopicTag.vue";
import TopicEditor from "@/components/TopicEditor.vue";
const route = useRoute()
const store = useStore()
@ -23,12 +24,16 @@ const topic = reactive({
collect: false,
comments: []
})
const edit = ref(false)
get(`/api/forum/topic?tid=${tid}`, data => {
topic.data = data
topic.like = data.interact.like
topic.collect = data.interact.collect
})
function init() {
get(`/api/forum/topic?tid=${tid}`, data => {
topic.data = data
topic.like = data.interact.like
topic.collect = data.interact.collect
})
}
init()
const content = computed(() => {
const ops = JSON.parse(topic.data.content).ops
@ -45,6 +50,19 @@ function interact(type, message) {
ElMessage.success(`已取消${message}!`)
})
}
function updateTopic(editor) {
post('/api/forum/update-topic', {
id: tid,
type: editor.type,
title: editor.title,
content: editor.text
}, () => {
ElMessage.success("帖子内容更新成功!")
edit.value = false
init()
})
}
</script>
<template>
@ -91,6 +109,10 @@ function interact(type, message) {
<div>发帖时间: {{new Date(topic.data.time).toLocaleString()}}</div>
</div>
<div style="text-align: right;margin-top: 30px">
<interact-button name="编辑帖子" color="dodgerblue" style="margin-right: 20px"
:check="false" @check="edit = true" v-if="store.user.id === topic.data.user.uid">
<el-icon><EditPen /></el-icon>
</interact-button>
<interact-button name="点个赞吧" check-name="已点赞" color="pink"
:check="topic.like" @check="interact('like', '点赞')">
<el-icon><CircleCheck /></el-icon>
@ -103,6 +125,10 @@ function interact(type, message) {
</div>
</div>
</div>
<topic-editor :show="edit" @close="edit = false" v-if="topic.data"
:default-title="topic.data.title" :default-text="topic.data.content"
:default-type="topic.data.type" submit-button="更新帖子内容"
:submit="updateTopic"/>
</div>
</template>