<template>
  <!-- 用户头像上传,可裁剪 -->
  <div class="AvatarUpload">
    <a-upload
      action="#"
      :auto-upload="false"
      :show-file-list="false"
      list-type="picture"
      :before-upload="beforePassportUpload"
      @change="changeUpload"
    >
      <div class="view-content">
        <img v-if="imageUrl" :src="imageUrl" />
        <a-icon v-if="!imageUrl" type="plus" />
      </div>
    </a-upload>
    <!-- 图片剪裁 -->
    <MegaModal
      :title="$t('IMAGE_CLIPPING')"
      :visible.sync="dialogVisible"
      append-to-body
      width="50%"
      @cancel="() => (dialogVisible = false)"
    >
      <div class="cropper-content">
        <div class="cropper" style="text-align: center">
          <vueCropper
            ref="cropper"
            high
            can-scale
            mode="cover"
            :img="option.img"
            :output-size="option.outputSize"
            :output-type="option.outputType"
            :info="option.info"
            :auto-crop="option.autoCrop"
            :auto-crop-width="option.autoCropWidth"
            :auto-crop-height="option.autoCropHeight"
            :fixed="option.fixed"
            :fixed-box="option.fixedBox"
            :fixed-number="option.fixedNumber"
            @realTime="realTime"
          />
        </div>
        <div class="preview-content">
          <!-- 预览 -->
          <span class="preview-text">{{ $t("PREVIEW") }}</span>
          <div class="show-preview">
            <div :style="previews.div" class="preview">
              <img
                :src="previews.url"
                :style="{ ...previews.img, maxWidth: 'none' }"
              />
            </div>
          </div>
        </div>
      </div>
      <div slot="footer" class="dialog-footer">
        <a-button type="primary" @click="finish()">
          <Icon type="icon-cur-save_1" :size="18" />{{ $t("SAVE") }}</a-button
        >
        <a-button @click="dialogVisible = false"
          ><Icon type="icon-dir-f-rollback" :size="18" />
          {{ $t("CANCEL") }}</a-button
        >
      </div>
    </MegaModal>
  </div>
</template>
<script>
import { VueCropper } from "vue-cropper";
import { Modal as MegaModal, Icon } from "@mega-design/ui-vue";
import { fetchFileUrl } from "@/utils/file";

export default {
  name: "AvatarUpload",
  components: {
    VueCropper,
    MegaModal,
    Icon,
  },
  props: {
    // 配合v-model 加载初始值
    value: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      imageUrl: "",
      dialogVisible: false,
      // 裁剪组件的基础配置option
      option: {
        img: "", // 裁剪图片的地址
        info: true, // 裁剪框的大小信息
        outputSize: 1, // 裁剪生成图片的质量
        outputType: "png", // 裁剪生成图片的格式
        canScale: true, // 图片是否允许滚轮缩放
        autoCrop: true, // 是否默认生成截图框
        autoCropWidth: 180, // 默认生成截图框宽度
        autoCropHeight: 180, // 默认生成截图框高度
        fixedBox: true, // 固定截图框大小 不允许改变
        fixed: true, // 是否开启截图框宽高固定比例
        fixedNumber: [1, 1], // 截图框的宽高比例
        full: false, // 是否输出原图比例的截图
        canMoveBox: false, // 截图框能否拖动
        original: false, // 上传图片按照原始比例渲染
        centerBox: false, // 截图框是否被限制在图片里面
        infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
        canMove: true,
      },
      previews: {},
      picsList: [], // 页面显示的数组
      // 防止重复提交
      loading: false,
      fileinfo: {},
    };
  },
  // 监听父组件值是否在变化
  watch: {
    value(newValue, oldValue) {
      // 有些页面初始初始src没有赋值
      if (!newValue) return;
      this.imageUrl = fetchFileUrl(newValue, this);
    },
  },
  created() {
    this.imageUrl = this.value;
  },
  methods: {
    // 限制图片大小
    // eslint-disable-next-line consistent-return
    beforePassportUpload(file) {
      const suffixs = [".png", ".jpg", ".gif", ".jepg", ".jpeg"];
      const i = file.name.lastIndexOf(".");
      const suffix = file.name.slice(i);
      if (!suffixs.includes(suffix)) {
        this.$message.error(this.$t("PICTURE_FORMAT_ERROR")); // 文件格式错误！
        return false;
      }
      const isLt5M = file.size / 1024 / 1024 < 5;
      if (!isLt5M) {
        this.$message.error(this.$t("FILESIZE_WARNING")); // 上传文件大小不能超过 5MB!
        return false;
      }
    },
    // 上传按钮
    changeUpload(file) {
      if (file.file.status === "done") {
        this.$nextTick(() => {
          this.getBase64(file.file.originFileObj, (imageUrl) => {
            this.option.img = imageUrl;
            this.dialogVisible = true;
          });
        });
      }
    },
    getBase64(img, callback) {
      const reader = new FileReader();
      reader.addEventListener("load", () => callback(reader.result));
      reader.readAsDataURL(img);
    },
    // 实时预览函数
    realTime(data) {
      this.previews = data;
    },
    // 上传图片（点击上传按钮）
    finish(type) {
      const formData = new FormData();
      // 输出
      this.$refs.cropper.getCropBlob((data) => {
        this.imageUrl = window.URL.createObjectURL(data);
        // Blob 转 File
        const suffix = {
          jpeg: "jpg",
          png: "png",
          webp: "webp",
        }[this.option.outputType];
        const time = new Date().getTime();
        const file = new File([data], `${time}.${suffix}`, {
          type: `image/${this.option.outputType}`,
        });
        formData.append("files", file);
        this.$axios.post("/core/api/sys/file", formData).then((res) => {
          this.$emit("input", res.data.data[0].fileUrl);
          this.$emit("uploadSuccess", res.data.data[0].fileUrl);
          this.dialogVisible = false;
        });
      });
    },
  },
};
</script>
<style lang="less" scoped>
@import (optional, once) "@/theme";

.AvatarUpload {
  position: relative;
  width: 180px;
  height: 180px;
  .login-name {
    position: absolute;
    right: 62px;
    bottom: -34px;
    color: @primary-color;
    font-size: 14px;
    cursor: pointer;
  }
}
/deep/.view-content {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border: 1px dashed #ccc;
  border-radius: 50%;
}
/deep/img {
  width: 100%;
  height: 100%;
}

/deep/.vue-cropper {
  width: 500px;
  height: 400px;
}
/deep/.cropper-content {
  display: flex;
  justify-content: space-between;
  width: 100% !important;
  height: 400px;
}
/deep/.preview-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 360px;
  margin-left: 130px;
  .preview-text {
    margin-bottom: 20px;
    font-size: 21px;
  }
  .show-preview {
    width: 180px;
    height: 180px;
    margin: 5px;
    overflow: hidden;
    border-radius: 50%;
  }
  .reupload {
    margin-top: 50px;
  }
}
/deep/.cropper {
  width: 500px;
  height: 400px;
  background: #fff;
}
/deep/.ant-upload-list {
  display: none;
}
</style>
