<template>
  <div>
    <div class="gva-search-box">
      <el-form ref="elSearchFormRef" :inline="true" :model="searchInfo" label-width="90px" class="demo-form-inline"
        @keyup.enter="handleSubmitSearch">
        <el-form-item label="创建日期" prop="createdAt" style="width:300px">
          <template #label>
            <span>
              <el-tooltip content="搜索范围是创建开始日期（包含）至创建结束日期（包含）" placement="top-start">
                <el-icon>
                  <QuestionFilled />
                </el-icon>
              </el-tooltip>
              创建日期
            </span>
          </template>
          <el-date-picker v-model="searchInfo.dateRange" type="daterange" value-format="YYYY-MM-DD" :clearable="false"
            :editable="false" />
        </el-form-item>
        <el-form-item label="关键词" style="width:300px">
          <template #label>
            <span>
              <el-tooltip content="从标题、副标题、摘要中搜索" placement="top-start">
                <el-icon>
                  <QuestionFilled />
                </el-icon>
              </el-tooltip>
              关键词
            </span>
          </template>
          <el-input v-model="searchInfo.keyword" class="keyword" placeholder="请输入" clearable style="width:100%" />
        </el-form-item>
        <el-form-item label="所属栏目" prop="channelId" style="width:300px">
          <el-cascader v-model="searchChannelId" :options="channelOptions" style="width:100%"
            :props="{ label: 'title', value: 'ID', disabled: 'disabled', emitPath: false }" :show-all-levels="true"
            clearable placeholder="请选择" filterable />
        </el-form-item>
        <el-form-item label="文章分类" prop="categoryId" style="width:300px">
          <el-cascader v-model="searchCategoryId" :options="categoryOptions" style="width:100%"
            :props="{ label: 'title', value: 'ID', disabled: 'disabled', emitPath: false }" :show-all-levels="true"
            clearable placeholder="请选择" filterable />
        </el-form-item>
        <el-form-item label="发布状态" prop="status" style="width:300px">
          <el-select v-model="searchInfo.status" placeholder="请选择" clearable style="width:300px">
            <el-option v-for="item in statusOptions" :key="item.key" :label="item.label" :value="item.key" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="search" @click="handleSubmitSearch">查询</el-button>
          <el-button icon="refresh" @click="handleResetSearch">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <div class="gva-table-box">
      <div class="gva-btn-list">
        <el-button type="primary" icon="plus" @click="handleAdd('0')">新增文章</el-button>
        <el-button icon="delete" style="margin-left: 10px;" :disabled="!multipleSelection.length"
          @click="handleMultiDelete">删除</el-button>
        <el-button icon="plus" style="margin-left: 10px;" :disabled="!multipleSelection.length"
          @click="handleMultiPublish">发布</el-button>
      </div>

      <!-- 由于此处菜单跟左侧列表一一对应所以不需要分页 pageSize默认999 -->
      <el-table ref="multipleTable" :data="tableData" row-key="ID" @selection-change="handleSelectionChange">
        <el-table-column fixed type="selection" width="40" align="center" />
        <el-table-column align="left" label="ID" min-width="60" prop="ID" />
        <el-table-column align="left" label="标题/副标题" min-width="270" prop="title">
          <template #default="scope">
            {{ scope.row.title }}
            <div><small>{{ scope.row.subtitle }}</small></div>
          </template>
        </el-table-column>
        <el-table-column align="left" label="摘要" min-width="400" prop="desc" class-name="text-truncate">
          <template #default="scope">
            <div>{{ scope.row.desc }}</div>
          </template>
        </el-table-column>
        <el-table-column align="left" label="标签" min-width="150" prop="tags">
          <template #default="scope">
            <el-tag v-for="(item, index) in formatTags(scope.row.tags)" :key="index" size="small"
              style="margin-right: 5px;">
              {{ item }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column align="left" label="时间" width="280">
          <template #default="scope">
            <div><b>发布时间：</b>{{ formatDate(scope.row.publishDate) }}</div>
            <div><b>最后更新：</b>{{ formatDate(scope.row.UpdatedAt) }}</div>
          </template>
        </el-table-column>
        <el-table-column align="left" label="所属栏目" prop="categories" width="180">
          <template #default="scope">
            <el-cascader v-model="scope.row.channelIds" :options="channelOptions" style="width:100%"
              :props="{ label: 'title', value: 'ID', emitPath: false, expandTrigger: 'hover', multiple: true }"
              :collapse-tags="true" :max-collapse-tags="3" filterable
              @visible-change="(flag) => { if (!flag) handleChangeChannels(scope.row) }"
              @remove-tag="() => { handleChangeChannels(scope.row) }" />
          </template>
        </el-table-column>
        <el-table-column align=" left" label="文章分类" prop="categories" width="180">
          <template #default="scope">
            <el-cascader v-model="scope.row.categoryIds" :options="categoryOptions" style="width:100%"
              :props="{ label: 'title', value: 'ID', emitPath: false, expandTrigger: 'hover', multiple: true }"
              :collapse-tags="true" :max-collapse-tags="3" filterable
              @visible-change="(flag) => { if (!flag) handleChangeCategories(scope.row) }"
              @remove-tag="() => { handleChangeCategories(scope.row) }" />
          </template>
        </el-table-column>
        <el-table-column align="left" label="作者" min-width="80" prop="author" />
        <el-table-column align="left" label="类型" min-width="80" prop="articleType">
          <template #default="scope">{{ formatArticleType(scope.row.articleType) }}</template>
        </el-table-column>
        <el-table-column align="left" label="状态" width="80">
          <template #default="scope">{{ formatStatus(scope.row.status) }}</template>
        </el-table-column>
        <el-table-column align="left" fixed="right" label="操作" width="80">
          <template #default="scope">
            <div>
              <el-button type="primary" link icon="memo" :disabled="scope.row.status === 2"
                @click="handleRowPreview(scope.row)">预览</el-button>
            </div>
            <div>
              <el-button type="primary" link icon="plus" :disabled="scope.row.status === 2"
                @click="handleRowChange(scope.row)">发布</el-button>
            </div>
            <div>
              <el-button type="primary" link icon="edit" @click="handleRowEdit(scope.row.ID)">编辑</el-button>
            </div>
            <div>
              <el-button type="primary" link icon="delete" @click="handleRowDelete(scope.row.ID)">删除</el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>
      <div class="gva-pagination">
        <el-pagination layout="total, sizes, prev, pager, next, jumper" :current-page="page" :page-size="pageSize"
          :page-sizes="[10, 30, 50, 100]" :total="total" @current-change="handleCurrentChange"
          @size-change="handleSizeChange" />
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, watch, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { formatDate } from '@/utils/format'
import { getSourceList } from '@/api/source'
import { getCategoryTree } from '@/api/category'
import { getChannelTree } from '@/api/channel'
import { formatTimeToStr } from '@/utils/date'
import { equalArr } from '@/utils/arr'
import {
  getArticleList,
  releaseArticle,
  deleteArticle,
  setArticleChannels,
  setArticleCategories
} from '@/api/article'

const router = useRouter()

const page = ref(1)
const total = ref(0)
const pageSize = ref(10)
const searchInfo = ref({})
const searchCategoryId = ref('')
const searchChannelId = ref('')
const tableData = ref([])
const multipleSelection = ref([])// 多选数据
const elSearchFormRef = ref()
const articleTypeOptions = ref([
  { key: 1, label: '图文' },
  { key: 2, label: '视频' },
])
const statusOptions = ref([
  { key: 1, label: '未发布' },
  { key: 2, label: '已发布' },
])

const formatArticleType = (value) => {
  const rowLabel = articleTypeOptions.value.filter(item => item.key === value)
  return rowLabel && rowLabel[0] && rowLabel[0].label
}

const formatStatus = (value) => {
  const rowLabel = statusOptions.value.filter(item => item.key === value)
  return rowLabel && rowLabel[0] && rowLabel[0].label
}

const formatTags = (tags) => {
  return tags && tags.split(',')
}

const initSearchInfo = () => {
  const endDate = new Date()
  const startDate = new Date(endDate.getTime() - 7 * 24 * 60 * 60 * 1000)

  searchChannelId.value = ''
  searchCategoryId.value = ''

  searchInfo.value = {
    dateRange: [
      formatTimeToStr(startDate, 'yyyy-MM-dd'),
      formatTimeToStr(endDate, 'yyyy-MM-dd'),
    ]
  }
}

initSearchInfo()

// 多选
const handleSelectionChange = (val) => {
  multipleSelection.value = val
}

const handleMultiDelete = () => {
  // @todo 批量删除
}
const handleMultiPublish = () => {
  // @todo 批量发布
}

// 重置
const handleResetSearch = () => {
  initSearchInfo()
  getTableData()
}

// 搜索
const handleSubmitSearch = () => {
  elSearchFormRef.value?.validate(async (valid) => {
    if (!valid) return
    if (searchInfo.value.status === '') {
      searchInfo.value.status = null
    }
    if (searchChannelId.value !== '') {
      searchInfo.value.channelId = parseInt(searchChannelId.value, 10)
    }
    if (searchCategoryId.value !== '') {
      searchInfo.value.categoryId = parseInt(searchCategoryId.value, 10)
    }
    getTableData()
  })
}

// 分页
const handleSizeChange = (val) => {
  pageSize.value = val
  getTableData()
}

// 修改页面容量
const handleCurrentChange = (val) => {
  page.value = val
  getTableData()
}

// 添加
const handleAdd = () => {
  router.push({ name: 'articleEdit' })
}

// 修改
const handleRowEdit = (ID) => {
  const query = { id: ID }
  router.push({ name: 'articleEdit', query })
}

// 删除
const handleRowDelete = (ID) => {
  ElMessageBox.confirm('此操作将永久删除文章, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(async () => {
    const res = await deleteArticle({ ID })
    if (res.code === 0) {
      ElMessage({
        type: 'success',
        message: '删除成功!'
      })
      if (tableData.value.length === 1 && page.value > 1) {
        page.value--
      }
      getTableData()
    }
  })
}

// 发布
const handleRowChange = (row) => {
  ElMessageBox.confirm('此操作将发布文章, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(async () => {
    const res = await releaseArticle({ ID: row.ID, status: 2 })
    if (res.code === 0) {
      ElMessage({
        type: 'success',
        message: '发布成功!'
      })
      if (tableData.value.length === 1 && page.value > 1) {
        page.value--
      }
      getTableData()
    }
  })
}

// 预览
const handleRowPreview = (row) => {
  ElMessage({
    type: 'success',
    message: '开发中。。。'
  })
}

// ----- 列表更新栏目相关 -----
const handleChangeChannels = async (row) => {
  await nextTick()
  const ids = row.channelIds.map(i => { return parseInt(i) })
  if (ids.length === 0) {
    restoreChannels(row, '所属栏目不能为空')
    return
  }
  // 比较是否有变化
  const existArr = row.channels && row.channels.map(i => { return String(i.ID) })
  if (equalArr(existArr, ids)) {
    return
  }
  const res = await setArticleChannels({
    ID: row.ID,
    channelIds: ids
  })
  if (res.code === 0) {
    ElMessage({ type: 'success', message: '所属栏目设置成功' })
    getTableData()
  } else {
    // 恢复回去
    restoreChannels(row, res.message)
  }
}
const restoreChannels = (row, message) => {
  row.channelIds = row.channels && row.channels.map(i => { return String(i.ID) })
  ElMessage({ type: 'error', message: message })
}
// ----- 列表分类相关 -----
const handleChangeCategories = async (row) => {
  await nextTick()
  const ids = row.categoryIds.map(i => { return parseInt(i) })
  if (ids.length === 0) {
    restoreCategories(row, '文章分类不能为空')
    return
  }
  // 比较是否有变化
  const existArr = row.categories && row.categories.map(i => { return String(i.ID) })
  if (equalArr(existArr, ids)) {
    return
  }
  const res = await setArticleCategories({
    ID: row.ID,
    categoryIds: ids
  })
  if (res.code === 0) {
    ElMessage({ type: 'success', message: '文章分类设置成功' })
    getTableData()
  } else {
    // 恢复回去
    restoreCategories(row, res.message)
  }
}
const restoreCategories = (row, message) => {
  row.categoryIds = row.categories && row.categories.map(i => { return String(i.ID) })
  ElMessage({ type: 'error', message: message })
}

watch(() => tableData.value, () => {
  // 初始化数据
  setCategoryIds()
  setChannelIds()
})

// ----- 查询 -----
const getTableData = async () => {
  const res = await getArticleList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
  if (res.code === 0) {
    tableData.value = res.data.list
    total.value = res.data.total
  }
}

const setCategoryIds = () => {
  tableData.value && tableData.value.forEach((row) => {
    row.categoryIds = row.categories && row.categories.map(i => { return String(i.ID) })
  })
}

const setChannelIds = () => {
  tableData.value && tableData.value.forEach((row) => {
    row.channelIds = row.channels && row.channels.map(i => { return String(i.ID) })
  })
}

// options 相关
const initOptions = (data, optionsData, disabled) => {
  data &&
    data.forEach(item => {
      if (item.children && item.children.length) {
        const option = {
          title: item.title,
          ID: String(item.ID),
          children: []
        }
        initOptions(
          item.children,
          option.children,
        )
        optionsData.push(option)
      } else {
        const option = {
          title: item.title,
          ID: String(item.ID),
        }
        optionsData.push(option)
      }
    })
}

const channelOptions = ref([])
const categoryOptions = ref([])

const getCategoryData = async () => {
  categoryOptions.value = []
  const res = await getCategoryTree()
  if (res.code === 0) {
    initOptions(res.data.categoryTree, categoryOptions.value, false)
  }
}
const getChannelData = async () => {
  channelOptions.value = []
  const res = await getChannelTree()
  if (res.code === 0) {
    initOptions(res.data.channelTree, channelOptions.value, false)
  }
}
const getSourceData = async () => {
  channelOptions.value = []
  const res = await getSourceList({ page: 1, pageSize: 999 })
  if (res.code === 0) {
    res.data.list && res.data.list.map(item => item.name)
  }
}

const setOptions = () => {
  getCategoryData()
  getChannelData()
  getSourceData()
}

setOptions()
getTableData()

</script>

<style type="scss">
.admin-box .el-table td .cell {
  line-height: 28px;
}

.text-truncate .cell {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
}
</style>
