CN-971知识库列表改版

This commit is contained in:
hyx
2023-04-26 23:46:23 +08:00
parent bc81631be3
commit 1faf418cc8
11 changed files with 1299 additions and 224 deletions

View File

@@ -1,55 +1,94 @@
<template>
<div style="height: 100%;" class="knowledge-base">
<div style="height: 100%;overflow:auto;" class="knowledge-base">
<div class="top-title">
{{$t('overall.knowledgeBase')}}
</div>
<cn-data-list
ref="dataList"
:tableId="tableId"
v-model:custom-table-title="tools.customTableTitle"
:api="url"
from="knowledge-base"
:layout="['columnCustomize','elementSet','search']"
@search="search"
>
<template v-slot:top-tool-left>
<button id="knowledge-base-add" :title="$t('knowledgeBase.createKnowledgeBase')" class="top-tool-btn margin-r-10 top-tool-btn--create"
@click="jumpToCreatePage">
<i class="cn-icon-xinjian cn-icon"></i>
<span>{{$t('overall.create')}}</span>
</button>
<button id="knowledge-base-edit" :title="$t('knowledgeBase.editKnowledgeBase')" class="top-tool-btn margin-r-10" :disabled="disableEdit"
@click="editSelectRecord">
<i class="cn-icon-edit cn-icon" ></i>
<span>{{$t('overall.edit')}}</span>
</button>
<button id="knowledge-base-delete" :title="$t('knowledgeBase.deleteKnowledgeBase')" class="top-tool-btn margin-r-10"
@click="delBatch">
<i class="cn-icon-delete cn-icon"></i>
<span>{{$t('overall.delete')}}</span>
</button>
</template>
<template v-slot:default>
<knowledge-base-table
ref="dataTable"
v-loading="tools.loading"
:api="url"
:custom-table-title="tools.customTableTitle"
:height="mainTableHeight"
:table-data="tableData"
@delete="del"
@edit="edit"
@orderBy="tableDataSort"
@reload="getTableData"
@selectionChange="selectionChange"
></knowledge-base-table>
</template>
<!-- 分页组件 -->
<template #pagination>
<pagination ref="pagination" :page-obj="pageObj" :table-id="tableId" @pageNo='pageNo' @pageSize='pageSize'></pagination>
</template>
</cn-data-list>
<div class="knowledge-base__content" style="">
<div class="left-filter" style="">
<knowledge-filter ref="knowledgeFilter"
@reload="reload"
@clearList="clearList"></knowledge-filter>
</div>
<div class="right-list-card" style="">
<div class="top-tools" style="">
<button id="knowledge-base-add" :title="$t('knowledgeBase.createKnowledgeBase')" class="top-tool-btn margin-r-10 top-tool-btn--create"
style="width:72px;"
@click="jumpToCreatePage">
<i class="cn-icon-xinjian cn-icon"></i>
<span>{{$t('overall.create')}}</span>
</button>
<button id="knowledge-base-edit" :title="$t('knowledgeBase.select')" class="top-tool-btn margin-r-10"
style="width:72px;"
@click="toSelect">
<i class="cn-icon-xuanzebianji cn-icon" ></i>
<span>{{$t('overall.select')}}</span>
</button>
<button id="knowledge-base-delete" :title="$t('knowledgeBase.deleteKnowledgeBase')" class="top-tool-btn margin-r-10"
style="width:72px;" :disabled="disableDelete"
@click="toDelete">
<i class="cn-icon-delete cn-icon"></i>
<span>{{$t('overall.delete')}}</span>
</button>
<div class="top-tool-search margin-l-10" style="">
<el-input v-model="keyWord" size="small" @keyup.enter="onSearch"></el-input>
<button class="top-tool-btn top-tool-btn--search" style="border-radius: 0 2px 2px 0 !important;" @click="onSearch">
<i class="el-icon-search"></i>
</button>
</div>
</div>
<div class="cards" style="" >
<knowledge-base-table
ref="dataTable"
v-loading="tools.loading"
:api="url"
:custom-table-title="tools.customTableTitle"
:table-data="tableData"
:is-selected-status="isSelectedStatus"
:all-count="18"
@delete="toDelete"
@checkboxStatusChange="checkboxStatusChange"
></knowledge-base-table>
</div>
<div class="knowledge-pagination" style="">
<pagination ref="pagination" :page-obj="pageObj" :table-id="tableId" @pageNo='pageNo' @pageSize='pageSize'></pagination>
</div>
</div>
</div>
</div>
<el-dialog v-model="showConfirmDialog"
:title="$t('overall.hint')"
width="480px"
custom-class="del-model-hint"
:before-close="handleClose">
<div class="dialog-message">{{$t('knowledge.deleteDataHint')}}</div>
<el-table v-model="delItemList"
ref="delDataTable"
:data="batchDeleteObjs"
@selection-change="secondSelectionChange"
height="156px"
width="100%"
class="dialog-table"
:row-style="rowStyle"
cell-style="padding:4px 0px;font-size: 12px;color: #353636;font-weight: 400;"
header-cell-style="padding:4px 0px;background: #F5F8FA;font-size: 12px;color: #353636;font-weight: 500;"
:header-row-style="tableHeaderRowStyle">
<el-table-column
:resizable="false"
align="center"
type="selection"
width="50">
</el-table-column>
<el-table-column property="id" label="ID" width="112"></el-table-column>
<el-table-column property="tagType" label="Type" width="112"></el-table-column>
<el-table-column property="tagName" label="Name"></el-table-column>
</el-table>
<template #footer>
<span class="dialog-footer">
<el-button @click="showConfirmDialog = false">{{ $t('overall.cancel') }}</el-button>
<el-button type="primary" @click="submit">{{ $t('tip.confirm') }}</el-button>
</span>
</template>
</el-dialog>
</template>
<script>
import cnDataList from '@/components/table/CnDataList'
@@ -57,21 +96,103 @@ import dataListMixin from '@/mixins/data-list'
import KnowledgeBaseTable from '@/components/table/setting/KnowledgeBaseTable'
import { api } from '@/utils/api'
import axios from 'axios'
import KnowledgeFilter from '@/views/setting/KnowledgeFilter'
export default {
name: 'knowledgeBase',
components: {
cnDataList,
KnowledgeBaseTable
KnowledgeBaseTable,
KnowledgeFilter
},
mixins: [dataListMixin],
data () {
return {
url: api.knowledgeBase,
tableId: 'knowledgeBaseTable' // 需要分页的table的id用于记录每页数量
tableId: 'knowledgeBaseTable', // 需要分页的table的id用于记录每页数量
isSelectedStatus: false,
keyWord: '',
showConfirmDialog: false,
delItemList: [],
secondBatchDeleteObjs: []
}
},
watch: {
},
methods: {
onSearch () {
const params = {
q: this.keyWord
}
this.search(params)
},
handleClose () {
this.showConfirmDialog = false
},
showDelDialog () {
this.showConfirmDialog = true
this.$nextTick(() => {
this.batchDeleteObjs.forEach((item) => {
this.$refs.delDataTable.toggleRowSelection(item, true)
})
})
},
secondSelectionChange (objs) {
this.secondBatchDeleteObjs = objs
},
delBatchKnowledge () {
const ids = []
if (this.secondBatchDeleteObjs && this.secondBatchDeleteObjs.length > 0) {
this.secondBatchDeleteObjs.forEach(item => {
ids.push(item.id)
})
}
if (ids.length === 0) {
this.$alert(this.$t('tip.pleaseSelect'), {
confirmButtonText: this.$t('tip.yes'),
type: 'warning'
}).catch(() => {})
} else {
this.tools.loading = true
axios.delete(this.url + '?ids=' + ids).then(response => {
if (response.data.code === 200) {
this.delFlag = true
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.deleteSuccess') })
this.secondBatchDeleteObjs.forEach((item) => {
this.$refs.delDataTable.toggleRowSelection(item, false)
})
this.$refs.knowledgeFilter.reloadFilter()
this.secondBatchDeleteObjs = []
this.batchDeleteObjs = []
this.getTableData()
} else {
this.$message.error(response.data.message)
}
}).finally(() => {
this.tools.loading = false
if (this.isSelectedStatus != undefined) {
this.isSelectedStatus = false
this.disableDelete = true
this.secondBatchDeleteObjs = []
this.batchDeleteObjs = []
this.showConfirmDialog = false
}
})
}
},
tableHeaderRowStyle ({ row, rowIndex }) {
// if (rowIndex === 0) {
// return 'font-weight: 500;font-size: 14px;'
// }
},
rowStyle ({ row, rowIndex }) {
// return 'height:32px !important;'//font-size: 14px;color: #666666;font-weight: 400;
},
submit () {
this.delBatchKnowledge()
this.showConfirmDialog = false
},
edit (u) {
axios.get(`${this.url}/${u.id}`).then(response => {
if (response.data.code === 200) {
@@ -87,6 +208,24 @@ export default {
}
})
},
reload (params, isAll, isClearType) {
this.disableDelete = true
this.isSelectedStatus = false
this.batchDeleteObjs = []
this.secondBatchDeleteObjs = []
this.getTableData(params, isAll, isClearType)
},
clearList () {
this.disableDelete = true
this.isSelectedStatus = false
this.batchDeleteObjs = []
this.secondBatchDeleteObjs = []
this.tableData = 0
this.pageObj.total = 0
},
toSelect () {
this.isSelectedStatus = !this.isSelectedStatus
},
editSelectRecord () {
if (this.batchDeleteObjs.length === 0) {
this.$alert(this.$t('tip.pleaseSelectForEdit'), {
@@ -97,6 +236,15 @@ export default {
this.jumpToEditPage(this.batchDeleteObjs[0].id)
}
},
toDelete (data) {
if (data && data.id) {
this.secondBatchDeleteObjs = []
this.batchDeleteObjs = []
this.secondBatchDeleteObjs.push(data)
this.batchDeleteObjs.push(data)
}
this.showDelDialog()
},
del (row) {
this.$confirm(this.$t('tip.confirmDelete'), {
confirmButtonText: this.$t('tip.yes'),
@@ -141,6 +289,93 @@ export default {
}
})
}
},
mounted () {
},
computed: {
}
}
</script>
<style lang="scss">
.del-model__hint {
display:flex;
flex-direction: column;
padding-bottom:0px !important;
width:480px !important;
height:190px;
.el-message-box__header{
display: flex;
flex-direction: row;
border-bottom:1px solid #eee;
height:42px;
background: #F7F7F7;
box-shadow: 0 1px 0 0 rgba(53,54,54,0.08);
padding-left:20px;
padding-top:14px;
padding-bottom:14px;
.el-message-box__headerbtn {
display: flex !important;
flex-direction: row-reverse;
justify-content: center;
align-items: center;
font-size: 10px;
line-height: 10px;
padding-right: 5px !important;
i {
width:10px;
height:10px;
}
}
.el-message-box__title {
font-size: 14px !important;
color: #353636;
letter-spacing: 0;
font-weight: 400;
}
}
.el-message-box__content {
height:96px;
font-size: 14px;
color: #353636;
letter-spacing: 0;
line-height: 22px;
font-weight: 400;
padding-top:8px;
padding-right:20px;
padding-left:20px;
.el-message-box__message {
padding-left:0px !important;
padding-right:0px !important;
}
}
.el-message-box__btns {
height:52px;
border-top:1px solid #eee;
box-shadow: inset 0 -1px 0 0 rgba(0,0,0,0.07);
padding:11px 0px 12px!important;
.el-button--small {
padding:8px 21px !important;
line-height: 12px;
//font-family: NotoSansHans-Medium !important;
font-size: 12px;
font-weight: 500;
min-height: 28px;
}
.el-button:nth-child(1) {
margin-right:20px;
width:80px;
height:28px;
color: #353636;
}
.el-button:nth-child(2) {
width:80px;
height:28px;
margin-right:20px;
margin-left:0px !important;
background-color:#2d8cf0;
border-color:#2d8cf0;
}
}
}
</style>

View File

@@ -0,0 +1,187 @@
<template>
<div>
<div class="filter-title">
{{ $t('knowledge.filters') }}
</div>
<template v-for="(filter, index) in filterData" :key="index">
<div class="knowledge-filter" v-show="filter.data.length > 0">
<div class="filter__header" @click="filter.collapse = !filter.collapse">
<span class="new-knowledge-filter-header-title">{{filter.title}}</span>
<i class="el-icon-arrow-right new-knowledge-filter-icon" :class="{ 'arrow-rotate': !filter.collapse }"></i>
</div>
<el-collapse-transition>
<div class="filter__body" v-show="!filter.collapse">
<el-checkbox label="all" v-if="index === 0" key="all" @change="handleCheckedAllChange" v-model="checkAll" :indeterminate="isIndeterminateModel">
<div class="filter__checkbox-label">
<div class="filter-label" style="">
<span>All</span>
</div>
<div class="filter-count">{{allCount}}</div>
</div>
</el-checkbox>
<el-checkbox-group v-if="index === 0" v-model="filter.value" @change="handleCheckedItemChange">
<el-checkbox checked="true" v-for="(d, i) in filter.data" :label="d.value" :key="d.value" >
<div class="filter__checkbox-label">
<div class="filter-label" style="">
<span>{{d.label}}</span>
</div>
<div class="filter-count" v-if="d.count || d.count === 0">{{d.count}}</div>
</div>
</el-checkbox>
</el-checkbox-group>
<el-checkbox-group v-else v-model="filter.value" >
<el-checkbox checked="true" v-for="(d, i) in filter.data" :label="d.value" :key="d.value" >
<div class="filter__checkbox-label">
<div class="filter-label" style="">
<span>{{d.label}}</span>
</div>
<div class="filter-count" v-if="d.count || d.count === 0">{{d.count}}</div>
</div>
</el-checkbox>
</el-checkbox-group>
</div>
</el-collapse-transition>
</div>
</template>
</div>
</template>
<script>
import { api } from '@/utils/api'
import { get } from '@/utils/http'
export default {
name: 'KnowledgeFilter',
props: {
},
data () {
return {
url: api.knowledgeBase,
checkAll: true,
isIndeterminateModel: false,
filterData: [
{
title: this.$t('knowledge.type'),
collapse: false,
value: [],
data: []
},
{
title: this.$t('knowledge.status'),
collapse: false,
value: [],
data: []
}
],
allTableData: [],
allCount: 0
}
},
watch: {
},
methods: {
handleCheckedAllChange (item) {
const values = []
this.filterData[0].data.forEach(d => {
values.push(d.value)
})
this.filterData[0].value = item ? values : []
this.isIndeterminateModel = false
if (item) {
this.$emit('reload', null, true)
} else {
this.$emit('clearList')
}
},
handleCheckedItemChange (values) {
const len = values.length
const allTypeLen = this.filterData[0].data.length
let params = {}
if (len === 0) {
this.isIndeterminateModel = false
this.checkAll = false
// this.$emit('reload',null,true)
this.$emit('clearList')
} else if (len > 0 && len < allTypeLen) {
this.checkAll = true
this.isIndeterminateModel = true
const types = []
values.forEach(val => {
types.push(val)
})
params = {
tagType: types.toString()
}
this.$emit('reload', params, true)
} else if (len === allTypeLen) {
this.isIndeterminateModel = false
this.checkAll = true
this.$emit('reload', null, true)
}
},
getAllTableData (params) {
let searchParams = { pageSize: -1 }
if (params) {
searchParams = { ...searchParams, ...params }
}
get(this.url, searchParams).then(response => {
if (response.code === 200) {
this.allTableData = response.data.list
this.initAllData()
this.initStatusData()
} else {
console.error(response)
}
})
},
initAllData () {
this.allCount = this.allTableData.length
let ipCount = 0
let domainCount = 0
let appCount = 0
let builtInCount = 0
this.allTableData.forEach(data => {
if (data.tagType === 'ip') {
ipCount++
} else if (data.tagType === 'domain') {
domainCount++
} else if (data.tagType === 'app') {
appCount++
} else if (data.tagType === 'builtIn') {
builtInCount++
}
})
this.filterData[0].data = [
// { label: 'All', value: 'all', count: 18 },
{ label: 'IP', value: 'ip', count: ipCount },
{ label: 'Domain', value: 'domain', count: domainCount },
{ label: 'Application', value: 'app', count: appCount },
{ label: 'Built-in', value: 'builtIn', count: builtInCount }
]
},
initStatusData () {
let enableCount = 0
let disableCount = 0
this.allTableData.forEach(data => {
if (data.status === 'disable') {
disableCount++
} else {
enableCount++
}
})
this.filterData[1].data = [
{ label: 'enabled', value: 'enabled', count: enableCount },
{ label: 'disable', value: 'ip', count: disableCount }
]
},
reloadFilter () {
this.getAllTableData()
}
},
mounted () {
this.getAllTableData()
},
computed: {
}
}
</script>