summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/assets/css/components/components/charts/panel.scss974
-rw-r--r--src/components/charts/ChartMap.vue39
-rw-r--r--src/components/charts/ChartSingleValue.vue95
-rw-r--r--src/components/charts/ChartTable.vue72
-rw-r--r--src/components/charts/ChartTableActiveIp.vue112
-rw-r--r--src/components/charts/ChartTablePagination.vue55
-rw-r--r--src/components/charts/ChartTitle.vue9
-rw-r--r--src/components/charts/EchartsFrame.vue44
-rw-r--r--src/components/charts/PieTable.vue258
-rw-r--r--src/components/charts/chart-options.js828
-rw-r--r--src/components/entities/EntityList.vue4
-rw-r--r--src/router/index.js4
-rw-r--r--src/views/charts/Chart.vue2624
-rw-r--r--src/views/charts/Chart2.vue358
-rw-r--r--src/views/charts/ChartError.vue (renamed from src/components/charts/ChartError.vue)0
-rw-r--r--src/views/charts/ChartHeader.vue2
-rw-r--r--src/views/charts/PanelChart.vue4
-rw-r--r--src/views/charts/charts/ChartCategoryBar.vue2
-rw-r--r--src/views/charts/charts/ChartEchart.vue2
-rw-r--r--src/views/charts/charts/ChartEchartWithStatistics.vue2
-rw-r--r--src/views/charts/charts/ChartIpOpenPortBar.vue2
-rw-r--r--src/views/charts/charts/ChartSingleValue.vue2
-rw-r--r--src/views/charts/charts/ChartTimeBar.vue2
-rw-r--r--src/views/charts/charts/StatisticsLegend.vue (renamed from src/components/charts/StatisticsLegend.vue)2
-rw-r--r--src/views/charts/charts/chart-table-title.js (renamed from src/components/charts/chart-table-title.js)0
-rw-r--r--src/views/detections/Index.vue13
-rw-r--r--src/views/entities/EntityExplorer.vue487
-rw-r--r--src/views/entityExplorer/entityList/detailOverview/App.vue8
-rw-r--r--src/views/entityExplorer/entityList/detailOverview/Domain.vue10
-rw-r--r--src/views/entityExplorer/entityList/detailOverview/Ip.vue8
-rw-r--r--src/views/entityExplorer/entityList/detailOverview/entityDetailMixin.js2
-rw-r--r--src/views/entityExplorer/entityList/entityListMixin.js4
32 files changed, 342 insertions, 5686 deletions
diff --git a/src/assets/css/components/components/charts/panel.scss b/src/assets/css/components/components/charts/panel.scss
deleted file mode 100644
index 77c31ec6..00000000
--- a/src/assets/css/components/components/charts/panel.scss
+++ /dev/null
@@ -1,974 +0,0 @@
-.entity-detail-tool {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin: 10px 20px 10px 0;
- padding: 0 20px;
- height: 60px;
- background-color: #FFFFFF;
- box-shadow: 0 1px 2px 0 rgba(0,0,0,0.06);
- border-radius: 2px;
-
- .cn-icon-arrow-left-circle {
- color: $--color-primary;
- font-size: 20px;
- }
-}
-
-.chart-error-popper{
- word-wrap:break-word;
- word-break:break-word;
- border: 1px solid #e02f44;
- min-width: 180px !important;
- max-width: 280px !important;
-}
-
-.chart-header-position{
- position: relative;
-}
-
-.chart-error-popper.el-popper.is-light {
- background: #e02f44;
- border: 1px solid #e02f44;
-}
-.chart-error-popper.el-popover.el-popper {
- color:white;
-}
-
-.chart-error-popper.el-popper.is-light[data-popper-placement^='top'] .el-popper__arrow::before {
- border-color: #e02f44;
- background: #e02f44;
- bottom:0px;
-}
-
-.chart-error-popper.el-popper.is-light[data-popper-placement^='bottom'] .el-popper__arrow::before {
- border-color: #e02f44;
- background: #e02f44;
-}
-
-.chart-info-corner {
- color: #767980;
- cursor: pointer;
- position: absolute;
- display: none;
- left: 0;
- width: 28px;
- height: 28px;
- z-index: 2;
- top: 0;
-}
-.chart-info-corner--error {
- display: block;
- color: #fff;
-}
-.chart-info-corner--error .chart-info-corner-inner {
- border-left: 28px solid #e02f44;
- border-right: none;
- border-bottom: 28px solid rgba(0,0,0,0);
-}
-.chart-info-corner-inner {
- width: 0;
- height: 0;
- position: absolute;
- left: 0;
- bottom: 0;
-}
-.chart-info-corner .fa {
- position: absolute;
- top: 2px;
- left: 6px;
- font-size: 65%;
- z-index: 3;
- font-style: normal;
-}
-.cn-chart-icon-warning:before {
- content: "!";
- font-weight:normal;
-}
-
-.cn-chart:not(.cn-chart__group):not(.cn-chart__block) {
- &>.cn-chart__body {
- height: 100%;
- width: 100%;
- }
-}
-.cn-panel, .cn-panel>.cn-chart__tabs>.el-tabs__content>.el-tab-pane, .cn-chart__group .cn-chart__body, .cn-chart__block .cn-chart__body {
- display: grid;
- grid-template-columns: repeat(30, 1fr);
- grid-auto-flow: row;
- grid-gap: 10px;
- overflow: auto;
- padding-right: 20px;
- position: relative;
-
- .panel__time {
- position: absolute;
- right: 20px;
- top: 10px;
- z-index: 1;
- display: flex;
-
- &>div {
- margin-left: 10px;
- }
- }
-
- &>.cn-chart {
- position: relative;
- background-color: #FFFFFF;
- border: 1px solid #E7EAED;
- box-shadow: 0 2px 4px 0 rgba(51,51,51,0.02);
- border-radius: 2px;
- height: calc(100% - 47px);
- width: 100%;
-
- .chart-drawing {
- height: 100%;
- width: 100%;
- }
- }
- &>.cn-chart__whois>.cn-chart__body {
- overflow: auto;
- }
- &>.cn-chart__echarts, &>.cn-chart__table, &>.cn-chart__map, &>.cn-chart__group, &>.cn-chart__block, &>.cn-chart__whois, &>.cn-chart__dns-record, &>.cn-chart__app-basic {
- display: flex;
- flex-direction: column;
- .cn-chart__header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- flex-shrink: 0;
- padding: 10px 20px 10px 18px;
- height: 47px;
-
- .cn-chart__title {
- font-size: 16px;
- color: #333333;
- font-weight: bold;
- }
- .header__operations {
- color: #999;
- }
- }
- .cn-chart__body {
- flex: auto;
- display: flex;
- .el-descriptions {
- padding-top: 30px;
- }
- &>.el-descriptions {
- flex: 0 0 350px;
- padding: 30px 36px;
- }
- .chart-location {
- display: flex;
- flex: 1;
- flex-direction: column;
- padding: 0 20px 20px 0;
- }
- .el-descriptions__content {
- color: #3976CB;
- }
- }
- }
- &>.cn-chart__block {
- &>.cn-chart__header {
- height: 60px;
- border-bottom: none !important;
- }
- &>.cn-chart__body {
- display: grid !important;
- grid-template-columns: repeat(30, 1fr);
- grid-auto-flow: row;
- grid-gap: 10px;
- padding: 0 20px;
- &>.cn-chart {
- border: 1px solid #E7EAED;
- }
- /* detail页面block下的五连图的标题样式改变 */
- .cn-chart__group .cn-chart__echarts {
- .cn-chart__header {
- border-bottom: none !important;
-
- .header__title {
- font-size: 14px !important;
- color: #3976CB !important;
- }
- }
- }
- }
- }
- .cn-chart__group {
- .cn-chart__header {
- border-bottom: 1px solid $--content-right-background-color;
- }
- &>.cn-chart__body {
- display: grid !important;
- grid-gap: 10px;
- padding: 0 20px;
- .cn-chart {
- border: none;
- box-shadow: none;
- }
- }
- }
- &>.cn-chart__title {
- display: flex;
- align-items: center;
- font-size: 20px;
- padding-left: 10px;
- color: #333;
- background-color: transparent;
- box-shadow: none;
- border: none;
- }
- &>.cn-chart__tabs {
- padding: 10px 25px 10px 15px;
-
- .el-tabs__nav-wrap::after {
- height: 1px;
- }
- &>.el-tabs__header {
- margin-bottom: 10px;
- }
- &>.el-tabs__content {
- height: calc(100% - 40px);
- }
- }
- &>.cn-chart__table {
- .cn-chart__header {
- border-bottom: 1px solid $--content-right-background-color;
- .header__operations {
- display: flex;
- justify-content: end;
- align-items: center;
-
- .header__operation.header__operation--table {
- display: flex;
- align-items: center;
- height: 22px;
- margin-left: 10px;
- color: $--color-primary;
- border: 1px solid $--color-primary;
- border-radius: $--border-radius-primary;
-
- .option__button {
- display: flex;
- align-items: center;
- height: 100%;
- padding: 0 5px;
- cursor: pointer;
- background-color: white;
- transition: all linear .2s;
- }
- .option__button:hover {
- background-color: #EFF2F5;
- }
- .option__button.icon-group-item:first-of-type:not(:last-of-type) {
- padding: 0 5px 0 0;
- }
- .option__button.icon-group-item:last-of-type:not(:first-of-type) {
- padding: 0 0 0 5px;
- }
- .option__select {
- .el-input__inner {
- width: 80px;
- padding-right: 20px;
- border: none;
- height: 100%;
- line-height: 20px;
- color: $--color-primary;
- }
- .el-input__prefix > div {
- font-weight: normal;
- line-height: 19px;
- color: $--color-primary;
- }
- .el-input__suffix {
- display: flex;
- .el-input__suffix-inner {
- line-height: 14px;
- .el-select__caret {
- line-height: 14px;
- width: 16px;
- color: $--color-primary;
- }
- }
- }
- }
- .option__select.select-column {
- .el-input__inner {
- width: 86px;
- padding-left: 8px;
- }
- }
- .icon-group-divide {
- height: 14px;
- width: 1px;
- background-color: $--color-primary;
- }
- i {
- font-size: 12px;
- }
- }
- }
- }
- .cn-chart__body {
- flex: auto;
- overflow-y: auto;
-
- .el-table {
- padding: 0 10px;
-
- &:before {
- height: 0;
- }
- thead {
- color: #333;
- }
- th.is-leaf, td {
- border-bottom: none;
- }
- th {
- padding-bottom: 5px;
- }
- td {
- padding: 4px 0;
- color: #333;
- }
- }
- }
- }
- &>.cn-chart__echarts {
- .cn-chart__header {
- border-bottom: 1px solid $--content-right-background-color;
- .header__operations {
- display: flex;
- justify-content: end;
- align-items: center;
-
- .header__operation.header__operation--echarts {
- display: flex;
- align-items: center;
- height: 22px;
- margin-left: 10px;
- color: $--color-primary;
- border: 1px solid $--color-primary;
- border-radius: $--border-radius-primary;
-
- .option__button {
- display: flex;
- align-items: center;
- height: 100%;
- padding: 0 5px;
- cursor: pointer;
- background-color: white;
- transition: all linear .2s;
- }
- .option__button:hover {
- background-color: #EFF2F5;
- }
- .option__button.icon-group-item:first-of-type:not(:last-of-type) {
- padding: 0 5px 0 0;
- }
- .option__button.icon-group-item:last-of-type:not(:first-of-type) {
- padding: 0 0 0 5px;
- }
- .option__select {
- .el-input__inner {
- width: 120px;
- padding-right: 20px;
- border: none;
- height: 100%;
- line-height: 20px;
- color: $--color-primary;
- }
- .el-input__prefix > div {
- font-weight: normal;
- line-height: 19px;
- color: $--color-primary;
- }
- .el-input__suffix {
- display: flex;
- .el-input__suffix-inner {
- line-height: 14px;
- .el-select__caret {
- line-height: 14px;
- width: 16px;
- color: $--color-primary;
- }
- }
- }
- }
- .option__select.select-column {
- .el-input__inner {
- width: 86px;
- padding-left: 8px;
- }
- }
- .icon-group-divide {
- height: 14px;
- width: 1px;
- background-color: $--color-primary;
- }
- i {
- font-size: 12px;
- }
- }
- }
- }
- .cn-chart__body {
- overflow: hidden auto;
-
- .el-table {
- padding: 0 10px;
-
- &:before {
- height: 0;
- }
- thead {
- color: #333;
- }
- th.is-leaf, td {
- border-bottom: none;
- }
- th {
- padding-bottom: 5px;
- }
- td {
- padding: 4px 0;
- color: #333;
- }
- }
- }
- .cn-chart__body.pie-with-table {
- flex-basis: 40%;
- }
- .cn-chart__footer.pie-with-table {
- flex-basis: 60%;
- padding: 10px 30px 30px;
- }
- }
- .pie-table {
- font-size: 14px;
- color: #333333;
- font-weight: 500;
-
- .el-table__header-wrapper {
- .cell {
- color: #333;
- }
- }
- .el-table__expanded-cell[class*=cell] {
- padding: 0;
- }
-
- .expand-table .el-table__body .el-table__row:last-of-type td {
- border: none;
- }
- .expand-table {
- font-weight: 400;
- color: #606266;
-
- .el-table__body-wrapper {
- height: auto !important;
- }
- }
- }
- .chart__legend {
- width: calc(100% - 40px);
- border: 1px solid #E7EAED;
- color: #5f6368;
- margin: auto;
- margin-bottom: 15px;
-
- .chart__table-top {
- width: 100%;
- height: 30px;
- border-bottom: #E7EAED 1px solid;
- display: flex;
-
- div {
- font-size: 13px;
- line-height: 28px;
- color: $--color-primary;
- }
- }
- .chart__table-below {
- height: 240px;
- width: 100%;
- font-size: 13px;
- }
- .table-below-box {
- width: 100%;
- display: flex;
- align-items: center;
- line-height: 24px;
- }
- .table-below-box:hover {
- background-color: #f9f9f9;
- border: 0;
- color: #383838;
- }
- .table__below-color {
- width: 27px;
- height: 7px;
- flex-shrink: 0;
- padding-left: 10px;
-
- div {
- height: 100%;
- width: 100%;
- border-radius: 24%;
- }
- }
- .table__below-title {
- padding: 0 6px;
- flex-shrink: 1;
- flex-grow: 1;
- overflow: hidden;
- min-width: 200px;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .table__below-statistics {
- width: 80px;
- flex-shrink: 0;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .table-below-box:not(.chart__table-top) {
- cursor: pointer;
- }
- .table-below-box.table-below-box--inactivated {
- color: #ccc;
- .table__below-color div {
- background-color: #ccc !important;
- }
- }
- }
-}
-@media only screen and (min-width : 10px) {
- .cn-panel, .cn-panel>.cn-chart__tabs>.el-tabs__content>.el-tab-pane,
- .cn-chart__body {
- grid-auto-rows: 25px;
- }
-}
-@media only screen and (min-width : 1224px) {
- .cn-panel,
- .cn-panel>.cn-chart__tabs>.el-tabs__content>.el-tab-pane,
- .cn-chart__body {
- grid-auto-rows: 30px;
- }
-}
-@media only screen and (min-width : 1824px) {
- .cn-panel,
- .cn-panel>.cn-chart__tabs>.el-tabs__content>.el-tab-pane,
- .cn-chart__body {
- grid-auto-rows: 40px;
- }
-}
-@media only screen and (min-width : 2424px) {
- .cn-panel,
- .cn-panel>.cn-chart__tabs>.el-tabs__content>.el-tab-pane,
- .cn-chart__body {
- grid-auto-rows: 55px;
- }
-}
-.cn-panel>.cn-chart__tabs>.el-tabs__content>.el-tab-pane>.cn-chart {
- border: none;
- box-shadow: none;
- .cn-chart__header {
- border-bottom: none;
- }
-}
-
-.cn-entity-detail {
- height: 100%;
- width: 100%;
- overflow: hidden;
- .entity-detail__header {
- display: flex;
- justify-content: space-between;
- height: 70px;
- padding-right: 20px;
- background-color: #F7F9FB;
-
- .detail-header__title {
- display: flex;
- align-items: center;
- padding-left: 20px;
- font-size: 20px;
-
- .title__icon-circle {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 38px;
- width: 38px;
- border-radius: 50%;
- background-color: #B8C1D1;
-
- i {
- color: white;
- font-size: 20px;
- }
- }
- .title__name {
- text-overflow: ellipsis;
- max-width: 400px;
- overflow: hidden;
- white-space: nowrap;
- padding-left: 10px;
- color: #333;
- }
- }
- .detail-header__operation {
- display: flex;
- align-items: flex-end;
-
- .panel__time {
- display: flex;
- padding: 0 30px 10px 0;
- }
-
- & > .el-tabs > .el-tabs__header { // header背景色
- margin: 0 0 -1px 0;
-
- & > .el-tabs__nav-wrap > .el-tabs__nav-scroll > .el-tabs__nav {
- & > .el-tabs__item {
- height: 35px;
- line-height: 35px;
- }
- & > .el-tabs__item.is-active { // 激活的tab上边框和背景色
- background-color: white;
- border-top: 2px solid #0091ff;
- }
- & > .el-tabs__active-bar {
- display: none;
- }
- & > div:last-of-type {
- padding-right: 20px;
- }
- & > div:nth-of-type(2) {
- padding-left: 20px;
- }
- }
- }
- & > .el-tabs > .el-tabs__header > .el-tabs__nav-wrap::after { // 去掉tabs下方边框
- height: 0 !important;
- }
- &>.el-tabs { // 底部对齐
- display: flex;
- align-items: flex-end;
- }
- }
- }
- .entity-detail__body {
- height: 100%;
- width: 100%;
- overflow: auto;
- /*&>div {
- display: grid;
- grid-template-columns: repeat(30, 1fr);
- grid-auto-flow: row;
- grid-gap: 10px;
- height: 100%;
- }
-
- .cn-panel {
- padding: 20px;
- grid-gap: 10px;
-
- &>.cn-chart>.cn-chart__header {
- border-bottom: 1px solid $--content-right-background-color;
- .header__title>span {
- color: #1890FF;
- font-weight: bold;
- font-size: 16px;
- }
- }
- &>.cn-chart>.cn-chart__body {
- .cn-chart__header {
- border-bottom: 1px solid $--content-right-background-color;
- .header__title {
- color: #666;
- font-size: 16px;
- }
- }
- }
- }*/
- }
-}
-.el-overlay {
- overflow: hidden !important;
-}
-.entity-detail__dialog {
- height: 90vh;
- overflow: hidden;
- .el-dialog__header {
- display: none;
- }
- .el-dialog__body {
- height: 100%;
- padding: 0;
- }
-}
-.option-popper {
- .el-select-dropdown__item {
- height: 24px;
- line-height: 24px;
- font-size: 12px;
- }
-}
-.header__operation-btn {
- margin-left: 12px;
- cursor: pointer;
- color: #999;
-}
-.ip-detail-as {
- color: #999;
- font-size: 12px;
- padding-left: 10px;
-}
-//.cn-chart-select{
-// display: flex;
-// align-items: center;
-// height: 22px;
-// margin-left: 10px;
-// color: #0091ff;
-// border: 1px solid #0091ff;
-// border-radius: 2px;
-//}
-.cn-chart__single-value.cn-chart__single-value--detail-overview.cn-chart__single-value--icon-left {
- .single-value__icon {
- width: 38px;
- height: 38px;
-
- i {
- font-size: 15px;
- }
- }
- .single-value__content {
- .content__data {
- font-size: 14px;
- }
- .content__title {
- font-size: 12px;
- }
- }
-}
-.cn-chart__single-value.cn-chart__single-value--icon-left {
- display: flex;
- align-items: center;
-
- .single-value-icon__box {
- display: flex;
- align-items: center;
- justify-content: center;
- flex: 0 0 40%;
- }
-
- .single-value__icon {
- display: flex;
- justify-content: center;
- width: 72px;
- height: 72px;
- background-color: $--chart-single-value-icon-background-color;
- border-radius: 50%;
-
- i {
- display: flex;
- align-items: center;
- font-size: 28px;
- color: $--color-primary;
- }
- }
-
- .single-value__content {
- display: flex;
- flex-direction: column;
- max-width: 60%;
- padding-right: 10px;
-
- .content__data {
- padding-bottom: 7%;
- font-size: 24px;
- color: #333333;
- font-weight: bold;
- }
- .content__title {
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- font-size: 16px;
- color: #666666;
- }
- &.single-value__content--with-chart {
- .content__title {
- border-bottom: 1px solid $--content-right-background-color;
- }
- }
- .single-value__unit {
- font-weight: normal;
- padding-left: 10px;
- color: #666;
- font-size: 20px;
- }
- }
-}
-.cn-chart__single-value.cn-chart__single-value--icon-right {
- display: flex;
- flex-direction: row-reverse;
- justify-content: space-around;
- align-items: center;
-
- .single-value__icon {
- background-color: $--chart-single-value-icon-background-color;
- border-radius: 50%;
- position: relative;
- margin-right: 7.5%;
- margin-bottom: 6%;
- width: 56px;
- height: 56px;
-
- i {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%,-50%);
- font-size: 24px;
- color: $--color-primary;
- }
- }
-
- .single-value__content {
- display: flex;
- height: 100%;
- flex-direction: column;
-
- .content__title {
- display: flex;
- align-items: center;
- height: 50%;
- font-size: 16px;
- color: #666666;
- }
- .content__data {
- display: flex;
- padding-top: 5%;
- height: 50%;
- flex: auto;
- font-size: 24px;
- color: #333333;
- font-weight: bold;
- }
- }
-}
-.cn-chart__single-value.cn-chart__single-value--icon-right--color {
- display: flex;
- flex-direction: row-reverse;
- justify-content: space-around;
- align-items: center;
-
- .single-value__content {
- display: flex;
- height: 100%;
- width: 100%;
- flex-direction: row-reverse;
- justify-content: space-between;
- align-items: center;
-
- .single-value-icon__box {
- padding-right: 30px;
- .single-value__icon {
- border-radius: 50%;
- position: relative;
- margin-right: 7.5%;
- margin-top: 30%;
-
- .cn-icon-svg {
- width: 50px;
- height: 50px;
- vertical-align: middle;
- fill: currentColor;
- overflow: hidden;
- }
-
- i {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%,-50%);
- font-size: 24px;
- }
- }
- }
-
- .single-value__data{
- display: flex;
- height: 100%;
- flex-direction: column;
- padding-left: 20px;
-
- .content__title {
- display: flex;
- align-items: end;
- height: 50%;
- font-size: 16px;
- color: #666666;
- padding-bottom: 5px;
- }
- .content__data {
- display: flex;
- padding-top: 5%;
- height: 50%;
- flex: auto;
- font-size: 24px;
- color: #333333;
- font-weight: bold;
- }
- }
-
- }
-}
-.cn-chart__single-value.cn-chart__single-value--chart {
- display: flex;
- padding: 13px 20px;
-
- .single-value__content {
- display: flex;
- height: 100%;
- width: 100%;
- flex-direction: column;
-
- .content__title {
- display: flex;
- align-items: center;
- height: 30%;
- font-size: 16px;
- color: #666666;
- }
- .content__data {
- display: flex;
- align-items: center;
- height: 25%;
- font-size: 24px;
- color: #333333;
- font-weight: bold;
- }
- .content__chart {
- flex: auto
- }
- }
-}
-
-.chart-table-pagination.el-pagination {
- padding: 12px 0 9px 0;
- text-align: center;
-
- .el-pagination__jump {
- margin-left: 10px;
- }
-}
diff --git a/src/components/charts/ChartMap.vue b/src/components/charts/ChartMap.vue
deleted file mode 100644
index 573f993b..00000000
--- a/src/components/charts/ChartMap.vue
+++ /dev/null
@@ -1,39 +0,0 @@
-<template>
- <div class="cn-chart__map">
- <div class="cn-chart__header chart-header-position" >
- <slot name="chartErrorInfo"></slot>
- <div class="header__title" v-if="!hideHeader">
- <slot name="title"></slot>
- </div>
- <div class="header__operations" v-if="!hideHeader">
- <slot name="operations"></slot>
- </div>
- </div>
- <div class="cn-chart__body">
- <slot></slot>
- </div>
- <div class="chart__loading" v-show="loading">
- <i class="el-icon-loading"></i>
- </div>
- <div class="cn-chart__footer">
- <slot name="footer"></slot>
- </div>
- </div>
-</template>
-
-<script>
-
-export default {
- name: 'ChartMap',
- props: {
- loading: Boolean,
- hideHeader: Boolean
- },
- data () {
- return {
- errorContent: '出错了。。。',
- isError: true
- }
- }
-}
-</script>
diff --git a/src/components/charts/ChartSingleValue.vue b/src/components/charts/ChartSingleValue.vue
deleted file mode 100644
index 5721bd84..00000000
--- a/src/components/charts/ChartSingleValue.vue
+++ /dev/null
@@ -1,95 +0,0 @@
-<template>
- <div class="cn-chart cn-chart__single-value chart-header-position" :class="singleValueClass(type)" :style="{backgroundColor:color}">
- <slot name="chartErrorInfo"></slot>
- <div class="single-value-icon__box" v-if="type != 54">
- <div class="single-value__icon"><i :class="icon"></i></div>
- </div>
- <div class="chart__loading" v-show="loading">
- <i class="el-icon-loading"></i>
- </div>
- <div class="single-value__content" v-if="type === 51">
- <div class="content__data">
- <slot name="data"></slot>
- </div>
- <div class="content__title">
- <slot name="title"></slot>
- </div>
- </div>
- <div class="single-value__content single-value__content--with-chart" v-if="type === 52 || type === 55">
- <div class="content__title">
- <slot name="title"></slot>
- </div>
- <div class="content__data">
- <slot name="data"></slot>
- </div>
- <div class="content__chart">
- <slot name="chart"></slot>
- </div>
- </div>
- <div class="single-value__content" v-if="type === 53">
- <div class="content__title"></div>
- <div class="content__data"></div>
- </div>
- <div class="single-value__content" v-if="type === 54" >
- <div class="single-value-icon__box" >
- <div class="single-value__icon">
- <!-- 使用图标-->
- <svg class="cn-icon-svg" aria-hidden="true">
- <use :xlink:href="icon"></use>
- </svg>
- </div>
- </div>
- <div class="single-value__data">
- <div class="content__title">
- <slot name="title"></slot>
- </div>
- <div class="content__data">
- <slot name="data"></slot>
- </div>
- </div>
-
- </div>
- </div>
-</template>
-
-<script>
-import '@/assets/css/font/iconfont.js'
-
-export default {
- name: 'ChartSingleValue',
- props: {
- type: Number,
- icon: String,
- loading: Boolean,
- color: String
- },
- computed: {
- singleValueClass () {
- return function (type) {
- let c
- switch (type) {
- case 51: {
- c = 'cn-chart__single-value--icon-left'
- break
- }
- case 55:
- case 52: {
- c = 'cn-chart__single-value--chart'
- break
- }
- case 53: {
- c = 'cn-chart__single-value--icon-right'
- break
- }
- case 54: {
- c = 'cn-chart__single-value--icon-right--color'
- break
- }
- default: break
- }
- return c
- }
- }
- }
-}
-</script>
diff --git a/src/components/charts/ChartTable.vue b/src/components/charts/ChartTable.vue
deleted file mode 100644
index 523e692b..00000000
--- a/src/components/charts/ChartTable.vue
+++ /dev/null
@@ -1,72 +0,0 @@
-<template>
- <div class="cn-chart cn-chart__table">
- <div class="cn-chart__header chart-header-position" >
- <slot name="chartErrorInfo"></slot>
- <div class="header__title">
- <slot name="title"></slot>
- </div>
- <div class="header__operations">
- <slot name="operations"></slot>
- </div>
- </div>
- <div class="chart__loading" v-show="loading">
- <i class="el-icon-loading"></i>
- </div>
- <div class="cn-chart__body" v-no-data="noData">
- <el-table
- style="width: 100%"
- tooltip-effect="light"
- :data="tableData"
- >
- <el-table-column
- type="index"
- label="#"
- >
- </el-table-column>
- <el-table-column
- v-for="(c, i) in tableColumns"
- show-overflow-tooltip
- :key="i"
- :label="c.label"
- :prop="c.prop"
- >
- <template #header>{{c.label}}</template>
- <template #default="{ row }">{{}}
- <span v-if="c.prop === 'bytes'">
- {{unitConvert(row[c.prop], unitTypes.byte).join(' ')}}
- </span>
- <span v-else-if="c.prop === 'packets' || c.prop === 'sessions'">
- {{unitConvert(row[c.prop], unitTypes.number).join(' ')}}
- </span>
- <span v-else>
- {{row[c.prop]}}
- </span>
- </template>
- </el-table-column>
- </el-table>
- </div>
- <div class="cn-chart__footer">
- <slot name="footer"></slot>
- </div>
- </div>
-</template>
-
-<script>
-import unitConvert from '@/utils/unit-convert'
-import { unitTypes } from '@/utils/constants'
-export default {
- name: 'ChartTable',
- props: {
- tableColumns: Array,
- tableData: Array,
- loading: Boolean,
- noData: Boolean
- },
- setup () {
- return {
- unitTypes,
- unitConvert
- }
- }
-}
-</script>
diff --git a/src/components/charts/ChartTableActiveIp.vue b/src/components/charts/ChartTableActiveIp.vue
deleted file mode 100644
index bde28488..00000000
--- a/src/components/charts/ChartTableActiveIp.vue
+++ /dev/null
@@ -1,112 +0,0 @@
-<template>
- <div class="cn-chart cn-chart__table">
- <div class="cn-chart__header chart-header-position" >
- <slot name="chartErrorInfo"></slot>
- <div class="header__title ">
- <slot name="title"></slot>
- </div>
- <div class="header__operations">
- <slot name="operations"></slot>
- </div>
- </div>
- <div class="chart__loading" v-show="loading">
- <i class="el-icon-loading"></i>
- </div>
- <div class="cn-chart__body" v-no-data="noData">
- <el-table
- style="width: 100%"
- tooltip-effect="light"
- :data="tableData"
- :show-header="false"
- :cell-style="{padding:'7px 0'}"
- >
- <el-table-column>
- <template #default="{ row }">
- <div class="active-ip__icon"><i class="cn-icon cn-icon-ip ip-green"></i></div>
- <div class="active-ip__content" >
- {{row['name']}}
- </div>
- </template>
- </el-table-column>
- <el-table-column align="center">
- <template #default="{ row }">
- <span>
- {{row['num']}}
- </span>
- </template>
- </el-table-column>
-
- <el-table-column
- v-for="(c, i) in tableColumns"
- show-overflow-tooltip
- :key="i"
- :label="c.label"
- :prop="c.prop"
- >
- <template #default="{ row }">
- <span v-if="c.prop === 'bytes'">
- {{unitConvert(row[c.prop], unitTypes.byte).join(' ')}}
- </span>
- <span v-else-if="c.prop === 'packets' || c.prop === 'sessions'">
- {{unitConvert(row[c.prop], unitTypes.number).join(' ')}}
- </span>
- <span v-else>
- {{row[c.prop]}}
- </span>
- </template>
- </el-table-column>
- </el-table>
- </div>
- <div class="cn-chart__footer">
- <slot name="footer"></slot>
- </div>
- </div>
-</template>
-
-<script>
-import unitConvert from '@/utils/unit-convert'
-import { unitTypes } from '@/utils/constants'
-export default {
- name: 'ChartTableActiveIp',
- props: {
- tableColumns: Array,
- tableData: Array,
- loading: Boolean,
- noData: Boolean
- },
- setup () {
- return {
- unitTypes,
- unitConvert
- }
- }
-}
-</script>
-
-<style>
-
- .active-ip__icon {
- overflow: hidden;
- position: absolute;
- top: 8px;
- left: 6px;
- display: flex;
- justify-content: center;
- justify-items: center;
- align-items: center;
- width: 23px;
- height: 23px;
- border-radius: 50%;
- background: #e8fbf9;
- border: 2px solid #e8fbf9;
- }
- .ip-green {
- color: #23BF9A;
- }
- .active-ip__content {
- position: absolute;
- top: 7px;
- left: 35px;
- overflow: hidden;
- }
-</style>
diff --git a/src/components/charts/ChartTablePagination.vue b/src/components/charts/ChartTablePagination.vue
deleted file mode 100644
index 521d861c..00000000
--- a/src/components/charts/ChartTablePagination.vue
+++ /dev/null
@@ -1,55 +0,0 @@
-<template>
- <el-pagination
- small
- ref="pagination"
- layout="prev,jumper,slot,next"
- class="chart-table-pagination"
- :total="total"
- :page-size="pageSize"
- v-model:currentPage="pageNo"
- @current-change="current"
- >
- <span>/&nbsp;{{totalPage}}</span>
- </el-pagination>
-</template>
-
-<script>
-import { chartTableDefaultPageSize } from '@/utils/constants'
-export default {
- name: 'ChartTablePagination',
- props: {
- total: Number
- },
- data () {
- return {
- pageSize: chartTableDefaultPageSize,
- pageNo: 1
- }
- },
- computed: {
- totalPage () {
- const remainder = this.total % this.pageSize
- if (remainder) {
- return parseInt(this.total / this.pageSize) + 1
- } else {
- return parseInt(this.total / this.pageSize)
- }
- }
- },
- methods: {
- current (val) {
- this.$emit('pageJump', val)
- },
- resetPageNo () {
- this.pageNo = 1
- }
- },
- mounted () {
- const _this = this
- this.emitter.on('chart-pageNo', function () {
- _this.resetPageNo()
- })
- this.$el.querySelector('.el-pagination__jump').childNodes[0].nodeValue = ''
- }
-}
-</script>
diff --git a/src/components/charts/ChartTitle.vue b/src/components/charts/ChartTitle.vue
deleted file mode 100644
index f790cfc5..00000000
--- a/src/components/charts/ChartTitle.vue
+++ /dev/null
@@ -1,9 +0,0 @@
-<template>
- <div class="cn-chart cn-chart__title"></div>
-</template>
-
-<script>
-export default {
- name: 'ChartTitle'
-}
-</script>
diff --git a/src/components/charts/EchartsFrame.vue b/src/components/charts/EchartsFrame.vue
deleted file mode 100644
index bc2acb6c..00000000
--- a/src/components/charts/EchartsFrame.vue
+++ /dev/null
@@ -1,44 +0,0 @@
-<template>
- <div class="cn-chart cn-chart__echarts" :class="{'cn-chart__echarts--statistics': isEchartsWithStatistics}">
- <div class="cn-chart__header chart-header-position" v-if="layout.indexOf(layoutConstant.HEADER) > -1" >
- <slot name="chartErrorInfo"></slot>
- <div class="header__title">
- <slot name="title"></slot>
- </div>
- <div class="header__operations">
- <slot name="operations"></slot>
- </div>
- </div>
- <div class="cn-chart__body" :class="{'pie-with-table': isPieWithTable}" v-no-data="noData">
- <slot></slot>
- </div>
- <div class="chart__loading" v-show="loading">
- <i class="el-icon-loading"></i>
- </div>
- <div class="cn-chart__footer" v-if="layout.indexOf(layoutConstant.FOOTER) > -1 && !noData" :class="{'pie-with-table': isPieWithTable}">
- <slot name="footer"></slot>
- </div>
- </div>
-</template>
-
-<script>
-import { layoutConstant, isEchartsWithTable, isEchartsWithStatistics } from '@/components/charts/chart-options'
-export default {
- name: 'EchartsFrame',
- props: {
- layout: Array,
- chartInfo: Object,
- loading: Boolean,
- noData: Boolean
- },
- setup (props) {
- return {
- layoutConstant,
- isPieWithTable: isEchartsWithTable(props.chartInfo.type),
- isEchartsWithStatistics: isEchartsWithStatistics(props.chartInfo.type)
- }
- },
- mounted () {
- }
-}
-</script>
diff --git a/src/components/charts/PieTable.vue b/src/components/charts/PieTable.vue
deleted file mode 100644
index 2615da28..00000000
--- a/src/components/charts/PieTable.vue
+++ /dev/null
@@ -1,258 +0,0 @@
-<template>
- <el-table
- ref="table"
- class="pie-table"
- :data="pieTableData"
- style="width: 100%;border: 1px solid #E7EAED"
- :row-key="getRowKey"
- @expand-change="currentChange"
- :current-row-key="tableNameColumn"
- tooltip-effect="light"
- :expand-row-keys="expandRowKeys"
- size="mini"
- height="100%">
- <el-table-column type="expand" min-width="5%">
- <template #default="props">
- <div style="position: relative">
- <div class="chart__loading" style="top: 0; height: 100%; z-index: 1;" v-show="loading">
- <i class="el-icon-loading"></i>
- </div>
- <el-table
- tooltip-effect="light"
- class="expand-table"
- :data="childrenTableData"
- style="width: 100%;"
- :show-header="false"
- :size="'mini'"
- :height="'100%'">
- <el-table-column
- width="48">
- </el-table-column>
- <el-table-column
- v-for="(item, index) in tableTitlesOther"
- :key="index"
- show-overflow-tooltip
- :min-width="item.width"
- :label="item.label"
- :prop="item.prop"
- #default="{row}">
- <span v-if="item.prop === 'nameColumn'">
- {{ nameColumn === 'domainCategoryName' ? row['categoryName'] :(nameColumn === 'domainReputationLevel'? row['reputationLevel']:(nameColumn==='appCategory'?row['appCategoryName']:appRisk(row['appRiskLevel'])))}}
- </span>
- <span v-else-if="item.prop === 'tableNameColumn'">
- {{ tableNameColumn === 'appName' ? row['appName'] : row['domain']}}
- </span>
- <span v-else-if="item.prop === 'bytes'">
- {{unitConvert(row[item.prop], unitTypes.byte).join(' ')}}
- </span>
- <span v-else-if="item.prop === 'packets' || item.prop === 'sessions'">
- {{unitConvert(row[item.prop], unitTypes.number).join(' ')}}
- </span>
- <span v-else>
- {{ row[item.prop] }}
- </span>
- </el-table-column>
- </el-table>
- </div>
- </template>
- </el-table-column>
- <el-table-column
- v-for="(item, index) in tableTitles"
- :key="index"
- show-overflow-tooltip
- :min-width="item.width"
- :label="(tableNameColumn === 'appName'&& item.prop === 'tableNameColumn')? $t('overall.appName'):item.label"
- :prop="item.prop"
- #default="{row}">
- <span v-if="item.prop === 'nameColumn'">
- {{ nameColumn === 'domainCategoryName' ? row['categoryName'] :(nameColumn === 'domainReputationLevel'? row['reputationLevel']:(nameColumn==='appCategory'?row['appCategoryName']:appRisk(row['appRiskLevel'])))}}
- </span>
- <span v-else-if="item.prop === 'tableNameColumn'">
- {{ tableNameColumn === 'appName' ? row['appName'] : row['domain']}}
- </span>
- <span v-else-if="item.prop === 'bytes'">
- {{unitConvert(row[item.prop], unitTypes.byte).join(' ')}}
- </span>
- <span v-else-if="item.prop === 'packets' || item.prop === 'sessions'">
- {{unitConvert(row[item.prop], unitTypes.number).join(' ')}}
- </span>
- <span v-else>
- {{ row[item.prop] }}
- </span>
- </el-table-column>
- </el-table>
-</template>
-
-<script>
-import unitConvert from '@/utils/unit-convert'
-import { get } from '@/utils/http'
-import { replaceUrlPlaceholder } from '@/utils/tools'
-import { unitTypes, riskLevelMapping } from '@/utils/constants'
-
-export default {
- name: 'PieTable',
- props: {
- tableData: Array,
- chartInfo: Object,
- order: String,
- timeFilter: Object
- },
- watch: {
- tableData: {
- deep: true,
- immediate: true,
- handler (n) {
- this.pieTableData = JSON.parse((JSON.stringify(n)))
- this.pieTableData.forEach(item => {
- item.children = []
- })
- }
- },
- chartInfo: {
- deep: true,
- immediate: true,
- handler (n) {
- if (n && n.params) {
- this.nameColumn = n.params.nameColumn
- this.tableNameColumn = n.params.tableNameColumn
- }
- }
- }
- },
- computed: {
- appRisk () {
- return function (level) {
- const m = riskLevelMapping.find(mapping => {
- return mapping.value == level
- })
- return (m && m.name) || level
- }
- }
- },
- data () {
- return {
- nameColumn: '',
- tableNameColumn: '',
- pieTableData: [],
- childrenTableData: [],
- expandRowKeys: [],
- tableTitles: [
- {
- label: this.$t('overall.domain'),
- prop: 'tableNameColumn', // 'domain'
- width: '20%'
- },
- {
- label: this.$t(this.chartInfo.params.tableTypeColumnLabel),
- prop: 'nameColumn',
- width: '22%'
- },
- {
- label: this.$t('overall.sessions'),
- prop: 'sessions',
- width: '18%'
- },
- {
- label: this.$t('overall.packets'),
- prop: 'packets',
- width: '18%'
- },
- {
- label: this.$t('overall.bytes'),
- prop: 'bytes',
- width: '18%'
- }
- ],
- tableTitlesOther: [
- {
- label: this.$t('overall.serverIp'),
- prop: 'serverIp',
- width: '20%'
- },
- {
- label: this.$t('overall.reputation'),
- prop: 'nameColumn',
- width: '22%'
- },
- {
- label: this.$t('overall.sessions'),
- prop: 'sessions',
- width: '18%'
- },
- {
- label: this.$t('overall.packets'),
- prop: 'packets',
- width: '18%'
- },
- {
- label: this.$t('overall.bytes'),
- prop: 'bytes',
- width: '18%'
- }
- ],
- loading: true
- }
- },
- methods: {
- currentChange (row, expandedRows) {
- this.loading = true
- this.childrenTableData = []
-
- if (this.tableNameColumn === 'appName') {
- if (this.expandRowKeys[0] && (row.appName === this.expandRowKeys[0])) {
- this.expandRowKeys = []
- } else {
- this.expandRowKeys = [row.appName]
- }
- } else {
- if (this.expandRowKeys[0] && (row.domain === this.expandRowKeys[0])) {
- this.expandRowKeys = []
- } else {
- this.expandRowKeys = [row.domain]
- }
- }
-
- const url = this.chartInfo.params.urlChildrenTable
- let queryParams = {
- startTime: parseInt(this.timeFilter.startTime / 1000),
- endTime: parseInt(this.timeFilter.endTime / 1000),
- order: this.order,
- domain: row.domain,
- limit: 10
- }
- if (this.tableNameColumn === 'appName') {
- queryParams = {
- startTime: parseInt(this.timeFilter.startTime / 1000),
- endTime: parseInt(this.timeFilter.endTime / 1000),
- order: this.order,
- appName: row.appName,
- limit: 10
- }
- }
- setTimeout(() => {
- get(replaceUrlPlaceholder(url, queryParams)).then(response2 => {
- if (response2.code === 200) {
- this.childrenTableData = response2.data.result
- }
- }).finally(() => {
- this.loading = false
- })
- }, 500)
- },
-
- getRowKey (row) {
- if (this.tableNameColumn === 'appName') {
- return row.appName
- } else {
- return row.domain
- }
- }
- },
- setup () {
- return {
- unitTypes,
- unitConvert
- }
- }
-}
-</script>
diff --git a/src/components/charts/chart-options.js b/src/components/charts/chart-options.js
deleted file mode 100644
index 460c4e6d..00000000
--- a/src/components/charts/chart-options.js
+++ /dev/null
@@ -1,828 +0,0 @@
-/**
- * @author 陈劲松
- * @date 2021/6/16
- * @description chart option和一些工具
-*/
-import { format } from 'echarts'
-import { unitTypes } from '@/utils/constants'
-import unitConvert from '@/utils/unit-convert'
-import _ from 'lodash'
-export const chartColor = ['#5370C6', '#90CC74', '#FAC858', '#EE6666',
- '#73BFDE', '#3BA172', '#FC8452', '#9960B4',
- '#E97CCC', '#FEA69E', '#0F8AB2', '#57CBAC',
- '#5888BC', '#63B6AC', '#EDC6B2', '#D5746B']
-export const chartBarColor = ['#0F8AB2', '#57CBAC']
-export function getChartColor (index) {
- return chartColor[index % chartColor.length]
-}
-export function getCharBartColor (index) {
- return chartBarColor[index % chartBarColor.length]
-}
-const line = {
- tooltip: {
- appendToBody: true,
- trigger: 'axis',
- textStyle: {
- width: '20px',
- overflow: 'truncate'
- },
- formatter: axiosFormatter,
- show: true,
- className: 'nz-chart-tooltip',
- extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
- },
- xAxis: {
- type: 'time'
- },
- yAxis: {
- type: 'value',
- axisLabel: {
- formatter: function (value, index, a, b) {
- return unitConvert(value, unitTypes.number).join(' ')
- }
- },
- minInterval: 1
- },
- animation: false,
- grid: {
- left: 55,
- bottom: 30,
- top: 100,
- right: 25
- },
- color: chartColor,
- legend: {
- tooltip: {
- show: true,
- formatter: '{a}'
- },
- show: true,
- right: 23,
- top: 8,
- padding: 2,
- orient: 'horizontal',
- icon: 'circle',
- itemGap: 10,
- itemWidth: 10,
- textStyle: {
- padding: [0, 0, 0, 2],
- fontSize: 14
- },
- formatter: tooLongFormatter
- },
- axisLabel: {
- fontSize: 14
- },
- series: [
- {
- name: '',
- type: 'line',
- smooth: false,
- symbol: 'none',
- data: []
- }
- ]
-}
-const lineWithStatistics = {
- tooltip: {
- appendToBody: true,
- trigger: 'axis',
- textStyle: {
- width: '20px',
- overflow: 'truncate'
- },
- formatter: axiosFormatter,
- className: 'nz-chart-tooltip',
- extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
- },
- xAxis: {
- type: 'time'
- },
- animation: false,
- yAxis: {
- type: 'value',
- axisLabel: {
- formatter: function (value, index) {
- return unitConvert(value, unitTypes.number).join(' ')
- }
- },
- minInterval: 1
- },
- color: chartColor,
- grid: {
- left: 55,
- bottom: 30,
- top: 20,
- right: 20
- },
- legend: {
- show: false
- },
- axisLabel: {
- fontSize: 14
- },
- series: [
- {
- name: '',
- type: 'line',
- smooth: false,
- symbol: 'none',
- data: []
- }
- ]
-}
-const lineStack = {
- tooltip: {
- appendToBody: true,
- trigger: 'axis',
- textStyle: {
- width: '20px',
- overflow: 'truncate'
- },
- formatter: axiosFormatter,
- className: 'nz-chart-tooltip',
- extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
- },
- xAxis: {
- type: 'time'
- },
- color: chartColor,
- yAxis: {
- type: 'value',
- axisLabel: {
- formatter: function (value, index) {
- return unitConvert(value, unitTypes.number).join(' ')
- }
- },
- minInterval: 1
- },
- grid: {
- left: 55,
- bottom: 45,
- top: 10,
- right: 180
- },
- legend: {
- show: true,
- right: 30,
- top: 'middle',
- orient: 'vertical',
- icon: 'circle',
- itemGap: 20,
- itemWidth: 10,
- formatter: tooLongFormatter,
- textStyle: {
- padding: [0, 0, 0, 5],
- fontSize: 14
- }
- },
- axisLabel: {
- fontSize: 14
- },
- series: [
- {
- name: '',
- type: 'line',
- stack: 'value',
- areaStyle: {},
- symbol: 'none',
- data: []
- }
- ]
-}
-const pieWithTable = {
- tooltip: {
- appendToBody: true
- },
- color: chartColor,
- animation: false,
- legend: {
- orient: 'vertical',
- type: 'plain',
- left: '60%',
- top: 'middle',
- icon: 'circle',
- itemWidth: 10, // 设置宽度
- itemHeight: 10, // 设置高度
- itemGap: 20,
- formatter: tooLongFormatter,
- tooltip: {
- show: true
- }
- },
- series: [
- {
- type: 'pie',
- selectedMode: 'single',
- radius: ['42%', '65%'],
- center: ['30%', '50%'],
- data: [],
- label: {
- formatter: '{d}%'
- },
- tooltip: {
- formatter: function (param, index, callback) {
- return `${param.name}: ${unitConvert(param.value, param.data.unitType).join(' ')}`
- }
- },
- emphasis: {
- itemStyle: {
- shadowBlur: 10,
- shadowOffsetX: 0,
- shadowColor: 'rgba(0, 0, 0, 0.5)'
- }
- }
- }
- ]
-}
-const ipHostedDomain = {
- color: chartColor,
- animation: false,
- tooltip: {
- show: true
- },
- legend: {
- orient: 'vertical',
- type: 'plain',
- right: '8%',
- top: 'middle',
- icon: 'circle',
- itemWidth: 10, // 设置宽度
- itemHeight: 10, // 设置高度
- itemGap: 20,
- tooltip: {
- show: true
- }
- },
- series: [
- {
- type: 'pie',
- selectedMode: 'single',
- radius: ['42%', '65%'],
- center: ['36%', '50%'],
- data: [],
- label: {
- formatter: '{d}%'
- },
- tooltip: {
- formatter: function (param, index, callback) {
- return `${param.name}: ${unitConvert(param.value, param.data.unitType).join(' ')}`
- }
- },
- emphasis: {
- itemStyle: {
- shadowBlur: 10,
- shadowOffsetX: 0,
- shadowColor: 'rgba(0, 0, 0, 0.5)'
- }
- }
- }
- ]
-}
-const singleValueLine = {
- tooltip: {
- show: true,
- enterable: true,
- showContent: true,
- appendToBody: true,
- trigger: 'axis',
- textStyle: {
- width: '20px',
- overflow: 'truncate'
- }
- },
- xAxis: {
- type: 'time',
- show: false
- },
- yAxis: {
- type: 'value',
- show: false
- },
- animation: false,
- grid: {
- left: 0,
- bottom: 2,
- top: 5,
- right: 0
- },
- color: chartColor,
- legend: {
- show: false
- },
- series: [
- {
- type: 'line',
- legendHoverLink: false,
- itemStyle: {
- normal: {
- color: '#81C9FF',
- lineStyle: {
- width: 2
- }
- }
- },
- data: [],
- showSymbol: false,
- areaStyle: { color: '#C9EAFF' }
- }
- ]
-}
-export const entityListLineOption = {
- tooltip: {
- appendToBody: true,
- trigger: 'axis',
- textStyle: {
- width: '20px',
- overflow: 'truncate'
- },
- formatter: axiosFormatter,
- show: true,
- className: 'nz-chart-tooltip',
- extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
- },
- xAxis: {
- type: 'time',
- show: false
- },
- yAxis: {
- type: 'value',
- show: false
- },
- animation: false,
- grid: {
- left: 0,
- bottom: 2,
- top: 5,
- right: 0
- },
- color: chartColor,
- legend: {
- show: false
- },
- series: [
- {
- type: 'line',
- legendHoverLink: false,
- itemStyle: {
- normal: {
- lineStyle: {
- width: 2
- }
- }
- },
- data: [],
- showSymbol: false
- }
- ]
-}
-const relationShip = {
- grid: {
- left: 0,
- bottom: 50,
- top: 80,
- right: 0
- },
- series: [
- {
- type: 'graph',
- layout: 'force',
- symbolSize: 40,
- roam: true,
- force: {
- repulsion: 350
- },
- draggable: true,
- label: { show: true },
- edgeSymbol: ['none', 'arrow'],
- edgeSymbolSize: 7,
- data: [],
- links: []
- }
- ]
-}
-const sankey = {
- tooltip: {
- trigger: 'item',
- triggerOn: 'mousemove'
- },
- series: [
- {
- type: 'sankey',
- data: [],
- links: [],
- right: '5%',
- top: 50,
- bottom: 100,
- levels: [
- {
- depth: 0,
- itemStyle: {
- color: '#47D49C'
- },
- lineStyle: {
- color: '#999'
- }
- }, {
- depth: 1,
- itemStyle: {
- color: '#A69BF5'
- },
- lineStyle: {
- color: '#999'
- }
- }, {
- depth: 2,
- itemStyle: {
- color: '#73A0FA'
- },
- lineStyle: {
- color: '#999'
- }
- }
- ]
- }
- ]
-}
-const ipOpenPortBar = {
- xAxis: {
- type: 'category',
- axisTick: { show: false },
- axisLine: { show: false }
- },
- grid: {
- top: 30,
- left: 60,
- right: 50,
- bottom: 50
- },
- yAxis: {
- type: 'value',
- show: false
- },
- series: [{
- barWidth: 38,
- data: [],
- type: 'bar',
- label: { show: true, position: 'top' },
- barCategoryGap: '10%'
- }]
-}
-const categoryBar = {
- tooltip: {
- appendToBody: true,
- trigger: 'axis',
- textStyle: {
- width: '20px',
- overflow: 'truncate'
- },
- formatter: categoryVerticalFormatter,
- show: true,
- className: 'nz-chart-tooltip',
- extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
- },
- xAxis: {
- type: 'category',
- axisTick: { show: false },
- axisLine: { show: false }
- },
- grid: {
- top: 20,
- left: 10,
- right: 25,
- bottom: 20,
- containLabel: true
- },
- yAxis: {
- type: 'value',
- axisTick: { show: false },
- axisLine: { show: false }
- },
- color: chartColor,
- series: [{
- barWidth: 15,
- data: [],
- type: 'bar',
- label: { show: false },
- barCategoryGap: '10%',
- itemStyle: {
- color: function (params) {
- return getCharBartColor([params.dataIndex])
- }
- }
- }]
-}
-
-const timeBar = {
- tooltip: {
- appendToBody: true,
- trigger: 'axis',
- textStyle: {
- width: '20px',
- overflow: 'truncate'
- },
- formatter: timeVerticalFormatter,
- show: true,
- className: 'nz-chart-tooltip',
- extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
- },
- xAxis: {
- type: 'time',
- axisTick: { show: false },
- axisLine: { show: false },
- axisLabel: {
- interval: 0,
- // rotate: -40, //设置日期显示样式(倾斜度)
- formatter: function (value) { // 在这里写你需要的时间格式
- const t_date = new Date(value)
- return [t_date.getMonth() + 1, t_date.getDate()].join('/') + ' ' + [t_date.getHours(), t_date.getMinutes()].join(':')
- }
- }
- },
- grid: {
- top: 20,
- left: 25,
- right: 25,
- bottom: 20,
- containLabel: true
- },
- yAxis: {
- type: 'value',
- axisTick: { show: false },
- axisLine: { show: false },
- axisLabel: {
- formatter: function (value, index, a, b) {
- return unitConvert(value, unitTypes.number).join(' ')
- }
- },
- minInterval: 1
- },
- color: chartColor,
- series: [{
- barWidth: 15,
- data: [],
- type: 'bar',
- label: { show: false },
- barCategoryGap: '10%',
- itemStyle: {
- color: function (params) {
- return getCharBartColor([params.dataIndex])
- }
- }
- }]
-}
-const typeOptionMappings = [
- { value: 11, option: line }, // 常规折线图
- { value: 12, option: lineWithStatistics }, // 带统计表格的折线图
- { value: 13, option: lineStack }, // 折线堆叠图
- { value: 22, option: ipOpenPortBar }, // ip详情--开放端口的柱状图
- { value: 23, option: timeBar }, // 矿机所属单位
- { value: 24, option: categoryBar }, // 挖矿事件统计
- { value: 31, option: pieWithTable }, // 常规折线图
- { value: 33, option: ipHostedDomain }, // ip详情--托管域名
- { value: 34, option: ipHostedDomain }, // app详情--相关域名
- { value: 42, option: relationShip }, // 关系图
- { value: 43, option: sankey }, // 桑基图
- { value: 52, option: singleValueLine }
-]
-const typeCategory = {
- MAP: 'map',
- TABLE: 'table',
- ECHARTS: 'echarts',
- TITLE: 'title',
- SINGLE: 'singleValue',
- TABS: 'tabs'
-}
-export function getTypeCategory (type) {
- if (isMap(type)) {
- return typeCategory.MAP
- } else if (isEcharts(type)) {
- return typeCategory.ECHARTS
- } else if (isTable(type)) {
- return typeCategory.TABLE
- } else if (isSingleValue(type)) {
- return typeCategory.SINGLE
- } else if (isTitle(type)) {
- return typeCategory.TITLE
- } else if (isTabs(type)) {
- return typeCategory.TABS
- }
-}
-/* 柱状图:挖矿事件统计(time类型柱状图) */
-export function isEchartsTimeBar (type) {
- return type == 23
-}
-/* 柱状图:矿机所属单位(category类型柱状图) */
-export function isEchartsCategoryBar (type) {
- return type == 24
-}
-/* 饼图柱状图等 */
-export function isEcharts (type) {
- return type >= 11 && type <= 50
-}
-/* 地图 */
-export function isMap (type) {
- return type >= 1 && type <= 10
-}
-/* 连线地图 */
-export function isMapLine (type) {
- return type === 1
-}
-/* 色块地图 */
-export function isMapBlock (type) {
- return type === 2
-}
-/* 带统计的折线图 */
-export function isEchartsWithStatistics (type) {
- return type === 12
-}
-/* 关系图 */
-export function isRelationShip (type) {
- return type === 42
-}
-/* 桑基图 */
-export function isSankey (type) {
- return type === 43
-}
-/* 单值 */
-export function isSingleValue (type) {
- return type >= 51 && type <= 60
-}
-/* 带折线图的单值 */
-export function isSingleValueWithEcharts (type) {
- return type === 52
-}
-/* 带折线图的单值 */
-export function isSingleValueWithEchartsTemp (type) {
- return type === 55
-}
-/* 带Table的饼图 */
-export function isEchartsWithTable (type) {
- return type === 31
-}
-/* table */
-export function isTable (type) {
- return type >= 61 && type <= 70
-}
-/* table */
-export function isActiveIpTable (type) {
- return type == 63
-}
-/* title */
-export function isTitle (type) {
- return type === 93
-}
-/* tabs */
-export function isTabs (type) {
- return type === 91
-}
-/* IP实体基本信息 */
-export function isIpBasicInfo (type) {
- return type === 4
-}
-/* IP实体开放端口 */
-export function isIpOpenPort (type) {
- return type === 22
-}
-/* IP实体托管域名 */
-export function isIpHostedDomain (type) {
- return type === 33
-}
-/* APP实体相关域名 */
-export function isAppRelatedDomain (type) {
- return type === 34
-}
-/* APP实体基本信息 */
-export function isAppBasicInfo (type) {
- return type === 82
-}
-/* DOMAIN实体Whois */
-export function isDomainWhois (type) {
- return type === 83
-}
-/* DOMAIN实体DNS记录 */
-export function isDomainDnsRecord (type) {
- return type === 84
-}
-/* 近期挖矿事件 */
-export function isCryptocurrencyEventList (type) {
- return type === 85
-}
-/* 组 */
-export function isGroup (type) {
- return type === 94
-}
-/* 实体详情块 */
-export function isBlock (type) {
- return type === 95
-}
-export function getOption (type) {
- const mapping = typeOptionMappings.find(m => m.value === type)
- return mapping && mapping.option ? _.cloneDeep(mapping.option) : null
-}
-export const layoutConstant = {
- HEADER: 'header',
- FOOTER: 'footer'
-}
-export function getLayout (type) {
- const layout = []
- if (!isSingleValue(type) && !isTitle(type)) {
- layout.push(layoutConstant.HEADER)
- }
- if (type === 12 || type === 31) {
- layout.push(layoutConstant.FOOTER)
- }
- return layout
-}
-
-function tooLongFormatter (name) {
- return format.truncateText(name, 110, '12')
-}
-function axiosFormatter (params) {
- let str = '<div>'
- params.forEach((item, i) => {
- const tData = item.data[0]
- if (i === 0) {
- str += '<div style="margin-bottom: 5px">'
- str += window.$dayJs.tz(tData).format('YYYY-MM-DD HH:mm:ss')
- str += '</div>'
- }
- str += '<div class="cn-chart-tooltip-box">'
- str += item.marker
- str += `<span class="cn-chart-tooltip-content">
- ${item.seriesName}
- </span>`
- str += `<span class="cn-chart-tooltip-value">
- ${unitConvert(item.data[1], item.data[2]).join(' ')}
- </span>`
- str += '</div>'
- })
- str += '</div>'
- return str
-}
-
-export function timeVerticalFormatter (params) {
- let str = '<div>'
- params.forEach((item, i) => {
- const tData = item.data[0]
- if (i === 0) {
- str += '<div style="margin-bottom: 5px">'
- str += window.$dayJs.tz(tData).format('YYYY-MM-DD HH:mm:ss')
- str += '</div>'
- }
- str += '<div class="cn-chart-tooltip-box">'
- str += item.marker
- str += `<span class="cn-chart-tooltip-content">
- ${item.seriesName}
- </span>`
- str += `<span class="cn-chart-tooltip-value">
- ${unitConvert(item.data[1], item.data[2]).join(' ')}
- </span>`
- str += '</div>'
- })
- str += '</div>'
- return str
-}
-
-export function timeHorizontalFormatter (params) {
- let str = '<div>'
- params.forEach((item, i) => {
- const tData = item.data[1]
- if (i === 0) {
- str += '<div style="margin-bottom: 5px">'
- str += window.$dayJs.tz(tData).format('YYYY-MM-DD HH:mm:ss')
- str += '</div>'
- }
- str += '<div class="cn-chart-tooltip-box">'
- str += item.marker
- str += `<span class="cn-chart-tooltip-content">
- ${item.seriesName}
- </span>`
- str += `<span class="cn-chart-tooltip-value">
- ${unitConvert(item.data[0], item.data[2]).join(' ')}
- </span>`
- str += '</div>'
- })
- str += '</div>'
- return str
-}
-export function categoryHorizontalFormatter (params) {
- let str = '<div>'
- params.forEach((item, i) => {
- str += '<div class="cn-chart-tooltip-box">'
- str += item.data[1] + ': ' + item.data[0]
- str += '</div>'
- })
- str += '</div>'
- return str
-}
-export function categoryVerticalFormatter (params) {
- let str = '<div>'
- params.forEach((item, i) => {
- str += '<div class="cn-chart-tooltip-box">'
- str += item.data[0] + ': ' + item.data[1]
- str += '</div>'
- })
- str += '</div>'
- return str
-}
diff --git a/src/components/entities/EntityList.vue b/src/components/entities/EntityList.vue
index 35bea4cb..1fa3c9bc 100644
--- a/src/components/entities/EntityList.vue
+++ b/src/components/entities/EntityList.vue
@@ -126,8 +126,8 @@
import { get } from '@/utils/http'
import { api } from '@/utils/api'
import * as echarts from 'echarts'
-import { getChartColor, entityListLineOption } from '@/components/charts/chart-options'
-import { legendMapping } from '@/components/charts/chart-table-title'
+import { getChartColor, entityListLineOption } from '@/views/charts/charts/chart-options'
+import { legendMapping } from '@/views/charts/charts/chart-table-title'
import unitConvert from '@/utils/unit-convert'
import { unitTypes } from '@/utils/constants'
diff --git a/src/router/index.js b/src/router/index.js
index 30bc4aba..580d0ec9 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -11,6 +11,10 @@ const routes = [
component: () => import('@/views/entityExplorer/EntityDetail')
},
{
+ path: '/detections',
+ component: () => import('@/views/detections/Index')
+ },
+ {
path: '/',
component: () => import('@/components/layout/Home'),
children: [
diff --git a/src/views/charts/Chart.vue b/src/views/charts/Chart.vue
index 48bdd627..5ce07b18 100644
--- a/src/views/charts/Chart.vue
+++ b/src/views/charts/Chart.vue
@@ -1,630 +1,231 @@
<template>
- <!-- 标题 -->
- <div
- v-if="isTitle"
- class="cn-chart cn-chart__title"
- :style="computePosition">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</div>
- <!-- Tabs -->
- <el-tabs
- class="cn-chart cn-chart__tabs"
- v-else-if="isTabs"
- v-model="activeTab"
- @tab-click="changeTab"
- :style="computePosition"
- :ref="`chart-${chart.id}`"
- >
- <el-tab-pane
- v-for="tab in chartInfo.children"
- :label="tab.i18n ? $t(tab.i18n) : tab.name" :name="`${tab.id}`"
- :key="tab.id"
- :ref="`chart-${chart.id}`"
- >
- <template v-for="chart in tab.children">
- <chart
- v-if="activeTab == tab.id"
- :key="Chart.id"
- :chart="Chart"
- :time-filter="timeFilter"
- :ref="`chart-${Chart.id}`"
- :entity="entity"
- @getCurrentTimeRange="getCurrentTimeRange"
- ></chart>
- </template>
- </el-tab-pane>
- </el-tabs>
- <!-- 地图 -->
- <chart-map
- v-else-if="isMap"
- :style="computePosition"
- :loading="loading"
- :hide-header="hideHeader"
- >
- <template #chartErrorInfo>
- <chart-error
- :isError="isError"
- :errorInfo="errorInfo"
- >
- </chart-error>
- </template>
- <template #title>{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</template>
- <template #operations>
- <span class="header__operation-btn" v-show="showMapBackButton" @click="mapBack"><i class="cn-icon el-icon-back"></i></span>
- <el-popover trigger="hover" placement="top" :content="chartInfo.remark" v-if="chartInfo.remark">
- <template #reference>
- <span class="header__operation-btn"><i class="cn-icon el-icon-info"></i></span>
- </template>
- </el-popover>
- <span class="header__operation-btn" @click="refresh"><i class="cn-icon cn-icon-refresh"></i></span>
- </template>
- <template #default>
- <template v-if="isIpBasicInfo">
- <el-descriptions :column="1">
- <el-descriptions-item label="ASN:">{{detailData.asn || '-'}}</el-descriptions-item>
- <el-descriptions-item label="AS Org:">{{detailData.asOrganization || '-'}}</el-descriptions-item>
- <el-descriptions-item :label="$t('entities.asSubnet') + ':'">{{detailData.asSubnet || '-'}}</el-descriptions-item>
- <el-descriptions-item label="ISP:">{{detailData.isp || '-'}}</el-descriptions-item>
- <el-descriptions-item label="DNS PTR:">{{detailData.dnsPtr || '-'}}</el-descriptions-item>
- </el-descriptions>
- <div class="chart-location">
- <el-descriptions :column="1">
- <el-descriptions-item :label="$t('overall.location') + ':'">{{location}}</el-descriptions-item>
- </el-descriptions>
- <div class="chart-drawing" style="padding: 0 36px 30px 0;" :id="`chart${chartInfo.id}`"></div>
- </div>
- </template>
- <template v-else>
- <div class="chart-drawing" :id="`chart${chartInfo.id}`"></div>
- </template>
- </template>
- </chart-map>
- <!-- echarts类的图,如饼图、柱状图、折线图等 -->
- <echarts-frame
- v-else-if="isEcharts"
- :layout="layout"
- :style="computePosition"
- :chartInfo="chartInfo"
- :loading="loading"
- :no-data="noData"
- >
- <template #chartErrorInfo>
- <chart-error
- :isError="isError"
- :errorInfo="errorInfo"
- >
- </chart-error>
- </template>
- <template #title v-if="layout.indexOf(layoutConstant.HEADER) > -1" >
- {{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}
- </template>
- <template #operations v-if="layout.indexOf(layoutConstant.HEADER) > -1">
- <div class="header__operation header__operation--echarts" v-if="chart.type === 31">
- <el-select
- size="mini"
- v-model="orderPieTable"
- class="option__select select-column"
- placeholder=""
- popper-class="option-popper is-light"
- @change="orderPieTableChange"
- >
- <el-option v-for="item in chartPieTableTopOptions" :key="item.value" :value="item.value">&nbsp{{item.name}}</el-option>
- </el-select>
- </div>
- <el-popover trigger="hover" placement="top" :content="chartInfo.remark" v-if="chartInfo.remark">
- <template #reference>
- <span class="header__operation-btn"><i class="cn-icon el-icon-info"></i></span>
- </template>
- </el-popover>
- <span class="header__operation-btn" @click="refresh" ><i class="cn-icon cn-icon-refresh"></i></span>
- </template>
- <template #default>
- <!-- IP详情 开放端口 -->
- <template v-if="isIpOpenPort">
- <div class="ip-detail__open-port">
- <div class="open-port__table">
- <div style="height: 100%; overflow: hidden auto;">
- <div class="open-port__table-row open-port__table-row--header">
- <div class="open-port__table-cell" style="min-width: 100px;">Port</div>
- <div class="open-port__table-cell" style="min-width: 130px;">{{$t('overall.protocol')}}</div>
- <div class="open-port__table-cell">Banner</div>
- <div class="open-port__table-cell" style="min-width: 200px;">Update at</div>
- </div>
- <div class="open-port__table-row" v-for="(data, index) in detailData" :key="index">
- <div class="open-port__table-cell">{{data.port || '-'}}</div>
- <div class="open-port__table-cell">{{data.protocol || '-'}}</div>
- <div class="open-port__table-cell">{{data.banner || '-'}}</div>
- <div class="open-port__table-cell">{{data.utime || '-'}}</div>
- </div>
- </div>
- </div>
- <div class="open-port__chart">
- <div class="open-port__chart-title">{{$t('overall.protocolsStatistics')}}</div>
- <div class="open-port__chart-body chart-drawing" :id="`chart${chartInfo.id}`"></div>
- </div>
- </div>
- </template>
- <!-- IP详情 托管域名 -->
- <template v-else-if="isIpHostedDomain">
- <div class="ip-detail__hosted-domain">
- <div class="hosted-domain__list">
- <div class="hosted-domain__list-title">{{$t('overall.domain')}}</div>
- <div class="hosted-domain__list-body">
- <div class="hosted-domain__list-row" v-for="(data, i) in detailData" :key="i">{{data}}</div>
- </div>
- </div>
- <div class="hosted-domain__chart">
- <div>
- <div class="hosted-domain__chart-title">{{$t('entities.byCategory')}}</div>
- <div class="chart-drawing" :id="`chart${chartInfo.id}-0`"></div>
- </div>
- <div>
- <div class="hosted-domain__chart-title">{{$t('entities.byCredit')}}</div>
- <div class="chart-drawing" :id="`chart${chartInfo.id}-1`"></div>
- </div>
- </div>
- </div>
- </template>
- <!-- APP详情 关联域名 -->
- <template v-else-if="isAppRelatedDomain">
- <div class="app-detail__related-domain">
- <div class="related-domain__list">
- <div class="related-domain__list-title">{{$t('overall.domain')}}</div>
- <div class="related-domain__list-body">
- <div class="related-domain__list-row" v-for="(data, i) in detailData" :key="i"><i class="cn-icon cn-icon-domain"></i>&nbsp;{{data}}</div>
- </div>
- </div>
- <div class="related-domain__chart">
- <div>
- <div class="related-domain__chart-title">{{$t('entities.byCategory')}}</div>
- <div class="chart-drawing" :id="`chart${chartInfo.id}-0`"></div>
- </div>
- <div>
- <div class="related-domain__chart-title">{{$t('entities.byCredit')}}</div>
- <div class="chart-drawing" :id="`chart${chartInfo.id}-1`"></div>
- </div>
- </div>
- </div>
- </template>
- <template v-else-if="isSankey">
- <div class="sankey-box">
- <div class="chart-drawing" :id="`chart${chartInfo.id}`"></div>
- <div class="sankey__label" style="left: 5%;">{{$t('entities.inboundLinkId')}}</div>
- <div class="sankey__label" style="left: 50%;">{{entity.ip || entity.domain || entity.app}}</div>
- <div class="sankey__label" style="right: 5%; transform: translateX(50%)">{{$t('entities.outboundLinkId')}}</div>
- </div>
- </template>
- <div v-else class="chart-drawing" :id="`chart${chartInfo.id}`"></div>
- </template>
- <template #footer v-if="layout.indexOf(layoutConstant.FOOTER) > -1">
- <!-- 带Table的饼图,展示Table -->
- <template v-if="isEchartsWithTable">
- <pie-table :tableData="pieTableData" ref="pieTable" :chartInfo="chartInfo" :time-filter="timeFilter" :order="orderPieTable"/>
- </template>
- <template v-else-if="isEchartsWithStatistics">
- <statistics-legend :data="statisticsData" :chart-info="chartInfo" @toggleLegend="toggleStatisticsLegend"></statistics-legend>
- </template>
- </template>
- </echarts-frame>
- <!-- 单值图 -->
- <single-value
- v-else-if="isSingleValue"
- :type="chartInfo.type"
- :style="computePosition"
- :icon="singleValue.icon"
- :color="singleValue.color"
- :loading="loading"
- >
- <template #chartErrorInfo>
- <chart-error
- :isError="isError"
- :errorInfo="errorInfo"
- >
- </chart-error>
- </template>
- <template #title>
- <span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span>
- <span
- v-if="chartInfo.params && chartInfo.params.as"
- class="ip-detail-as"
- >
- as&nbsp;<span style="text-transform: capitalize">{{chartInfo.params.as}}</span>
- </span>
- </template>
- <template #data>
- <span>{{handleSingleValue[0] || handleSingleValue[0] === 0 ? handleSingleValue[0] : '-'}}</span>
- <span class="single-value__unit">{{handleSingleValue[1]}}</span>
- </template>
- <template #chart>
- <div class="chart-drawing" :id="`chart${chartInfo.id}`"></div>
- </template>
- </single-value>
- <!-- 表格:Cryptocurrency活跃IP -->
- <chart-table-active-ip
- v-else-if="isActiveIpTable"
- :table-data="activeIpTable.tableData"
- :style="computePosition"
- :loading="loading"
- :no-data="noData"
- >
- <template #chartErrorInfo>
- <chart-error
- :isError="isError"
- :errorInfo="errorInfo"
- >
- </chart-error>
- </template>
- <template #title>{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</template>
- <template #operations>
- <el-popover trigger="hover" placement="top" :content="chartInfo.remark" v-if="chartInfo.remark">
- <template #reference>
- <span class="header__operation-btn"><i class="cn-icon el-icon-info"></i></span>
- </template>
- </el-popover>
- <div class="header__operation header__operation--table">
- <el-select
- size="mini"
- v-model="activeIpTable.orderBy"
- class="option__select select-column"
- :placeholder="$t('overall.field')"
- popper-class="option-popper"
- @change="activeIpTableLimitChange"
- >
- <template v-for="item in chartActiveIpTableOrderOptions" :key="item">
- <el-option :value="item">{{item}}</el-option>
- </template>
- </el-select>
- </div>
- <span class="header__operation-btn" @click="refresh"><i class="cn-icon cn-icon-refresh"></i></span>
- </template>
- </chart-table-active-ip>
- <!-- 表格 -->
- <chart-table
- v-else-if="isTable"
- :table-columns="table.tableColumns"
- :table-data="table.currentPageData"
- :style="computePosition"
- :loading="loading"
- :no-data="noData"
- >
- <template #chartErrorInfo>
- <chart-error
- :isError="isError"
- :errorInfo="errorInfo"
- >
- </chart-error>
- </template>
- <template #title>{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</template>
- <template #operations>
- <el-popover trigger="hover" placement="top" :content="chartInfo.remark" v-if="chartInfo.remark">
- <template #reference>
- <span class="header__operation-btn"><i class="cn-icon el-icon-info"></i></span>
- </template>
- </el-popover>
- <div class="header__operation header__operation--table">
- <el-select
- size="mini"
- v-model="table.limit"
- class="option__select select-topn"
- placeholder=""
- popper-class="option-popper"
- @change="tableLimitChange"
- >
- <el-option v-for="item in chartTableTopOptions" :key="item" :value="item">TOP&nbsp;{{item}}</el-option>
- <template #prefix>TOP&nbsp;</template>
- </el-select>
- </div>
- <div class="header__operation header__operation--table">
- <el-select
- size="mini"
- v-model="table.orderBy"
- class="option__select select-column"
- :placeholder="$t('overall.field')"
- popper-class="option-popper"
- @change="tableLimitChange"
- >
- <template v-for="(item, index) in table.tableColumns" :key="item.prop">
- <el-option v-if="index > 0" :value="item.prop">{{item.prop}}</el-option>
- </template>
- </el-select>
- </div>
- <span class="header__operation-btn" @click="refresh"><i class="cn-icon cn-icon-refresh"></i></span>
-<!-- <div class="header__operation header__operation&#45;&#45;table">
- <span class="option__button"><i class="cn-icon cn-icon-style"></i></span>
- <div class="icon-group-divide"></div>
- <span class="option__button"><i class="cn-icon cn-icon-dropdown"></i></span>
- </div>
- <div class="header__operation header__operation--table">
- <span class="option__button"><i class="cn-icon cn-icon-full-screen"></i></span>
- </div>-->
- </template>
- <template #footer>
- <chart-table-pagination
- ref="tablePagination"
- :total="table.tableData.length"
- @pageJump="pageJump"
- ></chart-table-pagination>
- </template>
- </chart-table>
- <!-- group -->
- <div
- v-else-if="isGroup"
- class="cn-chart cn-chart__group"
- :style="computePosition"
- >
- <div class="cn-chart__header">
- <chart-error
- :isError="isError"
- :errorInfo="errorInfo"
- >
- </chart-error>
- <div class="header__title">
- <span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span>
- <span
- v-if="chartInfo.params && chartInfo.params.as"
- class="ip-detail-as"
- >
- as&nbsp;<span style="text-transform: capitalize">{{chartInfo.params.as}}</span>
- </span>
- </div>
- </div>
- <div class="cn-chart__body">
- <template v-for="chart in chartInfo.children" :key="Chart.id">
- <chart
- :chart="Chart"
- :time-filter="timeFilter"
- :ref="`chart-${Chart.id}`"
- :entity="entity"
- :parent-data="groupData"
- :from-block="fromBlock"
- @getChartCurrentTimeRange="getChartCurrentTimeRange"
- ></chart>
- </template>
- </div>
- </div>
- <!-- block -->
- <div
- v-else-if="isBlock"
- class="cn-chart cn-chart__block"
- :style="computePosition"
- :id="chartInfo.params && chartInfo.params.anchorPoint"
- >
- <div class="cn-chart__header">
- <chart-error
- :isError="isError"
- :errorInfo="errorInfo"
- >
- </chart-error>
- <div class="header__title">
- <span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span>
- <div style="top: 18px;" class="panel__time" v-if="chartInfo.params && chartInfo.params.showTimeTool">
- <DateTimeRange class="date-time-range" :start-time="chartTimeFilter.startTime" :end-time="chartTimeFilter.endTime" ref="dateTimeRange" @change="reload"/>
- <TimeRefresh class="date-time-range" @change="timeRefreshChange" :end-time="chartTimeFilter.endTime"/>
- </div>
- </div>
- </div>
- <div class="cn-chart__body">
- <template v-for="chart in chartInfo.children" :key="Chart.id">
- <chart
- :chart="Chart"
- :time-filter="chartTimeFilter"
- :ref="`chart-${Chart.id}`"
- :entity="entity"
- :parent-data="groupData"
- :from-block="true"
- @getChartCurrentTimeRange="getChartCurrentTimeRange"
- ></chart>
- </template>
- </div>
- </div>
- <!-- Domain详情-whois -->
- <div
- v-else-if="isDomainWhois"
- class="cn-chart cn-chart__whois"
- :style="computePosition"
- >
- <div class="cn-chart__header">
- <chart-error
- :isError="isError"
- :errorInfo="errorInfo"
- >
- </chart-error>
- <div class="header__title">
- <span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span>
- </div>
- </div>
- <div class="cn-chart__body">
- <div class="domain-detail-list">
- <div class="domain-detail-list__row">
- <div class="domain-detail-list__label">{{$t('entities.sponsor')}}</div>
- <div class="domain-detail-list__content">{{detailData.registrar || '-'}}</div>
- </div>
- <div class="domain-detail-list__row">
- <div class="domain-detail-list__label">{{$t('entities.org')}}</div>
- <div class="domain-detail-list__content">{{detailData.org || '-'}}</div>
- </div>
- <div class="domain-detail-list__row">
- <div class="domain-detail-list__label">Email</div>
- <div class="domain-detail-list__content">{{detailData.postcode || '-'}}</div>
- </div>
- <div class="domain-detail-list__row">
- <div class="domain-detail-list__label">{{$t('overall.country')}}</div>
- <div class="domain-detail-list__content">{{detailData.country || '-'}}</div>
- </div>
- <div class="domain-detail-list__row">
- <div class="domain-detail-list__label">{{$t('entities.creationDate')}}</div>
- <div class="domain-detail-list__content">{{detailData.createTime ? parseMsDate(detailData.createTime) : '-'}}</div>
- </div>
- <div class="domain-detail-list__row">
- <div class="domain-detail-list__label">{{$t('entities.expirationDate')}}</div>
- <div class="domain-detail-list__content">{{detailData.expirationTime ? parseMsDate(detailData.expirationTime) : '-'}}</div>
- </div>
- </div>
- </div>
- </div>
- <!-- Domain详情-DNS记录 -->
- <div
- v-else-if="isDomainDnsRecord"
- class="cn-chart cn-chart__dns-record"
- :style="computePosition"
- >
- <div class="cn-chart__header">
- <chart-error
- :isError="isError"
- :errorInfo="errorInfo"
- >
- </chart-error>
- <div class="header__title">
- <span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span>
- </div>
- </div>
- <div class="cn-chart__body">
- <div class="entity-detail__dns-record">
- <div class="dns-record__table">
- <div style="height: 100%; overflow: hidden auto;">
- <div class="dns-record__table-row dns-record__table-row--header">
- <div class="dns-record__table-cell" style="min-width: 200px;">Type</div>
- <div class="dns-record__table-cell" style="width: 100%;">Value</div>
- </div>
- <div class="dns-record__table-row" v-for="(data, index) in detailData" :key="index">
- <div class="dns-record__table-cell">{{data.type || '-'}}</div>
- <div class="dns-record__table-cell">{{data.value || '-'}}</div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- Cryptocurrency EventList :近期挖矿事件-->
- <div v-else-if="isCryptocurrencyEventList"
- class="cn-chart cn-chart__table"
- :style="computePosition"
- >
- <div class="cn-chart__header" >
- <chart-error
- :isError="isError"
- :errorInfo="errorInfo"
- >
- </chart-error>
- <div class="header__title" >
- <span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span>
- </div>
-
- <span class="header__operations header__operation-btn" @click="refresh"><i class="cn-icon cn-icon-refresh"></i></span>
- </div>
- <div class="chart__loading" v-show="loading">
- <i class="el-icon-loading"></i>
- </div>
- <div class="cn-chart__body" v-no-data="noData">
- <div class="crypto-eventList__record">
- <div class="record__table">
- <div style="height: 100%; overflow: hidden auto;">
- <div class="record__table-row" v-for="(data, index) in croptyEventList" :key="index">
- <div class="record__table-cell">
- <div class="circle1" style=""></div>
- </div>
- <div class="record__table-cell">
- {{data.message || '-'}}:{{data.serverIP || '-'}}<br/>
- <span class="record_second" > {{data.time || '-'}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{data.clientIP || '-'}}&nbsp;&nbsp;&nbsp; </span>
- <div class="record_second arrow arrow-hor right"> </div>
- <span class="record_second">&nbsp;&nbsp;&nbsp; {{data.serverIP || '-'}}</span>
- </div>
+ <div class="cn-chart">
+ <loading :loading="loading && !isTabs && !isBlock && !isGroup"></loading>
+ <chart-no-data v-if="isNoData"></chart-no-data>
+ <template v-else>
+
+ <chart-tabs
+ v-if="isTabs"
+ :chart-info="chartInfo"
+ :query-params="queryParams"
+ :entity="entity"
+ ></chart-tabs>
+
+ <chart-map
+ v-else-if="isMap && !isIpBasicInfo"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :query-params="queryParams"
+ :entity="entity"
+ @showLoading="showLoading"
+ ></chart-map>
+
+ <chart-single-value
+ v-else-if="isSingleValue"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :query-params="queryParams"
+ @showLoading="showLoading"
+ ></chart-single-value>
+
+ <chart-block
+ v-else-if="isBlock"
+ ref="chart"
+ :timeFilter="queryParams"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :entity="entity"
+ ></chart-block>
+
+ <chart-group
+ v-else-if="isGroup"
+ :timeFilter="queryParams"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :entity="entity"
+ ></chart-group>
+
+ <ip-basic-info
+ v-else-if="isIpBasicInfo"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :entity="entity"
+ ></ip-basic-info>
+
+ <chart-time-bar
+ v-else-if="isEchartsTimeBar"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :result-type="resultType"
+ :query-params="queryParams"
+ @showLoading="showLoading"
+ ></chart-time-bar>
+
+ <chart-category-bar
+ v-else-if="isEchartsCategoryBar"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :result-type="resultType"
+ :query-params="queryParams"
+ @showLoading="showLoading"
+ ></chart-category-bar>
+
+ <chart-ip-open-port-bar
+ v-else-if="isIpOpenPortBar"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :result-type="resultType"
+ :query-params="queryParams"
+ @showLoading="showLoading"
+ ></chart-ip-open-port-bar>
+
+ <chart-table
+ v-else-if="isTable && isCurrentTable"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :table="table"
+ :query-params="queryParams"
+ @showLoading="showLoading"
+ ></chart-table>
+
+ <chart-active-ip-table
+ v-else-if="isActiveIpTable"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :table="table"
+ :query-params="queryParams"
+ ></chart-active-ip-table>
+
+ <chart-app-basic-info
+ v-else-if="isAppBasicInfo"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :query-params="queryParams"
+ ></chart-app-basic-info>
+
+ <chart-domain-whois
+ v-else-if="isDomainWhois"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :query-params="queryParams"
+ ></chart-domain-whois>
+
+ <chart-domain-dns-record
+ v-else-if="isDomainDnsRecord"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :query-params="queryParams"
+ ></chart-domain-dns-record>
+
+ <chart-cryptocurrency-event-list
+ v-else-if="isCryptocurrencyEventList"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :query-params="queryParams"
+ ></chart-cryptocurrency-event-list>
+
+ <chart-relation-ship
+ v-else-if="isRelationShip"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :query-params="queryParams"
+ ></chart-relation-ship>
+
+ <chart-san-key
+ v-else-if="isSankey"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :query-params="queryParams"
+ :entity="entity"
+ ></chart-san-key>
+
+ <chart-echart
+ v-else-if="isEchartsLine || isEchartsPie"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :result-type="resultType"
+ @showLoading="showLoading"
+ ></chart-echart>
+
+ <chart-echart-with-statistics
+ v-else-if="isEchartsWithStatistics"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :result-type="resultType"
+ @showLoading="showLoading"
+ ></chart-echart-with-statistics>
+
+ <chart-echart-with-table
+ v-else-if="isEchartsWithTable"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ :query-params="queryParams"
+ :result-type="resultType"
+ :order-pie-table="orderPieTable"
+ @showLoading="showLoading"
+ ></chart-echart-with-table>
+
+ <chart-echart-ip-hosted-domain
+ v-else-if="isIpHostedDomain"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ @showLoading="showLoading"
+ :entity="entity"
+ ></chart-echart-ip-hosted-domain>
+
+ <chart-echart-app-relate-domain
+ v-else-if="isAppRelatedDomain"
+ :chart-info="chartInfo"
+ :chart-data="chartData"
+ @showLoading="showLoading"
+ :entity="entity"
+ ></chart-echart-app-relate-domain>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- APP详情-基本信息 -->
- <div
- v-else-if="isAppBasicInfo"
- class="cn-chart cn-chart__app-basic"
- :style="computePosition"
- >
- <div class="cn-chart__header">
- <chart-error
- :isError="isError"
- :errorInfo="errorInfo"
- >
- </chart-error>
- <div class="header__title">
- <span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span>
- </div>
- </div>
- <div class="cn-chart__body">
- <div style="display: flex; justify-content: space-between; width: 100%;">
- <el-descriptions :column="1" style="padding: 20px 30px;">
- <el-descriptions-item :label="$t('overall.appName') + ':'">{{detailData.name || '-'}}</el-descriptions-item>
- <el-descriptions-item :label="$t('overall.appFullName') + ':'">{{detailData.allName || '-'}}</el-descriptions-item>
- <el-descriptions-item :label="$t('overall.technology') + ':'">{{detailData.tech || '-'}}</el-descriptions-item>
- <el-descriptions-item :label="$t('overall.remark') + ':'">{{detailData.description || '-'}}</el-descriptions-item>
- </el-descriptions>
- <div style="display: flex;">
- <single-value
- :type="51"
- icon="cn-icon cn-icon-category"
- :loading="false"
- style="width: 250px;"
- >
- <template #title>
- <span>{{$t('entities.category')}}</span>
- </template>
- <template #data>
- <span>{{detailData.category ? detailData.category : '-'}}</span>
- </template>
- </single-value>
- <single-value
- :type="51"
- icon="cn-icon cn-icon-sub-category"
- :loading="false"
- style="width: 250px;"
- >
- <template #title>
- <span>{{$t('entities.subcategory')}}</span>
- </template>
- <template #data>
- <span>{{detailData.subcategory ? detailData.subcategory : '-'}}</span>
- </template>
- </single-value>
- <single-value
- :type="51"
- icon="cn-icon cn-icon-credit"
- :loading="false"
- style="width: 250px;"
- >
- <template #title>
- <span>{{$t('entities.reputationLevel')}}</span>
- </template>
- <template #data>
- <span>{{detailData.risk ? detailData.risk : '-'}}</span>
- </template>
- </single-value>
- </div>
- </div>
- </div>
+ </template>
</div>
</template>
<script>
-import * as echarts from 'echarts'
-import * as am4Core from '@amcharts/amcharts4/core'
-import * as am4Maps from '@amcharts/amcharts4/maps'
-import { ref, shallowRef } from 'vue'
-import { tableTitleMapping, legendMapping } from '@/components/charts/chart-table-title'
+import Loading from '@/components/common/Loading'
+import ChartNoData from '@/views/charts/charts/ChartNoData'
+import ChartTabs from '@/views/charts/charts/ChartTabs'
+import ChartMap from '@/views/charts/charts/ChartMap'
+import ChartSingleValue from '@/views/charts/charts/ChartSingleValue'
+import ChartBlock from '@/views/charts/charts/ChartBlock'
+import ChartGroup from '@/views/charts/charts/ChartGroup'
+import IpBasicInfo from '@/views/charts/charts/IpBasicInfo'
+import ChartEchart from '@/views/charts/charts/ChartEchart'
+import ChartEchartWithStatistics from '@/views/charts/charts/ChartEchartWithStatistics'
+import ChartEchartWithTable from '@/views/charts/charts/ChartEchartWithTable'
+import ChartEchartIpHostedDomain from '@/views/charts/charts/ChartEchartIpHostedDomain'
+import ChartEchartAppRelateDomain from '@/views/charts/charts/ChartEchartAppRelateDomain'
+import ChartActiveIpTable from '@/views/charts/charts/ChartActiveIpTable'
+import ChartTimeBar from './charts/ChartTimeBar'
+import ChartCategoryBar from './charts/ChartCategoryBar'
+import ChartIpOpenPortBar from './charts/ChartIpOpenPortBar'
+import ChartTable from './charts/ChartTable'
+import ChartAppBasicInfo from '@/views/charts/charts/ChartAppBasicInfo'
+import ChartDomainWhois from '@/views/charts/charts/ChartDomainWhois'
+import ChartDomainDnsRecord from '@/views/charts/charts/ChartDomainDnsRecord'
+import ChartCryptocurrencyEventList from '@/views/charts/charts/ChartCryptocurrencyEventList'
+import ChartRelationShip from '@/views/charts/charts/ChartRelationShip'
+import ChartSanKey from '@/views/charts/charts/ChartSanKey'
import {
isEcharts,
+ isEchartsLine,
isSingleValue,
isTable,
+ isCurrentTable,
isActiveIpTable,
isTitle,
isMap,
getOption,
- getTypeCategory,
- getLayout,
- layoutConstant,
+ isEchartsPie,
isEchartsWithTable,
isEchartsWithStatistics,
isEchartsTimeBar,
isEchartsCategoryBar,
+ isIpOpenPortBar,
isMapLine,
isMapBlock,
isSingleValueWithEcharts,
@@ -641,1748 +242,117 @@ import {
isCryptocurrencyEventList,
isAppBasicInfo,
isAppRelatedDomain,
- getChartColor, chartBarColor, timeVerticalFormatter, timeHorizontalFormatter,
- categoryHorizontalFormatter, categoryVerticalFormatter, getCharBartColor, isBlock
-} from '@/components/charts/chart-options'
-import ChartError from '@/components/charts/ChartError'
-import EchartsFrame from '@/components/charts/EchartsFrame'
-import SingleValue from '@/components/charts/ChartSingleValue'
-import ChartTable from '@/components/charts/ChartTable'
-import ChartTableActiveIp from '@/components/charts/ChartTableActiveIp'
-import ChartMap from '@/components/charts/ChartMap'
-import PieTable from '@/components/charts/PieTable'
-import StatisticsLegend from '@/components/charts/StatisticsLegend'
-import ChartTablePagination from '@/components/charts/ChartTablePagination'
-import unitConvert, { getUnitType, valueToRangeValue } from '@/utils/unit-convert'
-import { chartTableDefaultPageSize, chartTableTopOptions, chartActiveIpTableOrderOptions, storageKey, chartPieTableTopOptions, unitTypes } from '@/utils/constants'
-import { get, post } from '@/utils/http'
-import { replaceUrlPlaceholder, getCapitalGeo, getGeoData, lineToSpace } from '@/utils/tools'
-import { HeatLegend } from '@/components/amcharts/heatLegend'
-import DateTimeRange from '@/components/common/TimeRange/DateTimeRange'
-import TimeRefresh from '@/components/common/TimeRange/TimeRefresh'
-
-import * as L from 'leaflet'
-import 'leaflet/dist/leaflet.css'
-import icon from 'leaflet/dist/images/marker-icon.png'
-import iconShadow from 'leaflet/dist/images/marker-shadow.png'
-import { getNowTime } from '@/utils/date-util'
+ isBlock
+} from './charts/tools'
+import _ from 'lodash'
export default {
- name: 'Chart',
- props: {
- chart: Object, // 图表对象,包括id、name、type等数据
- timeFilter: Object,
- parentData: Object,
- fromBlock: Boolean,
- hideHeader: Boolean,
- entity: {
- type: Object,
- default: () => {}
- }
- },
+ name: 'chart',
components: {
- EchartsFrame,
- SingleValue,
- ChartTablePagination,
+ ChartSanKey,
+ ChartCryptocurrencyEventList,
+ ChartDomainDnsRecord,
+ ChartDomainWhois,
+ ChartAppBasicInfo,
+ ChartActiveIpTable,
ChartTable,
- ChartTableActiveIp,
- PieTable,
- StatisticsLegend,
+ IpBasicInfo,
+ ChartSingleValue,
+ Loading,
+ ChartNoData,
+ ChartTabs,
ChartMap,
- ChartError,
- DateTimeRange,
- TimeRefresh
+ ChartBlock,
+ ChartTimeBar,
+ ChartCategoryBar,
+ ChartIpOpenPortBar,
+ ChartRelationShip,
+ ChartGroup,
+ ChartEchartWithStatistics,
+ ChartEchart,
+ ChartEchartWithTable,
+ ChartEchartIpHostedDomain,
+ ChartEchartAppRelateDomain
},
- data () {
- return {
- table: {
- pageSize: chartTableDefaultPageSize,
- limit: chartTableTopOptions[0], // top-n
- orderBy: 'sessions',
- tableColumns: [], // table字段
- tableData: [], // table的所有数据
- currentPageData: [] // table当前页的数据
- },
-
- activeIpTable: {
- orderBy: 'machine',
- tableData: [
- {
- name: '192.168.20.21',
- num: 111
-
- }, {
- name: '192.168.20.22',
- num: 345
- }, {
- name: '192.168.20.23',
- num: 111
-
- }, {
- name: '192.168.20.24',
- num: 345
- }, {
- name: '192.168.20.25',
- num: 111
-
- }, {
- name: '192.168.20.26',
- num: 345
- }
- ] // table的所有数据
- },
- pieTableData: [],
- singleValue: {
- value: '-',
- icon: '',
- color: ''
- },
- showMapBackButton: false, // 下钻之后控制是否显示返回上一层按钮
- standaloneTimeRange: { // 单个图表刷新时,重新获取时间范围,且不影响到其他图
- use: false,
- startTime: '',
- endTime: ''
- },
- queryTimeRange: { // 实际查询接口时使用的时间
- startTime: '',
- endTime: ''
- },
- activeTab: '',
- groupData: '', // group类型的查询数据,用于传递给子chart,子chart通过params.dataKey取值
- detailData: '', // 详情类型图表的数据
- croptyEventList: [],
- statisticsData: [],
- orderPieTable: chartPieTableTopOptions[0].value,
- selectPieChartName: '',
- allSelectPieChartName: [],
- chartOption: null,
- loading: true,
- noData: false, // 查询结果为空
- noData0: false, // 单chart内含多图表时使用
- noData1: false,
- throttle: null, // 节流器
- isError: false, // 接口响应是否报错
- errorInfo: '', // 接口具体错误信息
- polygonSeries: null, // 世界地图series
- countrySeries: null, // 下钻国家series
- baseMapSeriesName: ['Container', 'MapChart'],
- mapPictureUrl: '/Tiles/{z}/{x}/{y}.png'
- }
+ props: {
+ chartInfo: Object,
+ chartData: [Object, Array, String], // 数据在父组件查询后传入,本组件内不查询,只根据接传递的数据来渲染
+ resultType: Object, // 返回数据的类型
+ queryParams: Object, // 接口请求参数
+ customChartOption: Object, // 需要自定义echarts的option时传入,非必须;传入该值时仍需传对应格式的chartData
+ isFullscreen: Boolean,
+ loading: Boolean,
+ panelLock: Boolean,
+ entity: Object,
+ isError: Boolean,
+ table: Object,
+ orderPieTable: Object
},
- methods: {
- initChart () {
- this.loading = true
- if (this.standaloneTimeRange.use) {
- this.queryTimeRange = { startTime: parseInt(this.standaloneTimeRange.startTime / 1000), endTime: parseInt(this.standaloneTimeRange.endTime / 1000) }
- } else if (this.timeFilter) {
- this.queryTimeRange = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000) }
- } else {
- this.queryTimeRange = { startTime: parseInt(this.chartTimeFilter.startTime / 1000), endTime: parseInt(this.chartTimeFilter.endTime / 1000) }
- }
- try {
- const chartParams = this.chartInfo.params
- if (this.isMap) {
- this.initMap(`chart${this.chartInfo.id}`)
- if (chartParams) {
- this.isIpBasicInfo ? this.loadLeafletMap() : this.loadAm4ChartMap(this.polygonSeries)
- }
- // TODO 优化:缓存地图,重新查询时只更改数据,不再次初始化
- } else if (this.isEcharts) {
- if (this.isIpHostedDomain || this.isAppRelatedDomain) {
- const dom = document.getElementById(`chart${this.chartInfo.id}-0`)
- const dom2 = document.getElementById(`chart${this.chartInfo.id}-1`)
- !this.myChart && (this.myChart = echarts.init(dom))
- !this.myChart2 && (this.myChart2 = echarts.init(dom2))
- } else {
- const dom = document.getElementById(`chart${this.chartInfo.id}`)
- !this.myChart && (this.myChart = echarts.init(dom))
- }
- this.chartOption = this.$_.cloneDeep(getOption(this.chart.type))
- if (chartParams) {
- if (this.isEchartsWithTable) {
- this.initEchartsWithPieTable(chartParams)
- } else if (this.isEchartsWithStatistics) {
- this.initEchartsWithStatistics(chartParams)
- } else if (this.isRelationShip) {
- this.initRelationShip(chartParams)
- } else if (this.isSankey) {
- this.initSankey(chartParams)
- } else if (this.isIpOpenPort) {
- this.initIpOpenPort(chartParams)
- } else if (this.isIpHostedDomain) {
- this.initIpHostedDomain(chartParams)
- } else if (this.isAppRelatedDomain) {
- this.initAppRelatedDomain(chartParams)
- } else if (this.isEchartsTimeBar) {
- this.initEchartsTimeBar(chartParams)
- } else if (this.isEchartsCategoryBar) {
- this.initEchartsCategoryBar(chartParams)
- } else {
- this.initECharts(chartParams)
- }
- }
- } else if (this.isActiveIpTable) {
- this.initChartActiveIpTable(chartParams)
- } else if (this.isTable) {
- if (chartParams) {
- this.initChartTable(chartParams)
- }
- } else if (this.isSingleValue) {
- if (chartParams) {
- this.singleValue.icon = chartParams.icon
- if (chartParams.color) {
- this.singleValue.color = chartParams.color
- }
- const gotData = new Promise(resolve => {
- let result = ''
- if (chartParams.dataKey) {
- if (this.parentData && (this.parentData[chartParams.dataKey] || this.parentData[chartParams.dataKey] === 0)) {
- result = this.parentData[chartParams.dataKey]
- } else {
- this.noData = true
- }
- resolve(result)
- } else {
- const queryParams = { ...this.queryTimeRange, ...this.entity }
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- result = response.data.result
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- resolve(result)
- })
- }
- })
- gotData.then(result => {
- if (this.isSingleValueWithEcharts) { // 带曲线的单值图
- const dom = document.getElementById(`chart${this.chartInfo.id}`)
- !this.myChart && (this.myChart = echarts.init(dom))
- this.chartOption = this.$_.cloneDeep(getOption(this.chart.type))
- const seriesTemplate = this.chartOption.series[0]
- this.chartOption.series = result.map((r, i) => {
- return {
- ...seriesTemplate,
- name: r.legend,
- data: r.values.map(v => [Number(v[0]) * 1000, Number(v[1]), chartParams.unitType]),
- lineStyle: {
- color: getChartColor[i]
- }
- }
- })
- this.myChart.setOption(this.chartOption)
- this.singleValue.value = result[0].values[result[0].values.length - 1][1]
-
- /* const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), ...this.entity }
- const dom = document.getElementById(`chart${this.chartInfo.id}`)
- !this.myChart && (this.myChart = echarts.init(dom))
- this.chartOption = this.$_.cloneDeep(getOption(this.chart.type))
- const seriesTemplate = this.chartOption.series[0]
-
- get(replaceUrlPlaceholder(chartParams.urlLine, queryParams)).then(response => {
- if (response.code === 200) {
- this.chartOption.series = response.data.result.map((r, i) => {
- return {
- ...seriesTemplate,
- name: r.legend,
- data: r.values.map(v => [Number(v[0]) * 1000, Number(v[1]), chartParams.unitType]),
- lineStyle: {
- color: getChartColor[i]
- }
- }
- })
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- this.myChart.setOption(this.chartOption)
- }) */
- } else {
- this.singleValue.value = result
- this.loading = false
- }
- }).catch(() => {
- this.singleValue.value = ''
- }).finally(() => {
- setTimeout(() => {
- this.loading = false
- this.$nextTick(() => {
- this.echartsResize()
- })
- }, 250)
- })
- }
- } else if (this.isTabs) {
- if (!this.$_.isEmpty(this.chartInfo.children)) {
- this.activeTab = `${this.chartInfo.children[0].id}`
- }
- } else if (this.isGroup) {
- if (chartParams && chartParams.url) {
- const queryParams = { ...this.queryTimeRange, ...this.entity }
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- this.groupData = response.data.result
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- }).catch(e => {
- this.isError = true
- this.errorInfo = e
- })
- }
- } else if (this.isDomainWhois || this.isDomainDnsRecord) {
- const queryParams = { domain: this.entity.domain }
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- this.detailData = response.data.result
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- }).catch(e => {
- this.isError = true
- this.errorInfo = e
- })
- } else if (this.isCryptocurrencyEventList) {
- const queryParams = { ...this.queryTimeRange, ...this.entity }
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- if (response.data.result.length > 0) {
- this.croptyEventList = response.data.result
- } else {
- this.noData = true
- }
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- }).catch(e => {
- this.isError = true
- this.errorInfo = e
- }).finally(() => {
- setTimeout(() => { this.loading = false }, 250)
- })
- } else if (this.isAppBasicInfo) {
- const queryParams = { appName: this.entity.appName }
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- this.detailData = response.data.result
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- }).catch(e => {
- this.isError = true
- this.errorInfo = e
- })
- }
- } catch (e) {
- console.error(e)
- }
- },
-
- reloadChart () {
- this.initChart()
- this.$nextTick(() => {
- if (!this.$_.isEmpty(this.chart.children)) {
- this.chart.children.forEach(chart => {
- this.$refs[`chart-${chart.id}`].reloadChart()
- })
- }
- })
- },
- timeRefreshChange () {
- if (!this.$refs.dateTimeRange.isCustom) {
- const value = this.chartTimeFilter.dateRangeValue
- this.$refs.dateTimeRange.quickChange(value)
- }
- },
- reload (s, e, v) {
- this.dateTimeRangeChange(s, e, v)
- },
- dateTimeRangeChange (s, e, v) {
- this.chartTimeFilter = { startTime: s, endTime: e, dateRangeValue: v }
- },
- generateTooltipHTML () {
- return `
- <div class="map-tooltip" style="padding-bottom: 10px;">
- <div class="map-tooltip__title">{name}</div>
- <div class="map-tooltip__content">
- <span>{labelText}</span>
- <span>{showValue}</span>
- </div>
- </div>
- `
- },
- changeTab (tab) {
- this.activeTab = tab.paneName
- },
- initMap (id) {
- if (this.isIpBasicInfo) {
- L.Marker.prototype.options.icon = L.icon({
- iconUrl: icon,
- shadowUrl: iconShadow
- })
- const map = L.map(`chart${this.chartInfo.id}`, {
- minZoom: 3,
- maxZoom: 7,
- zoom: 5,
- attributionControl: false,
- zoomControl: false,
- maxBounds: L.latLngBounds(L.latLng(-90, -180), L.latLng(90, 180))
- })
- L.tileLayer(
- this.mapPictureUrl,
- { noWrap: true }
- ).addTo(map)
-
- const attribution = L.control.attribution({ position: 'bottomright', prefix: '' })
- attribution.addAttribution(' © OpenStreetMap contributors')
- attribution.addTo(map)
-
- /* L.control.zoom({
- position: 'bottomright',
- zoomInText: '<i class="nz-icon nz-icon-enlarge"></i>',
- zoomOutText: '<i class="nz-icon nz-icon-narrow"></i>',
- zoomInTitle: '',
- zoomOutTitle: ''
- }).addTo(map) */
-
- this.myChart = map
- } else {
- const chart = am4Core.create(id, am4Maps.MapChart)
- chart.geodata = getGeoData(storageKey.iso36112WorldLow)
- chart.projection = new am4Maps.projections.Miller()
- this.myChart = chart
- const polygonSeries = chart.series.push(new am4Maps.MapPolygonSeries())
- polygonSeries.useGeodata = true
- polygonSeries.exclude = ['AQ'] // 排除南极洲
- polygonSeries.tooltip.getFillFromObject = false
- polygonSeries.tooltip.background.fill = am4Core.color('#FFFFFF')
- this.polygonSeries = polygonSeries
- const polygonTemplate = polygonSeries.mapPolygons.template
- polygonTemplate.tooltipHTML = this.generateTooltipHTML()
- polygonTemplate.nonScalingStroke = true
- polygonTemplate.strokeWidth = 0.5
- polygonTemplate.fill = am4Core.color('rgba(176,196,222,.5)')
- polygonTemplate.events.on('hit', ev => {
- let countryId = ev.target.dataItem.dataContext.id
- countryId = countryId === 'Private IP' ? 'China' : countryId
- if (countryId) {
- ev.target.series.chart.zoomToMapObject(ev.target)
- ev.target.isHover = false
- this.countrySeries = chart.series.push(new am4Maps.MapPolygonSeries())
- this.countrySeries.tooltip.getFillFromObject = false
- this.countrySeries.tooltip.background.fill = am4Core.color('#FFFFFF')
- const countryTemplate = this.countrySeries.mapPolygons.template
- countryTemplate.tooltipHTML = this.generateTooltipHTML()
- countryTemplate.nonScalingStroke = true
- countryTemplate.strokeWidth = 0.5
- countryTemplate.fill = am4Core.color('rgba(176,196,222,.5)')
- const geoData = getGeoData(countryId)
- if (geoData) {
- this.countrySeries.geodata = geoData
- this.polygonSeries.hide()
- this.loadAm4ChartMap(this.countrySeries, ev.target.dataItem.dataContext.serverCountry)
- }
- }
- })
- }
- },
- loadAm4ChartMap (polygonSeries, country) {
- this.loading = true
- // 清除数据
- polygonSeries.data.splice(0)
- // 清除legend
- this.myChart.children.each((s, i) => {
- if (s.className !== 'Container') {
- this.myChart.children.removeIndex(i)
- }
- })
-
- this.showMapBackButton = !!country
- const chartParams = this.chartInfo.params
- const queryParams = { ...this.queryTimeRange, country: country || '', region: '', ...this.entity } // 统计数据的查询参数
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200 && !this.$_.isEmpty(response.data.result)) {
- const data = response.data.result
- data.forEach(r => {
- const serverCountryCapital = r.serverId && getCapitalGeo(r.serverId)
- const clientCountryCapital = r.clientId && getCapitalGeo(r.clientId)
- serverCountryCapital && (r.serverLongitude = serverCountryCapital.capitalLongitude)
- serverCountryCapital && (r.serverLatitude = serverCountryCapital.capitalLatitude)
- clientCountryCapital && (r.clientLongitude = clientCountryCapital.capitalLongitude)
- clientCountryCapital && (r.clientLatitude = clientCountryCapital.capitalLatitude)
- })
- /* if (this.isMapLine) {
- const lineSeries = this.myChart.series.push(new am4Maps.MapLineSeries())
- const lineTemplate = lineSeries.mapLines.template
- lineTemplate.stroke = am4Core.color('#A258EC')
- lineTemplate.line.nonScalingStroke = true
- lineTemplate.line.strokeDasharray = '4 3'
- lineTemplate.nonScalingStroke = true
- lineTemplate.arrow.nonScaling = true
- lineTemplate.arrow.width = 4
- lineTemplate.arrow.height = 6
- lineSeries.data = [
- {
- multiGeoLine: data.map(d => {
- return [
- {
- latitude: parseFloat(d.serverLatitude),
- longitude: parseFloat(d.serverLongitude)
- },
- {
- latitude: parseFloat(d.clientLatitude),
- longitude: parseFloat(d.clientLongitude)
- }
- ]
- })
- }
- ]
- const imageSeries = this.myChart.series.push(new am4Maps.MapImageSeries())
- imageSeries.dataFields.value = 'sessions'
- const imageSeriesTemplate = imageSeries.mapImages.template
- const circle = imageSeriesTemplate.createChild(am4Core.Circle)
-
- circle.fillOpacity = 0.7
- circle.nonScaling = true
- const radiusHeat = imageSeries.heatRules.push({
- target: circle,
- property: 'radius',
- min: 8,
- max: 30
- })
- const colorHeat = imageSeries.heatRules.push({
- target: circle,
- property: 'fill',
- min: am4Core.color('#D2A8FF'),
- max: am4Core.color('#A258EC')
- })
- imageSeriesTemplate.propertyFields.latitude = 'latitude'
- imageSeriesTemplate.propertyFields.longitude = 'longitude'
-
- const pointData = []
- data.forEach(d => {
- pointData.push({
- ...d,
- latitude: parseFloat(d.serverLatitude),
- longitude: parseFloat(d.serverLongitude)
- })
- pointData.push({
- ...d,
- latitude: parseFloat(d.clientLatitude),
- longitude: parseFloat(d.clientLongitude)
- })
- })
- imageSeries.data = pointData
- } */
- if (this.isMapBlock) {
- const sumData = []
- data.forEach(r => {
- const hit = sumData.find(s => s.id === r.serverId)
- const { key, labelText } = this.getDataKey(r)
- const value = Number(r[key]) || 0
- if (hit) {
- hit.value += value
- } else {
- sumData.push({
- id: r.serverId,
- serverCountry: r.serverCountry,
- key,
- labelText,
- value
- })
- }
- })
- const seriesData = sumData.map(r => ({
- ...r,
- showValue: (r.value || r.value === 0) ? valueToRangeValue(r.value, chartParams.unitType).join(' ') : ''
- }))
- polygonSeries.data = [...seriesData]
- const sorted = seriesData.sort((a, b) => b.value - a.value)
- const allZero = this.$_.isEmpty(sorted) || Number(sorted[0].value) === 0 // 数据全为0的情况,legend只显示1个颜色
-
- polygonSeries.heatRules.push({
- property: 'fill',
- target: polygonSeries.mapPolygons.template,
- min: this.myChart.colors.getIndex(1).brighten(1),
- max: allZero ? this.myChart.colors.getIndex(1).brighten(1) : this.myChart.colors.getIndex(1).brighten(-0.3)
- })
- const heatLegend = this.myChart.createChild(HeatLegend)
- heatLegend.markerContainer.height = 6
- heatLegend.series = polygonSeries
- heatLegend.align = 'left'
- heatLegend.markerCount = allZero ? 1 : 3
- heatLegend.minValue = 0
- heatLegend.fontSize = 12
- heatLegend.maxValue = allZero ? 1 : Number(sorted[0].value)
- heatLegend.width = allZero ? am4Core.percent(10) : am4Core.percent(25)
- heatLegend.marginLeft = 15
- heatLegend.valign = 'bottom'
-
- const minRange = heatLegend.valueAxis.axisRanges.create()
- minRange.value = heatLegend.minValue
- minRange.label.text = minRange.value === 0 ? 0 : unitConvert(heatLegend.minValue, chartParams.unitType).join(' ')
- const maxRange = heatLegend.valueAxis.axisRanges.create()
- maxRange.value = heatLegend.maxValue
- maxRange.label.text = maxRange.value === 0 ? 0 : unitConvert(heatLegend.maxValue, chartParams.unitType).join(' ')
-
- heatLegend.valueAxis.renderer.labels.template.adapter.add('text', function (labelText) {
- return ''
- })
- }
- } else if (response.code !== 200) {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- }).finally(() => {
- setTimeout(() => { this.loading = false }, 250)
- })
- },
- loadLeafletMap () {
- this.loading = true
- const chartParams = this.chartInfo.params
- get(replaceUrlPlaceholder(chartParams.url, this.entity)).then(response => {
- if (response.code === 200 && !this.$_.isEmpty(response.data.result)) {
- this.detailData = response.data.result
- this.myChart.setView([this.detailData.latitude, this.detailData.longitude], 5)
- const myIcon = L.divIcon({
- className: 'cn-icon cn-icon-position2 position-icon'
- })
- L.marker([this.detailData.latitude, this.detailData.longitude], { icon: myIcon }).addTo(this.myChart)
- }
- }).finally(() => {
- setTimeout(() => { this.loading = false }, 250)
- })
- },
- pageJump (val) {
- this.table.currentPageData = this.getTargetPageData(val, this.table.pageSize, this.table.tableData)
- },
- getTargetPageData (pageNum, pageSize, tableData) {
- return this.$_.slice(tableData, (pageNum - 1) * pageSize, pageNum * pageSize)
- },
- refresh () {
- const eventName = this.fromBlock ? 'getChartCurrentTimeRange' : 'getCurrentTimeRange'
- this.$emit(eventName, ({ startTime, endTime }) => {
- this.standaloneTimeRange.use = true
- this.standaloneTimeRange.startTime = startTime
- this.standaloneTimeRange.endTime = endTime
- this.initChart()
- })
- },
- mapBack () {
- this.countrySeries.hide()
- this.loadAm4ChartMap(this.polygonSeries)
- this.polygonSeries.show()
- this.myChart.goHome()
- },
- // 获取最新时间
- getCurrentTimeRange (callback) {
- this.$emit('getCurrentTimeRange', ({ startTime, endTime }) => {
- callback({ startTime, endTime })
- })
- },
- // 获取最新时间
- getChartCurrentTimeRange (callback) {
- if (this.isGroup) {
- this.$emit('getChartCurrentTimeRange', ({ startTime, endTime }) => {
- callback({ startTime, endTime })
- })
- } else {
- const myEndTime = window.$dayJs.tz().valueOf()
- const myStartTime = myEndTime - this.chartTimeFilter.dateRangeValue * 60 * 1000
- callback({ startTime: myStartTime, endTime: myEndTime })
- }
- },
- getDataKey (r) {
- let key = ''
- let labelText = ''
- if (r.establishLatency || r.establishLatency === 0) {
- key = 'establishLatency'
- labelText = this.$t('networkAppPerformance.tripTime')
- } else if (r.httpResponseLatency || r.httpResponseLatency === 0) {
- key = 'httpResponseLatency'
- labelText = this.$t('networkAppPerformance.httpResponse')
- } else if (r.sslConLatency || r.sslConLatency === 0) {
- key = 'sslConLatency'
- labelText = this.$t('networkAppPerformance.sslResponse')
- } else if (r.sequenceGapLossPercent || r.sequenceGapLossPercent === 0) {
- key = 'sequenceGapLossPercent'
- labelText = this.$t('networkAppPerformance.packetLossRate')
- } else if (r.pktRetransPercent || r.pktRetransPercent === 0) {
- key = 'pktRetransPercent'
- labelText = this.$t('networkAppPerformance.retransmissionRate')
- } else if (r.sessions || r.sessions === 0) {
- key = 'sessions'
- labelText = this.$t('overall.sessions')
- }
- return { key, labelText }
+ computed: {
+ isNoData () {
+ return !this.loading && (_.isEmpty(this.chartData) || this.isError) && !this.isSingleValue && !this.isTabs && !this.isDomainDnsRecord && !this.isCryptocurrencyEventList && !this.isActiveIpTable && !this.isMap
},
- getTableTitle (data) {
- if (data.length > 0) {
- const dataColumns = Object.keys(data[0]) // 返回数据的字段
- const columns = dataColumns.map(c => tableTitleMapping[c]) // 展示字段
- const keys = ['clientIp', 'serverIp', 'ip', 'appId', 'app', 'appName', 'domain']
- return columns.sort((a, b) => {
- if (keys.indexOf(a.prop) > -1) {
- return -1
- } else if (keys.indexOf(b.prop) > -1) {
- return 1
- } else {
- return 0
- }
- })
+ chartOption () {
+ if (this.customChartOption) {
+ return _.cloneDeep(this.customChartOption)
} else {
- return []
- }
- },
- toggleStatisticsLegend (index) {
- this.statisticsData[index].active = !this.statisticsData[index].active
- this.statisticsData.forEach((d, i) => {
- if (d.active) {
- this.myChart.dispatchAction({
- type: 'legendSelect',
- name: d.legend
- })
- } else {
- this.myChart.dispatchAction({
- type: 'legendUnSelect',
- name: d.legend
- })
- }
- })
- },
- orderPieTableChange () {
- if (this.chart.type === 31) {
- const chartParams = this.chartInfo.params || null // 图表参数
- this.initEchartsWithPieTable(chartParams)
- }
- },
- timeLineIsAllZero (data) {
- if (data.resultType === 'matrix') {
- let allZero = true
- try {
- data.result.forEach(d => {
- d.values.forEach(r => {
- if (r[1] && r[1] !== '0') {
- allZero = false
- throw new Error('break')
- }
- })
- })
- } catch (e) {}
- return allZero
- }
- },
- initECharts (chartParams) {
- if (chartParams.showLegend === false) {
- this.chartOption.legend.show = false
- }
- const queryParams = { ...this.queryTimeRange, ...this.entity }
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- return
- } else {
- this.noData = false
- }
- const seriesTemplate = this.chartOption.series[0]
- const allZero = this.timeLineIsAllZero(response.data)
- if (allZero) {
- this.chartOption.yAxis = {
- ...this.chartOption.yAxis,
- min: 0,
- max: 5,
- interval: 1
- }
- }
- this.chartOption.series = response.data.result.map(r => {
- return {
- ...seriesTemplate,
- name: legendMapping[`${this.entity && this.entity.ip ? 'ip_' : ''}${r.legend}`] ? legendMapping[`${this.entity && this.entity.ip ? 'ip_' : ''}${r.legend}`] : lineToSpace(r.legend),
- data: r.values.map(v => [Number(v[0]) * 1000, Number(v[1]), chartParams.unitType])
- }
- })
- const rows = (response.data.result.length - 1) / 4 + 1 // 根据legend个数动态预留legend空间
- const gridTop = 10 + 27 * rows
- this.chartOption.grid.top = gridTop
- if (chartParams.unitType === unitTypes.byte) {
- this.chartOption.yAxis.axisLabel.formatter = function (value, index, a, b) {
- return unitConvert(value, unitTypes.byte).join(' ')
- }
- this.chartOption.grid.left = 75
- }
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- this.myChart.setOption(this.chartOption)
- }).finally(() => {
- setTimeout(() => {
- this.loading = false
- this.$nextTick(() => {
- this.echartsResize()
- })
- }, 250)
- })
- },
- initRelationShip (chartParams) {
- this.isError = false
- this.errorInfo = '0'
- const queryParams = { ...this.entity, limit: 5 }
- post(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- if (!response.data.result) {
- this.noData = true
- return
- }
- const data = []
- const links = []
- handleData(data, links, response.data.result)
- this.chartOption.series[0].data = data
- this.chartOption.series[0].links = links
- this.myChart.setOption(this.chartOption)
- } else {
- this.isError = true
- this.errorInfo = response
- this.noData = true
- }
- }).finally(() => {
- setTimeout(() => {
- this.loading = false
- setTimeout(() => {
- this.myChart.resize()
- })
- }, 250)
- })
-
- const vm = this
- function handleData (data, links, item) {
- if (!data.some(d => d.name === item.name)) {
- data.push({ name: item.name, ...handleStyle(item) })
- }
- if (!vm.$_.isEmpty(item.from) && !vm.$_.isEmpty(item.to)) {
- links.push({ target: item.to, source: item.from })
- }
- if (!vm.$_.isEmpty(item.leaf)) {
- item.leaf.forEach(i => {
- handleData(data, links, i)
- })
- }
- }
-
- function handleStyle (item) {
- const style = {}
- switch (item.type) {
- case 'app_id': {
- style.itemStyle = { color: '#73DEB3' }
- style.symbol = 'circle'
- break
- }
- case 'domain': {
- style.itemStyle = { color: '#73A0FA' }
- style.symbol = 'circle'
- break
- }
- case 'client_ip': {
- style.itemStyle = { color: '#E8F6FF', borderColor: '#C9C9C9' }
- style.symbol = 'roundRect'
- style.symbolSize = [80, 25]
- break
- }
- case 'server_ip': {
- style.itemStyle = { color: '#E2FCEF', borderColor: '#C9C9C9' }
- style.symbol = 'roundRect'
- style.symbolSize = [80, 25]
- break
- }
- }
- return style
- }
- },
- initSankey (chartParams) {
- const vm = this
- const entityName = this.entity.ip || this.entity.domain || this.entity.app
- const queryParams = { ...this.queryTimeRange, ...this.entity }
- this.chartOption.series[0].tooltip = {
- formatter: function (param) {
- return `
- <div class="sankey__tooltip">
- <div class="sankey__tooltip-row">
- <div class="sankey__row-label">Via:</div>
- <div class="sankey__row-value">${param.data.name}</div>
- </div>
- <div class="sankey__tooltip-row">
- <div style="margin: 6px 0; height: 1px; width: 100%; background-color: #E7EAED;"></div>
- </div>
- <div class="sankey__tooltip-row">
- <div class="sankey__row-label">Traffic:</div>
- <div class="sankey__row-value">${param.data.convert[0]}${param.data.convert[1]}&nbsp;(${param.data.percent[0]}%)</div>
- </div>
- <div class="sankey__tooltip-row">
- <div class="sankey__row-label">Performance:</div>
- </div>
- <div class="sankey__tooltip-table">
- <div class="sankey__table-row">
- <div class="sankey__table-cell">${vm.$t('networkAppPerformance.tripTime')}:</div>
- <div class="sankey__table-cell">${param.data.latency[0]}&nbsp;${param.data.latency[1]}</div>
- </div>
- <div class="sankey__table-row">
- <div class="sankey__table-cell">${vm.$t('overall.packetLoss')}:</div>
- <div class="sankey__table-cell">${param.data.lossPercent[0]}&nbsp;%</div>
- </div>
- <div class="sankey__table-row">
- <div class="sankey__table-cell">${vm.$t('overall.packetRetrans')}:</div>
- <div class="sankey__table-cell">${param.data.retransPercent[0]}&nbsp;%</div>
- </div>
- </div>
- </div>
- `
- }
- }
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- } else {
- this.noData = false
- let inTotalValue = 0
- let outTotalValue = 0
-
- /* 测试代码
- const t = []
- for (const k in response.data.result) {
- t.push(response.data.result[k])
- }
- response.data.result = t */
-
- response.data.result.forEach(item => {
- if (item.direction === 'in') {
- inTotalValue += parseInt(item.bytes)
- } else if (item.direction === 'out') {
- outTotalValue += parseInt(item.bytes)
- }
- })
- const data = response.data.result.map(item => {
- return {
- ...item,
- name: item.linkID,
- percent: valueToRangeValue(parseInt(item.bytes) / (item.direction === 'in' ? inTotalValue : outTotalValue) * 100, unitTypes.percent),
- convert: unitConvert(item.bytes, unitTypes.byte),
- latency: valueToRangeValue(item.latency, unitTypes.time),
- lossPercent: valueToRangeValue(item.lossPercent, unitTypes.percent),
- retransPercent: valueToRangeValue(item.retransPercent, unitTypes.percent),
- bytes: parseFloat(item.bytes)
- }
- })
- data.push({ name: entityName })
-
- const link = data.map(item => {
- const source = item.direction === 'in' ? item.linkID : entityName
- const target = item.direction === 'in' ? entityName : item.linkID
- return {
- ...item,
- source,
- target,
- value: item.bytes
- }
- })
- this.chartOption.series[0].data = data
- this.chartOption.series[0].links = link
- this.myChart.setOption(this.chartOption)
- }
- }
- }).finally(() => {
- setTimeout(() => {
- this.loading = false
- this.$nextTick(() => {
- this.echartsResize()
- })
- }, 250)
- })
- /* const inDirection = new Promise(resolve =>
- get(replaceUrlPlaceholder(chartParams.url, { ...queryParams, direction: 'ingress' })).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- } else {
- this.noData = false
- resolve(handleData(response.data.result, 'in'))
- }
- }
- resolve()
- })
- )
- const outDirection = new Promise(resolve =>
- get(replaceUrlPlaceholder(chartParams.url, { ...queryParams, direction: 'egress' })).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- } else {
- this.noData = false
- resolve(handleData(response.data.result, 'out'))
- }
- }
- resolve()
- })
- )
- Promise.all([inDirection, outDirection]).then(responses => {
- const inData = responses[0]
- const outData = responses[1]
- this.chartOption.series[0].data = inData.data.concat(outData.data)
- this.chartOption.series[0].links = inData.link.concat(outData.link)
- this.myChart.setOption(this.chartOption)
- }).finally(() => {
- setTimeout(() => {
- this.loading = false
- this.$nextTick(() => {
- this.echartsResize()
- })
- }, 250)
- })
-
- function handleData (originalData, direction) {
- let totalValue = 0
- originalData.forEach(item => {
- totalValue += parseInt(item.bytes)
- })
- const data = originalData.map(item => {
- return {
- ...item,
- name: item.linkID,
- percent: unitConvert(parseInt(item.bytes) / totalValue, unitTypes.byte),
- bytes: unitConvert(item.bytes, unitTypes.byte)
- }
- })
-
- const link = data.map(item => {
- const source = direction === 'in' ? item.linkID : entityName
- const target = direction === 'in' ? entityName : item.linkID
- return {
- ...item,
- source,
- target,
- value: item.bytes
- }
- })
- return {
- data,
- link
- }
- } */
- },
- initIpOpenPort (chartParams) {
- get(replaceUrlPlaceholder(chartParams.url, { ip: this.entity.ip })).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- } else {
- this.noData = false
- this.detailData = response.data.result
- const protocols = []
- this.detailData.forEach((d, i) => {
- const index = protocols.findIndex(p => p.name === d.protocol.toUpperCase())
- if (index === -1) {
- protocols.push({ name: d.protocol.toUpperCase(), value: 1, itemStyle: { color: getChartColor(i) } })
- } else {
- protocols[index].value++
- }
- })
- this.chartOption.series[0].data = protocols
- this.chartOption.xAxis.data = protocols.map(p => p.name)
- this.myChart.setOption(this.chartOption)
- }
- }
- }).finally(() => {
- setTimeout(() => {
- this.loading = false
- this.$nextTick(() => {
- this.echartsResize()
- })
- }, 250)
- })
- },
- initIpHostedDomain (chartParams) {
- const list = new Promise(resolve => {
- get(replaceUrlPlaceholder(chartParams.url, { ip: this.entity.ip })).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- } else {
- this.noData = false
- this.detailData = response.data.result
- }
- }
- resolve()
- })
- })
- const byType = new Promise(resolve => {
- get(replaceUrlPlaceholder(chartParams.byTypeUrl, { ip: this.entity.ip })).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData0 = true
- } else {
- this.noData0 = false
- const chartOption = this.$_.cloneDeep(this.chartOption)
- chartOption.series[0].data = response.data.result.map(r => ({ ...r, unitType: chartParams.unitType }))
- this.myChart.setOption(chartOption)
- }
- }
- resolve()
- })
- })
- const byCredit = new Promise(resolve => {
- get(replaceUrlPlaceholder(chartParams.byCreditUrl, { ip: this.entity.ip })).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData1 = true
- } else {
- this.noData1 = false
- const chartOption = this.$_.cloneDeep(this.chartOption)
- chartOption.series[0].data = response.data.result.map(r => ({ ...r, unitType: chartParams.unitType }))
- this.myChart2.setOption(chartOption)
- }
- }
- resolve()
- })
- })
- Promise.all([list, byType, byCredit]).finally(response => {
- setTimeout(() => {
- this.loading = false
- this.$nextTick(() => {
- this.echartsResize()
- })
- }, 250)
- })
- },
- initAppRelatedDomain (chartParams) {
- this.noData = false
- this.loading = false
- this.chartOption.series[0].data = [
- {
- name: 'test1',
- value: 32
- },
- {
- name: 'test2',
- value: 21
- },
- {
- name: 'test3',
- value: 20
- },
- {
- name: 'test4',
- value: 7
- }
- ]
- this.myChart.setOption(this.chartOption)
- this.myChart2.setOption(this.chartOption)
- get(replaceUrlPlaceholder(chartParams.url, { appName: this.entity.appName })).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- } else {
- this.detailData = response.data.result
- this.noData = false
- }
- }
- }).finally(() => {
- setTimeout(() => {
- this.loading = false
- }, 250)
- })
- },
-
- handleTimeChartOption (chartParams, dataArray) {
- let direction = 'vertical'
- if (chartParams.direction) {
- direction = chartParams.direction
- if (direction == 'horizontal') { // 柱状图水平方向
- this.chartOption.xAxis = {
- axisTick: { show: false },
- axisLine: { show: false },
- type: 'value',
- axisLabel: {
- formatter: function (value, index, a, b) {
- return unitConvert(value, unitTypes.number).join(' ')
- }
- }
- }
-
- this.chartOption.yAxis = {
- type: 'category',
- axisTick: { show: false },
- axisLine: { show: false },
- axisLabel: {
- interval: 0,
- // rotate: -40, //设置日期显示样式(倾斜度)
- formatter: function (value) { // 在这里写你需要的时间格式
- return window.$dayJs.tz(Number(value)).format('M/D H:m')
- }
- },
- axisPointer: { // y轴上显示指针对应的值
- show: true
- }
- }
- } else if (direction == 'vertical') { // 柱状图竖直方向
- this.chartOption.yAxis = {
- axisTick: { show: false },
- axisLine: { show: false },
- type: 'value',
- axisLabel: {
- formatter: function (value, index, a, b) {
- return unitConvert(value, unitTypes.number).join(' ')
- }
- },
- minInterval: 1
- }
- this.chartOption.xAxis = {
- type: 'category',
- axisTick: { show: false },
- axisLine: { show: false },
- axisLabel: {
- interval: 0,
- // rotate: -40, //设置日期显示样式(倾斜度)
- formatter: function (value) { // 在这里写你需要的时间格式
- return window.$dayJs.tz(Number(value)).format('M/D H:m')
- }
- },
- axisPointer: { // y轴上显示指针对应的值
- show: true
- }
- }
- }
- }
-
- let itemColorAlternately = false// true|false 柱体色是否轮替
- if (chartParams.itemColorAlternately) {
- itemColorAlternately = chartParams.itemColorAlternately
- }
-
- this.chartOption.tooltip = {
- ...this.chartOption.tooltip,
- formatter: (direction == 'horizontal') ? timeHorizontalFormatter : timeVerticalFormatter
- }
-
- this.chartOption.series = {
- ...this.chartOption.series[0],
- name: this.chartInfo.name,
- data: dataArray,
- itemStyle: {
- color: function (params) {
- if (itemColorAlternately) {
- return getCharBartColor([params.dataIndex])
- } else {
- return getCharBartColor(0)
- }
- }
- }
- }
- },
-
- initEchartsTimeBar (chartParams) {
- const queryParams = { ...this.queryTimeRange, ...this.entity }
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- return
- } else {
- this.noData = false
- }
-
- let dataArray = []
- if (chartParams.direction == 'vertical') { // 柱状图竖直方向
- dataArray = response.data.result[0].values.map((r, i) => {
- return [Number(r[0]), Number(r[1]), chartParams.unitType]
- })
- } else if (chartParams.direction == 'horizontal') { // 柱状图水平方向
- dataArray = response.data.result[0].values.map((r, i) => {
- return [Number(r[1]), Number(r[0]), chartParams.unitType]
- })
- }
-
- this.handleTimeChartOption(chartParams, dataArray)
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- this.myChart.setOption(this.chartOption)
- }).finally(() => {
- setTimeout(() => {
- this.loading = false
- this.$nextTick(() => {
- this.echartsResize()
- })
- }, 250)
- })
- },
-
- initEchartsCategoryBar (chartParams) {
- const queryParams = { ...this.queryTimeRange, ...this.entity }
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- return
- } else {
- this.noData = false
- }
-
- let dataArray = []
- if (chartParams.direction == 'horizontal') { // 柱状图水平方向
- dataArray = response.data.result.map((r, i) => { return [r.num, r.name] })
- } else if (chartParams.direction == 'vertical') { // 柱状图竖直方向
- dataArray = response.data.result.map((r, i) => { return [r.name, r.num] })
- }
- this.handleCategoryChartOption(chartParams, dataArray)
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- this.myChart.setOption(this.chartOption)
- }).finally(() => {
- setTimeout(() => {
- this.loading = false
- this.$nextTick(() => {
- this.echartsResize()
- })
- }, 250)
- })
- },
-
- handleCategoryChartOption (chartParams, dataArray) {
- let xType = 'category'
- let yType = 'value'
- let direction = 'vertical'
- if (chartParams.direction) {
- direction = chartParams.direction
- if (direction == 'horizontal') { // 柱状图水平方向
- xType = 'value'
- yType = 'category'
- } else if (direction == 'vertical') { // 柱状图竖直方向
- xType = 'category'
- yType = 'value'
- }
- }
-
- let itemColorAlternately = false// true|false 柱体色是否轮替
- if (chartParams.itemColorAlternately) {
- itemColorAlternately = chartParams.itemColorAlternately
- }
-
- this.chartOption.tooltip = {
- ...this.chartOption.tooltip,
- formatter: (direction == 'horizontal') ? categoryHorizontalFormatter : categoryVerticalFormatter
- }
- this.chartOption.xAxis = {
- ...this.chartOption.xAxis,
- type: xType
- }
- this.chartOption.yAxis = {
- ...this.chartOption.yAxis,
- type: yType
+ return getOption(this.chartInfo.type)
}
- this.chartOption.series = {
- ...this.chartOption.series[0],
- data: dataArray,
- itemStyle: {
- color: function (params) {
- if (itemColorAlternately) {
- return getCharBartColor([params.dataIndex])
- } else {
- return getCharBartColor(0)
- }
- }
- }
- }
- },
-
- initEchartsWithStatistics (chartParams) {
- const queryParams = { ...this.queryTimeRange, ...this.entity }
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- return
- } else {
- this.noData = false
- }
- const allZero = this.timeLineIsAllZero(response.data)
- if (allZero) {
- this.chartOption.yAxis = {
- ...this.chartOption.yAxis,
- min: 0,
- max: 5,
- interval: 1
- }
- }
- this.statisticsData = response.data.result.map(d => {
- return {
- ...d,
- active: true
- }
- })
- const seriesTemplate = this.chartOption.series[0]
- this.chartOption.series = response.data.result.map((r, i) => {
- return {
- ...seriesTemplate,
- name: r.legend,
- data: r.values.map(v => [Number(v[0]) * 1000, Number(v[1]), chartParams.unitType]),
- lineStyle: {
- color: getChartColor[i]
- }
- }
- })
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- this.myChart.setOption(this.chartOption)
- }).finally(() => {
- setTimeout(() => {
- this.loading = false
- this.$nextTick(() => {
- this.echartsResize()
- })
- }, 250)
- })
- },
-
- initEchartsWithPieTable (chartParams) {
- const self = this
- chartParams.valueColumn = this.orderPieTable
- const unitType = getUnitType(chartParams.valueColumn)
- const queryParams = { ...this.queryTimeRange, limit: 10, order: this.orderPieTable, ...this.entity } // 统计数据的查询参数
- const tableQueryParams = { ...this.queryTimeRange, limit: 10, order: this.orderPieTable, ...this.entity } // 统计数据的查询参数
- tableQueryParams[chartParams.nameColumn] = [] // 处理两个图表不一样的地方)
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- return
- } else {
- this.noData = false
- }
- const allZero = this.timeLineIsAllZero(response.data)
- if (allZero) {
- this.chartOption.yAxis = {
- ...this.chartOption.yAxis,
- min: 0,
- max: 5,
- interval: 1
- }
- }
-
- const data = response.data.result.map(d => {
- if (d[chartParams.nameColumn]) {
- this.allSelectPieChartName.push(d[chartParams.nameColumn])
- }
- return {
- data: d,
- name: d[chartParams.nameColumn],
- value: parseInt(d[chartParams.valueColumn]),
- unitType: unitType
- }
- })
-
- this.allSelectPieChartName = tableQueryParams[chartParams.nameColumn]
- this.chartOption.series[0].data = data
- if (this.chartOption.series[0].data && this.chartOption.series[0].data.length > 10) { // pieWithTable 图例超过10个改为滚动显示
- this.chartOption.legend.type = 'scroll'
- }
- this.myChart.setOption(this.chartOption)
-
- if (!this.$_.isEmpty(data)) {
- get(replaceUrlPlaceholder(chartParams.urlTable, tableQueryParams)).then(response2 => {
- if (response2.code === 200) {
- this.pieTableData = response2.data.result
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- })
- }
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || 'Unknown'
- }
- }).finally(() => {
- setTimeout(() => {
- this.loading = false
- this.$nextTick(() => {
- this.echartsResize()
- })
- }, 250)
- })
- // legend点击事件
- this.myChart.off('legendselectchanged')
- this.myChart.on('legendselectchanged', function (params) {
- self.myChart.setOption({
- legend: { selected: { [params.name]: true } }
- })
- const index = self.chartOption.series[0].data.findIndex(d => d.name === params.name)
- if (self.selectPieChartName !== params.name) {
- self.myChart.dispatchAction({
- type: 'select',
- seriesIndex: 0,
- dataIndex: index
- })
- self.selectPieChartName = params.name
- self.loadPieTableData(params.name)
- } else {
- self.myChart.dispatchAction({
- type: 'unselect',
- seriesIndex: 0,
- dataIndex: index
- })
- self.selectPieChartName = ''
- self.loadPieTableData(this.allSelectPieChartName)
- }
- })
- // 饼图色块点击事件
- this.myChart.off('click')
- this.myChart.on('click', function (echartParams) {
- // 若是已选,则点击后取消选择,并查询全部数据
- if (echartParams.name === self.selectPieChartName) {
- self.selectPieChartName = ''
- self.loadPieTableData(this.allSelectPieChartName)
- } else { // 否则查询当前name数据
- self.selectPieChartName = echartParams.name
- self.loadPieTableData(echartParams.name)
- }
- })
- },
- loadPieTableData (name = '') {
- const childrenParams = { ...this.queryTimeRange, limit: 10, order: this.orderPieTable, ...this.entity }
- childrenParams[this.chartInfo.params.nameColumn] = name
- get(replaceUrlPlaceholder(this.chartInfo.params.urlTable, childrenParams)).then(response => {
- if (response.code === 200) {
- this.pieTableData = response.data.result
- }
- })
- },
- tableLimitChange () {
- const chartParams = this.chartInfo.params || null // 图表参数
- this.initChartTable(chartParams)
- },
- initChartTable (chartParams) {
- const queryParams = { ...this.queryTimeRange, limit: this.table.limit, order: this.table.orderBy, ...this.entity }
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- return
- } else {
- this.noData = false
- }
- this.table.tableData = response.data.result
- this.table.tableColumns = this.getTableTitle(response.data.result)
- this.table.currentPageData = this.getTargetPageData(1, this.table.pageSize, this.table.tableData)
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || this.$t('tip.unknownError')
- }
- }).finally(() => {
- this.$nextTick(() => {
- this.$refs.tablePagination.resetPageNo()
- })
- setTimeout(() => { this.loading = false }, 250)
- })
- },
-
- activeIpTableLimitChange () {
- const chartParams = this.chartInfo.params || null // 图表参数
- this.initChartActiveIpTable(chartParams)
- },
- initChartActiveIpTable (chartParams) {
- const queryParams = { ...this.queryTimeRange, order: this.activeIpTable.orderBy, ...this.entity }
- get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
- if (response.code === 200) {
- if (this.$_.isEmpty(response.data.result)) {
- this.noData = true
- return
- } else {
- this.noData = false
- }
- this.activeIpTable.tableData = response.data.result
- this.activeIpTable.tableColumns = this.getTableTitle(response.data.result)
- this.activeIpTable.currentPageData = this.getTargetPageData(1, this.activeIpTable.pageSize, this.activeIpTable.tableData)
- } else {
- this.isError = true
- this.noData = true
- this.errorInfo = response.msg || response.message || this.$t('tip.unknownError')
- }
- }).finally(() => {
- setTimeout(() => { this.loading = false }, 250)
- })
- },
- echartsResize () {
- this.myChart && this.myChart.resize()
- this.myChart2 && this.myChart2.resize()
}
},
- computed: {
- computePosition () {
- const gridColumn = `${this.chartInfo.x} / ${this.chartInfo.x + this.chartInfo.w}`
- const gridRow = `${this.chartInfo.y} / ${this.chartInfo.y + this.chartInfo.h}`
- return {
- gridColumn,
- gridRow
- }
+ methods: {
+ resize () {
+ this.$refs['chart' + this.chartInfo.id] && this.$refs['chart' + this.chartInfo.id].resize()
},
- location () {
- let location = ''
- if (this.detailData) {
- if (this.detailData.country) {
- location = this.detailData.country
- if (this.detailData.province) {
- location += ', '
- location += this.detailData.province
- if (this.detailData.city) {
- location += ', '
- location += this.detailData.city
- }
- }
- } else if (this.detailData.province) {
- location = this.detailData.province
- if (this.detailData.city) {
- location += ', '
- location += this.detailData.city
- }
- } else if (this.detailData.city) {
- location = this.detailData.city
- }
- }
- return location
+ showLoading (show) {
+ this.$emit('showLoading', show)
},
- handleSingleValue () {
- const value = this.singleValue.value
- const unitType = this.chartInfo.params.unitType
- const result = unitConvert(value, unitType)
- switch (unitType) {
- case unitTypes.percent: {
- result[0] = result[0] < 0.01 ? '< 0.01' : result[0]
- break
- }
- case unitTypes.time: {
- result[0] = result[0] < 1 ? '< 1' : result[0]
- break
- }
- default: break
- }
- return result
+ initEchartsWithTable () {
+ this.$refs['chart' + this.chartInfo.id] && this.$refs['chart' + this.chartInfo.id].initEchartsWithTable(`chart${this.chartInfo.id}`)
}
- },
- mounted () {
- setTimeout(() => {
- this.initChart()
- this.throttle = this.$_.throttle(this.echartsResize, 500)
- window.addEventListener('resize', this.throttle)
- }, 300)
+
},
watch: {
- chart: {
- immediate: true,
+ chartData: {
deep: true,
- handler (n, o) {
- if (o) {
- setTimeout(() => { this.initChart() })
- }
- }
- },
- timeFilter: {
- immediate: true,
- deep: true,
- handler (n, o) {
- if (n && o) {
- this.standaloneTimeRange.use = false
- this.$nextTick(() => {
- setTimeout(() => { this.initChart() })
- })
- }
- }
- },
- parentData: {
- immediate: true,
- deep: true,
- handler (n, o) {
- if (n) {
- this.$nextTick(() => {
- setTimeout(() => { this.initChart() })
- })
- }
+ handler (n) {
}
}
},
setup (props) {
- const chartInfo = JSON.parse(JSON.stringify(props.chart))
- chartInfo.category = getTypeCategory(props.chart.type)
-
- const dateRangeValue = 60
- const { startTime, endTime } = getNowTime(dateRangeValue)
- // entity详情内的chart时间工具不是公共的,需要单独定义
- const chartTimeFilter = ref({ startTime, endTime, dateRangeValue })
return {
- chartInfo,
- chartTimeFilter,
- layoutConstant,
- chartTableTopOptions,
- chartActiveIpTableOrderOptions,
- chartPieTableTopOptions,
- isEcharts: isEcharts(props.chart.type),
- isEchartsTimeBar: isEchartsTimeBar(props.chart.type),
- isEchartsCategoryBar: isEchartsCategoryBar(props.chart.type),
- isEchartsWithTable: isEchartsWithTable(props.chart.type),
- isEchartsWithStatistics: isEchartsWithStatistics(props.chart.type),
- isSingleValue: isSingleValue(props.chart.type),
- isSingleValueWithEcharts: isSingleValueWithEcharts(props.chart.type),
- isSingleValueWithEchartsTemp: isSingleValueWithEchartsTemp(props.chart.type),
- isRelationShip: isRelationShip(props.chart.type),
- isTable: isTable(props.chart.type),
- isActiveIpTable: isActiveIpTable(props.chart.type),
- isMap: isMap(props.chart.type),
- isTitle: isTitle(props.chart.type),
- isMapLine: isMapLine(props.chart.type),
- isMapBlock: isMapBlock(props.chart.type),
- isTabs: isTabs(props.chart.type),
- isGroup: isGroup(props.chart.type),
- isBlock: isBlock(props.chart.type),
- isSankey: isSankey(props.chart.type),
- isIpBasicInfo: isIpBasicInfo(props.chart.type),
- isIpHostedDomain: isIpHostedDomain(props.chart.type),
- isIpOpenPort: isIpOpenPort(props.chart.type),
- isDomainWhois: isDomainWhois(props.chart.type),
- isDomainDnsRecord: isDomainDnsRecord(props.chart.type),
- isCryptocurrencyEventList: isCryptocurrencyEventList(props.chart.type),
- isAppBasicInfo: isAppBasicInfo(props.chart.type),
- isAppRelatedDomain: isAppRelatedDomain(props.chart.type),
- layout: getLayout(props.chart.type),
- myChart: shallowRef(null),
- myChart2: shallowRef(null) // 个别有两个图表的chart
+ isEcharts: isEcharts(props.chartInfo.type),
+ isEchartsLine: isEchartsLine(props.chartInfo.type),
+ isEchartsTimeBar: isEchartsTimeBar(props.chartInfo.type),
+ isEchartsCategoryBar: isEchartsCategoryBar(props.chartInfo.type),
+ isIpOpenPortBar: isIpOpenPortBar(props.chartInfo.type),
+ isEchartsPie: isEchartsPie(props.chartInfo.type),
+ isEchartsWithTable: isEchartsWithTable(props.chartInfo.type),
+ isEchartsWithStatistics: isEchartsWithStatistics(props.chartInfo.type),
+ isSingleValue: isSingleValue(props.chartInfo.type),
+ isSingleValueWithEcharts: isSingleValueWithEcharts(props.chartInfo.type),
+ isSingleValueWithEchartsTemp: isSingleValueWithEchartsTemp(props.chartInfo.type),
+ isRelationShip: isRelationShip(props.chartInfo.type),
+ isTable: isTable(props.chartInfo.type),
+ isCurrentTable: isCurrentTable(props.chartInfo.type),
+ isActiveIpTable: isActiveIpTable(props.chartInfo.type),
+ isMap: isMap(props.chartInfo.type),
+ isTitle: isTitle(props.chartInfo.type),
+ isMapLine: isMapLine(props.chartInfo.type),
+ isMapBlock: isMapBlock(props.chartInfo.type),
+ isTabs: isTabs(props.chartInfo.type),
+ isGroup: isGroup(props.chartInfo.type),
+ isBlock: isBlock(props.chartInfo.type),
+ isSankey: isSankey(props.chartInfo.type),
+ isIpBasicInfo: isIpBasicInfo(props.chartInfo.type),
+ isIpHostedDomain: isIpHostedDomain(props.chartInfo.type),
+ isIpOpenPort: isIpOpenPort(props.chartInfo.type),
+ isDomainWhois: isDomainWhois(props.chartInfo.type),
+ isDomainDnsRecord: isDomainDnsRecord(props.chartInfo.type),
+ isCryptocurrencyEventList: isCryptocurrencyEventList(props.chartInfo.type),
+ isAppBasicInfo: isAppBasicInfo(props.chartInfo.type),
+ isAppRelatedDomain: isAppRelatedDomain(props.chartInfo.type)
}
- },
- unmounted () {
- window.removeEventListener('resize', this.throttle)
}
}
</script>
diff --git a/src/views/charts/Chart2.vue b/src/views/charts/Chart2.vue
deleted file mode 100644
index 5ce07b18..00000000
--- a/src/views/charts/Chart2.vue
+++ /dev/null
@@ -1,358 +0,0 @@
-<template>
- <div class="cn-chart">
- <loading :loading="loading && !isTabs && !isBlock && !isGroup"></loading>
- <chart-no-data v-if="isNoData"></chart-no-data>
- <template v-else>
-
- <chart-tabs
- v-if="isTabs"
- :chart-info="chartInfo"
- :query-params="queryParams"
- :entity="entity"
- ></chart-tabs>
-
- <chart-map
- v-else-if="isMap && !isIpBasicInfo"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :query-params="queryParams"
- :entity="entity"
- @showLoading="showLoading"
- ></chart-map>
-
- <chart-single-value
- v-else-if="isSingleValue"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :query-params="queryParams"
- @showLoading="showLoading"
- ></chart-single-value>
-
- <chart-block
- v-else-if="isBlock"
- ref="chart"
- :timeFilter="queryParams"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :entity="entity"
- ></chart-block>
-
- <chart-group
- v-else-if="isGroup"
- :timeFilter="queryParams"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :entity="entity"
- ></chart-group>
-
- <ip-basic-info
- v-else-if="isIpBasicInfo"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :entity="entity"
- ></ip-basic-info>
-
- <chart-time-bar
- v-else-if="isEchartsTimeBar"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :result-type="resultType"
- :query-params="queryParams"
- @showLoading="showLoading"
- ></chart-time-bar>
-
- <chart-category-bar
- v-else-if="isEchartsCategoryBar"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :result-type="resultType"
- :query-params="queryParams"
- @showLoading="showLoading"
- ></chart-category-bar>
-
- <chart-ip-open-port-bar
- v-else-if="isIpOpenPortBar"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :result-type="resultType"
- :query-params="queryParams"
- @showLoading="showLoading"
- ></chart-ip-open-port-bar>
-
- <chart-table
- v-else-if="isTable && isCurrentTable"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :table="table"
- :query-params="queryParams"
- @showLoading="showLoading"
- ></chart-table>
-
- <chart-active-ip-table
- v-else-if="isActiveIpTable"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :table="table"
- :query-params="queryParams"
- ></chart-active-ip-table>
-
- <chart-app-basic-info
- v-else-if="isAppBasicInfo"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :query-params="queryParams"
- ></chart-app-basic-info>
-
- <chart-domain-whois
- v-else-if="isDomainWhois"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :query-params="queryParams"
- ></chart-domain-whois>
-
- <chart-domain-dns-record
- v-else-if="isDomainDnsRecord"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :query-params="queryParams"
- ></chart-domain-dns-record>
-
- <chart-cryptocurrency-event-list
- v-else-if="isCryptocurrencyEventList"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :query-params="queryParams"
- ></chart-cryptocurrency-event-list>
-
- <chart-relation-ship
- v-else-if="isRelationShip"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :query-params="queryParams"
- ></chart-relation-ship>
-
- <chart-san-key
- v-else-if="isSankey"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :query-params="queryParams"
- :entity="entity"
- ></chart-san-key>
-
- <chart-echart
- v-else-if="isEchartsLine || isEchartsPie"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :result-type="resultType"
- @showLoading="showLoading"
- ></chart-echart>
-
- <chart-echart-with-statistics
- v-else-if="isEchartsWithStatistics"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :result-type="resultType"
- @showLoading="showLoading"
- ></chart-echart-with-statistics>
-
- <chart-echart-with-table
- v-else-if="isEchartsWithTable"
- :chart-info="chartInfo"
- :chart-data="chartData"
- :query-params="queryParams"
- :result-type="resultType"
- :order-pie-table="orderPieTable"
- @showLoading="showLoading"
- ></chart-echart-with-table>
-
- <chart-echart-ip-hosted-domain
- v-else-if="isIpHostedDomain"
- :chart-info="chartInfo"
- :chart-data="chartData"
- @showLoading="showLoading"
- :entity="entity"
- ></chart-echart-ip-hosted-domain>
-
- <chart-echart-app-relate-domain
- v-else-if="isAppRelatedDomain"
- :chart-info="chartInfo"
- :chart-data="chartData"
- @showLoading="showLoading"
- :entity="entity"
- ></chart-echart-app-relate-domain>
-
- </template>
- </div>
-</template>
-
-<script>
-import Loading from '@/components/common/Loading'
-import ChartNoData from '@/views/charts/charts/ChartNoData'
-import ChartTabs from '@/views/charts/charts/ChartTabs'
-import ChartMap from '@/views/charts/charts/ChartMap'
-import ChartSingleValue from '@/views/charts/charts/ChartSingleValue'
-import ChartBlock from '@/views/charts/charts/ChartBlock'
-import ChartGroup from '@/views/charts/charts/ChartGroup'
-import IpBasicInfo from '@/views/charts/charts/IpBasicInfo'
-import ChartEchart from '@/views/charts/charts/ChartEchart'
-import ChartEchartWithStatistics from '@/views/charts/charts/ChartEchartWithStatistics'
-import ChartEchartWithTable from '@/views/charts/charts/ChartEchartWithTable'
-import ChartEchartIpHostedDomain from '@/views/charts/charts/ChartEchartIpHostedDomain'
-import ChartEchartAppRelateDomain from '@/views/charts/charts/ChartEchartAppRelateDomain'
-import ChartActiveIpTable from '@/views/charts/charts/ChartActiveIpTable'
-import ChartTimeBar from './charts/ChartTimeBar'
-import ChartCategoryBar from './charts/ChartCategoryBar'
-import ChartIpOpenPortBar from './charts/ChartIpOpenPortBar'
-import ChartTable from './charts/ChartTable'
-import ChartAppBasicInfo from '@/views/charts/charts/ChartAppBasicInfo'
-import ChartDomainWhois from '@/views/charts/charts/ChartDomainWhois'
-import ChartDomainDnsRecord from '@/views/charts/charts/ChartDomainDnsRecord'
-import ChartCryptocurrencyEventList from '@/views/charts/charts/ChartCryptocurrencyEventList'
-import ChartRelationShip from '@/views/charts/charts/ChartRelationShip'
-import ChartSanKey from '@/views/charts/charts/ChartSanKey'
-import {
- isEcharts,
- isEchartsLine,
- isSingleValue,
- isTable,
- isCurrentTable,
- isActiveIpTable,
- isTitle,
- isMap,
- getOption,
- isEchartsPie,
- isEchartsWithTable,
- isEchartsWithStatistics,
- isEchartsTimeBar,
- isEchartsCategoryBar,
- isIpOpenPortBar,
- isMapLine,
- isMapBlock,
- isSingleValueWithEcharts,
- isSingleValueWithEchartsTemp,
- isRelationShip,
- isTabs,
- isGroup,
- isSankey,
- isIpBasicInfo,
- isIpOpenPort,
- isIpHostedDomain,
- isDomainWhois,
- isDomainDnsRecord,
- isCryptocurrencyEventList,
- isAppBasicInfo,
- isAppRelatedDomain,
- isBlock
-} from './charts/tools'
-import _ from 'lodash'
-
-export default {
- name: 'chart',
- components: {
- ChartSanKey,
- ChartCryptocurrencyEventList,
- ChartDomainDnsRecord,
- ChartDomainWhois,
- ChartAppBasicInfo,
- ChartActiveIpTable,
- ChartTable,
- IpBasicInfo,
- ChartSingleValue,
- Loading,
- ChartNoData,
- ChartTabs,
- ChartMap,
- ChartBlock,
- ChartTimeBar,
- ChartCategoryBar,
- ChartIpOpenPortBar,
- ChartRelationShip,
- ChartGroup,
- ChartEchartWithStatistics,
- ChartEchart,
- ChartEchartWithTable,
- ChartEchartIpHostedDomain,
- ChartEchartAppRelateDomain
- },
- props: {
- chartInfo: Object,
- chartData: [Object, Array, String], // 数据在父组件查询后传入,本组件内不查询,只根据接传递的数据来渲染
- resultType: Object, // 返回数据的类型
- queryParams: Object, // 接口请求参数
- customChartOption: Object, // 需要自定义echarts的option时传入,非必须;传入该值时仍需传对应格式的chartData
- isFullscreen: Boolean,
- loading: Boolean,
- panelLock: Boolean,
- entity: Object,
- isError: Boolean,
- table: Object,
- orderPieTable: Object
- },
- computed: {
- isNoData () {
- return !this.loading && (_.isEmpty(this.chartData) || this.isError) && !this.isSingleValue && !this.isTabs && !this.isDomainDnsRecord && !this.isCryptocurrencyEventList && !this.isActiveIpTable && !this.isMap
- },
- chartOption () {
- if (this.customChartOption) {
- return _.cloneDeep(this.customChartOption)
- } else {
- return getOption(this.chartInfo.type)
- }
- }
- },
- methods: {
- resize () {
- this.$refs['chart' + this.chartInfo.id] && this.$refs['chart' + this.chartInfo.id].resize()
- },
- showLoading (show) {
- this.$emit('showLoading', show)
- },
- initEchartsWithTable () {
- this.$refs['chart' + this.chartInfo.id] && this.$refs['chart' + this.chartInfo.id].initEchartsWithTable(`chart${this.chartInfo.id}`)
- }
-
- },
- watch: {
- chartData: {
- deep: true,
- handler (n) {
- }
- }
- },
- setup (props) {
- return {
- isEcharts: isEcharts(props.chartInfo.type),
- isEchartsLine: isEchartsLine(props.chartInfo.type),
- isEchartsTimeBar: isEchartsTimeBar(props.chartInfo.type),
- isEchartsCategoryBar: isEchartsCategoryBar(props.chartInfo.type),
- isIpOpenPortBar: isIpOpenPortBar(props.chartInfo.type),
- isEchartsPie: isEchartsPie(props.chartInfo.type),
- isEchartsWithTable: isEchartsWithTable(props.chartInfo.type),
- isEchartsWithStatistics: isEchartsWithStatistics(props.chartInfo.type),
- isSingleValue: isSingleValue(props.chartInfo.type),
- isSingleValueWithEcharts: isSingleValueWithEcharts(props.chartInfo.type),
- isSingleValueWithEchartsTemp: isSingleValueWithEchartsTemp(props.chartInfo.type),
- isRelationShip: isRelationShip(props.chartInfo.type),
- isTable: isTable(props.chartInfo.type),
- isCurrentTable: isCurrentTable(props.chartInfo.type),
- isActiveIpTable: isActiveIpTable(props.chartInfo.type),
- isMap: isMap(props.chartInfo.type),
- isTitle: isTitle(props.chartInfo.type),
- isMapLine: isMapLine(props.chartInfo.type),
- isMapBlock: isMapBlock(props.chartInfo.type),
- isTabs: isTabs(props.chartInfo.type),
- isGroup: isGroup(props.chartInfo.type),
- isBlock: isBlock(props.chartInfo.type),
- isSankey: isSankey(props.chartInfo.type),
- isIpBasicInfo: isIpBasicInfo(props.chartInfo.type),
- isIpHostedDomain: isIpHostedDomain(props.chartInfo.type),
- isIpOpenPort: isIpOpenPort(props.chartInfo.type),
- isDomainWhois: isDomainWhois(props.chartInfo.type),
- isDomainDnsRecord: isDomainDnsRecord(props.chartInfo.type),
- isCryptocurrencyEventList: isCryptocurrencyEventList(props.chartInfo.type),
- isAppBasicInfo: isAppBasicInfo(props.chartInfo.type),
- isAppRelatedDomain: isAppRelatedDomain(props.chartInfo.type)
- }
- }
-}
-</script>
diff --git a/src/components/charts/ChartError.vue b/src/views/charts/ChartError.vue
index 147726d2..147726d2 100644
--- a/src/components/charts/ChartError.vue
+++ b/src/views/charts/ChartError.vue
diff --git a/src/views/charts/ChartHeader.vue b/src/views/charts/ChartHeader.vue
index 47322a48..1ae0d764 100644
--- a/src/views/charts/ChartHeader.vue
+++ b/src/views/charts/ChartHeader.vue
@@ -115,7 +115,7 @@
<script>
import { isTitle, isTabs, isBlock, isTable, isActiveIpTable, isCurrentTable, isGroup, isEchartsWithTable } from './charts/tools'
-import ChartError from '@/components/charts/ChartError'
+import ChartError from '@/views/charts/ChartError'
import { getNowTime } from '@/utils/date-util'
import { ref } from 'vue'
import { chartTableTopOptions, chartActiveIpTableOrderOptions, chartPieTableTopOptions } from '@/utils/constants'
diff --git a/src/views/charts/PanelChart.vue b/src/views/charts/PanelChart.vue
index e364f48f..98996945 100644
--- a/src/views/charts/PanelChart.vue
+++ b/src/views/charts/PanelChart.vue
@@ -44,7 +44,7 @@
<script>
import ChartHeader from './ChartHeader'
-import Chart from '@/views/charts/Chart2'
+import Chart from '@/views/charts/Chart'
import testData from './charts/testData'
import {
isEcharts,
@@ -75,7 +75,7 @@ import {
isAppRelatedDomain,
isBlock
} from './charts/tools'
-import { tableTitleMapping, legendMapping } from '@/components/charts/chart-table-title'
+import { tableTitleMapping, legendMapping } from '@/views/charts/charts/chart-table-title'
import { replaceUrlPlaceholder } from '@/utils/tools'
import { getNowTime, getSecond } from '@/utils/date-util'
import { chartPieTableTopOptions, chartTableDefaultPageSize, chartTableTopOptions } from '@/utils/constants'
diff --git a/src/views/charts/charts/ChartCategoryBar.vue b/src/views/charts/charts/ChartCategoryBar.vue
index 44ec8936..7523f7ab 100644
--- a/src/views/charts/charts/ChartCategoryBar.vue
+++ b/src/views/charts/charts/ChartCategoryBar.vue
@@ -7,7 +7,7 @@ import unitConvert from '@/utils/unit-convert'
import * as echarts from 'echarts'
import { lineToSpace } from '@/utils/tools'
import { unitTypes } from '@/utils/constants'
-import { legendMapping } from '@/components/charts/chart-table-title'
+import { legendMapping } from '@/views/charts/charts/chart-table-title'
import {
categoryBar
} from '@/views/charts/charts/options/bar'
diff --git a/src/views/charts/charts/ChartEchart.vue b/src/views/charts/charts/ChartEchart.vue
index 2649780b..cab65a64 100644
--- a/src/views/charts/charts/ChartEchart.vue
+++ b/src/views/charts/charts/ChartEchart.vue
@@ -9,7 +9,7 @@ import { lineToSpace } from '@/utils/tools'
import { unitTypes } from '@/utils/constants'
import chartEchartMixin from './chart-echart-mixin'
import { getOption, isEchartsPie } from './tools'
-import { legendMapping } from '@/components/charts/chart-table-title'
+import { legendMapping } from '@/views/charts/charts/chart-table-title'
export default {
name: 'ChartEchart',
diff --git a/src/views/charts/charts/ChartEchartWithStatistics.vue b/src/views/charts/charts/ChartEchartWithStatistics.vue
index b3bfccdf..d9991eff 100644
--- a/src/views/charts/charts/ChartEchartWithStatistics.vue
+++ b/src/views/charts/charts/ChartEchartWithStatistics.vue
@@ -7,7 +7,7 @@
<script>
import * as echarts from 'echarts'
-import StatisticsLegend from '@/components/charts/StatisticsLegend'
+import StatisticsLegend from '@/views/charts/charts/StatisticsLegend'
import {
lineWithStatistics
} from '@/views/charts/charts/options/line'
diff --git a/src/views/charts/charts/ChartIpOpenPortBar.vue b/src/views/charts/charts/ChartIpOpenPortBar.vue
index 50c67e0f..42334acd 100644
--- a/src/views/charts/charts/ChartIpOpenPortBar.vue
+++ b/src/views/charts/charts/ChartIpOpenPortBar.vue
@@ -36,7 +36,7 @@
<script>
import lodash from 'lodash'
import { ipOpenPortBar } from '@/views/charts/charts/options/bar'
-import { getChartColor } from '@/components/charts/chart-options'
+import { getChartColor } from '@/views/charts/charts/chart-options'
import * as echarts from 'echarts'
export default {
name: 'ChartIpOpenPortBar',
diff --git a/src/views/charts/charts/ChartSingleValue.vue b/src/views/charts/charts/ChartSingleValue.vue
index 761eb5a2..3ac52153 100644
--- a/src/views/charts/charts/ChartSingleValue.vue
+++ b/src/views/charts/charts/ChartSingleValue.vue
@@ -67,7 +67,7 @@ import {
import { get } from '@/utils/http'
import { replaceUrlPlaceholder } from '@/utils/tools'
import * as echarts from 'echarts'
-import { getOption, getChartColor } from '@/components/charts/chart-options'
+import { getOption, getChartColor } from '@/views/charts/charts/chart-options'
export default {
name: 'chartSingleValue',
props: {
diff --git a/src/views/charts/charts/ChartTimeBar.vue b/src/views/charts/charts/ChartTimeBar.vue
index 89e35b02..20911ece 100644
--- a/src/views/charts/charts/ChartTimeBar.vue
+++ b/src/views/charts/charts/ChartTimeBar.vue
@@ -7,7 +7,7 @@ import unitConvert from '@/utils/unit-convert'
import * as echarts from 'echarts'
import { lineToSpace } from '@/utils/tools'
import { unitTypes } from '@/utils/constants'
-import { legendMapping } from '@/components/charts/chart-table-title'
+import { legendMapping } from '@/views/charts/charts/chart-table-title'
import {
timeBar
} from '@/views/charts/charts/options/bar'
diff --git a/src/components/charts/StatisticsLegend.vue b/src/views/charts/charts/StatisticsLegend.vue
index faa3e242..c4c12fe4 100644
--- a/src/components/charts/StatisticsLegend.vue
+++ b/src/views/charts/charts/StatisticsLegend.vue
@@ -19,7 +19,7 @@
</template>
<script>
-import { getChartColor } from '@/components/charts/chart-options'
+import { getChartColor } from '@/views/charts/charts/chart-options'
import unitConvert, { valueToRangeValue } from '@/utils/unit-convert'
export default {
name: 'StatisticsLegend',
diff --git a/src/components/charts/chart-table-title.js b/src/views/charts/charts/chart-table-title.js
index bb9194d1..bb9194d1 100644
--- a/src/components/charts/chart-table-title.js
+++ b/src/views/charts/charts/chart-table-title.js
diff --git a/src/views/detections/Index.vue b/src/views/detections/Index.vue
new file mode 100644
index 00000000..cca35d85
--- /dev/null
+++ b/src/views/detections/Index.vue
@@ -0,0 +1,13 @@
+<template>
+
+</template>
+
+<script>
+export default {
+ name: 'Index'
+}
+</script>
+
+<style scoped>
+
+</style>
diff --git a/src/views/entities/EntityExplorer.vue b/src/views/entities/EntityExplorer.vue
deleted file mode 100644
index 2d2ee1d6..00000000
--- a/src/views/entities/EntityExplorer.vue
+++ /dev/null
@@ -1,487 +0,0 @@
-<template>
- <div class="outer-box">
- <div class="cn-entities">
- <el-input
- v-model="searchContentTemp"
- style="width: 100%; grid-area: 1 / 1 / 1 / 3;"
- type="text"
- @keyup.enter="enter"
- >
- <template #prefix>
- <span style="padding-left: 4px"><i class="el-icon-search"></i></span>
- </template>
- </el-input>
- <!-- 筛选区域 -->
- <left-filter
- :top-filter-data="topFilterData"
- :bottom-filter-data="bottomFilterData"
- @select="select"
- @showMore="showMore"
- style="grid-area: 2 / 1 / 3 / 2;"
- ></left-filter>
- <!-- 内容区域 -->
- <entity-list
- :list-data="listData"
- :from="from"
- :loading="loading"
- :page-obj="pageObjRight"
- @showDetail="entityDetail"
- @pageNo="pageNoRight"
- style="grid-area: 2 / 2 / 3 / 3;"
- ></entity-list>
- </div>
- </div>
- <entity-detail
- v-model:show-detail="showDetail"
- top="5vh"
- :show-close="false"
- :entity="currentEntity"></entity-detail>
-</template>
-
-<script>
-import { entityType, entityFilterType } from '@/utils/constants'
-import LeftFilter from '@/components/entities/LeftFilter'
-import EntityList from '@/components/entities/EntityList'
-import { getEntityFilter, getEntityList, getEntityCount } from '@/utils/api'
-import { doubleQuotationToSingle } from '@/utils/tools'
-import EntityDetail from '@/components/entities/EntityDetail'
-export default {
- name: 'EntityExplorer',
- data () {
- return {
- searchContentTemp: '', // 搜索框内的文本内容,按回车键后为searchContent赋值
- searchContent: '', // 查询语句
- searchParams: null, // 搜索参数,格式为[{ name: xxx, value: xxx }, ...]
- filterObj: {}, // 被选中的左侧过滤条件
- topFilterData: {}, // 左侧上方的过滤列表数据
- bottomFilterData: {}, // 左侧下方的过滤列表数据
- listData: [], // 右侧实体列表数据
- pageObjLeftTop: {
- pageNo: 1,
- pageSize: 10,
- total: 0
- },
- pageObjLeftBottom: {
- pageNo: 1,
- pageSize: 10,
- total: 0
- },
- pageObjRight: {
- pageNo: 1,
- pageSize: 20,
- total: 0
- },
- showDetail: false,
- currentEntity: {},
- loading: true
- }
- },
- components: {
- EntityDetail,
- LeftFilter,
- EntityList
- },
- methods: {
- enter () {
- if (!this.searchContentTemp) {
- this.reset()
- } else {
- this.searchContent = this.searchContentTemp
- }
- },
- async showMore (column) {
- let index = 0
- switch (column) {
- case entityFilterType.ip.country:
- case entityFilterType.domain.categoryGroup:
- case entityFilterType.app.appCategory: {
- this.pageObjLeftTop.pageNo++
- break
- }
- case entityFilterType.ip.asn:
- case entityFilterType.domain.reputationLevel:
- case entityFilterType.app.appRisk: {
- index = 1
- this.pageObjLeftBottom.pageNo++
- break
- }
- default: break
- }
- const { topFilterData, bottomFilterData } = await this.queryFilterData({ column, q: doubleQuotationToSingle(this.searchContent), from: this.from })
- if (index === 1) {
- this.bottomFilterData = {
- ...this.bottomFilterData,
- data: this.$_.concat(this.bottomFilterData.data, bottomFilterData.data),
- hasnotMore: bottomFilterData.length < 10
- }
- } else {
- this.topFilterData = {
- ...this.topFilterData,
- data: this.$_.concat(this.topFilterData.data, topFilterData.data),
- hasnotMore: topFilterData.length < 10
- }
- }
- },
- async search () {
- const vm = this
- const params = { from: this.from, q: doubleQuotationToSingle(this.searchContent) }
- this.loading = true
- try {
- this.listData = (await getEntityList({ ...this.pageObjRight, ...params })).map(d => {
- return {
- ...d,
- id: window.btoa(unescape(encodeURIComponent(d.ip || d.domainName || d.appName))),
- latestSent: null,
- latestReceived: null
- }
- })
- this.pageObjRight.total = await getEntityCount(params)
- const { topFilterData, bottomFilterData } = await this.queryFilterData(params)
- this.topFilterData = topFilterData
- this.bottomFilterData = bottomFilterData
- } finally {
- setTimeout(() => {
- vm.loading = false
- }, 250)
- }
- },
- /* 重置条件 */
- reset () {
- this.pageObjLeftTop = {
- pageNo: 1,
- pageSize: 10
- }
- this.pageObjLeftBottom = {
- pageNo: 1,
- pageSize: 10
- }
- this.pageObjRight = {
- pageNo: 1,
- pageSize: 20
- }
- this.searchParams = null
- this.searchParams = []
- },
- async queryFilterData (params) {
- let topFilterParams = { ...params, ...this.pageObjLeftTop }
- let bottomFilterParams = { ...params, ...this.pageObjLeftBottom }
- const keys = Object.keys(this.filterObj)
- if (!this.$_.isEmpty(keys)) {
- let hasTopColumn = false
- let hasBottomColumn = false
- keys.forEach(key => {
- switch (key) {
- case entityFilterType.ip.country:
- case entityFilterType.domain.categoryGroup:
- case entityFilterType.app.appCategory: {
- hasTopColumn = true
- topFilterParams = { ...topFilterParams, column: key }
- break
- }
- case entityFilterType.ip.asn:
- case entityFilterType.domain.reputationLevel:
- case entityFilterType.app.appRisk: {
- hasBottomColumn = true
- bottomFilterParams = { ...bottomFilterParams, column: key }
- break
- }
- default: break
- }
- })
- if (!hasTopColumn) {
- topFilterParams = { ...topFilterParams, column: this.getDefaultTopColumn(this.from) }
- }
- if (!hasBottomColumn) {
- bottomFilterParams = { ...bottomFilterParams, column: this.getDefaultBottomColumn(this.from) }
- }
- } else {
- topFilterParams = { ...topFilterParams, column: this.getDefaultTopColumn(this.from) }
- bottomFilterParams = { ...bottomFilterParams, column: this.getDefaultBottomColumn(this.from) }
- }
- const topFilterListData = await getEntityFilter(topFilterParams) || []
- const bottomFilterListData = await getEntityFilter(bottomFilterParams) || []
- let topFilterData = { data: topFilterListData, hasnotMore: topFilterListData.length < 10, column: topFilterParams.column }
- let bottomFilterData = { data: bottomFilterListData, hasnotMore: bottomFilterListData.length < 10, column: bottomFilterParams.column }
- switch (this.from) {
- case 'ip': {
- topFilterData = { ...topFilterData, icon: 'cn-icon cn-icon-country', title: this.$t('entities.countryOrRegion') }
- bottomFilterData = { ...bottomFilterData, icon: 'cn-icon cn-icon-cloud', title: this.$t('entities.asn') }
- break
- }
- case 'domain': {
- topFilterData = { ...topFilterData, icon: 'cn-icon cn-icon-category', title: this.$t('entities.groupAndName') }
- bottomFilterData = { ...bottomFilterData, icon: 'cn-icon cn-icon-risk', title: this.$t('entities.creditLevel') }
- break
- }
- case 'app': {
- topFilterData = { ...topFilterData, icon: 'cn-icon cn-icon-category', title: this.$t('entities.categoryAndSub') }
- bottomFilterData = { ...bottomFilterData, icon: 'cn-icon cn-icon-risk', title: this.$t('entities.riskLevel') }
- break
- }
- default: break
- }
- return { topFilterData, bottomFilterData }
- },
- getDefaultTopColumn (from) {
- let column
- switch (from) {
- case 'ip': {
- column = entityFilterType.ip.country
- break
- }
- case 'domain': {
- column = entityFilterType.domain.categoryGroup
- break
- }
- case 'app': {
- column = entityFilterType.app.appCategory
- break
- }
- default: break
- }
- return column
- },
- getDefaultBottomColumn (from) {
- let column = ''
- switch (from) {
- case 'ip': {
- column = entityFilterType.ip.asn
- break
- }
- case 'domain': {
- column = entityFilterType.domain.reputationLevel
- break
- }
- case 'app': {
- column = entityFilterType.app.appRisk
- break
- }
- default: break
- }
- return column
- },
- async select (data, node, index, column) {
- if (index === 0) { // 上部过滤
- if (node.level === 1) {
- const columns = { ...this.filterObj, [column]: data.name }
- // 清除二级条件
- delete columns[entityFilterType.ip.region]
- delete columns[entityFilterType.domain.categoryName]
- delete columns[entityFilterType.app.appSubcategory]
- this.filterObj = columns
- } else if (node.level === 2) {
- const columns = { ...this.filterObj, [column]: data.parentName }
- // 清除一级条件
- let childColumn
- switch (column) {
- case entityFilterType.ip.country: {
- childColumn = entityFilterType.ip.region
- break
- }
- case entityFilterType.domain.categoryGroup: {
- childColumn = entityFilterType.domain.categoryName
- break
- }
- case entityFilterType.app.appCategory: {
- childColumn = entityFilterType.app.appSubcategory
- break
- }
- default: break
- }
- columns[childColumn] = data.name
- this.filterObj = columns
- }
- } else if (index === 1) { // 下部过滤
- this.filterObj[column] = data.name
- }
- },
- async loadLevel2FilterData (node, parentColumn) {
- if (parentColumn) {
- const where = {}
- where[parentColumn] = node.data.name
- let column
- switch (parentColumn) {
- case entityFilterType.ip.country: {
- column = entityFilterType.ip.region
- break
- }
- case entityFilterType.domain.categoryGroup: {
- column = entityFilterType.domain.categoryName
- break
- }
- case entityFilterType.app.appCategory: {
- column = entityFilterType.app.appSubcategory
- break
- }
- default: break
- }
- const params = {
- q: doubleQuotationToSingle(this.searchContent),
- from: this.from,
- pageNo: 1,
- where,
- column
- }
- const result = await getEntityFilter(params)
- return result.map(r => ({ ...r, leaf: true, parentName: node.data.name }))
- } else {
- return []
- }
- },
- pageNoRight (val) {
- this.pageObjRight.pageNo = val
- this.search()
- },
- entityDetail (entity, tabs) {
- this.typeName = `${this.from.toLowerCase()}EntityDetail`
- this.currentEntity = entity
- this.showDetail = true
- }
- },
- watch: {
- /* entity类型切换时,分页、搜索信息重置 */
- from (n) {
- this.reset()
- },
- /* 搜索框searchContent、左侧过滤条件filterObj互相联动
- * 监听filterObj改动,将改动同步给searchParams
- * 监听searchContent改动,将改动同步给searchParams
- * 监听searchParams,将改动同步给filterObj、searchContent之一,并重新请求接口,获取左侧过滤条件和右侧entity列表
- * */
- filterObj: {
- deep: true,
- handler (n) {
- if (n) {
- const searchParams = this.$_.cloneDeep(this.searchParams)
- let change = false
- Object.keys(n).forEach(key => {
- let containKey = false
- searchParams.forEach(item => {
- if (item.name === key) {
- containKey = true
- if (item.value !== n[key]) {
- change = true
- item.value !== n[key] && (item.value = n[key])
- }
- }
- })
- if (!containKey) {
- change = true
- const name = key
- const value = n[key]
- const param = { name, value }
- searchParams.push(param)
- }
- })
- if (change) {
- this.searchParams = searchParams
- }
- }
- }
- },
- searchContent (n) {
- if (n) {
- const paramsArr = n.split(/\s[aA][nN][dD]\s/)
- const paramsObj = {}
- let change = false
- paramsArr.forEach(string => {
- const param = string.split('=')
- if (param.length > 1) {
- let value = param[1].trim()
- const valueArr = value.split('"')
- if (valueArr.length > 2) {
- value = valueArr[1].trim()
- }
- paramsObj[param[0].trim()] = value
- }
- })
- const searchParams = this.$_.cloneDeep(this.searchParams)
- const newSearchParams = []
- const keys = Object.keys(paramsObj)
- keys.forEach(key => {
- newSearchParams.push({ name: key, value: paramsObj[key] })
- let containKey = false
- searchParams.forEach(item => {
- if (item.name === key) {
- containKey = true
- if (item.value !== paramsObj[key]) {
- change = true
- item.value = paramsObj[key]
- }
- }
- })
- if (!containKey) {
- change = true
- searchParams.push({ name: key, value: paramsObj[key] })
- }
- })
- if (newSearchParams.length !== searchParams.length) {
- this.searchParams = newSearchParams
- } else if (change) {
- this.searchParams = searchParams
- }
- } else {
- this.reset()
- }
- this.searchContentTemp !== n && (this.searchContentTemp = n)
- },
- searchParams: {
- deep: true,
- handler (n) {
- if (n) {
- let fromInput = false // input内容改变导致的变化
- let fromFilter = false // 左侧filter过滤条件改变导致的变化
- const filterKeys = Object.keys(this.filterObj)
- if (n.length === 0) {
- this.searchContentTemp = ''
- this.searchContent = ''
- this.filterObj = {}
- } else if (filterKeys.length !== n.length) {
- fromInput = true
- } else {
- fromFilter = true
- }
- if (fromInput) { // 是input导致的改变,则同步给filter
- const filterObj = {}
- n.forEach(item => {
- filterObj[item.name] = item.value
- })
- this.filterObj = filterObj
- }
- if (fromFilter) { // 是filter导致的改变,则同步给input
- let searchContent = ''
- n.forEach(item => {
- if (searchContent) {
- searchContent += ' AND '
- }
- searchContent += `${item.name}="${item.value}"`
- })
- this.searchContent = searchContent
- }
- // 请求接口,获取左侧过滤条件和右侧entity列表
- this.search()
- }
- }
- }
- },
- computed: {
- from () {
- return this.$store.getters.from
- }
- },
-
- async mounted () {
- this.$store.commit('showEntityTypeSelector', true)
- this.searchParams = []
- },
- setup () {
- return {
- entityType // 所有entity类型,用于header下拉框选择
- }
- },
- beforeUnmount () {
- this.$store.commit('entityTypeChange', Object.keys(entityType)[0])
- this.$store.commit('showEntityTypeSelector', false)
- }
-}
-</script>
diff --git a/src/views/entityExplorer/entityList/detailOverview/App.vue b/src/views/entityExplorer/entityList/detailOverview/App.vue
index fc6c91cd..bd743668 100644
--- a/src/views/entityExplorer/entityList/detailOverview/App.vue
+++ b/src/views/entityExplorer/entityList/detailOverview/App.vue
@@ -133,14 +133,14 @@
</div>
</div>
<div class="overview-map overview-map--app">
- <chart2
+ <chart
:chart-info="chart"
:chart-data="chartData"
:entity="entityCopy"
:query-params="getQueryParams"
:hide-header="true"
@getCurrentTimeRange="getCurrentTimeRange"
- ></chart2>
+ ></chart>
</div>
</template>
@@ -149,7 +149,7 @@ import { api } from '@/utils/api'
import entityDetailMixin from './entityDetailMixin'
import { unitTypes } from '@/utils/constants'
import unitConvert from '@/utils/unit-convert'
-import Chart2 from '@/views/charts/Chart2'
+import Chart from '@/views/charts/Chart'
import _ from 'lodash'
import ChartSingleValue from '@/views/charts/charts/ChartSingleValue'
import { get } from '@/utils/http'
@@ -158,7 +158,7 @@ export default {
name: 'App',
mixins: [entityDetailMixin],
components: {
- Chart2,
+ Chart,
ChartSingleValue
},
data () {
diff --git a/src/views/entityExplorer/entityList/detailOverview/Domain.vue b/src/views/entityExplorer/entityList/detailOverview/Domain.vue
index 4af40f47..ca055306 100644
--- a/src/views/entityExplorer/entityList/detailOverview/Domain.vue
+++ b/src/views/entityExplorer/entityList/detailOverview/Domain.vue
@@ -127,7 +127,7 @@
<div class="row__label">{{$t('entities.recentSecurity')}}</div>
<div class="row__content">{{entityData.securityNum || '-'}}</div>
</div>
- <div class="overview__row overview__row--small-font" v-for="security in entityData.securityList">
+ <div class="overview__row overview__row--small-font" v-for="(security, i) in entityData.securityList" :key="i">
<div class="row__label row__label--width160">{{security.startTime}}</div>
<div class="row__content row__content--width200">
<div class="alert-level-tag alert-level-tag--high">{{security.securitySeverity}}</div>
@@ -141,14 +141,14 @@
</div>
</div>
<div class="overview-map">
- <chart2
+ <chart
:chart-info="chart"
:chart-data="chartData"
:entity="entityCopy"
:query-params="getQueryParams"
:hide-header="true"
@getCurrentTimeRange="getCurrentTimeRange"
- ></chart2>
+ ></chart>
</div>
</template>
@@ -158,14 +158,14 @@ import { api } from '@/utils/api'
import entityDetailMixin from './entityDetailMixin'
import { unitTypes } from '@/utils/constants'
import unitConvert from '@/utils/unit-convert'
-import Chart2 from '@/views/charts/Chart2'
+import Chart from '@/views/charts/Chart'
import _ from 'lodash'
import { get } from '@/utils/http'
export default {
name: 'Domain',
components: {
ChartSingleValue,
- Chart2
+ Chart
},
mixins: [entityDetailMixin],
data () {
diff --git a/src/views/entityExplorer/entityList/detailOverview/Ip.vue b/src/views/entityExplorer/entityList/detailOverview/Ip.vue
index 29ee1a8f..425c3b54 100644
--- a/src/views/entityExplorer/entityList/detailOverview/Ip.vue
+++ b/src/views/entityExplorer/entityList/detailOverview/Ip.vue
@@ -125,14 +125,14 @@
</div>
</div>
<div class="overview-map overview-map--ip">
- <chart2
+ <chart
:chart-info="chart"
:chart-data="chartData"
:entity="entityCopy"
:query-params="getQueryParams"
:hide-header="true"
@getCurrentTimeRange="getCurrentTimeRange"
- ></chart2>
+ ></chart>
</div>
</template>
@@ -142,7 +142,7 @@ import ChartSingleValue from '@/views/charts/charts/ChartSingleValue'
import { api } from '@/utils/api'
import { unitTypes } from '@/utils/constants'
import unitConvert from '@/utils/unit-convert'
-import Chart2 from '@/views/charts/Chart2'
+import Chart from '@/views/charts/Chart'
import _ from 'lodash'
import { get } from '@/utils/http'
@@ -150,7 +150,7 @@ export default {
name: 'Ip',
mixins: [entityDetailMixin],
components: {
- Chart2,
+ Chart,
ChartSingleValue
},
data () {
diff --git a/src/views/entityExplorer/entityList/detailOverview/entityDetailMixin.js b/src/views/entityExplorer/entityList/detailOverview/entityDetailMixin.js
index 64b53a07..2eda0558 100644
--- a/src/views/entityExplorer/entityList/detailOverview/entityDetailMixin.js
+++ b/src/views/entityExplorer/entityList/detailOverview/entityDetailMixin.js
@@ -1,7 +1,7 @@
import _ from 'lodash'
import { get } from '@/utils/http'
import * as echarts from 'echarts'
-import { entityListLineOption } from '@/components/charts/chart-options'
+import { entityListLineOption } from '@/views/charts/charts/chart-options'
import { unitTypes } from '@/utils/constants'
import unitConvert from '@/utils/unit-convert'
diff --git a/src/views/entityExplorer/entityList/entityListMixin.js b/src/views/entityExplorer/entityList/entityListMixin.js
index 9da3a6ca..ee2bedfd 100644
--- a/src/views/entityExplorer/entityList/entityListMixin.js
+++ b/src/views/entityExplorer/entityList/entityListMixin.js
@@ -2,8 +2,8 @@ import _ from 'lodash'
import { get } from '@/utils/http'
import { api } from '@/utils/api'
import * as echarts from 'echarts'
-import { entityListLineOption } from '@/components/charts/chart-options'
-import {riskLevelMapping, unitTypes} from '@/utils/constants'
+import { entityListLineOption } from '@/views/charts/charts/chart-options'
+import { riskLevelMapping, unitTypes } from '@/utils/constants'
export default {
props: {