解析信息为什么不能自动写进表单中?
来源:13-9 新增电子书前端交互优化
慕容6513491
2020-07-03
我不想开发电子书,想结合教程开发三个基本功能:1.上传图片展示库,2.发布文章,3.文章管理/人员管理表格,可实现编辑和修改功能。
教程中的内容都是解析电子书,发布电子书,看的磕磕绊绊,照猫画虎,对应着源码适当改来改去。
其实这个板块都在作者花裤衩原始的原始文稿中都有模拟数据,但没研究明白,现在的问题是:
在开发功能1时,数据始终无法解析到那片表单中,我觉得问题可能出在parse,毕竟电子书一堆东西要解析,图片解析什么?自动写进表单中的也就路径和上传的图名这类元素。
但是我确实想解决这个问题,请给予指点。
前端:
router/index:
{
path: '/art',
component: Layout,
redirect: '/art/create',
name: 'art',
meta: {
title: '图库管理',
icon: 'documentation',
roles: ['admin', 'editor']
},
children: [
{
path: 'create',
component: () => import('@/views/art/create'),
name: 'artCreate',
meta: {
title: '上传图片',
icon: 'edit',
roles: ['admin'],
noCache: true
}
},
{
path: 'edit',
component: () => import('@/views/art/edit'),
name: 'artEdit',
hidden: true,
meta: {
title: '作品编辑',
icon: 'list',
roles: ['admin', 'editor'],
noCache: true,
activeMenu: '/art/list'
}
},
{
path: 'list-art',
component: () => import('@/views/art/list'),
name: 'artList',
meta: {
title: '作品列表',
icon: 'list',
roles: ['admin', 'editor'],
activeMenu: '/art/list'
}
},
{
path: 'list',
component: () => import('@/views/art/edit'),
name: 'artistList',
meta: {
title: '人物列表',
icon: 'list',
roles: ['admin', 'editor'],
activeMenu: '/art/list'
}
}
]
},
Detail:
<template>
<el-form ref="postForm" :model="postForm" :rules="rules">
<sticky :class-name="'sub-navbar'">
<el-button v-if="!isEdit" @click="showGuide">显示帮助</el-button>
<el-button v-loading="loading" type="success" style="margin-left: 10px" @click="submitForm">
{{ isEdit ? '编辑图库' : '添加作品' }}
</el-button>
</sticky>
<div class="detail-container">
<el-row>
<warning />
<el-col :span="24">
<!-- 上传控件的具体样式 -->
<art-upload
:file-list="fileList"
:disabled="isEdit"
@onSucess="onUploadSucess"
@onRemove="onUploadRemove"
/>
</el-col>
<el-col :span="24">
<el-form-item prop="title">
<MdInput v-model="postForm.title" :maxlength="100" name="name" required>
图片名
</MdInput>
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item prop="author" label="作者:" :label-width="labelWidth">
<el-input
v-model="postForm.author"
placeholder="作者"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="country" label="国家地区:" :label-width="labelWidth">
<el-input
v-model="postForm.country"
placeholder="国家地区"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item prop="category" label="类别:" :label-width="labelWidth">
<el-input
v-model="postForm.category"
placeholder="类别"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="createDate" label="创作时间:" :label-width="labelWidth">
<el-input
v-model="postForm.createDate"
placeholder="创作时间"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="文件大小:" :label-width="labelWidth">
<el-input
v-model="postForm.fileSize"
placeholder="文件大小"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="文件路径:" :label-width="labelWidth">
<el-input
v-model="postForm.filePath"
placeholder="文件路径"
disabled
/>
</el-form-item>
</el-col>
</el-row>
<略>
<script>
import Sticky from '../../../components/Sticky'
import Warning from './Warning'
import ArtUpload from '../../../components/ArtUpload'
import MdInput from '../../../components/MDinput/index'
import { createArt } from '../../../api/art'
const defaultForm = {
title: '',
filename: '',
filePath: '',
fileSize: ''
}
const fields = {
title: '图片名',
author: '作者',
country: '国家地区',
category: '类别',
createDate: '创作时间'
}
export default {
components: { MdInput, Sticky, Warning, ArtUpload },
props: {
isEdit: {
type: Boolean
}
},
data() {
const validateRequire = (rule, value, callback) => {
if (value === '') {
this.$message({
message: rule.field + '为必传项',
type: 'error'
})
callback(new Error(rule.field + '为必传项'))
} else {
callback()
}
}
return {
postForm: Object.assign({}, defaultForm),
loading: false,
// postForm: {},
fileList: [],
labelWidth: '120px',
rules: {
title: [{ validator: validateRequire }],
image_uri: [{ validator: validateRequire }],
author: [{ validator: validateRequire }],
country: [{ validator: validateRequire }],
category: [{ validator: validateRequire }],
createDate: [{ validator: validateRequire }]
}
}
},
methods: {
setData(data) {
const {
title,
filename,
filePath,
fileSize
} = data
this.postForm = {
...this.postForm,
title,
filename,
filePath,
fileSize
}
},
onUploadSucess(data) {
console.log('onUploadSucess', data)
this.setData(data)
},
setDefault() {
this.postForm = Object.assign({}, defaultForm)
},
onUploadRemove() {
this.setDefault()
},
submitForm() {
// if (!this.loading) {
this.loading = true
this.$refs.postForm.validate((valid, fields) => {
console.log(valid, fields)
if (valid) {
const art = Object.assign({}, this.postForm)
delete art.unzipPath
delete art.unzipUrl
if (!this.isEdit) {
createArt(art).then(response => {
const { msg } = response
this.$notify({
title: '操作成功',
message: msg,
type: 'success',
duration: 2000
})
this.loading = false
}).catch(() => {
this.loading = false
})
} else {
// updateArt(art)
}
} else {
const message = fields[Object.keys(fields)[0]][0].message
this.$message({ message, type: 'error' })
this.loading = false
}
})
// }
后端:
models/
class Art {
constructor(file, data) {
if (file) {
this.createArtFromFile(file)
} else {
this.createArtFromData(data)
}
}
createArtFromFile(file) {
console.log('createArtFromFile', file)
const {
destination,
filename,
mimetype = MIME_TYPE_ART,
path,
originalname,
size
} = file
// 图片的文件后缀名
const suffix = mimetype === MIME_TYPE_ART ? '.jpg' : ''
// 图片的原有路径
const oldArtPath = path
// 图片的新路径
const artPath = `${destination}/${filename}${suffix}`
// 图片的下载URL
const url = `${UPLOAD_URL}/art/${filename}${suffix}`
// 图片解压后的文件夹路径
const unzipPath = `${UPLOAD_PATH}/unzip/${filename}`
// 图片解压后的文件夹URL
const unzipUrl = `${UPLOAD_URL}/unzip/${filename}`
if (!fs.existsSync(unzipPath)) {
fs.mkdirSync(unzipPath, { recursive: true })
}
if (fs.existsSync(oldArtPath) && !fs.existsSync(artPath)) {
fs.renameSync(oldArtPath, artPath)
}
this.title = originalname //图片名
this.fileName = filename //文件名
this.path = `/art/${filename}${suffix}` // 图片文件相对路径
this.filePath = this.path
this.unzipPath = `/art/${filename}` // 图片解压后相对路径
this.url = url
this.fileSize = size //文件大小
this.unzipUrl = unzipUrl //解压后文件夹链接
this.originalname = originalname //图片文件的原名
}
createArtFromData(data) {
this.title = data.originalname
this.author = data.author
this.country = data.country
this.category = data.category
this.createDate = data.createDate
this.fileName = data.filename
this.filePath = data.filePath
this.fileSize = data.size
this.url = data.url
}
parse() {
return new Promise((resolve, reject) => {
const artPath = `${UPLOAD_PATH}${this.filePath}`
if (!fs.existsSync(artPath)) {
reject(new Error('图片不存在'))
}
const image = new Image(artPath)
//解析失败
image.on('err', err => {
reject(err)
})
// 解析成功
image.on('end', err => {
if (err) {
reject(err)
} else {
// console.log(image.metadata)// 获取一些信息,比如metadata
const {
title,
mimetype,
filePath,
url
} = image.metadata
if (!title) {
reject(new Error('图片名为空'))
} else {
this.title = filename
this.fileName = originalname
this.mimeType = mimetype
this.url = url
this.filePath = filePath
this.rootFile = image.rootFile
const handleGetImage = function(err, file, mimeType) {
if (error) {
reject(error)
} else {
resolve(this)// 解析结束
}
}
image.getImage(preview, handleGetImage)
}
}
})
image.parse()//来进行解析的过程
this.image = image
})
}
toJson() {
return {
title: this.title,
author: this.author,
country: this.country,
category: this.category,
createDate: this.createDate,
fileName: this.fileName,
filePath: this.filePath,
fileSize: this.fileSize,
url: this.url,
path: this.path
}
}
toDb() {
return {
title: this.originalname,
author: this.author,
country: this.country,
category: this.category,
createDate: this.createDate,
fileName: this.filename,
filePath: this.filePath,
fileSize: this.size
}
}
static genPath(path) {
if (path.startsWith('/')) {
return `${UPLOAD_PATH}${path}`
} else {
return `${UPLOAD_PATH}/${path}`
}
}
static pathExists(path) {
if (path.startsWith(UPLOAD_PATH)) {
return fs.existsSync(path)
} else {
return fs.existsSync(Book.genPath(path))
}
}
router:
const express = require('express')
const multer = require('multer')
const { UPLOAD_PATH } = require('../utils/constant')
const Result = require('../models/Result')
const Art = require('../models/Art')
const boom = require('boom')
const { decoded } = require('../utils')
const artService = require('../services/art')
const router = express.Router()
router.post(
'/upload',
multer({ dest: `${UPLOAD_PATH}/art` }).single('file'),
function(req, res) {
if (!req.file || req.file.length === 0) {
new Result('上传文件失败').fail(res)
} else {
const art = new Art(req.file)
console.log(art)
new Result(art, '上传文件成功').success(res)
}
}
)
router.post(
'/upload',
multer({ dest: `${UPLOAD_PATH}/art` }).single('file'),
function(req, res, next) {
if (!req.file || req.file.length === 0) {
new Result('上传文件失败').fail(res)
} else {
const art = new Art(req.file)
art.parse()
.then(art => {
// console.log('art', art)
new Result(art, '上传文件成功').success(res)
})
.catch(err => {
next(boom.badImplementation(err))
})
}
}
)
router.post(
'/create',
function(req, res, next) {
const decode = decoded(req)
console.log(req.body)
if (decode && decode.username) {
req.body.username = decode.username
}
const art = new Art(null, req.body)
console.log(art)
artService.insertArt(art).then(() => {
}).catch(err => {
next(boom.badImplementation(err))
})
}
)
module.exports = router
反馈:
现在目标是:怎么将图片标题和路径自动挂进表单中?需要修改哪里?
4回答
-
希卡利
2020-07-13
服务器方面,接口会获取到上传图片的数据和信息,你可以打印出来看看结构,然后根据你自己的需求去做操作,比如数据库要存什么,图片要存到哪里去,完全取决你技术方案怎么设定的,完全不用数据库也可以实现。
00 -
希卡利
2020-07-13
上传图片没有上传电子书那么麻烦。
你想拿到添加到页面上但是还没上传到服务器的图片信息的话,单存的input表单可以用change事件拿到
el-upload 这个组件可以从before-upload可以在这个属性这里绑定方法去获取,具体使用请去看文档。
00 -
扬_灵
2020-07-05
同学你好,这是我做的一个建议代码,你可以参考一下,
前端 <el-upload // 这里的属性和方法你可以自己选择要或者不要 ref="upload" :action="action" // http://localhost:18082/role/addUserAvatar list-type="picture-card" :limit="1" :file-list="fileList" accept="jpg/png/gif" :before-upload="beforeUpload" :on-exceed="onExceed" :on-success="succuss" > <i class="el-icon-plus" /> </el-upload>
beforeUpload(file) { const uploadType = file.name.substring(file.name.lastIndexOf('.') + 1) const imgType = uploadType === 'jpg' const imgType2 = uploadType === 'jpeg' const imgType3 = uploadType === 'gif' if (!imgType && !imgType2 && !imgType3) { this.$message({ message: '头像只能是jpg,jpeg,gie格式', type: 'warning' }) } this.oldAvatar = false return imgType || imgType2 || imgType3 }, succuss(file) { console.log(file) //这里是你上传成功之后的回调 你在这里把 this.setData(file)的方法执行一下 },
后端 在这里我对/role下的路由做了处理,这里是role/addUserAvatar接口 router.post( '/addUserAvatar', multer({ dest: `${UPLOAD_PATH_IMG}` }).single('file'), function(req, res, next) { if (!req.file || req.file.length === 0) { new Result('上传头像失败').fail(res) } else { const img = new Img(req.file) if(img){ new Result(img.url,'上传头像成功').success(res) }else{ next(boom.badImplementation(err)) } } } )
IMG (这里我是将文件上传到了本地nginx的文件夹里面的,返回的信息之后只需要图片的地址)
const { MIME_TYPE_JPEG, // 设置图片的类型image/jpeg MIME_TYPE_PNG, // image/png MIME_TYPE_GIF, // image/gif UPLOAD_PATH_OLD // 图片的地址 } = require('../utils/constant') const fs = require('fs') class Img { constructor(file) { if (file) { this.createUploadImgFile(file) } } createUploadImgFile(file) { const { destination, filename, mimetype, path, } = file; // 图片的文件后缀名 let suffix; if(mimetype ===MIME_TYPE_JPEG ){ suffix = '.jpg' }else if(mimetype ===MIME_TYPE_PNG){ suffix = '.png' }else if(mimetype === MIME_TYPE_GIF){ suffix = '.gif' } // 图片的原有路径 const oldImgPath = path // 图片的新路径 const imgPath = `${destination}/${filename}${suffix}` // 图片的下载URL const url = `${UPLOAD_PATH_OLD}/${filename}${suffix}` if (fs.existsSync(oldImgPath) && !fs.existsSync(imgPath)) { fs.renameSync(oldImgPath, imgPath) } this.fileName = filename // 图片名 this.path = `/${filename}${suffix}` // 图片相对路径 this.filePath = this.path this.url = url // 图片地址 // 在这里进行对图片的大小,文件信息等进行处理 } } module.exports = Img
00 -
扬_灵
2020-07-04
同学你好,使用element的上传组件,上传时需要使用action指定上传所调用的接口,这个接口会将图片信息全部携带过去,在后端中定义接口接收图片数据信息,在这里你可以对图片进行解析,处理需要返回的数据信息,调用成功后会在组件的on-success方法中获取到接口返回的信息,在你的表单中使用的是双向数据绑定,只需要将上传成功返回的数据赋给表单里面:model="postForm"的postForm变量就好了。如果不能解决你的问题,可以继续追问。
012020-07-04
相似问题