<template>
  <el-dialog :title="title" :visible.sync="visible" width="1200px" append-to-body>
    <div class="structure-container">
      <div class="tree-panel">
        <el-tree
          :data="structureData"
          :props="defaultProps"
          node-key="id"
          default-expand-all
          :expand-on-click-node="false"
          @node-click="handleNodeClick"
        >
          <span class="custom-tree-node" slot-scope="{ node, data }">
            <span>
              <i :class="getIconClass(data.type)"></i>
              {{ node.label }}
            </span>
          </span>
        </el-tree>
      </div>
      <div class="code-panel">
        <div v-if="preview.data && Object.keys(preview.data).length > 0" class="code-preview">
          <div class="preview-header">
            <span class="preview-title">{{ preview.activeName }}</span>
            <el-link
              :underline="false"
              icon="el-icon-document-copy"
              v-clipboard:copy="Object.values(preview.data)[0]"
              v-clipboard:success="clipboardSuccess"
              class="copy-btn"
            >复制</el-link>
          </div>
          <div class="preview-content" ref="previewContent">
            <pre><code class="hljs" v-html="highlightedCode(Object.values(preview.data)[0], Object.keys(preview.data)[0])"></code></pre>
          </div>
        </div>
        <div v-else class="empty-preview">
          <span>请点击左侧文件查看代码</span>
        </div>
      </div>
    </div>
    <div slot="footer" class="dialog-footer">
      <el-button @click="handleBack">返 回</el-button>
      <el-button
        type="primary"
        @click="handleDownload"
        v-hasPermi="['generator:project:download']"
      >下 载</el-button>
    </div>
  </el-dialog>
</template>

<script>
import { getProjectStructure, previewTableNew } from '@/api/generator/project'
import hljs from 'highlight.js/lib/highlight'
import 'highlight.js/styles/atom-one-dark.css'
hljs.registerLanguage('java', require('highlight.js/lib/languages/java'))
hljs.registerLanguage('xml', require('highlight.js/lib/languages/xml'))
hljs.registerLanguage('yaml', require('highlight.js/lib/languages/yaml'))
hljs.registerLanguage('html', require('highlight.js/lib/languages/xml'))
hljs.registerLanguage('vue', require('highlight.js/lib/languages/xml'))
hljs.registerLanguage('javascript', require('highlight.js/lib/languages/javascript'))
hljs.registerLanguage('sql', require('highlight.js/lib/languages/sql'))
hljs.registerLanguage('json', require('highlight.js/lib/languages/json'))
hljs.registerLanguage('css', require('highlight.js/lib/languages/css'))
hljs.registerLanguage('bash', require('highlight.js/lib/languages/bash'))
hljs.registerLanguage('properties', require('highlight.js/lib/languages/properties'))
hljs.registerLanguage('markdown', require('highlight.js/lib/languages/markdown'))
hljs.registerLanguage('typescript', require('highlight.js/lib/languages/typescript'))
hljs.registerLanguage('scss', require('highlight.js/lib/languages/scss'))
hljs.registerLanguage('less', require('highlight.js/lib/languages/less'))
hljs.registerLanguage('php', require('highlight.js/lib/languages/php'))
hljs.registerLanguage('python', require('highlight.js/lib/languages/python'))
hljs.registerLanguage('javascript', require('highlight.js/lib/languages/javascript'))

export default {
  name: 'ProjectStructure',
  data() {
    return {
      visible: false,
      projectId: '',
      type: '',
      title: '项目结构预览',
      structureData: [],
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      preview: {
        data: {}
      }
    }
  },
  methods: {
    init(projectId, type) {
      this.projectId = projectId
      this.type = type
      this.visible = true
      getProjectStructure(projectId, type).then(response => {
        this.structureData = response.data
      })
    },
    getIconClass(type) {
      return type === 'folder' ? 'el-icon-folder' : 'el-icon-document'
    },
    handleNodeClick(data) {
      this.preview.activeName = data.name
      if (data.type === 'file') {
        this.previewCode(this.projectId, data.tableId, data.category, this.type)
      }
    },
    previewCode(projectId, tableId, category, type) {
      previewTableNew(projectId, tableId, category, type).then(response => {
        this.preview.data = response.data
        this.$nextTick(() => {
          const previewContent = this.$refs.previewContent
          previewContent.scrollTop = 0
        })
      })
    },
    highlightedCode(code, key) {
      const vmName = key.substring(key.lastIndexOf('/') + 1, key.indexOf('.vm'))
      var language = vmName.substring(vmName.indexOf('.') + 1, vmName.length)

      // 处理config.js文件，使用javascript语法高亮
      if (key.includes('config.js')) {
        language = 'javascript'
      }
      if (key.includes('html')) {
        language = 'html'
      }
      if (key.includes('vue')) {
        language = 'vue'
      }
      if (key.includes('js')) {
        language = 'javascript'
      }
      if (key.includes('css')) {
        language = 'css'
      }
      if (key.includes('sql')) {
        language = 'sql'
      }

      const result = hljs.highlight(language, code || '', true)
      return result.value || '&nbsp;'
    },
    clipboardSuccess() {
      this.$modal.msgSuccess('复制成功')
    },
    handleDownload() {
      this.$download.zip(`/generator/project/download/${this.projectId}/${this.type}`)
    },
    handleBack() {
      this.visible = false
    }
  }
}
</script>

<style scoped>
.structure-container {
  display: flex;
  height: 600px;
}

.tree-panel {
  width: 300px;
  border-right: 1px solid #e6e6e6;
  padding-right: 10px;
  overflow-y: auto;
}

.code-panel {
  flex: 1;
  padding-left: 20px;
  overflow-y: auto;
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}

.empty-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #909399;
}

.code-preview {
  height: 100%;
}
.preview-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
  padding: 0 10px;
}

.preview-title {
  font-size: 16px;
  font-weight: 500;
  color: #303133;
}

.copy-btn {
  color: #409EFF;
  font-size: 14px;
}

.copy-btn:hover {
  color: #66b1ff;
}

.code-preview pre {
  margin: 0;
  padding: 10px;
  background-color: #f6f8fa;
  border-radius: 4px;
}

.dialog-footer {
  display: flex;
  justify-content: center;
  gap: 20px;
  padding: 10px 20px;
  border-top: 1px solid #e6e6e6;
}
</style>
