CN-480 feat: 报告下载前端界面开发 部分功能

This commit is contained in:
@changcode
2022-04-12 18:00:01 +08:00
parent 00326be6ea
commit 52db120e36
15 changed files with 438 additions and 9 deletions

View File

@@ -46,7 +46,7 @@
border: 1px solid #E6EAED; border: 1px solid #E6EAED;
} }
.top-tool-search.margin-r-20 { .top-tool-search {
.top-tool-btn { .top-tool-btn {
border-left: none; border-left: none;
} }
@@ -178,6 +178,9 @@
.table-operation-items { .table-operation-items {
display: flex; display: flex;
justify-content: center; justify-content: center;
.table-operation-item--down {
margin-right: 16px;
}
.table-operation-item { .table-operation-item {
display: flex; display: flex;
height: 22px; height: 22px;

View File

@@ -41,6 +41,7 @@
@import './views/charts/chartAlarmInfo'; @import './views/charts/chartAlarmInfo';
@import './views/chartHeader'; @import './views/chartHeader';
@import './views/charts/chartMap'; @import './views/charts/chartMap';
@import './views/report/builtinReport';
//@import '../chart'; //@import '../chart';

View File

@@ -0,0 +1,92 @@
.cn-builtin {
background: #fff;
margin: 10px;
height: calc(100% - 20px) !important;
display: flex;
flex-direction: row;
.cn-builtin-left {
width: 288px;
height: 100%;
border-right: 1px solid #E7EAED;
.cn-builtin-left-title {
padding: 28px 0 26px 13px;
font-size: 16px;
color: #333333;
letter-spacing: 0;
}
.cn-builtin-left-menu {
width: 250px;
height: 46px;
margin: auto;
font-size: 14px;
color: #333333;
letter-spacing: 0;
line-height: 46px;
padding-left: 15px;
cursor: pointer;
}
.cn-builtin-left-menu.cn-active {
background: #F4FAFF;
border-radius: 2px;
color: #0091FF;
}
}
.cn-builtin-right {
flex: 1;
.el-table__header th:first-of-type .el-checkbox:last-of-type {
border-left: none;
display: none;
}
.table-operation-all {
width: 300px;
position: absolute;
bottom: 17px;
z-index: 2;
left: 20px;
height: 22px;
display: flex;
.el-checkbox {
width: 14px;
height: 14px;
padding: 0;
.el-checkbox__input,.el-checkbox__inner {
width: 100%;
height: 100%;
min-width: unset;
}
}
.table-operation-all-span {
span:nth-of-type(1) {
margin: 0 10px;
font-size: 14px;
color: #666666;
letter-spacing: 0;
font-weight: 400;
}
span:nth-of-type(2) {
font-size: 12px;
color: #FFFFFF;
font-weight: 500;
height: 24px;
background: #D7D7D7;
border-radius: 2px;
padding: 3px 8px;
line-height: 16px;
cursor: pointer;
margin-top: 2px;
}
span:nth-of-type(2).table-operation-all-checkbox {
background: #0091ff;
}
}
}
.table-operation-items {
.table-operation-item--down {
cursor: pointer;
}
.table-operation-item--preview {
cursor: pointer;
}
}
}
}

View File

@@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "cn-icon"; /* Project id 2614877 */ font-family: "cn-icon"; /* Project id 2614877 */
src: url('iconfont.woff2?t=1648624431165') format('woff2'), src: url('iconfont.woff2?t=1649728125883') format('woff2'),
url('iconfont.woff?t=1648624431165') format('woff'), url('iconfont.woff?t=1649728125883') format('woff'),
url('iconfont.ttf?t=1648624431165') format('truetype'); url('iconfont.ttf?t=1649728125883') format('truetype');
} }
.cn-icon { .cn-icon {
@@ -13,6 +13,22 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.cn-icon-report:before {
content: "\e76f";
}
.cn-icon-shezhi:before {
content: "\e76c";
}
.cn-icon-preview:before {
content: "\e76d";
}
.cn-icon-download2:before {
content: "\e76e";
}
.cn-icon-requests:before { .cn-icon-requests:before {
content: "\e76a"; content: "\e76a";
} }

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View File

@@ -156,6 +156,15 @@ export default {
deep: true, deep: true,
handler (n, o) { handler (n, o) {
} }
},
tableData: {
immediate: true,
deep: true,
handler (n, o) {
if (n) {
this.checkbox = n
}
}
} }
} }
} }

View File

@@ -11,7 +11,7 @@
<div class="top-tool-right"> <div class="top-tool-right">
<!-- <el-input v-model="keyWord" value="keyWord"></el-input> <!-- <el-input v-model="keyWord" value="keyWord"></el-input>
<el-button @click="onsearch" icon="el-icon-search" type="info" size="mini" style="margin-right: 10px"></el-button>--> <el-button @click="onsearch" icon="el-icon-search" type="info" size="mini" style="margin-right: 10px"></el-button>-->
<div v-if="showLayout.indexOf('search') > -1" class="top-tool-search margin-r-20"> <div v-if="showLayout.indexOf('search') > -1" class="top-tool-search" :class="{'margin-r-20': from !== fromRoute.builtinReport}">
<div style="display: flex"> <div style="display: flex">
<el-input <el-input
v-model="keyWord" size="small" @keyup.enter="onsearch"></el-input> v-model="keyWord" size="small" @keyup.enter="onsearch"></el-input>
@@ -69,6 +69,9 @@ export default {
tableId: { tableId: {
type: String type: String
}, },
builtinId: {
type: Number
},
tableTitle: { tableTitle: {
type: Array type: Array
}, },
@@ -95,7 +98,11 @@ export default {
this.$emit('update:customTableTitle', custom) this.$emit('update:customTableTitle', custom)
}, },
onsearch () { onsearch () {
this.$emit('search', this.keyWord) const params = {
q: this.keyWord,
id: this.builtinId
}
this.$emit('search', params)
} }
}, },
watch: { watch: {

View File

@@ -0,0 +1,155 @@
<template>
<el-table
id="userTable"
ref="dataTable"
:data="tableData"
:height="height"
border
@header-dragend="dragend"
@sort-change="tableDataSort"
@selection-change="selectionChange"
@select-all="selectionChangeAll"
@select="select"
>
<el-table-column
:resizable="false"
align="center"
type="selection"
width="55">
</el-table-column>
<el-table-column
v-for="(item, index) in customTableTitles"
:key="`col-${index}`"
:fixed="item.fixed"
:label="item.label"
:min-width="`${item.minWidth}`"
:prop="item.prop"
:resizable="true"
:sort-orders="['ascending', 'descending']"
:sortable="item.sortable"
:width="`${item.width}`"
>
<template #header>
<span class="data-column__span">{{item.label}}</span>
<div class="col-resize-area"></div>
</template>
<template #default="scope" :column="item">
<span v-if="item.prop === 'dataRange'">
<template v-if="scope.row.startTime && scope.row.endTime">
{{scope.row.startTime}}-{{scope.row.endTime}}
</template>
</span>
<span v-else>{{scope.row[item.prop]}}</span>
</template>
</el-table-column>
<el-table-column
:resizable="false"
:width="operationWidth"
fixed="right">
<template #header>
<div class="table-operation-title">{{$t('overall.option')}}</div>
</template>
<template #default="scope">
<div class="table-operation-items">
<div class="table-operation-item--down" @click="tableOperation(['download', scope.row])"><i class="cn-icon cn-icon-download2"></i></div>
<div class="table-operation-item--preview" @click="tableOperation(['preview', scope.row])"><i class="cn-icon cn-icon-preview"></i></div>
</div>
</template>
</el-table-column>
</el-table>
<div class="pagination-all">
<el-checkbox v-model="checkbox" @change="builtinReportCheckbox"></el-checkbox>
<div class="pagination-all-span">
<span>{{ $t('overall.all') }}</span>
<span :disabled="downloadAgentFlag" @click="batchDownload">{{$t('report.batchDow')}}</span>
</div>
</div>
</template>
<script>
import table from '@/mixins/table'
import { get } from '@/utils/http'
export default {
name: 'builtinReportTable',
mixins: [table],
props: {
builtinReportLeftMenu: Number
},
data () {
return {
tableTitle: [ // 原始table列
{
label: this.$t('config.user.name'),
prop: 'name',
show: true,
sortable: 'custom'
}, {
label: this.$t('config.chart.remark'),
prop: 'remark',
show: true
}, {
label: this.$t('overall.type'),
prop: 'type',
show: true,
sortable: 'custom'
}, {
label: this.$t('report.dataRange'),
prop: 'dataRange',
show: true
}
],
checkbox: false,
downloadAgentFlag: false,
checkboxIds: '',
builtinId: ''
}
},
methods: {
select (objs) {
this.checkboxIds = objs.map(item => { return item.id }).join(',')
if (objs.length > 0) {
this.checkbox = true
} else {
this.checkbox = false
}
},
builtinReportCheckbox (objs) {
if (objs) {
this.selectionChangeAll(this.tableData)
}
},
selectionChangeAll (objs) {
console.log(objs)
},
batchDownload: function () {
this.downloadAgentFlag = true
get('/report/export', { id: this.checkboxIds }).then(data => {
this.downloadAgentFlag = false
let fileName = 'confagent'
const disposition = data.headers['content-disposition']
if (disposition) {
fileName = disposition.split(';')[1].split('filename=')[1]
}
// 由于ie不支持download属性故需要做兼容判断
if (navigator.appVersion.toString().indexOf('.NET') > 0) {
// ie独有的msSaveBlob属性data.data为Blob文件流
window.navigator.msSaveBlob(data.data, fileName)
} else {
// 以下流程即为文章开始的下载流程
const url = window.URL.createObjectURL(data.data)
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.download = fileName
document.body.appendChild(link)
link.click()
window.URL.revokeObjectURL(link.href)
}
}).catch(() => {
this.downloadAgentFlag = false
})
}
}
}
</script>

View File

@@ -55,6 +55,14 @@ export default {
this.copy(row) this.copy(row)
break break
} }
case 'download': {
this.download(row)
break
}
case 'preview': {
this.preview(row)
break
}
default: default:
break break
} }
@@ -137,6 +145,40 @@ export default {
this.object = { ...u, name: 'Copy from ' + u.name, id: '' } this.object = { ...u, name: 'Copy from ' + u.name, id: '' }
this.rightBox.show = true this.rightBox.show = true
}, },
download (u) {
get('/report/job/downloadPdf', { id: u.id }).then(data => {
this.downloadAgentFlag = false
let fileName = 'confBuiltin'
const disposition = data.headers['content-disposition']
if (disposition) {
fileName = disposition.split(';')[1].split('filename=')[1]
}
// 由于ie不支持download属性故需要做兼容判断
if (navigator.appVersion.toString().indexOf('.NET') > 0) {
// ie独有的msSaveBlob属性data.data为Blob文件流
window.navigator.msSaveBlob(data.data, fileName)
} else {
// 以下流程即为文章开始的下载流程
const url = window.URL.createObjectURL(data.data)
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.download = fileName
document.body.appendChild(link)
link.click()
window.URL.revokeObjectURL(link.href)
}
}).catch(() => {
this.downloadAgentFlag = false
})
},
preview (u) {
get('/report/job/view', { id: u.id }).then(res => {
if (res.code === 200) {
console.log(res)
}
})
},
esc () { esc () {
this.rightBox.show = false this.rightBox.show = false
}, },
@@ -151,7 +193,7 @@ export default {
}, },
search (params) { search (params) {
this.pageObj.pageNo = 1 this.pageObj.pageNo = 1
this.getTableData({ q: params }) this.getTableData(params)
} }
}, },
watch: { watch: {

View File

@@ -30,6 +30,10 @@ const routes = [
path: '/i18n', path: '/i18n',
component: () => import('@/views/settings/I18n') component: () => import('@/views/settings/I18n')
}, },
{
path: '/report/builtIn',
component: () => import('@/views/report/builtinReport')
},
{ {
path: '/operationLog', path: '/operationLog',
component: () => import('@/views/settings/OperationLog') component: () => import('@/views/settings/OperationLog')

View File

@@ -18,6 +18,8 @@ export const api = {
galaxyProxy: '/galaxy/setting', galaxyProxy: '/galaxy/setting',
operationLog: '/sys/log', operationLog: '/sys/log',
chartList: '/visual/chart/list', chartList: '/visual/chart/list',
// 报告相关
builtinReport: '/report/job',
// 业务 // 业务
panel: '/visual/panel', panel: '/visual/panel',
chart: '/visual/chart', chart: '/visual/chart',

View File

@@ -30,7 +30,8 @@ export const fromRoute = {
user: 'user', user: 'user',
galaxyProxy: 'galaxyProxy', galaxyProxy: 'galaxyProxy',
chart: 'chart', chart: 'chart',
cryptocurrency: 'cryptocurrency' cryptocurrency: 'cryptocurrency',
builtinReport: 'builtinReport'
} }
/* panel类别和名称之间的映射 */ /* panel类别和名称之间的映射 */

View File

@@ -0,0 +1,97 @@
<template>
<div class="cn-builtin">
<div class="cn-builtin-left">
<div class="cn-builtin-left-title">
{{$t('report.category')}}
</div>
<div class="cn-builtin-left-menu" :class="{'cn-active': builtinId === ''}" @click="builtinTabs('')">
{{$t('dns.all')}}
</div>
<div class="cn-builtin-left-menu" :class="{'cn-active': builtinId === item.id}" v-for="item in builtinReportLeftMenu" :key="item.id" @click="builtinTabs(item.id)">
{{item.name}}
</div>
</div>
<div class="cn-builtin-right">
<cn-data-list
ref="dataList"
:tableId="tableId"
v-model:custom-table-title="tools.customTableTitle"
:api="url"
:builtinId="builtinId"
:from="fromRoute.builtinReport"
:layout="['search']"
@search="search"
>
<template #default>
<builtin-report-table
ref="dataTable"
v-loading="tools.loading"
:api="url"
:custom-table-title="tools.customTableTitle"
:height="mainTableHeight"
:table-data="tableData"
@download="download"
@preview="preview"
@orderBy="tableDataSort"
@reload="getTableData"
@selectionChange="selectionChange"
/>
</template>
<template #pagination>
<pagination ref="pagination" :page-obj="pageObj" :tableData="tableData" :table-id="tableId" @pageNo='pageNo' @pageSize='pageSize'></pagination>
</template>
</cn-data-list>
</div>
</div>
</template>
<script>
import { get } from '@/utils/http'
import builtinReportTable from '@/components/table/report/builtinReportTable'
import cnDataList from '@/components/table/CnDataList'
import dataListMixin from '@/mixins/data-list'
import { api } from '@/utils/api'
export default {
name: 'Report',
data () {
return {
builtinReportLeftMenu: [],
builtinColor: false,
builtinId: '',
url: api.builtinReport,
blankObject: { // 空白对象
id: '',
name: '',
ctime: '',
remark: '',
uniq: '',
startTime: '',
endTime: ''
},
tableId: 'builtinReportTable'
}
},
mixins: [dataListMixin],
components: {
cnDataList,
builtinReportTable
},
methods: {
builtinReportData () {
get('/report/temp').then(res => {
if (res.code === 200) {
this.builtinReportLeftMenu = res.data.list
}
})
},
builtinTabs (id) {
this.builtinId = id
this.getTableData({ id: this.builtinId })
}
},
mounted () {
this.builtinReportData()
}
}
</script>