<template>
  <div v-loading="listLoading" class="app-container page-component__scroll">
    <div class="filter-container">
      <div v-if="selectedCount" class="filter-control">
        <el-button
          type="primary"
          size="small"
          icon="el-icon-edit"
          plain
          :disabled="selectedCount > 1"
          @click="onEditFile"
        >编辑</el-button>
        <el-button type="primary" size="small" icon="el-icon-rank" plain @click="onMoveFile">移动</el-button>
        <el-button type="primary" size="small" icon="el-icon-download" plain @click="onDownload">下载</el-button>
        <el-button type="primary" size="small" icon="el-icon-delete" plain @click="onDelete">删除</el-button>
      </div>
      <template v-else>
        <div class="filter-control">
          <OssUpload
            ref="ossUpload"
            :limit="999"
            :delay-upload="delayUpload"
            :multiple="true"
            :button-group="buttonGroup"
            :on-success="onSuccess"
            :on-error="onError"
            @typeChange="onOssUploadTypeChange"
          />
        </div>
        <div class="filter-control">
          <el-button
            type="primary"
            size="small"
            icon="el-icon-folder-add"
            plain
            @click="onCreateDir"
          >新建文件夹</el-button>
          <el-button
            type="primary"
            size="small"
            icon="el-icon-s-promotion"
            plain
            @click="onPublishArticle"
          >发布文章</el-button>
          <el-button
            type="primary"
            size="small"
            icon="el-icon-alarm-clock"
            plain
            @click="onUploadHistory"
          >上传记录</el-button>
        </div>
      </template>
    </div>
    <!-- 面包屑 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/docs/0/list' }">全部文件</el-breadcrumb-item>
      <template v-for="(item, index) in crumbList">
        <template v-if="index === crumbList.length - 1">
          <el-breadcrumb-item :key="item.id">
            <span class="cell">{{ item.fileName }}</span>
          </el-breadcrumb-item>
        </template>
        <template v-else>
          <el-breadcrumb-item :key="item.id" :to="{ path: `/docs/${item.id}/list` }">
            <span>{{ item.fileName | crumbFormat }}</span>
          </el-breadcrumb-item>
        </template>
      </template>
    </el-breadcrumb>
    <!-- 列表 -->
    <el-table
      :data="list"
      style="width: 100%"
      :row-style="{ cursor: 'pointer' }"
      @selection-change="onSelectionChange"
      @row-dblclick="onRowClick"
    >
      <el-table-column type="selection" align="center" width="50" />
      <el-table-column label="文件名">
        <template slot-scope="{ row }">
          <doc-icon v-if="!listLoading" :type="row.fileType" :src="row.screenshot" />
          <span v-if="row.fileType === 'article'" class="file-name" @click.stop="onRowClick(row)">{{
            row.fileName | fileNameFormat
          }}</span>
          <span v-else class="file-name" @click.stop="onRowClick(row)">{{ row.fileName }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="createTime" label="时间" width="160">
        <template slot-scope="{ row }">{{ row.saveTime | formatTime }}</template>
      </el-table-column>
      <el-table-column label="大小" width="120">
        <template slot-scope="{ row }">
          <span v-if="row.packageType > 0">{{ row.fileSize | fileSize }}</span>
          <span v-else>-</span>
        </template>
      </el-table-column>
    </el-table>

    <!-- 创建文件夹弹窗 -->
    <el-dialog :title="editText" :visible.sync="editDialog" width="30%" :close-on-click-modal="false" @close="onCancel">
      <el-form ref="ruleForm" :model="formData" :rules="rules" label-width="80">
        <el-form-item prop="fileName" label="名称：">
          <el-input v-model="formData.fileName" placeholder="请输入文件名" @keyup.enter.native="onSubmit" />
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editDialog = false">取 消</el-button>
        <el-button type="primary" @click="onSubmit">确 定</el-button>
      </span>
    </el-dialog>

    <!-- 移动文件 -->
    <el-dialog title="选择移动位置" :visible.sync="moveDialog" width="60%" :close-on-click-modal="false">
      <el-button icon="el-icon-arrow-left" :disabled="lastDisabled" size="mini" @click="currentIndex--" />
      <el-button icon="el-icon-arrow-right" :disabled="nextDisabled" size="mini" @click="currentIndex++" />
      <el-table
        :data="filterSameDir(moveCurrentDir.childList)"
        :row-style="{ cursor: 'pointer' }"
        style="width: 100%"
        :height="300"
        empty-text="该目录为空"
        @row-dblclick="onMoveRowClick"
      >
        <el-table-column label="文件名">
          <template slot-scope="{ row }">
            <doc-icon v-if="!listLoading" :type="row.fileType" />
            <span class="file-name" @click.stop="onMoveRowClick(row)">{{ row.fileName }}</span>
          </template>
        </el-table-column>
      </el-table>
      <span slot="footer" class="dialog-footer">
        <el-button @click="onMoveCancel">取 消</el-button>
        <el-button type="primary" @click="onSubmitMove">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import DocIcon from '@/views/components/DocIcon'
import { OssUpload } from '@/components/OssUpload'
import {
  createPackage,
  fetchDocsList,
  removePackage,
  saveFile,
  updatePackage,
  fetchPathCumbs,
  fetchDirTree,
  movePackage,
  saveFileWithDir
} from '@/api/doc'
import { downloadWithUrl } from '@/utils/tools'
export default {
  name: 'DocsAllList',
  components: { DocIcon, OssUpload },
  filters: {
    fileSize(size) {
      size = Math.round(size / 1024)
      if (size < 1024) return size + 'KB'
      size = Math.round(size / 1024)
      if (size < 1024) return size + 'MB'
      return Math.round(size / 1024) + 'GB'
    },
    crumbFormat(name) {
      if (name.length < 12) return name
      return name.substring(0, 10) + '…'
    },
    fileNameFormat(name) {
      return name.replace(/(.+)(.txt$)/, (match, $1, $2) => {
        return $1
      })
    }
  },
  data() {
    const fileNameValidate = (rule, value, callback) => {
      if (/[\\\/\[\]\|^%&',;=?$\x22]+/g.test(value)) {
        callback(new Error("文件名不能包含|\/\\^%&',;=?$等特殊字符"))
      } else {
        callback()
      }
    }

    return {
      selectionList: [], // 选中列表
      list: [],
      fileId: 0,
      editDialog: false,
      moveDialog: false,
      listLoading: false,
      formData: {
        fileName: '',
        fileId: ''
      },
      rules: {
        fileName: [
          { required: true, message: '文件名不能为空', trigger: ['blur'] },
          { validator: fileNameValidate, trigger: ['blur'] }
        ]
      },
      editType: '',
      current: null,
      crumbList: [],
      currentDirStack: [],
      currentIndex: 0,
      message: null,
      buttonGroup: [
        {
          type: 'file',
          color: 'primary',
          text: '上传文件',
          size: 'small',
          plain: true,
          icon: 'el-icon-upload2'
        },
        {
          type: 'folder',
          color: 'primary',
          text: '上传文件夹',
          size: 'small',
          plain: true,
          icon: 'el-icon-upload2'
        }
      ],
      uploadType: 'record',
      delayUpload: false
    }
  },
  computed: {
    selectedCount() {
      return this.selectionList.length
    },
    editText() {
      const texts = {
        editType: '创建文件夹',
        editFile: '修改文件'
      }
      return texts[this.editType]
    },
    moveCurrentDir() {
      return this.currentDirStack[this.currentIndex] || []
    },
    lastDisabled() {
      return this.currentIndex === 0 || this.currentDirStack.length === 0
    },
    nextDisabled() {
      return this.currentIndex === this.currentDirStack.length - 1 || this.currentDirStack.length === 0
    }
  },
  created() {
    this.init()
  },
  activated() {
    this.init()
  },
  methods: {
    // 排除相同文件夹
    filterSameDir(dirList) {
      if (!dirList) dirList = []
      return dirList.filter((item) => {
        return !this.selectionList.find((file) => file.id === item.id)
      })
    },
    // 获取文件夹结构
    async fetchDirTree() {
      try {
        const res = await fetchDirTree()
        res.data.fileName = '根目录'
        this.currentDirStack.push(res.data)
        this.currentIndex = this.currentDirStack.length - 1
      } catch (error) {
        console.log(error)
      }
    },

    // 处理面包屑
    generateCrumb(node) {
      const list = []
      if (!node) return list
      function recursive(node) {
        list.push(node)
        if (node.childNode) {
          recursive(node.childNode)
        }
      }
      recursive(node)
      return list
    },

    // 页面初始化
    init() {
      this.fileId = parseInt(this.$route.params.fileId)
      if (!this.fileId && this.fileId !== 0) return
      this.fetchDocsList()
      this.fetchPathCumbs()
    },

    // 获取面包屑导航
    async fetchPathCumbs() {
      try {
        const res = await fetchPathCumbs({ fileId: this.fileId })
        this.crumbList = this.generateCrumb(res.data)
      } catch (error) {
        console.log(error)
      }
    },
    // 获取资料库列表
    async fetchDocsList() {
      try {
        this.listLoading = true
        const res = await fetchDocsList({ fileId: this.fileId })
        this.list = res.data || []
        this.listLoading = false
      } catch (error) {
        console.log(error)
      }
    },
    // 保存上传文件
    async saveUploadFile(data) {
      try {
        await saveFile(data)
        this.fetchDocsList()
        if (this.message) this.message.close()
        this.message = this.$message.success('文件上传成功')
      } catch (error) {
        console.log(error)
      }
    },
    // 保存上传文件夹
    async saveUploadDir(fileList) {
      try {
        await saveFileWithDir({ params: fileList })
        this.fetchDocsList()
        if (this.message) this.message.close()
        this.message = this.$message.success('文件上传成功')
      } catch (error) {
        console.log(error)
      }
    },
    // 取消保存
    onCancel() {
      this.formData.fileId = ''
      this.formData.fileName = ''
      this.$refs.ruleForm.clearValidate()
    },
    // 保存
    async onSubmit() {
      const actions = {
        createDir: this.onSaveDir,
        editFile: this.onUpdateFile
      }
      try {
        await this.$refs.ruleForm.validate()
        actions[this.editType]()
      } catch (error) {
        console.log(error)
      }
    },
    // 保存文件夹
    async onSaveDir() {
      try {
        this.formData.fileId = this.fileId
        await createPackage(this.formData)
        this.fetchDocsList()
        this.editDialog = false
        this.$message.success('文件夹创建成功')
      } catch (error) {
        console.log(error)
      }
    },
    // 修改文件名
    async onUpdateFile() {
      try {
        await updatePackage(this.formData)
        this.fetchDocsList()
        this.editDialog = false
        this.$message.success('文件名修改成功')
      } catch (error) {
        console.log(error)
      }
    },
    // 选择文件并上传
    onChooseFile() {
      this.$refs.ossUpload.chooseFile()
    },
    // 上传成功
    onSuccess(res, file, fileList) {
      if (this.uploadType === 'folder') {
        this.onUploadWithDir(fileList)
      } else {
        this.onUploadWithFile(file)
      }
    },
    formatFileData(file) {
      const strList = file.name.split('.')
      const ossName = file.uuid + '.' + strList[strList.length - 1]
      return {
        fileName: file.name,
        ossName: ossName,
        ossUrl: file.ossUrl,
        fileSize: file.size,
        parentId: this.fileId,
        mime: file.raw.type,
        filePath: file.raw.webkitRelativePath || ''
      }
    },
    // 文件上传
    onUploadWithFile(file) {
      this.saveUploadFile(this.formatFileData(file))
    },
    // 文件夹上传
    onUploadWithDir(fileList) {
      const uploadFiles = fileList.map((file) => this.formatFileData(file))
      console.log(uploadFiles)
      this.saveUploadDir(uploadFiles)
    },
    // 上传错误
    onError(error) {
      console.log(error)
    },
    // 上传方式修改
    onOssUploadTypeChange(type) {
      this.uploadType = type
      this.delayUpload = type === 'folder'
    },
    // 查看历史记录
    onUploadHistory() {
      this.$refs.ossUpload.showRecord()
    },
    // 创建文件夹
    onCreateDir() {
      this.editType = 'createDir'
      this.editDialog = true
    },
    // 发布文章
    onPublishArticle() {
      const url = `/docs/article-edit?parentId=${this.fileId}`
      this.$router.push(url)
    },
    // 编辑文件
    onEditFile() {
      this.current = this.selectionList[0]
      if (this.current.fileType === 'article') {
        // 文章
        const url = `/docs/article-edit?parentId=${this.current.parentId}&articleId=${this.current.articleId}`
        this.$router.push(url)
      } else {
        this.editType = 'editFile'
        this.editDialog = true
        this.formData.fileName = this.current.fileName
        this.formData.fileId = this.current.id
      }
    },
    // 移动文件
    onMoveFile() {
      this.currentDirStack = []
      this.currentIndex = 0
      this.fetchDirTree()
      this.moveDialog = true
    },
    // 移动取消
    onMoveCancel() {
      this.moveDialog = false
      this.fetchDocsList()
    },
    // 移动确认
    async onSubmitMove() {
      const current = this.currentDirStack[this.currentIndex]
      const filedIds = this.selectionList.map((file) => file.id).join(',')
      try {
        await movePackage({ fileId: filedIds, parentId: current.id })
        this.moveDialog = false
        this.fetchDocsList()
        this.$message.success('文件移动成功')
      } catch (error) {
        console.log(error)
      }
    },
    // 下载文件
    async onDownload() {
      const confirmText = '文件'
      let fileName = '文件'
      const filedIds = this.selectionList.map((file) => file.id).join(',')
      const text = await this.$confirm(`确认下载所选${confirmText}?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).catch(() => {
        this.exportClubList = []
        this.$message.info('已取消操作')
      })
      if (text !== 'confirm') return
      let notification = null
      notification = this.$notify({
        title: '提示',
        message: `正在下载${confirmText}，请勿重复操作！`,
        duration: 0
      })
      // 下载链接
      let downUrl = ''
      if (this.selectionList.length === 1) {
        const target = this.selectionList[0]
        fileName = target.fileName
        if (target.packageType > 0) {
          downUrl = `${process.env.VUE_APP_BASE_API}/download/file?ossName=${
            target.ossName
          }&fileName=${encodeURIComponent(target.fileName)}`
        } else {
          downUrl = `${process.env.VUE_APP_BASE_API}/database/path/package/zip?fileId=${
            target.id
          }&fileName=${encodeURIComponent(target.fileName)}`
        }
      } else {
        // 使用a链接下载
        downUrl = `${process.env.VUE_APP_BASE_API}/database/path/chose/zip?fileId=${filedIds}`
      }
      downloadWithUrl(downUrl, fileName, {
        headers: {
          'X-Token': this.$store.getters.token
        }
      })
        .then((res) => {
          this.fetchDocsList()
        })
        .catch((err) => {
          console.log(err)
          this.$message.error(`下载${confirmText}失败`)
        })
        .finally(() => {
          notification.close()
        })
    },
    // 删除文件
    async onDelete(file) {
      const tip = file.packageType > 0 ? '确定删除该文件夹及其文件夹内的全部文件?' : '确定删除该文件?'
      let confirm = ''
      try {
        confirm = await this.$confirm(tip, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
      } catch (error) {
        console.log(error)
        this.$message.info('已取消操作')
      }
      if (confirm !== 'confirm') return false
      // 获取要删除的文件id
      const filedIds = this.selectionList.map((file) => file.id).join(',')
      try {
        this.listLoading = true
        await removePackage({ fileId: filedIds })
        this.fetchDocsList()
        this.$message.success('删除成功')
        this.listLoading = false
      } catch (error) {
        console.log(error)
      }
    },
    // 表格内容勾选
    onSelectionChange(val) {
      this.selectionList = val
    },
    // 文件点击
    onRowClick(row) {
      if (row.fileType === 'article') {
        // 文章
        const url = `/docs/article-edit?parentId=${row.parentId}&articleId=${row.articleId}`
        this.$router.push(url)
      } else if (row.packageType === 1) {
        // 其它文件
        console.log('详情')
        this.$router.push(`/docs/detail?id=${row.id}`)
      } else {
        this.$router.push(`/docs/${row.id}/list`)
        this.$store.dispatch('tagsView/delView', this.$route)
      }
    },
    // 移动位置点击
    onMoveRowClick(row) {
      if (this.currentIndex === this.currentDirStack.length - 1) {
        this.currentDirStack.push(row)
        this.currentIndex = this.currentDirStack.length - 1
      } else {
        this.currentDirStack.splice(this.currentIndex + 1, this.currentDirStack.length)
        this.currentDirStack.push(row)
        this.currentIndex = this.currentDirStack.length - 1
      }
    }
  }
}
</script>

<style scoped lang="scss">
.file-name {
  font-size: 14px;
  color: #666666;
  margin-left: 25px;
  cursor: pointer;
  line-height: 32px;
}

.file-name:hover {
  color: #1890ff;
}

.el-breadcrumb {
  margin: 16px 0;
  .cell {
    color: #999;
  }
}
</style>
