| <!-- |
| # |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| --> |
| |
| <template> |
| <div class="app-container"> |
| <div class="filter-container"> |
| <el-button |
| class="filter-item" |
| style="margin-left: 10px;" |
| type="primary" |
| icon="el-icon-edit" |
| @click="handleCreate" |
| > |
| {{ $t('table.add') }} |
| </el-button> |
| </div> |
| |
| <el-table |
| :key="tableKey" |
| v-loading="listLoading" |
| :data="tableData" |
| :span-method="objectSpanMethod" |
| border |
| fit |
| highlight-current-row |
| style="width: 100%;" |
| @sort-change="sortChange" |
| > |
| <el-table-column |
| v-for="(item, index) of tableKeys" |
| :key="index" |
| :label="item.key" |
| :prop="item.key" |
| :width="item.width" |
| :class-name="item.align === 'left' ? '' : 'status-col'" |
| header-align="center" |
| > |
| <template v-if="item.key === 'nodes'"> |
| <el-table-column |
| label="IP/HOST" |
| width="150" |
| prop="ip" |
| class-name="status-col" |
| /> |
| |
| <el-table-column |
| label="Port" |
| width="150" |
| prop="port" |
| class-name="status-col" |
| /> |
| |
| <el-table-column |
| label="Weights" |
| width="150" |
| prop="weights" |
| class-name="status-col" |
| /> |
| </template> |
| </el-table-column> |
| <el-table-column |
| :label="$t('table.actions')" |
| align="center" |
| class-name="fixed-width" |
| > |
| <template slot-scope="{row}"> |
| <el-button |
| type="primary" |
| size="mini" |
| @click="handleToEdit(row)" |
| > |
| {{ $t('table.edit') }} |
| </el-button> |
| |
| <el-button |
| size="mini" |
| type="danger" |
| @click="handleRemove(row)" |
| > |
| {{ $t('table.delete') }} |
| </el-button> |
| </template> |
| </el-table-column> |
| </el-table> |
| </div> |
| </template> |
| |
| <script lang="ts"> |
| import { Component, Vue } from 'vue-property-decorator' |
| import { Form } from 'element-ui' |
| |
| import Pagination from '../../../components/Pagination/index.vue' |
| |
| import { getUpstreamList, removeUpstream } from '../../../api/schema/upstream' |
| |
| @Component({ |
| name: 'UpstreamList', |
| components: { |
| Pagination |
| } |
| }) |
| export default class extends Vue { |
| private tableKey = 0 |
| private list = [] |
| private total = 0 |
| private listLoading = true |
| private listQuery = { |
| page: 1, |
| limit: 20, |
| importance: undefined, |
| title: undefined, |
| type: undefined, |
| sort: '+id' |
| } |
| |
| private tableData: any[] = [] |
| private tableKeys: any[] = [] |
| private spanArr: any[] = [] |
| private position = 0 |
| |
| created() { |
| this.getList() |
| } |
| |
| private async getList() { |
| this.listLoading = true |
| |
| this.tableKeys = [ |
| { |
| key: 'id', |
| width: 80 |
| }, { |
| key: 'description', |
| width: 300, |
| align: 'left' |
| }, { |
| key: 'type', |
| width: 120 |
| }, { |
| key: 'nodes', |
| width: 'auto' |
| }, { |
| key: 'other', |
| width: 'auto' |
| } |
| ] |
| |
| let { node: { nodes = [] } } = await getUpstreamList() as any |
| nodes = [...nodes].map((item: any) => { |
| const id = item.key.match(/\/([a-zA-Z0-9-_]+)$/)[1] |
| const fakeId = id |
| const type = item.value.type |
| const desc = item.value.desc |
| |
| return { |
| id: fakeId, |
| realId: id, |
| type, |
| nodes: item.value.nodes, |
| other: JSON.stringify(item.value.k8s_deployment_info || {}), |
| description: desc |
| } |
| }) |
| |
| let tableData: any[] = [] |
| const arr = nodes.forEach((item: any) => { |
| if (!item.nodes) { |
| tableData = tableData.concat(item) |
| return |
| } |
| Object.entries(item.nodes || {}).forEach(([ipWithPort, weights]) => { |
| // 释放 nodes |
| item.nodes = {} |
| tableData = tableData.concat({ |
| ...item, |
| ip: ipWithPort.split(':')[0], |
| port: ipWithPort.split(':')[1], |
| weights |
| }) |
| }) |
| }) |
| |
| tableData.sort((a, b) => b.id - a.id) |
| |
| this.tableData = tableData |
| this.rowspan(0, 'id') |
| this.rowspan(1, 'description') |
| this.rowspan(2, 'type') |
| this.rowspan(3, 'other') |
| |
| this.total = nodes.length |
| |
| setTimeout(() => { |
| this.listLoading = false |
| }, 0.5 * 1000) |
| } |
| |
| private handleFilter() { |
| this.listQuery.page = 1 |
| this.getList() |
| } |
| |
| private handleRemove(row: any) { |
| this.$confirm(`Do you want to remove upstream ${row.id}?`, 'Warning', { |
| confirmButtonText: 'Confirm', |
| cancelButtonText: 'Cancel', |
| type: 'warning' |
| }) |
| .then(async() => { |
| await removeUpstream(row.realId) |
| this.getList() |
| this.$message.success(`Remove upstream ${row.id} successfully!`) |
| }) |
| } |
| |
| private sortChange(data: any) { |
| const { prop, order } = data |
| if (prop === 'id') { |
| this.sortByID(order) |
| } |
| } |
| |
| private sortByID(order: string) { |
| if (order === 'ascending') { |
| this.listQuery.sort = '+id' |
| } else { |
| this.listQuery.sort = '-id' |
| } |
| this.handleFilter() |
| } |
| |
| private handleCreate() { |
| this.$router.push({ |
| name: 'SchemaUpstreamCreate' |
| }) |
| } |
| |
| private handleToEdit(row: any) { |
| this.$router.push({ |
| name: 'SchemaUpstreamEdit', |
| params: { |
| id: row.realId |
| } |
| }) |
| } |
| |
| private rowspan(idx: number, prop: any) { |
| this.spanArr[idx] = [] |
| this.position = 0 |
| this.tableData.forEach((item, index) => { |
| if (index === 0) { |
| this.spanArr[idx].push(1) |
| this.position = 0 |
| } else { |
| if (this.tableData[index][prop] === this.tableData[index - 1][prop]) { |
| this.spanArr[idx][this.position] += 1 |
| this.spanArr[idx].push(0) |
| } else { |
| this.spanArr[idx].push(1) |
| this.position = index |
| } |
| } |
| }) |
| } |
| |
| private objectSpanMethod({ row, column, rowIndex, columnIndex }: any) { |
| if (columnIndex === 6) { |
| return { |
| rowspan: this.spanArr[0][rowIndex], |
| colspan: this.spanArr[0][rowIndex] > 0 ? 1 : 0 |
| } |
| } |
| |
| if (columnIndex < 3) { |
| return { |
| rowspan: this.spanArr[0][rowIndex], |
| colspan: this.spanArr[0][rowIndex] > 0 ? 1 : 0 |
| } |
| } |
| } |
| } |
| </script> |