<template>
  <div>
    <input
      type="hidden"
      v-model="value"
      v-validate="inputValidate"
      :name="inputName"
    />
    <file-upload
      v-if="inputWriteable"
      ref="fileUpload"
      v-model="files"
      :action-url="actionUrl"
      :multiple="multiple"
      :accept="accept"
      :before-upload="beforeUpload"
      :on-success="uploadSuccess"
      @on-progress="handleProgress"
      :on-error="onError"
      :limit="limit"
      :header="header"
      :size="size"
      :readonly="!inputWriteable"
      :withCredentials="withCredentials"
      :auto-upload="autoUpload"
      :http-request="httpRequest"
      @handle-error="handleError"
    >
      <slot slot="append" name="append"></slot>
    </file-upload>
    <ht-field-tail
      :writeable.sync="writeable"
      :fieldName="inputName"
      :inputValue="value"
    />
    <div v-if="progressFlag">
      <p class="progress_msg">努力上传中,请耐心等待</p>
      <el-progress :stroke-width="4" :percentage="progressPercent" />
    </div>
    <el-table
      v-if="filesData && filesData.length > 0 && !isSimple"
      :data="filesData"
      border
      style="width: 98%; margin-top: 10px"
      class="file__upload-table"
      size="medium"
    >
      <el-table-column
        label="序号"
        align="center"
        type="index"
        width="50"
      ></el-table-column>
      <el-table-column label="附件名称" align="center">
        <template slot-scope="scope">
          <span
            :class="{ 'done-subject': previewable }"
            @click="preview(scope.row)"
            >{{ scope.row.name }}</span
          >
        </template>
      </el-table-column>
      <el-table-column
        v-if="calColumnShow.fileType"
        prop="type"
        align="center"
        lalign="center"
        width="100"
        label="附件类型"
      ></el-table-column>
      <el-table-column
        v-if="calColumnShow.fileSize"
        align="center"
        lalign="center"
        width="150"
        label="附件大小"
      >
        <template slot-scope="scope">{{
          scope.row.size | computerSize
        }}</template>
      </el-table-column>
      <el-table-column
        align="center"
        label="上传人"
        width="120"
        prop="username"
      >
      </el-table-column>
      <el-table-column
        v-if="inputWriteable"
        align="center"
        label="状态"
        width="80"
      >
        <template slot-scope="scope">
          <el-progress
            type="circle"
            :width="25"
            :stroke-width="2"
            :percentage="scope.row.percentage"
            :status="scope.row.state || 'warning'"
          ></el-progress>
        </template>
      </el-table-column>
      <el-table-column
        :prop="con.name"
        :label="con.desc"
        v-for="con in propConfList"
        :key="con.name"
        width="200"
        align="center"
      >
        <template slot-scope="scope">
          <ht-input
            v-model="filesData[scope.$index][con.name]"
            :name="con.desc"
            :permission="
              permission == 'w' || permission == 'b'
                ? con.requried
                  ? 'b'
                  : 'w'
                : permission
            "
            @change="syncInput"
          ></ht-input>
        </template>
      </el-table-column>
      <el-table-column
        align="center"
        label="操作"
        v-if="inputWriteable || downloadable"
        :width="operateWidth"
      >
        <template slot-scope="scope">
          <el-button
            @click="move(scope.row, 'up')"
            v-if="inputWriteable"
            size="small"
            icon="el-icon-arrow-up"
            plain
          >
          </el-button>
          <el-button
            @click="move(scope.row, 'down')"
            v-if="inputWriteable"
            size="small"
            icon="el-icon-arrow-down"
            plain
          ></el-button>
          <el-button
            v-if="downloadable"
            @click="download(scope.row)"
            size="small"
            icon="el-icon-download"
            plain
          >
          </el-button>
          <el-button
            @click="removeFile(scope.row)"
            v-if="inputWriteable"
            type="danger"
            size="small"
            icon="el-icon-delete"
            plain
          ></el-button>
        </template>
      </el-table-column>
    </el-table>
    <ul v-else-if="isSimple" class="file-list__wrap">
      <li v-for="(file, index) in filesData" :key="index" class="file-item">
        <i class="file-icon el-icon-document"></i>
        <p
          class="file__name"
          :class="{ 'done-subject': previewable }"
          @click="preview(file)"
        >
          {{ file.name }}
        </p>
        <i
          v-if="downloadable"
          class="file-close__icon el-icon-download"
          @click="download(file)"
        ></i>
        <i
          v-if="inputWriteable"
          class="file-close__icon el-icon-close"
          @click="removeFile(file)"
        ></i>
      </li>
    </ul>
  </div>
</template>
<script>
import utils from "@/utils.js";
import HtFieldTail from "@/components/HtFieldTail.vue";
import FileUpload from "@/components/common/FileUpload.vue";
import Locale from "@/mixins/locale";

export default {
  name: "ht-file",
  mixins: [Locale],
  props: {
    isSimple: {
      type: Boolean,
      default: false,
    },
    withCredentials: {
      type: Boolean,
      default: false,
    },
    actionUrl: {
      type: String,
      default: "https://jsonplaceholder.typicode.com/posts/",
    },
    value: {
      type: String,
    },
    validate: {
      type: Object,
    },
    name: {
      type: String,
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    permission: {
      type: String,
      default: "w",
      validator: function (value) {
        return ["b", "w", "r", "n"].indexOf(value) !== -1;
      },
    },
    accept: {
      type: String,
    },
    limit: {
      type: Number,
    },
    header: {
      type: Object,
    },
    size: {
      type: Number,
    },
    previewable: {
      type: Boolean,
      default: true,
    },
    downloadable: {
      type: Boolean,
      default: true,
    },
    propConfList: {
      type: Array,
      default() {
        return [];
      },
    },
    beforeUpload: {
      type: Function,
    },
    onSuccess: {
      type: Function,
    },
    onError: {
      type: Function,
    },
    columnShow: {
      type: Object,
      default() {
        return {};
      },
    },
    autoUpload: {
      type: Boolean,
      default: true,
    },
    httpRequest: {
      type: Function,
    },
  },
  components: { HtFieldTail, FileUpload },
  data() {
    return {
      operateWidth: this.permission === "r" ? "70" : "260",
      inputName: null,
      writeable: true,
      files: [],
      filesData: [],
      progressPercent: 0,
      progressFlag: false,
    };
  },
  computed: {
    inputWriteable: function () {
      return this.writeable
        ? utils.getWriteable(this.permission)
        : this.writeable;
    },
    inputValidate: function () {
      return utils.addRequiredOrNot(this.permission, this.validate, this);
    },
    calColumnShow: function () {
      let defaultSetting = { fileType: true, fileSize: true };
      return { ...defaultSetting, ...this.columnShow };
    },
  },
  watch: {
    filesData: {
      handler: function () {
        this.emitChange();
      },
    },
    files: function (newVal) {
      if (!newVal || newVal.length == 0) {
        this.filesData = [];
      }
    },
    value(val) {
      if (val && val.constructor === String) {
        if (!val.response) {
          let fileVal = [...JSON.parse(val)];
          //获取附件类型
          for (let i = 0; i < fileVal.length; i++) {
            if (fileVal[i].name && fileVal[i].name.split(".")) {
              fileVal[i].type = this.substringType(fileVal[i].name);
              fileVal[i].state = "success";
              fileVal[i].percentage = 100;
            }
          }
          this.files = fileVal;
          this.filesData = fileVal;
        } else {
          this.files = JSON.parse(val);
          this.filesData = JSON.parse(val);
        }
      }
    },
  },
  created() {
    this.inputName = this.name ? this.name : utils.getName();
    this.$validator = this.$root.$validator;
    if (this.value && this.value.constructor === String) {
      if (!this.value.response) {
        let fileVal = [...JSON.parse(this.value)];
        //获取附件类型
        for (let i = 0; i < fileVal.length; i++) {
          if (fileVal[i].name && fileVal[i].name.split(".")) {
            fileVal[i].type = this.substringType(fileVal[i].name);
            fileVal[i].state = "success";
            fileVal[i].percentage = 100;
          }
        }
        this.files = fileVal;
        this.filesData = fileVal;
      } else {
        this.files = JSON.parse(this.value);
        this.filesData = JSON.parse(this.value);
      }
    }
  },
  methods: {
    //获取指定字符串点最后一个字符
    substringType(str) {
      let valueArr = str.split(".");
      return valueArr[valueArr.length - 1];
    },
    handleError() {
      this.progressFlag = false;
    },
    handleProgress(event, file, fileList) {
      this.progressFlag = true;
      this.progressPercent = Math.floor(event.percent);
    },
    move(item, direct) {
      this.filesData = utils.arrayMove(this.filesData, item, direct);
    },
    uploadSuccess(response, file, fileList) {
      //获取附件类型
      let type = "";
      if (file.name && file.name.split(".")) {
        type = this.substringType(file.name);
      } else {
        type = file.type;
      }
      for (let i = 0; i < this.filesData.length; i++) {
        if (this.filesData[i].uid == file.uid) {
          this.filesData.splice(i, 1);
          break;
        }
      }
      this.filesData.push({
        name: file.name,
        size: file.size,
        percentage: file.percentage,
        status: file.status,
        state: file.status,
        response: file.response,
        username: file.response.username || "",
        type: type,
        uid: file.uid,
        prop1: "",
        prop2: "",
        prop3: "",
        prop4: "",
        prop5: "",
        prop6: "",
      });
      this.progressPercent === 100
        ? (this.progressFlag = false)
        : (this.progressFlag = true);
      this.$emit("onSuccess", response, file, fileList);
    },
    removeFile(file) {
      this.$confirm(`确定删除${file.name}?`)
        .then(() => {
          this.filesData.remove(file);
          this.$refs.fileUpload.remove(file);
          this.$emit("remove", file, this.files);
        })
        .catch(() => {});
    },
    download(file) {
      this.$emit("download", file, this.files);
    },
    preview(file) {
      if (this.previewable) {
        this.$emit("preview", file, this.files);
      } else {
        let msg = this.t("ht.file.nopreview");
        this.$message.warning(msg);
      }
    },
    emitChange() {
      let r = "";
      if (
        this.filesData &&
        this.filesData.constructor === Array &&
        this.filesData.length > 0
      ) {
        // 只有上传成功的附件才能更新v-model值
        let ary = this.filesData.filter((m) => m.status === "success");
        if (ary && ary.length > 0) {
          r = JSON.stringify(ary);
        }
      }
      this.$emit("input", r);
    },
    syncInput() {
      this.emitChange();
    },
  },
};
</script>
<style lang="scss" scoped>
input[aria-invalid="true"] + div >>> button {
  border-color: #f56c6c;
}

.done-subject {
  cursor: pointer;
}

.done-subject:hover {
  color: #2761ff;
}
.progress_msg {
  margin: 0;
  text-align: center;
  font-size: 12px;
}
.file-list__wrap {
  list-style: none;
  width: 360px;
  padding-left: 0;
  .file-item {
    padding: 0 6px;
    display: flex;
    .file__name {
      display: inline-block;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      width: 300px;
      margin: 0;
    }
    &:hover {
      cursor: pointer;
      color: #2761ff;
      background: #f5f5f5;
      .file-close__icon {
        display: inline-block;
      }
    }
    .file-icon {
      padding-right: 4px;
      padding-top: 7px;
    }
    .file-close__icon {
      display: none;
      float: right;
      padding-top: 7px;
      margin-left: 10px;
    }
  }
}
</style>
