mirror of
https://github.com/jumpserver/lina.git
synced 2025-08-23 00:58:03 +00:00
perf: 优化 card table
This commit is contained in:
parent
ae7e4b6ddf
commit
a6210c9add
@ -1,6 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||||
<meta content="0" http-equiv="Expires">
|
<meta content="0" http-equiv="Expires">
|
||||||
@ -20,31 +20,50 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: white;
|
background-color: rgba(255, 255, 255, 0.98);
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.spinner {
|
.spinner {
|
||||||
width: 50px;
|
width: 40px;
|
||||||
height: 50px;
|
height: 40px;
|
||||||
border: 5px solid rgba(0, 0, 0, 0.1);
|
border: 3px solid transparent;
|
||||||
|
border-top-color: var(--color-primary);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border-top-color: #3498db;
|
animation: spin 1s linear infinite;
|
||||||
animation: spin 1s infinite linear;
|
}
|
||||||
|
|
||||||
|
.spinner::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -3px;
|
||||||
|
left: -3px;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 3px solid transparent;
|
||||||
|
border-top-color: rgba(64, 158, 255, 0.2);
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 2s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
to {
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
<strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
<strong>
|
||||||
</noscript>
|
We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled.
|
||||||
<script>
|
Please enable it to continue.
|
||||||
|
</strong>
|
||||||
|
</noscript>
|
||||||
|
<script>
|
||||||
window.onload = function () {
|
window.onload = function () {
|
||||||
if (location.pathname === '/') {
|
if (location.pathname === '/') {
|
||||||
location.pathname = '/ui/'
|
location.pathname = '/ui/'
|
||||||
@ -60,12 +79,12 @@
|
|||||||
window.location.href = window.location.origin + pathname
|
window.location.href = window.location.origin + pathname
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
</div>
|
</div>
|
||||||
<div id="loading">
|
<div id="loading">
|
||||||
<div class="spinner"></div>
|
<div class="spinner"></div>
|
||||||
</div>
|
</div>
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-loading="loading">
|
<div>
|
||||||
<DataForm
|
<DataForm
|
||||||
v-if="!loading"
|
v-if="!loading"
|
||||||
ref="dataForm"
|
ref="dataForm"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-loading="loading">
|
<div>
|
||||||
<DataTable
|
<DataTable
|
||||||
v-if="!loading"
|
v-if="!loading"
|
||||||
ref="dataTable"
|
ref="dataTable"
|
||||||
|
150
src/components/Table/CardTable/Panel.vue
Normal file
150
src/components/Table/CardTable/Panel.vue
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<span v-if="d.edition === 'enterprise'" class="enterprise">
|
||||||
|
{{ $t('Enterprise') }}
|
||||||
|
</span>
|
||||||
|
<el-row class="panel">
|
||||||
|
<el-col v-if="d.icon" :span="8" class="image">
|
||||||
|
<img
|
||||||
|
v-if="d.icon.startsWith('/') || d.icon.startsWith('data:')"
|
||||||
|
:alt="d.display_name"
|
||||||
|
:src="d.icon"
|
||||||
|
>
|
||||||
|
<Icon v-else :icon="d.icon" />
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="16" class="text-zone">
|
||||||
|
<div class="one-line">
|
||||||
|
<b>{{ d.display_name }}</b>
|
||||||
|
<el-tag v-if="d.version" size="mini" style="margin-left: 5px">
|
||||||
|
{{ d.version }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
<div :title="d.comment " class="comment">
|
||||||
|
{{ d.comment }}
|
||||||
|
</div>
|
||||||
|
<div class="tag-zone">
|
||||||
|
<el-tag v-for="tag of d.tags" :key="tag" size="mini">
|
||||||
|
{{ capitalize(tag) }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Icon from '@/components/Widgets/Icon/index.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Panel',
|
||||||
|
components: { Icon },
|
||||||
|
props: {
|
||||||
|
d: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
capitalize(str) {
|
||||||
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.panel {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
margin-top: 0;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.image {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-zone {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
.one-line {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 10px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
b {
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-left: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment {
|
||||||
|
display: -webkit-box;
|
||||||
|
height: 120px;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 10px 0;
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-line-clamp: 4;
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-zone {
|
||||||
|
display: flex;
|
||||||
|
height: 30%;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.enterprise {
|
||||||
|
position: absolute;
|
||||||
|
right: -1px;
|
||||||
|
top: -1px;
|
||||||
|
background-color: var(--color-primary);
|
||||||
|
color: #fff;
|
||||||
|
padding: 3px 8px 4px 9px;
|
||||||
|
font-size: 13px;
|
||||||
|
border-radius: 3px 3px 3px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-zone {
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
.el-tag {
|
||||||
|
margin-right: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-zone {
|
||||||
|
text-align: left;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
@ -6,8 +6,8 @@
|
|||||||
:table-url="tableUrl"
|
:table-url="tableUrl"
|
||||||
v-bind="headerActions"
|
v-bind="headerActions"
|
||||||
/>
|
/>
|
||||||
<el-row :gutter="10" class="the-row">
|
<el-row v-loading="loading" class="the-row">
|
||||||
<IBox v-if="totalData.length === 0">
|
<IBox v-if="totalData.length === 0" class="empty-box">
|
||||||
<el-empty :description="$t('NoData')" :image-size="200" class="no-data" style="padding: 20px" />
|
<el-empty :description="$t('NoData')" :image-size="200" class="no-data" style="padding: 20px" />
|
||||||
</IBox>
|
</IBox>
|
||||||
<div class="card-container">
|
<div class="card-container">
|
||||||
@ -22,35 +22,7 @@
|
|||||||
>
|
>
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<slot :index="index" :item="d">
|
<slot :index="index" :item="d">
|
||||||
<span v-if="d.edition === 'enterprise'" class="enterprise">
|
<Panel :d="d" />
|
||||||
{{ $t('Enterprise') }}
|
|
||||||
</span>
|
|
||||||
<el-row>
|
|
||||||
<el-col v-if="d.icon" :span="8" class="image">
|
|
||||||
<img
|
|
||||||
v-if="d.icon.startsWith('/') || d.icon.startsWith('data:')"
|
|
||||||
:alt="d.display_name"
|
|
||||||
:src="d.icon"
|
|
||||||
>
|
|
||||||
<Icon v-else :icon="d.icon" />
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="16" class="text-zone">
|
|
||||||
<div class="one-line">
|
|
||||||
<b>{{ d.display_name }}</b>
|
|
||||||
<el-tag v-if="d.version" size="mini" style="margin-left: 5px">
|
|
||||||
{{ d.version }}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
<div :title="d.comment " class="comment">
|
|
||||||
{{ d.comment }}
|
|
||||||
</div>
|
|
||||||
<div class="tag-zone">
|
|
||||||
<el-tag v-for="tag of d.tags" :key="tag" size="mini">
|
|
||||||
{{ capitalize(tag) }}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</slot>
|
</slot>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</el-card>
|
</el-card>
|
||||||
@ -68,11 +40,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import TableAction from '@/components/Table/ListTable/TableAction'
|
|
||||||
import { Pagination } from '@/components'
|
|
||||||
import Icon from '@/components/Widgets/Icon/index.vue'
|
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
import { Pagination } from '@/components'
|
||||||
|
import TableAction from '@/components/Table/ListTable/TableAction'
|
||||||
import IBox from '@/components/Common/IBox/index.vue'
|
import IBox from '@/components/Common/IBox/index.vue'
|
||||||
|
import Panel from './Panel'
|
||||||
|
|
||||||
const defaultFirstPage = 1
|
const defaultFirstPage = 1
|
||||||
|
|
||||||
@ -80,9 +52,9 @@ export default {
|
|||||||
name: 'CardTable',
|
name: 'CardTable',
|
||||||
components: {
|
components: {
|
||||||
IBox,
|
IBox,
|
||||||
|
Panel,
|
||||||
TableAction,
|
TableAction,
|
||||||
Pagination,
|
Pagination
|
||||||
Icon
|
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
// 定义 table 的配置
|
// 定义 table 的配置
|
||||||
@ -120,6 +92,7 @@ export default {
|
|||||||
paginationSize: 6,
|
paginationSize: 6,
|
||||||
paginationLayout: 'total, sizes, prev, pager, next',
|
paginationLayout: 'total, sizes, prev, pager, next',
|
||||||
paginationSizes: [6, 18, 27],
|
paginationSizes: [6, 18, 27],
|
||||||
|
loading: true,
|
||||||
axiosConfig: {
|
axiosConfig: {
|
||||||
raw: 1,
|
raw: 1,
|
||||||
params: {
|
params: {
|
||||||
@ -135,16 +108,17 @@ export default {
|
|||||||
return this.tableConfig.url || ''
|
return this.tableConfig.url || ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
async mounted() {
|
||||||
this.getList()
|
try {
|
||||||
|
await this.getList()
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
isDisabled(item) {
|
isDisabled(item) {
|
||||||
return item.edition?.value === 'enterprise' && !this.hasValidLicense
|
return item.edition?.value === 'enterprise' && !this.hasValidLicense
|
||||||
},
|
},
|
||||||
capitalize(str) {
|
|
||||||
return str.charAt(0).toUpperCase() + str.slice(1)
|
|
||||||
},
|
|
||||||
getIcon(status) {
|
getIcon(status) {
|
||||||
let iconClass = 'fa-check-circle'
|
let iconClass = 'fa-check-circle'
|
||||||
if (status === false) {
|
if (status === false) {
|
||||||
@ -155,7 +129,7 @@ export default {
|
|||||||
getPageQuery(currentPage, pageSize) {
|
getPageQuery(currentPage, pageSize) {
|
||||||
return this.$refs.pagination.getPageQuery(currentPage, pageSize)
|
return this.$refs.pagination.getPageQuery(currentPage, pageSize)
|
||||||
},
|
},
|
||||||
getList() {
|
async getList() {
|
||||||
if (this.tableConfig.totalData) {
|
if (this.tableConfig.totalData) {
|
||||||
this.totalData = this.tableConfig.totalData
|
this.totalData = this.tableConfig.totalData
|
||||||
this.total = this.totalData.length
|
this.total = this.totalData.length
|
||||||
@ -169,16 +143,10 @@ export default {
|
|||||||
const queryString = Object.keys(query).map(key => key + '=' + query[key]).join('&')
|
const queryString = Object.keys(query).map(key => key + '=' + query[key]).join('&')
|
||||||
const url = `${this.tableUrl}?${queryString}`
|
const url = `${this.tableUrl}?${queryString}`
|
||||||
|
|
||||||
this.$axios
|
const resp = await this.$axios.get(url, this.axiosConfig)
|
||||||
.get(url, this.axiosConfig)
|
const data = resp.data
|
||||||
.then(({ data: resp }) => {
|
this.total = data?.count || 0
|
||||||
this.total = resp?.count || 0
|
this.totalData = data?.results || []
|
||||||
this.totalData = resp?.results || []
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
this.$log.error('Error occur: ', err)
|
|
||||||
this.total = 0
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
reloadTable() {
|
reloadTable() {
|
||||||
this.getList()
|
this.getList()
|
||||||
@ -240,6 +208,19 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.the-row .empty-box {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
::v-deep {
|
||||||
|
.el-empty {
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
.el-empty__image {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.the-row {
|
.the-row {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
max-width: 1600px;
|
max-width: 1600px;
|
||||||
@ -258,74 +239,6 @@ export default {
|
|||||||
|
|
||||||
::v-deep .el-card__body {
|
::v-deep .el-card__body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.el-row {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
margin-top: 0;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
.image {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-zone {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
|
|
||||||
.one-line {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: center;
|
|
||||||
padding-top: 10px;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
b {
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
margin-left: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.comment {
|
|
||||||
display: -webkit-box;
|
|
||||||
height: 120px;
|
|
||||||
font-size: 12px;
|
|
||||||
padding: 10px 0;
|
|
||||||
cursor: pointer;
|
|
||||||
overflow: hidden;
|
|
||||||
-webkit-line-clamp: 4;
|
|
||||||
-webkit-box-flex: 1;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag-zone {
|
|
||||||
display: flex;
|
|
||||||
height: 30%;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-disabled {
|
&.is-disabled {
|
||||||
@ -353,30 +266,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.enterprise {
|
|
||||||
position: absolute;
|
|
||||||
right: -1px;
|
|
||||||
top: -1px;
|
|
||||||
background-color: var(--color-primary);
|
|
||||||
color: #fff;
|
|
||||||
padding: 3px 8px 4px 9px;
|
|
||||||
font-size: 13px;
|
|
||||||
border-radius: 3px 3px 3px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag-zone {
|
|
||||||
margin-top: 10px;
|
|
||||||
|
|
||||||
.el-tag {
|
|
||||||
margin-right: 3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-zone {
|
|
||||||
text-align: left;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pagination {
|
.pagination {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
border-top: 1px solid #e7eaec;
|
border-top: 1px solid #e7eaec;
|
||||||
|
@ -696,5 +696,5 @@ li.rmenu i.fa {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.el-loading-parent--relative {
|
div.el-loading-parent--relative {
|
||||||
min-height: 200px;
|
min-height: 150px;
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,9 @@ function customizer(objValue, srcValue) {
|
|||||||
|
|
||||||
export function newURL(url) {
|
export function newURL(url) {
|
||||||
let obj
|
let obj
|
||||||
|
if (!url) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
if (url.indexOf('//') > -1) {
|
if (url.indexOf('//') > -1) {
|
||||||
obj = new URL(url)
|
obj = new URL(url)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,23 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<SmallCard ref="table" class="account-table" v-bind="$data" />
|
<SmallCard ref="table" class="account-table" v-bind="table" />
|
||||||
<CreateDialog v-if="visible" :visible.sync="visible" v-bind="providerConfig" />
|
<CreateDialog v-if="visible" :visible.sync="visible" v-bind="providerConfig" />
|
||||||
<Drawer
|
<UpdateDialog v-if="updateVisible" :object="object" :update-visible="updateVisible" />
|
||||||
v-if="updateVisible"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
:show-buttons="false"
|
|
||||||
:title="$tc('CloudAccountUpdate')"
|
|
||||||
:visible.sync="updateVisible"
|
|
||||||
v-on="$listeners"
|
|
||||||
>
|
|
||||||
<AuthPanel
|
|
||||||
:object="object"
|
|
||||||
:provider="object.provider.value"
|
|
||||||
:visible.sync="updateVisible"
|
|
||||||
origin="update"
|
|
||||||
@submitSuccess="onSubmitSuccess"
|
|
||||||
/>
|
|
||||||
</Drawer>
|
|
||||||
<Dialog
|
<Dialog
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
:close-on-press-escape="false"
|
:close-on-press-escape="false"
|
||||||
@ -62,28 +47,27 @@ import {
|
|||||||
zstack
|
zstack
|
||||||
} from '../const'
|
} from '../const'
|
||||||
import CreateDialog from './components/CreateDialog.vue'
|
import CreateDialog from './components/CreateDialog.vue'
|
||||||
|
import UpdateDialog from './components/UpdateDialog.vue'
|
||||||
import SmallCard from '@/components/Table/CardTable/DataCardTable/index.vue'
|
import SmallCard from '@/components/Table/CardTable/DataCardTable/index.vue'
|
||||||
import { ACCOUNT_PROVIDER_ATTRS_MAP } from '@/views/assets/Cloud/const'
|
import { ACCOUNT_PROVIDER_ATTRS_MAP } from '@/views/assets/Cloud/const'
|
||||||
import Dialog from '@/components/Dialog/index.vue'
|
import Dialog from '@/components/Dialog/index.vue'
|
||||||
import Drawer from '@/components/Drawer/index.vue'
|
|
||||||
import AssetPanel from './components/AssetPanel.vue'
|
import AssetPanel from './components/AssetPanel.vue'
|
||||||
import AuthPanel from './components/AuthPanel.vue'
|
|
||||||
import { toSafeLocalDateStr } from '@/utils/time'
|
import { toSafeLocalDateStr } from '@/utils/time'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CloudAccountList',
|
name: 'CloudAccountList',
|
||||||
components: {
|
components: {
|
||||||
Drawer,
|
|
||||||
AuthPanel,
|
|
||||||
AssetPanel,
|
AssetPanel,
|
||||||
Dialog,
|
Dialog,
|
||||||
SmallCard,
|
SmallCard,
|
||||||
CreateDialog
|
CreateDialog,
|
||||||
|
UpdateDialog
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const vm = this
|
const vm = this
|
||||||
return {
|
return {
|
||||||
object: null,
|
object: null,
|
||||||
|
table: {
|
||||||
tableConfig: {
|
tableConfig: {
|
||||||
url: '/api/v1/xpack/cloud/accounts/',
|
url: '/api/v1/xpack/cloud/accounts/',
|
||||||
permissions: {
|
permissions: {
|
||||||
@ -91,6 +75,40 @@ export default {
|
|||||||
resource: 'account'
|
resource: 'account'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
subComponentProps: {
|
||||||
|
handleUpdate: (obj) => {
|
||||||
|
this.object = obj
|
||||||
|
this.updateVisible = true
|
||||||
|
},
|
||||||
|
getImage: (obj) => {
|
||||||
|
return ACCOUNT_PROVIDER_ATTRS_MAP[obj.provider.value].image
|
||||||
|
},
|
||||||
|
getInfos: (obj) => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
title: this.$tc('TotalSyncRegion'),
|
||||||
|
content: obj?.task.regions.length
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: this.$tc('TotalSyncAsset'),
|
||||||
|
content: obj?.task.instance_count
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: this.$tc('DateLastSync'),
|
||||||
|
content: toSafeLocalDateStr(obj?.task.date_last_sync)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
id: 'online-sync',
|
||||||
|
name: this.$tc('SyncOnline'),
|
||||||
|
icon: 'el-icon-thumb',
|
||||||
|
callback: this.handleOnlineExecute,
|
||||||
|
disabled: !this.$hasPerm('xpack.change_syncinstancetask')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
headerActions: {
|
headerActions: {
|
||||||
hasImport: false,
|
hasImport: false,
|
||||||
hasExport: false,
|
hasExport: false,
|
||||||
@ -151,47 +169,14 @@ export default {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
providerConfig: {
|
providerConfig: {
|
||||||
providers: []
|
providers: []
|
||||||
},
|
},
|
||||||
visible: false,
|
visible: false,
|
||||||
updateVisible: false,
|
updateVisible: false,
|
||||||
onlineSyncVisible: false,
|
onlineSyncVisible: false
|
||||||
subComponentProps: {
|
|
||||||
handleUpdate: (obj) => {
|
|
||||||
this.object = obj
|
|
||||||
this.updateVisible = true
|
|
||||||
},
|
|
||||||
getImage: (obj) => {
|
|
||||||
return ACCOUNT_PROVIDER_ATTRS_MAP[obj.provider.value].image
|
|
||||||
},
|
|
||||||
getInfos: (obj) => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
title: this.$tc('TotalSyncRegion'),
|
|
||||||
content: obj?.task.regions.length
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$tc('TotalSyncAsset'),
|
|
||||||
content: obj?.task.instance_count
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$tc('DateLastSync'),
|
|
||||||
content: toSafeLocalDateStr(obj?.task.date_last_sync)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
actions: [
|
|
||||||
{
|
|
||||||
id: 'online-sync',
|
|
||||||
name: this.$tc('SyncOnline'),
|
|
||||||
icon: 'el-icon-thumb',
|
|
||||||
callback: this.handleOnlineExecute,
|
|
||||||
disabled: !this.$hasPerm('xpack.change_syncinstancetask')
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="asset-panel">
|
||||||
<el-alert
|
<el-alert
|
||||||
:center="false"
|
:center="false"
|
||||||
:closable="true"
|
:closable="true"
|
||||||
@ -9,8 +9,8 @@
|
|||||||
</el-alert>
|
</el-alert>
|
||||||
<ImportTable
|
<ImportTable
|
||||||
ref="importTable"
|
ref="importTable"
|
||||||
v-bind="settings"
|
|
||||||
origin="cloudSync"
|
origin="cloudSync"
|
||||||
|
v-bind="settings"
|
||||||
@cancel="closeDialog"
|
@cancel="closeDialog"
|
||||||
@finish="showResult"
|
@finish="showResult"
|
||||||
/>
|
/>
|
||||||
@ -162,3 +162,9 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.asset-panel {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
</el-steps>
|
</el-steps>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="18">
|
<el-col :span="18">
|
||||||
|
<div class="right-content">
|
||||||
<component
|
<component
|
||||||
:is="activeMenu"
|
:is="activeMenu"
|
||||||
:active.sync="active"
|
:active.sync="active"
|
||||||
@ -31,6 +32,7 @@
|
|||||||
:selected.sync="iSelected"
|
:selected.sync="iSelected"
|
||||||
:visible.sync="iVisible"
|
:visible.sync="iVisible"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
@ -43,10 +45,12 @@ import AuthPanel from '@/views/assets/Cloud/Account/components/AuthPanel'
|
|||||||
import AssetPanel from '@/views/assets/Cloud/Account/components/AssetPanel'
|
import AssetPanel from '@/views/assets/Cloud/Account/components/AssetPanel'
|
||||||
import ResultPanel from '@/views/assets/Cloud/Account/components/ResultPanel'
|
import ResultPanel from '@/views/assets/Cloud/Account/components/ResultPanel'
|
||||||
import { ACCOUNT_PROVIDER_ATTRS_MAP } from '@/views/assets/Cloud/const'
|
import { ACCOUNT_PROVIDER_ATTRS_MAP } from '@/views/assets/Cloud/const'
|
||||||
|
import IBox from '@/components/Common/IBox/index.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CreateDialog',
|
name: 'CreateDialog',
|
||||||
components: {
|
components: {
|
||||||
|
IBox,
|
||||||
Drawer,
|
Drawer,
|
||||||
AuthPanel,
|
AuthPanel,
|
||||||
AssetPanel,
|
AssetPanel,
|
||||||
@ -118,6 +122,11 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.right-content {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
::v-deep .el-step {
|
::v-deep .el-step {
|
||||||
.el-step__head {
|
.el-step__head {
|
||||||
&.is-process {
|
&.is-process {
|
||||||
|
@ -83,7 +83,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.cloud-select-wrap {
|
.cloud-select-wrap {
|
||||||
height: 300px;
|
background: #f3f3f3;
|
||||||
|
|
||||||
.el-row {
|
.el-row {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -1,23 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="result-panel">
|
||||||
<el-table
|
<el-table
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:show-header="false"
|
:show-header="false"
|
||||||
size="medium"
|
size="medium"
|
||||||
>
|
>
|
||||||
<el-table-column
|
<el-table-column prop="key" width="120" />
|
||||||
prop="key"
|
<el-table-column prop="value">
|
||||||
width="120"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
prop="value"
|
|
||||||
>
|
|
||||||
<template v-slot="scope">
|
<template v-slot="scope">
|
||||||
<el-link :underline="false" type="primary"> {{ scope.row.value }}</el-link>
|
<el-link :underline="false"> {{ scope.row.value }}</el-link>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<div style="float: right; margin: 10px">
|
<div style="margin-top: 20px">
|
||||||
<el-button size="small" type="primary" @click="handleClick">{{ $t('CloudAccountDetail') }}</el-button>
|
<el-button size="small" type="primary" @click="handleClick">{{ $t('CloudAccountDetail') }}</el-button>
|
||||||
<el-button size="small" @click="handleClose">{{ $t('Close') }}</el-button>
|
<el-button size="small" @click="handleClose">{{ $t('Close') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
@ -25,7 +20,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ResultPanel',
|
name: 'ResultPanel',
|
||||||
components: {},
|
components: {},
|
||||||
@ -67,6 +61,10 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang='scss' scoped>
|
<style lang='scss' scoped>
|
||||||
|
.result-panel {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
::v-deep .el-alert__content {
|
::v-deep .el-alert__content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
44
src/views/assets/Cloud/Account/components/UpdateDialog.vue
Normal file
44
src/views/assets/Cloud/Account/components/UpdateDialog.vue
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<template>
|
||||||
|
<Drawer
|
||||||
|
v-if="updateVisible"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
:show-buttons="false"
|
||||||
|
:title="$tc('CloudAccountUpdate')"
|
||||||
|
:visible.sync="updateVisible"
|
||||||
|
v-on="$listeners"
|
||||||
|
>
|
||||||
|
<div style="background: white">
|
||||||
|
<AuthPanel
|
||||||
|
:object="object"
|
||||||
|
:provider="object.provider.value"
|
||||||
|
:visible.sync="updateVisible"
|
||||||
|
origin="update"
|
||||||
|
@submitSuccess="onSubmitSuccess"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import AuthPanel from '@/views/assets/Cloud/Account/components/AuthPanel.vue'
|
||||||
|
import Drawer from '@/components/Drawer/index.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'UpdateDialog',
|
||||||
|
components: { Drawer, AuthPanel },
|
||||||
|
props: {
|
||||||
|
object: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
updateVisible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
Loading…
Reference in New Issue
Block a user