elment-ui 文件上传
<template> <div> <el-upload ref="upload" :action="action" :limit="1" :file-list="fileList" :on-exceed="handleExceed" :on-remove="handleRemove" :on-success="handleSuccess" :before-upload="beforeUpload" :disabled="disabled" :on-preview="hanleOnpreview" > <el-button size="small" type="primary">点击上传</el-button> <div slot="tip" class="el-upload__tip"> <!-- 可以上传jpg/png/Jpeg/word/pdf/excel等格式文件,单个文件不可超过5M,附件不可超过5个 --> </div> </el-upload> </div> </template> <script> // /file/download // 下载 // import { fileDownload } from "@/api/announcement-manage"; export default { props: { file: { type: Array, default: () => { return []; }, }, uploadType: { type: String, default: () => { return ""; }, }, disabled: { type: Boolean, default: () => { return false; }, }, }, data() { return { // action: "https://www.xwqyy.com/filemanage/file/upload?project=customer", action: `${this.$util.uploadUrl}/file/uploadImage`, fileList: [], }; }, mounted() { this.fileList = this.file.length > 0 ? this.file : []; }, watch: { file: { handler(newData, oldData) { this.fileList = newData.length > 0 ? newData : []; }, deep: true, }, }, methods: { handleRemove(file, fileList) { console.log("删除file", file); console.log("删除fileList", fileList); // for (let item of fileList) { // item.fileName = item.name; // item.filePath = item.url; // } if (this.uploadType == "fileList") { this.$emit("getFileListdel", fileList); } }, handleSuccess(res, file, fileList) { // res.data.name = res.data.fileName; // res.data.url = res.data.filePath; // this.fileList.push(res.data); let imgarr = []; for (let item of fileList) { item.fileName = res.data.fileName; item.filePath = res.data.filePath; imgarr = fileList; } if (this.uploadType == "fileList") { this.$emit("getFileListup", imgarr); } }, beforeUpload(file) { let fileType = file.name.split("."); fileType = fileType[fileType.length - 1].toLowerCase(); const isMps = fileType === "mp3"; const isLt5M = file.size / 1024 / 1024 < 5; if (!isMps) { this.$message.error("上传文件只能是mp3格式!"); } if (!isLt5M) { this.$message.error("上传文件大小不能超过 5MB!"); } return isMps && isLt5M; }, handleExceed(files, fileList) { this.$message.warning("附件不能超过1个"); }, //点击下载 hanleOnpreview(file) { // fileDownload({ // filePath: file.url, // }).then((res) => { // this.downFile(res.data, file.name); // }); window.open(file.url); }, //下载乱码转换 downFile(content, fileName) { const dom = document.createElement("a"); // 隐藏的a标签,href为输出流 const blob = new Blob([content], { type: "application/vnd.ms-excel", // 创建一个类文件对象:Blob对象表示一个不可变的、原始数据的类文件对象 }); const url = window.URL.createObjectURL(blob); // 生成一个Blob对象 dom.style.display = "none"; dom.href = url; document.body.appendChild(dom); dom.setAttribute("download", fileName); dom.click(); document.body.removeChild(dom); URL.revokeObjectURL(url); }, }, }; </script> <style lang="less"> .disabled .el-upload--picture-card { display: none; } </style>
<template> <div class="yun-container"> <div class="yun-container-content"> <Spin size="large" fix v-if="loadInfo"></Spin> <Form ref="addform" :model="info" :rules="rules" :label-width="85" label-position="right" > <Row :gutter="16"> <Col span="14"> <FormItem label="名称:" prop="name"> <Input type="text" v-model="info.name" placeholder="请输入名称" ></Input> </FormItem> </Col> <Col span="14"> <FormItem label="类型:" prop="type"> <Select v-model="info.type" clearable> <Option v-for="item in typeList" :value="item.value" :key="item.value" >{{ item.label }} </Option> </Select> </FormItem> </Col> <Col span="14"> <FormItem label="介绍:" prop="intro"> <Input type="textarea" maxlength="1000" show-word-limit :autosize="{ minRows: 8, maxRows: 20 }" v-model="info.intro" placeholder="请输入介绍" ></Input> </FormItem> </Col> <Col span="24"> <FormItem label="上传照片:" prop="pic_url"> <div class="demo-upload-list" v-for="(item, index) in uploadList_img" :key="item.url" > <template v-if="item.status === 'finished'"> <img :src="item.url" /> <div class="demo-upload-list-cover"> <Icon type="md-eye" @click.native="handleView(item.url)" ></Icon> <Icon type="ios-trash-outline" @click.native="handleRemove(item, index)" ></Icon> </div> </template> <template v-else> <Progress v-if="item.showProgress" :percent="item.percentage" hide-info ></Progress> </template> </div> <Upload ref="upload" name="file" :default-file-list="defaultList_img" :show-upload-list="false" accept=".jpg, .jpeg, .png" :format="['jpg', 'jpeg', 'png']" :max-size="5120" :on-format-error="handleFormatError" :on-exceeded-size="handleMaxSize" :on-success="handleImgSuccess" :before-upload="handleBeforeUpload" multiple type="drag" :headers="headers" :action="action" style="display: inline-block; width: 88px" > <div style="width: 88px; height: 88px; line-height: 88px"> <Icon type="md-add" size="20"></Icon> </div> </Upload> <span class="note">图片上传上限5张,每张图片限5M</span> </FormItem> </Col> <Col span="14"> <FormItem label="上传音频:"> <UploadFile uploadType="fileList" @getFileListdel="getFileListdel" @getFileListup="getFileListup" :file="filearr" > </UploadFile ></FormItem> </Col> <!-- <Col span="24"> <FormItem label="上传视频:" prop="videoUrl"> <div class="demo-upload-list" v-for="item in uploadList_vod" :key="item.url" > <template v-if="item.status === 'finished'"> <img :src="baseImg" /> <div class="demo-upload-list-cover"> <Icon type="md-videocam" @click.native="handleViewVod(item.url)" ></Icon> <Icon type="ios-trash-outline" @click.native="handleRemoveVod(item)" ></Icon> </div> </template> <template v-else> <Progress v-if="item.showProgress" :percent="item.percentage" hide-info ></Progress> </template> </div> <Upload ref="uploadvod" name="file" :default-file-list="defaultList_vod" :show-upload-list="false" accept=".mp4" :format="['mp4']" :max-size="30720" :on-format-error="handleFormatErrorVod" :on-exceeded-size="handleMaxSizeVod" :on-success="handleImgSuccessVod" :before-upload="handleBeforeUploadVod" multiple type="drag" :headers="headers" :action="actionVod" style="display: inline-block; width: 88px" > <div style="width: 88px; height: 88px; line-height: 88px"> <Icon type="md-add" size="20"></Icon> </div> </Upload> <span class="note">视频上传上限3个,每个视频限30M</span> </FormItem> </Col> --> <Col span="24"> <div class="lat-wrap"> <div class="lat-wrap-title">地图位置:</div> <div class="lat-wrap-form"> <FormItem label="经度:" prop="lng"> <Input type="text" class="w150" v-model="info.lng" placeholder="经度" :disabled="true" ></Input> </FormItem> <FormItem label="纬度:" prop="lat"> <Input type="text" class="w150" v-model="info.lat" placeholder="纬度" :disabled="true" ></Input> </FormItem> </div> </div> </Col> <Col span="22"> <FormItem label=""> <div class="map" id="baiduMap" ref="baiduMap"></div> <div id="r-result" class="r-result"> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text">搜索地址:</span> </div> <input type="text" id="suggestId" class="suggestId" placeholder="" /> </div> </div> <div id="searchResultPanel" style=" border: 1px solid #c0c0c0; width: 150px; height: auto; display: none; " ></div> </FormItem> </Col> <Col span="24"> <div class="submit-wrap"> <Button type="primary" @click="handleSubmit('')" :loading="loading" >提交 </Button> <Button type="default" @click="closeMe()">返回</Button> </div> </Col> </Row> </Form> </div> <Modal title="查看图片" :styles="{ top: '20px' }" width="50%" v-model="IconView" > <div class="yun-modal-view-img"> <img :src="ViewImg" v-if="IconView" /> </div> </Modal> <Modal title="播放视频" :styles="{ top: '20px' }" width="800" v-model="vodView" > <div class="yun-modal-view-img"> <video-player :options="videoOptions" v-if="vodView" /> </div> </Modal> </div> </template> <script> import VideoPlayer from "@/components/VideoPlayer.vue"; import { sourceget, sourceadd, sourceupdate } from "@/api/alarm"; import { BaiduMap, mapOpts } from "@/libs/map.js"; import { validDouble } from "@/libs/validator.js"; import _GLOBAL from "@/libs/config"; import UploadFile from "./UploadFile.vue"; export default { name: "AddAlarm", components: { VideoPlayer, UploadFile, }, data() { const validateDouble = (rule, value, callback) => { if (!value) { callback(new Error("经纬度不能为空")); } else if (!validDouble(value)) { callback(new Error("数字及小数点")); } else { callback(); } }; return { baseImg: require("@/assets/vod.png"), ViewImg: "", IconView: false, vodView: false, myValue: "", mapSetInfo: { centerLat: "30.679277", centerLng: "118.140187", mapLevel: 14, }, editID: undefined, loadInfo: false, isEdit: false, loading: false, typeList: _GLOBAL.typeList, headers: { "author-token-key": localStorage.getItem("token"), }, action: `${this.$util.uploadUrl}/file/uploadImage`, uploadList_img: [], defaultList_img: [], actionVod: `${this.$util.uploadUrl}/file/uploadImage`, uploadList_vod: [], defaultList_vod: [], info: { id: "", type: "", name: "", lng: "", lat: "", pic_url: "", voice_url: "", intro: "", // left: "", // top: "", }, rules: { type: [ { required: true, validator: "请选择", message: "请选择类型", trigger: "change", }, ], name: [ { required: true, message: "名称不能为空", trigger: "blur" }, { type: "string", max: 30, message: "名称不能超过30个字符", trigger: "blur", }, ], // address: [ // { // type: "string", // max: 50, // message: "告警地址不超过50个字符", // trigger: "blur", // }, // ], intro: [ { type: "string", max: 400, message: "不超过400个字符", trigger: "blur", }, ], lng: [{ required: true, validator: validateDouble, trigger: "blur" }], lat: [{ required: true, validator: validateDouble, trigger: "blur" }], }, marker: null, videoOptions: { autoplay: true, controls: true, width: "760px", height: "400px", sources: [ { src: "//vjs.zencdn.net/v/oceans.mp4", type: "video/mp4", }, ], }, paramsId: this.$route.params.id, filearr: [], }; }, watch: { defaultList_img: { handler(val) { // this.uploadList_img.splice(0, this.uploadList_img.length) // console.log(val) /* val.forEach((element) => { this.uploadList_img.push({ name: element.name, url: element.url, showProgress: false, status: 'finished' }) }) */ }, deep: true, }, }, created() { let _this = this; // 如果是编辑 if (_this.paramsId) { _this._sourceget(); //详情 // 获取草稿 // let temp = { ..._this.$byStoreGet("hasDrafts") }; // console.log("temp=====", temp); // _this.$Modal.confirm({ // title: "草稿箱", // content: `<p>是否加载您在 ${temp.time} 保存的草稿?</p>`, // okText: "确定加载", // cancelText: "不加载并删除草稿", // loading: true, // onOk: () => { // _this.$nextTick(() => { // _this.defaultList_img = temp.img; // _this.defaultList_vod = temp.vod; // // _this.uploadList_img = [..._this.defaultList_img] // delete temp.time; // delete temp.img; // delete temp.vod; // _this.info = temp; // setTimeout(() => { // _this.$Modal.remove(); // _this.infoResource(); // _this.uploadList_img = _this.$refs.upload.fileList; // _this.uploadList_vod = _this.$refs.uploadvod.fileList; // }, 500); // }); // }, // onCancel: () => { // _this.$byStoreDelete("hasDrafts"); // _this.uploadList_img = _this.$refs.upload.fileList; // _this.uploadList_vod = _this.$refs.uploadvod.fileList; // }, // }); } else { } }, mounted() { let _this = this; // _this.uploadList_img = _this.$refs.upload.fileList; // _this.uploadList_vod = _this.$refs.uploadvod.fileList; _this.initMap(); //加载地图 }, methods: { //详情 _sourceget() { sourceget({ id: this.$route.params.id }).then((res) => { if (res.data.code == "00000") { this.info = Object.assign({}, res.data.data); //图片回显 if (this.info.pic_url && this.info.pic_url !== null) { this.info.pic_url = this.info.pic_url.split(","); this.info.pic_url.forEach((element) => { this.uploadList_img.push({ url: element, showProgress: false, status: "finished", }); }); } if (this.info.voice_url) { // let voice_urlarr = this.info.voice_url; // console.log("voice_urlarr", voice_urlarr); // let darr = []; // for (const item of voice_urlarr) { // darr.push({ // name: item.name, // url: item.value, // }); // } // console.log("darr", darr); this.filearr = [ { name: "音频文件", url: this.info.voice_url, }, ]; } this.infoResource(); } }); }, infoResource() { let _this = this; if (_this.info.lng && _this.info.lat) { _this.setInitMarker(); _this.map.centerAndZoom( new BMap.Point(_this.info.lng, _this.info.lat), _this.mapSetInfo.mapLevel ); } }, GOing(id) { return document.getElementById(id); }, setPlace() { let _this = this; _this.map.clearOverlays(); // 清除地图上所有覆盖物 function myFun() { // 获取第一个智能搜索的结果 let pp = local.getResults().getPoi(0).point; _this.map.centerAndZoom(pp, _this.mapSetInfo.mapLevel); // 添加标注 _this.map.addOverlay(new BMap.Marker(pp)); _this.info.lng = pp.lng; _this.info.lat = pp.lat; // _this.info.address = _this.myValue; } // 智能搜索 let local = new BMap.LocalSearch(_this.map, { onSearchComplete: myFun, }); local.search(_this.myValue); }, initMap() { let _this = this; BaiduMap.init().then((BMap) => { _this.map = new BMap.Map(_this.$refs.baiduMap); _this.map.addControl( new BMap.MapTypeControl({ mapTypes: [BMAP_NORMAL_MAP, BMAP_HYBRID_MAP], }) ); var top_left_navigation = new BMap.NavigationControl({ anchor: BMAP_ANCHOR_BOTTOM_RIGHT, type: BMAP_NAVIGATION_CONTROL_SMALL, }); _this.map.addControl(top_left_navigation); _this.map.centerAndZoom( new BMap.Point( _this.mapSetInfo.centerLng, _this.mapSetInfo.centerLat ), _this.mapSetInfo.mapLevel ); _this.map.enableScrollWheelZoom(); _this.map.addEventListener("click", _this.MapClick); var ac = new BMap.Autocomplete({ input: "suggestId", location: _this.map, }); // 建立一个自动完成的对象 ac.addEventListener("onhighlight", (e) => { let str = ""; let _value = e.fromitem.value; let value = ""; if (e.fromitem.index > -1) { value = _value.province + _value.city + _value.district + _value.street + _value.business; } str = "FromItem<br />index = " + e.fromitem.index + "<br />value = " + value; value = ""; if (e.toitem.index > -1) { _value = e.toitem.value; value = _value.province + _value.city + _value.district + _value.street + _value.business; } str += "<br />ToItem<br />index = " + e.toitem.index + "<br />value = " + value; _this.GOing("searchResultPanel").innerHTML = str; }); ac.addEventListener("onconfirm", (e) => { let _value = e.item.value; _this.myValue = _value.province + _value.city + _value.district + _value.street + _value.business; _this.GOing("searchResultPanel").innerHTML = "onconfirm<br />index = " + e.item.index + "<br />this.myValue = " + _this.myValue; _this.setPlace(); }); }); }, setInitMarker() { let _this = this; _this.marker = new window.BMap.Marker( new window.BMap.Point(_this.info.lng, _this.info.lat) ); _this.map.addOverlay(_this.marker); }, MapClick(e) { let _this = this; if (_this.marker) { _this.map.clearOverlays(); } const myGeo = new BMap.Geocoder(); myGeo.getLocation(e.point, (rs) => { // _this.info.address = rs.address; }); _this.info.lng = e.point.lng; _this.info.lat = e.point.lat; let newPoint = new window.BMap.Point(_this.info.lng, _this.info.lat); _this.map.panTo(newPoint); _this.marker = new window.BMap.Marker(newPoint); _this.map.addOverlay(_this.marker); }, handleSubmit() { let _this = this; _this.loading = true; _this.$refs["addform"].validate((valid) => { if (valid) { const params = Object.assign({}, _this.info); const _img = _this.uploadList_img.map((item, index, arr) => { return item.url; }); const _vod = _this.uploadList_vod.map((item, index, arr) => { return item.url; }); params.pic_url = _img.join(","); // params.videoUrl = _vod.join(","); _this.submitDetails(params); } else { _this.loading = false; _this.$Message.error({ duration: 5, closable: true, background: true, content: "请输入必填项!", }); } }); }, submitDetails(data) { let _this = this; let msg = _this.$Message.loading({ content: "正在提交数据", duration: 0, }); if (_this.paramsId) { sourceupdate(data) .then((res) => { msg(); if (res.data.code === "00000") { // _this.$byStoreDelete("hasDrafts"); _this.$Message.success({ duration: 3, closable: true, background: true, content: "数据提交成功", }); this.closeMe(); } else { _this.$Message.warning({ duration: 3, closable: true, background: true, content: res.data.desc, }); } }) .catch((error) => { _this.$Message.warning({ duration: 3, closable: true, background: true, content: res.data.desc, }); }) .finally(() => { _this.loading = false; }); } else { sourceadd(data) .then((res) => { msg(); if (res.data.code === "00000") { // _this.$byStoreDelete("hasDrafts"); _this.$Message.success({ duration: 3, closable: true, background: true, content: "数据提交成功", }); this.closeMe(); } else { _this.$Message.warning({ duration: 3, closable: true, background: true, content: "数据提交失败", }); } }) .catch((error) => { _this.$Message.warning({ duration: 3, closable: true, background: true, content: "数据提交失败", }); }) .finally(() => { _this.loading = false; }); } }, handleReset() { this.info = { id: "", type: "", name: "", lng: "", lat: "", pic_url: "", voice_url: "", intro: "", left: "", top: "", }; }, handleView(src) { this.ViewImg = src; this.IconView = true; }, //删除 handleRemove(file, index) { this.uploadList_img.splice(index, 1); }, handleViewVod(src) { this.videoOptions.sources[0].src = src; this.vodView = true; }, handleRemoveVod(file) { const fileList = this.$refs.uploadvod.fileList; this.$refs.uploadvod.fileList.splice(fileList.indexOf(file), 1); }, handleImgSuccessVod(res, file) { console.log(res, file); if (res.code === "00000") { file.url = res.data; } else { this.$Message.error({ content: "上传失败", duration: 5, }); } }, handleImgSuccess(res, file) { if (res.code === "00000") { this.uploadList_img.push({ name: file.name, url: res.data, showProgress: false, status: "finished", }); } else { this.$Message.error({ content: "上传失败", duration: 5, }); } }, handleFormatErrorVod(file) { this.$Message.error({ content: "请上传MP4格式视频", duration: 5, }); }, handleFormatError(file) { this.$Message.error({ content: "请上传png或jpg格式图片", duration: 5, }); }, handleMaxSizeVod(file) { this.$Message.error({ content: "视频文件不能超过30M.", duration: 5, }); }, handleMaxSize(file) { this.$Message.error({ content: "图片文件不能超过5M.", duration: 5, }); }, handleBeforeUploadVod() { const check = this.uploadList_vod.length < 3; if (!check) { this.$Message.warning("最多上传3个视频"); } return check; }, handleBeforeUpload() { const check = this.uploadList_img.length < 5; if (!check) { this.$Message.warning("最多上传5张照片"); } return check; }, closeMe() { this.$store.commit("app/closePage", { vm: this, fromName: this.$route.name, toName: "alarm", }); }, //附件列表获取 getFileListup(data) { let d = []; data.map((item) => { d.push({ name: item.fileName, value: item.filePath, }); }); this.info.voice_url = data[0].response.data; }, //附件列表删除 getFileListdel(data) { this.info.voice_url = ""; }, }, beforeDestroy() { this.map = null; }, }; </script> <style lang="less" scoped> .w350 { width: 350px; } .map { margin-bottom: 15px; width: 100%; height: 600px; border: 1px solid #c30d2d; } .input-group { position: relative; display: flex; flex-wrap: wrap; align-items: stretch; width: 350px; } .input-group-prepend { margin-right: -1px; } .input-group-text { display: flex; align-items: center; padding: 4px 7px; margin-bottom: 0; font-size: 14px; font-weight: 400; line-height: 1.5; color: #495057; text-align: center; white-space: nowrap; background-color: #f8f8f9; border: 1px solid #d8d8d8; border-radius: 5px; border-top-right-radius: 0; border-bottom-right-radius: 0; } .suggestId { display: block; flex: 1 1 auto; width: 1%; font-weight: 400; line-height: 1.5; color: #495057; background-color: #fff; background-clip: padding-box; border: 1px solid #d8d8d8; border-radius: 5px; border-top-left-radius: 0; border-bottom-left-radius: 0; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } .suggestId:hover { border-color: #999999; } .suggestId:focus { border-color: #2a89e0; outline: 0; box-shadow: 0 0 0 2px rgba(45, 140, 240, 0.2); } .r-result { display: inline-block; position: absolute; left: 5px; top: 5px; color: #000; font-size: 14px; z-index: 1006; } .search-ResultPanel { display: none; position: absolute; left: 94px; top: 50px; color: #000; font-size: 16px; z-index: 999999; background: #fff; border-top: 1px solid #ddd; width: 350px; max-height: 800px; overflow-y: auto; padding: 10px 20px; } .lat-wrap { display: flex; .lat-wrap-title { width: 85px; text-align: right; padding: 6px 12px 10px 0; } .lat-wrap-form { display: flex; } } .demo-upload-list { display: inline-block; width: 88px; height: 88px; text-align: center; line-height: 88px; border: 1px solid transparent; border-radius: 4px; overflow: hidden; background: #fff; position: relative; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); margin-right: 4px; } .demo-upload-list img { width: 100%; //height: 100%; position: absolute; top: 0; left: 0; bottom: 0; margin: auto; } .demo-upload-list-cover { display: none; position: absolute; top: 0; bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, 0.6); } .demo-upload-list:hover .demo-upload-list-cover { display: block; } .demo-upload-list-cover i { color: #fff; font-size: 20px; cursor: pointer; margin: 0 2px; } .note { color: #999999; font-size: 12px; margin-left: 5px; } </style>