mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-12-01 05:20:24 +08:00
reafctor: 团队管理与授权凭证优化
This commit is contained in:
@@ -48,10 +48,15 @@
|
||||
|
||||
<el-divider content-position="left">账号</el-divider>
|
||||
<div>
|
||||
<ResourceAuthCertEdit v-model="form.authCerts" :resource-code="form.code" :resource-type="TagResourceTypeEnum.Machine.value" />
|
||||
<ResourceAuthCertTableEdit
|
||||
v-model="form.authCerts"
|
||||
:resource-code="form.code"
|
||||
:resource-type="TagResourceTypeEnum.Machine.value"
|
||||
:test-conn-btn-loading="testConnBtnLoading"
|
||||
@test-conn="testConn"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- <el-tab-pane label="其他配置" name="other"> -->
|
||||
<el-divider content-position="left">其他</el-divider>
|
||||
<el-form-item prop="enableRecorder" label="终端回放">
|
||||
<el-checkbox v-model="form.enableRecorder" :true-value="1" :false-value="-1"></el-checkbox>
|
||||
@@ -64,7 +69,6 @@
|
||||
|
||||
<template #footer>
|
||||
<div>
|
||||
<el-button @click="testConn" :loading="testConnBtnLoading" type="success">测试连接</el-button>
|
||||
<el-button @click="cancel()">取 消</el-button>
|
||||
<el-button type="primary" :loading="saveBtnLoading" @click="btnOk">确 定</el-button>
|
||||
</div>
|
||||
@@ -78,7 +82,7 @@ import { reactive, ref, toRefs, watch } from 'vue';
|
||||
import { machineApi } from './api';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import TagTreeSelect from '../component/TagTreeSelect.vue';
|
||||
import ResourceAuthCertEdit from '../component/ResourceAuthCertEdit.vue';
|
||||
import ResourceAuthCertTableEdit from '../component/ResourceAuthCertTableEdit.vue';
|
||||
import SshTunnelSelect from '../component/SshTunnelSelect.vue';
|
||||
import { MachineProtocolEnum } from './enums';
|
||||
import DrawerHeader from '@/components/drawer-header/DrawerHeader.vue';
|
||||
@@ -165,7 +169,7 @@ const state = reactive({
|
||||
dialogVisible: false,
|
||||
sshTunnelMachineList: [] as any,
|
||||
form: defaultForm,
|
||||
submitForm: {},
|
||||
submitForm: {} as any,
|
||||
pwd: '',
|
||||
});
|
||||
|
||||
@@ -187,7 +191,7 @@ watch(props, async (newValue: any) => {
|
||||
}
|
||||
});
|
||||
|
||||
const testConn = async () => {
|
||||
const testConn = async (authCert: any) => {
|
||||
machineForm.value.validate(async (valid: boolean) => {
|
||||
if (!valid) {
|
||||
ElMessage.error('请正确填写信息');
|
||||
@@ -195,6 +199,7 @@ const testConn = async () => {
|
||||
}
|
||||
|
||||
state.submitForm = getReqForm();
|
||||
state.submitForm.authCerts = [authCert];
|
||||
await testConnExec();
|
||||
ElMessage.success('连接成功');
|
||||
});
|
||||
|
||||
@@ -106,7 +106,9 @@
|
||||
<el-divider direction="vertical" border-style="dashed" />
|
||||
</span>
|
||||
|
||||
<el-button :disabled="data.status == -1" type="warning" @click="serviceManager(data)" link>脚本</el-button>
|
||||
<el-button v-if="data.protocol == MachineProtocolEnum.Ssh.value" :disabled="data.status == -1" type="warning" @click="serviceManager(data)" link
|
||||
>脚本</el-button
|
||||
>
|
||||
<el-divider direction="vertical" border-style="dashed" />
|
||||
|
||||
<el-dropdown @command="handleCommand">
|
||||
@@ -120,11 +122,19 @@
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item :command="{ type: 'detail', data }"> 详情 </el-dropdown-item>
|
||||
|
||||
<el-dropdown-item :command="{ type: 'rdp-blank', data }" v-if="data.protocol == 2"> RDP(新窗口) </el-dropdown-item>
|
||||
<el-dropdown-item :command="{ type: 'rdp-blank', data }" v-if="data.protocol == MachineProtocolEnum.Rdp.value">
|
||||
RDP(新窗口)
|
||||
</el-dropdown-item>
|
||||
|
||||
<el-dropdown-item :command="{ type: 'edit', data }" v-if="actionBtns[perms.updateMachine]"> 编辑 </el-dropdown-item>
|
||||
|
||||
<el-dropdown-item :command="{ type: 'process', data }" :disabled="data.status == -1"> 进程 </el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
v-if="data.protocol == MachineProtocolEnum.Ssh.value"
|
||||
:command="{ type: 'process', data }"
|
||||
:disabled="data.status == -1"
|
||||
>
|
||||
进程
|
||||
</el-dropdown-item>
|
||||
|
||||
<el-dropdown-item :command="{ type: 'terminalRec', data }" v-if="actionBtns[perms.updateMachine] && data.enableRecorder == 1">
|
||||
终端回放
|
||||
@@ -177,7 +187,12 @@
|
||||
|
||||
<process-list v-model:visible="processDialog.visible" v-model:machineId="processDialog.machineId" />
|
||||
|
||||
<script-manage :title="serviceDialog.title" v-model:visible="serviceDialog.visible" v-model:machineId="serviceDialog.machineId" />
|
||||
<script-manage
|
||||
:title="serviceDialog.title"
|
||||
v-model:visible="serviceDialog.visible"
|
||||
v-model:machineId="serviceDialog.machineId"
|
||||
:auth-cert-name="serviceDialog.authCertName"
|
||||
/>
|
||||
|
||||
<file-conf-list
|
||||
:title="fileDialog.title"
|
||||
@@ -298,6 +313,7 @@ const state = reactive({
|
||||
serviceDialog: {
|
||||
visible: false,
|
||||
machineId: 0,
|
||||
authCertName: '',
|
||||
title: '',
|
||||
},
|
||||
processDialog: {
|
||||
@@ -468,9 +484,11 @@ const deleteMachine = async () => {
|
||||
};
|
||||
|
||||
const serviceManager = (row: any) => {
|
||||
const authCert = row.selectAuthCert;
|
||||
state.serviceDialog.machineId = row.id;
|
||||
state.serviceDialog.authCertName = authCert.name;
|
||||
state.serviceDialog.visible = true;
|
||||
state.serviceDialog.title = `${row.name} => ${row.ip}`;
|
||||
state.serviceDialog.title = `${row.name} => ${authCert.username}@${row.ip}`;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -111,10 +111,16 @@
|
||||
|
||||
<process-list v-model:visible="processDialog.visible" v-model:machineId="processDialog.machineId" />
|
||||
|
||||
<script-manage :title="serviceDialog.title" v-model:visible="serviceDialog.visible" v-model:machineId="serviceDialog.machineId" />
|
||||
<script-manage
|
||||
:title="serviceDialog.title"
|
||||
v-model:visible="serviceDialog.visible"
|
||||
v-model:machineId="serviceDialog.machineId"
|
||||
:auth-cert-name="serviceDialog.authCertName"
|
||||
/>
|
||||
|
||||
<file-conf-list
|
||||
:title="fileDialog.title"
|
||||
:auth-cert-name="fileDialog.authCertName"
|
||||
v-model:visible="fileDialog.visible"
|
||||
v-model:machineId="fileDialog.machineId"
|
||||
:protocol="fileDialog.protocol"
|
||||
@@ -129,6 +135,7 @@
|
||||
>
|
||||
<machine-file
|
||||
:machine-id="state.filesystemDialog.machineId"
|
||||
:auth-cert-name="state.filesystemDialog.authCertName"
|
||||
:protocol="state.filesystemDialog.protocol"
|
||||
:file-id="state.filesystemDialog.fileId"
|
||||
:path="state.filesystemDialog.path"
|
||||
@@ -202,6 +209,7 @@ const state = reactive({
|
||||
serviceDialog: {
|
||||
visible: false,
|
||||
machineId: 0,
|
||||
authCertName: '',
|
||||
title: '',
|
||||
},
|
||||
processDialog: {
|
||||
@@ -213,10 +221,12 @@ const state = reactive({
|
||||
machineId: 0,
|
||||
protocol: 1,
|
||||
title: '',
|
||||
authCertName: '',
|
||||
},
|
||||
filesystemDialog: {
|
||||
visible: false,
|
||||
machineId: 0,
|
||||
authCertName: '',
|
||||
protocol: 1,
|
||||
title: '',
|
||||
fileId: 0,
|
||||
@@ -280,8 +290,17 @@ const NodeTypeMachine = new NodeType(MachineNodeType.Machine)
|
||||
})
|
||||
.withContextMenuItems([
|
||||
new ContextmenuItem('detail', '详情').withIcon('More').withOnClick((node: any) => showInfo(node.params)),
|
||||
new ContextmenuItem('status', '状态').withIcon('Compass').withOnClick((node: any) => showMachineStats(node.params)),
|
||||
new ContextmenuItem('process', '进程').withIcon('DataLine').withOnClick((node: any) => showProcess(node.params)),
|
||||
|
||||
new ContextmenuItem('status', '状态')
|
||||
.withIcon('Compass')
|
||||
.withHideFunc((node: any) => node.params.protocol != MachineProtocolEnum.Ssh.value)
|
||||
.withOnClick((node: any) => showMachineStats(node.params)),
|
||||
|
||||
new ContextmenuItem('process', '进程')
|
||||
.withIcon('DataLine')
|
||||
.withHideFunc((node: any) => node.params.protocol != MachineProtocolEnum.Ssh.value)
|
||||
.withOnClick((node: any) => showProcess(node.params)),
|
||||
|
||||
new ContextmenuItem('edit', '终端回放')
|
||||
.withIcon('Compass')
|
||||
.withOnClick((node: any) => showRec(node.params))
|
||||
@@ -296,7 +315,11 @@ const NodeTypeAuthCert = new NodeType(MachineNodeType.AuthCert)
|
||||
new ContextmenuItem('term', '打开终端').withIcon('Monitor').withOnClick((node: any) => openTerminal(node.params)),
|
||||
new ContextmenuItem('term-ex', '打开终端(新窗口)').withIcon('Monitor').withOnClick((node: any) => openTerminal(node.params, true)),
|
||||
new ContextmenuItem('files', '文件管理').withIcon('FolderOpened').withOnClick((node: any) => showFileManage(node.params)),
|
||||
new ContextmenuItem('scripts', '脚本管理').withIcon('Files').withOnClick((node: any) => serviceManager(node.params)),
|
||||
|
||||
new ContextmenuItem('scripts', '脚本管理')
|
||||
.withIcon('Files')
|
||||
.withHideFunc((node: any) => node.params.protocol != MachineProtocolEnum.Ssh.value)
|
||||
.withOnClick((node: any) => serviceManager(node.params)),
|
||||
]);
|
||||
|
||||
const openTerminal = (machine: any, ex?: boolean) => {
|
||||
@@ -356,9 +379,11 @@ const openTerminal = (machine: any, ex?: boolean) => {
|
||||
};
|
||||
|
||||
const serviceManager = (row: any) => {
|
||||
const authCert = row.selectAuthCert;
|
||||
state.serviceDialog.machineId = row.id;
|
||||
state.serviceDialog.visible = true;
|
||||
state.serviceDialog.title = `${row.name} => ${row.ip}`;
|
||||
state.serviceDialog.authCertName = authCert.name;
|
||||
state.serviceDialog.title = `${row.name} => ${authCert.username}@${row.ip}`;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -376,16 +401,19 @@ const search = async () => {
|
||||
};
|
||||
|
||||
const showFileManage = (selectionData: any) => {
|
||||
const authCert = selectionData.selectAuthCert;
|
||||
if (selectionData.protocol == 1) {
|
||||
state.fileDialog.visible = true;
|
||||
state.fileDialog.protocol = selectionData.protocol;
|
||||
state.fileDialog.machineId = selectionData.id;
|
||||
state.fileDialog.title = `${selectionData.name} => ${selectionData.ip}`;
|
||||
state.fileDialog.authCertName = authCert.name;
|
||||
state.fileDialog.title = `${selectionData.name} => ${authCert.username}@${selectionData.ip}`;
|
||||
}
|
||||
|
||||
if (selectionData.protocol == 2) {
|
||||
state.filesystemDialog.protocol = 2;
|
||||
state.filesystemDialog.machineId = selectionData.id;
|
||||
state.filesystemDialog.authCertName = authCert.name;
|
||||
state.filesystemDialog.fileId = selectionData.id;
|
||||
state.filesystemDialog.path = '/';
|
||||
state.filesystemDialog.title = `远程桌面文件管理`;
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
draggable
|
||||
append-to-body
|
||||
>
|
||||
<TerminalBody ref="terminal" :cmd="terminalDialog.cmd" :socket-url="getMachineTerminalSocketUrl(terminalDialog.machineId)" height="560px" />
|
||||
<TerminalBody ref="terminal" :cmd="terminalDialog.cmd" :socket-url="getMachineTerminalSocketUrl(props.authCertName)" height="560px" />
|
||||
</el-dialog>
|
||||
|
||||
<script-edit
|
||||
@@ -100,6 +100,7 @@ import { SearchItem } from '@/components/SearchForm';
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean },
|
||||
machineId: { type: Number },
|
||||
authCertName: { type: String },
|
||||
title: { type: String },
|
||||
});
|
||||
|
||||
@@ -143,7 +144,6 @@ const state = reactive({
|
||||
terminalDialog: {
|
||||
visible: false,
|
||||
cmd: '',
|
||||
machineId: 0,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -195,6 +195,7 @@ const run = async (script: any) => {
|
||||
if (script.type == ScriptResultEnum.Result.value || noResult) {
|
||||
const res = await machineApi.runScript.request({
|
||||
machineId: props.machineId,
|
||||
ac: props.authCertName,
|
||||
scriptId: script.id,
|
||||
params: JSON.stringify(state.scriptParamsDialog.params),
|
||||
});
|
||||
@@ -215,7 +216,6 @@ const run = async (script: any) => {
|
||||
}
|
||||
state.terminalDialog.cmd = script;
|
||||
state.terminalDialog.visible = true;
|
||||
state.terminalDialog.machineId = props.machineId as any;
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -236,7 +236,6 @@ function templateResolve(template: string, param: any) {
|
||||
|
||||
const closeTermnial = () => {
|
||||
state.terminalDialog.visible = false;
|
||||
state.terminalDialog.machineId = 0;
|
||||
};
|
||||
|
||||
const editScript = (data: any) => {
|
||||
|
||||
@@ -20,7 +20,7 @@ export const machineApi = {
|
||||
// 删除机器
|
||||
del: Api.newDelete('/machines/{id}'),
|
||||
scripts: Api.newGet('/machines/{machineId}/scripts'),
|
||||
runScript: Api.newGet('/machines/{machineId}/scripts/{scriptId}/run'),
|
||||
runScript: Api.newGet('/machines/scripts/{scriptId}/{ac}/run'),
|
||||
saveScript: Api.newPost('/machines/{machineId}/scripts'),
|
||||
deleteScript: Api.newDelete('/machines/{machineId}/scripts/{scriptId}'),
|
||||
// 获取配置文件列表
|
||||
@@ -48,13 +48,6 @@ export const machineApi = {
|
||||
termOpRec: Api.newGet('/machines/{id}/term-recs/{recId}'),
|
||||
};
|
||||
|
||||
export const authCertApi = {
|
||||
baseList: Api.newGet('/sys/authcerts/base'),
|
||||
list: Api.newGet('/sys/authcerts'),
|
||||
save: Api.newPost('/sys/authcerts'),
|
||||
delete: Api.newDelete('/sys/authcerts/{id}'),
|
||||
};
|
||||
|
||||
export const cronJobApi = {
|
||||
list: Api.newGet('/machine-cronjobs'),
|
||||
relateMachineIds: Api.newGet('/machine-cronjobs/machine-ids'),
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog :title="title" v-model="dvisible" :show-close="false" :before-close="cancel" width="500px" :destroy-on-close="true">
|
||||
<el-form ref="acForm" :rules="rules" :model="form" label-width="auto">
|
||||
<el-form-item prop="name" label="名称" required>
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="authMethod" label="认证方式" required>
|
||||
<el-select style="width: 100%" v-model="form.authMethod" placeholder="请选择认证方式">
|
||||
<el-option key="1" label="密码" :value="1"> </el-option>
|
||||
<el-option key="2" label="密钥" :value="2"> </el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.authMethod == 1" prop="password" label="密码">
|
||||
<el-input type="password" show-password clearable v-model.trim="form.password" placeholder="请输入密码" autocomplete="new-password">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.authMethod == 2" prop="password" label="秘钥">
|
||||
<el-input type="textarea" :rows="5" v-model="form.password" placeholder="请将私钥文件内容拷贝至此"> </el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.authMethod == 2" prop="passphrase" label="秘钥密码">
|
||||
<el-input type="password" v-model="form.passphrase"> </el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remark" type="textarea" :rows="2"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="cancel()">取 消</el-button>
|
||||
<el-button type="primary" :loading="btnLoading" @click="btnOk">确 定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, toRefs, reactive, watch } from 'vue';
|
||||
import { authCertApi } from '../api';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
},
|
||||
data: {
|
||||
type: [Boolean, Object],
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
});
|
||||
|
||||
//定义事件
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
|
||||
|
||||
const acForm: any = ref(null);
|
||||
|
||||
const rules = {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '授权凭证名称不能为空',
|
||||
trigger: ['change', 'blur'],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const state = reactive({
|
||||
dvisible: false,
|
||||
params: [] as any,
|
||||
form: {
|
||||
id: null,
|
||||
name: '',
|
||||
authMethod: 1,
|
||||
password: '',
|
||||
passphrase: '',
|
||||
remark: '',
|
||||
},
|
||||
btnLoading: false,
|
||||
});
|
||||
|
||||
const { dvisible, form, btnLoading } = toRefs(state);
|
||||
|
||||
watch(props, (newValue: any) => {
|
||||
state.dvisible = newValue.visible;
|
||||
if (newValue.data) {
|
||||
state.form = { ...newValue.data };
|
||||
} else {
|
||||
state.form = { authMethod: 1 } as any;
|
||||
state.params = [];
|
||||
}
|
||||
});
|
||||
|
||||
const cancel = () => {
|
||||
// 更新父组件visible prop对应的值为false
|
||||
emit('update:visible', false);
|
||||
// 若父组件有取消事件,则调用
|
||||
emit('cancel');
|
||||
};
|
||||
|
||||
const btnOk = async () => {
|
||||
acForm.value.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
state.btnLoading = true;
|
||||
try {
|
||||
await authCertApi.save.request(state.form);
|
||||
emit('val-change', state.form);
|
||||
cancel();
|
||||
} finally {
|
||||
state.btnLoading = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
@@ -1,106 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<page-table
|
||||
ref="pageTableRef"
|
||||
:page-api="authCertApi.list"
|
||||
:search-items="state.searchItems"
|
||||
v-model:query-form="query"
|
||||
:show-selection="true"
|
||||
v-model:selection-data="selectionData"
|
||||
:columns="state.columns"
|
||||
>
|
||||
<template #tableHeader>
|
||||
<el-button type="primary" icon="plus" @click="edit(false)">添加</el-button>
|
||||
<el-button :disabled="selectionData.length < 1" @click="deleteAc(selectionData)" type="danger" icon="delete">删除 </el-button>
|
||||
</template>
|
||||
|
||||
<template #action="{ data }">
|
||||
<el-button @click="edit(data)" type="primary" link>编辑 </el-button>
|
||||
</template>
|
||||
</page-table>
|
||||
|
||||
<auth-cert-edit :title="editor.title" v-model:visible="editor.visible" :data="editor.authcert" @val-change="editChange" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { toRefs, reactive, onMounted, ref, Ref } from 'vue';
|
||||
import AuthCertEdit from './AuthCertEdit.vue';
|
||||
import { authCertApi } from '../api';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import PageTable from '@/components/pagetable/PageTable.vue';
|
||||
import { TableColumn } from '@/components/pagetable';
|
||||
import { AuthMethodEnum } from '../enums';
|
||||
import { SearchItem } from '@/components/SearchForm';
|
||||
|
||||
const pageTableRef: Ref<any> = ref(null);
|
||||
const state = reactive({
|
||||
query: {
|
||||
pageNum: 1,
|
||||
pageSize: 0,
|
||||
name: null,
|
||||
},
|
||||
searchItems: [SearchItem.input('name', '凭证名称')],
|
||||
columns: [
|
||||
TableColumn.new('name', '名称'),
|
||||
TableColumn.new('authMethod', '认证方式').typeTag(AuthMethodEnum),
|
||||
TableColumn.new('remark', '备注'),
|
||||
TableColumn.new('creator', '创建人'),
|
||||
TableColumn.new('createTime', '创建时间').isTime(),
|
||||
TableColumn.new('creator', '修改者'),
|
||||
TableColumn.new('createTime', '修改时间').isTime(),
|
||||
TableColumn.new('action', '操作').isSlot().fixedRight().setMinWidth(65).alignCenter(),
|
||||
],
|
||||
selectionData: [],
|
||||
paramsDialog: {
|
||||
visible: false,
|
||||
config: null as any,
|
||||
params: {},
|
||||
paramsFormItem: [] as any,
|
||||
},
|
||||
editor: {
|
||||
title: '授权凭证保存',
|
||||
visible: false,
|
||||
authcert: {},
|
||||
},
|
||||
});
|
||||
|
||||
const { query, selectionData, editor } = toRefs(state);
|
||||
|
||||
onMounted(() => {});
|
||||
|
||||
const search = async () => {
|
||||
pageTableRef.value.search();
|
||||
};
|
||||
|
||||
const editChange = () => {
|
||||
ElMessage.success('保存成功');
|
||||
search();
|
||||
};
|
||||
|
||||
const edit = (data: any) => {
|
||||
if (data) {
|
||||
state.editor.authcert = data;
|
||||
} else {
|
||||
state.editor.authcert = false;
|
||||
}
|
||||
|
||||
state.editor.visible = true;
|
||||
};
|
||||
|
||||
const deleteAc = async (data: any) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定删除该【${data.map((x: any) => x.name).join(', ')}授权凭证?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
});
|
||||
await authCertApi.delete.request({ id: data.map((x: any) => x.id).join(',') });
|
||||
ElMessage.success('删除成功');
|
||||
search();
|
||||
} catch (err) {
|
||||
//
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
@@ -1,57 +0,0 @@
|
||||
<template>
|
||||
<div style="width: 100%">
|
||||
<el-select @change="changeValue" v-model="id" filterable placeholder="请选择授权凭证,可前往[机器管理->授权凭证]添加" style="width: 100%">
|
||||
<el-option v-for="ac in acs" :key="ac.id" :value="ac.id" :label="ac.name">
|
||||
<el-tag v-if="ac.authMethod == 1" type="success" size="small">密码</el-tag>
|
||||
<el-tag v-if="ac.authMethod == 2" size="small">密钥</el-tag>
|
||||
|
||||
<el-divider direction="vertical" border-style="dashed" />
|
||||
{{ ac.name }}
|
||||
|
||||
<el-divider direction="vertical" border-style="dashed" />
|
||||
{{ ac.remark }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, toRefs, onMounted } from 'vue';
|
||||
import { authCertApi } from '../api';
|
||||
|
||||
//定义事件
|
||||
const emit = defineEmits(['update:modelValue', 'change']);
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [Number],
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
acs: [] as any,
|
||||
id: null as any,
|
||||
});
|
||||
|
||||
const { acs, id } = toRefs(state);
|
||||
|
||||
onMounted(async () => {
|
||||
await getAcs();
|
||||
if (props.modelValue) {
|
||||
state.id = props.modelValue;
|
||||
}
|
||||
});
|
||||
|
||||
const changeValue = (val: any) => {
|
||||
emit('update:modelValue', val);
|
||||
emit('change', val);
|
||||
};
|
||||
|
||||
const getAcs = async () => {
|
||||
const acs = await authCertApi.baseList.request({ pageSize: 100, type: 2 });
|
||||
state.acs = acs.list;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss"></style>
|
||||
Reference in New Issue
Block a user