<template>
  <div :class="$style.contain">
    <div v-if="listType === 'picture-card'" class="ant-upload-list-picture-card">
      <div
        v-for="item in attachmentsList"
        :key="item.code"
        class="ant-upload-list-picture-card-container"
        :class="{ [$style.checked]: selectedKeys && selectedKeys.includes(item.code) }"
        @click="select(item)"
      >
        <div
          v-if="item.code"
          class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture-card"
        >
          <div class="ant-upload-list-item-info">
            <a class="ant-upload-list-item-thumbnail">
              <img
                :src="
                  (`api/framework/v1/task-form-process/download-attachments/` + item.code)
                    | sdResource
                "
                class="ant-upload-list-item-image" /></a
          ></div>
          <span class="ant-upload-list-item-actions"
            ><a class="prebtnatt" @click="showEye">
              <a-icon type="eye-o" />
            </a>
            <a-modal
              title="预览首页效果"
              :visible="visible"
              :footer="null"
              @ok="handleOk"
              @cancel="handleCancel"
            >
              <div class="preivewboxatt">
                <img
                  v-if="visible"
                  class="previewimg"
                  :src="
                    `api/flow-mobile/v1/task-form-process/download-attachments/${item.code}`
                      | sdResource
                  "
                />
                <span class="sliderTitleatt">{{ item.title }}</span>
              </div>
            </a-modal>
            <a-icon
              v-if="item.deletable && !formReadOnly"
              type="delete"
              @click.stop="DelFile(item)"
            />
          </span>
        </div>
      </div>
    </div>
    <template v-if="_uploadable && attachmentsList.length < max && !formReadOnly">
      <div v-if="listType === 'picture-card' || listType === 'text'" :class="$style.buttons">
        <a-upload
          name="fj"
          :list-type="listType"
          :custom-request="(file) => customRequest(file, catNum)"
          :file-list="[]"
          :accept="actualAccept"
          :multiple="max > 1"
        >
          <slot>
            <div v-if="listType === 'picture-card'">
              <a-icon type="plus" />
              <div class="ant-upload-text">上传</div>
            </div>
            <a-button v-else> <a-icon type="paper-clip" /> 上传附件</a-button>
          </slot>
        </a-upload>
      </div>
      <a-upload-dragger
        v-else
        name="fj"
        :custom-request="(file) => customRequest(file, catNum)"
        :file-list="[]"
        :accept="actualAccept"
        :multiple="max > 1"
        @reject="reject(actualAccept)"
        @drop.native.stop
      >
        <p class="ant-upload-drag-icon"><a-icon type="inbox" />上传文件</p>
      </a-upload-dragger>
    </template>
    <!-- 不是图片显示模式且附件数大于1，显示批量下载按钮 -->
    <a-button
      v-if="downloadBatch && listType !== 'picture-card' && attachmentViewList.length > 1"
      :class="$style.actionbtn"
      @click="plsave"
    >
      <a-icon type="download" />批量下载
    </a-button>
    <div
      v-for="(list, i) in [computedZwList, computedFjList, computedHjList]"
      :key="i"
      class="ant-list ant-list-sm ant-list-split"
    >
      <sd-draggable
        v-if="listType !== 'picture-card'"
        v-show="attachmentsList.length > 0"
        v-model="computedFjList"
        :disabled="i !== 1"
        tag="ul"
        class="ant-list-items"
        handle=".handle"
      >
        <a-list-item
          v-for="item in list"
          :key="item.code"
          :class="[
            $style.actionlist,
            $style.list,
            { [$style.henji]: ['-3', '-4'].includes(item.CatNum) },
          ]"
        >
          <a-spin v-if="item.busy" size="small"> </a-spin>
          <span :class="[$style.listTitle, { [$style.renaming]: item.doReName }]">
            <a-checkbox
              v-if="showSelection"
              :class="$style.checkbox"
              :checked="selectedKeysCompute.includes(item.code)"
              @change="select(item)"
            ></a-checkbox>
            <span @click.stop="OpenMyFile(item.FileName)">
              <!--
                      @slot 自定义文件图标<p>8.0.14 新增</p>
                      @binding {scope} item 附件名name，附件code和附件分类CatNum信息
                    -->
              <slot name="file-icon" :item="item">
                <a-icon
                  theme="filled"
                  :type="getIcon(item.FileName)"
                  :class="$style[getIcon(item.FileName)]"
                />
              </slot>
              {{ item.FileName }} ({{ item.size | sdBytesFormat }})
              <slot name="file-progress" :item="item">
                <span v-show="!item.Completed">上传中...</span>
                <span v-show="item.downloading">下载中...</span>
                <a-progress v-show="false"></a-progress>
              </slot>
            </span>
          </span>

          <div v-show="item.doReName" :class="$style.rename">
            <a-input
              v-model="newname"
              :addon-after="getFileType(item.FileName)"
              :max-length="parseInt(filenameMaxLength)"
            />
            <a-button @click="ReName(item, false)">取消</a-button>
            <a-button type="primary" @click="UpdateName(item)"> 确定 </a-button></div
          >
          <div :class="[$style.actionbutton, 'ant-list-item-action']">
            <slot name="actions" :item="item" />
            <a-tooltip
              v-if="item.Completed && item.deletable && !formReadOnly"
              placement="top"
              title="删除"
            >
              <a-button icon="sd-trash2" type="link" @click="DelFile(item)" />
            </a-tooltip>
            <a-tooltip
              v-if="item.Completed && item.renamable && !formReadOnly"
              slot="actions"
              placement="top"
              title="重命名"
              overlay-class-name="sd-att-tip"
            >
              <a-button icon="sd-edit" type="link" @click="ReName(item, true)" />
            </a-tooltip>
            <a-tooltip
              v-if="
                ['0', '-4'].includes(item.CatNum) &&
                computedFjList.length > 1 &&
                _sortable &&
                !formReadOnly
              "
              placement="right"
              title="拖拽排序"
            >
              <a class="handle ant-btn ant-btn-link ant-btn-icon-only" :title="null">
                <a-icon type="sd-swap"
              /></a>
            </a-tooltip>
            <a-tooltip v-if="item.Completed" placement="top" title="预览">
              <a-button icon="sd-desktop" type="link" @click="preview(item)" />
            </a-tooltip>
          </div>
        </a-list-item>
      </sd-draggable>
    </div>
  </div>
</template>

<script>
import Vue from 'vue'
import { Modal, Message } from 'ant-design-vue'
import moment from 'moment'
import attrAccept from 'ant-design-vue/es/vc-upload/src/attr-accept'
import pickValues from '../services/pick-values'
import { sdLocalStorage } from '../services/storage-service'
import sdListPickerVue from './sd-list-picker.vue'
import components from './_import-components/sd-attachment-import'
import download from '@/common/services/download'
import axios from '@/common/services/axios-instance'
import storeMixin from '@/common/store-mixin'
/**
 * 纯js附件组件
 * @displayName SdAttachment 附件
 */
export default {
  name: 'SdAttachment',
  components,
  mixins: [storeMixin],
  props: {
    /**
     * @ignore
     */
    formId: {
      type: String,
      default: '-1',
    },
    /**
     * @ignore
     */
    beanId: {
      type: String,
      default: '-1',
    },
    /**
     *  选中的附件
     * @model
     */
    value: {
      type: Array,
      default: () => {},
    },
    /**
     * listType为picture-card生效，指定选中的图片附件
     */
    selectedKeys: {
      type: Array,
      default: undefined,
    },
    /**
     * 附件展示方式，默认为拖拽方式，picture-card 图片模式，text 按钮上传方法
     */
    listType: {
      type: String,
      default: '',
    },
    /**
     * 附件的groupId
     */
    groupId: {
      required: true,
      type: [String, Number],
      default: '',
    },
    /**
     * 是否只读
     */
    readOnly: {
      type: Boolean,
      default: false,
    },
    /**
     * 最多上传附件个数
     */
    max: {
      type: Number,
      default: Infinity,
    },
    /**
     * 单个文件最大大小
     */
    maxFileSize: {
      type: Number,
      default: 1024,
    },
    /**
     * 指定上传文件的catNum
     */
    catNum: {
      type: Number,
      default: 0,
    },
    /**
     * 接收的文件类型，如word文件".doc,.docx"或图片"image/*"，更多见input的accept属性
     *
     */
    accept: {
      type: String,
      default: '',
    },
    /**
     * 不符合上传条件时提示语
     *
     */
    rejectMessage: {
      type: String,
      default: '',
    },
    /**
     * 重命名文件名最大长度
     *
     */
    filenameMaxLength: {
      type: [String, Number],
      default: Infinity,
    },
    /**
     * 是否显示选择框
     *
     */
    showSelection: {
      type: Boolean,
      default: false,
    },
    /**
     * 隐藏指定catnum的附件
     *
     */
    catNumToHide: {
      type: Array,
      default: undefined,
    },
    /**
     * 允许批量下载
     * @since 8.1.0.24
     */
    downloadBatch: {
      type: Boolean,
      default: false,
    },
    /**
     * @ignore
     */
    uploadable: {
      type: [Boolean, String],
      default: function () {
        return !this.readOnly
      },
    },
    /**
     * 是否允许上传正文
     */
    zwUploadable: {
      type: [Boolean, String],
      default: function () {
        return !this.readOnly
      },
    },
    /**
     * @ignore
     */
    sortable: {
      type: [Boolean, String],
      default: function () {
        return !this.readOnly
      },
    },
    /**
     * @ignore
     */
    initValue: {
      type: Array,
      default: function () {
        return this.webflow.FlowData?.processFormData.processFormPropertyValues.find((item) => {
          return item.value?.indexOf?.(this.groupId) > -1
        })?.attr?.attachments
      },
    },
    /**
     * @ignore
     */
    infoProperties: {
      type: Object,
      default: function () {
        return (
          this.webflow.FlowData?.processFormData.processFormPropertyValues.find((item) => {
            return item.value?.indexOf?.(this.groupId) > -1
          })?.attr?.infoProperties || {}
        )
      },
    },
  },
  data() {
    return {
      visible: false,
      attachments: [],
      newname: '',
      selectedKeysLocal: [],
      saveSort: false,
    }
  },
  computed: {
    _zwUploadable() {
      return this.zwUploadable.toString() !== 'false'
    },
    _uploadable() {
      return this.uploadable.toString() !== 'false'
    },
    _sortable() {
      return this.sortable.toString() !== 'false'
    },
    actualAccept() {
      // 优先使用前端配置的类型限制，如未配置，则使用后端支持的类型
      return (
        this.accept || JSON.parse(sdLocalStorage.getItem('commonConfig') || '{}').attachType || ''
      )
    },
    selectedKeysCompute() {
      if (this.selectedKeys) {
        return this.selectedKeys
      } else {
        return this.selectedKeysLocal
      }
    },
    attachmentsList() {
      const hideCatNums = this.catNumToHide?.map((catnum) => catnum.toString())
      return this.attachments?.filter((item) => {
        return !this.catNumToHide || !hideCatNums?.includes(item.CatNum.toString())
      })
    },
    computedZwList() {
      // 正文
      return this.attachmentsList.filter((item) => item.CatNum.toString() === '-1')
    },
    computedFjList: {
      // 附件
      get: function () {
        return this.attachmentsList.filter((item) =>
          ['0', '-5', '-6'].includes(item.CatNum.toString())
        )
      },
      set: function (newValue) {
        this.attachments = [
          ...this.computedZwList,
          ...newValue,
          ...this.computedHjList,
          ...this.attachments.filter((item) => {
            return !this.attachmentsList.find((att) => att.code === item.code)
          }),
        ]
        this.saveFilesSort()
      },
    },
    computedHjList() {
      // 痕迹搞
      return this.attachmentsList.filter((item) => ['-3', '-4'].includes(item.CatNum.toString()))
    },
    attachmentViewList() {
      return this.computedZwList
        .concat(this.computedFjList)
        .concat(this.computedHjList)
        .filter((item) => item.Completed)
    },
    formReadOnly() {
      return (
        this.SdFormContext?.readOnly ||
        this.SdFormContext?.selectors?.some((i) => i.field === this.infoProperties?.field) // 如果附件字段作为选择器，不可编辑
      )
    },
  },
  watch: {
    value(value) {
      if (value?.[0] === 'updateAttachmentList') {
        this.updateFileList()
      }
    },
  },
  created() {
    const lock = sdLocalStorage.getItem(`Lock${this.webflow?.FlowData?.instId}`)
    this.lockId = (lock && JSON.parse(lock).sessionId) || ''
    this.loadPlugin()
  },
  methods: {
    handleOk() {
      this.visible = false
    },
    handleCancel() {
      this.visible = false
    },
    showEye() {
      this.visible = true
    },
    loadPlugin() {
      this.getFileList(true, true, true)
    },
    updateFileList(falg = true) {
      // 默认只更新控件列表，不触发change事件
      this.getFileList(falg)
    },
    getFileList(noTriggerCheck = false, updateList = true, fromField = false) {
      let p = Promise.resolve(this.initValue)
      if (!fromField || !Array.isArray(this.initValue)) {
        p = axios
          .get(`api/framework/v1/attachment-extend/attachments-info-perm/${this.groupId}`, {
            params: this.infoProperties,
          })
          .then((res) => res.data)
      }
      return p.then((data) => {
        data.forEach((item) => {
          item.Unid = item.code
          item.FileName = item.name
          item.Completed = 1
          item.size = item.fileSize || item.size
          item.CatNum = item.properties?.match(/<CatNum>(.*)<\/CatNum>/)?.[1] || item.catNum
          // 兼容没有权限设置的情况，比如非流程表单
          item.deletable = !this.readOnly
          item.editable = !this.readOnly
          item.renamable = !this.readOnly
          if (item.attr) {
            // 如果有流程id，那说明权限从接口返回的取
            item.deletable = item.attr.deletable
            item.editable = item.attr.editable
            item.renamable = item.attr.renamable
          }
        })
        // 附件排序，顺序为正文，附件，其他
        const zw = data.filter((item) => item.properties?.includes('<CatNum>-1</CatNum>'))
        const fj = data.filter((item) => item.properties?.includes('<CatNum>0</CatNum>'))
        const others = data.filter((item) => !item.properties?.match(/<CatNum>(-1|0)<\/CatNum>/))
        data = [...zw, ...fj, ...others]
        if (updateList) {
          this.attachments = data
          this.$emit('input', this.attachments)
        } else {
          return data
        }
        if (!noTriggerCheck && updateList) {
          /**
           * 附件添加删除时触发
           * @property {Array} 附件信息
           */
          this.$emit('change', this.attachments)
        }
      })
    },
    // 选择文件后上传、附件图标颜色
    getIcon(fname) {
      const suffix = fname.split('.').pop().toLowerCase()
      if (['doc', 'docx'].includes(suffix)) {
        return 'file-word'
      }
      if (['pdf', 'ofd'].includes(suffix)) {
        return 'file-pdf'
      }
      if (['jpg', 'png', 'gif', 'bmp'].includes(suffix)) {
        return 'file-image'
      }
      if (['xls', 'xlsx'].includes(suffix)) {
        return 'file-excel'
      }
      if (['txt', 'text'].includes(suffix)) {
        return 'file-text'
      }
      if (['ppt', 'pptx'].includes(suffix)) {
        return 'file-ppt'
      }
      if (['zip', 'rar', '7z'].includes(suffix)) {
        return 'file-zip'
      }
      return 'file'
    },

    customRequest(data, catnum = 0, item) {
      // 前端上传indidoc兼容附件
      if (this.attachments.find((item) => item.FileName === data.file.name)) {
        Message.warn(`已存在文件《${data.file.name}》`)
        return
      }
      // 后台限制大小单位为M，前端转换成M进行对比
      if (data.file.size / 1024 / 1024 > this.maxFileSize) {
        Message.warn(
          `文件超过最大大小${Vue.filter('sdBytesFormat')(this.maxFileSize * 1024 * 1024)}` // maxFilesize传过来的单位是
        )
        return
      }
      if (data.file.size === 0) {
        Message.warn(`不能上传大小为0的文件`)
        return
      }
      // 附件限制
      if (!attrAccept(data.file, this.actualAccept)) {
        this.reject(this.actualAccept)
        return
      }
      const file = {
        FileName: data.file.name,
        Completed: 0,
        CatNum: catnum,
      }
      if (catnum === -1) {
        this.attachments.unshift(file)
      } else {
        this.attachments.push(file)
      }

      this.attachments = [...this.attachments]
      const strTime = moment().format('YYYY-MM-DD HH:mm:ss')
      const formData = new FormData()
      formData.append('file', data.file)
      formData.append('FileName', data.file.name)
      formData.append('lockId', this.lockId)
      formData.append('groupId', this.groupId)
      Object.keys(this.infoProperties).forEach((key) => {
        formData.append(key, this.infoProperties[key])
      })

      formData.append(
        'querystring',
        `<file_unid></file_unid><file_name>${data.file.name}</file_name><file_size>${data.file.size}</file_size><completed>1</completed><file_create>${strTime}</file_create><file_update>${strTime}</file_update><file_editmodel>0</file_editmodel><file_lockuser>0</file_lockuser><CreateInfo>${this.userInfo.account} ${strTime}</CreateInfo><filetype></filetype><user_name>${this.userInfo.account}</user_name><UpdateInfo>${this.userInfo.account}于${strTime}创建.</UpdateInfo><TaodaInfo></TaodaInfo><CatNum>${catnum}</CatNum><Ext></Ext>`
      )
      let url = 'api/xcoa-mobile/v1/iam-attachment-extend/attachments-upload/indi'
      if (item) {
        formData.append('attachmentId', item.code)
        url = 'api/framework/v1/attachment-extend/attachments-replace/indi'
        this.attachments.splice(this.attachments.indexOf(item), 1)
      }
      axios
        .post(url, formData, {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        })
        .then((_) => {
          _.data = '' + _.data
          if (_.data.includes('lockError')) {
            if (catnum === -1) {
              this.attachments.shift()
            } else {
              this.attachments.pop()
            }
            Message.warn(`其他人正在处理该流程，不能执行当前操作`)
            return
          }
          const i = this.attachments.findIndex((item) => item.FileName === data.file.name)
          if (_.data.startsWith('false')) {
            this.attachments.splice(i, 1)
            Message.error(`${data.file.name} 上传失败`)
            return
          }
          if (item) {
            this.getFileList()
          } else {
            // 为了上传多个附件时保留各自顺序，不直接刷列表
            this.getFileList(true, false).then((files) => {
              const file = files.find((item) => item.FileName === data.file.name)
              if (file) {
                this.attachments[i] = file
              } else {
                // 附件列表中没有当前上传的附件，可能是上传失败了，从附件列表中删除
                this.attachments.splice(i, 1)
              }
              this.attachments = [...this.attachments]
              // 判断当前是否还有在上传中的附件，有且位置在当前已完成上传的附件前面，则设置标识，需保存附件排序
              const uploadingIndex = this.attachments.findIndex((item) => !item.Completed)
              if (uploadingIndex !== -1 && uploadingIndex < i) {
                this.saveSort = true
              }
              // 所有附件均已上传完成 且 需要保存排序
              if (uploadingIndex === -1 && this.saveSort) {
                this.saveFilesSort()
              }
              this.$emit('input', this.attachments)
              this.filesChanged()
            })
          }
        })
        .catch((e) => {
          this.getFileList()
          throw e
        })
    },
    saveFilesSort() {
      axios
        .post(
          `api/framework/v1/attachment-extend/attachments-sort/indi?groupId=${
            this.groupId
          }&sortfileid=${this.attachments.map((item) => item.code).join(',')}`
        )
        .catch(() => {
          Message.warn('附件排序设置失败')
        })
    },
    filesChanged() {
      this.$emit('change', this.attachments)
    },
    preview(file) {
      const storeName = 'iamAttachment'
      const fileId = file.Unid
      axios
        .get(`api/xcoa-mobile/v1/wps/preview/url/${storeName}/${fileId}`)
        .then((_) => {
          const data = _.data
          console.log(data)
          if (data.status === 'error') {
            alert(data.message)
          } else {
            window.open(data.previewLink, '_blank')
          }
        })
        .catch((e) => {
          console.log('get preview url error', e)
          alert('预览功能错误')
        })
    },
    DelFile(file) {
      Modal.confirm({
        title: `确认删除附件《${file.FileName}》?`,
        okType: 'danger',
        onOk: () => {
          axios
            .delete(`api/framework/v1/attachment-extend/attachments-delete/${this.groupId}`, {
              params: {
                attachmentId: file.Unid,
                lockId: this.lockId,
                ...this.infoProperties,
              },
            })
            .then((_) => {
              if (typeof this.selectedKeys !== 'undefined') {
                // 如果是可选择附件，并且被选中的附件删除，则更新选中的key
                const keys = [...this.selectedKeys]
                if (keys.includes(file.Unid)) {
                  keys.splice(keys.indexOf(file.Unid), 1)
                }
                if (typeof this.selectedKeys === 'undefined') {
                  this.selectedKeysLocal = keys
                }
                this.$emit('update:selectedKeys', keys)
              }
              this.getFileList()
            })
            .catch((e) => {
              Message.info(
                e.response?.data?.code === 21001008
                  ? `其他人正在处理该流程，不能执行当前操作`
                  : '删除失败'
              )
            })
        },
      })
    },
    OpenMyFile(fname) {
      const file = this.attachments.find((item) => item.FileName === fname)
      const code = file.Unid
      if (!code) {
        Message.error(`上传中不能下载`)
        return
      }
      file.downloading = true
      this.attachments = [...this.attachments]
      const url = `${location.origin}${location.pathname}api/framework/v1/task-form-process/download-attachments/${code}`
      download(url, fname).then((_) => {
        file.downloading = false
        this.attachments = [...this.attachments]
      })
    },
    plsave() {
      let p
      if (this.attachmentViewList.length <= 2) {
        p = Promise.resolve(this.attachmentViewList)
      } else {
        // 弹框下载
        p = pickValues(sdListPickerVue, {
          optionValue: 'Unid',
          singleColumn: true,
          loadListData: () => this.attachmentViewList,
          value: this.attachmentViewList,
        })
      }
      p.then((attachs) => {
        if (attachs) {
          if (attachs.length === 0) {
            Message.warn('请选择需要下载的文件')
          } else {
            // 多附件打包下载
            const tmpArr = attachs[0].FileName.split('.')
            tmpArr.pop()
            const fileName = tmpArr.join('.')
            download(
              `api/framework/v1/attachment-extend/attachments-download/multi?groupId=${
                this.groupId
              }&codes=${attachs.map((_) => _.code).toString()}`,
              `${fileName}等${attachs.length}个附件.zip`
            )
          }
        }
      })
    },
    ReName(item, flag) {
      this.attachments.forEach((item) => (item.doReName = false))
      item.doReName = flag
      // 附件名称去掉后缀
      const names = item.FileName.split('.')
      names.pop()
      this.newname = names.join('.')
      this.attachments = JSON.parse(JSON.stringify(this.attachments))
    },
    UpdateName(file) {
      const reg = new RegExp('[\\\\/:*?"<>|]')
      if (this.newname === '') {
        Message.error(`文件名不能为空`)
        return
      }
      if (reg.test(this.newname)) {
        Message.error(`文件名包含非法的字符"${this.newname.match(reg)[0]}"`)
        return
      }
      if (
        this.attachments.find(
          (item) =>
            item.FileName.toLowerCase() ===
              (this.newname + this.getFileType(item.FileName)).toLowerCase() &&
            item.code !== file.code
        )
      ) {
        Message.error(`已存在同名文件`)
        return
      }
      const formData = new FormData()
      formData.append('groupId', this.groupId)
      formData.append('FileName', this.newname + this.getFileType(file.FileName))
      Object.keys(this.infoProperties).forEach((key) => {
        formData.append(key, this.infoProperties[key])
      })
      formData.append('lockId', this.lockId)
      formData.append(
        'querystring',
        `<file_action>rename_file</file_action><file_unid>${file.Unid}</file_unid>`
      )
      axios
        .post('api/xcoa-mobile/v1/iam-attachment-extend/attachments-upload/indi', formData, {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        })
        .then((_) => {
          if (_.data.includes('lockError')) {
            Message.warn(`其他人正在处理该流程，不能执行当前操作`)
            return
          }
          this.getFileList()
        })
    },
    getFileType(strFileName) {
      return '.' + strFileName.split('.').pop()
    },
    select(item) {
      const keys = [...this.selectedKeysCompute]
      if (keys.includes(item.code)) {
        keys.splice(keys.indexOf(item.code), 1)
      } else {
        keys.push(item.code)
      }
      /**
       * list-type为picture-card模式下生效，选中的图片
       * @property {keys} 选中的附件id
       */
      if (typeof this.selectedKeys === 'undefined') {
        this.selectedKeysLocal = keys
      }
      this.$emit('update:selectedKeys', keys)
    },
    reject(accept) {
      Message.warn(this.rejectMessage || `不支持的文件类型，支持的文件类型有${accept}`)
    },
  },
  inject: {
    webflow: { default: () => ({}) },
    SdFormContext: { default: () => ({}) },
  },
}
</script>

<style module lang="scss" src="./sd-attachment.scss"></style>
