Element框架实现后台管理系统的业务逻辑(首页嵌套发布文章),面包屑、卡片、富文本、文件上传

74 篇文章 3 订阅

实现后台管理系统的业务逻辑(登录页)
实现后台管理系统的业务逻辑(首页)

一、配置子路由

{
            name: 'index',
            path: '/index',
            // 异步引入组件
            component: () => import('@/views/index.vue'),
            redirect: { name: 'postList' },
            children: [ {
                    name: 'PostPublish',
                    path: 'PostPublish',//无需添加斜杠
                    component: () => import('@/views/PostPublish.vue')
                },
            ]
        },

二、创建组件并在首页设置跳转路由

创建单独的发布文章组件PostPublish.vue,并在首页左侧二级菜单的index设置路由跳转.

<template>
  <div class="PostPublish">文章发布</div>
</template>
<el-menu-item index="PostPublish">
     <i class="el-icon-user"></i>
     <span>文章发布</span>
   </el-menu-item>

效果
在这里插入图片描述

三、发布文章组件

需要用到的element组件:
1.Breadcrumb 面包屑
2.Card 卡片
3.Button 按钮
4.Form 表单
5.Radio 单选框
5.Upload 上传
富文本框:富文本框下载及解说

3.1插入面包屑组件

 <!-- 路径导航 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/index' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>文章管理</el-breadcrumb-item>
      <el-breadcrumb-item>文章发布</el-breadcrumb-item>
    </el-breadcrumb>

3.1.1面包屑效果

在这里插入图片描述

3.2卡片视图

<!-- 卡片视图 -->
    <el-card class="box-card" style="margin-top: 20px"> </el-card>

3.3定义数据

发布文章基本的就是收集数据,那在最初就先把需要的参数设置好

export default {
  data() {
    return {
      postFrom: {
        title: "", //文章标题
        content: "", //文章内容
        categories: [], //所属栏目id集合
        cover: [], //封面图片id集合
        type:1, //1为文章,2为视频,默认选文章
      },
    };
  },
};

3.4收集标题数据

卡片内填写代码,将from表单包裹input,:model动态绑定数据对象,点击按钮获取数据

 <!-- 卡片视图 -->
    <el-card class="box-card" style="margin-top: 20px">
      <!--from表单包裹 -->
      <!-- :model:绑定的数据 -->
      <el-form ref="postFrom" :model="postFrom" label-width="80px">
        <!-- 标题 -->
        <el-form-item label="标题">
          <el-input v-model="postFrom.title"></el-input> </el-form-item
      ></el-form>
      <!-- 类型 -->
      <!-- 内容 -->
      <!-- 栏目 -->
      <!-- 封面 -->
      <!-- 按钮 -->
      <!-- 点击发送事件 -->
      <el-button type="success" @click="publishPost">发布文章</el-button>
    </el-card>
 methods: {
    publishPost() {
      console.log(this.postFrom);
    },
  },

3.4.1标题数据效果

在这里插入图片描述

3.5收集类型数据

v-model:是当前被选中的单选按钮的label,得定义一个变量进行存储,后期等
用户选中单选按钮的时候,就会将这个被选中的单选按钮label值赋值给v-model所绑定的属性.

 <!-- 类型 -->
        <!-- v-model:是当前被选中的单选按钮的label,得定义一个变量进行存储,后期等
        用户选中单选按钮的时候,就会将这个被选中的单选按钮label值赋值给v-model所绑定的属性 -->
        <el-form-item label="类型">
          <el-radio-group v-model="postFrom.type">
            <el-radio :label="1">文章</el-radio>
            <el-radio :label="2">视频</el-radio>
          </el-radio-group>
        </el-form-item>

3.5.1类型数据效果

在这里插入图片描述

3.6收集文章内容数据

3.6.1富文本框下载安装

npm install vue-word-editor --save
地址:https://github.com/hsian/vue-word-editor

3.6.2引入富文本框

//引入富文本框
import VueEditor from "vue-word-editor";
import "quill/dist/quill.snow.css";

3.6.3注册富文本框

components: {
    VueEditor, //注册富文本框
  },

3.6.4使用富文本框

    <!-- 内容 -->
        <el-form-item label="内容">
          <!-- 使用富文本框 -->
          <!-- 给组件添加ref标识 -->
          <!-- v-if:类别为1才显示 -->
          <VueEditor
            :config="config"
            ref="vueEditor"
            v-if="postFrom.type == 1"
          />
          <!-- v-if:类别为2才显示 -->
          <!-- headers:传递token -->
          <!-- action:上传的地址,必传 -->
          <!-- file-list:当前用户所选择文件列表 -->
           <!-- on-success:视频上传成功之后调用钩子函数 -->
          <el-upload
            class="upload-demo"
            v-if="postFrom.type == 2"
            :headers="getToken()"
            :action="baseURL + '/upload'"
            :file-list="fileList"
            :on-success="onsuccess"
          >
            <el-button size="small" type="primary">点击上传</el-button>
            <div slot="tip" class="el-upload__tip">只能上传视频文件</div>
          </el-upload>
        </el-form-item>

3.6.5在data中引入必要属性

上传文件需要验证用户信息,意味着需要拦截器.
但几乎所有框架都不会用用户封装的拦截器,因为它们自己封装了内部请求,意味着我们添加的拦截器不会经过,所以需要自己设置请求头(header)进行token的传递.
因为图片跟视频都需要用信息,所以做了个简单封装
图片路径为选择的图片在服务器上的路径
需要做的是:
1.将图片上传到服务器
2.接收服务器返回的地址
3.填充

      baseURL: axios.defaults.baseURL, //http://localhost:3000
      fileList: [],
   //   富文本框的必要配置
      config: {
        // 上传图片的配置
        uploadImage: {
          url: axios.defaults.baseURL + "/upload", //文章上传的服务器端的处理路径
          //    url: "http://localhost:3000/upload",
          name: "file", //后台所需要的参数名称
          //请求头
          headers: this.getToken(),
          // res是结果,insert方法会把内容注入到编辑器中,res.data.url是资源地址
          uploadSuccess(res, insert) {
            //文件上传成功之后的回调
            insert(axios.defaults.baseURL + res.data.data.url);
            //  insert("http://localhost:3000" + res.data.data.url)
            console.log(res, insert);
          },
        },

        // 上传视频的配置
        uploadVideo: {
          url: axios.defaults.baseURL + "/upload",
          //    url: "http://localhost:3000/upload",
          name: "file",
          uploadSuccess(res, insert) {
            insert(axios.defaults.baseURL + res.data.url);
            //  insert("http://localhost:3000" + res.data.data.url)
          },
        },
      },
 methods: {
    publishPost() {
      // 如果类型为文章, 那将标识为vueEditor的文本框内容赋值给content;
      if (this.postFrom.type == 1) {
        this.postFrom.content = this.$refs.vueEditor.editor.root.innerHTML;
      }
      console.log(this.postFrom);
    },
    getToken() {
      return {
        //   获取存储的token
        Authorization: JSON.parse(localStorage.getItem("usermanager")).token,
      };
    },
    // 视频上传成功之后调用钩子函数
    onsuccess(response, file, fileList) {
      console.log(response, file, fileList);
      if (response.message == "文件上传成功") {
        //类型为视频的时候,content中存储的内容就是视频在服务器中的全路径
        this.postFrom.content = axios.defaults.baseURL + response.data.url;
      }
    },
  },

3.6.6富文本框文字效果

在这里插入图片描述

3.6.7富文本框图片文件上传效果

在这里插入图片描述
在这里插入图片描述

3.6.8富文本框视频文件上传效果

在这里插入图片描述

3.7封面处理

1.on-exceed限制最大三张图片,超出给提示
2.limit:限制图片个数
3.上传成功后返回图片路径
4.处理细节,选中图片删除后要把数据也一并删除

  <!-- 封面 -->
        <!-- list-type:文件列表的类型 -->
        <!-- limit:	最大允许上传个数 -->
        <!-- on-exceed:文件超出个数限制时的钩子 -->
        <!-- on-preview:点击文件列表中已上传的文件时的钩子 -->
        <!-- on-remove:文件列表移除文件时的钩子 -->
        <el-form-item label="封面">
          <el-upload
            :action="baseURL + '/upload'"
            :headers="getToken()"
            list-type="picture-card"
            :limit="3"
            :on-exceed="handleExceed"
            :on-preview="handlePictureCardPreview"
            :on-success="onPosterSucess"
            :on-remove="onPosterRemove"
          >
            <i class="el-icon-plus"></i>
          </el-upload>
          <el-dialog :visible.sync="dialogVisible">
            <img width="100%" :src="userimg" alt="" />
          </el-dialog>
        </el-form-item>

date里添加

 dialogVisible: false,
      userimg: "",

methods里添加

 //移出封面:重点是将对用的图片数据从postFrom.cover移出
    //file:当前移出的
    //fileList:现在还保留的
    onPosterRemove(file, fileList) {
      let id = file.response.data.id;
      for (let i = 0; i < this.postFrom.cover.length; i++) {
        if (this.postFrom.cover[i].id == id) {
          this.postFrom.cover.splice(i, 1);
          break;
        }
      }
    },
  //处理图片上传后操作
    onPosterSucess(response) {
      console.log(response);
      if (response.message == "文件上传成功") {
        this.postFrom.cover.push({ id: response.data.id });
      }
    },
    //实现封面的预览
    handlePictureCardPreview(file) {
      console.log(file);
      this.userimg = file.url;
      this.dialogVisible = true;
    },
    // 文件超出个数限制时的钩子
    handleExceed(files) {
      console.log(files);
      this.$message.warning("最多只能选择三张图片");
    },
3.7.1封面效果

在这里插入图片描述

四、发送文章组件全部代码

<template>
  <div class="PostPublish">
    <!-- 路径导航 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/index' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>文章管理</el-breadcrumb-item>
      <el-breadcrumb-item>文章发布</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 卡片视图 -->
    <el-card class="box-card" style="margin-top: 20px">
      <!--from表单包裹 -->
      <!-- :model:绑定的数据 -->
      <el-form ref="postFrom" :model="postFrom" label-width="80px">
        <!-- 标题 -->
        <el-form-item label="标题">
          <el-input v-model="postFrom.title"></el-input>
        </el-form-item>
        <!-- 类型 -->
        <!-- v-model:是当前被选中的单选按钮的label,得定义一个变量进行存储,后期等
        用户选中单选按钮的时候,就会将这个被选中的单选按钮label值赋值给v-model所绑定的属性 -->
        <el-form-item label="类型">
          <el-radio-group v-model="postFrom.type">
            <el-radio :label="1">文章</el-radio>
            <el-radio :label="2">视频</el-radio>
          </el-radio-group>
        </el-form-item>
        <!-- 内容 -->
        <el-form-item label="内容">
          <!-- 使用富文本框 -->
          <!-- 给组件添加ref标识 -->
          <!-- v-if:类别为1才显示 -->
          <VueEditor
            :config="config"
            ref="vueEditor"
            v-if="postFrom.type == 1"
          />
          <!-- v-if:类别为2才显示 -->
          <!-- headers:传递token -->
          <!-- action:上传的地址,必传 -->
          <!-- file-list:当前用户所选择文件列表 -->
          <!-- on-success:视频上传成功之后调用钩子函数 -->
          <el-upload
            class="upload-demo"
            v-if="postFrom.type == 2"
            :headers="getToken()"
            :action="baseURL + '/upload'"
            :file-list="fileList"
            :on-success="onsuccess"
          >
            <el-button size="small" type="primary">点击上传</el-button>
            <div slot="tip" class="el-upload__tip">只能上传视频文件</div>
          </el-upload>
        </el-form-item>
        <!-- 栏目 -->
        <!-- 封面 -->
        <!-- list-type:文件列表的类型 -->
        <!-- limit:	最大允许上传个数 -->
        <!-- on-exceed:文件超出个数限制时的钩子 -->
        <!-- on-preview:点击文件列表中已上传的文件时的钩子 -->
        <!-- on-remove:文件列表移除文件时的钩子 -->
        <el-form-item label="封面">
          <el-upload
            :action="baseURL + '/upload'"
            :headers="getToken()"
            list-type="picture-card"
            :limit="3"
            :on-exceed="handleExceed"
            :on-preview="handlePictureCardPreview"
            :on-success="onPosterSucess"
            :on-remove="onPosterRemove"
          >
            <i class="el-icon-plus"></i>
          </el-upload>
          <el-dialog :visible.sync="dialogVisible">
            <img width="100%" :src="userimg" alt="" />
          </el-dialog>
        </el-form-item>
        <!-- 按钮 -->
      </el-form>
      <!-- 点击发送事件 -->
      <el-button type="success" @click="publishPost">发布文章</el-button>
    </el-card>
  </div>
</template>

<script>
//引入富文本框
import VueEditor from "vue-word-editor";
import "quill/dist/quill.snow.css";
import axios from "@/utils/myaxios";
export default {
  data() {
    return {
      dialogVisible: false,
      userimg: "",
      baseURL: axios.defaults.baseURL, //http://localhost:3000
      fileList: [],
      postFrom: {
        title: "", //文章标题
        content: "", //文章内容
        categories: [], //所属栏目id集合
        cover: [], //封面图片id集合
        type: 1, //1为文章,2为视频,默认选文章
      },
      //   富文本框的必要配置
      config: {
        // 上传图片的配置
        uploadImage: {
          url: axios.defaults.baseURL + "/upload", //文章上传的服务器端的处理路径
          //    url: "http://localhost:3000/upload",
          name: "file", //后台所需要的参数名称
          //请求头
          headers: this.getToken(),
          // res是结果,insert方法会把内容注入到编辑器中,res.data.url是资源地址
          uploadSuccess(res, insert) {
            //文件上传成功之后的回调
            insert(axios.defaults.baseURL + res.data.data.url);
            //  insert("http://localhost:3000" + res.data.data.url)
            console.log(res, insert);
          },
        },

        // 上传视频的配置
        uploadVideo: {
          url: axios.defaults.baseURL + "/upload",
          //    url: "http://localhost:3000/upload",
          name: "file",
          uploadSuccess(res, insert) {
            insert(axios.defaults.baseURL + res.data.url);
            //  insert("http://localhost:3000" + res.data.data.url)
          },
        },
      },
    };
  },
  components: {
    VueEditor, //注册富文本框
  },
  methods: {
    //移出封面:重点是将对用的图片数据从postFrom.cover移出
    //file:当前移出的
    //fileList:现在还保留的
    onPosterRemove(file, fileList) {
      let id = file.response.data.id;
      for (let i = 0; i < this.postFrom.cover.length; i++) {
        if (this.postFrom.cover[i].id == id) {
          this.postFrom.cover.splice(i, 1);
          break;
        }
      }
    },
    //处理图片上传后操作
    onPosterSucess(response) {
      console.log(response);
      if (response.message == "文件上传成功") {
        this.postFrom.cover.push({ id: response.data.id });
      }
    },
    //实现封面的预览
    handlePictureCardPreview(file) {
      console.log(file);
      this.userimg = file.url;
      this.dialogVisible = true;
    },
    // 文件超出个数限制时的钩子
    handleExceed(files) {
      console.log(files);
      this.$message.warning("最多只能选择三张图片");
    },
    publishPost() {
      // 如果类型为文章, 那将标识为vueEditor的文本框内容赋值给content;
      if (this.postFrom.type == 1) {
        this.postFrom.content = this.$refs.vueEditor.editor.root.innerHTML;
      }
      console.log(this.postFrom);
    },
    getToken() {
      return {
        //   获取存储的token
        Authorization: JSON.parse(localStorage.getItem("usermanager")).token,
      };
    },
    // 视频上传成功之后调用钩子函数
    onsuccess(response, file, fileList) {
      console.log(response, file, fileList);
      if (response.message == "文件上传成功") {
        //类型为视频的时候,content中存储的内容就是视频在服务器中的全路径
        this.postFrom.content = axios.defaults.baseURL + response.data.url;
      }
    },
  },
};
</script>

<style lang="less" scoped>
</style>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值