diff options
| author | hyx <[email protected]> | 2021-10-15 16:42:15 +0800 |
|---|---|---|
| committer | hyx <[email protected]> | 2021-10-15 16:42:15 +0800 |
| commit | 7c45b758efded216582dbc976226cb4e66ee5b9c (patch) | |
| tree | 9f64b6ef3f6d839f67caf67df03ce9eaa176297c | |
| parent | 3c492fdad9f787bf27443b1cb2a226c49ddae472 (diff) | |
CN-154 chart列表页面开发
CN-155 chart编辑页面开发
| -rw-r--r-- | src/components/rightBox/settings/ChartBox.vue | 382 | ||||
| -rw-r--r-- | src/components/table/settings/ChartTable.vue | 177 | ||||
| -rw-r--r-- | src/mixins/dataList.js | 6 | ||||
| -rw-r--r-- | src/router/index.js | 4 | ||||
| -rw-r--r-- | src/utils/api.js | 1 | ||||
| -rw-r--r-- | src/utils/constants.js | 3 | ||||
| -rw-r--r-- | src/views/settings/Chart.vue | 83 |
7 files changed, 654 insertions, 2 deletions
diff --git a/src/components/rightBox/settings/ChartBox.vue b/src/components/rightBox/settings/ChartBox.vue new file mode 100644 index 00000000..044adf1f --- /dev/null +++ b/src/components/rightBox/settings/ChartBox.vue @@ -0,0 +1,382 @@ +<template> + <div v-click-outside="{object: editObject, func: esc}" class="right-box right-box-user"> + <div class="right-box__header"> + <div class="header__title">{{editObject.id ? $t('config.chart.edit') : $t('config.chart.add')}}</div> + <div class="header__operation"> + <span v-cancel="{object: editObject, func: esc}"><i class="cn-icon cn-icon-close"></i></span> + </div> + </div> + <div class="right-box__container"> + <div class="container__form"> + <el-form ref="chartForm" :model="editObject" :rules="editObject.id ? rules2 : rules" label-position="top" label-width="120px"> + <!--name--> + <el-form-item :label="$t('overall.name')" prop="name"> + <el-input id="chart-input-name" v-model="editObject.name" :disabled="editObject.name==='admin' && editObject.id === 1" + maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input> + </el-form-item> + <!--i18n--> + <el-form-item :label="$t('config.chart.i18n')" prop="i18n"> + <el-input id="chart-input-i18n" v-model="editObject.i18n" + maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input> + </el-form-item> + <!--type--> + <el-form-item :label="$t('config.chart.type')" prop="type"> + <el-select id="chart-type" + v-model="editObject.type" + class="right-box__select" + clearable + collapse-tags + placeholder="" + popper-class="right-box-select-dropdown prevent-clickoutside" + size="small" + @change="()=>{ this.$forceUpdate() }"> + + <el-option + v-for="item in options" + :key="item.value" + :label="item.label" + :value="item.value"> + <span style="float: left">{{ item.label }}</span><span style="float: right;color: #909399;font-size: 13px;">{{ item.remark }}</span> + </el-option> + + </el-select> + </el-form-item> + <!--panel--> + <el-form-item :label="$t('config.chart.panel')" prop="panelId"> + <el-select id="chart-input-panelId" + v-model="editObject.panelId" + class="right-box__select" + clearable + collapse-tags + placeholder="" + :disabled="editObject.id?true:false" + popper-class="right-box-select-dropdown prevent-clickoutside" + size="small" + @change="getChartData"> + + <el-option :key="panelTypeAndRouteMapping.trafficSummary" :label="$t('trafficSummary.trafficSummary')" :value="panelTypeAndRouteMapping.trafficSummary"></el-option> + <el-option :key="panelTypeAndRouteMapping.networkAppPerformance" :label="$t('networkAppPerformance.networkAppPerformance')" :value="panelTypeAndRouteMapping.networkAppPerformance"></el-option> + <el-option :key="panelTypeAndRouteMapping.dnsServiceInsights" :label="$t('dnsServiceInsights.dnsServiceInsights')" :value="panelTypeAndRouteMapping.dnsServiceInsights"></el-option> + <el-option :key="panelTypeAndRouteMapping.ipEntityDetail" :label="$t('entities.ipEntityDetail')" :value="panelTypeAndRouteMapping.ipEntityDetail"></el-option> + <el-option :key="panelTypeAndRouteMapping.domainEntityDetail" :label="$t('entities.domainEntityDetail')" :value="panelTypeAndRouteMapping.domainEntityDetail"></el-option> + <el-option :key="panelTypeAndRouteMapping.appEntityDetail" :label="$t('entities.appEntityDetail')" :value="panelTypeAndRouteMapping.appEntityDetail"></el-option> + + </el-select> + </el-form-item> + <!--pid--> + <el-form-item :label="$t('config.chart.pid')" prop="pid"> + <el-select id="chart-pid" + v-model="editObject.pid" + class="right-box__select" + clearable + collapse-tags + placeholder="" + :disabled="editObject.id?true:false" + popper-class="right-box-select-dropdown prevent-clickoutside" + size="small" + @change="()=>{ this.$forceUpdate() }"> + + <template v-for="chart in chartData" :key="chart.id"> + <el-option :label="chart.name" :value="chart.id"></el-option> + </template> + </el-select> + </el-form-item> + <!--x--> + <el-form-item :label="$t('config.chart.x')" prop="x"> + <el-input id="chart-input-x" v-model="editObject.x" + maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input> + </el-form-item> + <!--y--> + <el-form-item :label="$t('config.chart.y')" prop="y"> + <el-input id="chart-input-y" v-model="editObject.y" + maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input> + </el-form-item> + <!--w--> + <el-form-item :label="$t('config.chart.w')" prop="w"> + <el-input id="chart-input-x" v-model="editObject.w" + maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input> + </el-form-item> + <!--h--> + <el-form-item :label="$t('config.chart.h')" prop="h"> + <el-input id="chart-input-y" v-model="editObject.h" + maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input> + </el-form-item> + + <!--params--> + <el-form-item :label="$t('config.chart.params')"> + <el-input maxlength="1024" show-word-limit :rows="2" size='mini' type="textarea" v-model="editObject.params" id="chart-box-params"/> + </el-form-item> + <!--remark--> + <el-form-item :label="$t('config.chart.remark')"> + <el-input maxlength="1024" show-word-limit :rows="2" size='mini' type="textarea" v-model="editObject.remark" id="chart-box-remark"/> + </el-form-item> + + </el-form> + </div> + </div> + <div class="right-box__footer"> + <button id="chart-edit-cancel" v-cancel="{object: editObject, func: esc}" class="footer__btn footer__btn--light"> + <span>{{$t('overall.cancel')}}</span> + </button> + <button id="chart-edit-save" :class="{'footer__btn--disabled': blockOperation.save}" :disabled="blockOperation.save" class="footer__btn" @click="save"> + <span>{{$t('overall.save')}}</span> + </button> + </div> + </div> +</template> + +<script> +import rightBoxMixin from '@/mixins/rightBox' +import { get, post, put } from '@/utils/http' +import { panelTypeAndRouteMapping } from '@/utils/constants' +import { api } from '@/utils/api' + +export default { + name: 'ChartBox', + mixins: [rightBoxMixin], + data () { + return { + url: api.chart, + loginName: localStorage.getItem('cn-username'), + panelTypeAndRouteMapping: panelTypeAndRouteMapping, + rules: { // 表单校验规则 + name: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ], + type: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ], + panel_id: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ], + x: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ], + y: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ], + w: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ], + h: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ] + }, + rules2: { // 表单校验规则 + name: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ], + type: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ], + panel_id: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ], + x: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ], + y: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ], + w: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ], + h: [ + { required: true, message: this.$t('validate.required'), trigger: 'blur' } + ] + }, + chartData: [], + options: [ + { + value: 1, + label: 'map-1', + remark: '流量流向地图-连线' + }, + { + value: 2, + label: 'map-2', + remark: '地图-色块' + }, { + value: 3, + label: 'map-3', + remark: '地图-点' + }, + { + value: 4, + label: 'map-4', + remark: '地图-点' + }, { + value: 11, + label: 'line-1', + remark: '折线图-常规' + }, + { + value: 61, + label: 'table-1', + remark: '表格' + }, { + value: 62, + label: 'table-2', + remark: 'DNS记录' + }, + { + value: 31, + label: 'pie-1', + remark: '饼图-带联动表格' + }, { + value: 51, + label: 'singleValue-1', + remark: '单值图' + }, + { + value: 91, + label: 'tab-container', + remark: 'tab标签(容器)' + }, { + value: 92, + label: 'tab-item', + remark: 'tab标签(标签页)' + }, + { + value: 93, + label: 'title', + remark: '标题' + }, { + value: 94, + label: 'group', + remark: '组' + }, + { + value: 12, + label: 'line-2', + remark: '折线图-带统计' + }, { + value: 52, + label: 'singleValue-2', + remark: '详情单值图' + }, + { + value: 53, + label: 'singleValue-3', + remark: '单值图' + }, { + value: 13, + label: 'line-3', + remark: '折线图-堆叠面积' + }, + { + value: 21, + label: 'bar-1', + remark: '柱状图' + }, { + value: 22, + label: 'bar-2', + remark: '开放端口' + }, + { + value: 32, + label: 'pie-2', + remark: '饼图-常规' + }, { + value: 33, + label: 'pie-3', + remark: '托管域名' + }, + { + value: 34, + label: 'pie-4', + remark: '相关域名' + }, { + value: 42, + label: 'relation-2', + remark: '关系图谱' + }, + { + value: 43, + label: 'relation-3', + remark: '访问链路图' + }, + { + value: 82, + label: 'base-2', + remark: 'APP基本信息' + }, { + value: 83, + label: 'list-1', + remark: 'Whois' + }, + { + value: 84, + label: 'list-2', + remark: 'DNS记录' + } + ] + } + }, + setup () { + }, + mounted () { + if (this.editObject.id) { + this.getChartData(this.editObject.panelId) + } + }, + watch: { + 'editObject.panelId': function (newValue, oldValue) { + this.editObject.pid = '' + } + }, + methods: { + isCurrentUser (username) { + return localStorage.getItem('cn-username') === username + }, + /* 密码失去焦点 检验确认密码 */ + pinBlur () { + if (this.editObject.pin && this.editObject.pinChange) { + this.$refs.chartForm.validateField('pinChange') + } + }, + save () { + if (this.blockOperation.save) { return } + this.blockOperation.save = true + + this.$refs.chartForm.validate((valid) => { + if (valid) { + if (this.editObject.id) { + put(this.url, this.editObject).then(res => { + this.blockOperation.save = false + if (res.code === 200) { + this.$message({ duration: 2000, type: 'success', message: this.$t('tip.saveSuccess') }) + this.esc(true) + } else { + this.$message.error(res.msg) + } + }) + } else { + post(this.url, this.editObject).then(res => { + this.blockOperation.save = false + if (res.code === 200) { + this.$message({ duration: 2000, type: 'success', message: this.$t('tip.saveSuccess') }) + this.esc(true) + } else { + this.$message.error(res.msg) + } + }) + } + } else { + this.blockOperation.save = false + return false + } + }) + }, + async getChartData (value) { + await get('/visual/chart?panelId=' + value).then(response => { + if (response.code === 200) { + this.chartData = response.data.list + } + }) + + // this.$set(this.editObject, 'pid', '') + } + } +} +</script> diff --git a/src/components/table/settings/ChartTable.vue b/src/components/table/settings/ChartTable.vue new file mode 100644 index 00000000..18794378 --- /dev/null +++ b/src/components/table/settings/ChartTable.vue @@ -0,0 +1,177 @@ +<template> + <el-table + id="chartTable" + ref="dataTable" + :data="tableData" + :height="height" + border + @header-dragend="dragend" + @sort-change="tableDataSort" + @selection-change="selectionChange" + > + <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}`" + class="data-column" + > + <template #header> + <span class="data-column__span">{{item.label}}</span> + <div class="col-resize-area"></div> + </template> + <template #default="scope" :column="item"> + <template v-if="item.prop === 'name'"> + <template v-if="scope.row.i18n"> + <span>{{$t(scope.row.i18n)}}</span> + </template> + <template v-else-if="scope.row.name"> + <span>{{scope.row.name}}</span> + </template> + <template v-else> + <span>-</span> + </template> + </template> + <template v-else-if="item.prop === 'buildIn'"> + <template v-if="scope.row[item.prop]==1"> + {{$t('config.chart.buildIn.yes')}} + </template> + <template v-else-if="scope.row[item.prop]==0"> + {{$t('config.chart.buildIn.no')}} + </template> + <template v-else> + {{scope.row[item.prop]}} + </template> + </template> + <template v-else-if="item.prop === 'panelId'"> + <template v-if="scope.row[item.prop]==panelTypeAndRouteMapping.trafficSummary"> + {{$t('trafficSummary.trafficSummary')}} + </template> + <template v-else-if="scope.row[item.prop]==panelTypeAndRouteMapping.networkAppPerformance"> + {{$t('networkAppPerformance.networkAppPerformance')}} + </template> + <template v-else-if="scope.row[item.prop]==panelTypeAndRouteMapping.dnsServiceInsights"> + {{$t('dnsServiceInsights.dnsServiceInsights')}} + </template> + <template v-else-if="scope.row[item.prop]==panelTypeAndRouteMapping.ipEntityDetail"> + {{$t('entities.ipEntityDetail')}} + </template> + <template v-else-if="scope.row[item.prop]==panelTypeAndRouteMapping.domainEntityDetail"> + {{$t('entities.domainEntityDetail')}} + </template> + <template v-else-if="scope.row[item.prop]==panelTypeAndRouteMapping.appEntityDetail"> + {{$t('entities.appEntityDetail')}} + </template> + <template v-else> + {{scope.row[item.prop]}} + </template> + </template> + <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"> + <button class="table-operation-item" @click="tableOperation(['edit', scope.row])"><i class="cn-icon cn-icon-edit"></i></button> + <el-dropdown size="medium" trigger="hover" @command="tableOperation"> + <div class="table-operation-item table-operation-item--more"> + <i class="cn-icon cn-icon-more-arrow-down"></i> + </div> + <template #dropdown> + <el-dropdown-menu > + <el-dropdown-item :command="['delete', scope.row]" :disabled="scope.row['buildIn'] === 1"><i class="cn-icon cn-icon-delete"></i><span class="operation-dropdown-text">{{$t('overall.delete')}}</span></el-dropdown-item> + </el-dropdown-menu> + </template> + </el-dropdown> + </div> + </template> + </el-table-column> + </el-table> +</template> + +<script> +import table from '@/mixins/table' +import { panelTypeAndRouteMapping } from '@/utils/constants' +import { api } from '@/utils/api' + +export default { + name: 'chartTable', + mixins: [table], + data () { + return { + panelTypeAndRouteMapping: panelTypeAndRouteMapping, + tableTitle: [ // 原table列 + { + label: 'ID', + prop: 'id', + show: true, + width: 80, + sortable: 'custom' + }, { + label: this.$t('config.chart.name'), + prop: 'name', + show: true + }, { + label: this.$t('config.chart.params'), + prop: 'params', + show: true + }, { + label: this.$t('config.chart.panel'), + prop: 'panelId', + show: true + }, { + label: this.$t('config.chart.i18n'), + prop: 'i18n', + show: true + }, { + label: this.$t('config.chart.type'), + prop: 'type', + show: true + }, { + label: this.$t('config.chart.x'), + prop: 'x', + show: true + }, { + label: this.$t('config.chart.y'), + prop: 'y', + show: true + }, { + label: this.$t('config.chart.w'), + prop: 'w', + show: true + }, { + label: this.$t('config.chart.h'), + prop: 'h', + show: true + }, { + label: this.$t('config.chart.buildIn'), + prop: 'buildIn', + show: true + }, { + label: this.$t('config.chart.remark'), + prop: 'remark', + show: true + } + ] + } + } +} +</script> diff --git a/src/mixins/dataList.js b/src/mixins/dataList.js index ed261072..b9581603 100644 --- a/src/mixins/dataList.js +++ b/src/mixins/dataList.js @@ -69,7 +69,11 @@ export default { this.searchLabel = { ...this.searchLabel, ...this.pageObj } this.tools.loading = true delete this.searchLabel.total - get(this.url, this.searchLabel).then(response => { + let listUrl = this.url + if (this.listUrl) { + listUrl = this.listUrl + } + get(listUrl, this.searchLabel).then(response => { this.tools.loading = false if (response.code === 200) { for (let i = 0; i < response.data.list.length; i++) { diff --git a/src/router/index.js b/src/router/index.js index eb35f671..14ac931d 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -37,6 +37,10 @@ const routes = [ { path: '/galaxyProxy', component: () => import('@/views/settings/GalaxyProxy') + }, + { + path: '/chart', + component: () => import('@/views/settings/Chart') } ] } diff --git a/src/utils/api.js b/src/utils/api.js index 5154d77a..93c07e18 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -16,6 +16,7 @@ export const api = { role: '/sys/role', galaxyProxy: '/galaxy/setting', operationLog: '/sys/log', + chartList: '/visual/chart/list', // 业务 panel: '/visual/panel', chart: '/visual/chart', diff --git a/src/utils/constants.js b/src/utils/constants.js index 3e63a9f4..f365fe8f 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -30,7 +30,8 @@ export const fromRoute = { networkAppPerformance: 'networkAppPerformance', dnsServiceInsights: 'dnsServiceInsights', user: 'user', - galaxyProxy: 'galaxyProxy' + galaxyProxy: 'galaxyProxy', + chart: 'chart' } /* panel类别和名称之间的映射 */ diff --git a/src/views/settings/Chart.vue b/src/views/settings/Chart.vue new file mode 100644 index 00000000..72e2edf3 --- /dev/null +++ b/src/views/settings/Chart.vue @@ -0,0 +1,83 @@ +<template> + <div> + <cn-data-list + ref="dataList" + :tableId="tableId" + v-model:custom-table-title="tools.customTableTitle" + :api="url" + :from="fromRoute.chart" + :layout="['columnCustomize','elementSet','searchInput']" + @search="search" + > + <template #top-tool-right> + <button + id="account-add" + class="top-tool-btn margin-r-10" + type="button" + @click="add" + > + <i class="cn-icon-add cn-icon"/> + </button> + </template> + <template #default> + <chart-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" + /> + </template> + <template #pagination> + <pagination ref="pagination" :page-obj="pageObj" :table-id="tableId" @pageNo='pageNo' @pageSize='pageSize'></pagination> + </template> + </cn-data-list> + <el-drawer + v-model="rightBox.show" + direction="rtl" + :with-header="false" + :size="700" + destroy-on-close> + <chart-box + :object="object" + @close="closeRightBox" + /> + </el-drawer> + </div> +</template> +<script> +import cnDataList from '@/components/table/CnDataList' +import dataListMixin from '@/mixins/dataList' +import chartTable from '@/components/table/settings/ChartTable' +import chartBox from '@/components/rightBox/settings/ChartBox' +import { api } from '@/utils/api' + +export default { + name: 'Chart', + mixins: [dataListMixin], + components: { + cnDataList, + chartTable, + chartBox + }, + data () { + return { + url: api.chart, + listUrl: api.chartList, + blankObject: { // 空白对象 + id: '', + name: '', + params: '', + i18n: '' + }, + tableId: 'chartTable' + } + } +} +</script> |
