<template>
  <div class="page-view flex-row-sb">
    <app-sync-tree
      ref="appAsyncTree"
      :actions="treeActions"
      :default-checked-keys="defaultCheckedKeys"
      :default-data="{ customConfigField: 'custom config field' }"
      :default-expanded-keys="defaultExpandedKeys"
      :expand-all="expandAll"
      :fields="treeFields"
      :props="treeProps"
      :request-method="getTreeNodes"
      highlight-first
      title="应用数据资源目录"
      @select="onTreeNodeClick"
    />

    <div class="flex-col flex-1 ml-15 h-100">
      <app-filter ref="app-filter" :model="filters" class="bg-white px-15 border-radius-5" label-width="90px"
                  @query="onQuery" @reset="onReset">
        <app-filter-item :filter-config="{ operation: 'EQUAL' }" :span="6" el-type="input" label="表资源名称">
          <el-input v-model="filters.name" clearable placeholder="请输入"
                    @keyup.enter.native="$refs['app-filter'].query" />
        </app-filter-item>
        <app-filter-item :span="6" label="数据库表名">
          <el-input v-model="filters.tableNameEn" clearable placeholder="请输入"
                    @keyup.enter.native="$refs['app-filter'].query" />
        </app-filter-item>
        <app-filter-item :span="6" label="发布状态">
          <el-select v-model="filters.deployed" clearable placeholder="请选择"
                     @keyup.enter.native="$refs['app-filter'].query">
            <el-option v-for="item in deployStatus" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </app-filter-item>
      </app-filter>

      <div class="pa-11 mt-11 bg-white flex-1 flex-col border-radius-5 overflow-h">
        <div class="mb-11 bg-white">
          <el-button icon="el-icon-plus" size="mini" type="primary" @click="addTable"> 添加表</el-button>
          <el-popover v-model="uploadVisible" placement="bottom" trigger="hover">
            <p>请先下载模板，填写完成后上传</p>
            <div class="text-c flex-row-c">
              <el-button class="mr-10" plain size="mini" type="primary" @click="download">下载模板</el-button>
              <el-upload
                ref="upload"
                :action="actionUrl"
                :before-upload="beforeUpload"
                :data="importData"
                :headers="headers"
                :multiple="false"
                :on-error="handleError"
                :on-success="handleSuccess"
                :show-file-list="false"
              >
                <el-button plain size="mini" type="warning">导入资源项</el-button>
              </el-upload>
            </div>
            <el-button slot="reference" :loading="uploadLoading" class="ml-10" icon="el-icon-upload2" size="mini"
                       type="primary"> 导入表
            </el-button>
          </el-popover>
          <el-button :disabled="selectedRows.length === 0" class="ml-10" icon="el-icon-refresh" size="mini"
                     type="primary" @click="dataMove"> 移动
          </el-button>
        </div>
        <app-table
          ref="table"
          :column="columns"
          :pagination="pagination"
          :table-data="tableData"
          :table-loading="tableLoading"
          :total="total"
          checkbox
          row-key="id"
          @selection-change="handleSelectionChange"
          @pagination-change="onPaginationChange"
          @row-dblclick="editTable"
        >
          <template #level="scope">
            <template v-for="item in getDictionaryByCode('zymj')">
              <el-tag v-if="item.value === scope.row['level']" :key="item.value" :label="item.value"
                      :type="scope.row['level'] === '4' ? 'danger' : ''"
              >{{ item.name }}
              </el-tag>
            </template>
          </template>
          <template #deployed="scope">
            <el-tag :type="scope.row['deployed'] === '1' ? '' : 'danger'">
              {{ scope.row['deployed'] === '1' ? '已发布' : '未发布' }}
            </el-tag>
          </template>
        </app-table>
      </div>
    </div>
    <source-dialog v-model="dialogVisible" :data="dialogdData" :title="dialogTitle" @confirm="onConfirm" />
    <fields-manage v-model="fieldDialogVisible" :data="rowData" title="字段管理" />
    <put-out-dialog v-model="putOutVisible" :data="rowData" @confirm="refresh" />
    <move-dialog v-model="dialogMove" :selected-rows="selectedRows" :title="MoveTitle"
                 @move-success="handleMoveSuccess" />
  </div>
</template>

<script>
import {getDictionaryByCode} from '@/utils/dictionary.js'
import tableMixin from '@/mixins/table.js' // 列表mixins
import sourceDialog from './sourceDialog.vue'
import fieldsManage from './fieldsManage.vue'
import putOutDialog from './PutOutDialog.vue'
import API from '@/api/business/dataAPPCatalog.js'
import {mapState} from 'vuex'
import MoveDialog from './MoveDialog.vue'

export default {
  name: 'AppLayerCatalogue',
  components: {MoveDialog, sourceDialog, fieldsManage, putOutDialog},
  mixins: [tableMixin],
  data() {
    const TREE_CONFIG = {
      treeProps: {
        value: 'id',
        label: 'name'
      },
      expandAll: false,
      defaultExpandedKeys: ['1'],
      defaultCheckedKeys: ['1'],
      // 此处fields内配置对象属性包括: label/prop/rules/type(枚举:switch/number/input(默认))/span/
      treeFields: [
        {
          label: '资源目录名称',
          prop: 'name',
          labelWidth: '120',
          rules: [{required: true, message: '资源目录名称不能为空'}]
        },
        {
          label: '资源目录编码',
          prop: 'code',
          labelWidth: '120',
          rules: [{required: true, message: '资源目录编码不能为空'}]
        }
      ],
      curNode: {} // 当前选择节点
    }
    const TABLE_CONFIG = {
      deployStatus: [
        {
          value: '1',
          label: '已发布'
        },
        {
          value: '0',
          label: '未发布'
        }
      ],
      // 列表表头
      columns: [
        {label: '表资源名称', prop: 'name'},
        {label: '表资源编码', prop: 'code'},
        {label: '数据库表名', prop: 'tableNameEn'},
        // { label: '中文', prop: 'tableNameCh' },
        {label: '发布状态', prop: 'deployed', dataType: 'slot', slot: 'deployed', width: '140', align: 'center'},
        {
          dataType: 'option',
          label: '操作',
          width: '260px',
          fixed: 'right',
          operation: [
            {
              name: '字段管理',
              type: 'text',
              size: 'mini',
              icon: 'el-icon-s-order',
              color: '#409eff',
              plain: true,
              clickFun: (row) => {
                this.rowData = row
                this.fieldManage(row)
              }
            },
            {
              name: '发布建表',
              type: 'text',
              size: 'mini',
              icon: 'el-icon-s-promotion',
              color: '#fa912a',
              plain: true,
              showHide: (row) => {
                return row.deployed !== '1'
              },
              clickFun: (row) => {
                this.publishTable(row)
              }
            },
            {
              name: '删除',
              type: 'text',
              size: 'mini',
              icon: 'el-icon-delete',
              color: 'red',
              plain: true,
              clickFun: (row) => {
                this.delTable(row)
              }
            }
          ]
        }
      ],
      defaultFilter: [
        {
          operation: 'EQUAL',
          property: 'appCatalogsId',
          relation: 'AND',
          value: ''
        }
      ],
      rowData: {}
    }
    const DIALOG_CONFIG = {
      dialogVisible: false,
      dialogTitle: '新增',
      fieldDialogVisible: false,
      dialogdData: {},
      putOutVisible: false,
      dialogMove: false,
      MoveTitle: '移动'
    }

    return {
      selectedRows: [], // 新增：存储选中的行数据
      treeData: [],
      ...TREE_CONFIG,
      ...TABLE_CONFIG,
      ...DIALOG_CONFIG,
      uploadVisible: false,
      uploadLoading: false,
      importData: {catalogId: ''}
    }
  },
  computed: {
    // 配置列表接口方法：只有配置了该计算属性 才会执行 table mixins中的getData方法
    dataMethod() {
      return API.queryAPPTable
    },
    actionUrl: (_) => `${window.context.portal}/biz/app/catalogs/table/v1/importFile`,
    ...mapState({
      headers: (state) => ({
        Authorization: `Bearer ${state.login.currentUser.token}`
      })
    })
  },

  methods: {
    getDictionaryByCode,
    // 树 -----------------
    async getTreeNodes() {
      const {value = []} = await API.getAPPTree()
      this.defaultExpandedKeys = [value?.[0]?.id || '']
      return {data: value || []}
    },

    reloadTree() {
      this.$refs.appAsyncTree.getTreeData()
    },

    /**
     * @description: treeActions支持函数也支持数组，由于实际场景当中 可能会动态设置按钮，故以函数示例来展示
     * @param {*} data 当前点击节点数据
     * @return {*} 当前节点展示的操作项数组
     */
    treeActions(data) {
      // 根节点判断方式以业务为准，此处仅为示例
      return [
        {label: '添加', type: 'add', method: this.addNode},
        {
          label: '编辑',
          type: 'edit',
          method: this.editNode,
          showHide: (row) => {
            return row.id !== '1'
          }
        },
        {
          label: '删除',
          type: 'delete',
          method: this.delNode,
          showHide: (row) => {
            return row.id !== '1'
          }
        }
      ]
    },

    onTreeNodeClick(node) {
      if (node.id === this.curNode?.id) return
      this.curNode = {...node}
      this.importData.catalogId = this.curNode.id
      this.getData()
    },

    async addNode(params, node) {
      const {code, name} = params
      const {id} = node
      const newNode = {
        code,
        name,
        parentId: id
      }
      try {
        const {state, message} = await API.addAPPTree(newNode)
        if (state) {
          this.reloadTree()
          this.$message.success('添加资源目录成功！')
        }
      } catch (err) {
        this.$message.warning(err || '添加资源目录失败！')
      }
    },
    async editNode(params) {
      const {code, name, parentId, id} = params
      const newNode = {
        code,
        name,
        id,
        parentId
      }
      try {
        const {state, message} = await API.editAPPTree(newNode)
        if (state) {
          this.reloadTree()
          this.$message.success('编辑资源目录成功！')
        }
      } catch (err) {
        this.$message.warning(err || '编辑资源目录失败！')
      }
    },
    async delNode(params, node) {
      try {
        const {state, message} = await API.removeAPPTree(node.id)
        if (state) {
          this.reloadTree()
          this.$message.success('删除资源目录成功！')
        }
      } catch (err) {
        this.$message.warning(err || '删除资源目录失败！')
      }
    },
    // 新增：处理表格选择变化
    handleSelectionChange(selection) {
      this.selectedRows = selection
      console.log(this.selectedRows, '勾选的数据')
    },

    dataMove() {
      if (this.selectedRows.length === 0) {
        this.$message.warning('请至少选择一条要移动的数据')
        return
      }
      this.dialogMove = true
      this.MoveTitle = '移动表-请选择移动的目标目录'
    },
    // 新增：移动确认后的处理
    handleMoveSuccess() {
      this.selectedRows = [] // 清空选择
      this.refresh() // 刷新数据
    },
    // 列表 ------------
    addTable() {
      if (!this.curNode?.id) {
        this.$message.warning('请选择资源项所属目录')
        return
      }
      this.dialogTitle = '新增数据资源项'
      this.dialogdData = {
        appCatalogsId: this.curNode.id
      }
      this.dialogVisible = true
    },
    editTable(row) {
      this.dialogTitle = `编辑 - ${row.name}`
      this.dialogdData = row
      this.dialogVisible = true
    },
    fieldManage() {
      this.fieldDialogVisible = true
    },
    delTable(row) {
      this.$confirm(`此操作将删除分类（${row.name}）, 是否继续?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(async () => {
          try {
            const {state, message} = await API.removeAppSource(row.id)
            if (state) {
              this.getData()
              this.$message.success('删除资源项成功！')
            } else {
              this.$message.warning(message || '删除资源项失败！')
            }
          } catch (err) {
            this.$message.warning(err || '删除资源项失败！')
          }
        })
        .catch(() => {
        })
    },
    onBeforeGetData(queryParams, formData) {
      this.setFilterValue(this.queryParams, this.defaultFilter, 'appCatalogsId', this.curNode.id)
    },
    onConfirm(data, pData) {
      this.getData()
    },
    async publishTable(data) {
      this.rowData = data
      this.putOutVisible = true
      //   this.$confirm(`此操作将发布（${data.name}）, 是否继续?`, '提示', {
      //     confirmButtonText: '确定',
      //     cancelButtonText: '取消',
      //     type: 'warning',
      //   })
      //     .then(async () => {
      //       try {
      //         const { state, message } = await API.publishAppSource(data.id);
      //         if (state) {
      //           this.getData();
      //           this.$message.success('资源项发布成功！');
      //         } else {
      //           this.$message.warning(message || '资源项发布失败！');
      //         }
      //       } catch (err) {
      //         this.$message.warning(err || '资源项发布失败！');
      //       }
      //     })
      //     .catch(() => {});
    },

    download() {
      const fileType = '数据应用层数据资源表清单.xlsx'
      var a = document.createElement('a')
      a.href = window.context.download + fileType
      a.download = fileType // 设置下载文件文件名
      a.style.display = 'none'
      document.body.appendChild(a)
      a.click()
      a.remove()
    },

    //  导入文件上传前
    beforeUpload(file) {
      return new Promise((resolve, reject) => {
        this.uploadLoading = true
        const {size, name} = file
        this.$confirm(`请确认是否导入 “${name}” ？`, '提示', {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning'
        })
          .then((_) => {
            let passedOrNot = true // 是否通过验证
            const typeRegular = /\.(xls|xlsx)$/i
            const verification = [
              {
                condition: !typeRegular.test(name),
                result: () => this.$message.error('只能上传xls或xlsx文件类型')
              }
            ]
            verification.forEach((item) => {
              if (item.condition) {
                item.result()
                passedOrNot = false
                this.uploadLoading = false
              }
            })

            passedOrNot ? resolve() : reject()
          })
          .catch((_) => {
            reject()
            this.uploadLoading = false
            this.$message.warning('已取消上传')
          })
      })
    },

    // 导入文件上传成功
    handleSuccess(res) {
      if (res.state) {
        this.$message.success('导入成功')
        this.uploadLoading = false
        this.getData()
      } else {
        this.$message.error(res.message)
      }
    },

    // 导入文件上传失败
    handleError(err) {
      if (err) {
        let errData = err.toString().replace('Error:', '')
        errData = JSON.parse(errData)
        this.$message.error(errData.message || '导入失败，请重试')
      } else {
        this.$message.error('导入失败，请重试')
      }
      this.uploadLoading = false
    }
  }
}
</script>

<style lang="scss" scoped></style>
