feat(功能): 完善部分功能及界面

This commit is contained in:
Boen_Shi 2026-05-28 13:55:16 +08:00
parent f9cd176743
commit bb17029279

View File

@ -181,8 +181,6 @@
<el-option v-for='group in systemGroups' :key='group.groupname' :label='group.groupname' :value='group.groupname' /> <el-option v-for='group in systemGroups' :key='group.groupname' :label='group.groupname' :value='group.groupname' />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label='Shell'><el-input v-model='systemUserForm.shell' /></el-form-item>
<el-form-item label='Home'><el-input v-model='systemUserForm.home_dir' placeholder='可为空' clearable /></el-form-item>
</template> </template>
<template v-else> <template v-else>
<el-form-item label='用户组'><el-input v-model='systemUserForm.groupname' /></el-form-item> <el-form-item label='用户组'><el-input v-model='systemUserForm.groupname' /></el-form-item>
@ -318,11 +316,7 @@
<el-dialog v-model='protocolDialogVisible' :title='editingProtocolId ? "编辑协议" : "新增协议"' width='520px'> <el-dialog v-model='protocolDialogVisible' :title='editingProtocolId ? "编辑协议" : "新增协议"' width='520px'>
<el-form :model='protocolForm' label-width='90px'> <el-form :model='protocolForm' label-width='90px'>
<el-form-item label='协议名称'><el-input v-model='protocolForm.name' /></el-form-item> <el-form-item label='协议名称'><el-input v-model='protocolForm.name' /></el-form-item>
<el-form-item label='协议ID'><el-input-number v-model='protocolForm.bastion_protocol_id' :min='1'
class='w-full' /></el-form-item>
<el-form-item label='描述'><el-input v-model='protocolForm.description' /></el-form-item> <el-form-item label='描述'><el-input v-model='protocolForm.description' /></el-form-item>
<el-form-item label='排序'><el-input-number v-model='protocolForm.sort' :min='0' class='w-full' /></el-form-item>
<el-form-item label='启用'><el-switch v-model='protocolForm.is_active' /></el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<el-button @click='protocolDialogVisible = false'>取消</el-button> <el-button @click='protocolDialogVisible = false'>取消</el-button>
@ -336,8 +330,6 @@
</div> </div>
<el-table :data='softwareProtocol?.softwares || []' border> <el-table :data='softwareProtocol?.softwares || []' border>
<el-table-column prop='name' label='软件名称' min-width='160' /> <el-table-column prop='name' label='软件名称' min-width='160' />
<el-table-column prop='client_path' label='ClientPath' min-width='220' />
<el-table-column prop='sort' label='排序' width='80' />
<el-table-column label='启用' width='80'> <el-table-column label='启用' width='80'>
<template #default='{ row }'><el-tag :type='row.is_active ? "success" : "info"'>{{ row.is_active ? '是' : '否' <template #default='{ row }'><el-tag :type='row.is_active ? "success" : "info"'>{{ row.is_active ? '是' : '否'
}}</el-tag></template> }}</el-tag></template>
@ -351,17 +343,18 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<template #footer>
<el-button @click='softwareDialogVisible = false'>关闭</el-button>
</template>
</el-dialog>
<el-divider /> <el-dialog v-model='softwareFormDialogVisible' :title='editingSoftwareId ? "编辑软件" : "新增软件"' width='520px'>
<el-form :model='softwareForm' label-width='90px'> <el-form :model='softwareForm' label-width='90px'>
<el-form-item label='软件名称'><el-input v-model='softwareForm.name' /></el-form-item> <el-form-item label='软件名称'><el-input v-model='softwareForm.name' /></el-form-item>
<el-form-item label='ClientPath'><el-input v-model='softwareForm.client_path'
placeholder='可为空' /></el-form-item>
<el-form-item label='排序'><el-input-number v-model='softwareForm.sort' :min='0' class='w-full' /></el-form-item>
<el-form-item label='启用'><el-switch v-model='softwareForm.is_active' /></el-form-item> <el-form-item label='启用'><el-switch v-model='softwareForm.is_active' /></el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<el-button @click='softwareDialogVisible = false'>关闭</el-button> <el-button @click='softwareFormDialogVisible = false'>取消</el-button>
<el-button type='primary' :loading='opsSaving' @click='submitSoftware'>{{ editingSoftwareId ? '更新软件' : '新增软件' <el-button type='primary' :loading='opsSaving' @click='submitSoftware'>{{ editingSoftwareId ? '更新软件' : '新增软件'
}}</el-button> }}</el-button>
</template> </template>
@ -390,6 +383,7 @@ const passwordDialogVisible = ref(false)
const boundPasswordDialogVisible = ref(false) const boundPasswordDialogVisible = ref(false)
const protocolDialogVisible = ref(false) const protocolDialogVisible = ref(false)
const softwareDialogVisible = ref(false) const softwareDialogVisible = ref(false)
const softwareFormDialogVisible = ref(false)
const savingPermissions = ref(false) const savingPermissions = ref(false)
const usingResource = ref(false) const usingResource = ref(false)
const copyingTempPassword = ref(false) const copyingTempPassword = ref(false)
@ -421,12 +415,12 @@ const opsSavedSelections = reactive<Record<string, number | null>>({})
const typeOptions = [{ label: '服务器', value: 'server' }, { label: '资源', value: 'resource' }] const typeOptions = [{ label: '服务器', value: 'server' }, { label: '资源', value: 'resource' }]
const form = reactive<any>({ type: 'server', name: '', display_name: '', parent_id: null, internal_ip: '', user_api_base_url: '', user_api_token: '', asset_id: null, account_id: null, protocol: '', allow_copy_temp_password: false, description: '', is_active: true }) const form = reactive<any>({ type: 'server', name: '', display_name: '', parent_id: null, internal_ip: '', user_api_base_url: '', user_api_token: '', asset_id: null, account_id: null, protocol: '', allow_copy_temp_password: false, description: '', is_active: true })
const systemUserForm = reactive<any>({ username: '', password: '', groups: [], shell: '/bin/bash', home_dir: '', groupname: '' }) const systemUserForm = reactive<any>({ username: '', password: '', groups: [], groupname: '' })
const useForm = reactive<any>({ protocol: 'SSH', account_name: '', password: '', remember: false, last_temp_password: '' }) const useForm = reactive<any>({ protocol: 'SSH', account_name: '', password: '', remember: false, last_temp_password: '' })
const passwordForm = reactive<any>({ password: '' }) const passwordForm = reactive<any>({ password: '' })
const boundPasswordForm = reactive<any>({ password: '' }) const boundPasswordForm = reactive<any>({ password: '' })
const protocolForm = reactive<any>({ name: '', bastion_protocol_id: 2, description: '', sort: 0, is_active: true }) const protocolForm = reactive<any>({ name: '', description: '' })
const softwareForm = reactive<any>({ name: '', client_path: '', sort: 0, is_active: true }) const softwareForm = reactive<any>({ name: '', is_active: true })
const opsSelections = reactive<Record<string, number | null>>({}) const opsSelections = reactive<Record<string, number | null>>({})
const systemUserGroupSelections = reactive<Record<string, string[]>>({}) const systemUserGroupSelections = reactive<Record<string, string[]>>({})
const systemUsers = ref<any[]>([]) const systemUsers = ref<any[]>([])
@ -775,13 +769,13 @@ function bindingLabel(username: string): string {
function openCreateSystemUser(): void { function openCreateSystemUser(): void {
systemUserFormMode.value = 'user' systemUserFormMode.value = 'user'
Object.assign(systemUserForm, { username: '', password: '', groups: [], shell: '/bin/bash', home_dir: '', groupname: '' }) Object.assign(systemUserForm, { username: '', password: '', groups: [], groupname: '' })
systemUserFormVisible.value = true systemUserFormVisible.value = true
} }
function openCreateSystemGroup(): void { function openCreateSystemGroup(): void {
systemUserFormMode.value = 'group' systemUserFormMode.value = 'group'
Object.assign(systemUserForm, { username: '', password: '', groups: [], shell: '/bin/bash', home_dir: '', groupname: '' }) Object.assign(systemUserForm, { username: '', password: '', groups: [], groupname: '' })
systemUserFormVisible.value = true systemUserFormVisible.value = true
} }
@ -799,8 +793,6 @@ async function submitSystemUserForm(): Promise<void> {
username: systemUserForm.username, username: systemUserForm.username,
password: systemUserForm.password, password: systemUserForm.password,
groups: systemUserForm.groups, groups: systemUserForm.groups,
shell: systemUserForm.shell || '/bin/bash',
home_dir: systemUserForm.home_dir || null,
}) })
ElMessage.success('服务器用户创建成功') ElMessage.success('服务器用户创建成功')
} }
@ -990,7 +982,7 @@ async function fetchOpsMeta(): Promise<void> {
} }
function resetProtocolForm(): void { function resetProtocolForm(): void {
Object.assign(protocolForm, { name: '', bastion_protocol_id: 2, description: '', sort: 0, is_active: true }) Object.assign(protocolForm, { name: '', description: '' })
} }
function openCreateProtocol(): void { function openCreateProtocol(): void {
@ -1003,10 +995,7 @@ function openEditProtocol(row: any): void {
editingProtocolId.value = row.id editingProtocolId.value = row.id
Object.assign(protocolForm, { Object.assign(protocolForm, {
name: row.name, name: row.name,
bastion_protocol_id: row.bastion_protocol_id || 2,
description: row.description || '', description: row.description || '',
sort: row.sort || 0,
is_active: Boolean(row.is_active),
}) })
protocolDialogVisible.value = true protocolDialogVisible.value = true
} }
@ -1016,10 +1005,7 @@ async function submitProtocol(): Promise<void> {
try { try {
const payload = { const payload = {
name: protocolForm.name, name: protocolForm.name,
bastion_protocol_id: Number(protocolForm.bastion_protocol_id || 2),
description: protocolForm.description || '', description: protocolForm.description || '',
sort: protocolForm.sort || 0,
is_active: Boolean(protocolForm.is_active),
} }
if (editingProtocolId.value) { if (editingProtocolId.value) {
await serversApi.updateOpsProtocol(editingProtocolId.value, payload) await serversApi.updateOpsProtocol(editingProtocolId.value, payload)
@ -1047,27 +1033,28 @@ async function removeProtocol(row: any): Promise<void> {
function resetSoftwareForm(): void { function resetSoftwareForm(): void {
editingSoftwareId.value = null editingSoftwareId.value = null
Object.assign(softwareForm, { name: '', client_path: '', sort: 0, is_active: true }) Object.assign(softwareForm, { name: '', is_active: true })
} }
function openSoftwareDialog(row: any): void { function openSoftwareDialog(row: any): void {
softwareProtocol.value = row softwareProtocol.value = row
resetSoftwareForm() resetSoftwareForm()
softwareFormDialogVisible.value = false
softwareDialogVisible.value = true softwareDialogVisible.value = true
} }
function openCreateSoftware(): void { function openCreateSoftware(): void {
resetSoftwareForm() resetSoftwareForm()
softwareFormDialogVisible.value = true
} }
function openEditSoftware(row: any): void { function openEditSoftware(row: any): void {
editingSoftwareId.value = row.id editingSoftwareId.value = row.id
Object.assign(softwareForm, { Object.assign(softwareForm, {
name: row.name, name: row.name,
client_path: row.client_path || '',
sort: row.sort || 0,
is_active: Boolean(row.is_active), is_active: Boolean(row.is_active),
}) })
softwareFormDialogVisible.value = true
} }
async function submitSoftware(): Promise<void> { async function submitSoftware(): Promise<void> {
@ -1079,8 +1066,6 @@ async function submitSoftware(): Promise<void> {
try { try {
const payload = { const payload = {
name: softwareForm.name, name: softwareForm.name,
client_path: softwareForm.client_path || '',
sort: softwareForm.sort || 0,
is_active: Boolean(softwareForm.is_active), is_active: Boolean(softwareForm.is_active),
} }
if (editingSoftwareId.value) { if (editingSoftwareId.value) {
@ -1090,6 +1075,7 @@ async function submitSoftware(): Promise<void> {
await serversApi.createOpsSoftware(softwareProtocol.value.id, payload) await serversApi.createOpsSoftware(softwareProtocol.value.id, payload)
ElMessage.success('软件创建成功') ElMessage.success('软件创建成功')
} }
softwareFormDialogVisible.value = false
resetSoftwareForm() resetSoftwareForm()
await fetchOpsMeta() await fetchOpsMeta()
softwareProtocol.value = opsProtocols.value.find((item) => item.id === softwareProtocol.value?.id) || null softwareProtocol.value = opsProtocols.value.find((item) => item.id === softwareProtocol.value?.id) || null