|
@@ -0,0 +1,544 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <div v-if="type !== 'callback'" class="imgcomp-upload-list" v-for="item in uploadList">
|
|
|
+ <template v-if="item.status === 'finished'">
|
|
|
+ <div class="imgcomp-upload-img" v-bind:style="{ 'background-image': 'url(' + __thumb(item.thumb) + ')' }"></div>
|
|
|
+ <div class="imgcomp-upload-list-cover">
|
|
|
+ <Icon type="ios-eye-outline" @click.native="handleView(item)"></Icon>
|
|
|
+ <Icon type="ios-trash-outline" @click.native="handleRemove(item)"></Icon>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <Progress v-if="item.showProgress" :percent="item.percentage" hide-info></Progress>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ <div class="add-box" v-bind:class="{ 'callback-add-box': type === 'callback' }">
|
|
|
+ <div class="add-box-icon">
|
|
|
+ <Icon type="md-add" size="32"></Icon>
|
|
|
+ </div>
|
|
|
+ <div class="add-box-upload">
|
|
|
+ <div class="add-box-item" @click="browsePicture">
|
|
|
+ <span>浏览<em v-if="type === 'callback'">图片</em></span>
|
|
|
+ </div>
|
|
|
+ <div class="add-box-item">
|
|
|
+ <Upload
|
|
|
+ name="image"
|
|
|
+ ref="upload"
|
|
|
+ accept="image/*"
|
|
|
+ :action="actionUrl"
|
|
|
+ :data="params"
|
|
|
+ :show-upload-list="false"
|
|
|
+ :max-size="2048"
|
|
|
+ :format="['jpg', 'jpeg', 'gif', 'png']"
|
|
|
+ :default-file-list="defaultList"
|
|
|
+ :on-success="handleSuccess"
|
|
|
+ :on-format-error="handleFormatError"
|
|
|
+ :on-exceeded-size="handleMaxSize"
|
|
|
+ :before-upload="handleBeforeUpload"
|
|
|
+ :multiple=multiple>
|
|
|
+ <span>上传<em v-if="type === 'callback'">图片</em></span>
|
|
|
+ </Upload>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <Modal title="浏览图片空间的图片" v-model="browseVisible" class="img-upload-modal" width="710" :styles="{top: '35px',paddingBottom: '35px'}">
|
|
|
+ <div class="browse-load" v-if="isLoading">加载中...</div>
|
|
|
+ <div class="browse-list" :class="httpType==='input'?'browse-list-disabled':''" ref="browselistbox">
|
|
|
+ <div class="browse-item" v-for="item in browseList" @click="browseItem(item)">
|
|
|
+ <Icon v-if="item.active" class="browse-icon" type="ios-checkmark-circle"></Icon>
|
|
|
+ <div class="browse-img" v-bind:style="{ 'background-image': 'url(' + item.thumb + ')' }"></div>
|
|
|
+ <div class="browse-title">{{item.title}}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div slot="footer" class="img-upload-foot">
|
|
|
+ <div v-if="type !== 'callback' && http && httpType===''" class="img-upload-foot-input" @click="httpType='input'">
|
|
|
+ <Icon type="ios-image" size="22"/>
|
|
|
+ <div class="img-upload-foot-httptitle">自定义图片地址</div>
|
|
|
+ </div>
|
|
|
+ <div v-if="type !== 'callback' && http && httpType==='input'" class="img-upload-foot-input">
|
|
|
+ <Input v-model="httpValue" placeholder="以“http://”或“https://”开头" @on-search="httpEnter" search enter-button="确定">
|
|
|
+ <span slot="prepend" @click="httpType=''" style="cursor:pointer">自定义地址:</span>
|
|
|
+ </Input>
|
|
|
+ </div>
|
|
|
+ <Button v-if="httpType===''" @click="browseVisible=false">关闭</Button>
|
|
|
+ <Button v-if="httpType===''" type="primary" @click="handleCallback(true)">完成</Button>
|
|
|
+ </div>
|
|
|
+ </Modal>
|
|
|
+ <Modal title="查看图片" v-model="visible" class="img-upload-modal" draggable>
|
|
|
+ <div style="max-height:480px;overflow:auto;">
|
|
|
+ <a :href="imgVisible" target="_blank"><img :src="imgVisible" v-if="visible" style="max-width:100%;max-height:900px;display:block;margin:0 auto"></a>
|
|
|
+ </div>
|
|
|
+ </Modal>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+ .img-upload-modal {
|
|
|
+ .ivu-modal-mask {
|
|
|
+ z-index: 1001;
|
|
|
+ }
|
|
|
+ .ivu-modal-no-mask {
|
|
|
+ background-color: rgba(55,55,55,.2);
|
|
|
+ }
|
|
|
+ .ivu-modal-wrap {
|
|
|
+ z-index: 1001;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .imgcomp-upload-list{
|
|
|
+ display: inline-block;
|
|
|
+ width: 60px;
|
|
|
+ height: 60px;
|
|
|
+ text-align: center;
|
|
|
+ line-height: 60px;
|
|
|
+ border: 1px solid transparent;
|
|
|
+ border-radius: 4px;
|
|
|
+ overflow: hidden;
|
|
|
+ background: #fff;
|
|
|
+ position: relative;
|
|
|
+ box-shadow: 0 1px 1px rgba(0,0,0,.2);
|
|
|
+ margin-right: 4px;
|
|
|
+ vertical-align: top;
|
|
|
+ .imgcomp-upload-img {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background-position: center;
|
|
|
+ background-size: cover;
|
|
|
+ }
|
|
|
+ .imgcomp-upload-list-cover{
|
|
|
+ display: none;
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ background: rgba(0,0,0,.6);
|
|
|
+ }
|
|
|
+ .imgcomp-upload-list-cover i{
|
|
|
+ color: #fff;
|
|
|
+ font-size: 24px;
|
|
|
+ cursor: pointer;
|
|
|
+ vertical-align: middle;
|
|
|
+ margin: 0;
|
|
|
+ transition: all .2s;
|
|
|
+ }
|
|
|
+ .imgcomp-upload-list-cover i:hover{
|
|
|
+ font-size: 28px;
|
|
|
+ }
|
|
|
+ .ivu-progress-outer {
|
|
|
+ background-color: rgba(0, 0, 0, 0.68);
|
|
|
+ .ivu-progress-inner{
|
|
|
+ width: 88%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .imgcomp-upload-list:hover .imgcomp-upload-list-cover{
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+ .img-upload-foot {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: flex-end;
|
|
|
+ .img-upload-foot-input {
|
|
|
+ flex: 1;
|
|
|
+ text-align: left;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: flex-end;
|
|
|
+ .img-upload-foot-httptitle {
|
|
|
+ cursor: pointer;
|
|
|
+ padding-left: 3px;
|
|
|
+ margin-right: 22px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .add-box {
|
|
|
+ width: 60px;
|
|
|
+ height: 60px;
|
|
|
+ line-height: 60px;
|
|
|
+ display: inline-block;
|
|
|
+ background: #fff;
|
|
|
+ border: 1px dashed #dddee1;
|
|
|
+ border-radius: 4px;
|
|
|
+ text-align: center;
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+ vertical-align: top;
|
|
|
+ .add-box-icon {
|
|
|
+ i {
|
|
|
+ vertical-align:middle;
|
|
|
+ padding-bottom: 2px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .add-box-upload {
|
|
|
+ display: none;
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ height: 100%;
|
|
|
+ width: 100%;
|
|
|
+ color: #ffffff;
|
|
|
+ padding-top: 9px;
|
|
|
+ background: rgba(0, 0, 0, 0.6);
|
|
|
+ .add-box-item {
|
|
|
+ height: 22px;
|
|
|
+ line-height: 22px;
|
|
|
+ cursor: pointer;
|
|
|
+ .ivu-upload-drag,.ivu-upload-drag:hover {
|
|
|
+ background:transparent;
|
|
|
+ border:0;
|
|
|
+ border-radius:0;
|
|
|
+ }
|
|
|
+ span {
|
|
|
+ transition: all .2s;
|
|
|
+ font-size: 12px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .add-box-item:hover {
|
|
|
+ span {
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ em {
|
|
|
+ font-style: normal;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .add-box:hover {
|
|
|
+ border-color: rgba(0,0,0,.6);
|
|
|
+ .add-box-upload {
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .callback-add-box {
|
|
|
+ display: block;
|
|
|
+ width: auto;
|
|
|
+ height: 25px;
|
|
|
+ line-height: 25px;
|
|
|
+ border: 0;
|
|
|
+ background: transparent;
|
|
|
+ .add-box-icon {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+ .add-box-upload {
|
|
|
+ display: block;
|
|
|
+ width: auto;
|
|
|
+ background: transparent;
|
|
|
+ color: #333;
|
|
|
+ padding: 0;
|
|
|
+ > div {
|
|
|
+ display: inline-block;
|
|
|
+ padding-right: 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .browse-load {
|
|
|
+ margin: 20px;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ .browse-list {
|
|
|
+ max-height: 540px;
|
|
|
+ overflow: auto;
|
|
|
+ .browse-item {
|
|
|
+ margin: 10px 15px;
|
|
|
+ display: inline-block;
|
|
|
+ text-align: center;
|
|
|
+ cursor: pointer;
|
|
|
+ position: relative;
|
|
|
+ .browse-img {
|
|
|
+ width: 64px;
|
|
|
+ height: 64px;
|
|
|
+ background-image: url("../../../statics/images/loading.png");
|
|
|
+ background-position: center;
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-size: cover;
|
|
|
+ }
|
|
|
+ .browse-title {
|
|
|
+ display: block;
|
|
|
+ width: 64px;
|
|
|
+ margin-top: 5px;
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ }
|
|
|
+ .browse-icon {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 64px;
|
|
|
+ font-size: 36px;
|
|
|
+ padding-top: 15px;
|
|
|
+ color: #ffffff;
|
|
|
+ background-color: rgba(0, 0, 0, 0.5);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .browse-list-disabled {
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+ .browse-list-disabled:after {
|
|
|
+ position: absolute;
|
|
|
+ content: '';
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background-color: rgba(255, 255, 255, 0.9);
|
|
|
+ z-index: 1;
|
|
|
+ }
|
|
|
+</style>
|
|
|
+<script>
|
|
|
+ export default {
|
|
|
+ name: 'ImgUpload',
|
|
|
+ props: {
|
|
|
+ value: {
|
|
|
+ },
|
|
|
+ num: {
|
|
|
+ },
|
|
|
+ width: {
|
|
|
+ },
|
|
|
+ height: {
|
|
|
+ },
|
|
|
+ type: {
|
|
|
+ },
|
|
|
+ http: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data () {
|
|
|
+ return {
|
|
|
+ actionUrl: $A.aUrl('imgupload'),
|
|
|
+ params: {'token': $A.token(), 'width': this.width, 'height': this.height},
|
|
|
+ multiple: this.num > 1,
|
|
|
+ visible: false,
|
|
|
+ browseVisible: false,
|
|
|
+ isLoading: false,
|
|
|
+ browseList: [],
|
|
|
+ browseListNext: [],
|
|
|
+ imgVisible: '',
|
|
|
+ defaultList: this.initItems(this.value),
|
|
|
+ uploadList: [],
|
|
|
+ maxNum: Math.min(Math.max($A.runNum(this.num), 1), 99),
|
|
|
+ httpValue: '',
|
|
|
+ httpType: '',
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted () {
|
|
|
+ this.uploadList = this.$refs.upload.fileList;
|
|
|
+ this.$emit('input', this.uploadList);
|
|
|
+ //
|
|
|
+ let browseBox = $A(this.$refs.browselistbox);
|
|
|
+ browseBox.scroll(()=>{
|
|
|
+ let nHight = browseBox[0].scrollHeight;
|
|
|
+ let nTop = browseBox[0].scrollTop;
|
|
|
+ let boxHight = browseBox.height();
|
|
|
+ if(nTop + boxHight >= nHight) {
|
|
|
+ //到底了
|
|
|
+ if (this.browseListNext.length > 0) {
|
|
|
+ let tmpNext = this.browseListNext;
|
|
|
+ this.browseListNext = [];
|
|
|
+ this.browsePictureFor(tmpNext);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ value (val) {
|
|
|
+ if (typeof val === 'string') {
|
|
|
+ this.$emit('input', this.initItems(val));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (val === this.$refs.upload.fileList) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.$refs.upload.fileList = this.initItems(val);
|
|
|
+ this.uploadList = this.$refs.upload.fileList;
|
|
|
+ },
|
|
|
+ browseVisible() {
|
|
|
+ this.httpType = '';
|
|
|
+ this.httpValue = '';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ handleCallback(file) {
|
|
|
+ if (this.type === 'callback') {
|
|
|
+ if (file === true) {
|
|
|
+ this.$emit('on-callback', this.uploadList);
|
|
|
+ this.$refs.upload.fileList = [];
|
|
|
+ this.uploadList = this.$refs.upload.fileList;
|
|
|
+ }else if (typeof file === "object") {
|
|
|
+ this.$emit('on-callback', [file]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.browseVisible = false;
|
|
|
+ },
|
|
|
+ initItems(items) {
|
|
|
+ //数据初始化
|
|
|
+ if (typeof items === 'string') {
|
|
|
+ items = [{'url': items}];
|
|
|
+ }
|
|
|
+ let lists = [];
|
|
|
+ $A.each(items, (index, item)=>{
|
|
|
+ if (typeof item === 'string') item = {'url': item};
|
|
|
+ if (item.url) {
|
|
|
+ item.active = true;
|
|
|
+ item.status = 'finished';
|
|
|
+ if (typeof item.path === 'undefined') item.path = item.url;
|
|
|
+ if (typeof item.thumb === 'undefined') item.thumb = item.url;
|
|
|
+ lists.push(item);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return lists;
|
|
|
+ },
|
|
|
+ handleView (item) {
|
|
|
+ //查看
|
|
|
+ this.visible = true;
|
|
|
+ this.imgVisible = item.url;
|
|
|
+ },
|
|
|
+ handleRemove (item) {
|
|
|
+ //删除
|
|
|
+ let fileList = this.$refs.upload.fileList;
|
|
|
+ this.$refs.upload.fileList.splice(fileList.indexOf(item), 1);
|
|
|
+ this.$emit('input', this.$refs.upload.fileList);
|
|
|
+ },
|
|
|
+ handleSuccess (res, file) {
|
|
|
+ //上传完成
|
|
|
+ if (res.ret === 1) {
|
|
|
+ file.url = res.data.url;
|
|
|
+ file.path = res.data.path;
|
|
|
+ file.thumb = res.data.thumb;
|
|
|
+ this.handleCallback(file);
|
|
|
+ }else{
|
|
|
+ this.$Modal.warning({
|
|
|
+ title: '上传失败',
|
|
|
+ content: '文件 ' + file.name + ' 上传失败,' + res.msg
|
|
|
+ });
|
|
|
+ this.$refs.upload.fileList.pop();
|
|
|
+ }
|
|
|
+ this.$emit('input', this.$refs.upload.fileList);
|
|
|
+ },
|
|
|
+ handleFormatError (file) {
|
|
|
+ //上传类型错误
|
|
|
+ this.$Modal.warning({
|
|
|
+ title: '文件格式不正确',
|
|
|
+ content: '文件 ' + file.name + ' 格式不正确,请上传 jpg、jpeg、gif、png 格式的图片。'
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleMaxSize (file) {
|
|
|
+ //上传大小错误
|
|
|
+ this.$Modal.warning({
|
|
|
+ title: '超出文件大小限制',
|
|
|
+ content: '文件 ' + file.name + ' 太大,不能超过 2M。'
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleBeforeUpload () {
|
|
|
+ //上传前判断
|
|
|
+ let check = this.uploadList.length < this.maxNum;
|
|
|
+ if (!check) {
|
|
|
+ this.$Modal.warning({ title: '温馨提示', content: '最多只能上传 ' + this.maxNum + ' 张图片。' });
|
|
|
+ }
|
|
|
+ return check;
|
|
|
+ },
|
|
|
+ handleClick() {
|
|
|
+ //手动上传
|
|
|
+ if (this.handleBeforeUpload()) {
|
|
|
+ this.$refs.upload.handleClick()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ browsePicture(path) {
|
|
|
+ //获取图片空间
|
|
|
+ this.browseVisible = true;
|
|
|
+ this.browseList = [];
|
|
|
+ this.browseListNext = [];
|
|
|
+ this.isLoading = true;
|
|
|
+ $A.aAjax({
|
|
|
+ url: 'imgview',
|
|
|
+ data: { path: path?path:'' },
|
|
|
+ beforeSend: true,
|
|
|
+ complete: true,
|
|
|
+ error: true,
|
|
|
+ success: (res) => {
|
|
|
+ this.isLoading = false;
|
|
|
+ if (res.ret === 1) {
|
|
|
+ let dirs = res.data['dirs'];
|
|
|
+ for (let i = 0; i < dirs.length; i++) {
|
|
|
+ this.browseList.push(dirs[i]);
|
|
|
+ }
|
|
|
+ this.browsePictureFor(res.data['files']);
|
|
|
+ }else if (res.ret === -2) {
|
|
|
+ this.browseVisible = false;
|
|
|
+ this.$Modal.warning({ title: '温馨提示', content: res.msg });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ browsePictureFor(files) {
|
|
|
+ for (let o = 0; o < files.length; o++) {
|
|
|
+ for (let j = 0; j < this.uploadList.length; j++) {
|
|
|
+ if (this.uploadList[j]['url'] === files[o]['url']
|
|
|
+ || this.uploadList[j]['url'] === files[o]['path']) {
|
|
|
+ files[o]['active'] = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (o < 100) {
|
|
|
+ this.browseList.push(files[o]);
|
|
|
+ }else{
|
|
|
+ this.browseListNext.push(files[o]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ browseItem(item) {
|
|
|
+ //点击选择图片
|
|
|
+ if (item.type === 'dir') {
|
|
|
+ //目录
|
|
|
+ this.browsePicture(item.path);
|
|
|
+ }else if (item.type === 'file') {
|
|
|
+ //文件
|
|
|
+ if (item.active) {
|
|
|
+ let fileList = this.$refs.upload.fileList;
|
|
|
+ this.$refs.upload.fileList.splice(fileList.indexOf(item), 1);
|
|
|
+ item.active = false;
|
|
|
+ }else{
|
|
|
+ if (this.maxNum === 1) {
|
|
|
+ for (let i = 0; i < this.browseList.length; i++) {
|
|
|
+ this.browseList[i].active = false;
|
|
|
+ }
|
|
|
+ this.$refs.upload.fileList = [];
|
|
|
+ this.uploadList = this.$refs.upload.fileList;
|
|
|
+ }
|
|
|
+ let check = this.uploadList.length < this.maxNum;
|
|
|
+ if (!check) {
|
|
|
+ this.$Modal.warning({ title: '温馨提示', content: '最多只能选择 ' + this.maxNum + ' 张图片。' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ item.active = true;
|
|
|
+ item.status = 'finished';
|
|
|
+ this.$refs.upload.fileList.push(item);
|
|
|
+ this.uploadList = this.$refs.upload.fileList;
|
|
|
+ }
|
|
|
+ this.$emit('input', this.$refs.upload.fileList);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ __thumb(url) {
|
|
|
+ if ($A.strExists(url, "?", false)) {
|
|
|
+ return url + "&__thumb=true";
|
|
|
+ }else{
|
|
|
+ return url + "?__thumb=true";
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ httpEnter() {
|
|
|
+ this.$emit('input', this.initItems(this.httpValue));
|
|
|
+ this.browseVisible = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+</script>
|