<style scoped lang="scss">


.upload-btn {
  width: 60px;
  height: 60px;
  line-height: 60px;
  text-align: center;
  border: 1px dashed #dddddd;
  border-radius: 2px;
  cursor: pointer;
  transition:all 0.5s;
  margin-left: 5px;

  &:hover{
    border:1px dashed var(--el-color-primary)

  }
}

.tips {
  position: absolute;
  font-size: 8px;
  color: #FE526A;
  display: inline-block;
  bottom: -15px;
}


::v-deep(.el-form-item--default .el-form-item__content) {
  display: none;
}

::v-deep(.el-upload-list) {
  display: none !important;
}
</style>
<template>
  <div style="display:flex;align-items:center;min-width: 200px;padding: 10px 0;">
    <canvas v-if="!readonly&&mime==='image'"  id="uploadCanvasId" style="display: none;"></canvas>
      <div style="display: flex;flex-wrap: wrap;width: 100%" v-if="state.files.length>0">
        <draggable
            style="width: 100%"
            :list="state.files"
            itemKey="name"
            ghost-class="ghost"
            chosen-class="chosenClass"
            animation="300"
            @start="onMove"
            @end="onEnd">
          <template #item="{element,index}">
            <div v-if="isAvatar"  class="hp">
              <el-avatar :src="u.fmt.fmtImg(element.uid)" :size="60"/>
              <SvgIcon name="ele-CircleCloseFilled" color="red" class="hc" @click="handleDeleteItem(0)"/>
            </div>
            <Attach v-else  :attach="element" @on-delete="handleDeleteItem(index)"/>
          </template>
        </draggable>
      </div>

    <el-upload
        v-if="!readonly&&state.files.length<limit"
        ref="upload"
        :multiple="multiple"
        :limit="limit"
        :show-upload-list="false"
        :before-upload="beforeUpload"
        :on-success="handleUploadSuccess"
        :max-size="maxSize||2048"
        :accept="state.accept"
        :data="state.uploadData"
        :on-error="handleError"
        :on-exceed="handleUploadMaxSize"
        :on-progress="handleUploadProgress"
        :action="uploadUrl"
        style="display: inline-block;">
      <div class="upload-btn">
        <SvgIcon size="20" :name="mime==='image'?'ele-Picture':'ele-Paperclip'"/>
      </div>
      <el-progress status="success" style="width: 80px;"
                   :percentage="Number(state.percent)"
                   :stroke-color="['#108ee9', '#87d068']" :stroke-width="5"
                   v-if="state.percent>0&&state.percent<100"/>
    </el-upload>


    <br>
    <!--    <div v-if="readonly&&!value" class="upload-btn">-->
    <!--      <SvgIcon size="20" :name="mime==='image'?'ele-Picture':'ele-Paperclip'"/>-->
    <!--    </div>-->

    <div class="tips" v-if="tips">{{ tips }}</div>
  </div>
</template>
<script setup lang="ts" name="ExtUpload">
import draggable from "vuedraggable";
import {reactive, onMounted, computed, watch, onBeforeMount} from 'vue';
import {UploadRawFile} from 'element-plus';
import {$body} from "/@/utils/request";
import u from "/@/utils/u";
import {Session} from "/@/utils/storage";
import {Msg} from "/@/utils/message";
import Attach from "/@/components/attach/Attach.vue";


const props = defineProps({
  modelValue: {
    type: [Object, Array, String]
  },
  maxSize: {
    type: Number,
    require: true,
    default: 10240
  },
  mime: {
    type: String,
    require: true,
    default: 'image'
  },
  tips: {
    type: String
  },
  multiple: {
    type: Boolean,
    default: false
  },
  readonly: {
    type: Boolean,
    default: false
  },
  limit: {
    type: Number,
    default:1
  },
  compressed: {
    type: Boolean,
    default: false
  },
  isAvatar:{
    type:Boolean,
    default:false
  }
});


const uploadUrl = computed(() => {
  let token = Session.get('token');
  return `${u.url.server}file/upload?X-Token=${token}`
})

const state = reactive({
  previewUrl: '',
  uploadData: {
    data: undefined as any,
    fileName: undefined as any
  },
  progressInterval: undefined,
  accept: '' as string,
  fileFormat: [] as Array<string>,
  // uploadUrl: `${u.url.server}/file/upload?token=${app.token}`,
  maxLength: props.limit || 1,
  fileLength: 0,
  files: [] as Array<any>,
  spinShow: false,
  images: [] as Array<any>,
  init: false,
  percent: '',
  mode: 'cos',//当前上传模式，空-后台服务器/qiniu-七牛云/cos-腾讯云
  qiniuConfig: {
    useCdnDomain: false,
    region: null
  },
  qiniuExtra: {},
  qiniuUrl: 'http://pxal1j743.bkt.clouddn.com/',
  cosUrl: "https://zyp-1258963180.cos.ap-guangzhou.myqcloud.com/",
  cos: undefined,
  cosConfig: {
    tmpSecretId: undefined,
    tmpSecretKey: undefined,
    sessionToken: undefined,
    expiredTime: undefined,
  },
  editable: false,
  previewImage: null,
  loading: null as any
})

const emit = defineEmits(['update:modelValue','on-change']);

watch(
    () => state.files,
    (val) => {
      console.log(!val,state.files)
      if(!state.files||state.files.length===0){
        if (props.limit && props.limit > 1) {
          emit('update:modelValue', []);
          emit('on-change')
        }else{
          emit('update:modelValue', null);
          emit('on-change')
        }
      }else{
        console.log("watch", state.files)
        if (props.mime !== 'image') {
          if (props.limit && props.limit > 1) {
            emit('update:modelValue', val);
          } else {
            emit('update:modelValue', val[0]);
          }
        } else {
          if (props.limit && props.limit > 1) {
            emit('update:modelValue', state.files.map(k => k.uid));
          } else {
            emit('update:modelValue', state.files[0].uid);
          }
        }
        emit('on-change')
      }
    },
    {
      deep: true
    }
);



onBeforeMount(() => {
  document.body.ondrop = function (event) {
    //组织默认事件
    event.preventDefault();
    //阻止时间冒泡
    event.stopPropagation();
  }
})

onMounted(() => {
  if (!props.limit) {
    state.maxLength = 1;
  } else {
    state.maxLength = Number(props.limit);
  }
  prepareUpload();
  initData();
})

/*const preview = (item: any) => {
  let url = u.fmt.fmtPreview(item.url || item)
  state.previewUrl = url;
  console.log("preview:", item, url)
  previewRef.value.handlePreview();
  /!*  console.log("preview:", item)
    let url = item.url || item;
    let fullUrl = u.fmt.fmtUrl(url);
    // url.indexOf("http") === 0 ? url : u.url.file + url;
    if (!item) {
      return;
    }
    let type = props.mime;
    if (['image', 'video', 'audio'].includes(type)) {
      ElMessage.warning(`预览功能开发中，敬请期待`)
      // app.openModal('ExtPreview', {
      //   url: fullUrl,
      //   type: 'image'
      // })
      // this.previewImage = fullUrl;
      // this.$refs.preview.open();
    } else if (props.mime === 'wps' || props.mime === 'pdf') {
      window.open("http://www.xdocin.com/xdoc?_func=to&_format=html&_cache=true&_xdoc=" + fullUrl, "_blank");
    } else {
      window.open(fullUrl, "_blank")
    }*!/
}*/

const prepareUpload = () => {
  const type = props.mime;
  if (type == 'image') {
    state.accept = "image/*";
    state.fileFormat = ['jpg', 'jpeg', 'png', 'gif', 'svg'];
  } else if (type == 'video') {
    state.accept = "video/*";
    state.fileFormat = ["mp4", "ogg", "avi", "webm"]
  } else if (type == 'audio') {
    state.accept = "audio/*";
    state.fileFormat = ["mp3", "amr", "avi", "wav"]
  } else if (type == 'pdf') {
    state.accept = "application/pdf";
    state.fileFormat = ["pdf"]
  } else if (type == 'wps') {
    state.fileFormat = ["doc", "docx", "xls", "xlsx", "ppt"]
  } else {
    state.accept = "**/*";
  }
  console.log(state.accept, props.mime)
}

/*const contains = (val: any, array: Array<any>) => {
  let contain = false;
  if (val) {
    if (typeof val === "object") {
      for (let i = 0; i < array.length; i++) {
        if (val == array[i].url) {
          contain = true;
          break;
        }
      }
    } else {
      for (let i = 0; i < array.length; i++) {
        if (val == array[i]) {
          contain = true;
          break;
        }
      }
    }
  }
  return contain;
}*/

const initData = () => {
  if (state.init) {
    return
  }
  if (!props.modelValue) {
    return;
  }



    if (props.mime === 'image') {
      if (props.multiple) {
        state.files = props.modelValue.map(k => {
          return {uid: k, name: k}
        })
      } else {
        state.files = [{uid: props.modelValue, name: props.modelValue}]
      }
    } else {
      if (props.multiple) {
        state.files = props.modelValue;
      } else {
        state.files = [props.modelValue]
      }
    }

  state.init = true;
  console.log("init",JSON.stringify(state.files),props.modelValue)
}

/**
 * 图片压缩转base64上传
 * @param image
 */
const compress = (image: any) => {
  const maxWidth = 1920;
  let canvas: any = document.getElementById("uploadCanvasId");
  let ctx = canvas?.getContext("2d");
  // var initImgSize = image.src.length;
  let width = image.width;
  let height = image.height;
  if (width > maxWidth) {
    let ration = maxWidth / width;
    width = maxWidth;
    height = height * ration
  }
  canvas.width = width;
  canvas.height = height;
  //图片过大需要进行瓦片绘制，暂不做处理
  ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
  //进行压缩
  return canvas.toDataURL("image/jpeg", 0.5);
}


const beforeUpload = (file: UploadRawFile) => {
  let originalName = file.name;
  let size = file.size;
  if (size > props.maxSize * 1024) {
    Msg.message(`文件超出大小${(props.maxSize / 1024).toFixed(2)}Mb限制`, 'error')
    return false;
  }
  Msg.showLoading("上传中...")
  //压缩上传
  if (props.compressed && props.mime == 'image') {
    //---压缩base64上传
    let fileReader = new FileReader();
    fileReader.onload = e => {
      try {
        let src = e.target?.result;
        const image = new Image();
        image.setAttribute('crossOrigin', 'anonymous');
        Msg.showLoading("上传中...")
        image.src = src;
        image.onload = function () {
          let width = image.width;
          if (width && width > 1920) {
            let base64Data = compress(image);
            state.uploadData = {
              data: base64Data,
              fileName: file.name
            }
          } else {
            state.uploadData = {
              data: src,
              fileName: originalName
            }
          }
          let token = Session.get("token");
          $body(`/file/uploadBase64?X-Token=${token}`, state.uploadData)
              .then((res: any) => {
                state.init = true;
                state.files.unshift(res);
                Msg.hideLoading();
              }).catch(err => {
            console.error(err)
            Msg.hideLoading();
          });
        };
      } catch (e) {
        Msg.hideLoading();
        console.error(e);
      }
    };
    fileReader.readAsDataURL(file);
    Msg.showLoading("上传中，请稍后...")
    // state.loading = ElLoading.service({text: '上传中，请稍后'});
    // app.showLoading("上传中，请稍后");
    return false;
  } else {
    //---七牛云上传
    if (state.mode === "qiniu") {
      /* var qiniu = require('qiniu-js');
       _this.$get("/file/qnToken").then(res => {
           let fileName = app.randomDateSeq(16) + file.name.substring(file.name.lastIndexOf("."));
           var observable = qiniu.upload(file, fileName, res, _this.qiniuExtra, _this.qiniuConfig)
           observable.subscribe((next) => {
               _this.percent = next.total.percent + "%";
               if (next.total.percent >= 100) {
                   _this.clearProgressInterval();
               }
           }, (error) => {
               console.error("qnUpload ERR", error)
           }, (compelete) => {
               if (this.type === 'image') {
                   this.images.push(_this.qiniuUrl + fileName);
               } else {
                   this.files.push({
                       url: _this.qiniuUrl + fileName,
                       name: originalName
                   });
               }
               _this.clearProgressInterval();
           });
       }).catch(err => {
           _this.clearProgressInterval();
           console.error("qnToken ERR", err)
       });
       app.showLoading("上传中，请稍后");
       //阻止upload的默认上传
       return false;*/
    } else if (state.mode == 'cos') {
      /*      //----腾讯cos文件上传
            state. loading = ElLoading.service({text: '上传中，请稍后'});
            var COS = require('cos-js-sdk-v5');
            let key = app.randomDateSeq(16) + file.name.substring(file.name.lastIndexOf("."));
            if (!_this.cosConfig.expiredTime || _this.cosConfig.expiredTime < new Date().getTime()) {
              _this.$get("/file/cosToken").then(res => {
                _this.cosConfig = res;
                _this.cos = new COS({
                  SecretId: _this.cosConfig.tmpSecretId,
                  SecretKey: _this.cosConfig.tmpSecretKey,
                  XCosSecurityToken: _this.cosConfig.sessionToken,
                  ExpiredTime: _this.cosConfig.expiredTime * 1000,
                });
                _this.cosUpload(key, file);
              }).catch(e => {
                console.error(e)
                _this.clearProgressInterval();
              });
            } else {
              _this.cosUpload(key, file);
            }
            //阻止upload的默认上传
            return false;*/
    } else {
      // _this.spinShow = true;

    }
  }
}

const handleUploadMaxSize = () => {
  Msg.message(`文件超出大小${(props.maxSize / 1024).toFixed(2)}Mb限制`, 'error')
  // ElMessage.error(`文件超出大小${(props.maxSize / 1024).toFixed(2)}Mb限制`)
  clearProgressInterval();
}
/*

const handleUploadFormatError = () => {
  ElMessage.error('请选择正确的文件格式上传');
  clearProgressInterval();
}
*/

const handleUploadSuccess = (res: any) => {
  // Msg.hideLoading();
  Msg.message('上传成功');
  console.log(res)
  state.init = true;
  if (res && res.code === 200) {
    state.files.unshift(res.data)
    /*   if (props.mime === 'image') {
         state.images.unshift(res.data.url);
       } else {
         state.files.unshift({
           id: 0,
           url: res.data.url,
           name: res.data.name,
           size: res.data.size
         });
       }*/
  } else {
    Msg.message('文件上传出错:' + res.msg, 'error')
  }
  clearProgressInterval();
}

const handleUploadProgress = (event: any) => {
  console.log("progress>>>", event)
  state.percent = Number(event.percent).toFixed(0);
  if (event.percent >= 100) {
    clearProgressInterval();
  }
}

const handleError = (error: Error) => {
  Msg.message("上传出错了，请稍后再试", 'error')
  clearProgressInterval();
  console.log(error)
}

const clearProgressInterval = () => {
  state.init = true;
  // this.spinShow = false;
  // state.loading?.close();
  // Msg.hideLoading();
  if (state.progressInterval) {
    clearInterval(state.progressInterval);
  }
}

const handleDeleteItem = (idx: number) => {
  state.files.splice(idx, 1);
  console.log(props.readonly,state.files,props.limit)
}


const onEnd = (event: any) => {
  console.log("location>>>>", event)
}
const onMove = (event: any) => {
  let {relatedContext, draggedContext} = event;
  console.log(relatedContext, draggedContext)
}

</script>
