| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- <template>
- <div class="fm-uplaod-container"
- :id="uploadId"
- >
- <draggable class="drag-img-list"
- v-model="fileList"
- v-bind="{group: uploadId, ghostClass: 'ghost', animation: 200}"
- :no-transition-on-drag="true"
- >
- <div
- :id="item.key"
- :style="{width: width+'px', height: height+'px'}"
- :class="{uploading: item.status=='uploading', 'is-success': item.status=='success', 'is-disabled': disabled}"
- class="upload-file" v-for="(item) in fileList" :key="item.key">
- <img :src="item.url" />
- <el-progress v-if="item.status=='uploading' && ui == 'element'" :width="miniWidth*0.9" class="upload-progress" type="circle" :percentage="item.percent"></el-progress>
- <a-progress v-if="item.status=='uploading' && ui == 'antd'" :width="miniWidth*0.9" class="upload-progress" type="circle" :percent="item.percent"></a-progress>
- <label class="item-status" v-if="item.status=='success'">
- <i class="el-icon-upload-success el-icon-check" v-if="ui=='element'"></i>
- <a-icon type="check" v-if="ui=='antd'" />
- </label>
- <div class="uplaod-action" :style="{height: miniWidth / 4 + 'px'}">
- <i class="iconfont icon-tupianyulan" :title="$t('fm.upload.preview')" @click="handlePreviewFile(item.key)" :style="{'font-size': miniWidth/8+'px'}"></i>
- <i v-if="isEdit && !disabled" class="iconfont icon-sync1" :title="$t('fm.upload.edit')" @click="handleEdit(item.key)" :style="{'font-size': miniWidth/8+'px'}"></i>
- <i v-if="isDelete && fileList.length > min && !disabled" class="iconfont icon-delete" :title="$t('fm.upload.delete')" @click="handleRemove(item.key)" :style="{'font-size': miniWidth/8+'px'}"></i>
- </div>
- </div>
- </draggable>
- <div
- :class="{'is-disabled': disabled, 'el-upload': ui == 'element', 'el-upload--picture-card': ui == 'element', 'ant-upload': ui == 'antd', 'ant-upload-select' : ui == 'antd', 'ant-upload-select-picture-card': ui == 'antd'}"
- v-show="(!isQiniu || (isQiniu && token)) && fileList.length < limit"
- :style="{width: width+'px', height: height+'px'}"
- @click="handleAdd"
- v-if="!readonly"
- >
- <a-icon type="plus" v-if="ui=='antd'" :style="{fontSize:miniWidth/4+'px',marginTop: (-miniWidth/8)+'px', marginLeft: (-miniWidth/8)+'px', position: 'absolute', left: '50%', top: '50%'}" />
- <i v-if="ui == 'element'" class="el-icon-plus" :style="{fontSize:miniWidth/4+'px',marginTop: (-miniWidth/8)+'px', marginLeft: (-miniWidth/8)+'px'}"></i>
- <input accept="image/*" v-if="multiple" multiple ref="uploadInput" @change="handleChange" type="file" :style="{width: 0, height: 0}" name="file" class=" upload-input">
- <input accept="image/*" v-else ref="uploadInput" @change="handleChange" type="file" :style="{width:0, height: 0}" name="file" class=" upload-input">
- </div>
- </div>
- </template>
- <script>
- import Viewer from 'viewerjs'
- import Draggable from 'vuedraggable'
- import { EventBus } from '../../util/event-bus.js'
- import * as qiniu from 'qiniu-js'
- require('viewerjs/dist/viewer.css')
- export default {
- components: {
- Draggable
- },
- props: {
- value: {
- type: Array,
- default: () => []
- },
- width: {
- type: Number,
- default: 100
- },
- height: {
- type: Number,
- default: 100
- },
- token: {
- type: String,
- default: ''
- },
- domain: {
- type: String,
- default: ''
- },
- multiple: {
- type: Boolean,
- default: false
- },
- limit: {
- type: Number,
- default: 9
- },
- isQiniu: {
- type: Boolean,
- default: false
- },
- isDelete: {
- type: Boolean,
- default: false
- },
- min: {
- type: Number,
- default: 0
- },
- meitu: {
- type: Boolean,
- default: false
- },
- isEdit: {
- type: Boolean,
- default: false
- },
- action: {
- type: String,
- default: ''
- },
- disabled: {
- type: Boolean,
- default: false
- },
- readonly: {
- type: Boolean,
- default: false
- },
- headers: {
- type: Array,
- default: () => []
- },
- ui: {
- type: String,
- default: 'element'
- }
- },
- data () {
- return {
- fileList: this.value.map(item => {
- return {
- ...item,
- key: item.key ? item.key : (new Date().getTime()) + '_' + Math.ceil(Math.random() * 99999),
- }
- }),
- viewer: null,
- uploadId: 'upload_' + new Date().getTime(),
- editIndex: -1,
- meituIndex: -1,
- }
- },
- computed: {
- miniWidth () {
- if (this.width > this.height) {
- return this.height
- } else {
- return this.width
- }
- }
- },
- methods: {
- handleChange () {
- console.log(this.$refs.uploadInput.files)
- const files = this.$refs.uploadInput.files
-
- for (let i = 0; i < files.length; i++) {
- const file = files[i]
- const reader = new FileReader()
- const key = (new Date().getTime()) + '_' + Math.ceil(Math.random() * 99999)
- reader.readAsDataURL(file)
- reader.onload = () => {
-
- if (this.editIndex >= 0) {
- this.$set(this.fileList, this.editIndex, {
- key,
- url: reader.result,
- percent: 0,
- status: 'uploading'
- })
- this.editIndex = -1
- } else {
- this.fileList.push({
- key,
- url: reader.result,
- percent: 0,
- status: 'uploading'
- })
- }
- this.$nextTick(() => {
- if (this.isQiniu) {
- this.uplaodAction2(reader.result, file, key)
- } else {
- this.uplaodAction(reader.result, file, key)
- }
- })
- }
- }
- this.$refs.uploadInput.value = []
- },
- uplaodAction (res, file, key) {
- let changeIndex = this.fileList.findIndex(item => item.key === key)
- console.log(this.fileList.findIndex(item => item.key === key))
- const xhr = new XMLHttpRequest()
-
- const url = this.action
- xhr.open('POST', url, true)
- // xhr.setRequestHeader('Content-Type', 'multipart/form-data')
- this.headers.map(item => {
- xhr.setRequestHeader(item.key, item.value)
- })
- let formData = new FormData()
- formData.append('file', file)
- formData.append('fname', file.name)
- formData.append('key', key)
- xhr.send(formData)
- xhr.onreadystatechange = () => {
- console.log(xhr)
- if (xhr.readyState === 4) {
-
- let resData = JSON.parse(xhr.response)
- if (resData && resData.url) {
- this.$set(this.fileList, this.fileList.findIndex(item => item.key === key), {
- ...this.fileList[this.fileList.findIndex(item => item.key === key)],
- url: resData.url,
- percent: 100,
- ...resData
- })
- setTimeout(() => {
- this.$set(this.fileList, this.fileList.findIndex(item => item.key === key), {
- ...this.fileList[this.fileList.findIndex(item => item.key === key)],
- status: 'success'
- })
- if (this.ui == 'element') {
- this.$emit('input', this.fileList)
- } else {
- EventBus.$emit('on-field-change', this.$attrs.id, this.fileList)
- }
- }, 200)
- } else {
- this.$set(this.fileList, this.fileList.findIndex(item => item.key === key), {
- ...this.fileList[this.fileList.findIndex(item => item.key === key)],
- status: 'error'
- })
- this.fileList.splice(this.fileList.findIndex(item => item.key === key), 1)
- }
- }
- }
- xhr.onprogress = (res) => {
- console.log('progress', res)
- if (res.total && res.loaded) {
- this.$set(this.fileList[this.fileList.findIndex(item => item.key === key)], 'percent', res.loaded/res.total*100)
- }
- }
- },
- uplaodAction2 (res, file, key) {
- const _this = this
- const observable = qiniu.upload(file, key, this.token, {
- fname: key,
- mimeType: []
- }, {
- useCdnDomain: true,
- // region: qiniu.region.z2
- })
- observable.subscribe({
- next (res) {
- _this.$set(_this.fileList[_this.fileList.findIndex(item => item.key === key)], 'percent', parseInt(res.total.percent))
-
- },
- error (err) {
- _this.$set(_this.fileList, _this.fileList.findIndex(item => item.key === key), {
- ..._this.fileList[_this.fileList.findIndex(item => item.key === key)],
- status: 'error'
- })
- _this.fileList.splice(_this.fileList.findIndex(item => item.key === key), 1)
- },
- complete (res) {
- _this.$set(_this.fileList, _this.fileList.findIndex(item => item.key === key), {
- ..._this.fileList[_this.fileList.findIndex(item => item.key === key)],
- url: _this.domain + res.key,
- percent: 100,
- ...res,
- })
- setTimeout(() => {
- _this.$set(_this.fileList, _this.fileList.findIndex(item => item.key === key), {
- ..._this.fileList[_this.fileList.findIndex(item => item.key === key)],
- status: 'success'
- })
-
- if (_this.ui == 'element') {
- _this.$emit('input', _this.fileList)
- } else {
- EventBus.$emit('on-field-change', _this.$attrs.id, _this.fileList)
- }
- }, 200)
- }
- })
- },
- handleRemove (key) {
- this.fileList.splice(this.fileList.findIndex(item => item.key === key), 1)
- this.$nextTick(() => {
- if (this.ui == 'element') {
- this.$emit('input', this.fileList)
- } else {
- EventBus.$emit('on-field-change', this.$attrs.id, this.fileList)
- }
- })
- },
- handleEdit (key) {
-
- this.editIndex = this.fileList.findIndex(item => item.key === key)
-
- this.$refs.uploadInput.click()
- },
- handleMeitu (key) {
- this.$emit('on-meitu', this.fileList.findIndex(item => item.key === key))
- },
- handleAdd () {
- if (!this.disabled) {
- this.editIndex = -1
- this.$refs.uploadInput.click()
- }
- },
- handlePreviewFile (key) {
- this.viewer && this.viewer.destroy()
- this.uploadId = 'upload_' + new Date().getTime()
-
- console.log(this.viewer)
- this.$nextTick(() => {
- this.viewer = new Viewer(document.getElementById(this.uploadId))
- this.viewer.view(this.fileList.findIndex(item => item.key === key))
- })
- }
- },
- watch: {
- value (val) {
- this.fileList = this.value.map(item => {
- return {
- ...item,
- key: item.key ? item.key : (new Date().getTime()) + '_' + Math.ceil(Math.random() * 99999),
- }
- })
- }
- }
- }
- </script>
- <style lang="scss">
- .fm-uplaod-container{
- .is-disabled{
- position: relative;
- &::after{
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- // background: rgba(0,0,0,.1);
- content: '';
- display: block;
- cursor:not-allowed;
- }
- }
- .upload-file{
- margin: 0 10px 10px 0;
- display: inline-flex;
- justify-content: center;
- align-items: center;
- // background: #fff;
- overflow: hidden;
- background-color: #fff;
- border: 1px solid #c0ccda;
- border-radius: 6px;
- box-sizing: border-box;
- position: relative;
- vertical-align: top;
- &:hover{
- .uplaod-action{
- display: flex;
- }
- }
- .uplaod-action{
- position: absolute;
- // top: 0;
- // height: 30px;
- bottom: 0;
- left: 0;
- right: 0;
- background: rgba(0,0,0,0.6);
- display: none;
- justify-content: center;
- align-items: center;
- i{
- color: #fff;
- cursor: pointer;
- margin: 0 5px;
- }
- }
- &.is-success{
- .item-status{
- position: absolute;
- right: -15px;
- top: -6px;
- width: 40px;
- height: 24px;
- background: #00B53A;
- text-align: center;
- transform: rotate(45deg);
- box-shadow: 0 0 1pc 1px rgba(0,0,0,.2);
- &>i{
- font-size: 12px;
- margin-top: 11px;
- color: #fff;
- transform: rotate(-45deg);
- }
- }
- }
- &.uploading{
- &:before{
- display: block;
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: rgba(0,0,0,0.3);
- }
- }
- .upload-progress{
- position: absolute;
- .el-progress__text{
- color: #fff;
- font-size: 16px !important;
- }
- }
- img{
- max-width: 100%;
- max-height: 100%;
- vertical-align: middle;
- }
- }
- .el-upload--picture-card{
- position: relative;
- overflow: hidden;
- .el-icon-plus{
- position: absolute;
- top: 50%;
- left: 50%;
- }
- }
- .upload-input{
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- display: block;
- opacity: 0;
- cursor: pointer;
- }
- .drag-img-list{
- display: inline;
- .ghost{
- position: relative;
- &::after {
- width: 100%;
- height: 100%;
- display: block;
- content: '';
- background: #fbfdff;
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- border: 1px dashed #3bb3c2;
- }
- }
- &>div{
- cursor: move;
- }
- }
- .ant-upload{
- display: inline-block;
- position: relative;
- }
- }
- .viewer-container{
- z-index: 9999 !important;
- }
- </style>
|