管理商品必需要實現的幾個功能
先看一下數據結構
首先商品分類vue
類下面的商品詳情node
思路:
一、將添加商品類,添加商品,修改商品分離成單獨的組件git
二、添加路由github
三、 先寫出添加商品頁面express
掛在路由打開mangerprods.vuenpm
<template> <section class="box"> <div class="head"> <h3>{{this.$route.name}}</h3> </div> <!-- 商品管理路由 --> <div class="prodmenu">\ <el-menu mode="horizontal" :default-active="$router.path" router> <el-menu-item v-for="item in $router.options.routes[1].children[1].children" :key="item.path" :index="item.path"> {{item.name}} </el-menu-item> </el-menu> </div> <!-- 渲染路由 --> <router-view></router-view> </section> </template> <script> export default { // .. } </script> <style lang="less" scoped> @import '../../common/less/index.less'; .box { .head { .leftborder } .prodmenu { margin: 0 15px; } } </style>
四、寫添加商品類別頁面segmentfault
<template> <!-- 添加商品類 --> <div class="addprod"> <h4>添加一個商品類</h4> <el-input placeholder="請輸入商品類名" v-model="prodtype" clearable> </el-input> <el-input placeholder="請輸入商品類簡介" v-model="prodsub" type="textarea" :rows="2" clearable> </el-input> <el-button type="danger" :disabled="disabled" @click="addtype" round>添加</el-button> </div> </template> <script> export default { data () { return { prodtype: '', prodsub: '' } }, computed: { disabled () { if (this.prodtype === '' || this.prodsub === '') { return true } else { return false } } }, methods: { addtype () { console.log('do') } } } </script> <style lang="less" scoped> @import '../../../common/less/index.less'; .addprod { .learncontent; .el-input { margin: 5px 0; } .el-button { margin: 10px 0; width: 100%; } } </style>
五、寫添加商品頁面後端
<template> <!-- 新增商品 --> <div class="addprod"> <h4>新增商品</h4> <el-form ref="addprod" :rules="prodrules" :model="addprod" label-width="80px"> <el-form-item label="商品名" prop="name"> <el-input v-model="addprod.name" placeholder="請輸入商品名"></el-input> </el-form-item> <el-form-item label="價格" prop="price"> <el-input v-model.number="addprod.price" placeholder="請輸入商品價格"></el-input> </el-form-item> <el-form-item label="商品主圖" prop="image"> <el-upload class="prod-image" action="/learn/upload" :show-file-list="false" :on-success="handleSuccess" :before-upload="beforeUpload"> <img v-if="imageUrl" :src="imageUrl" class="cur-image"> <i v-else class="el-icon-plus prod-uploader-icon"></i> </el-upload> </el-form-item> <el-form-item label="商品類別" prop="type"> <el-select v-model="addprod.type" placeholder="請選擇商品類別"> <el-option label="石榴" value="shiliu"></el-option> <el-option label="火腿" value="ham"></el-option> </el-select> </el-form-item> <el-form-item label="是否上架"> <el-switch v-model="addprod.selling"></el-switch> </el-form-item> <el-form-item label="商品簡介" prop="desc"> <el-input type="textarea" v-model="addprod.desc" placeholder="請請輸入商品簡介"></el-input> </el-form-item> <el-form-item label="商品詳情" prop="info"> <mavon-editor ref="md" @imgAdd="$imgAdd" @imgDel="$imgDel" v-model="addprod.info"></mavon-editor> </el-form-item> <el-form-item> <el-button type="primary" @click="newprod">當即添加</el-button> </el-form-item> </el-form> </div> </template> <script> import {UploadFile} from '../../../api/api' export default { data () { return { imageUrl: '', addprod: { name: '', price: '', type: '', selling: '', desc: '', info: '' }, prodrules: { name: [ { required: true, message: '請輸入商品名', trigger: 'blur' }, { min: 3, max: 15, message: '長度在 3 到 15 個字', trigger: 'blur' } ], price: [ { required: true, message: '請輸入商品價格', trigger: 'blur' }, { type: 'number', message: '價格必須是數字', trigger: 'blur' } ], type: [ { required: true, message: '商品必須選擇一個類別', trigger: 'change' } ], desc: [ { required: true, message: '請輸入商品簡介', trigger: 'blur' } ] } } }, methods: { newprod () { this.$refs.addprod.validate(valid => { if (valid) { // console.log('add prod!') // const prodFd = new FormData() // prodFd.append('name', this.addprod.name) } else { console.log('請先完成驗證') return false } }) }, // mavoneditor圖片上傳並替換地址 // 綁定@imgAdd event $imgAdd (pos, $file) { // 第一步.將圖片上傳到服務器. let formdata = new FormData() formdata.append('file', $file) UploadFile(formdata) .then(url => { // console.log(url) console.log(this.addprod.info) // 第二步.將返回的url替換到文本原位置![...](./0) -> ![...](url) this.$refs.md.$img2Url(pos, url.data) }) }, $imgDel (pos) { delete this.img_file[pos] }, // 獲取商品主圖上傳成功後返回的圖片 handleSuccess (res, file) { this.imageUrl = URL.createObjectURL(file.raw) }, // 商品主圖再上傳前對文件進行判斷 beforeUpload (file) { const isPIC = file.type === 'image/jpeg' || 'image/png' const isLt5M = file.size / 1024 / 1024 < 5 if (!isPIC) { this.$message.error('上傳圖片只能是 JPG或PNG 格式!') } if (!isLt5M) { this.$message.error('上傳圖片大小不能超過 5MB!') } return isPIC && isLt5M } } } </script> <style lang="less" scoped> @import '../../../common/less/index.less'; .addprod { .learncontent; .el-form { text-align: left; .el-select { width: 100%; } .el-switch { margin: 10px 0 0 0; } .prod-image { width: 200px; height: 200px; border: 1px dashed #d9d9d9; border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; .cur-image { width: 100%; } .prod-uploader-icon { font-size: 45px; color: #8c939d; width: 200px; height: 200px; line-height: 200px; text-align: center; } } } } </style>
六、引入markdown編輯器api
cnpm i mavon-editor --save
引用
main.js服務器
使用
再addprod.vue中直接使用
引用mavoneditor
mavonedior上傳圖片操做
與服務端進行交互的API
由於markdown編輯器是具備實時預覽功能,若是咱們將本地圖片插入,執行步驟是這樣的
一、他會當即執行上傳圖片操做,並獲取服務端返回的圖片地址
二、獲取到圖片地址,mavon會馬上向服務端請求這個地址來獲取這張圖片,並渲染出來
效果是合適的
同時後端也記錄了3次上傳和3次獲取圖片
我當時寫服務端代碼的時候,再上傳圖片的地方,我將
const form = new formidable.IncomingForm()
寫在了頁面的開頭,並無將formidable的實例化卸載每一次上傳的過程當中,這致使了一個問題,上傳第一張圖片能夠成功,但上傳第二張開始就發生錯誤
Can't set headers after they are sent
這是由於我全部的req解析都在同一個實例化的form裏面,第一次執行upload成功時,form會調用一次form.on('end'),第二次upload成功時,form也會調用一次form.on('end'),這樣就產生了Can't set headers after they are sent這個錯誤
再此很是感謝segmentfault的 @程序猿小卡_casper,無私的幫助我解決了問題並細心的講解錯誤緣由,謝謝!!,同時也感謝其餘真心幫助我解決問題的朋友!
又興趣的朋友能夠看看這個問題的原題
https://segmentfault.com/q/10...
learn:https://github.com/lyttonlee/...
server:https://github.com/lyttonlee/...