review: 数据库实例管理调整

This commit is contained in:
meilin.huang
2023-09-05 12:49:12 +08:00
parent baf8053613
commit d0ac7de4cb
16 changed files with 199 additions and 137 deletions

View File

@@ -25,7 +25,7 @@ export async function RsaEncrypt(value: any) {
if (!value) { if (!value) {
return ''; return '';
} }
if (encryptor != null) { if (encryptor != null && sessionStorage.getItem('RsaPublicKey') != null) {
return encryptor.encrypt(value); return encryptor.encrypt(value);
} }
encryptor = new JSEncrypt(); encryptor = new JSEncrypt();

View File

@@ -1,14 +1,39 @@
<template> <template>
<div> <div>
<el-dialog :title="title" v-model="dialogVisible" @open="open" :before-close="cancel" :close-on-click-modal="false" :destroy-on-close="true" width="38%"> <el-dialog
:title="title"
v-model="dialogVisible"
@open="open"
:before-close="cancel"
:close-on-click-modal="false"
:destroy-on-close="true"
width="38%"
>
<el-form :model="form" ref="dbForm" :rules="rules" label-width="auto"> <el-form :model="form" ref="dbForm" :rules="rules" label-width="auto">
<el-form-item prop="tagId" label="标签:" required> <el-form-item prop="tagId" label="标签:" required>
<tag-select v-model="form.tagId" v-model:tag-path="form.tagPath" style="width: 100%" /> <tag-select v-model="form.tagId" v-model:tag-path="form.tagPath" style="width: 100%" />
</el-form-item> </el-form-item>
<el-form-item prop="instanceId" label="数据库实例:" required> <el-form-item prop="instanceId" label="数据库实例:" required>
<el-select :disabled="form.id !== undefined" @change="getAllDatabase" v-model="form.instanceId" placeholder="请选择实例" filterable clearable style="width: 200px"> <el-select
<el-option v-for="item in state.instances" :key="item.id" :label="item.name" :value="item.id"> </el-option> :disabled="form.id !== undefined"
remote
:remote-method="getInstances"
@change="getAllDatabase"
v-model="form.instanceId"
placeholder="请输入实例名称搜索并选择实例"
filterable
clearable
class="w100"
>
<el-option v-for="item in state.instances" :key="item.id" :label="`${item.name}`" :value="item.id">
{{ item.name }}
<el-divider direction="vertical" border-style="dashed" />
{{ item.type }} / {{ item.host }}:{{ item.port }}
<el-divider direction="vertical" border-style="dashed" />
{{ item.username }}
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
@@ -17,20 +42,20 @@
</el-form-item> </el-form-item>
<el-form-item prop="database" label="数据库名:" required> <el-form-item prop="database" label="数据库名:" required>
<el-select <el-select
@change="changeDatabase" @change="changeDatabase"
v-model="databaseList" v-model="databaseList"
multiple multiple
clearable clearable
collapse-tags collapse-tags
collapse-tags-tooltip collapse-tags-tooltip
filterable filterable
allow-create allow-create
placeholder="请确保数据库实例信息填写完整后获取库名" placeholder="请确保数据库实例信息填写完整后获取库名"
style="width: 100%" style="width: 100%"
> >
<el-option v-for="db in allDatabases" :key="db" :label="db" :value="db" /> <el-option v-for="db in allDatabases" :key="db" :label="db" :value="db" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item prop="remark" label="备注:"> <el-form-item prop="remark" label="备注:">
@@ -146,21 +171,28 @@ const changeDatabase = () => {
}; };
const getAllDatabase = async () => { const getAllDatabase = async () => {
const reqForm = { ...state.form };
if (state.form.instanceId > 0) { if (state.form.instanceId > 0) {
state.allDatabases = await dbApi.getAllDatabase.request(reqForm); state.allDatabases = await dbApi.getAllDatabase.request({ instanceId: state.form.instanceId });
} }
}; };
const getAllInstances = async () => { const getInstances = async (instanceName: string = '', id = 0) => {
const data = await dbApi.instances.request(null); if (!id && !instanceName) {
state.instances = [];
return;
}
const data = await dbApi.instances.request({ id, name: instanceName });
if (data) { if (data) {
state.instances = data.list; state.instances = data.list;
} }
} };
const open = async () => { const open = async () => {
await getAllInstances() if (state.form.instanceId) {
await getAllDatabase() // 根据id获取因为需要回显实例名称
getInstances('', state.form.instanceId);
}
await getAllDatabase();
}; };
const btnOk = async () => { const btnOk = async () => {

View File

@@ -20,8 +20,23 @@
</template> </template>
<template #instanceSelect> <template #instanceSelect>
<el-select @focus="getInstances" v-model="query.instanceId" placeholder="请选择实例" filterable clearable style="width: 200px"> <el-select
<el-option v-for="item in instances" :key="item.id" :label="item.name" :value="item.id"> </el-option> remote
:remote-method="getInstances"
v-model="query.instanceId"
placeholder="输入并选择实例"
filterable
clearable
style="width: 200px"
>
<el-option v-for="item in state.instances" :key="item.id" :label="`${item.name}`" :value="item.id">
{{ item.name }}
<el-divider direction="vertical" border-style="dashed" />
{{ item.type }} / {{ item.host }}:{{ item.port }}
<el-divider direction="vertical" border-style="dashed" />
{{ item.username }}
</el-option>
</el-select> </el-select>
</template> </template>
@@ -234,21 +249,21 @@
<el-dialog v-model="infoDialog.visible" :before-close="onBeforeCloseInfoDialog" :close-on-click-modal="false"> <el-dialog v-model="infoDialog.visible" :before-close="onBeforeCloseInfoDialog" :close-on-click-modal="false">
<el-descriptions title="详情" :column="3" border> <el-descriptions title="详情" :column="3" border>
<el-descriptions-item :span="3" label="标签路径">{{ infoDialog.data.tagPath }}</el-descriptions-item> <el-descriptions-item :span="3" label="标签路径">{{ infoDialog.data?.tagPath }}</el-descriptions-item>
<el-descriptions-item :span="2" label="名称">{{ infoDialog.data.name }}</el-descriptions-item> <el-descriptions-item :span="2" label="名称">{{ infoDialog.data?.name }}</el-descriptions-item>
<el-descriptions-item :span="1" label="id">{{ infoDialog.data.id }}</el-descriptions-item> <el-descriptions-item :span="1" label="id">{{ infoDialog.data?.id }}</el-descriptions-item>
<el-descriptions-item :span="3" label="数据库">{{ infoDialog.data.database }}</el-descriptions-item> <el-descriptions-item :span="3" label="数据库">{{ infoDialog.data?.database }}</el-descriptions-item>
<el-descriptions-item :span="3" label="备注">{{ infoDialog.data.remark }}</el-descriptions-item> <el-descriptions-item :span="3" label="备注">{{ infoDialog.data?.remark }}</el-descriptions-item>
<el-descriptions-item :span="2" label="创建时间">{{ dateFormat(infoDialog.data.createTime) }} </el-descriptions-item> <el-descriptions-item :span="2" label="创建时间">{{ dateFormat(infoDialog.data?.createTime) }} </el-descriptions-item>
<el-descriptions-item :span="1" label="创建者">{{ infoDialog.data.creator }}</el-descriptions-item> <el-descriptions-item :span="1" label="创建者">{{ infoDialog.data?.creator }}</el-descriptions-item>
<el-descriptions-item :span="2" label="更新时间">{{ dateFormat(infoDialog.data.updateTime) }} </el-descriptions-item> <el-descriptions-item :span="2" label="更新时间">{{ dateFormat(infoDialog.data?.updateTime) }} </el-descriptions-item>
<el-descriptions-item :span="1" label="修改者">{{ infoDialog.data.modifier }}</el-descriptions-item> <el-descriptions-item :span="1" label="修改者">{{ infoDialog.data?.modifier }}</el-descriptions-item>
<el-descriptions-item :span="3" label="数据库实例名称">{{ infoDialog.instance.name }}</el-descriptions-item> <el-descriptions-item :span="3" label="数据库实例名称">{{ infoDialog.instance?.name }}</el-descriptions-item>
<el-descriptions-item :span="2" label="主机">{{ infoDialog.instance.host }}</el-descriptions-item> <el-descriptions-item :span="2" label="主机">{{ infoDialog.instance?.host }}</el-descriptions-item>
<el-descriptions-item :span="1" label="端口">{{ infoDialog.instance.port }}</el-descriptions-item> <el-descriptions-item :span="1" label="端口">{{ infoDialog.instance?.port }}</el-descriptions-item>
<el-descriptions-item :span="2" label="用户名">{{ infoDialog.instance.username }}</el-descriptions-item> <el-descriptions-item :span="2" label="用户名">{{ infoDialog.instance?.username }}</el-descriptions-item>
<el-descriptions-item :span="1" label="类型">{{ infoDialog.instance.type }}</el-descriptions-item> <el-descriptions-item :span="1" label="类型">{{ infoDialog.instance?.type }}</el-descriptions-item>
</el-descriptions> </el-descriptions>
</el-dialog> </el-dialog>
@@ -291,10 +306,7 @@ const perms = {
delDb: 'db:del', delDb: 'db:del',
}; };
const queryConfig = [ const queryConfig = [TableQuery.slot('tagPath', '标签', 'tagPathSelect'), TableQuery.slot('instanceId', '实例', 'instanceSelect')];
TableQuery.slot('tagPath', '标签', 'tagPathSelect'),
TableQuery.slot('instanceId', '实例', 'instanceSelect'),
];
const columns = ref([ const columns = ref([
TableColumn.new('tagPath', '标签路径').isSlot().setAddWidth(20), TableColumn.new('tagPath', '标签路径').isSlot().setAddWidth(20),
@@ -315,7 +327,7 @@ const state = reactive({
dbId: 0, dbId: 0,
db: '', db: '',
tags: [], tags: [],
instances: [], instances: [] as any,
/** /**
* 选中的数据 * 选中的数据
*/ */
@@ -337,7 +349,7 @@ const state = reactive({
instance: null as any, instance: null as any,
query: { query: {
instanceId: 0, instanceId: 0,
} },
}, },
showDumpInfo: false, showDumpInfo: false,
dumpInfo: { dumpInfo: {
@@ -504,19 +516,23 @@ const showInfo = async (info: any) => {
}; };
const onBeforeCloseInfoDialog = () => { const onBeforeCloseInfoDialog = () => {
state.infoDialog.visible = false; state.infoDialog.visible = false;
state.infoDialog.data = null; state.infoDialog.data = null;
state.infoDialog.instance = null; state.infoDialog.instance = null;
}; };
const getTags = async () => { const getTags = async () => {
state.tags = await dbApi.dbTags.request(null); state.tags = await dbApi.dbTags.request(null);
}; };
const getInstances = async () => { const getInstances = async (instanceName = '') => {
const data = await dbApi.instances.request(null); if (!instanceName) {
state.instances = [];
return;
}
const data = await dbApi.instances.request({ name: instanceName });
if (data) { if (data) {
state.instances = data.list; state.instances = data.list;
} }
}; };

View File

@@ -26,13 +26,17 @@
<el-input v-model.trim="form.username" placeholder="请输入用户名"></el-input> <el-input v-model.trim="form.username" placeholder="请输入用户名"></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password" label="密码:"> <el-form-item prop="password" label="密码:">
<el-input <el-input type="password" show-password v-model.trim="form.password" placeholder="请输入密码" autocomplete="new-password">
type="password" <template v-if="form.id && form.id != 0" #suffix>
show-password <el-popover @hide="pwd = ''" placement="right" title="原密码" :width="200" trigger="click" :content="pwd">
v-model.trim="form.password" <template #reference>
placeholder="请输入密码" <el-link v-auth="'db:instance:save'" @click="getDbPwd" :underline="false" type="primary" class="mr5"
autocomplete="new-password" >原密码
/> </el-link>
</template>
</el-popover>
</template>
</el-input>
</el-form-item> </el-form-item>
<el-form-item prop="remark" label="备注:"> <el-form-item prop="remark" label="备注:">
@@ -79,7 +83,6 @@ import { dbApi } from './api';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { notBlank } from '@/common/assert'; import { notBlank } from '@/common/assert';
import { RsaEncrypt } from '@/common/rsa'; import { RsaEncrypt } from '@/common/rsa';
import TagSelect from '../component/TagSelect.vue';
import SshTunnelSelect from '../component/SshTunnelSelect.vue'; import SshTunnelSelect from '../component/SshTunnelSelect.vue';
const props = defineProps({ const props = defineProps({
@@ -161,11 +164,11 @@ watch(props, (newValue: any) => {
} }
state.tabActiveName = 'basic'; state.tabActiveName = 'basic';
if (newValue.data) { if (newValue.data) {
state.form = { ...newValue.data}; state.form = { ...newValue.data };
state.oldUserName = state.form.username state.oldUserName = state.form.username;
} else { } else {
state.form = { port: 3306 } as any; state.form = { port: 3306 } as any;
state.oldUserName = null state.oldUserName = null;
} }
}); });
@@ -177,7 +180,7 @@ const btnOk = async () => {
if (!state.form.id) { if (!state.form.id) {
notBlank(state.form.password, '新增操作,密码不可为空'); notBlank(state.form.password, '新增操作,密码不可为空');
} else if (state.form.username != state.oldUserName) { } else if (state.form.username != state.oldUserName) {
notBlank(state.form.password, '已修改用户名,请输入密码'); notBlank(state.form.password, '已修改用户名,请输入密码');
} }
dbForm.value.validate(async (valid: boolean) => { dbForm.value.validate(async (valid: boolean) => {

View File

@@ -15,7 +15,9 @@
> >
<template #queryRight> <template #queryRight>
<el-button v-auth="perms.saveInstance" type="primary" icon="plus" @click="editInstance(false)">添加</el-button> <el-button v-auth="perms.saveInstance" type="primary" icon="plus" @click="editInstance(false)">添加</el-button>
<el-button v-auth="perms.delInstance" :disabled="selectionData.length < 1" @click="deleteInstance()" type="danger" icon="delete">删除</el-button> <el-button v-auth="perms.delInstance" :disabled="selectionData.length < 1" @click="deleteInstance()" type="danger" icon="delete"
>删除</el-button
>
</template> </template>
<template #more="{ data }"> <template #more="{ data }">
@@ -50,12 +52,17 @@
</el-descriptions> </el-descriptions>
</el-dialog> </el-dialog>
<instance-edit @val-change="valChange" :title="instanceEditDialog.title" v-model:visible="instanceEditDialog.visible" v-model:data="instanceEditDialog.data"></instance-edit> <instance-edit
@val-change="valChange"
:title="instanceEditDialog.title"
v-model:visible="instanceEditDialog.visible"
v-model:data="instanceEditDialog.data"
></instance-edit>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, toRefs, reactive, computed, onMounted, defineAsyncComponent } from 'vue'; import { ref, toRefs, reactive, onMounted, defineAsyncComponent } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import { dbApi } from './api'; import { dbApi } from './api';
import { dateFormat } from '@/common/utils/date'; import { dateFormat } from '@/common/utils/date';
@@ -66,8 +73,8 @@ import { hasPerms } from '@/components/auth/auth';
const InstanceEdit = defineAsyncComponent(() => import('./InstanceEdit.vue')); const InstanceEdit = defineAsyncComponent(() => import('./InstanceEdit.vue'));
const perms = { const perms = {
saveInstance: 'instance:save', saveInstance: 'db:instance:save',
delInstance: 'instance:del', delInstance: 'db:instance:del',
}; };
const queryConfig = [TableQuery.text('name', '名称')]; const queryConfig = [TableQuery.text('name', '名称')];
@@ -116,16 +123,7 @@ const state = reactive({
}, },
}); });
const { const { selectionData, query, datas, total, infoDialog, instanceEditDialog } = toRefs(state);
dbId,
db,
selectionData,
query,
datas,
total,
infoDialog,
instanceEditDialog,
} = toRefs(state);
onMounted(async () => { onMounted(async () => {
if (Object.keys(actionBtns).length > 0) { if (Object.keys(actionBtns).length > 0) {
@@ -177,6 +175,5 @@ const deleteInstance = async () => {
search(); search();
} catch (err) {} } catch (err) {}
}; };
</script> </script>
<style lang="scss"></style> <style lang="scss"></style>

View File

@@ -44,8 +44,7 @@
<template #default> <template #default>
<el-form class="instances-pop-form" label-width="55px" :size="'small'"> <el-form class="instances-pop-form" label-width="55px" :size="'small'">
<el-form-item label="类型:">{{ data.params.type }}</el-form-item> <el-form-item label="类型:">{{ data.params.type }}</el-form-item>
<el-form-item label="链接:">{{ data.params.host }}:{{ data.params.port }}</el-form-item> <el-form-item label="名称:">{{ data.params.name }}</el-form-item>
<el-form-item label="用户:">{{ data.params.username }}</el-form-item>
<el-form-item v-if="data.params.remark" label="备注:">{{ data.params.remark }}</el-form-item> <el-form-item v-if="data.params.remark" label="备注:">{{ data.params.remark }}</el-form-item>
</el-form> </el-form>
</template> </template>
@@ -633,12 +632,12 @@ const registerSqlCompletionItemProvider = () => {
range, range,
}); });
}); });
let replacedFunctions = [] as string[]; let replacedFunctions = [] as string[];
// 添加的函数 // 添加的函数
addSqlLanguage.replaceFunctions.forEach((item: any) => { addSqlLanguage.replaceFunctions.forEach((item: any) => {
replacedFunctions.push(item.label) replacedFunctions.push(item.label);
suggestions.push({ suggestions.push({
label: { label: {
label: item.label, label: item.label,
@@ -649,18 +648,19 @@ const registerSqlCompletionItemProvider = () => {
range, range,
}); });
}); });
// 内置函数 // 内置函数
sqlCompletionBuiltinFunctions.forEach((item: any) => { sqlCompletionBuiltinFunctions.forEach((item: any) => {
replacedFunctions.indexOf(item) < 0 && suggestions.push({ replacedFunctions.indexOf(item) < 0 &&
label: { suggestions.push({
label: item, label: {
description: 'func', label: item,
}, description: 'func',
kind: monaco.languages.CompletionItemKind.Function, },
insertText: item, kind: monaco.languages.CompletionItemKind.Function,
range, insertText: item,
}); range,
});
}); });
// 内置变量 // 内置变量
sqlCompletionBuiltinVariables.forEach((item: string) => { sqlCompletionBuiltinVariables.forEach((item: string) => {

View File

@@ -9,16 +9,16 @@
:destroy-on-close="true" :destroy-on-close="true"
width="900px" width="900px"
> >
<el-form :model="form" ref="scriptForm" label-width="auto"> <el-form :model="form" :rules="rules" ref="scriptForm" label-width="auto">
<el-form-item prop="method" label="名称"> <el-form-item prop="name" label="名称" required>
<el-input v-model="form.name" placeholder="请输入名称"></el-input> <el-input v-model="form.name" placeholder="请输入名称"></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="description" label="描述"> <el-form-item prop="description" label="描述" required>
<el-input v-model="form.description" placeholder="请输入描述"></el-input> <el-input v-model="form.description" placeholder="请输入描述"></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="type" label="类型"> <el-form-item prop="type" label="类型" required>
<el-select v-model="form.type" default-first-option style="width: 100%" placeholder="请选择类型"> <el-select v-model="form.type" default-first-option style="width: 100%" placeholder="请选择类型">
<el-option v-for="item in ScriptResultEnum" :key="item.value" :label="item.label" :value="item.value"></el-option> <el-option v-for="item in ScriptResultEnum" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select> </el-select>
@@ -59,7 +59,11 @@
</el-row> </el-row>
</el-form-item> </el-form-item>
<monaco-editor v-model="form.script" language="shell" height="300px" /> <el-form-item required prop="script" class="100w">
<div style="width: 100%">
<monaco-editor v-model="form.script" language="shell" height="300px" />
</div>
</el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
@@ -100,6 +104,37 @@ const props = defineProps({
const emit = defineEmits(['update:visible', 'cancel', 'submitSuccess']); const emit = defineEmits(['update:visible', 'cancel', 'submitSuccess']);
const rules = {
name: [
{
required: true,
message: '请输入名称',
trigger: ['change', 'blur'],
},
],
description: [
{
required: true,
message: '请输入描述',
trigger: ['blur', 'change'],
},
],
type: [
{
required: true,
message: '请选择类型',
trigger: ['change', 'blur'],
},
],
script: [
{
required: true,
message: '请输入脚本',
trigger: ['blur', 'change'],
},
],
};
const { isCommon, machineId } = toRefs(props); const { isCommon, machineId } = toRefs(props);
const scriptForm: any = ref(null); const scriptForm: any = ref(null);
@@ -147,12 +182,8 @@ const onDeleteParam = (idx: number) => {
const btnOk = () => { const btnOk = () => {
state.form.machineId = isCommon.value ? 9999999 : (machineId?.value as any); state.form.machineId = isCommon.value ? 9999999 : (machineId?.value as any);
console.log('machineid:', machineId);
scriptForm.value.validate((valid: any) => { scriptForm.value.validate((valid: any) => {
if (valid) { if (valid) {
notEmpty(state.form.name, '名称不能为空');
notEmpty(state.form.description, '描述不能为空');
notEmpty(state.form.script, '内容不能为空');
if (state.params) { if (state.params) {
state.form.params = JSON.stringify(state.params); state.form.params = JSON.stringify(state.params);
} }

View File

@@ -1,24 +1,23 @@
package api package api
import ( import (
"github.com/gin-gonic/gin"
"mayfly-go/internal/db/api/form" "mayfly-go/internal/db/api/form"
"mayfly-go/internal/db/api/vo" "mayfly-go/internal/db/api/vo"
"mayfly-go/internal/db/application" "mayfly-go/internal/db/application"
"mayfly-go/internal/db/domain/entity" "mayfly-go/internal/db/domain/entity"
msgapp "mayfly-go/internal/msg/application"
"mayfly-go/pkg/biz" "mayfly-go/pkg/biz"
"mayfly-go/pkg/ginx" "mayfly-go/pkg/ginx"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
"mayfly-go/pkg/utils/cryptox" "mayfly-go/pkg/utils/cryptox"
"strconv" "strconv"
"strings" "strings"
"github.com/gin-gonic/gin"
) )
type Instance struct { type Instance struct {
InstanceApp application.Instance InstanceApp application.Instance
DbApp application.Db DbApp application.Db
MsgApp msgapp.Msg
} }
// Instances 获取数据库实例信息 // Instances 获取数据库实例信息

View File

@@ -4,17 +4,9 @@ import "mayfly-go/pkg/model"
// 数据库实例查询 // 数据库实例查询
type InstanceQuery struct { type InstanceQuery struct {
model.Model Id uint64 `json:"id" form:"id"`
Name string `json:"name" form:"name"`
Name string `orm:"column(name)" json:"name" form:"name"` Host string `json:"host" form:"host"`
Type string `orm:"column(type)" json:"type"` // 类型mysql oracle等
Host string `orm:"column(host)" json:"host"`
Port int `orm:"column(port)" json:"port"`
Network string `orm:"column(network)" json:"network"`
Username string `orm:"column(username)" json:"username"`
Password string `orm:"column(password)" json:"-"`
Params string `orm:"column(params)" json:"params"`
Remark string `orm:"column(remark)" json:"remark"`
} }
// 数据库查询实体,不与数据库表字段一一对应 // 数据库查询实体,不与数据库表字段一一对应

View File

@@ -17,9 +17,8 @@ func newInstanceRepo() repository.Instance {
// 分页获取数据库信息列表 // 分页获取数据库信息列表
func (d *instanceRepoImpl) GetInstanceList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] { func (d *instanceRepoImpl) GetInstanceList(condition *entity.InstanceQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) *model.PageResult[any] {
qd := gormx.NewQuery(new(entity.Instance)). qd := gormx.NewQuery(new(entity.Instance)).
Eq("id", condition.Id).
Eq("host", condition.Host). Eq("host", condition.Host).
Eq("port", condition.Port).
Eq("username", condition.Username).
Like("name", condition.Name) Like("name", condition.Name)
return gormx.PageQuery(qd, pageParam, toEntity) return gormx.PageQuery(qd, pageParam, toEntity)
} }

View File

@@ -3,7 +3,6 @@ package router
import ( import (
"mayfly-go/internal/db/api" "mayfly-go/internal/db/api"
"mayfly-go/internal/db/application" "mayfly-go/internal/db/application"
msgapp "mayfly-go/internal/msg/application"
"mayfly-go/pkg/req" "mayfly-go/pkg/req"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@@ -15,7 +14,6 @@ func InitInstanceRouter(router *gin.RouterGroup) {
d := &api.Instance{ d := &api.Instance{
InstanceApp: application.GetInstanceApp(), InstanceApp: application.GetInstanceApp(),
DbApp: application.GetDbApp(), DbApp: application.GetDbApp(),
MsgApp: msgapp.GetMsgApp(),
} }
reqs := [...]*req.Conf{ reqs := [...]*req.Conf{

View File

@@ -129,12 +129,8 @@ func (m *Machine) GetProcess(rc *req.Ctx) {
cmd += fmt.Sprintf("| grep %s ", pname) cmd += fmt.Sprintf("| grep %s ", pname)
} }
count := g.Query("count") count := ginx.QueryInt(g, "count", 10)
if count == "" { cmd += "| head -n " + fmt.Sprintf("%d", count)
count = "10"
}
cmd += "| head -n " + count
cli := m.MachineApp.GetCli(GetMachineId(rc.GinCtx)) cli := m.MachineApp.GetCli(GetMachineId(rc.GinCtx))
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s") biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.LoginAccount.Id, cli.GetMachine().TagPath), "%s")

View File

@@ -104,7 +104,7 @@ func (d *mongoAppImpl) GetMongoInst(id uint64) *MongoInstance {
var mongoCliCache = cache.NewTimedCache(consts.MongoConnExpireTime, 5*time.Second). var mongoCliCache = cache.NewTimedCache(consts.MongoConnExpireTime, 5*time.Second).
WithUpdateAccessTime(true). WithUpdateAccessTime(true).
OnEvicted(func(key any, value any) { OnEvicted(func(key any, value any) {
logx.Info("删除mongo连接缓存: id = ", key) logx.Infof("删除mongo连接缓存: id = %s", key)
value.(*MongoInstance).Close() value.(*MongoInstance).Close()
}) })

View File

@@ -635,9 +635,9 @@ INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES(134, 80, 'Mongo452/eggago31/3sblw1Wb/', 2, 1, '删除数据', 'mongo:data:del', 1692674964, 'null', 1, 'admin', 1, 'admin', '2023-08-22 11:29:24', '2023-08-22 11:29:24', 0, NULL); INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES(134, 80, 'Mongo452/eggago31/3sblw1Wb/', 2, 1, '删除数据', 'mongo:data:del', 1692674964, 'null', 1, 'admin', 1, 'admin', '2023-08-22 11:29:24', '2023-08-22 11:29:24', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES(133, 80, 'Mongo452/eggago31/xvpKk36u/', 2, 1, '保存数据', 'mongo:data:save', 1692674943, 'null', 1, 'admin', 1, 'admin', '2023-08-22 11:29:04', '2023-08-22 11:29:11', 0, NULL); INSERT INTO t_sys_resource (id, pid, ui_path, type, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES(133, 80, 'Mongo452/eggago31/xvpKk36u/', 2, 1, '保存数据', 'mongo:data:save', 1692674943, 'null', 1, 'admin', 1, 'admin', '2023-08-22 11:29:04', '2023-08-22 11:29:11', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (135, 36, 'dbms23ax/X0f4BxT0/', 1, 1, '数据库实例管理', 'instances', 1693040706, '{\"component\":\"ops/db/InstanceList\",\"icon\":\"Coin\",\"isKeepAlive\":true,\"routeName\":\"InstanceList\"}', 1, 'admin', 1, 'admin', '2023-08-26 09:05:07', '2023-08-29 22:35:11', 0, NULL); INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (135, 36, 'dbms23ax/X0f4BxT0/', 1, 1, '数据库实例管理', 'instances', 1693040706, '{\"component\":\"ops/db/InstanceList\",\"icon\":\"Coin\",\"isKeepAlive\":true,\"routeName\":\"InstanceList\"}', 1, 'admin', 1, 'admin', '2023-08-26 09:05:07', '2023-08-29 22:35:11', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (136, 133, 'dbms23ax/X0f4BxT0/D23fUiBr/', 2, 1, '实例保存', 'instance:save', 1693041001, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:10:02', '2023-08-26 09:10:02', 0, NULL); INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (136, 135, 'dbms23ax/X0f4BxT0/D23fUiBr/', 2, 1, '实例保存', 'db:instance:save', 1693041001, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:10:02', '2023-08-26 09:10:02', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (137, 133, 'dbms23ax/X0f4BxT0/mJlBeTCs/', 2, 1, '基本权限', 'instance', 1693041055, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:10:55', '2023-08-26 09:10:55', 0, NULL); INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (137, 135, 'dbms23ax/X0f4BxT0/mJlBeTCs/', 2, 1, '基本权限', 'db:instance', 1693041055, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:10:55', '2023-08-26 09:10:55', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (138, 133, 'dbms23ax/X0f4BxT0/Sgg8uPwz/', 2, 1, '实例删除', 'instance:del', 1693041084, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:11:24', '2023-08-26 09:11:24', 0, NULL); INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (138, 135, 'dbms23ax/X0f4BxT0/Sgg8uPwz/', 2, 1, '实例删除', 'db:instance:del', 1693041084, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:11:24', '2023-08-26 09:11:24', 0, NULL);
COMMIT; COMMIT;
-- ---------------------------- -- ----------------------------

View File

@@ -28,11 +28,11 @@ BEGIN;
INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (135, 36, 'dbms23ax/X0f4BxT0/', 1, 1, '数据库实例管理', 'instances', 1693040706, '{\"component\":\"ops/db/InstanceList\",\"icon\":\"Coin\",\"isKeepAlive\":true,\"routeName\":\"InstanceList\"}', 1, 'admin', 1, 'admin', '2023-08-26 09:05:07', '2023-08-29 22:35:11', 0, NULL); INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (135, 36, 'dbms23ax/X0f4BxT0/', 1, 1, '数据库实例管理', 'instances', 1693040706, '{\"component\":\"ops/db/InstanceList\",\"icon\":\"Coin\",\"isKeepAlive\":true,\"routeName\":\"InstanceList\"}', 1, 'admin', 1, 'admin', '2023-08-26 09:05:07', '2023-08-29 22:35:11', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (136, 133, 'dbms23ax/X0f4BxT0/D23fUiBr/', 2, 1, '实例保存', 'instance:save', 1693041001, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:10:02', '2023-08-26 09:10:02', 0, NULL); INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (136, 135, 'dbms23ax/X0f4BxT0/D23fUiBr/', 2, 1, '实例保存', 'db:instance:save', 1693041001, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:10:02', '2023-08-26 09:10:02', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (137, 133, 'dbms23ax/X0f4BxT0/mJlBeTCs/', 2, 1, '基本权限', 'instance', 1693041055, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:10:55', '2023-08-26 09:10:55', 0, NULL); INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (137, 135, 'dbms23ax/X0f4BxT0/mJlBeTCs/', 2, 1, '基本权限', 'db:instance', 1693041055, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:10:55', '2023-08-26 09:10:55', 0, NULL);
INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (138, 133, 'dbms23ax/X0f4BxT0/Sgg8uPwz/', 2, 1, '实例删除', 'instance:del', 1693041084, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:11:24', '2023-08-26 09:11:24', 0, NULL); INSERT INTO t_sys_resource (id, pid, ui_path, `type`, status, name, code, weight, meta, creator_id, creator, modifier_id, modifier, create_time, update_time, is_deleted, delete_time) VALUES (138, 135, 'dbms23ax/X0f4BxT0/Sgg8uPwz/', 2, 1, '实例删除', 'db:instance:del', 1693041084, 'null', 1, 'admin', 1, 'admin', '2023-08-26 09:11:24', '2023-08-26 09:11:24', 0, NULL);
INSERT INTO `t_sys_role_resource` (role_id,resource_id,creator_id,creator,create_time,is_deleted,delete_time) VALUES INSERT INTO `t_sys_role_resource` (role_id,resource_id,creator_id,creator,create_time,is_deleted,delete_time) VALUES
(1,135,1,'admin','2023-08-30 20:17:00', 0, NULL), (1,135,1,'admin','2023-08-30 20:17:00', 0, NULL),

View File

@@ -50,7 +50,6 @@ func (rc *Ctx) Handle(handler HandlerFunc) {
} }
handler(rc) handler(rc)
rc.timed = time.Since(begin).Milliseconds()
if rc.Conf == nil || !rc.Conf.noRes { if rc.Conf == nil || !rc.Conf.noRes {
ginx.SuccessRes(ginCtx, rc.ResData) ginx.SuccessRes(ginCtx, rc.ResData)
} }