<template>
<div>
  <div class="search-panel">
  <el-form inline :model="search">
    <el-form-item label="标题">
      <el-input v-model="search.title" />
    </el-form-item>
    <el-form-item label="创建时间">
      <el-date-picker
        v-model="search.createDate"
        type="daterange"
        range-separator="至"
        start-placeholder="开始日期"
        end-placeholder="结束日期" />
    </el-form-item>
    <el-form-item label="分类">
      <el-select v-model="search.category" filterable clearable>
        <el-option v-for="item in categories" :key="item" :value="item" :label="item" />
      </el-select>
    </el-form-item>
    <el-form-item label="标签">
      <el-select v-model="search.tag" filterable clearable>
        <el-option v-for="item in tags" :key="item" :value="item" :label="item" />
      </el-select>
    </el-form-item>
    <el-form-item label="已分词">
      <el-select v-model="search.isSplited" >
        <el-option :value="true" label="是" />
        <el-option :value="false" label="否" />
      </el-select>
    </el-form-item>
  </el-form>
  </div>
  <div class="btn-container">
    <el-button type="primary" @click="splitWord" style="vertical-align: bottom">分词处理</el-button>
    <el-button @click="pullArticles" style="vertical-align: bottom">拉取文章</el-button>
    <el-upload
      action="/api/system/deployBlog"
      accept="application/zip"
      name="blogZip"
      :headers="{token: store.state.loginInfo.token}"
      :before-upload="beforeUpload"
      :on-success="uploadSuccess"
      :on-error="uploadError" 
      auto-upload
      :show-file-list="false"
      style="display: inline-block;margin-left: 10px;">
      <el-button type="primary" icon="Upload" :loading="isUploading">发布博客</el-button>
    </el-upload>
    <div class="search-btn">
      <el-button type="primary" @click="loadDataBase(true)" icon="Search">搜索</el-button>
      <el-button @click="reset" icon="RefreshLeft">重置</el-button>
    </div>
  </div>
  <el-row>
    <el-col :span="4" style="height: 520px;overflow: auto;">
      <el-tree :props="treeProps" :load="loadTreeData" lazy highlight-current @node-click="articlePreview" />
    </el-col>
    <el-col :span="20">
      <div class="table-container">
      <el-table :data="articleData" v-loading="loading" stripe @selection-change="dataSelect">
        <el-table-column type="selection" width="55" />
        <el-table-column prop="title" label="标题" />
        <el-table-column prop="path" label="路径" >
          <template #default="scope">
            {{ scope.row.path.join('/') }}
          </template>
        </el-table-column>
        <el-table-column prop="categories" label="分类" width="150" >
          <template #default="scope">
            {{ typeof scope.row.categories === 'string' ? scope.row.categories : scope.row.categories?.join('，') }}
          </template>
        </el-table-column>
        <el-table-column prop="tags" label="标签" width="180" >
          <template #default="scope">
            {{ typeof scope.row.tags === 'string' ? scope.row.tags : scope.row.tags?.join('，') }}
          </template>
        </el-table-column>
        <el-table-column prop="content_len" label="正文长度" width="100" />
        <el-table-column prop="create_date" label="创建时间" width="180" >
          <template #default="scope">
            {{ datetimeFormat(scope.row.create_date) }}
          </template>
        </el-table-column>
        <el-table-column prop="tags" label="是否已分词" width="120" >
          <template #default="scope">
            <div style="width: 18px">
              <Check v-if="scope.row.is_splited" />
              <Close v-else/>
            </div>
          </template>
        </el-table-column>
      </el-table>
      <div class="page-container">
        <el-pagination background 
          :page-sizes="store.state.pageSizeOpts"
          :layout="store.state.pageLayout"
          :current-page="search.pageNum"
          :total="total"
          @size-change="pageSizeChange"
          @current-change="pageChange">
        </el-pagination>
      </div>
      </div>
    </el-col>
  </el-row>
  <el-drawer
    v-model="markdownPreview.show"
    :title="markdownPreview.title"
    direction="rtl"
    class="custom-drawer">
    <div v-html="markdownPreview.content"></div>
  </el-drawer>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { useStore } from 'vuex'
import hyperdown from 'hyperdown'
import { ArticleModel, TreeNodeData, TreeNodeSource } from '@/model/system/article'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Node } from 'element-plus/lib/components/tree/src/model/node'
import { useBaseList } from '@/model/baselist'
import { Page, MsgResult } from '@/model/common.dto'
import http from '@/utils/http'

class ArticlePage extends Page {
  title?: string
  createDate?: [Date, Date]
  category?: string
  tag?: string
  isSplited?: boolean
  reset() {
    super.reset()
    this.title = undefined
    this.createDate = undefined
    this.category = undefined
    this.tag = undefined
    this.isSplited = undefined
  }
}

const store = useStore()
const { loading, total, search, setLoadData, loadDataBase, reset, pageChange, pageSizeChange, datetimeFormat } = useBaseList(new ArticlePage())

const articleData = ref<ArticleModel[]>([])
const tags = ref<string[]>([])
const categories = ref<string[]>([])
const markdownPreview = reactive<{
  show: boolean
  title: string | null
  content: string | null
}>({
  show: false,
  title: null,
  content: null
})
const isUploading = ref(false)

let selectedData: string[] = []

async function loadData() {
  loading.value = true
  const data = await http.get<ArticlePage, any>('/api/v1/article/list', {params: search})
  selectedData = []
  loading.value = false
  total.value = data.total
  articleData.value = data.data
}
setLoadData(loadData)

function splitWord() {
  if (!selectedData.length) {
    ElMessage.warning('请选择要执行分词的文章')
    return
  }
  ElMessageBox.confirm(`是否确认对选中的${selectedData.length}篇文章执行分词处理？`, '操作确认', {type: 'info'}).then(async () => {
    const data = await http.put<{_ids: string[]}, any>('/api/v1/article/splitWord', {_ids: selectedData})
    if (data.status) {
      ElMessage.success(data.message)
    } else {
      ElMessage.warning(data.message)
    }
  }).catch(() => {})
}
function pullArticles() {
  ElMessageBox.confirm('确认拉取全部文章？', '操作确认', {type: 'info'}).then(async () => {
    const data = await http.put<never, any>('/api/v1/article/pull')
    if (data.status) {
      ElMessage.success(data.message)
      loadData()
    } else {
      ElMessage.warning(data.message)
    }
  }).catch(() => {})
}
function dataSelect(selection: ArticleModel[]) {
  selectedData = selection.map(item => item._id)
}
function beforeUpload(file: File): boolean {
  isUploading.value = true
  return true
}
function uploadSuccess(response: MsgResult) {
  if (response.status) {
    ElMessage.success(response.message)
  } else {
    ElMessage.warning(response.message)
  }
  isUploading.value = false
}
function uploadError(error: Error) {
  isUploading.value = false
  ElMessage.error(error.message)
}

const treeProps = {
  label: 'name',
  children: 'children',
  isLeaf: 'isLeaf',
}
async function loadTreeData(node: Node, resolve: Function) {
  const childItems: TreeNodeSource[] = await http.get('/api/v1/article/tree', {params: {deep: node.level, parent: node.data.name}})
  resolve(childItems.map((childItem): TreeNodeData => {
    const treeNode: TreeNodeData = {
      name: childItem._id,
      title: childItem.article_id ? childItem._id : `${childItem._id}(${childItem.cnt})`,
      id: childItem.article_id || childItem._id,
      isLeaf: !!childItem.article_id
    }
    return treeNode
  }))
}
async function articlePreview(node: TreeNodeData) {
  if (!node.isLeaf) return
  const mdText = await http.get<never, any>('/api/v1/article/markdown', {params: {id: node.id}})
  markdownPreview.show = true
  const markdownHtml = new hyperdown().makeHtml(mdText)
  markdownPreview.content = markdownHtml.replace(/(?<=<pre><code[^>]*?>)[\s\S]*?(?=<\/code><\/pre>)/gi, (content: string) => {
    return content.replace(/_&/g, ' ').replace(/&quot;/g, '"').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&')
  })
  markdownPreview.title = node.name
}

// created
loadData()
http.get<never, any>('/api/v1/article/listCategories').then(data => {
  categories.value = data
})
http.get<never, any>('/api/v1/article/listTags').then(data => {
  tags.value = data
})
</script>
