vue 博客项目后台upload文件上传、富文本编辑器

 关于博客项目从koa服务端到iview后台管理中的图片文件相关配置操作截图

 koa服务端配置

入口app.js 中的监听端口http://localhost:3000。

进行了article(文章)路由配置,因为后续操作文件上传富文本编辑都是要在文章页面进行。

koa服务端 /app.js

以下是截取的部分相关配置

const Koa = require("koa");
const Router = require("koa-router");
const app = new Koa();
const router = new Router();
//引入文章路由
const articleRoutes = require("./routes/article");

app.use(bodyparser())//body解析
.use(require("koa-cors"))//跨域
.use(require("koa-static")(__dirname + "/public"))//静态文件中间件
.use(router.routes())//路由
.use(router.allowedMethods());//允许post请求

// 路由前缀
router.prefix("/api/v1");
// 引用路由
articleRoutes(router);

module.exports = app.listen(3000, () => {
  console.log(`Listening on http://localhost:3000`);
});

routes/article.js

const ArticleController = require("../controller/ArticleController");
const upload = require("../middlewares/upload");
module.exports = (router) => {

  // 图片上传
  router.post(
    "/upload",
    upload.single("avatar"),//single单文件上传
    ArticleController.uploadCoverImg
  );
};

middlewares/upload

// 文件上传
const multer = require('koa-multer');
//配置 磁盘存储
const storage = multer.diskStorage({
  //文件保存路径
  destination: function (req, file, cb) {
    cb(null, 'public/images/')
  },
  //修改文件名称
  filename: function (req, file, cb) {
    var fileFormat = (file.originalname).split("."); //以点分割成数组,数组的最后一项就是后缀名
    cb(null, Date.now() + "." + fileFormat[fileFormat.length - 1]);
  }
})
//加载配置
const upload = multer({
  storage: storage
});
module.exports = upload;

public文件夹

该文件夹两个作用;

第一是用来作为静态根目录

第二是用来存储上传的图片,也就是说用户上传的图片文件最终都会存储到images当中 

 controller/ActicleController

const res = require("../core/helper");//工具类,用来封装返回结果
static ArticleController{
    //还有很多操作(crud),因为涉及的中间件比较多,一一省略
     static async uploadCoverImg(ctx, next) {
    // http://localhost:3000/public/image/13131414.png
        console.log(ctx.req.file)
        ctx.body = res.json(ctx.req.file);
  }
}

 core/helper

class Resolve {
  success(msg = "success", errorCode = 1, code = 200) {
    return {
      msg,
      errorCode,
      code,
    };
  }
  json(data, msg = "success", errorCode = 1, code = 200) {
    return {
      msg,
      errorCode,
      code,
      data,
    };
  }
}
const res = new Resolve();
module.exports = res;

博客后台管理

 该后台管理采用的是vue框架ivewUi

以下是该项目用到的包

package.json

 "dependencies": {
    "axios": "^0.19.2",
    "core-js": "^3.6.5",
    "mavon-editor": "^2.9.0",
    "qs": "^6.9.4",
    "view-design": "^4.2.0",
    "vue": "^2.6.11",
    "vue-router": "^3.2.0",
    "vuex": "^3.4.0"
  },

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// iView的使用
import ViewUI from 'view-design'
Vue.use(ViewUI)
import 'view-design/dist/styles/iview.css';
// 使用富文本的编辑器
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
Vue.use(mavonEditor);
// 导入默认的css模块
import './assets/style/admin.css'

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

 views/acticle/create.vue

以下是文章创建页面所有细节 

<template>
  <section>
    <Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="100">
      <FormItem label="文章标题" prop="title">
        <Input v-model="formValidate.title" placeholder="文章标题"/>
      </FormItem>
      <FormItem label="文章作者" prop="author">
        <Input v-model="formValidate.author" placeholder="文章作者"/>
      </FormItem>
      <FormItem label="文章简介" prop="description">
        <Input v-model="formValidate.description" placeholder="文章简介"/>
      </FormItem>
      <FormItem label="文章关键字" prop="keyword">
        <Input v-model="formValidate.keyword" placeholder="文章简介"/>
      </FormItem>
      <FormItem label="文章分类" v-if="categoryList && categoryList.length > 0" prop="category_id">
        <Select v-model="formValidate.category_id">
          <Option v-for="(item, index) in categoryList" :value="item._id" :key="index">{{item.name}}</Option>
        </Select>
      </FormItem>
      <FormItem label="文章封面" prop="cover">
        <div class="cover">
          <div class="upload">
            <Upload
              multiple
              type="drag"
              action="http://localhost:3000/api/v1/upload"
              :show-upload-list="false"
              :on-success="uploadSuccess"
              :on-error="uploadError"
              name="avatar"
            >
              <div style="padding: 20px 0">
                <Icon type="ios-cloud-upload" size="52" style="color: #3399ff"></Icon>
                <p>点击或者拖拽上传</p>
              </div>
            </Upload>
          </div>
          <div class="article-cover" v-if="formValidate.cover">
            <img :src="formValidate.cover" alt="cover">
          </div>
        </div>
      </FormItem>
      <FormItem label="文章内容" prop="content">
        <mavon-editor v-model="formValidate.content" :ishljs="true" ref="md"></mavon-editor>
      </FormItem>
      <FormItem>
        <Button @click="handleReset('formValidate')">重置</Button>
        <Button type="primary" @click="handleSubmit('formValidate')" style="margin-left: 8px">提交</Button>
      </FormItem>
    </Form>
  </section>
</template>
<script>
import { mapActions } from "vuex";

export default {
  data() {
    return {
      token: "",
      id: this.$route.params.id,
      detail: null,
      categoryList: [],
      formValidate: {
        title: "",
        author: "",
        category_id: "",
        cover: "",
        description: "",
        keyword: "",
        content: ""
      },
      ruleValidate: {
        title: [
          { required: true, message: "文章标题不能为空", trigger: "blur" }
        ],
        author: [
          { required: true, message: "文章作者不能为空", trigger: "blur" }
        ],
        cover: [
          { required: true, message: "文章封面不能为空", trigger: "blur" }
        ],
        description: [
          { required: true, message: "文章简介不能为空", trigger: "blur" }
        ],
        keyword: [
          { required: true, message: "文章关键字不能为空", trigger: "blur" }
        ],
        content: [
          { required: true, message: "文章内容不能为空", trigger: "blur" }
        ],
        category_id: [
          { required: true, message: "分类不能为空", trigger: "blur" }
        ]
      }
    };
  },
  created() {
    // 获取分类列表
    this._getCategoryList();
  },
  methods: {
    ...mapActions({
      getCategoryList: "category/getCategoryList",
      createArticle:'article/createArticle'
    }),
    uploadSuccess(response, file, fileList) {
     const coverUrl ='http://localhost:3000' + file.response.data.path.split('public')[1];
      console.log(coverUrl);
      console.log(file.response.data.path);

      this.formValidate.cover = coverUrl;
      this.$Message.success('上传成功')
    },
    async _getCategoryList() {
      const res = await this.getCategoryList();
      this.categoryList = res.data.content;
    },
    // 上传图片失败
    uploadError(response) {
      this.$Message.error("上传失败!");
      console.log(response);
    },
    // 提交
    handleSubmit(name) {
      this.$refs[name].validate(valid => {
        if (valid) {
          // 创建文章
          this._createArticle();
        } else {
          this.$Message.error("请完成表单!");
        }
      });
    },
    handleReset(name) {
      this.$refs[name].resetFields();
    },
    // 创建文章业务逻辑
    async _createArticle(){
      await this.createArticle(this.formValidate);
      this.$Message.success('创建文章成功');
      this.$router.push('/article');
    },
  }
};
</script>
<style scoped>
.article-cover {
  width: 120px;
}

.article-cover img {
  width: 100%;
}

.cover {
  display: flex;
}

.cover .upload {
  width: 280px;
  margin-right: 32px;
}
</style>

 当然本文重点是upload图片上传,以及富文本编辑器的使用

以下相关截图

图片上传代码截图

 

 运行视图:

 富文本编辑器代码块截图

 

ishljs为高亮(ishighlight.js) 

运行视图:左编辑,右预览

 创建提交

后台效果

 到前台查看是否存在该文章图片 

进入查看内容: 

 好了大功告成!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值