You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

403 lines
12 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div>
<el-card shadow="never" class="search-card">
<FormSearch
:fields="searchFormFields"
:loading="loading"
:show-create="false"
:show-delete="false"
:disabled-delete="selectedRow.length === 0"
:default-search="search"
@onSearch="onSearch"
>
<template slot="buttons">
<el-form-item>
<el-button
type="success"
icon="el-icon-refresh-left"
:disabled="selectedRow.length === 0"
@click="batchRecover"
></el-button
> </el-form-item
><el-form-item>
<el-button
type="warning"
icon="el-icon-close"
:disabled="selectedRow.length === 0"
@click="batchDelete"
></el-button
> </el-form-item
><el-form-item>
<el-button
type="danger"
:disabled="selectedRow.length > 0"
icon="el-icon-delete"
@click="clearAll"
></el-button
>
</el-form-item>
</template>
</FormSearch>
</el-card>
<el-card shadow="never" class="mgt-20px">
<TableList
:loading="loading"
:table-data="documents"
:fields="tableListFields"
:show-actions="true"
:show-view="false"
:show-edit="false"
:show-delete="true"
:show-select="true"
@selectRow="selectRow"
@deleteRow="deleteRow"
>
<template slot="actions" slot-scope="scope">
<el-button
type="text"
icon="el-icon-refresh-left"
size="small"
@click="recoverRow(scope.row)"
></el-button
>
</template>
</TableList>
</el-card>
<el-card shadow="never" class="mgt-20px">
<div class="text-right">
<el-pagination
background
:current-page="search.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="search.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handlePageChange"
>
</el-pagination>
</div>
</el-card>
</div>
</template>
<script>
import { listCategory } from '~/api/category'
import {
clearRecycleDocument,
deleteRecycleDocument,
listRecycleDocument,
recoverRecycleDocument,
} from '~/api/document'
import TableList from '~/components/TableList.vue'
import FormSearch from '~/components/FormSearch.vue'
import { categoryToTrees, parseQueryIntArray, genLinkHTML } from '~/utils/utils'
import { documentStatusOptions } from '~/utils/enum'
import { mapGetters } from 'vuex'
export default {
components: { TableList, FormSearch },
layout: 'admin',
data() {
return {
loading: false,
formVisible: false,
search: {
page: 1,
size: 10,
},
documents: [],
trees: [],
categoryMap: {},
total: 0,
searchFormFields: [],
tableListFields: [],
selectedRow: [],
documentStatusOptions,
document: { id: 0 },
}
},
head() {
return {
title: `回收站 - ${this.settings.system.sitename}`,
}
},
computed: {
...mapGetters('setting', ['settings']),
},
watch: {
'$route.query': {
immediate: true,
async handler() {
this.search = {
...this.search,
...this.$route.query,
page: parseInt(this.$route.query.page) || 1,
size: parseInt(this.$route.query.size) || 10,
...parseQueryIntArray(this.$route.query, ['category_id', 'status']),
}
// 需要先加载分类数据
if (this.trees.length === 0) {
await this.listCategory()
}
await this.listDocument()
},
},
},
async created() {
this.initSearchForm()
this.initTableListFields()
},
methods: {
async listCategory() {
const res = await listCategory({ field: ['id', 'parent_id', 'title'] })
if (res.status === 200) {
let categories = res.data.category || []
categories = categories.map((item) => {
item.disable_delete = item.doc_count > 0
return item
})
const categoryMap = {}
categories.forEach((item) => {
categoryMap[item.id] = item
})
this.categoryMap = categoryMap
this.trees = categoryToTrees(categories, false)
this.total = res.data.total
this.initSearchForm()
} else {
this.$message.error(res.data.message)
}
},
async listDocument() {
this.loading = true
const search = { ...this.search }
if (search.category_id && typeof search.category_id === 'object') {
search.category_id = search.category_id[search.category_id.length - 1]
}
const res = await listRecycleDocument(search)
this.loading = false
if (res.status === 200) {
const documents = res.data.document || []
documents.forEach((item) => {
;(item.category_id || (item.category_id = [])).forEach((id) => {
;(item.category_name || (item.category_name = [])).push(
this.categoryMap[id].title || '-' // 有可能分类已经被删除
)
})
item.title_html = genLinkHTML(item.title, `/document/${item.id}`)
item.username_html = genLinkHTML(
item.username,
`/user/${item.user_id}`
)
})
this.documents = documents
this.total = res.data.total
} else {
this.$message.error(res.data.message)
}
},
handleSizeChange(val) {
this.search.size = val
this.$router.push({
query: this.search,
})
},
handlePageChange(val) {
this.search.page = val
this.$router.push({
query: this.search,
})
},
onSearch(search) {
this.search = { ...this.search, ...search, page: 1 }
if (
location.pathname + location.search ===
        this.$router.resolve({
          query: this.search,
        }).href
) {
this.listDocument()
} else {
this.$router.push({
query: this.search,
})
}
},
recoverRow(row) {
this.$confirm(`您确定要要恢复【${row.title}】吗?`, '', {
confirmButtonText: '',
cancelButtonText: '',
type: 'info',
}).then(async () => {
const res = await recoverRecycleDocument({ id: [row.id] })
if (res.status === 200) {
this.$message.success('')
this.listDocument()
} else {
this.$message.error(res.data.message || '')
}
})
},
clearAll() {
this.$confirm(
'',
'',
{
confirmButtonText: '',
cancelButtonText: '',
type: 'error',
}
).then(async () => {
const res = await clearRecycleDocument({ id: 0 })
if (res.status === 200) {
this.$message.success('')
this.listDocument()
} else {
this.$message.error(res.data.message || '')
}
})
},
batchRecover() {
this.$confirm(
`您确定要从回收站中恢复选中的【${this.selectedRow.length}个】文档吗?`,
'',
{
confirmButtonText: '',
cancelButtonText: '',
type: 'info',
}
)
.then(async () => {
const ids = this.selectedRow.map((item) => item.id)
const res = await recoverRecycleDocument({ id: ids })
if (res.status === 200) {
this.$message.success('')
this.listDocument()
} else {
this.$message.error(res.data.message)
}
})
.catch(() => {})
},
batchDelete() {
this.$confirm(
`您确定要从回收站中删除选中的【${this.selectedRow.length}个】文档吗?删除之后不可恢复!`,
'',
{
confirmButtonText: '',
cancelButtonText: '',
type: 'info',
}
)
.then(async () => {
const ids = this.selectedRow.map((item) => item.id)
const res = await deleteRecycleDocument({ id: ids })
if (res.status === 200) {
this.$message.success('')
this.listDocument()
} else {
this.$message.error(res.data.message)
}
})
.catch(() => {})
},
deleteRow(row) {
this.$confirm(
`您确定要从回收站中删除文档【${row.title}】吗?删除之后不可恢复!`,
'',
{
confirmButtonText: '',
cancelButtonText: '',
type: 'warning',
}
)
.then(async () => {
const res = await deleteRecycleDocument({ id: row.id })
if (res.status === 200) {
this.$message.success('')
this.listDocument()
} else {
this.$message.error(res.data.message)
}
})
.catch(() => {})
},
selectRow(rows) {
this.selectedRow = rows
},
initSearchForm() {
this.searchFormFields = [
{
type: 'text',
label: '',
name: 'wd',
placeholder: '',
},
{
type: 'select',
label: '',
name: 'status',
placeholder: '',
multiple: true,
options: documentStatusOptions,
},
// 级联
{
type: 'cascader',
label: '',
name: 'category_id',
placeholder: '',
trees: this.trees,
},
]
},
initTableListFields() {
const statusMap = {}
this.documentStatusOptions.forEach((item) => {
statusMap[item.value] = item
})
this.tableListFields = [
{ prop: 'id', label: 'ID', width: 80, type: 'number', fixed: 'left' },
{
prop: 'title_html',
label: '',
minWidth: 200,
fixed: 'left',
type: 'html',
},
{ prop: 'username_html', label: '', width: 120, type: 'html' },
{ prop: 'deleted_username', label: '', width: 120 },
{ prop: 'deleted_at', label: '', width: 160, type: 'datetime' },
{
prop: 'status',
label: '',
width: 120,
type: 'enum',
enum: statusMap,
},
{
prop: 'category_name',
label: '',
minWidth: 180,
type: 'breadcrumb',
},
{ prop: 'pages', label: '', width: 80, type: 'number' },
{ prop: 'price', label: '', width: 80, type: 'number' },
{ prop: 'download_count', label: '', width: 80, type: 'number' },
{ prop: 'view_count', label: '', width: 80, type: 'number' },
{ prop: 'favorite_count', label: '', width: 80, type: 'number' },
{ prop: 'comment_count', label: '', width: 80, type: 'number' },
{ prop: 'keywords', label: '', minWidth: 200 },
// { prop: 'description', label: '摘要', minWidth: 200 },
{ prop: 'created_at', label: '', width: 160, type: 'datetime' },
{ prop: 'updated_at', label: '', width: 160, type: 'datetime' },
]
},
},
}
</script>
<style></style>