平台增加适配 品高云和海云和华为云

x-20250106
chengmingrui 2025-06-03 17:17:02 +08:00
parent 94b3ccffeb
commit 0aca3945e8
10 changed files with 275 additions and 329 deletions

View File

@ -1,29 +1,24 @@
module.exports = { module.exports = {
root: true, root: true,
env: { env: {
node: true node: true,
}, },
extends: ['plugin:vue/essential', '@vue/standard', '@vue/typescript'], extends: ['plugin:vue/essential', '@vue/standard', '@vue/typescript'],
rules: { rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-unused-vars': [ 'no-unused-vars': [0, { vars: 'all', args: 'none' }],
0, semi: 0,
{ eqeqeq: 0,
vars: 'all', 'one-var': 0,
args: 'none' camelcase: 0,
} 'no-case-declarations': 0,
], 'space-before-function-paren': 0,
semi: 0, 'vue/no-parsing-error': [2, { 'x-invalid-end-tag': false }],
eqeqeq: 0, '@typescript-eslint/indent': ['error', 2],
'one-var': 0, 'comma-dangle': ['error', 2],
camelcase: 0, },
'no-case-declarations': 0, parserOptions: {
'space-before-function-paren': 0, parser: '@typescript-eslint/parser',
'vue/no-parsing-error': [2, { "x-invalid-end-tag": false }], },
'@typescript-eslint/indent': ['error', 2] }
},
parserOptions: {
parser: '@typescript-eslint/parser'
}
};

View File

@ -1,10 +1,9 @@
@media screen and(-ms-high-contrast:active), @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
(-ms-high-contrast:none) { .el-table__header,
.el-table__header, .el-table__body {
.el-table__body { width: 100% !important;
width: 100% !important; }
} /* .basic-form-item{
/* .basic-form-item{
height: 32.76px; height: 32.76px;
} */ } */
} }

View File

@ -1,3 +1,5 @@
import Vue from 'vue'
// 正反编译 // 正反编译
export function booleanFilter(value) { export function booleanFilter(value) {
const obj = { const obj = {
@ -6,7 +8,7 @@ export function booleanFilter(value) {
1: '是', 1: '是',
0: '否', 0: '否',
YES: '是', YES: '是',
NO: '否' NO: '否',
} }
return obj[value] || value return obj[value] || value
} }
@ -29,7 +31,10 @@ export function vmStatusFilter(status) {
UNKNOWN: '已断开', UNKNOWN: '已断开',
UNKNOWNON: '已断开', UNKNOWNON: '已断开',
UNKNOWNOFF: '已断开', UNKNOWNOFF: '已断开',
UNKNOWNSUSPEND: '已断开' UNKNOWNSUSPEND: '已断开',
RECYCLING: '回收中',
MIGRATING: '迁移中',
FAULT_RESUMING: '故障恢复中',
} }
return statusMap[status] || '未知' return statusMap[status] || '未知'
} }
@ -95,7 +100,10 @@ export function vmStatusColorFilter(status) {
DISABLED: 'danger', DISABLED: 'danger',
DEALLOCATEING: 'warning', DEALLOCATEING: 'warning',
PROTECTING: 'warning', PROTECTING: 'warning',
DOWN: 'info' DOWN: 'info',
RECYCLING: 'warning',
MIGRATING: 'warning',
FAULT_RESUMING: 'warning',
} }
return statusMap[status] || 'danger' return statusMap[status] || 'danger'
} }
@ -104,12 +112,12 @@ export function taskStatusFilter(value, type) {
const statusMap = { const statusMap = {
DEVELOPING: '开发中', DEVELOPING: '开发中',
APPROVING: '发布中', APPROVING: '发布中',
APPROVED: ' 已发布' APPROVED: ' 已发布',
} }
const colorMap = { const colorMap = {
DEVELOPING: 'normal', DEVELOPING: 'normal',
APPROVING: 'warning', APPROVING: 'warning',
APPROVED: 'success' APPROVED: 'success',
} }
return type === 'color' ? colorMap[value] : statusMap[value] return type === 'color' ? colorMap[value] : statusMap[value]
} }
@ -123,7 +131,7 @@ export function taskTypeFilter(value) {
RECOVERY: '文件恢复', RECOVERY: '文件恢复',
HTTP: 'HTTP请求', HTTP: 'HTTP请求',
DATABASE: '数据库', DATABASE: '数据库',
POINT: '聚合节点' POINT: '聚合节点',
} }
return obj[value] return obj[value]
} }
@ -140,20 +148,20 @@ export function applyStatusFilter(value, type) {
// }, // },
APPROVED: { APPROVED: {
name: '已发布', name: '已发布',
color: 'success' color: 'success',
}, },
DEVELOPING: { DEVELOPING: {
name: '开发中', name: '开发中',
color: 'normal' color: 'normal',
}, },
UNAPPLY: { UNAPPLY: {
name: '未发布', name: '未发布',
color: 'primary' color: 'primary',
}, },
CREATED: { CREATED: {
name: '新创建', name: '新创建',
color: 'normal' color: 'normal',
} },
} }
return obj[value] && obj[value][type] return obj[value] && obj[value][type]
} }
@ -162,48 +170,62 @@ export function taskExeStatusFilter(value, type = 'name') {
const obj = { const obj = {
CREATED: { CREATED: {
name: '未执行', name: '未执行',
color: 'normal' color: 'normal',
}, },
NOREADY: { NOREADY: {
name: '已跳过', name: '已跳过',
color: 'warning' color: 'warning',
}, },
READY: { READY: {
name: '准备中', name: '准备中',
color: 'normal' color: 'normal',
}, },
WAITTING: { WAITTING: {
name: '等待执行', name: '等待执行',
color: 'primary' color: 'primary',
}, },
CANCELING: { CANCELING: {
name: '取消中', name: '取消中',
color: 'primary' color: 'primary',
}, },
RUNNING: { RUNNING: {
name: '正在执行', name: '正在执行',
color: 'normal' color: 'normal',
}, },
SUCCESS: { SUCCESS: {
name: '执行成功', name: '执行成功',
color: 'success' color: 'success',
}, },
SUSPENDED: { SUSPENDED: {
name: '已暂停', name: '已暂停',
color: 'warning' color: 'warning',
}, },
FAILED: { FAILED: {
name: '执行失败', name: '执行失败',
color: 'danger' color: 'danger',
}, },
CANCELED: { CANCELED: {
name: '手动结束', name: '手动结束',
color: 'warning' color: 'warning',
}, },
EXCEPTION: { EXCEPTION: {
name: '执行异常', name: '执行异常',
color: 'danger' color: 'danger',
} },
} }
return obj[value] && obj[value][type] // 容错处理(初始化值不存在) return obj[value] && obj[value][type] // 容错处理(初始化值不存在)
} }
const filters = {
booleanFilter,
vmStatusFilter,
vmStatusColorFilter,
taskStatusFilter,
taskTypeFilter,
applyStatusFilter,
taskExeStatusFilter,
}
// 注册全局过滤器
Object.keys(filters).forEach((key) => {
Vue.filter(key, filters[key])
})

View File

@ -21,21 +21,22 @@ import './icons'
import VueCompositionAPI from '@vue/composition-api' import VueCompositionAPI from '@vue/composition-api'
import rules from '@/validate/index' import rules from '@/validate/index'
import actions from './shared/action' import actions from './shared/action'
import './filters'
Vue.use(ElementUI, { size: 'small' }); Vue.use(ElementUI, { size: 'small' })
Vue.use(VueCompositionAPI) Vue.use(VueCompositionAPI)
Vue.use(CmpElement, { rules }) Vue.use(CmpElement, { rules })
Vue.use(CmpEcharts) Vue.use(CmpEcharts)
Vue.config.productionTip = false Vue.config.productionTip = false
let instance: any = null let instance: any = null
function render(props:any) { function render(props: any) {
const { appPath = '', container } = props; const { appPath = '', container } = props
instance = new Vue({ instance = new Vue({
router, router,
store, store,
render: h => h(App) render: (h) => h(App),
}).$mount(container ? container.querySelector('#app') : '#app'); }).$mount(container ? container.querySelector('#app') : '#app')
store.commit('SET_APP_PATH', appPath) store.commit('SET_APP_PATH', appPath)
} }
if (!(window as any).__POWERED_BY_QIANKUN__) { if (!(window as any).__POWERED_BY_QIANKUN__) {
@ -48,8 +49,8 @@ export async function bootstrap() {
} }
export async function mount(props: any) { export async function mount(props: any) {
console.log('cop app mounted'); console.log('cop app mounted')
const getStyle = window.getComputedStyle; const getStyle = window.getComputedStyle
// @ts-ignore // @ts-ignore
// window.getComputedStyle = (element, property) => { // window.getComputedStyle = (element, property) => {
// if (!element || element.nodeType === 9) return {}; // if (!element || element.nodeType === 9) return {};
@ -57,10 +58,10 @@ export async function mount(props: any) {
// }; // };
render(props) render(props)
actions.init(props, (state: any) => { actions.init(props, (state: any) => {
const { permissions, userData } = state; const { permissions, userData } = state
userData && store.commit('SET_USERDATA', userData); userData && store.commit('SET_USERDATA', userData)
if (!store.getters.addRoutes && permissions) { if (!store.getters.addRoutes && permissions) {
store.dispatch('permission/GenerateRoutes'); store.dispatch('permission/GenerateRoutes')
} }
}) })
} }

View File

@ -83,9 +83,7 @@
</template> </template>
<el-table-column label="状态"> <el-table-column label="状态">
<template slot-scope="scope"> <template slot-scope="scope">
<status-icon :type="vmStatusColorFilter(scope.row.status)"> <status-icon :type="scope.row.status | vmStatusColorFilter"> {{ scope.row.status | vmStatusFilter }} </status-icon>
{{ vmStatusFilter(scope.row.status) }}
</status-icon>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="平台名称" prop="vendorName"></el-table-column> <el-table-column label="平台名称" prop="vendorName"></el-table-column>
@ -110,36 +108,34 @@ export default {
mixins: [show], mixins: [show],
props: { props: {
itemData: { itemData: {
type: Object type: Object,
}, },
osCategory: { osCategory: {
type: String, type: String,
default: '' default: '',
}, },
hasResource: { hasResource: {
type: Boolean, type: Boolean,
default: false default: false,
} },
}, },
data() { data() {
return { return {
vmStatusFilter,
vmStatusColorFilter,
list: null, list: null,
total: null, total: null,
listQuery: { listQuery: {
name: '', name: '',
privateIps: '' privateIps: '',
}, },
params: { params: {
page: 1, page: 1,
rows: 10 rows: 10,
}, },
dialogServerVisible: false, dialogServerVisible: false,
vendorOptions: '', vendorOptions: '',
selectList: [], selectList: [],
idList: [], idList: [],
http: getResource http: getResource,
} }
}, },
created() { created() {
@ -148,12 +144,12 @@ export default {
computed: { computed: {
path() { path() {
return this.$route.path return this.$route.path
} },
}, },
watch: { watch: {
path(val) { path(val) {
this.http = val.includes('PatchDeploy') ? getHosts : getResource this.http = val.includes('PatchDeploy') ? getHosts : getResource
} },
}, },
methods: { methods: {
clearCustomParams() { clearCustomParams() {
@ -183,7 +179,7 @@ export default {
this.listQuery = { this.listQuery = {
name: '', name: '',
privateIps: '', privateIps: '',
vendorId: '' vendorId: '',
} }
this.params.page = 1 this.params.page = 1
this.selectList = [] this.selectList = []
@ -196,7 +192,7 @@ export default {
host: data.host, host: data.host,
username: data.user, username: data.user,
password: data.pasd, password: data.pasd,
osCategory: data.category osCategory: data.category,
}) })
}) })
this.dialogServerVisible = true this.dialogServerVisible = true
@ -206,7 +202,7 @@ export default {
this.$confirm('您确定要清空所选主机吗?', '提示', { this.$confirm('您确定要清空所选主机吗?', '提示', {
confirmButtonText: '清空', confirmButtonText: '清空',
confirmButtonClass: 'el-button--danger', confirmButtonClass: 'el-button--danger',
type: 'warning' type: 'warning',
}).then(() => { }).then(() => {
this.clearCustomParams() this.clearCustomParams()
this.itemData.hostList = [] this.itemData.hostList = []
@ -223,7 +219,7 @@ export default {
}, },
getVendor() { getVendor() {
getCloudVendor({ getCloudVendor({
simple: true simple: true,
}).then((data) => { }).then((data) => {
if (data.success) { if (data.success) {
this.vendorOptions = data.data.rows this.vendorOptions = data.data.rows
@ -305,7 +301,7 @@ export default {
category: this.path.includes('PatchDeploy') ? '' : 'Computer', category: this.path.includes('PatchDeploy') ? '' : 'Computer',
catalog: this.path.includes('PatchDeploy') ? 'Computer' : '', catalog: this.path.includes('PatchDeploy') ? 'Computer' : '',
osCategory: this.osCategory, osCategory: this.osCategory,
vendorId: this.listQuery.vendorId vendorId: this.listQuery.vendorId,
}) })
this.getList() this.getList()
}, },
@ -326,7 +322,7 @@ export default {
pasd: data.password || getPassword(data), pasd: data.password || getPassword(data),
port: data.osCategory.toUpperCase() === 'WINDOWS' ? 5986 : 22, port: data.osCategory.toUpperCase() === 'WINDOWS' ? 5986 : 22,
category: data.osCategory, category: data.osCategory,
privateIps: this.path.includes('PatchDeploy') ? '' : data.privateIps privateIps: this.path.includes('PatchDeploy') ? '' : data.privateIps,
} }
if (data.paramsList) { if (data.paramsList) {
tmp.paramsList = data.paramsList tmp.paramsList = data.paramsList
@ -339,13 +335,13 @@ export default {
this.itemData.resourceList = this.itemData.hostList.slice() this.itemData.resourceList = this.itemData.hostList.slice()
this.itemData.resourceList.unshift({ this.itemData.resourceList.unshift({
id: 0, id: 0,
rawName: '选择全部' rawName: '选择全部',
}) })
} }
this.clearCustomParams() this.clearCustomParams()
this.dialogServerVisible = false this.dialogServerVisible = false
} },
} },
} }
</script> </script>
<style scoped> <style scoped>

View File

@ -15,32 +15,24 @@
<el-col :span="24"> <el-col :span="24">
<el-form-item label=""> <el-form-item label="">
<smart-table :data="itemData.targets" class="target-table"> <smart-table :data="itemData.targets" class="target-table">
<el-table-column label="主机名称" prop="name" show-overflow-tooltip> <el-table-column label="主机名称" prop="name" show-overflow-tooltip> </el-table-column>
</el-table-column>
<el-table-column label="IP"> <el-table-column label="IP">
<template slot-scope="scope"> <template slot-scope="scope">
<el-select v-model="scope.row.host" placeholder="请选择"> <el-select v-model="scope.row.host" placeholder="请选择">
<el-option <el-option v-for="(item, index) in scope.row.privateIps" :key="index" :label="item" :value="item"> </el-option>
v-for="(item, index) in scope.row.privateIps"
:key="index"
:label="item"
:value="item">
</el-option>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="端口"> <el-table-column label="端口">
<template slot-scope="scope"> <template slot-scope="scope">
<el-form-item class="m-b-none" :prop="'targets.'+scope.row.indexKey+'.port'" <el-form-item class="m-b-none" :prop="'targets.' + scope.row.indexKey + '.port'" :rules="{ required: true, message: '请填写端口号' }">
:rules="{required: true, message: '请填写端口号'}">
<el-input v-model="scope.row.port" type="number"></el-input> <el-input v-model="scope.row.port" type="number"></el-input>
</el-form-item> </el-form-item>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="用户名"> <el-table-column label="用户名">
<template slot-scope="scope"> <template slot-scope="scope">
<el-form-item class="m-b-none" :prop="'targets.'+scope.row.indexKey+'.user'" <el-form-item class="m-b-none" :prop="'targets.' + scope.row.indexKey + '.user'" :rules="{ required: true, message: '请填写用户名' }">
:rules="{required: true, message: '请填写用户名'}">
<el-input v-model="scope.row.user"></el-input> <el-input v-model="scope.row.user"></el-input>
</el-form-item> </el-form-item>
</template> </template>
@ -61,47 +53,37 @@
</smart-table> </smart-table>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-dialog width="70%" title="服务器列表" :close-on-click-modal="false" :visible.sync="dialogServerVisible" <el-dialog width="70%" title="服务器列表" :close-on-click-modal="false" :visible.sync="dialogServerVisible" append-to-body>
append-to-body>
<el-form :inline="true"> <el-form :inline="true">
<el-form-item> <el-form-item>
<el-select clearable v-model="listQuery.vendorId" placeholder="所属平台"> <el-select clearable v-model="listQuery.vendorId" placeholder="所属平台">
<el-option v-for="item in vendorOptions" :key="item.id" :label="item.name" :value="item.id"> <el-option v-for="item in vendorOptions" :key="item.id" :label="item.name" :value="item.id"> </el-option>
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-input placeholder="IP地址" v-model="listQuery.ip"> <el-input placeholder="IP地址" v-model="listQuery.ip"> </el-input>
</el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-input placeholder="主机名" v-model="listQuery.name"> <el-input placeholder="主机名" v-model="listQuery.name"> </el-input>
</el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="ghost" icon="el-icon-search" @click="handleSearch"></el-button> <el-button type="ghost" icon="el-icon-search" @click="handleSearch"></el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<basic-table :data="list" :params="params" :get-list="getList" :total="total" ref="serverTable1" <basic-table :data="list" :params="params" :get-list="getList" :total="total" ref="serverTable1" @select="handleSelectItem" @select-all="handleSelectAll">
@select="handleSelectItem" @select-all="handleSelectAll"> <el-table-column type="selection" :selectable="selectAble" width="60"> </el-table-column>
<el-table-column type="selection" :selectable="selectAble" width="60"> <el-table-column label="主机名" prop="name"> </el-table-column>
</el-table-column>
<el-table-column label="主机名" prop="name">
</el-table-column>
<el-table-column label="IP"> <el-table-column label="IP">
<template slot-scope="scope"> <template slot-scope="scope">
<div v-for="(item, index) in scope.row.privateIps" :key="index">{{item}}</div> <div v-for="(item, index) in scope.row.privateIps" :key="index">{{ item }}</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="状态"> <el-table-column label="状态">
<template slot-scope="scope"> <template slot-scope="scope">
<status-icon :type="vmStatusColorFilter(scope.row.status)"> <status-icon :type="scope.row.status | vmStatusColorFilter"> {{ scope.row.status | vmStatusFilter }} </status-icon>
{{vmStatusFilter(scope.row.status)}}
</status-icon>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="平台名称" prop="vendorName"> <el-table-column label="平台名称" prop="vendorName"> </el-table-column>
</el-table-column>
</basic-table> </basic-table>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button type="ghost" @click.native="dialogServerVisible = false">取消</el-button> <el-button type="ghost" @click.native="dialogServerVisible = false">取消</el-button>
@ -118,47 +100,42 @@ import { vmStatusFilter, vmStatusColorFilter } from '@/filters/index'
export default { export default {
props: { props: {
itemData: { itemData: {
type: Object type: Object,
} },
}, },
data () { data() {
return { return {
vmStatusFilter,
vmStatusColorFilter,
list: null, list: null,
total: null, total: null,
listQuery: { listQuery: {
name: '', name: '',
privateIps: '', privateIps: '',
catalog: '' catalog: '',
}, },
params: { params: {
page: 1, page: 1,
rows: 10 rows: 10,
}, },
dialogServerVisible: false, dialogServerVisible: false,
vendorOptions: '', vendorOptions: '',
selectList: [], selectList: [],
idList: [] idList: [],
} }
}, },
created () { created() {},
},
methods: { methods: {
selectAble (row) { selectAble(row) {
if (row.osCategory && row.osCategory.toLowerCase() == 'linux' && row.status && row.status.toLowerCase() == 'running') { if (row.osCategory && row.osCategory.toLowerCase() == 'linux' && row.status && row.status.toLowerCase() == 'running') {
if (row.catalog.toLowerCase() == 'physical') { if (row.catalog.toLowerCase() == 'physical') {
const server = JSON.parse(row.inventory) const server = JSON.parse(row.inventory)
if ((server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) || if ((server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) || (server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
(server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
if (server.powerState.toLowerCase() == 'running') { if (server.powerState.toLowerCase() == 'running') {
return true return true
} }
} }
} else if (row.catalog.toLowerCase() == 'logical') { } else if (row.catalog.toLowerCase() == 'logical') {
const cloud_server = JSON.parse(row.inventory) const cloud_server = JSON.parse(row.inventory)
if ((cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) || if ((cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) || (cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
(cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
if (cloud_server.status.toLowerCase() == 'running') { if (cloud_server.status.toLowerCase() == 'running') {
return true return true
} }
@ -167,41 +144,41 @@ export default {
} }
return false return false
}, },
selectServer () { selectServer() {
this.getVendor() this.getVendor()
// //
this.listQuery = { this.listQuery = {
name: '', name: '',
privateIps: '', privateIps: '',
catalog: '', catalog: '',
vendorId: '' vendorId: '',
} }
this.params.page = 1 this.params.page = 1
this.selectList = [] this.selectList = []
// //
this.itemData.targets.forEach(data => { this.itemData.targets.forEach((data) => {
this.selectList.push({ this.selectList.push({
id: data.resourceId, id: data.resourceId,
name: data.name, name: data.name,
host: data.host, host: data.host,
username: data.user, username: data.user,
password: data.pasd ? crypto.encrypt(data.pasd) : data.pasd, password: data.pasd ? crypto.encrypt(data.pasd) : data.pasd,
osCategory: data.category osCategory: data.category,
}) })
}) })
this.dialogServerVisible = true this.dialogServerVisible = true
this.handleSearch() this.handleSearch()
}, },
clearServer () { clearServer() {
this.$confirm('您确定要清空所选主机吗?', '提示', { this.$confirm('您确定要清空所选主机吗?', '提示', {
confirmButtonText: '清空', confirmButtonText: '清空',
confirmButtonClass: 'el-button--danger', confirmButtonClass: 'el-button--danger',
type: 'warning' type: 'warning',
}).then(() => { }).then(() => {
this.itemData.targets = [] this.itemData.targets = []
}) })
}, },
delServer (id) { delServer(id) {
for (let i = 0, len = this.itemData.targets.length; i < len; i++) { for (let i = 0, len = this.itemData.targets.length; i < len; i++) {
if (this.itemData.targets[i].id === id) { if (this.itemData.targets[i].id === id) {
this.itemData.targets.splice(i, 1) this.itemData.targets.splice(i, 1)
@ -209,16 +186,16 @@ export default {
} }
} }
}, },
getVendor () { getVendor() {
getCloudVendor({ getCloudVendor({
simple: true simple: true,
}).then(data => { }).then((data) => {
if (data.success) { if (data.success) {
this.vendorOptions = data.data.rows this.vendorOptions = data.data.rows
} }
}) })
}, },
handleSelectItem (selection, row) { handleSelectItem(selection, row) {
this.refreshId() this.refreshId()
if (this.idList.indexOf(row.id) > -1) { if (this.idList.indexOf(row.id) > -1) {
for (let j = 0; j < this.selectList.length; j++) { for (let j = 0; j < this.selectList.length; j++) {
@ -232,16 +209,18 @@ export default {
this.selectList.push(row) this.selectList.push(row)
} }
}, },
handleSelectAll (selection) { handleSelectAll(selection) {
this.refreshId() this.refreshId()
if (selection.length) { // if (selection.length) {
this.list.forEach(item => { //
this.list.forEach((item) => {
if (this.idList.indexOf(item.id) == -1 && item.privateIps.length && item.status != 'STOPPED') { if (this.idList.indexOf(item.id) == -1 && item.privateIps.length && item.status != 'STOPPED') {
this.selectList.push(item) this.selectList.push(item)
} }
}) })
} else { // } else {
this.list.forEach(item => { //
this.list.forEach((item) => {
if (this.idList.indexOf(item.id) > -1) { if (this.idList.indexOf(item.id) > -1) {
for (let j = 0; j < this.selectList.length; j++) { for (let j = 0; j < this.selectList.length; j++) {
const row = this.selectList[j] const row = this.selectList[j]
@ -254,13 +233,13 @@ export default {
}) })
} }
}, },
refreshId () { refreshId() {
this.idList = [] this.idList = []
this.selectList.forEach(item => { this.selectList.forEach((item) => {
this.idList.push(item.id) this.idList.push(item.id)
}) })
}, },
getList () { getList() {
const self = this const self = this
this.refreshId() this.refreshId()
const handleData = function (data) { const handleData = function (data) {
@ -271,7 +250,7 @@ export default {
}) })
}) })
} }
getResource(this.params).then(data => { getResource(this.params).then((data) => {
if (data.success) { if (data.success) {
this.list = data.data.rows this.list = data.data.rows
this.total = data.data.total this.total = data.data.total
@ -279,20 +258,20 @@ export default {
} }
}) })
}, },
handleSearch () { handleSearch() {
this.params.page = 1 this.params.page = 1
this.params.params = this.$tools.handleSearchParam({ this.params.params = this.$tools.handleSearchParam({
vendorId: this.listQuery.vendorId, vendorId: this.listQuery.vendorId,
category: 'Computer', category: 'Computer',
catalog: this.listQuery.catalog, catalog: this.listQuery.catalog,
'name:LK': this.listQuery.name, 'name:LK': this.listQuery.name,
'privateIps:LK': this.listQuery.ip 'privateIps:LK': this.listQuery.ip,
}) })
this.getList() this.getList()
}, },
ok () { ok() {
this.itemData.targets = [] this.itemData.targets = []
this.selectList.forEach(data => { this.selectList.forEach((data) => {
this.itemData.targets.push({ this.itemData.targets.push({
resourceId: data.id, resourceId: data.id,
name: data.name, name: data.name,
@ -302,17 +281,16 @@ export default {
pasd: data.password ? crypto.decrypt(data.password) : data.password, pasd: data.password ? crypto.decrypt(data.password) : data.password,
category: data.osCategory, category: data.osCategory,
sudo: true, sudo: true,
privateIps: data.privateIps privateIps: data.privateIps,
}) })
}) })
this.dialogServerVisible = false this.dialogServerVisible = false
} },
} },
} }
</script> </script>
<style scoped> <style scoped>
.target-table .el-form-item.is-error { .target-table .el-form-item.is-error {
margin-bottom: 15px !important; margin-bottom: 15px !important;
} }
</style> </style>

View File

@ -11,32 +11,24 @@
<el-col :span="24"> <el-col :span="24">
<el-form-item label=""> <el-form-item label="">
<smart-table :data="itemData.targets" class="target-table"> <smart-table :data="itemData.targets" class="target-table">
<el-table-column label="主机名称" prop="name" show-overflow-tooltip> <el-table-column label="主机名称" prop="name" show-overflow-tooltip> </el-table-column>
</el-table-column>
<el-table-column label="IP"> <el-table-column label="IP">
<template slot-scope="scope"> <template slot-scope="scope">
<el-select v-model="scope.row.host" placeholder="请选择"> <el-select v-model="scope.row.host" placeholder="请选择">
<el-option <el-option v-for="(item, index) in scope.row.privateIps" :key="index" :label="item" :value="item"> </el-option>
v-for="(item, index) in scope.row.privateIps"
:key="index"
:label="item"
:value="item">
</el-option>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="端口"> <el-table-column label="端口">
<template slot-scope="scope"> <template slot-scope="scope">
<el-form-item class="m-b-none" :prop="'targets.'+scope.row.indexKey+'.port'" <el-form-item class="m-b-none" :prop="'targets.' + scope.row.indexKey + '.port'" :rules="{ required: true, message: '请填写端口号' }">
:rules="{required: true, message: '请填写端口号'}">
<el-input v-model="scope.row.port" type="number"></el-input> <el-input v-model="scope.row.port" type="number"></el-input>
</el-form-item> </el-form-item>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="用户名"> <el-table-column label="用户名">
<template slot-scope="scope"> <template slot-scope="scope">
<el-form-item class="m-b-none" :prop="'targets.'+scope.row.indexKey+'.user'" <el-form-item class="m-b-none" :prop="'targets.' + scope.row.indexKey + '.user'" :rules="{ required: true, message: '请填写用户名' }">
:rules="{required: true, message: '请填写用户名'}">
<el-input v-model="scope.row.user"></el-input> <el-input v-model="scope.row.user"></el-input>
</el-form-item> </el-form-item>
</template> </template>
@ -57,22 +49,18 @@
</smart-table> </smart-table>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-dialog width="70%" title="服务器列表" :close-on-click-modal="false" :visible.sync="dialogServerVisible" <el-dialog width="70%" title="服务器列表" :close-on-click-modal="false" :visible.sync="dialogServerVisible" append-to-body>
append-to-body>
<el-form :inline="true"> <el-form :inline="true">
<el-form-item> <el-form-item>
<el-select clearable v-model="listQuery.vendorId" placeholder="所属平台"> <el-select clearable v-model="listQuery.vendorId" placeholder="所属平台">
<el-option v-for="item in vendorOptions" :key="item.id" :label="item.name" :value="item.id"> <el-option v-for="item in vendorOptions" :key="item.id" :label="item.name" :value="item.id"> </el-option>
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-input placeholder="IP地址" v-model="listQuery.ip"> <el-input placeholder="IP地址" v-model="listQuery.ip"> </el-input>
</el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-input placeholder="主机名" v-model="listQuery.name"> <el-input placeholder="主机名" v-model="listQuery.name"> </el-input>
</el-input>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="ghost" icon="el-icon-search" @click="handleSearch"></el-button> <el-button type="ghost" icon="el-icon-search" @click="handleSearch"></el-button>
@ -82,24 +70,21 @@
<el-table-column label="主机名称"> <el-table-column label="主机名称">
<template slot-scope="scope"> <template slot-scope="scope">
<el-radio :label="scope.row.id" v-model="targetId" :disabled="selectAble(scope.row)" @change.native="getCurrentRow(scope.row)"> <el-radio :label="scope.row.id" v-model="targetId" :disabled="selectAble(scope.row)" @change.native="getCurrentRow(scope.row)">
<span style="font-size: 12px;">{{scope.row.name}}</span> <span style="font-size: 12px">{{ scope.row.name }}</span>
</el-radio> </el-radio>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="IP"> <el-table-column label="IP">
<template slot-scope="scope"> <template slot-scope="scope">
<div v-for="(item, index) in scope.row.privateIps" :key="index">{{item}}</div> <div v-for="(item, index) in scope.row.privateIps" :key="index">{{ item }}</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="状态"> <el-table-column label="状态">
<template slot-scope="scope"> <template slot-scope="scope">
<status-icon :type="vmStatusColorFilter(scope.row.status)"> <status-icon :type="scope.row.status | vmStatusColorFilter"> {{ scope.row.status | vmStatusFilter }} </status-icon>
{{vmStatusFilter(scope.row.status)}}
</status-icon>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="平台名称" prop="vendorName"> <el-table-column label="平台名称" prop="vendorName"> </el-table-column>
</el-table-column>
</basic-table> </basic-table>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button type="ghost" @click.native="dialogServerVisible = false">取消</el-button> <el-button type="ghost" @click.native="dialogServerVisible = false">取消</el-button>
@ -116,48 +101,43 @@ import crypto from 'utils/crypto.js'
export default { export default {
props: { props: {
itemData: { itemData: {
type: Object type: Object,
} },
}, },
data () { data() {
return { return {
vmStatusFilter,
vmStatusColorFilter,
list: null, list: null,
total: null, total: null,
listQuery: { listQuery: {
name: '', name: '',
privateIps: '' privateIps: '',
}, },
params: { params: {
page: 1, page: 1,
rows: 10 rows: 10,
}, },
dialogServerVisible: false, dialogServerVisible: false,
groupOptions: '', groupOptions: '',
vendorOptions: '', vendorOptions: '',
selectList: [], selectList: [],
idList: [], idList: [],
targetId: null targetId: null,
} }
}, },
created () { created() {},
},
methods: { methods: {
selectAble (row) { selectAble(row) {
if (row.osCategory && row.osCategory.toLowerCase() == 'linux' && row.status.toLowerCase() == 'running') { if (row.osCategory && row.osCategory.toLowerCase() == 'linux' && row.status.toLowerCase() == 'running') {
if (row.catalog.toLowerCase() == 'physical') { if (row.catalog.toLowerCase() == 'physical') {
const server = JSON.parse(row.inventory) const server = JSON.parse(row.inventory)
if ((server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) || if ((server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) || (server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
(server.config && server.config.osName && server.config.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
if (server.powerState.toLowerCase() == 'running') { if (server.powerState.toLowerCase() == 'running') {
return false return false
} }
} }
} else if (row.catalog.toLowerCase() == 'logical') { } else if (row.catalog.toLowerCase() == 'logical') {
const cloud_server = JSON.parse(row.inventory) const cloud_server = JSON.parse(row.inventory)
if ((cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) || if ((cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('centos') > -1) || (cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
(cloud_server.osName && cloud_server.osName.trim().replace(/\s*/g, '').toLowerCase().indexOf('redhat') > -1)) {
if (cloud_server.status.toLowerCase() == 'running') { if (cloud_server.status.toLowerCase() == 'running') {
return false return false
} }
@ -166,51 +146,51 @@ export default {
} }
return true return true
}, },
selectServer () { selectServer() {
this.getVendor() this.getVendor()
// //
this.listQuery = { this.listQuery = {
name: '', name: '',
privateIps: '', privateIps: '',
vendorId: '' vendorId: '',
} }
this.params.page = 1 this.params.page = 1
this.selectList = [] this.selectList = []
// //
this.itemData.targets.forEach(data => { this.itemData.targets.forEach((data) => {
this.selectList.push({ this.selectList.push({
id: data.resourceId, id: data.resourceId,
name: data.name, name: data.name,
host: data.host, host: data.host,
username: data.user, username: data.user,
password: data.pasd ? crypto.encrypt(data.pasd) : data.pasd, password: data.pasd ? crypto.encrypt(data.pasd) : data.pasd,
osCategory: data.category osCategory: data.category,
}) })
}) })
this.dialogServerVisible = true this.dialogServerVisible = true
this.handleSearch() this.handleSearch()
}, },
delServer () { delServer() {
this.selectList = []; this.selectList = []
this.itemData.targets = []; this.itemData.targets = []
this.targetId = null; this.targetId = null
}, },
getVendor () { getVendor() {
getCloudVendor({ getCloudVendor({
simple: true simple: true,
}).then(data => { }).then((data) => {
if (data.success) { if (data.success) {
this.vendorOptions = data.data.rows this.vendorOptions = data.data.rows
} }
}) })
}, },
refreshId () { refreshId() {
this.idList = [] this.idList = []
this.selectList.forEach(item => { this.selectList.forEach((item) => {
this.idList.push(item.id) this.idList.push(item.id)
}) })
}, },
getList () { getList() {
const self = this const self = this
this.refreshId() this.refreshId()
const handleData = function (data) { const handleData = function (data) {
@ -218,7 +198,7 @@ export default {
item.privateIps = JSON.parse(item.privateIps) item.privateIps = JSON.parse(item.privateIps)
}) })
} }
getResource(this.params).then(data => { getResource(this.params).then((data) => {
if (data.success) { if (data.success) {
this.list = data.data.rows this.list = data.data.rows
this.total = data.data.total this.total = data.data.total
@ -226,22 +206,22 @@ export default {
} }
}) })
}, },
handleSearch () { handleSearch() {
this.params.page = 1 this.params.page = 1
this.params.params = this.$tools.handleSearchParam({ this.params.params = this.$tools.handleSearchParam({
vendorId: this.listQuery.vendorId, vendorId: this.listQuery.vendorId,
category: 'Computer', category: 'Computer',
'name:LK': this.listQuery.name, 'name:LK': this.listQuery.name,
'privateIps:LK': this.listQuery.ip 'privateIps:LK': this.listQuery.ip,
}) })
this.getList() this.getList()
}, },
getCurrentRow (data) { getCurrentRow(data) {
this.selectList = [data]; this.selectList = [data]
}, },
ok () { ok() {
this.itemData.targets = [] this.itemData.targets = []
this.selectList.forEach(data => { this.selectList.forEach((data) => {
this.itemData.targets.push({ this.itemData.targets.push({
resourceId: data.id, resourceId: data.id,
name: data.name, name: data.name,
@ -251,17 +231,16 @@ export default {
pasd: data.password ? crypto.decrypt(data.password) : data.password, pasd: data.password ? crypto.decrypt(data.password) : data.password,
category: data.osCategory, category: data.osCategory,
sudo: true, sudo: true,
privateIps: data.privateIps privateIps: data.privateIps,
}) })
}) })
this.dialogServerVisible = false this.dialogServerVisible = false
} },
} },
} }
</script> </script>
<style scoped> <style scoped>
.target-table .el-form-item.is-error { .target-table .el-form-item.is-error {
margin-bottom: 15px !important; margin-bottom: 15px !important;
} }
</style> </style>

View File

@ -2,9 +2,7 @@
<div> <div>
<AdvanceTable :title="`${title}主机列表`" :data="tableData" :searchConfigs="searchConfigs" :params="params" :total="total" :columns="columns" :get-list="getData" :loading="loading" :key="path"> <AdvanceTable :title="`${title}主机列表`" :data="tableData" :searchConfigs="searchConfigs" :params="params" :total="total" :columns="columns" :get-list="getData" :loading="loading" :key="path">
<template v-slot:action> <template v-slot:action>
<el-button type="primary" @click="handleCreate(null, 1)" icon="el-icon-plus"> <el-button type="primary" @click="handleCreate(null, 1)" icon="el-icon-plus"> 新增 </el-button>
新增
</el-button>
<el-button type="primary" icon="el-icon-refresh" @click="handleSynchro(type)"></el-button> <el-button type="primary" icon="el-icon-refresh" @click="handleSynchro(type)"></el-button>
<!-- <el-button type="primary" icon="el-icon-refresh" @click="handleSynchro('RIS')">RIS</el-button> --> <!-- <el-button type="primary" icon="el-icon-refresh" @click="handleSynchro('RIS')">RIS</el-button> -->
<el-button icon="el-icon-upload2" @click="importData"> </el-button> <el-button icon="el-icon-upload2" @click="importData"> </el-button>
@ -127,7 +125,7 @@ export default {
} else { } else {
callback(new Error('请输入正确的IP地址')) callback(new Error('请输入正确的IP地址'))
} }
} },
}, },
columns, columns,
vmSearchConfigs, vmSearchConfigs,
@ -138,11 +136,11 @@ export default {
params: { params: {
page: 1, page: 1,
rows: 20, rows: 20,
sorter: JSON.stringify({ gmtCreate: '1' }) sorter: JSON.stringify({ gmtCreate: '1' }),
}, },
setData: { setData: {
dialog: false, dialog: false,
data: {} data: {},
}, },
type: 'VM', type: 'VM',
searchConfigs: vmSearchConfigs, searchConfigs: vmSearchConfigs,
@ -151,7 +149,7 @@ export default {
// //
textMap2: { textMap2: {
update: '主机修改', update: '主机修改',
create: '新增主机' create: '新增主机',
}, },
addHostVisible: false, addHostVisible: false,
addHostData: { addHostData: {
@ -164,7 +162,7 @@ export default {
ips: [], ips: [],
// ip: '', // ip: '',
username: '', username: '',
password: '' password: '',
}, },
typeName: 'ansible', typeName: 'ansible',
statusList: [ statusList: [
@ -174,54 +172,29 @@ export default {
{ id: 'PAUSED', name: '已停止' }, { id: 'PAUSED', name: '已停止' },
{ id: 'UNKNOWN', name: '已断开' }, { id: 'UNKNOWN', name: '已断开' },
{ id: 'EXCEPTION', name: '异常' }, { id: 'EXCEPTION', name: '异常' },
{ id: 'UNKNOWSTATUS', name: '未知' } { id: 'UNKNOWSTATUS', name: '未知' },
], ],
segmentIdList: [], segmentIdList: [],
flag: true, flag: true,
detail: {}, detail: {},
importDialog: { importDialog: {
visible: false visible: false,
}, },
idx: '', idx: '',
userConfig: { userConfig: {
visible: false visible: false,
} },
} }
}, },
computed: { computed: {
path() { path() {
return this.$route.path return this.$route.path
} },
}, },
watch: { watch: {
path(val) { path(val) {
this.judgeType(val) this.judgeType(val)
}
},
filters: {
vmStatusFilter(val) {
const statusMap = {
RUNNING: '运行中',
STOPPED: '已关机',
SUSPENDED: '已挂起',
PAUSED: '已停止',
UNKNOWN: '已断开',
EXCEPTION: '异常',
UNKNOWSTATUS: '未知'
}
return statusMap[val] || '未知'
}, },
vmStatusColorFilter(val) {
const statusMap = {
RUNNING: 'success',
STOPPED: 'danger',
SUSPENDED: 'danger',
PAUSED: 'danger',
EXCEPTION: 'warning',
UNKNOWN: 'warning'
}
return statusMap[val] || 'warning'
}
}, },
created() { created() {
this.judgeType(this.path) this.judgeType(this.path)
@ -241,7 +214,7 @@ export default {
// //
importData() { importData() {
this.importDialog = { this.importDialog = {
visible: true visible: true,
} }
}, },
async getsegmentIdList() { async getsegmentIdList() {
@ -256,7 +229,7 @@ export default {
addIp() { addIp() {
this.addHostData.ipList.push({ this.addHostData.ipList.push({
value: '', value: '',
key: Date.now() key: Date.now(),
}) })
this.$forceUpdate() this.$forceUpdate()
}, },
@ -286,14 +259,14 @@ export default {
category: this.type == 'VM' ? 'LOGICAL' : 'PHYSICAL', category: this.type == 'VM' ? 'LOGICAL' : 'PHYSICAL',
ipList: [ ipList: [
{ {
value: '' value: '',
} },
], ],
ips: [], ips: [],
// ip: '', // ip: '',
username: '', username: '',
password: '', password: '',
updateMode: 'MANUAL' updateMode: 'MANUAL',
} }
break break
case 2: case 2:
@ -308,7 +281,7 @@ export default {
ips.split(' ').forEach((item) => { ips.split(' ').forEach((item) => {
this.addHostData.ipList.push({ this.addHostData.ipList.push({
value: item, value: item,
key: Date.now() key: Date.now(),
}) })
}) })
break break
@ -340,7 +313,7 @@ export default {
if (data.success) { if (data.success) {
this.$message({ this.$message({
message: data.message, message: data.message,
type: 'success' type: 'success',
}) })
that.addHostVisible = false that.addHostVisible = false
that.getData() that.getData()
@ -354,13 +327,13 @@ export default {
dialog: true, dialog: true,
data: { data: {
...row, ...row,
ips: row.ips.includes('[') ? JSON.parse(row.ips).join('') : row.ips ips: row.ips.includes('[') ? JSON.parse(row.ips).join('') : row.ips,
} },
} }
}, },
handleSynchro(category) { handleSynchro(category) {
this.$confirm('执行同步操作前,请先在【分组管理—>网段管理】页面创建网段数据,以免影响正常使用,您确定要同步?', '提示', { this.$confirm('执行同步操作前,请先在【分组管理—>网段管理】页面创建网段数据,以免影响正常使用,您确定要同步?', '提示', {
type: 'warning' type: 'warning',
}).then(() => { }).then(() => {
syncHost(this.type == 'VM' ? 'LOGICAL' : 'PHYSICAL').then((res) => { syncHost(this.type == 'VM' ? 'LOGICAL' : 'PHYSICAL').then((res) => {
const type = res.success ? 'success' : 'error' const type = res.success ? 'success' : 'error'
@ -371,7 +344,7 @@ export default {
}, },
settingAllow(row) { settingAllow(row) {
this.$confirm('您确定要设置HostsAllow配置嘛?', '提示', { this.$confirm('您确定要设置HostsAllow配置嘛?', '提示', {
type: 'warning' type: 'warning',
}).then(() => { }).then(() => {
HostsAllow(row.id).then((res) => { HostsAllow(row.id).then((res) => {
const type = res.success ? 'success' : 'error' const type = res.success ? 'success' : 'error'
@ -382,7 +355,7 @@ export default {
}, },
handleDelete(row) { handleDelete(row) {
this.$confirm('您确定要删除该主机吗嘛?', '提示', { this.$confirm('您确定要删除该主机吗嘛?', '提示', {
type: 'warning' type: 'warning',
}).then(() => { }).then(() => {
deleteBsmHost(row.id).then((res) => { deleteBsmHost(row.id).then((res) => {
const type = res.success ? 'success' : 'error' const type = res.success ? 'success' : 'error'
@ -402,7 +375,7 @@ export default {
if (document.querySelector('#inspect')) document.querySelector('#inspect').checked = true if (document.querySelector('#inspect')) document.querySelector('#inspect').checked = true
this.$confirm(`<div>您确定要对主机[${row.ip}]进行纳管巡检吗?<div> <div><input type="checkbox" id="inspect" autocomplete="off" checked>是否更新密码再进行纳管巡检</div>`, '提示', { this.$confirm(`<div>您确定要对主机[${row.ip}]进行纳管巡检吗?<div> <div><input type="checkbox" id="inspect" autocomplete="off" checked>是否更新密码再进行纳管巡检</div>`, '提示', {
type: 'warning', type: 'warning',
dangerouslyUseHTMLString: true dangerouslyUseHTMLString: true,
}).then(() => { }).then(() => {
this.submitInspect({ id: row.id, force: document.querySelector('#inspect').checked }) this.submitInspect({ id: row.id, force: document.querySelector('#inspect').checked })
}) })
@ -425,7 +398,7 @@ export default {
OC = osCategory.toLocaleUpperCase() OC = osCategory.toLocaleUpperCase()
} }
this.$router.push({ name: 'serverConfig', params: { type: 'pm', osCategory: OC, host: data.ip, segmentId: data.segmentId } }) this.$router.push({ name: 'serverConfig', params: { type: 'pm', osCategory: OC, host: data.ip, segmentId: data.segmentId } })
} },
} },
} }
</script> </script>

View File

@ -47,7 +47,7 @@
<el-dialog title="服务器列表" :close-on-click-modal="false" :visible.sync="dialogServerVisible" append-to-body width="1200px"> <el-dialog title="服务器列表" :close-on-click-modal="false" :visible.sync="dialogServerVisible" append-to-body width="1200px">
<AdvanceTable :data="list" :card-border="false" row-key="id" :searchConfigs="searchConfigs" :params="params" :total="total" :columns="columns" :get-list="getList" :loading="loading" ref="tableRef" @select="handleSelectItem" @select-all="handleSelectAll"> <AdvanceTable :data="list" :card-border="false" row-key="id" :searchConfigs="searchConfigs" :params="params" :total="total" :columns="columns" :get-list="getList" :loading="loading" ref="tableRef" @select="handleSelectItem" @select-all="handleSelectAll">
<template #status="status"> <template #status="status">
<status-icon :type="vmStatusColorFilter(status, 'color')">{{ vmStatusFilter(status) }}</status-icon> <status-icon :type="status | vmStatusColorFilter">{{ status | vmStatusFilter }}</status-icon>
</template> </template>
</AdvanceTable> </AdvanceTable>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
@ -69,24 +69,24 @@ import { vmStatusFilter, vmStatusColorFilter } from '@/filters/index'
import { ref, nextTick, unref, computed, reactive, watch, defineComponent, Ref } from '@vue/composition-api' import { ref, nextTick, unref, computed, reactive, watch, defineComponent, Ref } from '@vue/composition-api'
import { Message, MessageBox } from 'element-ui' import { Message, MessageBox } from 'element-ui'
interface IHost { interface IHost {
id: number, id: number
name: string, name: string
ip: string, ip: string
port: number, port: number
segmentId: number, segmentId: number
osCategory: string, osCategory: string
username: string, username: string
pasd: string, pasd: string
password: string password: string
} }
interface ITargetHost { interface ITargetHost {
id: number, id: number
rawName: string, rawName: string
host: string, host: string
port: number, port: number
segmentId: number, segmentId: number
category: string, category: string
user: string, user: string
pasd: string pasd: string
} }
function formatHostData(list: IHost[]) { function formatHostData(list: IHost[]) {
@ -100,23 +100,24 @@ function formatHostData(list: IHost[]) {
segmentId, segmentId,
category, category,
user, user,
pasd: pasd && encrypt(pasd) pasd: pasd && encrypt(pasd),
} }
}) })
} }
export default defineComponent({ export default defineComponent({
props: { props: {
itemData: { itemData: {
type: Object type: Object,
}, },
osCategory: { // osCategorylinux/windows osCategory: {
// osCategorylinux/windows
type: String, type: String,
default: '' default: '',
}, },
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false default: false,
} },
}, },
setup(props, context) { setup(props, context) {
const hostData = reactive({ const hostData = reactive({
@ -131,14 +132,17 @@ export default defineComponent({
username, username,
pasd: password, pasd: password,
password, password,
osCategory osCategory,
} }
}) }),
}) })
// //
watch(() => hostData.list, () => { watch(
context.emit('host-change', formatHostData(hostData.list)) () => hostData.list,
}); () => {
context.emit('host-change', formatHostData(hostData.list))
}
)
const { list, total, params, loading, getList } = useTable({ const { list, total, params, loading, getList } = useTable({
getService: getHosts, getService: getHosts,
async afterGetList() { async afterGetList() {
@ -148,7 +152,7 @@ export default defineComponent({
unref(tableRef).toggleRowSelection(item, true) unref(tableRef).toggleRowSelection(item, true)
} }
}) })
} },
}) })
const selectList: Ref<IHost[]> = ref([]) const selectList: Ref<IHost[]> = ref([])
function handleSelectItem(selection: IHost[], row: IHost) { function handleSelectItem(selection: IHost[], row: IHost) {
@ -188,7 +192,7 @@ export default defineComponent({
...others, ...others,
osCategory, osCategory,
pasd: pasd || (password && decrypt(password)), pasd: pasd || (password && decrypt(password)),
port: port || (osCategory.toUpperCase() === 'WINDOWS' ? 5986 : 22) port: port || (osCategory.toUpperCase() === 'WINDOWS' ? 5986 : 22),
} }
}) })
dialogServerVisible.value = false dialogServerVisible.value = false
@ -211,7 +215,7 @@ export default defineComponent({
MessageBox.confirm('您确定要清空所选主机吗?', '提示', { MessageBox.confirm('您确定要清空所选主机吗?', '提示', {
confirmButtonText: '清空', confirmButtonText: '清空',
confirmButtonClass: 'el-button--danger', confirmButtonClass: 'el-button--danger',
type: 'warning' type: 'warning',
}).then(() => { }).then(() => {
hostData.list = [] hostData.list = []
}) })
@ -220,7 +224,7 @@ export default defineComponent({
MessageBox.confirm(`您确定要删除主机【${name}】吗?`, '提示', { MessageBox.confirm(`您确定要删除主机【${name}】吗?`, '提示', {
confirmButtonText: '清空', confirmButtonText: '清空',
confirmButtonClass: 'el-button--danger', confirmButtonClass: 'el-button--danger',
type: 'warning' type: 'warning',
}).then(() => { }).then(() => {
const index = hostData.list.findIndex((item: IHost) => item.id === id) const index = hostData.list.findIndex((item: IHost) => item.id === id)
hostData.list.splice(index, 1) hostData.list.splice(index, 1)
@ -246,8 +250,6 @@ export default defineComponent({
total, total,
params, params,
loading, loading,
vmStatusFilter,
vmStatusColorFilter,
getList, getList,
handleSelectItem, handleSelectItem,
handleSelectAll, handleSelectAll,
@ -259,9 +261,9 @@ export default defineComponent({
selectServer, selectServer,
clearServer, clearServer,
delServer, delServer,
getPostData getPostData,
} }
} },
}) })
</script> </script>
<style scoped> <style scoped>

View File

@ -14,6 +14,7 @@
"allowJs": true, "allowJs": true,
"baseUrl": ".", "baseUrl": ".",
"types": ["webpack-env"], "types": ["webpack-env"],
"outDir": "dist",
// "typeRoots": ["./node_modules/@types/", "./types"], // "typeRoots": ["./node_modules/@types/", "./types"],
"paths": { "paths": {
"@/*": ["src/*"], "@/*": ["src/*"],