<template>
  <div class="table-select">
    <span class="title">{{ title }}</span>
    <div class="close-btn"><i class="iconfont icon-pop-ups_shut-down" @click="$emit('cancle')"></i></div>

    <div class="material-tab">
      <a v-if="selectableType.includes('image')" class="material-tab-item"
        @click.prevent="currentMaterialType = 'image'">
        <span :class="{ active: currentMaterialType === 'image' }" class="text">
          {{ image }}
        </span>
        <div v-if="currentMaterialType === 'image'" class="bottom-line"></div>
      </a>
      <a v-if="selectableType.includes('pano')" class="material-tab-item" @click.prevent="currentMaterialType = 'pano'">
        <span :class="{ active: currentMaterialType === 'pano' }" class="text">
          {{ panorama }}
        </span>
        <div v-if="currentMaterialType === 'pano'" class="bottom-line"></div>
      </a>
      <a v-if="selectableType.includes('audio')" class="material-tab-item"
        @click.prevent="currentMaterialType = 'audio'">
        <span :class="{ active: currentMaterialType === 'audio' }" class="text">
          {{ audio }}
        </span>
        <div v-if="currentMaterialType === 'audio'" class="bottom-line"></div>
      </a>
      <a v-if="selectableType.includes('video')" class="material-tab-item"
        @click.prevent="currentMaterialType = 'video'">
        <span :class="{ active: currentMaterialType === 'video' }" class="text">
          {{ video }}
        </span>
        <div v-if="currentMaterialType === 'video'" class="bottom-line"></div>
      </a>
      <a v-if="selectableType.includes('3D')" class="material-tab-item" @click.prevent="currentMaterialType = '3D'">
        <span :class="{ active: currentMaterialType === '3D' }" class="text">
          {{ scene }}
        </span>
        <div v-if="currentMaterialType === '3D'" class="bottom-line"></div>
      </a>
    </div>

    <div class="filter">
      <input type="text" :placeholder="keywords" v-model="searchKey" />
      <i v-if="!searchKey" class="iconfont icon-editor_search search-icon" />
      <i v-if="searchKey" @click="searchKey = ''" class="iconfont icontoast_red clear-icon"></i>
    </div>

    <div class="table table-pano" v-show="currentMaterialType === 'pano'">
      <div class="table-head-row">
        <span class="table-head">1</span>
        <span class="table-head" v-for="(item, i) in tableHeadersForPano" :key="i">
          {{ item.name && $i18n.t(`zh_key.${item.name}`) }}</span>
      </div>
      <div v-if="panoListLocalLength !== 0 || hasMorePanoData" class="table-body"
        v-infinite-scroll="requestMorePanoData"
        :infinite-scroll-disabled="!hasMorePanoData || isRequestingMorePanoData">
        <!-- vuex中的上传中数据 -->
        <div class="table-body-row" v-for="(item, i) in uploadStatusListPano" :key="item.uid" @click="onClickRow">
          <!-- 如果已经上传成功 -->
          <template v-if="item.status === 'SUCCESS'">
            <span class="table-data">
              <RadioOrCheckbox class="checkbox" :isLightTheme="true" :isMultiSelection="isMultiSelection"
                :isCheckedInitial="select.some(i => i[primaryKey] === item.successInfo[primaryKey])"
                @change="v => selectItem(item.successInfo, v)" />
            </span>
            <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForPano" :key="idx">
              <div v-if="tableItemStructure.type == 'image'" class="list-img">
                <img
                  :src="item.successInfo[tableItemStructure.key] + (Number(item.fileSize) > 512 ? $imgsuffix : ``)"
                  alt="">
              </div>
              <span v-else class="ellipsis"
                v-title="tableItemStructure.key === 'name' ? item.successInfo[tableItemStructure.key] : ''">{{
                    item.successInfo[tableItemStructure.key]
                }}</span>
            </span>
          </template>
          <!-- 如果还在上传或切图处理中 -->
          <template v-else-if="item.status = 'LOADING'">
            <span class="table-data">
              <div class="checkbox">
                <span class="for-outer-circle"></span>
                <span class="for-inner-circle disabled"></span>
              </div>
            </span>
            <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForPano" :key="idx">
              <div v-if="tableItemStructure.type == 'image'" class="list-img">
                <img src="@/assets/images/icons/upload-file-type-icon-image@2x.png" alt="">
              </div>
              <span v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
              <span v-if="tableItemStructure.key === 'fileSize' && item.ifKnowProgress">{{$i18n.t(`gather.upload_material`)}} {{ Math.round(item.progress
                  * 100)
              }}%</span>
              <span v-if="tableItemStructure.key === 'fileSize' && !item.ifKnowProgress">{{ item.statusText }}</span>
              <span v-if="tableItemStructure.key === 'name'" class="ellipsis"
                v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
            </span>
          </template>
          <!-- 如果上传失败了 -->
          <template v-else-if="item.status = 'FAIL'">
            <span class="table-data">
              <div class="checkbox">
                <span class="for-outer-circle"></span>
                <span class="for-inner-circle disabled"></span>
              </div>
            </span>
            <span class="table-data" v-for="(tableItemStructure, idx) in tableHeadersForPano" :key="idx">
              <div v-if="tableItemStructure.type == 'image'" class="list-img">
                <img src="@/assets/images/icons/upload-file-type-icon-image@2x.png" alt="">
              </div>
              <span v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
              <span v-if="tableItemStructure.key === 'fileSize'">{{ $i18n.t(`tips_code.FAILURE_3025`) }}</span>
              <span v-if="tableItemStructure.key === 'name'" class="ellipsis"
                v-title="tableItemStructure.key === 'name' ? item.title : ''">{{ item.title }}</span>
            </span>
          </template>
        </div>
        <!-- 本组件内的列表数据 -->
        <div class="table-body-row" v-for="(item, i) in panoList" :key="i" @click="onClickRow">
          <span class="table-data">
            <RadioOrCheckbox class="checkbox" :isLightTheme="true" :isMultiSelection="isMultiSelection"
              :isCheckedInitial="select.some(i => i[primaryKey] === item[primaryKey])"
              @change="v => selectItem(item, v)" />
          </span>
          <span class="table-data" v-for="(sub, idx) in tableHeadersForPano" :key="idx">
            <div v-if="sub.type == 'image'" class="list-img">
              <img
                :src="item[sub.key] + (Number(item.fileSize) > 512 ? $imgsuffix : ``)"
                alt="">
            </div>
            <span class="ellipsis" v-else v-title="sub.key === 'name' ? item[sub.key] : ''">{{ item[sub.key] }}</span>
          </span>
        </div>
      </div>
      <!-- 无数据时的提示 -->
      <div v-else class="no-data">
        <div v-if="latestUsedSearchKey">
          <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
          <span>{{ no_serch_result }}</span>
        </div>
        <div v-if="!latestUsedSearchKey">
          <img :src="require('@/assets/images/default/empty_04.png')" alt="">
          <span>{{ no_material_result }}</span>
        </div>
      </div>
    </div>

    <div class="table table-3D" v-show="currentMaterialType === '3D'">
      <div class="table-head-row">
        <span class="table-head">1</span>
        <span class="table-head" v-for="(item, i) in tableHeadersFor3D" :key="i">
          {{ item.name && $i18n.t(`zh_key.${item.name}`) }}</span>
      </div>
      <div v-if="scene3DList.length !== 0 || hasMore3DData" class="table-body" v-infinite-scroll="requestMore3DData"
        :infinite-scroll-disabled="!hasMore3DData || isRequestingMore3DData">
        <div class="table-body-row" v-for="(item, i) in scene3DList" :key="i">
          <span class="table-data">
            <RadioOrCheckbox class="checkbox" :isLightTheme="true" :isMultiSelection="isMultiSelection"
              :isCheckedInitial="select.some(i => i[primaryKey] === item[primaryKey])"
              @change="v => selectItem(item, v)" />
          </span>
          <span class="table-data" v-for="(sub, idx) in tableHeadersFor3D" :key="idx">
            <div v-if="sub.type == 'image'" class="list-img">
              <img
                :src="item[sub.key] + (Number(item.fileSize) > 512 ? $imgsuffix : ``)"
                alt="">
            </div>
            <span class="ellipsis" v-else v-title="sub.key === 'name' ? item[sub.key] : ''">{{ item[sub.key] }}</span>
          </span>
        </div>
      </div>
      <!-- 无数据时的提示 -->
      <div v-else class="no-data">
        <div v-if="latestUsedSearchKey">
          <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
          <span>{{ no_serch_result }}</span>
        </div>
        <div v-if="!latestUsedSearchKey">
          <img :src="require('@/assets/images/default/empty_04.png')" alt="">
          <span>{{ no_material_result }}</span>
          <a href="/#/">
            <button class="ui-button">{{ how_to_shoot }}</button>
          </a>
        </div>
      </div>
    </div>

    <div class="btns">
      <button v-if="currentMaterialType !== '3D'" class="ui-button upload-btn" @click="onClickUpload">
        <span>{{ upload_material }}</span>
        <i :key="currentMaterialType" class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="
          currentMaterialType === 'image' ? img_size :
            currentMaterialType === 'pano' ? pano_size :
              currentMaterialType === 'audio' ? audio_size :
                currentMaterialType === 'video' ? video_size : ''
        ">
        </i>
        <FileInput ref="file-input" :failString="fileInputFailString" :limitFailStr="fileInputLimitFailStr"
          :acceptType="fileInputAcceptType" :mediaType="fileInputMediaType" :limit="fileInputLimit"
          @file-change="onFileInputChange"></FileInput>
      </button>
      <div v-else class="button-placeholder"></div>
      <div>
        <button class="ui-button cancel" @click="$emit('cancle')">{{ cancel }}</button>
        <button class="ui-button submit" :class="{ disable: !select.length }" @click="onClickComfirm">
          {{ comfirm }}
        </button>
      </div>
    </div>
  </div>
</template>

<script>
import { mapMutations } from "vuex";
import {
  getMaterialList,
  getSceneList,
  uploadMaterial,
  checkMStatus,
  checkUserSize,
} from "@/api";
import { getImgWH, changeByteUnit } from "@/utils/file";
import config from "@/config";
import { debounce } from "@/utils/other.js"
import FileInput from "@/components/shared/uploads/UploadMultiple.vue";
import { mapState } from "vuex";
import RadioOrCheckbox from "@/components/shared/RadioOrCheckbox.vue";
import { i18n } from "@/lang"

export default {
  props: {
    title: {
      default: '',
      type: String
    },
    primaryKey: {
      default: 'id'
    },
    selectableType: {
      type: Array,
      default: function () {
        return [
          'pano',
          '3D',
        ]
      },
    },
    initialMaterialType: {
      type: String,
      default: 'image',
    },
    isMultiSelection: {
      type: Boolean,
      default: false,
    },
    workId: {
      type: String,
      default: '',
    },
  },
  components: {
    FileInput,
    RadioOrCheckbox,
  },
  watch: {
    searchKey: {
      handler: function () {
        this.refreshMaterialList(this.currentMaterialType)
      },
      immediate: false,
    },
    currentMaterialType: {
      handler: function (newVal) {
        if (newVal === 'pano' && this.panoList.length === 0) {
          this.refreshMaterialList('pano')
        } else if (newVal === '3D' && this.scene3DList.length === 0) {
          this.refreshMaterialList('3D')
        }
      },
      immediate: false,
    },
    needLongPolling: {
      handler: function (newVal) {
        if (!newVal) {
          clearInterval(this.longPollingIntervalId)
          this.longPollingIntervalId = null
        } else {
          clearInterval(this.longPollingIntervalId)
          this.longPollingIntervalId = null
          this.longPollingIntervalId = setInterval(() => {
            this._checkMStatus();
          }, 3000);
        }
      },
      immediate: true,
    },
  },
  computed: {
    ...mapState({
      uploadStatusListAudio: 'uploadStatusListAudio',
      uploadStatusListImage: 'uploadStatusListImage',
      uploadStatusListPano: 'uploadStatusListPano',
      uploadStatusListVideo: 'uploadStatusListVideo',
    }),
    tableHeadersForPano() {
      return this.$MAPTABLEHEADER['pano'].filter(item => {
        return ['icon', 'name', 'fileSize'].includes(item.key)
      })
    },
    tableHeadersFor3D() {
      return this.$MAPTABLEHEADER['scene'].filter(item => {
        return ['thumb', 'sceneName', 'createTime'].includes(item.key)
      })
    },
    fileInputFailString() {
      let ret = ''
      switch (this.currentMaterialType) {
        case 'pano':
          ret = this.$i18n.t(`gather.pano_fail`)
          break;
        default:
          break;
      }
      return ret
    },
    fileInputLimitFailStr() {
      let ret = ''
      switch (this.currentMaterialType) {
        case 'pano':
          ret = this.$i18n.t(`gather.pano_limit`)
          break;
        default:
          break;
      }
      return ret
    },
    fileInputAcceptType() {
      let ret = ''
      switch (this.currentMaterialType) {
        case 'pano':
          ret = 'image/jpeg'
          break;
        default:
          break;
      }
      return ret
    },
    fileInputMediaType() {
      let ret = ''
      switch (this.currentMaterialType) {
        case 'pano':
          ret = 'image'
          break;
        default:
          break;
      }
      return ret
    },
    fileInputLimit() {
      let ret
      switch (this.currentMaterialType) {
        case 'pano':
          ret = 120
          break;
        default:
          break;
      }
      return ret
    },
    panoListRealLength() {
      return this.panoList.length + this.uploadStatusListPano.filter((item) => {
        return item.status === 'SUCCESS'
      }).length
    },
    panoListLocalLength() {
      return this.panoList.length + this.uploadStatusListPano.length
    },
    needLongPolling() {
      return this.uploadStatusListPano.some((item) => {
        return item.status === 'LOADING' && item.ifKnowProgress === false
      })
    },
  },
  data() {
    return {
      no_serch_result: i18n.t("gather.no_serch_result"),
      no_material_result: i18n.t("gather.no_material_result"),
      panorama: i18n.t("gather.panorama"),
      scene: i18n.t("gather.scene"),
      keywords: i18n.t("gather.keywords"),
      how_to_shoot: i18n.t("gather.how_to_shoot"),
      upload_material: i18n.t("gather.upload_material"),
      pano_size: i18n.t("gather.pano_size"),
      cancel: i18n.t("gather.cancel"),
      comfirm: i18n.t("gather.comfirm"),

      panoList: [],
      scene3DList: [],

      select: [],
      searchKey: '', // 搜索关键词
      latestUsedSearchKey: '',

      currentMaterialType: this.initialMaterialType,

      isRequestingMorePanoData: false,
      isRequestingMore3DData: false,
      hasMorePanoData: true,
      hasMore3DData: true,

      longPollingIntervalId: null,
    }
  },
  methods: {
    ...mapMutations([
      'clearUploadStatusLists',
    ]),
    selectItem(item, v) {
      item.materialType = this.currentMaterialType // 三维场景数据没有type字段来表明自己是三维场景。所以统一加一个字段。
        if (this.isMultiSelection) {
          if (v) {
            this.select.push(item)
          } else {
            const toDeleteIdx = this.select.findIndex((eachSelect) => {
              return eachSelect.id === item.id
            })
            if (toDeleteIdx >= 0) {
              this.select.splice(toDeleteIdx, 1)
            }
          }
        } else {
          if (v) {
            this.select = [item]
          } else {
            this.select = []
          }
        }
    },
    requestMorePanoData() {
      this.isRequestingMorePanoData = true
      const latestUsedSearchKey = this.searchKey
      getMaterialList(
        {
          pageNum: Math.floor(this.panoListRealLength / config.PAGE_SIZE) + 1,
          pageSize: config.PAGE_SIZE,
          searchKey: this.searchKey,
          type: 'pano',
        },
        (data) => {
          const newData = data.data.list.map((i) => {
            i.fileSize = changeByteUnit(Number(i.fileSize));
            i.createTime = i.createTime.substring(0, i.createTime.length - 3)
            i.updateTime = i.updateTime.substring(0, i.updateTime.length - 3)
            return i;
          });
          this.panoList = this.panoList.concat(newData)
          if (this.panoListRealLength === data.data.total) {
            this.hasMorePanoData = false
          }
          this.isRequestingMorePanoData = false
          this.latestUsedSearchKey = latestUsedSearchKey
        },
        () => {
          this.isRequestingMorePanoData = false
          this.latestUsedSearchKey = latestUsedSearchKey
        }
      );
    },
    requestMore3DData() {
      this.isRequestingMore3DData = true
      const latestUsedSearchKey = this.searchKey
      getSceneList(
        {
          pageNum: Math.floor(this.scene3DList.length / config.PAGE_SIZE) + 1,
          pageSize: config.PAGE_SIZE,
          searchKey: this.searchKey,
          workId: this.workId,
        },
        (data) => {
          const newData = data.data.data.list.map((i) => {
            return i;
          });
          this.scene3DList = this.scene3DList.concat(newData)
          if (this.scene3DList.length === data.data.data.total) {
            this.hasMore3DData = false
          }
          this.isRequestingMore3DData = false
          this.latestUsedSearchKey = latestUsedSearchKey
        },
        () => {
          this.isRequestingMore3DData = false
          this.latestUsedSearchKey = latestUsedSearchKey
        }
      )
    },
    refreshMaterialList: debounce(function (type) {
      if (type === 'pano') {
        this.isRequestingMorePanoData = false
        this.hasMorePanoData = true
        this.panoList = []
        let filterResult = this.uploadStatusListPano.filter((item) => {
          return item.status === 'LOADING'
        })
        this.$store.commit('setUploadStatusListPano', filterResult)
        this.requestMorePanoData()
      } else if (type === '3D') {
        this.isRequestingMore3DData = false
        this.hasMore3DData = true
        this.scene3DList = []
        this.requestMore3DData()
      }
    }, 500, false),
    onFileInputChange(e) {
      switch (this.currentMaterialType) {
        case 'pano':
          this.onPanoFileInputChange(e)
          break;
        default:
          break;
      }
    },
    onPanoFileInputChange(e) {
      e.files.forEach(async (eachFile, i) => {
        if (
          eachFile.type.indexOf("jpeg") <= -1
        ) {
          console.log('格式不对！');
          setTimeout(() => {
            this.$msg({
              message: `“${eachFile.name}”${this.$i18n.t(`gather.pano_fail`)}`,
              type: "warning",
            });
          }, i * 100);
          return;
        }

        if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
          setTimeout(() => {
            this.$msg({
              message: `“${eachFile.name}”${this.$i18n.t(`gather.too_long_word`)}`,
              type: "warning",
            });
          }, i * 100);
          return;
        }

        let WHRate = null
        try {
          const { width, height } = await getImgWH(eachFile)
          WHRate = width / height
        } catch (e) {
          console.error('获取图像宽高失败：', e)
          setTimeout(() => {
            this.$msg({
              message: `“${eachFile.name}”${this.$i18n.t(`gather.pano_fail`)}`,
              type: "warning",
            });
          }, i * 100);
          return
        }
        if (WHRate !== 2) {
          setTimeout(() => {
            this.$msg({
              message: `“${eachFile.name}”${this.$i18n.t(`gather.pano_fail`)}`,
              type: "warning",
            });
          }, i * 100);
          return
        }

        let itemInUploadList = {
          title: eachFile.name,
          ifKnowProgress: true,
          progress: 0,
          status: 'LOADING',
          statusText: this.$i18n.t(`gather.uploading_material`),
          uid: `u_${this.$randomWord(true, 8, 8)}`,
          abortHandler: null,
          backendId: '',
        };

        itemInUploadList.abortHandler = uploadMaterial(
          {
            file: eachFile
          },
          {
            type: 'pano',
            uid: itemInUploadList.uid,
          },
          (response) => { // 上传成功
            itemInUploadList.statusText = this.$i18n.t(`gather.cutting`)
            itemInUploadList.ifKnowProgress = false
            itemInUploadList.backendId = response.data.id
          },
          (err) => {
            if (err.statusText === 'abort') { // 用户取消了上传任务。
              console.log('用户取消了任务！');
              const index = this.uploadStatusListPano.findIndex((eachItem) => {
                return eachItem.uid === itemInUploadList.uid
              })
              this.uploadStatusListPano.splice(index, 1)
            } else {
              console.log('失败！');
              itemInUploadList.status = 'FAIL'
              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
            }
          },
          (progress) => {
            console.log('进度：', progress);
            itemInUploadList.progress = progress
          }
        )

        this.uploadStatusListPano.unshift(itemInUploadList);
      })
    },
    _checkMStatus() {
      let needPollingTaskList = this.uploadStatusListPano.filter((item) => item.status === 'LOADING' && item.ifKnowProgress === false);
      if (needPollingTaskList.length > 0) {
        checkMStatus(
          {
            ids: needPollingTaskList.map((item) => item.backendId),
            islongpolling: true,
          },
          (res) => {
            // 1切图中，2失败，3成功
            res.data.forEach(eachRes => {
              if (eachRes.status === 2) {
                const index = this.uploadStatusListPano.findIndex(eachTask => eachTask.backendId === eachRes.id)
                if (index >= 0) {
                  const targetItem = this.uploadStatusListPano[index]
                  targetItem.status = 'FAIL'
                  targetItem.statusText = this.$i18n.t(`gather.material_cutting_fail`)
                  targetItem.ifKnowProgress = true
                }
              } else if (eachRes.status === 3) {
                const index = this.uploadStatusListPano.findIndex(eachTask => eachTask.backendId === eachRes.id)
                if (index >= 0) {
                  const targetItem = this.uploadStatusListPano[index]
                  targetItem.status = 'SUCCESS'
                  eachRes.fileSize = changeByteUnit(Number(eachRes.fileSize));
                  targetItem.successInfo = eachRes
                }
              }
            });
          }
        );
      }
    },
    onClickRow(e) {
      const checkboxNodeList = e.currentTarget.getElementsByClassName('selection-click-target')
      if (checkboxNodeList && checkboxNodeList[0]) {
        checkboxNodeList[0].click()
      }
    },
    onClickUpload() {
      checkUserSize({}, (data) => {
        //判断已用是否大于3G
        if ((data.data / 1024 / 1024) > 3) {
          this.$alert({ content: this.$i18n.t('tips_code.FAILURE_3024')});
        } else {
          this.$refs['file-input'].click()
        }
      })
    },
    onClickComfirm: debounce(function () {
      this.$emit('submit', this.select)
    }, 250),
  },
  mounted() {
    this.clearUploadStatusLists()
  },
  beforeDestroy() {
    this.$store.commit('setUploadStatusListPano', this.uploadStatusListPano.filter((item) => {
      return item.status === 'LOADING'
    }))
  }
}
</script>

<style lang="less" scoped>
.ellipsis {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  width: 100%;
  display: inline-block;
}

.table-select {
  position: absolute;
  z-index: 3;
  left: 50%;
  top: 50%;
  transform: translateX(-50%) translateY(-50%);
  width: 600px;
  height: 730px;
  border-radius: 4px;
  border: 1px solid #EBEDF0;
  padding: 26px;
  background: #fff;
}

.title {
  font-size: 18px;
  color: #323233;
}

.close-btn {
  display: inline-block;
  position: absolute;
  top: 26px;
  right: 20px;
  font-size: 12px;
  color: #969799;
  cursor: pointer;
  padding: 6px;
}

.material-tab {
  margin-top: 35px;

  >.material-tab-item {
    display: inline-block;
    margin-right: 20px;
    position: relative;
    cursor: pointer;

    >.text {
      font-size: 14px;
      font-family: MicrosoftYaHei;
      color: #969799;

      &.active {
        color: #323233;
      }
    }

    >.bottom-line {
      position: absolute;
      left: 50%;
      transform: translateX(-50%);
      bottom: -4px;
      width: 16px;
      height: 2px;
      background: #0076F6;
      border-radius: 1px;
    }
  }
}

.filter {
  margin-top: 28px;
  width: 100%;
  height: 36px;
  background: #F7F8FA;
  border-radius: 2px;
  border: 1px solid #EBEDF0;
  position: relative;

  >input {
    box-sizing: border-box;
    width: calc(100% - 42px);
    height: 100%;
    border: none;
    padding-left: 16px;
    background: transparent;
    color: #323233;
    outline: none;
  }

  >.search-icon {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    right: 18px;
    color: #C8C9CC;
    font-size: 20px;
  }

  >.clear-icon {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    right: 18px;
    color: #C8C9CC;
    font-size: 20px;
    cursor: pointer;
  }
}

@table-height: 440px;
@table-head-row-height: 40px;
@table-border-size: 1px;

.table {
  margin-top: 20px;
  border: @table-border-size solid #EBEDF0;
  background: #ffffff;
  width: 100%;
  height: @table-height;

  >.table-head-row {
    width: 100%;
    height: @table-head-row-height;
    background: #F5F7FA;
    color: #646566;

    .table-head {
      font-size: 16px;
      line-height: @table-head-row-height;
      height: 100%;
      display: inline-block;
    }
  }

  >.table-body {
    height: calc(@table-height - @table-head-row-height - @table-border-size - @table-border-size);
    overflow: auto;
    display: inline-block;
    width: 100%;

    >.table-body-row {
      height: 50px;
      border-bottom: 1px solid #EBEDF0;
      display: flex;
      align-items: center;
      cursor: pointer;

      >.table-data {
        font-size: 14px;
        line-height: 50px;
        height: 100%;
        color: #323233;

        >.list-img {
          position: relative;
          height: 100%;
          display: inline-block;
          width: 100%;

          >img,
          .audio-player {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            width: 40px;
            height: 40px;
            object-fit: cover;
          }
        }
      }
    }
  }

  >.no-data {
    height: calc(@table-height - @table-head-row-height - @table-border-size - @table-border-size);
    width: 100%;
    position: relative;

    >div {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      text-align: center;

      >img {
        width: 116px;
      }

      >span {
        margin-top: 20px;
        display: block;
        font-size: 14px;
        color: rgba(255, 255, 255, 0.6);
      }

      >a {
        >button {
          margin-top: 20px;
        }
      }
    }
  }
}

.table-pano .table-head,
.table-pano .table-data {
  &:nth-of-type(1) {
    width: 50px;
    color: transparent;
  }

  &:nth-of-type(2) {
    width: calc(146px - 50px);
  }

  &:nth-of-type(3) {
    width: calc(380px - 146px);
    padding-right: 30px;
  }

  &:nth-of-type(4) {
    width: calc(100% - 380px);
  }
}

.table-3D .table-head,
.table-3D .table-data {
  &:nth-of-type(1) {
    width: 50px;
    color: transparent;
  }

  &:nth-of-type(2) {
    width: calc(146px - 50px);
  }

  &:nth-of-type(3) {
    width: calc(380px - 146px);
    padding-right: 30px;
  }

  &:nth-of-type(4) {
    width: calc(100% - 380px);
  }
}

.checkbox {
  width: 100%;
  height: 100%;
}

.btns {
  display: flex;
  justify-content: space-between;
  margin-top: 40px;

  .upload-btn {
    display: flex;
    align-items: center;

    >span {
      display: inline-block;
      margin-right: 4px;
    }

    i.tool-tip-for-editor {
      font-size: 12px;
      transform: scale(0.923) translateY(1px);
      cursor: default;
    }
  }

  >div {
    .cancel {
      margin-right: 16px;
    }
  }
}
</style>