<template>
  <view class="image-uploader">
    <up-upload
      :source-type="['camera', 'album']"
      :fileList="fileList"
      @afterRead="handleAfterRead"
      @delete="handleDelete"
      :maxCount="maxCount"
      :previewFullImage="true"
      :multiple="multiple"
      :disabled="disabled"
      :deletable="!disabled"
    >
      <view class="upload-btn" v-if="fileList.length < maxCount">
        <u-icon name="plus" size="40" color="#c0c4cc"></u-icon>
      </view>
    </up-upload>
  </view>
</template>

<script setup>
import { ref, watch } from "vue";
import { $upload, Toast } from "@/utils";
import { t } from "@/locale";

const props = defineProps({
  // 初始图片列表
  modelValue: {
    type: Array,
    default: () => [],
  },
  // 最大上传数量
  maxCount: {
    type: Number,
    default: 1,
  },
  // 是否多选
  multiple: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  // 上传按钮文字
  uploadText: {
    type: String,
    default: "上传图片",
  },
  // 上传接口地址
  uploadUrl: {
    type: String,
    default: "",
  },
});

const emit = defineEmits(["update:modelValue", "success", "delete", "error"]);

const uToast = ref(null);
const fileList = ref([]);

// 监听父组件传入的值
watch(
  () => props.modelValue,
  (newVal) => {
    fileList.value = newVal.map((item) => {
      return typeof item === "string" ? { url: item } : item;
    });
  },
  { immediate: true }
);

// 文件读取完成后处理
const handleAfterRead = async (event) => {
  const files = event.file;
  try {
    const uploadFiles = Array.isArray(files) ? files : [files];
    const results = await Promise.all(
      uploadFiles.map((file) => {
        return $upload(file.url);
      })
    );
    const newFiles = results.map((res) => ({
      url: res.data.url,
      name: res.data.name,
      status: "success",
    }));
    fileList.value = [...fileList.value, ...newFiles];
    emit("update:modelValue", fileList.value);
    emit("success", newFiles);
    Toast(t("成功"));
  } catch (error) {
    emit("error", error);
    Toast(t("失败"));
  }
};

const handleDelete = (event) => {
  const { index } = event;
  const deletedFile = fileList.value[index];
  fileList.value.splice(index, 1);
  emit("update:modelValue", fileList.value);
  emit("delete", deletedFile);
};

defineExpose({
  clearFiles: () => {
    fileList.value = [];
    emit("update:modelValue", []);
  },
});
</script>

<style lang="less" scoped>
.image-uploader {
  padding: 10rpx;

  .upload-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 150rpx;
    height: 150rpx;
    border: 1px dashed #c0c4cc;
    border-radius: 8rpx;
    background-color: #f5f7fa;

    .upload-text {
      margin-top: 10rpx;
      font-size: 24rpx;
      color: #909399;
    }
  }
}
</style>