赞
踩
项目使用到的技术与库
1.前端 Vue2 elementUi Cookie WangEditer
2.后端 SpringBoot Mybatis-Plus
3.数据库 MySql
1.1主页效果:
1.2 文章编辑页面:
1.3 成功发布文章
1.4 文章关键字搜索提示
1.5 文章查询结果展示
1.6 文章内容及交互展示
用户:
- create table paitool.user
- (
- id int auto_increment
- primary key,
- account varchar(255) not null,
- password varchar(255) not null,
- phone varchar(20) null,
- address varchar(255) null,
- isVip tinyint(1) default 0 null,
- email varchar(255) null,
- registration_date datetime default CURRENT_TIMESTAMP null,
- last_login datetime null,
- status enum ('active', 'inactive') default 'active' null,
- constraint account_UNIQUE
- unique (account),
- constraint email_UNIQUE
- unique (email),
- constraint phone_UNIQUE
- unique (phone)
- );

文章:
- create table paitool.forum_posts
- (
- id int auto_increment
- primary key,
- title varchar(255) not null,
- content text not null,
- author_id int not null,
- created_at timestamp default CURRENT_TIMESTAMP null,
- updated_at timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP,
- heat_value int default 0 null,
- rating decimal(3, 2) default 0.00 null,
- tag varchar(10) default '其它' null,
- constraint forum_posts_ibfk_1
- foreign key (author_id) references paitool.user (id)
- );
文章交互表-点赞:
- create table paitool.forum_post_likes
- (
- user_id int not null,
- post_id int not null,
- primary key (user_id, post_id),
- constraint forum_post_likes_ibfk_1
- foreign key (user_id) references paitool.user (id),
- constraint forum_post_likes_ibfk_2
- foreign key (post_id) references paitool.forum_posts (id)
- );
文章交互表-收藏:
- create table paitool.forum_post_favorites
- (
- user_id int not null,
- post_id int not null,
- primary key (user_id, post_id),
- constraint forum_post_favorites_ibfk_1
- foreign key (user_id) references paitool.user (id),
- constraint forum_post_favorites_ibfk_2
- foreign key (post_id) references paitool.forum_posts (id)
- );
文章交互表-评论
- create table paitool.forum_comments
- (
- id int auto_increment
- primary key,
- post_id int not null,
- user_id int not null,
- comment_text text not null,
- created_at timestamp default CURRENT_TIMESTAMP null,
- constraint forum_comments_ibfk_1
- foreign key (user_id) references paitool.user (id),
- constraint forum_comments_ibfk_2
- foreign key (post_id) references paitool.forum_posts (id)
- );
Html:
- <template>
- <div id="forumLayOut">
-
- <div id="Top" style="background-color: rgb(250, 250, 250); padding-top: 20px">
-
- <div id="serchBorder" style="padding-bottom: 13px;">
- <!-- 搜索框 -->
- <el-autocomplete v-model="searchKeyWord" :fetch-suggestions="querySearchAsync" :trigger-on-focus="false"
- placeholder="请输入关键字" style="width: 300px;" @select="handleSelect">
- </el-autocomplete>
- <el-button type="primary" @click="onSubmit">查询</el-button>
- </div>
-
- <!-- 分类查询 -->
- <div>
-
- <div style="margin-bottom: 15px;">
- <el-checkbox-group v-model="checkboxGroup1" :max="1">
- <el-checkbox-button v-for="city in cities" :label="city" :key="city">{{ city
- }}</el-checkbox-button>
- </el-checkbox-group>
- </div>
-
- </div>
-
-
- <div style="height: 380px; width: 100%;">
- <!-- 轮播图 -->
- <div class="block" style="width: 30%; float: left; margin-left: 5%; height: 400px;">
- <el-carousel height="350px" style="width: 100%; ">
- <el-carousel-item v-for="item in 4" :key="item">
- <img src="https://img95.699pic.com/photo/50035/3211.jpg_wh860.jpg" alt="风景测试">
- <h3 class="small">{{ item }}</h3>
- </el-carousel-item>
- </el-carousel>
- </div>
-
-
- <div style=" height: 350px; background-color: rgb(250, 250, 250); width: 25%; float: left;
- border: 1px solid rgb(240, 240, 242); margin-left: 3%;">
-
-
- <div style="height: 50px; width: 100%; background-color: rgb(245, 245, 245); ">
- <i class="el-icon-share"></i>
- <div><b>热门</b></div>
- <hr>
- </div>
-
- <div class="link-container">
- <a href="#" class="link" id="TurnLink">杀死谷歌,成为AI时代的搜索皇帝!</a>
- <p style="color: gray;">Perplexity CEO 最新四万字访谈</p>
- </div>
-
- <div class="link-container">
- <a href="#" class="link" id="TurnLink">重写系统后痛批:这门语言烂透了!</a>
- <p style="color: gray;">耗时18个月,开发者弃TypeScript投Rust</p>
- </div>
- <div class="link-container">
- <a href="#" class="link" id="TurnLink">Shire 编码智能体语言</a>
- <p style="color: gray;">打造你的专属 AI 编程助手</p>
- </div>
-
-
- </div>
-
-
- <div style="float: left; margin-left: 3%; height: 350px; background-color: rgb(250, 250, 250); width: 25%; float: left;
- border: 1px solid rgb(240, 240, 242); ">
-
-
- <div style="height: 50px; width: 100%; background-color: rgb(245, 245, 245); ">
- <i class="el-icon-message-solid"></i>
- <div><b>头条</b></div>
- <hr>
- </div>
-
- <div class="link-container">
- <a href="#" class="link" id="TurnLink">史上开发最久的游戏!</a>
- <p style="color: gray;">耗时 22 年,5 名打工人凑了几百欧就开工,只剩 1 人坚守到发布...</p>
- </div>
-
- <div class="link-container">
- <a href="#" class="link" id="TurnLink">实习期间创下 Transformer</a>
- <p style="color: gray;">他说:当年整个 AI 圈都无法预见我们今天的高度</p>
- </div>
-
- <div class="link-container">
- <a href="#" class="link" id="TurnLink">杀死谷歌,成为AI时代的搜索皇帝!</a>
- <p style="color: gray;">Perplexity CEO 最新四万字访谈</p>
- </div>
-
- </div>
- </div>
-
-
- </div>
-
- <el-divider></el-divider>
- <div id="bottom">
-
- <!-- Tabs 标签页 -->
- <el-tabs v-model="activeName" @tab-click="handleClick" style="padding-left: 2em; ">
-
- <el-tab-pane label="我的文章" name="first">
- <div class="parent-div" style="min-height: 500px">
-
- <div v-if="posts.length === 0">
- <el-empty :image-size="200"></el-empty>
- </div>
-
- <div class="custom-card" v-for="(post, index) in posts" :key="index"
- @click="getForumPostDetail(post.id)">
- <div class="card-content">
- <h1 class="card-title">标题: {{ post.title }}</h1>
- <div class="card-meta">
- <span>作者: {{ post.account }}</span>
- <span>标签: {{ post.tag }}</span>
- <span><i class="el-icon-view">{{ post.heatValue }}</i></span>
- </div>
- <div class="card-rating">
- <span>文章评分:</span>
- <el-rate v-model="post.rating" disabled show-score text-color="#ff9900"
- score-template="{value}" style="display: inline-block;"></el-rate>
- </div>
- </div>
- </div>
- </div>
-
-
- </el-tab-pane>
-
-
- <el-tab-pane label="推荐文章" name="second">
-
- <div v-if="posts.length === 0">
- <el-empty :image-size="200"></el-empty>
- </div>
-
- <div class="custom-card" v-for="(post, index) in posts" :key="index"
- @click="getForumPostDetail(post.postId)">
- <div class="card-content">
- <h1 class="card-title">标题: {{ post.title }}</h1>
- <div class="card-meta">
- <span>作者: {{ post.account }}</span>
- <span>标签: {{ post.tag }}</span>
- <span><i class="el-icon-view">{{ post.heat_value }}</i></span>
- </div>
- <div class="card-rating">
- <span>文章评分:</span>
- <el-rate v-model="post.rating" disabled show-score text-color="#ff9900"
- score-template="{value}" style="display: inline-block;"></el-rate>
- </div>
- </div>
- </div>
-
- </el-tab-pane>
- <el-tab-pane label="热门文章" name="third">
-
-
-
- <div class="parent-div" style="min-height: 500px">
- <div v-if="posts.length === 0">
- <el-empty :image-size="200"></el-empty>
- </div>
- <div class="custom-card" v-for="(post, index) in posts" :key="index"
- @click="getForumPostDetail(post.id)">
- <div class="card-content">
- <h1 class="card-title">标题: {{ post.title }}</h1>
- <div class="card-meta">
- <span>作者: {{ post.account }}</span>
- <span>标签: {{ post.tag }}</span>
- <span><i class="el-icon-view">{{ post.heatValue }}</i></span>
- </div>
- <div class="card-rating">
- <span>文章评分:</span>
- <el-rate v-model="post.rating" disabled show-score text-color="#ff9900"
- score-template="{value}" style="display: inline-block;"></el-rate>
- </div>
- </div>
- </div>
- </div>
-
-
-
-
- </el-tab-pane>
-
- <el-tab-pane label="优质文章" name="fourth">
-
-
- <div class="parent-div" style="min-height: 500px">
- <div v-if="posts.length === 0">
- <el-empty :image-size="200"></el-empty>
- </div>
- <div class="custom-card" v-for="(post, index) in posts" :key="index"
- @click="getForumPostDetail(post.id)">
- <div class="card-content">
- <h1 class="card-title">标题: {{ post.title }}</h1>
- <div class="card-meta">
- <span>作者: {{ post.account }}</span>
- <span>标签: {{ post.tag }}</span>
- <span><i class="el-icon-view">{{ post.heatValue }}</i></span>
- </div>
- <div class="card-rating">
- <span>文章评分:</span>
- <el-rate v-model="post.rating" disabled show-score text-color="#ff9900"
- score-template="{value}" style="display: inline-block;"></el-rate>
- </div>
- </div>
- </div>
- </div>
-
-
-
- </el-tab-pane>
-
- <el-tab-pane label="我的收藏" name="fifth">
- <div v-if="posts.length === 0">
- <el-empty :image-size="200"></el-empty>
- </div>
-
-
-
- <div class="parent-div" style="min-height: 500px">
- <div v-if="posts.length === 0">
- <el-empty :image-size="200"></el-empty>
- </div>
- <div class="custom-card" v-for="(post, index) in posts" :key="index"
- @click="getForumPostDetail(post.id)">
- <div class="card-content">
- <h1 class="card-title">标题: {{ post.title }}</h1>
- <div class="card-meta">
- <span>作者: {{ post.account }}</span>
- <span>标签: {{ post.tag }}</span>
- <span><i class="el-icon-view">{{ post.heatValue }}</i></span>
- </div>
- <div class="card-rating">
- <span>文章评分:</span>
- <el-rate v-model="post.rating" disabled show-score text-color="#ff9900"
- score-template="{value}" style="display: inline-block;"></el-rate>
- </div>
- </div>
- </div>
- </div>
-
-
- </el-tab-pane>
- </el-tabs>
-
- <el-button type="warning" round id="iWantPost" @click="navigateToPostEdit">我要发布文章</el-button>
-
- </div>
-
-
-
-
- </div>
- </template>

js:
- <script>
- import axios from 'axios';
- import Cookies from 'js-cookie';
-
- const cityOptions = ['新闻报道', '科技动态', '生活时尚', '教育学习', '健康养生'];
- export default {
- components: {
-
- },
-
- data() {
- return {
- searchKeyWord: '',
- suggestions: [], // 添加这个属性
- checkboxGroup1: [],
- cities: cityOptions,
- activeName: 'first',
- currentPage1: 5,
- currentPage2: 5,
- currentPage3: 5,
- currentPage4: 4,
- posts: [
- ],
-
- }
- },
- methods: {
- onSubmit() {
- this.$router.push({
- name: 'ArticalSearchView',
- params: {
- searchKeyWord: this.searchKeyWord
- }
- })
-
-
- },
- handleClick(tab) {
-
- // 我的文章
- if (tab.name === 'first') {
- this.posts = []
- this.getMyArticle();
-
- }
-
- // 推荐文章
- if (tab.name === 'second') {
- this.posts = [];
-
- axios.get('/api/forum/getAllForumPost', {
- params: {
- pageSize: 1,
- pageNumber: 10
- }
- }).then((response) => {
- console.log(response.data.data);
-
- this.posts = response.data.data;
- });
-
-
- }
- // 热门文章
- if (tab.name === 'third') {
- this.posts = [];
-
- axios.get('/api/forum/getHotPosts').then((response) => {
- console.log(response.data.data);
- this.posts = response.data.data;
- });
-
-
- }
-
- // 优质文章
- if (tab.name === 'fourth') {
- this.posts = [];
-
- axios.get('/api/forum/getOutStandPosts').then((response) => {
- console.log(response.data.data);
- this.posts = response.data.data;
- });
-
- }
-
- // 我的收藏
- if (tab.name === 'fifth') {
- this.posts = [];
- const id = Cookies.get("userId");
-
- if (id === null) {
- this.$message({
- message: '请先登录',
- type: 'warning'
- });
- return;
- }
-
- axios.get('/api/forum/getMyFavorite', {
- params: {
- id: id
- }
- }).then((response) => {
- console.log(response.data.data);
- this.posts = response.data.data;
- });
-
- }
-
-
-
- },
-
- // 处理分页功能
- handleSizeChange(val) {
- console.log(`每页 ${val} 条`);
- },
- handleCurrentChange(val) {
- console.log(`当前页: ${val}`);
- },
-
- navigateToPostEdit() {
- this.$router.push({ name: 'ForumPostEditView' });
- },
-
-
- // 跳转到文章详情
- getForumPostDetail(postId) {
- console.log("getForumPostDetail");
- console.log(postId);
- this.$router.push(`/post/${postId}`);
- },
-
- getMyArticle() {
- this.posts = [];
- const id = Cookies.get("userId");
-
- if (id === null) {
- this.$message({
- message: '请先登录',
- type: 'warning'
- });
- return;
- } else {
- axios.get('/api/forum/MyArticle', {
- params: {
- id: id
- }
- }).then((response) => {
- console.log(response.data.data);
- this.posts = response.data.data;
- })
-
- }
-
- },
- // 异步获取建议列表
- querySearchAsync(queryString, cb) {
- if (queryString.length === 0) {
- return cb([]); // 当查询字符串为空时,直接返回空数组
- }
- axios.get('/api/forum/getLikeSearch', { params: { keyword: queryString } })
- .then(response => {
- // 确保从后端返回的数据中提取出正确的数组
- const results = response.data.data || [];
- // 调用callback函数,传入搜索结果
- cb(results);
- })
- .catch(error => {
- console.error('Error fetching search suggestions:', error);
-
- cb([]);
- });
- },
- // 处理选择事件
- handleSelect(item) {
- this.searchKeyWord = item.value;
- this.onSubmit();
- }
-
-
- },
-
- mounted() {
- this.getMyArticle();
-
- }
-
-
- }
-
- </script>

css:
- <style scoped>
- #forumLayOut {
-
- background-color: white;
- height: auto;
- width: 100%;
- line-height: normal;
- }
-
- #serchBorder {
-
- line-height: normal;
- }
-
- .el-carousel__item h3 {
- color: #475669;
- font-size: 14px;
- opacity: 0.75;
- line-height: 150px;
- margin: 0;
- }
-
- .el-carousel__item:nth-child(2n) {
- background-color: #99a9bf;
- }
-
- .el-carousel__item:nth-child(2n+1) {
- background-color: #d3dce6;
- }
-
- #Pagination {
- align-self: center;
- /* 居中对齐 */
- margin-bottom: 1rem;
- /* 可选,增加底部边距 */
- margin-top: 10%;
- }
-
-
- #iWantPost {
- position: fixed;
- /* 设置为固定定位 */
- bottom: 60px;
- /* 距离底部的距离,可根据需要调整 */
- right: 40px;
- /* 距离右侧的距离,可根据需要调整 */
- }
-
-
- .el-tabs__content {
- overflow: hidden;
- position: relative;
- height: auto;
- }
-
- .custom-card {
- background-color: #ffffff;
- border-radius: 4px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
- margin-bottom: 16px;
- transition: box-shadow 0.3s ease-in-out;
- }
-
- .custom-card:hover {
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
- cursor: pointer;
- background-color: rgb(245, 245, 245);
- }
-
- .card-content {
- padding: 16px;
- }
-
- .card-title {
- font-size: 1.2em;
- margin-bottom: 8px;
- color: #333;
- }
-
- .card-meta {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 12px;
- color: #666;
- }
-
- .card-rating {
- color: #666;
- }
-
- .link-container {
- line-height: normal;
- float: left;
- width: 100%;
- text-align: left;
- padding-left: 40px;
- padding-top: 10px;
- }
-
- .link {
- text-decoration: none;
- font-size: large;
- color: black;
- }
-
- .link:hover {
- text-decoration: underline;
- }
- </style>

- <template>
-
- <div style="border: 1px solid #ccc; line-height: normal; height: 100%;">
- <div>
-
- <el-form :inline="true" :model="formInline" class="demo-form-inline">
- <el-form-item label="文章标题">
- <el-input v-model="formInline.title" placeholder="请输入文章标题" maxlength="20"></el-input>
- </el-form-item>
-
-
- <el-form-item label="类别">
- <el-select v-model="formInline.category" placeholder="请选择文章类别">
- <el-option label="新闻报道" value="news"></el-option>
- <el-option label="科技动态" value="technology"></el-option>
- <el-option label="生活时尚" value="lifestyle"></el-option>
- <el-option label="教育学习" value="education"></el-option>
- <el-option label="健康养生" value="health"></el-option>
- </el-select>
- </el-form-item>
-
-
- <el-form-item>
- <el-button type="primary" @click="onSubmit"
- v-loading.fullscreen.lock="fullscreenLoading">提交</el-button>
- </el-form-item>
- </el-form>
-
- </div>
- <Toolbar style="border-bottom: 1px solid #ccc" :editor="editor" :defaultConfig="toolbarConfig" :mode="mode" />
- <Editor style="height: 500px; overflow-y: hidden; height: 100%;" v-model="html" :defaultConfig="editorConfig"
- :mode="mode" @onCreated="onCreated" />
- </div>
-
- </template>
-
-
- <script>
- import Vue from 'vue'
- import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
- import axios from 'axios'
- import Cookies from 'js-cookie'
-
-
- export default Vue.extend({
- components: { Editor, Toolbar },
- data() {
- return {
- editor: null,
- html: ' ',
- toolbarConfig: {},
- editorConfig: { placeholder: '请输入内容...' },
- mode: 'default', // or 'simple'
- formInline: {
- title: '',
- category: ''
- },
- fullscreenLoading: false
- }
- },
- methods: {
- onCreated(editor) {
- this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
-
- },
- onSubmit() {
-
- this.fullscreenLoading = true;
-
- const userId = Cookies.get('userId'); // 获取并转换userId
-
- axios.post('/api/forum/add', {
-
- "title": this.formInline.title,
-
- "content": this.editor.getHtml(),
-
- "authorId": userId,
-
- "tag": this.formInline.category,
-
- }).then((response) => {
-
- console.log(response.data);
-
- this.fullscreenLoading = false;
-
- this.$router.push({ name: 'ForumSucessPostView' });
-
- }).catch(error => {
-
- console.error(error);
-
- this.fullscreenLoading = false;
-
- });
-
- },
-
- },
- mounted() {
-
- },
- beforeDestroy() {
- const editor = this.editor
- if (editor == null) return
- editor.destroy() // 组件销毁时,及时销毁编辑器
-
-
- },
-
- })
- </script>
-
-
- <style src="@wangeditor/editor/dist/css/style.css"></style>

html:
- <template>
- <div style="line-height: normal; background-color: rgb(246, 247, 249); height: auto; min-height: 80%;">
-
- <!-- 文章信息 -->
- <div style="padding-top: 10px; width: auto; min-width: 40%;">
- <!-- 实现文字垂直居中 -->
- <div id="Infor" style="background-color: white;">
- <h1 style="font-size: 28px; text-align: center">文章标题:{{title}}</h1>
- <span>创作者:{{author}}</span>
- <span style="margin-left: 20px;">创作日期:{{createAt}}</span>
- <span style="margin-left: 20px;"><i class="el-icon-view">{{heatValue}}</i></span>
- </div>
-
- <el-divider><i class="el-icon-mobile-phone"></i></el-divider>
-
-
- <!-- 文章内容展示区 -->
- <div id="contentDisplay">
- <div v-html="content"
- style="padding-left: 2em; padding-top: 15px; padding-right: 2em; padding-bottom: 30px;"></div>
- </div>
- </div>
-
- <el-divider><i class="el-icon-edit"></i></el-divider>
-
- <!-- 交互按键 -->
- <div id="buttom">
- <el-button type="warning" round @click="getBackToForum">返回到论坛</el-button>
- <el-button type="warning" icon="el-icon-star-off" circle @click="PostFavorite"></el-button>
- <el-button type="danger" icon="el-icon-thumb" circle @click="PostLike"></el-button>
-
- </div>
-
- <!-- 评论区 -->
- <div id="commentListShow">
- <el-card class="box-card">
- <div slot="header" class="clearfix">
- <span>评论详情</span>
- </div>
- <div id="commentInputArea">
-
- <el-input type="textarea" placeholder="请您输入友善的评论吧" v-model="textarea" maxlength="300"
- show-word-limit id="inputFrame" :clearable="clearAble" resize="none">
- </el-input>
- <div style="margin-top: 10px; padding-bottom: 50px;">
- <el-button type="primary" @click="SubmitComment">发表评论</el-button>
- <el-button type="primary" @click="CancelComment">取消评论</el-button>
- </div>
- </div>
-
- <div id="commentList">
- <div class="comment-card" v-for="comment in comments" :key="comment.id">
- <div class="comment-head">
- <h1 class="username">{{ comment.account }}</h1>
- <p class="created-at">发表于:{{ comment.createdAt }}</p>
- </div>
- <el-divider></el-divider>
- <p class="comment-text">{{ comment.commentText }}</p>
- </div>
- </div>
-
- </el-card>
- </div>
-
-
- </div>
- </template>

script:
- <script>
- import axios from 'axios';
- import Cookies from 'js-cookie';
-
-
- export default{
- data() {
- return {
- postId: '',
- title: '',
- content: '',
- value1: null,
- textarea: '',
- userId:'',
- clearAble: true,
- comments:{},
- author:'',
- createAt:'',
- heatValue:'',
- }
- },
- created() {
-
- this.postId = this.$route.params.postId;
- this.fetchPostDetail(this.$route.params.postId);
- this.userId = Cookies.get('userId');
- },
- mounted() {
- this.readComment();
-
- },
- methods: {
- // 前端实现路径传参
- async fetchPostDetail(postId) {
- try {
- this.fullscreenLoading = true;
- const url = `/api/forum/post/${postId}`;
- // 发起GET请求
- const response = await axios.get(url);
-
- if (response.status === 200) {
- // 请求成功,处理响应数据
- const postData = response.data;
- console.log('文章详情:', postData);
- // 更新组件状态或执行其他操作
- this.title = response.data.data.title;
- this.content = response.data.data.content;
- this.author = response.data.data.account;
- this.createAt = response.data.data.createdAt;
- this.heatValue = response.data.data.heatValue;
- this.fullscreenLoading = false;
- } else {
- console.error('请求失败,状态码:', response.status);
- }
- } catch (error) {
- console.error('请求错误:', error);
- }
- },
-
- getBackToForum() {
- this.$router.push({ name: 'forum' });
- },
-
-
- // 取消评论
- CancelComment(){
- this.textarea = '';
-
- },
-
- // 执行点赞按钮
- PostLike(){
- this.isLogin();
- axios.get('/api/forum/like',{
- params:{
- postId : this.postId,
- userId : this.userId
- }
- }).then((response)=>{
- this.MessageNotify(response);
- })
- },
-
- // 执行收藏按钮
- PostFavorite(){
- this.isLogin();
- axios.get('/api/forum/favorite',{
- params:{
- postId : this.postId,
- userId : this.userId
- }
- }).then((response)=>{
- this.MessageNotify(response);
- })
-
-
- },
- SubmitComment(){
-
- this.isLogin();
-
- axios.post('/api/forum/writeComment',{
- postId : this.postId,
- userId : this.userId,
- commentText : this.textarea
- }).then((response)=>{
- this.MessageNotify(response);
- this.textarea = '';
- this.readComment();
- })
-
- console.log("submit");
- },
-
- isLogin(){
- if(Cookies.get('userId') == null){
- this.$message.error('请先登录');
- return;
- }
- },
-
- // 消息提醒
- MessageNotify(response){
- if(response.data.code == 200){
- this.$message.success(response.data.data);
- }else{
- console.log(response.data);
- this.$message.error(response.data.message);
- }
- },
-
- readComment(){
- axios.get('/api/forum/getComment',{
- params:{
- postId : this.postId
- }
- }).then((response)=>{
- this.comments = response.data.data;
- })
- },
-
-
- }
-
- }
-
-
- </script>

css:
html:
- <template>
- <div id="layout">
-
- <div id="searchFrame">
- <div id="InputFrame">
- <el-input type="textarea" placeholder="请输入内容" v-model="textarea" rows="1" resize="none"
- style="font-size: larger; width: 80%;">
- </el-input>
- <el-button type="warning" @click="SearchSubmit" icon="el-icon-search">查询</el-button>
- </div>
- </div>
-
- <div id="excess">
-
- <div id="Interate">
- <i class="el-icon-search"> 搜索结果</i>
- </div>
-
- </div>
-
-
- <div id="SearchContent">
-
- <div v-if="posts.length === 0">
- <el-empty :image-size="200"></el-empty>
- </div>
-
-
-
- <div class="custom-card" v-for="(post, index) in posts" :key="index" @click="getForumPostDetail(post.id)">
- <div class="card-content">
- <h1 class="card-title">标题: {{ post.title }}</h1>
- <div class="card-meta">
- <span>作者: {{ post.account }}</span>
- <span>标签: {{ post.tag }}</span>
- <span><i class="el-icon-view">{{ post.heatValue }}</i></span>
- </div>
- <div class="card-rating">
- <span>文章评分:</span>
- <el-rate v-model="post.rating" disabled show-score text-color="#ff9900" score-template="{value}"
- style="display: inline-block;"></el-rate>
- </div>
- </div>
- </div>
- </div>
-
-
- </div>
- </template>

script:
- <script>
- import axios from 'axios';
-
-
- export default {
- data() {
- return {
- textarea: '',
- searchKeyWord: '',
- posts: [],
- }
- },
-
- methods: {
- SearchSubmit() {
- console.log(this.textarea);
- axios.get('/api/forum/search', {
- params: {
- searchKeyWord: this.textarea
- }
- }).then((response) => {
-
- if (response.data.code !== 200) {
- this.$notify({
- title: '警告',
- message: '搜索失败',
- type: 'warning'
- });
- }
-
- console.log(response.data.data);
- this.posts = response.data.data;
- });
- },
-
-
- Search() {
-
- axios.get('/api/forum/search', {
- params: {
- searchKeyWord: this.searchKeyWord
- }
- }).then((response) => {
-
- if (response.data.code !== 200) {
- this.$notify({
- title: '警告',
- message: '搜索失败',
- type: 'warning'
- });
- }
-
- console.log(response.data.data);
- this.posts = response.data.data;
- });
- },
-
- // 跳转到文章详情
- getForumPostDetail(postId) {
- console.log("getForumPostDetail");
- console.log(postId);
- this.$router.push(`/post/${postId}`);
- },
-
-
-
- },
-
- mounted() {
- this.searchKeyWord = this.$route.params.searchKeyWord;
- this.textarea = this.searchKeyWord;
- this.Search();
- }
-
- }
- </script>

css:
- <style scoped>
- #layout {
- width: 100%;
- min-height: 90%;
- background-color: rgb(245, 246, 247);
- line-height: normal;
- }
-
- #SearchContent{
- min-height: 800px;
-
-
- }
-
- #searchFrame {
- height: 70px;
- width: 100%;
- background-color: white;
- box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
- position: -webkit-sticky;
- /* Safari */
- position: sticky;
- top: 0;
- z-index: 1000;
- line-height: normal;
- }
-
- #InputFrame {
- width: 40%;
- margin: 0 auto;
- height: 60%;
- padding-top: 15px;
- }
-
- #Interate {
-
- float: left;
- margin-top: 20px;
- margin-left: 20px;
- }
-
- #excess {
-
- height: 61px;
- width: 80%;
- background-color: white;
- margin: 0 auto;
- margin-top: 25px;
- border: 1px solid rgb(245, 245, 245);
- border-radius: 4px;
- }
-
-
-
- .custom-card {
- background-color: #ffffff;
- border-radius: 4px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
- margin-bottom: 16px;
- transition: box-shadow 0.3s ease-in-out;
- width: 80%;
- margin: 0 auto;
-
- border: 1px solid rgb(245, 245, 245);
- }
-
- .custom-card:hover {
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
- cursor: pointer;
- background-color: rgb(245, 245, 245);
- }
-
- .card-content {
- padding: 16px;
- }
-
- .card-title {
- font-size: 1.2em;
- margin-bottom: 8px;
- color: #333;
- }
-
- .card-meta {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 12px;
- color: #666;
- }
-
- .card-rating {
- color: #666;
- }
-
- .card-rating {
- color: #666;
- }
- </style>

- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- <scope>compile</scope>
- </dependency>
-
- <dependency>
- <groupId>com.mysql</groupId>
- <artifactId>mysql-connector-j</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <optional>true</optional>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mybatis.spring.boot</groupId>
- <artifactId>mybatis-spring-boot-starter</artifactId>
- <version>2.3.1</version>
- </dependency>
-
- <dependency>
- <groupId>cn.hutool</groupId>
- <artifactId>hutool-all</artifactId>
- <version>5.8.11</version>
- </dependency>
-
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>mybatis-plus-boot-starter</artifactId>
- <version>3.5.3.1</version>
- </dependency>
-
- <!--swagger-->
- <dependency>
- <groupId>com.github.xiaoymin</groupId>
- <artifactId>knife4j-spring-boot-starter</artifactId>
- <version>3.0.2</version>
- </dependency>
-
- <!--web-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>5.3.15</version>
- </dependency>
- <dependency>
- <groupId>io.springfox</groupId>
- <artifactId>springfox-spring-web</artifactId>
- <version>3.0.0</version>
- </dependency>
-
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>fastjson</artifactId>
- <version>1.2.76</version>
- </dependency>
-
- <!-- https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java -->
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>dashscope-sdk-java</artifactId>
- <version>2.8.2</version>
- </dependency>
- <!--okhttp3 依赖-->
- <dependency>
- <groupId>com.squareup.okhttp3</groupId>
- <artifactId>okhttp</artifactId>
- <version>4.9.3</version>
- </dependency>
-
- <!-- Lombok dependency -->
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <optional>true</optional>
- </dependency>
-
- <!-- 验证码模块-->
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <version>3.12.0</version>
- </dependency>

- public class Result<T> {
- // 状态码常量
- public static final int SUCCESS = 200;
- public static final int ERROR = 500;
-
- private int code; // 状态码
- private String message; // 消息
- private T data; // 数据
-
- // 构造函数,用于创建成功的结果对象
- private Result(int code, String message, T data) {
- this.code = code;
- this.message = message;
- this.data = data;
- }
-
- // 成功结果的静态方法
- public static <T> Result<T> success(T data) {
- return new Result<>(SUCCESS, "Success", data);
- }
-
-
- // 错误结果的静态方法
- public static <T> Result<T> error(String message) {
- return new Result<>(ERROR, message, null);
- }
-
- // 错误结果的静态方法,可以传入自定义的状态码
- public static <T> Result<T> error(int code, String message) {
- return new Result<>(code, message, null);
- }
-
- // 获取状态码
- public int getCode() {
- return code;
- }
-
- // 设置状态码
- public void setCode(int code) {
- this.code = code;
- }
-
- // 获取消息
- public String getMessage() {
- return message;
- }
-
- // 设置消息
- public void setMessage(String message) {
- this.message = message;
- }
-
- // 获取数据
- public T getData() {
- return data;
- }
-
- // 设置数据
- public void setData(T data) {
- this.data = data;
- }
-
- // 用于转换为Map类型的方法,方便序列化为JSON
- public Map<String, Object> toMap() {
- Map<String, Object> map = new HashMap<>();
- map.put("code", code);
- map.put("message", message);
- map.put("data", data);
- return map;
- }
- }

Entity:
Forumpost:
- @TableName(value ="forum_posts")
- @Data
- public class ForumPosts implements Serializable {
- /**
- *
- */
- @TableId(value = "id", type = IdType.AUTO)
- private Integer id;
- /**
- *
- */
- @TableField(value = "title")
- private String title;
- /**
- *
- */
- @TableField(value = "content")
- private String content;
- /**
- *
- */
- @TableField(value = "author_id")
- private Integer authorId;
- /**
- *
- */
- @TableField(value = "created_at")
- private LocalDateTime createdAt;
- /**
- *
- */
- @TableField(value = "updated_at")
- private LocalDateTime updatedAt;
- /**
- *
- */
- @TableField(value = "heat_value")
- private Integer heatValue;
- /**
- *
- */
- @TableField(value = "rating")
- private BigDecimal rating;
- /**
- *
- */
- @TableField(value = "tag")
- private String tag;
-
- @TableField(exist = false)
- private static final long serialVersionUID = 1L;
-
- @Override
- public boolean equals(Object that) {
- if (this == that) {
- return true;
- }
- if (that == null) {
- return false;
- }
- if (getClass() != that.getClass()) {
- return false;
- }
- ForumPosts other = (ForumPosts) that;
- return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
- && (this.getTitle() == null ? other.getTitle() == null : this.getTitle().equals(other.getTitle()))
- && (this.getContent() == null ? other.getContent() == null : this.getContent().equals(other.getContent()))
- && (this.getAuthorId() == null ? other.getAuthorId() == null : this.getAuthorId().equals(other.getAuthorId()))
- && (this.getCreatedAt() == null ? other.getCreatedAt() == null : this.getCreatedAt().equals(other.getCreatedAt()))
- && (this.getUpdatedAt() == null ? other.getUpdatedAt() == null : this.getUpdatedAt().equals(other.getUpdatedAt()))
- && (this.getHeatValue() == null ? other.getHeatValue() == null : this.getHeatValue().equals(other.getHeatValue()))
- && (this.getRating() == null ? other.getRating() == null : this.getRating().equals(other.getRating()))
- && (this.getTag() == null ? other.getTag() == null : this.getTag().equals(other.getTag()));
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
- result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode());
- result = prime * result + ((getContent() == null) ? 0 : getContent().hashCode());
- result = prime * result + ((getAuthorId() == null) ? 0 : getAuthorId().hashCode());
- result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode());
- result = prime * result + ((getUpdatedAt() == null) ? 0 : getUpdatedAt().hashCode());
- result = prime * result + ((getHeatValue() == null) ? 0 : getHeatValue().hashCode());
- result = prime * result + ((getRating() == null) ? 0 : getRating().hashCode());
- result = prime * result + ((getTag() == null) ? 0 : getTag().hashCode());
- return result;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append(getClass().getSimpleName());
- sb.append(" [");
- sb.append("Hash = ").append(hashCode());
- sb.append(", id=").append(id);
- sb.append(", title=").append(title);
- sb.append(", content=").append(content);
- sb.append(", authorId=").append(authorId);
- sb.append(", createdAt=").append(createdAt);
- sb.append(", updatedAt=").append(updatedAt);
- sb.append(", heatValue=").append(heatValue);
- sb.append(", rating=").append(rating);
- sb.append(", tag=").append(tag);
- sb.append(", serialVersionUID=").append(serialVersionUID);
- sb.append("]");
- return sb.toString();
- }
- }

ForumPostLike:
- @Data
-
- @TableName(value ="forum_post_likes")
-
- public class ForumPostLike {
-
- private int userId;
-
- private int postId;
-
-
- }
ForumPostFavorites:
- @Data
- @TableName(value ="forum_post_favorites")
- public class ForumPostFavorites {
-
- private int userId;
-
- private int postId;
-
- }
ForumComments
- @TableName(value ="forum_comments")
- @Data
- public class ForumComments implements Serializable {
- /**
- *
- */
- @TableId(value = "id", type = IdType.AUTO)
- private Integer id;
-
- /**
- *
- */
- @TableField(value = "post_id")
- private Integer postId;
-
- /**
- *
- */
- @TableField(value = "user_id")
- private Integer userId;
-
- /**
- *
- */
- @TableField(value = "comment_text")
- private String commentText;
-
- /**
- *
- */
- @TableField(value = "created_at")
- private LocalDateTime createdAt;
-
- @TableField(exist = false)
- private static final long serialVersionUID = 1L;
-
- @Override
- public boolean equals(Object that) {
- if (this == that) {
- return true;
- }
- if (that == null) {
- return false;
- }
- if (getClass() != that.getClass()) {
- return false;
- }
- ForumComments other = (ForumComments) that;
- return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
- && (this.getPostId() == null ? other.getPostId() == null : this.getPostId().equals(other.getPostId()))
- && (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId()))
- && (this.getCommentText() == null ? other.getCommentText() == null : this.getCommentText().equals(other.getCommentText()))
- && (this.getCreatedAt() == null ? other.getCreatedAt() == null : this.getCreatedAt().equals(other.getCreatedAt()));
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
- result = prime * result + ((getPostId() == null) ? 0 : getPostId().hashCode());
- result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode());
- result = prime * result + ((getCommentText() == null) ? 0 : getCommentText().hashCode());
- result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode());
- return result;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append(getClass().getSimpleName());
- sb.append(" [");
- sb.append("Hash = ").append(hashCode());
- sb.append(", id=").append(id);
- sb.append(", postId=").append(postId);
- sb.append(", userId=").append(userId);
- sb.append(", commentText=").append(commentText);
- sb.append(", createdAt=").append(createdAt);
- sb.append(", serialVersionUID=").append(serialVersionUID);
- sb.append("]");
- return sb.toString();
- }
- }

DTO:
- @Data
- public class CommentDTO {
-
-
- private int userId;
-
- private int postId;
-
- private String commentText;
-
-
- }
- @Data
- public class ForumAddPostDTO {
-
- @JsonProperty("title")
- private String title;
-
- @JsonProperty("content")
- private String content;
-
- @JsonProperty("authorId")
- private Integer authorId;
-
- @JsonProperty("tag")
- private String tag;
- }
VO:
- @Data
- public class ArticleVO {
-
- private String title;
-
- private String content;
-
- private String account;
-
- private Integer heatValue;
-
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- private LocalDateTime createdAt;
-
- }
- @Data
- public class CommentVo {
-
- private int id;
-
- private String commentText;
-
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- private LocalDateTime createdAt;
-
- private String account;
- }
- @Data
- public class LikeSearchVo {
- private String value;
- }
- public class BaseException extends RuntimeException{
-
- public BaseException(){
- }
- public BaseException(String msg){
- super(msg);
- }
-
- }
- public class NotFoundArticleException extends BaseException{
- public NotFoundArticleException(String msg){
- super(msg);
- }
-
- }
- public class AlreadyLikeException extends BaseException{
-
- public AlreadyLikeException(String msg){
- super(msg);
- }
-
-
- }
全局异常处理类:
- @RestControllerAdvice
- @Slf4j
- public class GlobalExceptionHandler {
-
- @ExceptionHandler
- public Result exceptionHandler(BaseException ex){
- log.error("异常信息:{}", ex.getMessage());
- return Result.error(ex.getMessage());
- }
-
- }
1.ForumPostController
- @RequestMapping("/forum")
- @RestController
- @Api(tags = "文章管理")
- @Slf4j
- public class ForumPostController {
-
- @Autowired
- ForumPostsService forumPostsService;
-
- @Autowired
- UserService userService;
-
- @Autowired
- ForumCommentsService forumCommentsService;
-
-
-
-
- @ApiOperation("新增文章")
- @PostMapping("/add")
- public Result addForumPost(@RequestBody ForumAddPostDTO forumAddPostDTO) throws ParseException {
- ForumPosts forumPosts = new ForumPosts();
- BeanUtils.copyProperties(forumAddPostDTO, forumPosts);
- forumPostsService.save(forumPosts);
- return Result.success("新增成功");
- }
-
-
- @GetMapping("/getAllForumPost")
- @ApiOperation("推荐文章查询")
- public Result getAllForumPost(@RequestParam(value="pageSize", defaultValue = "10") int pageSize,
- @RequestParam(value="pageNumber", defaultValue = "1") int pageNumber){
-
-
- Page<ForumPosts> page = new Page<>(pageNumber, pageSize);
- // 创建查询包装器并指定排序规则
- QueryWrapper<ForumPosts> queryWrapper = new QueryWrapper<>();
- // 假设你想按照创建时间降序排序
- queryWrapper.orderByDesc("created_at");
- Page<ForumPosts> paged = forumPostsService.page(page,queryWrapper);
- List<ForumPosts> postsList = paged.getRecords();
- List<ForumPageVO> posts = new ArrayList<>();
-
-
- for (ForumPosts post : postsList) {
- ForumPageVO vo = new ForumPageVO();
- // 获取账户信息
- User user = userService.getById(post.getAuthorId());
- vo.setAccount(user.getAccount());
-
- // 直接从ForumPosts对象复制其他字段
- vo.setTag(post.getTag());
- vo.setRating(post.getRating()); // 如果需要字符串形式
- vo.setTitle(post.getTitle());
- vo.setPostId(post.getId());
- vo.setHeat_value(post.getHeatValue());
- // 添加到列表
- posts.add(vo);
- }
-
-
- return Result.success(posts);
-
- }
-
-
- // 文章阅读
- @ApiOperation("读取文章")
- @GetMapping("post/{id}")
- public Result<ArticleVO> readArtical(@PathVariable int id){
- ArticleVO articleVO = forumPostsService.readArticle(id);
- return Result.success(articleVO);
- }
-
-
- // 我的文章功能
- @ApiOperation("我的文章")
- @GetMapping("/MyArticle")
- public Result getMyArticle(@Param("id") int id){
- List<ForumPosts> forumPostsList = forumPostsService.getByAuthorId(id);
- return Result.success(forumPostsList);
- }
-
- // 热门文章功能
- @ApiOperation("热门文章")
- @GetMapping("/getHotPosts")
- public Result getHotPosts(){
- QueryWrapper<ForumPosts> queryWrapper = new QueryWrapper();
- queryWrapper.orderByDesc("heat_value");
- List<ForumPosts> forumPosts = forumPostsService.list(queryWrapper);
- return Result.success(forumPosts);
- }
-
- // 热门文章功能
- @ApiOperation("优质文章")
- @GetMapping("/getOutStandPosts")
- public Result getOutStandPosts(){
-
- QueryWrapper<ForumPosts> queryWrapper = new QueryWrapper();
- queryWrapper.orderByDesc("rating");
- List<ForumPosts> forumPosts = forumPostsService.list(queryWrapper);
- return Result.success(forumPosts);
- }
-
-
- // 我的收藏
- @ApiOperation("我的收藏")
- @GetMapping("/getMyFavorite")
- public Result getMyFavorite(@Param("id") int id){
-
- List<ForumPosts> forumPostsList = forumPostsService.getMyFavorite(id);
-
- return Result.success(forumPostsList);
- }
-
-
- // 文章查询
- @ApiOperation("文章查询")
- @GetMapping("/search")
- public Result postSearch(@RequestParam("searchKeyWord") String searchText){
-
- if (searchText == null){
- return Result.error("不能输入为空噢");
- }
- LambdaQueryWrapper<ForumPosts> lambdaQueryWrapper = new LambdaQueryWrapper<>();
-
- // TODO:通过LamdaQueryWrapper 模糊查询
- // 模糊查询title字段,%searchText%会被自动添加
- lambdaQueryWrapper.like(ForumPosts::getTitle, searchText);
-
- // 假设这里有一个service接口用于操作ForumPosts表
- List<ForumPosts> postsList = forumPostsService.list(lambdaQueryWrapper);
-
- // 根据你的Result类的具体实现,返回查询结果
- return Result.success(postsList);
- }
-
- /**
- * 标题模糊查询
- * @param keyword 关键词
- * @return 匹配的标题列表
- */
- @GetMapping("/getLikeSearch")
- @ApiOperation("标题模糊查询")
- public Result getLikeSearch(@RequestParam String keyword){
- List<LikeSearchVo> titles = forumPostsService.findTitlesByKeyword(keyword);
- return Result.success(titles);
- }
-
-
- // 用户交互
- // 点赞
- @ApiOperation("点赞")
- @GetMapping("/like")
- public Result PostLike(@RequestParam("postId") int postId,@RequestParam("userId") int userId){
- String result = forumPostsService.PostLike(postId,userId);
- return Result.success(result);
- }
-
- // 收藏
- @ApiOperation("收藏")
- @GetMapping("/favorite")
- public Result PostFavorite(@RequestParam("postId") int postId,@RequestParam("userId") int userId){
-
- String result = forumPostsService.PostFavorite(postId,userId);
-
- return Result.success(result);
- }
-
- // 写评论
- @ApiOperation("写评论")
- @PostMapping("/writeComment")
- public Result WriteComment(@RequestBody CommentDTO commentdto){
-
- ForumComments forumComments = new ForumComments();
- BeanUtils.copyProperties(commentdto,forumComments);
- forumCommentsService.save(forumComments);
- return Result.success("评论成功");
- }
-
-
- // 读评论
- @ApiOperation("读取评论")
- @GetMapping("/getComment")
- public Result<List<CommentVo>> GetComment(@RequestParam("postId") int postId){
- List<CommentVo> comment = forumCommentsService.getComment(postId);
- return Result.success(comment);
- }
-
-
- }

- public interface ForumPostsService extends IService<ForumPosts> {
-
- List<ForumPosts> getByAuthorId(Integer id);
-
- String PostLike(int postId, int userId);
-
- String PostFavorite(int postId, int userId);
-
- ArticleVO readArticle(int id);
-
- List<ForumPosts> getMyFavorite(int id);
-
- List<LikeSearchVo> findTitlesByKeyword(String keyword);
- }
- public interface ForumCommentsService extends IService<ForumComments> {
-
- List<CommentVo> getComment(int postId);
- }
- public interface ForumCommentsMapper extends BaseMapper<ForumComments> {
-
- }
- @Mapper
- public interface ForumPostFavoritesMapper extends BaseMapper<ForumPostFavorites> {
- }
- @Mapper
- public interface ForumPostLikeMapper extends BaseMapper<ForumPostLike> {
- }
- @Mapper
- public interface ForumPostsMapper extends BaseMapper<ForumPosts> {
-
-
- @Select("select * from paitool.user as a,paitool.forum_posts as b where a.id=b.author_id and a.id = #{id}")
- List<ForumPosts> getByAuthorId(Integer id);
-
-
- }
1.通过ElasticSearch优化搜索引擎
2.使用Redis存储热门文章,以减少数据库压力
3.通过若依框架+AI 完善管理系统
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。