【项目实战】vue+springboot项目使用富文本编辑器实现长文章发表和展示

本人前端烂,文章展示部分现在还弄的不好。
效果:
在这里插入图片描述

在这里插入图片描述
很想实现点击查看详情然后进入查看具体的文章内容,但还不知道怎么弄,有知道的兄弟可以教我一下。

首先npm下载:
cnpm install vue-quill-editor
发表日志模块:

<template>
  <div class="nn">

    <p id="p2" style="background-color:red;"><Icon type="md-paw" />发表长日志</p>

    <el-form ref="form" :model="form" label-width="80px">
      <el-form-item label="标题"><Icon type="md-water" />
        <el-input v-model="form.title"></el-input>
      </el-form-item>
      <el-form-item label="描述"><Icon type="md-text" />
        <el-input v-model="form.description"></el-input>
      </el-form-item>
      <el-form-item label="正文" style="color: #bd2c00;font-size: 10px"><Icon type="md-walk" />
        <quill-editor
            ref="myQuillEditor"
            class="editor"
            v-model="form.content"
            :options="editorOption"
            @blur="onEditorBlur($event)"
            @focus="onEditorFocus($event)"
            @ready="onEditorReady($event)"
        />
      </el-form-item>
      <Button type="primary" shape="circle" @click="submit"><Icon type="md-checkbox" />提交</Button>

    </el-form>
  </div>

</template>

<script>

import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'


import { quillEditor } from 'vue-quill-editor'
import axios from 'axios'

export default {
  components: { quillEditor },
  props: {},

  name: "About",
  data() {
    return {
      form: {
        title: '',
        description: '',
        content: '',
      },
      editorOption: {
        modules: {
          toolbar: [
            ['bold', 'italic', 'underline', 'strike'], //加粗,斜体,下划线,删除线
            ['blockquote', 'code-block'], //引用,代码块


            [{ header: 1 }, { header: 2 }], // 标题,键值对的形式;1、2表示字体大小
            [{ list: 'ordered' }, { list: 'bullet' }], //列表
            [{ script: 'sub' }, { script: 'super' }], // 上下标
            [{ indent: '-1' }, { indent: '+1' }], // 缩进
            [{ direction: 'rtl' }], // 文本方向


            [{ size: ['small', false, 'large', 'huge'] }], // 字体大小
            [{ header: [1, 2, 3, 4, 5, 6, false] }], //几级标题


            [{ color: [] }, { background: [] }], // 字体颜色,字体背景颜色
            [{ font: [] }], //字体
            [{ align: [] }], //对齐方式


            ['clean'], //清除字体样式
            // ['image', 'video'], //上传图片、上传视频
          ],
        },
        theme: 'snow',
      },
    }
  },
  methods:{
  submit() {
    if (!this.form.title) {
      this.$message('请输入标题')
    }
    if (!this.form.description) {
      this.$message('请输入描述')
    }
    if (!this.form.content) {
      this.$message('请输入正文')
    }
    this.$refs.form.validate(async valid => {
      const {data: res} = await this.$http.post("addarticle", this.form);
      if (res != "ok") {

        return this.$message.error("操作失败!!!");
      }
      this.$message.success("操作成功!!!");
    })

  },
},

}
</script>

<style scoped>

#p2{font-style:italic;
  color: #03FCA1;
margin-left: 440px;
height: 70px;
width: 100px}
.editor {
  height: 500px;
}
.btn {
  margin-top: 100px;
}
.nn{
  background-color: #b2dba1;
}
</style>

文章详情:

<template>
  <div class="">
    <h1 style="margin-left: 300px"><Icon type="md-bookmarks" />文章详情</h1>
    <div><Icon type="md-bookmarks" />{{total}}条</div>



    <el-col v-for="(item, index) in detail" :key="index" :span="4" style="min-width:250px">
      <div class="grid-content bg-purple">
        <el-card class="box-card">

          <div class="title"  style="padding: 14px;"><Icon type="md-cube" />标题{{item.title}}</div>


          <div class="des"><Icon type="ios-fastforward" />描述{{ item.description }}</div>
          <Icon type="ios-ice-cream-outline" />内容:<div class="con" v-html="item.content"></div>
          <div>{{look[index]}}</div>
          <el-button @click="active(index)">查看详情</el-button>
          <div>{{look[index]}}</div>
          <div class="time" style="color: #DD4A68"><Icon type="logo-octocat" />创建时间:{{ item.createdatetime }}</div>

        </el-card>
      </div>
    </el-col>





  </div>
</template>

<script>
export default {
name: "Detail",
  data() {
    return {
      look:['0','0','0'],
      total:'',
      detail: [],
      pagination: { //分页后的留言列表
        current: 1, //当前页
        total: null, //记录条数
        size: 10 //每页条数
      },
    }
  },
  created() {
    this.getMsg()
  },
  methods: {
    handleSizeChange(newSize) {
      this.queryInfo.pageSize = newSize;
      this.getMsg(); // 数据发生改变重新申请数据
    },
    // 监听pageNum改变的事件
    handleCurrentChange(newPage) {
      this.queryInfo.pageNum = newPage;
      this.getMsg(); // 数据发生改变重新申请数据
    },

    async getMsg() {
      const { data: res } = await this.$http.get("AllPage");
      console.log(res.data)
      this.detail = res.data; // 将返回数据赋值
      this.total = res.numbers; // 总个数

    },
    active(index){
      console.log(index)
      this.look[index]='1'
    }
  }
}
</script>

<style scoped>
.title {
  font-weight: bold;
  font-size: 16px;
  text-align: left;
  margin-bottom: 10px;
}
.des {
  font-size: 14px;
  text-align: left;
  margin-bottom: 10px;
}
.con {
  font-size: 14px;
  text-align: left;
  margin-bottom: 10px;
}
.time {
  font-size: 14px;
  text-align: left;
}

</style>

后端:

DROP TABLE IF EXISTS `t_article`;
CREATE TABLE `t_article` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL,
  `content` varchar(4550) DEFAULT NULL,
  `createdatetime` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Java文件:
Controller


@RestController

@CrossOrigin
public class ArticleEditController {


        @Autowired
private ArticleService articleService;
        @ApiOperation(value="添加文章")
        @PostMapping("/addarticle")
        public String addarticle(@RequestBody  Article vo)
        {
            System.out.println("添加文字");
            try
            {
articleService.insert(vo);
                ApiResult apiResultHandler  = new ApiResult();
                apiResultHandler.setCode(200);
                return "ok";
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            return "no";}

        @PostMapping("/loadPage")

        public Object loadPage(String title)
        {
            System.out.println("按照内容查找文章");
            List<Article>articles = articleService.findByCondit(title);
            HashMap<String, Object> res = new HashMap<>();
            int numbers = articles.size();
            res.put("numbers",numbers);
            res.put("data",articles);
            String users_json = JSON.toJSONString(res);
            return users_json;

        }

    @GetMapping("/AllPage")
    public Object AllPage(QueryInfo queryInfo){
        System.out.println("查所有文章");
        ApiResult apiResult;
        System.out.println(queryInfo);
        int numbers = articleService.findAll().size();// 获取数据总数
        int pageStart = (queryInfo.getPageNum()-1)*queryInfo.getPageSize();
     //   Page<Article> articlePage = new Page<>(page,size);
        List<Article> all = articleService.findAll();
        apiResult = ApiResultHandler.buildApiResult(200, "请求成功!", all);
        HashMap<String, Object> res = new HashMap<>();
;
        res.put("numbers",numbers);
        res.put("data",all);
        return res;
    }
    }


实体类:

@Data
@ApiModel(value="发布文章", description="发布文章")
public class Article implements Serializable
{
    private static final long serialVersionUID = 1L;
  
    private int Id;
    private String title;
    private String description;
   
    private String content;
    
    @JsonFormat(pattern="yyyy-MM-dd HH:mm", timezone="GMT+8")
    private Timestamp createdatetime;
  
    @Override
    public String toString() {
        return "Article [id=" + Id + ", title=" + title + ", description=" + description + ", content=" + content
                + ", articletype=" +  ", createdatetime=" + createdatetime + "]";
    }
}

用注解的方式写Sql:

package com.naughty.userlogin02.dao;

import com.naughty.userlogin02.bean.Article;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper
public interface ArticleDao
{
    @Options(useGeneratedKeys = true,keyProperty = "Id")
   @Insert("insert into t_article(title,description,content,createdatetime)\n" +
           "                values (#{title},#{description},#{content},#{createdatetime}) ")
void save(Article vo);

        @Select("select title,description,content,createdatetime from t_article where title=#{title}")
        List<Article> findByCondit(String title);
        @Select("select title,description,content,createdatetime from t_article")
        List<Article> findAll();

}

service:

import java.util.List;

public interface ArticleService {
    void insert(Article vo);
    List<Article> findByCondit(String title);

    List<Article> findAll();


}


import java.util.Date;
import java.util.List;

@Service
@Transactional
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private ArticleDao articleDao;

    @Override
    public void insert(Article vo) {
        vo.setCreatedatetime(new Timestamp(new Date().getTime()));

        articleDao.save(vo);
    }

    @Override
    public  List<Article> findAll(){
        List<Article> articles2 = articleDao.findAll();
        return articles2;
    };
    @Override
   public List<Article> findByCondit(String title) {

        List<Article> articles = articleDao.findByCondit(title);
        return articles;
    }
}

注:关于注解@Transactional
事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。
Spring Framework对事务管理提供了一致的抽象,其特点如下:

为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects)
支持声明式事务管理,特别是基于注解的声明式事务管理,简单易用
提供比其他事务API如JTA更简单的编程式事务管理API
与spring数据访问抽象的完美集成
事务管理方式

spring支持编程式事务管理和声明式事务管理两种方式。

编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。

声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。

声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值