mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-20 16:20:25 +08:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05625bd8c1 | ||
|
|
4afeac5fdd | ||
|
|
1d0e91f1af | ||
|
|
cf5111a325 | ||
|
|
78957a8ebd | ||
|
|
29fd5a25d2 |
@@ -14,7 +14,7 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
server:
|
server:
|
||||||
image: mayfly-go:v1.3.1
|
image: ccr.ccs.tencentyun.com/mayfly/mayfly-go:v1.8.3
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
"sql-formatter": "^15.0.2",
|
"sql-formatter": "^15.0.2",
|
||||||
"trzsz": "^1.1.5",
|
"trzsz": "^1.1.5",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"vue": "^3.4.25",
|
"vue": "^3.4.27",
|
||||||
"vue-router": "^4.3.2",
|
"vue-router": "^4.3.2",
|
||||||
"xterm": "^5.3.0",
|
"xterm": "^5.3.0",
|
||||||
"xterm-addon-fit": "^0.8.0",
|
"xterm-addon-fit": "^0.8.0",
|
||||||
@@ -48,15 +48,15 @@
|
|||||||
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
||||||
"@typescript-eslint/parser": "^6.7.4",
|
"@typescript-eslint/parser": "^6.7.4",
|
||||||
"@vitejs/plugin-vue": "^5.0.4",
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
"@vue/compiler-sfc": "^3.4.25",
|
"@vue/compiler-sfc": "^3.4.27",
|
||||||
"code-inspector-plugin": "^0.4.5",
|
"code-inspector-plugin": "^0.4.5",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"eslint": "^8.35.0",
|
"eslint": "^8.35.0",
|
||||||
"eslint-plugin-vue": "^9.25.0",
|
"eslint-plugin-vue": "^9.25.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"sass": "^1.75.0",
|
"sass": "^1.76.0",
|
||||||
"typescript": "^5.4.5",
|
"typescript": "^5.4.5",
|
||||||
"vite": "^5.2.10",
|
"vite": "^5.2.11",
|
||||||
"vue-eslint-parser": "^9.4.2"
|
"vue-eslint-parser": "^9.4.2"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const config = {
|
|||||||
baseWsUrl: `${(window as any).globalConfig.BaseWsUrl || `${location.protocol == 'https:' ? 'wss:' : 'ws:'}//${getBaseApiUrl()}`}/api`,
|
baseWsUrl: `${(window as any).globalConfig.BaseWsUrl || `${location.protocol == 'https:' ? 'wss:' : 'ws:'}//${getBaseApiUrl()}`}/api`,
|
||||||
|
|
||||||
// 系统版本
|
// 系统版本
|
||||||
version: 'v1.8.2',
|
version: 'v1.8.3',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-drawer @open="initSort" :title="title" v-model="visible" :before-close="cancel" :destroy-on-close="true" :close-on-click-modal="false">
|
<el-drawer @open="initSort" :title="title" v-model="visible" :before-close="cancel" :destroy-on-close="true" :close-on-click-modal="false" size="40%">
|
||||||
<template #header>
|
<template #header>
|
||||||
<DrawerHeader :header="title" :back="cancel" />
|
<DrawerHeader :header="title" :back="cancel" />
|
||||||
</template>
|
</template>
|
||||||
@@ -21,6 +21,10 @@
|
|||||||
<el-input v-model.trim="form.remark" placeholder="备注" auto-complete="off" clearable></el-input>
|
<el-input v-model.trim="form.remark" placeholder="备注" auto-complete="off" clearable></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item ref="tagSelectRef" prop="codePaths" label="关联资源">
|
||||||
|
<tag-tree-check height="300px" v-model="form.codePaths" :tag-type="[TagResourceTypeEnum.DbName.value, TagResourceTypeEnum.Redis.value]" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-divider content-position="left">审批节点</el-divider>
|
<el-divider content-position="left">审批节点</el-divider>
|
||||||
|
|
||||||
<el-table ref="taskTableRef" :data="tasks" row-key="taskKey" stripe style="width: 100%">
|
<el-table ref="taskTableRef" :data="tasks" row-key="taskKey" stripe style="width: 100%">
|
||||||
@@ -70,6 +74,8 @@ import AccountSelectFormItem from '@/views/system/account/components/AccountSele
|
|||||||
import Sortable from 'sortablejs';
|
import Sortable from 'sortablejs';
|
||||||
import { randomUuid } from '../../common/utils/string';
|
import { randomUuid } from '../../common/utils/string';
|
||||||
import { ProcdefStatus } from './enums';
|
import { ProcdefStatus } from './enums';
|
||||||
|
import TagTreeCheck from '../ops/component/TagTreeCheck.vue';
|
||||||
|
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
@@ -115,6 +121,7 @@ const state = reactive({
|
|||||||
remark: null,
|
remark: null,
|
||||||
// 流程的审批节点任务
|
// 流程的审批节点任务
|
||||||
tasks: '',
|
tasks: '',
|
||||||
|
codePaths: [],
|
||||||
},
|
},
|
||||||
sortable: '' as any,
|
sortable: '' as any,
|
||||||
});
|
});
|
||||||
@@ -126,6 +133,7 @@ const { isFetching: saveBtnLoading, execute: saveFlowDefExec } = procdefApi.save
|
|||||||
watch(props, (newValue: any) => {
|
watch(props, (newValue: any) => {
|
||||||
if (newValue.data) {
|
if (newValue.data) {
|
||||||
state.form = { ...newValue.data };
|
state.form = { ...newValue.data };
|
||||||
|
state.form.codePaths = newValue.data.tags?.map((tag: any) => tag.codePath);
|
||||||
const tasks = JSON.parse(state.form.tasks);
|
const tasks = JSON.parse(state.form.tasks);
|
||||||
tasks.forEach((t: any) => {
|
tasks.forEach((t: any) => {
|
||||||
t.userId = Number.parseInt(t.userId);
|
t.userId = Number.parseInt(t.userId);
|
||||||
@@ -160,25 +168,26 @@ const deleteTask = (idx: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const btnOk = async () => {
|
const btnOk = async () => {
|
||||||
formRef.value.validate(async (valid: boolean) => {
|
try {
|
||||||
if (!valid) {
|
await formRef.value.validate();
|
||||||
ElMessage.error('表单填写有误');
|
} catch (e: any) {
|
||||||
return false;
|
ElMessage.error('请正确填写信息');
|
||||||
}
|
return false;
|
||||||
const checkRes = checkTasks();
|
}
|
||||||
if (checkRes.err) {
|
|
||||||
ElMessage.error(checkRes.err);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.form.tasks = JSON.stringify(checkRes.tasks);
|
const checkRes = checkTasks();
|
||||||
await saveFlowDefExec();
|
if (checkRes.err) {
|
||||||
ElMessage.success('操作成功');
|
ElMessage.error(checkRes.err);
|
||||||
emit('val-change', state.form);
|
return false;
|
||||||
//重置表单域
|
}
|
||||||
formRef.value.resetFields();
|
|
||||||
state.form = {} as any;
|
state.form.tasks = JSON.stringify(checkRes.tasks);
|
||||||
});
|
await saveFlowDefExec();
|
||||||
|
ElMessage.success('操作成功');
|
||||||
|
emit('val-change', state.form);
|
||||||
|
//重置表单域
|
||||||
|
formRef.value.resetFields();
|
||||||
|
state.form = {} as any;
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkTasks = () => {
|
const checkTasks = () => {
|
||||||
|
|||||||
@@ -18,6 +18,10 @@
|
|||||||
<el-link @click="showProcdefTasks(data)" icon="view" type="primary" :underline="false"> </el-link>
|
<el-link @click="showProcdefTasks(data)" icon="view" type="primary" :underline="false"> </el-link>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #codePaths="{ data }">
|
||||||
|
<TagCodePath :path="data.tags?.map((tag: any) => tag.codePath)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #action="{ data }">
|
<template #action="{ data }">
|
||||||
<el-button link v-if="actionBtns[perms.save]" @click="editFlowDef(data)" type="primary">编辑</el-button>
|
<el-button link v-if="actionBtns[perms.save]" @click="editFlowDef(data)" type="primary">编辑</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -42,6 +46,7 @@ import { SearchItem } from '@/components/SearchForm';
|
|||||||
import ProcdefEdit from './ProcdefEdit.vue';
|
import ProcdefEdit from './ProcdefEdit.vue';
|
||||||
import ProcdefTasks from './components/ProcdefTasks.vue';
|
import ProcdefTasks from './components/ProcdefTasks.vue';
|
||||||
import { ProcdefStatus } from './enums';
|
import { ProcdefStatus } from './enums';
|
||||||
|
import TagCodePath from '../ops/component/TagCodePath.vue';
|
||||||
|
|
||||||
const perms = {
|
const perms = {
|
||||||
save: 'flow:procdef:save',
|
save: 'flow:procdef:save',
|
||||||
@@ -55,6 +60,7 @@ const columns = [
|
|||||||
TableColumn.new('status', '状态').typeTag(ProcdefStatus),
|
TableColumn.new('status', '状态').typeTag(ProcdefStatus),
|
||||||
TableColumn.new('remark', '备注'),
|
TableColumn.new('remark', '备注'),
|
||||||
TableColumn.new('tasks', '审批节点').isSlot().alignCenter().setMinWidth(60),
|
TableColumn.new('tasks', '审批节点').isSlot().alignCenter().setMinWidth(60),
|
||||||
|
TableColumn.new('codePaths', '关联资源').isSlot().setMinWidth('250px'),
|
||||||
TableColumn.new('creator', '创建账号'),
|
TableColumn.new('creator', '创建账号'),
|
||||||
TableColumn.new('createTime', '创建时间').isTime(),
|
TableColumn.new('createTime', '创建时间').isTime(),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import Api from '@/common/Api';
|
|||||||
|
|
||||||
export const procdefApi = {
|
export const procdefApi = {
|
||||||
list: Api.newGet('/flow/procdefs'),
|
list: Api.newGet('/flow/procdefs'),
|
||||||
getByKey: Api.newGet('/flow/procdefs/{key}'),
|
getByResource: Api.newGet('/flow/procdefs/{resourceType}/{resourceCode}'),
|
||||||
save: Api.newPost('/flow/procdefs'),
|
save: Api.newPost('/flow/procdefs'),
|
||||||
del: Api.newDelete('/flow/procdefs/{id}'),
|
del: Api.newDelete('/flow/procdefs/{id}'),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import { toRefs, reactive, watch, onMounted } from 'vue';
|
|||||||
import { accountApi } from '../../system/api';
|
import { accountApi } from '../../system/api';
|
||||||
import { ProcinstTaskStatus } from '../enums';
|
import { ProcinstTaskStatus } from '../enums';
|
||||||
import { dateFormat } from '@/common/utils/date';
|
import { dateFormat } from '@/common/utils/date';
|
||||||
import { procdefApi } from '../api';
|
|
||||||
import { ElSteps, ElStep } from 'element-plus';
|
import { ElSteps, ElStep } from 'element-plus';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -23,8 +22,8 @@ const props = defineProps({
|
|||||||
tasks: {
|
tasks: {
|
||||||
type: [String, Object],
|
type: [String, Object],
|
||||||
},
|
},
|
||||||
procdefKey: {
|
procdef: {
|
||||||
type: String,
|
type: [Object],
|
||||||
},
|
},
|
||||||
// 流程实例任务列表
|
// 流程实例任务列表
|
||||||
procinstTasks: {
|
procinstTasks: {
|
||||||
@@ -54,7 +53,7 @@ watch(
|
|||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.procdefKey,
|
() => props.procdef,
|
||||||
async (newValue: any) => {
|
async (newValue: any) => {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
parseTasksByKey(newValue);
|
parseTasksByKey(newValue);
|
||||||
@@ -63,15 +62,14 @@ watch(
|
|||||||
);
|
);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.procdefKey) {
|
if (props.procdef) {
|
||||||
parseTasksByKey(props.procdefKey);
|
parseTasksByKey(props.procdef);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
parseTasks(props.tasks);
|
parseTasks(props.tasks);
|
||||||
});
|
});
|
||||||
|
|
||||||
const parseTasksByKey = async (key: string) => {
|
const parseTasksByKey = async (procdef: any) => {
|
||||||
const procdef = await procdefApi.getByKey.request({ key });
|
|
||||||
parseTasks(procdef.tasks);
|
parseTasks(procdef.tasks);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,9 @@
|
|||||||
</slot>
|
</slot>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<slot :node="node" :data="data" name="suffix"></slot>
|
<span class="label-suffix">
|
||||||
|
<slot :node="node" :data="data" name="suffix"></slot>
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-tree>
|
</el-tree>
|
||||||
@@ -222,5 +224,13 @@ defineExpose({
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.label-suffix {
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
color: #c4c9c4;
|
||||||
|
font-size: 10px;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,51 +1,52 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w100" style="border: 1px solid var(--el-border-color)">
|
<div class="w100 tag-tree-check">
|
||||||
<el-input v-model="filterTag" clearable placeholder="输入关键字过滤" size="small" />
|
<el-input v-model="filterTag" @input="onFilterValChanged" clearable placeholder="输入关键字过滤" size="small" />
|
||||||
<el-scrollbar :style="{ height: props.height }">
|
<div class="mt3" style="border: 1px solid var(--el-border-color)">
|
||||||
<el-tree
|
<el-scrollbar :style="{ height: props.height }">
|
||||||
v-bind="$attrs"
|
<el-tree
|
||||||
ref="tagTreeRef"
|
v-bind="$attrs"
|
||||||
style="width: 100%"
|
ref="tagTreeRef"
|
||||||
:data="state.tags"
|
:data="state.tags"
|
||||||
:default-expanded-keys="checkedTags"
|
:default-expanded-keys="checkedTags"
|
||||||
:default-checked-keys="checkedTags"
|
:default-checked-keys="checkedTags"
|
||||||
multiple
|
multiple
|
||||||
:render-after-expand="true"
|
:render-after-expand="true"
|
||||||
show-checkbox
|
show-checkbox
|
||||||
check-strictly
|
check-strictly
|
||||||
:node-key="$props.nodeKey"
|
:node-key="$props.nodeKey"
|
||||||
:props="{
|
:props="{
|
||||||
value: $props.nodeKey,
|
value: $props.nodeKey,
|
||||||
label: 'codePath',
|
label: 'codePath',
|
||||||
children: 'children',
|
children: 'children',
|
||||||
disabled: 'disabled',
|
disabled: 'disabled',
|
||||||
}"
|
}"
|
||||||
@check="tagTreeNodeCheck"
|
@check="tagTreeNodeCheck"
|
||||||
:filter-node-method="filterNode"
|
:filter-node-method="filterNode"
|
||||||
>
|
>
|
||||||
<template #default="{ data }">
|
<template #default="{ data }">
|
||||||
<span class="custom-tree-node">
|
<span>
|
||||||
<SvgIcon
|
<SvgIcon
|
||||||
:name="EnumValue.getEnumByValue(TagResourceTypeEnum, data.type)?.extra.icon"
|
:name="EnumValue.getEnumByValue(TagResourceTypeEnum, data.type)?.extra.icon"
|
||||||
:color="EnumValue.getEnumByValue(TagResourceTypeEnum, data.type)?.extra.iconColor"
|
:color="EnumValue.getEnumByValue(TagResourceTypeEnum, data.type)?.extra.iconColor"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span class="font13 ml5">
|
<span class="font13 ml5">
|
||||||
{{ data.code }}
|
{{ data.code }}
|
||||||
<span style="color: #3c8dbc">【</span>
|
<span style="color: #3c8dbc">【</span>
|
||||||
{{ data.name }}
|
{{ data.name }}
|
||||||
<span style="color: #3c8dbc">】</span>
|
<span style="color: #3c8dbc">】</span>
|
||||||
<el-tag v-if="data.children !== null" size="small">{{ data.children.length }} </el-tag>
|
<el-tag v-if="data.children !== null" size="small">{{ data.children.length }} </el-tag>
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</template>
|
||||||
</template>
|
</el-tree>
|
||||||
</el-tree>
|
</el-scrollbar>
|
||||||
</el-scrollbar>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, reactive, onMounted, watch } from 'vue';
|
import { ref, reactive, onMounted } from 'vue';
|
||||||
import { tagApi } from '../tag/api';
|
import { tagApi } from '../tag/api';
|
||||||
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
||||||
import EnumValue from '@/common/Enum';
|
import EnumValue from '@/common/Enum';
|
||||||
@@ -56,7 +57,7 @@ const props = defineProps({
|
|||||||
default: 'calc(100vh - 330px)',
|
default: 'calc(100vh - 330px)',
|
||||||
},
|
},
|
||||||
tagType: {
|
tagType: {
|
||||||
type: Number,
|
type: [Number, Array<Number>],
|
||||||
default: TagResourceTypeEnum.Tag.value,
|
default: TagResourceTypeEnum.Tag.value,
|
||||||
},
|
},
|
||||||
nodeKey: {
|
nodeKey: {
|
||||||
@@ -81,7 +82,12 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
state.tags = await tagApi.getTagTrees.request({ type: props.tagType });
|
let tagType: any = props.tagType;
|
||||||
|
if (Array.isArray(props.tagType)) {
|
||||||
|
tagType = props.tagType.join(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
state.tags = await tagApi.getTagTrees.request({ type: tagType });
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const checkedNodes = tagTreeRef.value.getCheckedNodes();
|
const checkedNodes = tagTreeRef.value.getCheckedNodes();
|
||||||
@@ -93,10 +99,6 @@ const search = async () => {
|
|||||||
}, 200);
|
}, 200);
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(filterTag, (val) => {
|
|
||||||
tagTreeRef.value!.filter(val);
|
|
||||||
});
|
|
||||||
|
|
||||||
const filterNode = (value: string, data: any) => {
|
const filterNode = (value: string, data: any) => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return true;
|
return true;
|
||||||
@@ -104,6 +106,10 @@ const filterNode = (value: string, data: any) => {
|
|||||||
return data.codePath.toLowerCase().includes(value) || data.name.includes(value);
|
return data.codePath.toLowerCase().includes(value) || data.name.includes(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onFilterValChanged = (val: string) => {
|
||||||
|
tagTreeRef.value!.filter(val);
|
||||||
|
};
|
||||||
|
|
||||||
const tagTreeNodeCheck = (data: any) => {
|
const tagTreeNodeCheck = (data: any) => {
|
||||||
const node = tagTreeRef.value.getNode(data.codePath);
|
const node = tagTreeRef.value.getNode(data.codePath);
|
||||||
console.log('check node: ', node);
|
console.log('check node: ', node);
|
||||||
@@ -150,4 +156,12 @@ const disableParentNodes = (node: any, disable = true) => {
|
|||||||
disableParentNodes(node.parent, disable);
|
disableParentNodes(node.parent, disable);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped>
|
||||||
|
.tag-tree-check {
|
||||||
|
.el-tree {
|
||||||
|
min-width: 100%;
|
||||||
|
// 横向滚动生效
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -199,3 +199,16 @@ export function getTagTypeCodeByPath(codePath: string) {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function expandCodePath(codePath: string) {
|
||||||
|
const parts = codePath.split('/');
|
||||||
|
const result = [];
|
||||||
|
let currentPath = '';
|
||||||
|
|
||||||
|
for (let i = 0; i < parts.length - 1; i++) {
|
||||||
|
currentPath += parts[i] + '/';
|
||||||
|
result.push(currentPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,8 +62,6 @@
|
|||||||
<el-form-item prop="remark" label="备注">
|
<el-form-item prop="remark" label="备注">
|
||||||
<el-input v-model.trim="form.remark" auto-complete="off" type="textarea"></el-input>
|
<el-input v-model.trim="form.remark" auto-complete="off" type="textarea"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<procdef-select-form-item v-model="form.flowProcdefKey" />
|
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -80,9 +78,7 @@
|
|||||||
import { toRefs, reactive, watch, ref, watchEffect } from 'vue';
|
import { toRefs, reactive, watch, ref, watchEffect } from 'vue';
|
||||||
import { dbApi } from './api';
|
import { dbApi } from './api';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
// import TagTreeSelect from '../component/TagTreeSelect.vue';
|
|
||||||
import type { CheckboxValueType } from 'element-plus';
|
import type { CheckboxValueType } from 'element-plus';
|
||||||
import ProcdefSelectFormItem from '@/views/flow/components/ProcdefSelectFormItem.vue';
|
|
||||||
import { DbType } from '@/views/ops/db/dialect';
|
import { DbType } from '@/views/ops/db/dialect';
|
||||||
import { ResourceCodePattern } from '@/common/pattern';
|
import { ResourceCodePattern } from '@/common/pattern';
|
||||||
|
|
||||||
@@ -183,7 +179,6 @@ const state = reactive({
|
|||||||
remark: '',
|
remark: '',
|
||||||
instanceId: null as any,
|
instanceId: null as any,
|
||||||
authCertName: '',
|
authCertName: '',
|
||||||
flowProcdefKey: '',
|
|
||||||
},
|
},
|
||||||
instances: [] as any,
|
instances: [] as any,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -187,8 +187,6 @@
|
|||||||
<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="3" label="工单流程key">{{ infoDialog.data?.flowProcdefKey }}</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>
|
||||||
|
|
||||||
@@ -240,7 +238,6 @@ const columns = ref([
|
|||||||
TableColumn.new('host', 'ip:port').isSlot().setAddWidth(40),
|
TableColumn.new('host', 'ip:port').isSlot().setAddWidth(40),
|
||||||
TableColumn.new('authCertName', '授权凭证'),
|
TableColumn.new('authCertName', '授权凭证'),
|
||||||
TableColumn.new('database', '库').isSlot().setMinWidth(80),
|
TableColumn.new('database', '库').isSlot().setMinWidth(80),
|
||||||
TableColumn.new('flowProcdefKey', '关联流程'),
|
|
||||||
TableColumn.new('remark', '备注'),
|
TableColumn.new('remark', '备注'),
|
||||||
TableColumn.new('code', '编号'),
|
TableColumn.new('code', '编号'),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column prop="remark" label="备注" show-overflow-tooltip min-width="120"> </el-table-column>
|
<el-table-column prop="remark" label="备注" show-overflow-tooltip min-width="120"> </el-table-column>
|
||||||
<el-table-column prop="flowProcdefKey" label="关联流程" min-width="120" show-overflow-tooltip> </el-table-column>
|
|
||||||
<el-table-column prop="code" label="编号" show-overflow-tooltip min-width="120"> </el-table-column>
|
<el-table-column prop="code" label="编号" show-overflow-tooltip min-width="120"> </el-table-column>
|
||||||
<el-table-column min-wdith="120px">
|
<el-table-column min-wdith="120px">
|
||||||
<template #header>
|
<template #header>
|
||||||
|
|||||||
@@ -47,10 +47,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #suffix="{ data }">
|
<template #suffix="{ data }">
|
||||||
<span class="db-table-size" v-if="data.type.value == SqlExecNodeType.Table && data.params.size">{{ ` ${data.params.size}` }}</span>
|
<span v-if="data.type.value == SqlExecNodeType.Table && data.params.size">{{ ` ${data.params.size}` }}</span>
|
||||||
<span class="db-table-size" v-if="data.type.value == SqlExecNodeType.TableMenu && data.params.dbTableSize">{{
|
<span v-if="data.type.value == SqlExecNodeType.TableMenu && data.params.dbTableSize">{{ ` ${data.params.dbTableSize}` }}</span>
|
||||||
` ${data.params.dbTableSize}`
|
|
||||||
}}</span>
|
|
||||||
</template>
|
</template>
|
||||||
</tag-tree>
|
</tag-tree>
|
||||||
</Pane>
|
</Pane>
|
||||||
@@ -148,7 +146,7 @@
|
|||||||
:db-id="dt.params.id"
|
:db-id="dt.params.id"
|
||||||
:db="dt.params.db"
|
:db="dt.params.db"
|
||||||
:db-type="dt.params.type"
|
:db-type="dt.params.type"
|
||||||
:flow-procdef-key="dt.params.flowProcdefKey"
|
:flow-procdef="dt.params.flowProcdef"
|
||||||
:height="state.tablesOpHeight"
|
:height="state.tablesOpHeight"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
@@ -163,7 +161,7 @@
|
|||||||
:dbId="tableCreateDialog.dbId"
|
:dbId="tableCreateDialog.dbId"
|
||||||
:db="tableCreateDialog.db"
|
:db="tableCreateDialog.db"
|
||||||
:dbType="tableCreateDialog.dbType"
|
:dbType="tableCreateDialog.dbType"
|
||||||
:flow-procdef-key="tableCreateDialog.flowProcdefKey"
|
:flow-procdef="tableCreateDialog.flowProcdef"
|
||||||
:data="tableCreateDialog.data"
|
:data="tableCreateDialog.data"
|
||||||
v-model:visible="tableCreateDialog.visible"
|
v-model:visible="tableCreateDialog.visible"
|
||||||
@submit-sql="onSubmitEditTableSql"
|
@submit-sql="onSubmitEditTableSql"
|
||||||
@@ -190,6 +188,7 @@ import { useEventListener } from '@vueuse/core';
|
|||||||
import SqlExecBox from '@/views/ops/db/component/sqleditor/SqlExecBox';
|
import SqlExecBox from '@/views/ops/db/component/sqleditor/SqlExecBox';
|
||||||
import { useAutoOpenResource } from '@/store/autoOpenResource';
|
import { useAutoOpenResource } from '@/store/autoOpenResource';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { procdefApi } from '@/views/flow/api';
|
||||||
|
|
||||||
const DbTableOp = defineAsyncComponent(() => import('./component/table/DbTableOp.vue'));
|
const DbTableOp = defineAsyncComponent(() => import('./component/table/DbTableOp.vue'));
|
||||||
const DbSqlEditor = defineAsyncComponent(() => import('./component/sqleditor/DbSqlEditor.vue'));
|
const DbSqlEditor = defineAsyncComponent(() => import('./component/sqleditor/DbSqlEditor.vue'));
|
||||||
@@ -243,7 +242,7 @@ const nodeClickChangeDb = (nodeData: TagTreeNode) => {
|
|||||||
type: params.type,
|
type: params.type,
|
||||||
tagPath: params.tagPath,
|
tagPath: params.tagPath,
|
||||||
databases: params.dbs,
|
databases: params.dbs,
|
||||||
flowProcdefKey: params.flowProcdefKey,
|
flowProcdef: params.flowProcdef,
|
||||||
},
|
},
|
||||||
params.db
|
params.db
|
||||||
);
|
);
|
||||||
@@ -271,10 +270,11 @@ const NodeTypeTagPath = new NodeType(TagTreeNode.TagPath)
|
|||||||
.withContextMenuItems([ContextmenuItemRefresh]);
|
.withContextMenuItems([ContextmenuItemRefresh]);
|
||||||
|
|
||||||
// 数据库实例节点类型
|
// 数据库实例节点类型
|
||||||
const NodeTypeDbInst = new NodeType(SqlExecNodeType.DbInst).withLoadNodesFunc((parentNode: TagTreeNode) => {
|
const NodeTypeDbInst = new NodeType(SqlExecNodeType.DbInst).withLoadNodesFunc(async (parentNode: TagTreeNode) => {
|
||||||
const params = parentNode.params;
|
const params = parentNode.params;
|
||||||
const dbs = params.database.split(' ')?.sort();
|
const dbs = params.database.split(' ')?.sort();
|
||||||
|
|
||||||
|
const flowProcdef = await procdefApi.getByResource.request({ resourceType: TagResourceTypeEnum.DbName.value, resourceCode: params.code });
|
||||||
return dbs.map((x: any) => {
|
return dbs.map((x: any) => {
|
||||||
return new TagTreeNode(`${parentNode.key}.${x}`, x, NodeTypeDb)
|
return new TagTreeNode(`${parentNode.key}.${x}`, x, NodeTypeDb)
|
||||||
.withParams({
|
.withParams({
|
||||||
@@ -285,7 +285,7 @@ const NodeTypeDbInst = new NodeType(SqlExecNodeType.DbInst).withLoadNodesFunc((p
|
|||||||
host: `${params.host}:${params.port}`,
|
host: `${params.host}:${params.port}`,
|
||||||
dbs: dbs,
|
dbs: dbs,
|
||||||
db: x,
|
db: x,
|
||||||
flowProcdefKey: params.flowProcdefKey,
|
flowProcdef: flowProcdef,
|
||||||
})
|
})
|
||||||
.withIcon(DbIcon);
|
.withIcon(DbIcon);
|
||||||
});
|
});
|
||||||
@@ -346,7 +346,7 @@ const NodeTypeTableMenu = new NodeType(SqlExecNodeType.TableMenu)
|
|||||||
])
|
])
|
||||||
.withLoadNodesFunc(async (parentNode: TagTreeNode) => {
|
.withLoadNodesFunc(async (parentNode: TagTreeNode) => {
|
||||||
const params = parentNode.params;
|
const params = parentNode.params;
|
||||||
let { id, db, type, flowProcdefKey, schema } = params;
|
let { id, db, type, flowProcdef, schema } = params;
|
||||||
// 获取当前库的所有表信息
|
// 获取当前库的所有表信息
|
||||||
let tables = await DbInst.getInst(id).loadTables(db, state.reloadStatus);
|
let tables = await DbInst.getInst(id).loadTables(db, state.reloadStatus);
|
||||||
state.reloadStatus = false;
|
state.reloadStatus = false;
|
||||||
@@ -362,7 +362,7 @@ const NodeTypeTableMenu = new NodeType(SqlExecNodeType.TableMenu)
|
|||||||
db,
|
db,
|
||||||
type,
|
type,
|
||||||
schema,
|
schema,
|
||||||
flowProcdefKey: flowProcdefKey,
|
flowProcdef: flowProcdef,
|
||||||
key: key,
|
key: key,
|
||||||
parentKey: parentNode.key,
|
parentKey: parentNode.key,
|
||||||
tableName: x.tableName,
|
tableName: x.tableName,
|
||||||
@@ -448,7 +448,7 @@ const state = reactive({
|
|||||||
dbId: 0,
|
dbId: 0,
|
||||||
db: '',
|
db: '',
|
||||||
dbType: '',
|
dbType: '',
|
||||||
flowProcdefKey: '',
|
flowProcdef: null as any,
|
||||||
data: {},
|
data: {},
|
||||||
parentKey: '',
|
parentKey: '',
|
||||||
},
|
},
|
||||||
@@ -497,7 +497,7 @@ const autoOpenDb = (codePath: string) => {
|
|||||||
// 置空
|
// 置空
|
||||||
autoOpenResourceStore.setDbCodePath('');
|
autoOpenResourceStore.setDbCodePath('');
|
||||||
tagTreeRef.value.setCurrentKey(dbCode);
|
tagTreeRef.value.setCurrentKey(dbCode);
|
||||||
}, 600);
|
}, 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -669,6 +669,8 @@ const onTabChange = () => {
|
|||||||
// 注册sql提示
|
// 注册sql提示
|
||||||
registerDbCompletionItemProvider(nowTab.dbId, nowTab.db, nowTab.params.dbs, nowDbInst.value.type);
|
registerDbCompletionItemProvider(nowTab.dbId, nowTab.db, nowTab.params.dbs, nowDbInst.value.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tagTreeRef.value.setCurrentKey(nowTab?.treeNodeKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
const reloadSqls = (dbId: number, db: string) => {
|
const reloadSqls = (dbId: number, db: string) => {
|
||||||
@@ -700,7 +702,7 @@ const reloadNode = (nodeKey: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onEditTable = async (data: any) => {
|
const onEditTable = async (data: any) => {
|
||||||
let { db, id, tableName, tableComment, type, parentKey, key, flowProcdefKey } = data.params;
|
let { db, id, tableName, tableComment, type, parentKey, key, flowProcdef } = data.params;
|
||||||
// data.label就是表名
|
// data.label就是表名
|
||||||
if (tableName) {
|
if (tableName) {
|
||||||
state.tableCreateDialog.title = '修改表';
|
state.tableCreateDialog.title = '修改表';
|
||||||
@@ -719,12 +721,12 @@ const onEditTable = async (data: any) => {
|
|||||||
state.tableCreateDialog.dbId = id;
|
state.tableCreateDialog.dbId = id;
|
||||||
state.tableCreateDialog.db = db;
|
state.tableCreateDialog.db = db;
|
||||||
state.tableCreateDialog.dbType = type;
|
state.tableCreateDialog.dbType = type;
|
||||||
state.tableCreateDialog.flowProcdefKey = flowProcdefKey;
|
state.tableCreateDialog.flowProcdef = flowProcdef;
|
||||||
state.tableCreateDialog.visible = true;
|
state.tableCreateDialog.visible = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDeleteTable = async (data: any) => {
|
const onDeleteTable = async (data: any) => {
|
||||||
let { db, id, tableName, parentKey, flowProcdefKey, schema } = data.params;
|
let { db, id, tableName, parentKey, flowProcdef, schema } = data.params;
|
||||||
await ElMessageBox.confirm(`此操作是永久性且无法撤销,确定删除【${tableName}】? `, '提示', {
|
await ElMessageBox.confirm(`此操作是永久性且无法撤销,确定删除【${tableName}】? `, '提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
@@ -736,7 +738,7 @@ const onDeleteTable = async (data: any) => {
|
|||||||
let schemaStr = schema ? `${dialect.quoteIdentifier(schema)}.` : '';
|
let schemaStr = schema ? `${dialect.quoteIdentifier(schema)}.` : '';
|
||||||
|
|
||||||
dbApi.sqlExec.request({ id, db, sql: `drop table ${schemaStr + dialect.quoteIdentifier(tableName)}` }).then(() => {
|
dbApi.sqlExec.request({ id, db, sql: `drop table ${schemaStr + dialect.quoteIdentifier(tableName)}` }).then(() => {
|
||||||
if (flowProcdefKey) {
|
if (flowProcdef) {
|
||||||
ElMessage.success('工单提交成功');
|
ElMessage.success('工单提交成功');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -748,7 +750,7 @@ const onDeleteTable = async (data: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onRenameTable = async (data: any) => {
|
const onRenameTable = async (data: any) => {
|
||||||
let { db, id, tableName, parentKey, flowProcdefKey } = data.params;
|
let { db, id, tableName, parentKey, flowProcdef } = data.params;
|
||||||
let tableData = { db, oldTableName: tableName, tableName };
|
let tableData = { db, oldTableName: tableName, tableName };
|
||||||
|
|
||||||
let value = ref(tableName);
|
let value = ref(tableName);
|
||||||
@@ -771,7 +773,7 @@ const onRenameTable = async (data: any) => {
|
|||||||
dbId: id as any,
|
dbId: id as any,
|
||||||
db: db as any,
|
db: db as any,
|
||||||
dbType: nowDbInst.value.getDialect().getInfo().formatSqlDialect,
|
dbType: nowDbInst.value.getDialect().getInfo().formatSqlDialect,
|
||||||
flowProcdefKey: flowProcdefKey,
|
flowProcdef: flowProcdef,
|
||||||
runSuccessCallback: () => {
|
runSuccessCallback: () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
parentKey && reloadNode(parentKey);
|
parentKey && reloadNode(parentKey);
|
||||||
@@ -831,7 +833,7 @@ const getNowDbInfo = () => {
|
|||||||
name: di.name,
|
name: di.name,
|
||||||
type: di.type,
|
type: di.type,
|
||||||
host: di.host,
|
host: di.host,
|
||||||
flowProcdefKey: di.flowProcdefKey,
|
flowProcdef: di.flowProcdef,
|
||||||
dbName: state.db,
|
dbName: state.db,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -839,11 +841,6 @@ const getNowDbInfo = () => {
|
|||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.db-sql-exec {
|
.db-sql-exec {
|
||||||
.db-table-size {
|
|
||||||
color: #c4c9c4;
|
|
||||||
font-size: 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.db-op {
|
.db-op {
|
||||||
height: calc(100vh - 106px);
|
height: calc(100vh - 106px);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
<el-option
|
<el-option
|
||||||
v-for="item in state.targetColumnList"
|
v-for="item in state.targetColumnList"
|
||||||
:key="item.columnName"
|
:key="item.columnName"
|
||||||
:label="item.columnName + ` ${item.showDataType}` + (item.columnComment && ' - ' + item.columnComment)"
|
:label="item.columnName + ` ${item.columnType}` + (item.columnComment && ' - ' + item.columnComment)"
|
||||||
:value="item.columnName"
|
:value="item.columnName"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ const onRunSql = async (newTab = false) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 启用工单审批
|
// 启用工单审批
|
||||||
if (execRemark && getNowDbInst().flowProcdefKey) {
|
if (execRemark && getNowDbInst().flowProcdef) {
|
||||||
try {
|
try {
|
||||||
await getNowDbInst().runSql(props.dbName, sql, execRemark);
|
await getNowDbInst().runSql(props.dbName, sql, execRemark);
|
||||||
ElMessage.success('工单提交成功');
|
ElMessage.success('工单提交成功');
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export type SqlExecProps = {
|
|||||||
dbId: number;
|
dbId: number;
|
||||||
db: string;
|
db: string;
|
||||||
dbType?: string;
|
dbType?: string;
|
||||||
flowProcdefKey?: string;
|
flowProcdef?: any;
|
||||||
runSuccessCallback?: Function;
|
runSuccessCallback?: Function;
|
||||||
cancelCallback?: Function;
|
cancelCallback?: Function;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-dialog title="待执行SQL" v-model="dialogVisible" :show-close="false" width="600px">
|
<el-dialog title="待执行SQL" v-model="dialogVisible" :show-close="false" width="600px" :close-on-click-modal="false">
|
||||||
<monaco-editor height="300px" class="codesql" language="sql" v-model="sqlValue" />
|
<monaco-editor height="300px" class="codesql" language="sql" v-model="sqlValue" />
|
||||||
<el-input
|
<el-input
|
||||||
@keyup.enter="runSql"
|
@keyup.enter="runSql"
|
||||||
ref="remarkInputRef"
|
ref="remarkInputRef"
|
||||||
v-model="remark"
|
v-model="remark"
|
||||||
:placeholder="props.flowProcdefKey ? '执行备注(必填)' : '执行备注(选填)'"
|
:placeholder="props.flowProcdef ? '执行备注(必填)' : '执行备注(选填)'"
|
||||||
class="mt5"
|
class="mt5"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div v-if="props.flowProcdefKey">
|
<div v-if="props.flowProcdef">
|
||||||
<el-divider content-position="left">审批节点</el-divider>
|
<el-divider content-position="left">审批节点</el-divider>
|
||||||
<procdef-tasks :procdef-key="props.flowProcdefKey" />
|
<procdef-tasks :procdef="props.flowProcdef" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -59,7 +59,7 @@ onMounted(() => {
|
|||||||
*/
|
*/
|
||||||
const runSql = async () => {
|
const runSql = async () => {
|
||||||
// 存在流程审批,则备注为必填
|
// 存在流程审批,则备注为必填
|
||||||
if (!state.remark && props.flowProcdefKey) {
|
if (!state.remark && props.flowProcdef) {
|
||||||
ElMessage.error('请输入执行的备注信息');
|
ElMessage.error('请输入执行的备注信息');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ const runSql = async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 存在流程审批
|
// 存在流程审批
|
||||||
if (props.flowProcdefKey) {
|
if (props.flowProcdef) {
|
||||||
runSuccess = false;
|
runSuccess = false;
|
||||||
ElMessage.success('工单提交成功');
|
ElMessage.success('工单提交成功');
|
||||||
return;
|
return;
|
||||||
@@ -113,7 +113,7 @@ const cancel = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const open = () => {
|
const open = () => {
|
||||||
state.sqlValue = sqlFormatter(props.sql, { language: props.dbType || 'mysql' });
|
state.sqlValue = sqlFormatter(props.sql, { language: (props.dbType || 'mysql') as any });
|
||||||
state.dialogVisible = true;
|
state.dialogVisible = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
remarkInputRef.value?.focus();
|
remarkInputRef.value?.focus();
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="string-input-container w100" v-if="dataType == DataType.String">
|
<div class="string-input-container w100" v-if="dataType == DataType.String || dataType == DataType.Number">
|
||||||
<el-input
|
<el-input
|
||||||
v-if="dataType == DataType.String"
|
|
||||||
:ref="(el: any) => focus && el?.focus()"
|
:ref="(el: any) => focus && el?.focus()"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
@blur="handleBlur"
|
@blur="handleBlur"
|
||||||
@@ -13,18 +12,6 @@
|
|||||||
<SvgIcon v-if="showEditorIcon" @mousedown="openEditor" class="string-input-container-icon" name="FullScreen" :size="10" />
|
<SvgIcon v-if="showEditorIcon" @mousedown="openEditor" class="string-input-container-icon" name="FullScreen" :size="10" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-input
|
|
||||||
v-else-if="dataType == DataType.Number"
|
|
||||||
:ref="(el: any) => focus && el?.focus()"
|
|
||||||
:disabled="disabled"
|
|
||||||
@blur="handleBlur"
|
|
||||||
class="w100 mb4"
|
|
||||||
size="small"
|
|
||||||
v-model.number="itemValue"
|
|
||||||
:placeholder="placeholder"
|
|
||||||
type="number"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-else-if="dataType == DataType.Date"
|
v-else-if="dataType == DataType.Date"
|
||||||
:ref="(el: any) => focus && el?.focus()"
|
:ref="(el: any) => focus && el?.focus()"
|
||||||
@@ -75,7 +62,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref, Ref } from 'vue';
|
import { computed, ref, Ref } from 'vue';
|
||||||
import { ElInput } from 'element-plus';
|
import { ElInput, ElMessage } from 'element-plus';
|
||||||
import { DataType } from '../../dialect/index';
|
import { DataType } from '../../dialect/index';
|
||||||
import SvgIcon from '@/components/svgIcon/index.vue';
|
import SvgIcon from '@/components/svgIcon/index.vue';
|
||||||
import MonacoEditorDialog from '@/components/monaco/MonacoEditorDialog';
|
import MonacoEditorDialog from '@/components/monaco/MonacoEditorDialog';
|
||||||
@@ -130,6 +117,10 @@ const handleBlur = () => {
|
|||||||
if (editorOpening.value) {
|
if (editorOpening.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (props.dataType == DataType.Number && !/^-?\d*\.?\d+$/.test(itemValue.value)) {
|
||||||
|
ElMessage.error('输入内容与类型不匹配');
|
||||||
|
return;
|
||||||
|
}
|
||||||
emit('update:modelValue', itemValue.value);
|
emit('update:modelValue', itemValue.value);
|
||||||
emit('blur');
|
emit('blur');
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
<!-- 字段列的数据类型 -->
|
<!-- 字段列的数据类型 -->
|
||||||
<div class="column-type">
|
<div class="column-type">
|
||||||
<span v-if="column.dataTypeSubscript === 'icon-clock'">
|
<span v-if="column.dataTypeSubscript === 'icon-clock'">
|
||||||
<SvgIcon :size="10" name="Clock" style="cursor: unset" />
|
<SvgIcon :size="9" name="Clock" style="cursor: unset" />
|
||||||
</span>
|
</span>
|
||||||
<span class="font8" v-else>{{ column.dataTypeSubscript }}</span>
|
<span class="font8" v-else>{{ column.dataTypeSubscript }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -476,9 +476,9 @@ const setTableColumns = (columns: any) => {
|
|||||||
state.columns = columns.map((x: any) => {
|
state.columns = columns.map((x: any) => {
|
||||||
const columnName = x.columnName;
|
const columnName = x.columnName;
|
||||||
// 数据类型
|
// 数据类型
|
||||||
x.dataType = dbDialect.getDataType(x.dataType);
|
x.dataType = dbDialect.getDataType(x.columnType);
|
||||||
x.dataTypeSubscript = ColumnTypeSubscript[x.dataType];
|
x.dataTypeSubscript = ColumnTypeSubscript[x.dataType];
|
||||||
x.remark = `${x.showDataType} ${x.columnComment ? ' | ' + x.columnComment : ''}`;
|
x.remark = `${x.columnType} ${x.columnComment ? ' | ' + x.columnComment : ''}`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...x,
|
...x,
|
||||||
@@ -880,8 +880,8 @@ defineExpose({
|
|||||||
color: var(--el-color-info-light-3);
|
color: var(--el-color-info-light-3);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -5px;
|
top: -7px;
|
||||||
padding: 2px;
|
padding: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.column-right {
|
.column-right {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
:required="column.nullable != 'YES' && !column.isPrimaryKey && !column.isIdentity"
|
:required="column.nullable != 'YES' && !column.isPrimaryKey && !column.isIdentity"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
<span class="pointer" :title="`${column.showDataType} | ${column.columnComment}`">
|
<span class="pointer" :title="`${column.columnType} | ${column.columnComment}`">
|
||||||
{{ column.columnName }}
|
{{ column.columnName }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
<ColumnFormItem
|
<ColumnFormItem
|
||||||
v-model="modelValue[`${column.columnName}`]"
|
v-model="modelValue[`${column.columnName}`]"
|
||||||
:data-type="dbInst.getDialect().getDataType(column.dataType)"
|
:data-type="dbInst.getDialect().getDataType(column.dataType)"
|
||||||
:placeholder="`${column.showDataType} ${column.columnComment}`"
|
:placeholder="`${column.columnType} ${column.columnComment}`"
|
||||||
:column-name="column.columnName"
|
:column-name="column.columnName"
|
||||||
:disabled="column.isIdentity"
|
:disabled="column.isIdentity"
|
||||||
/>
|
/>
|
||||||
@@ -37,7 +37,6 @@ import { ref, watch, onMounted } from 'vue';
|
|||||||
import ColumnFormItem from './ColumnFormItem.vue';
|
import ColumnFormItem from './ColumnFormItem.vue';
|
||||||
import { DbInst } from '../../db';
|
import { DbInst } from '../../db';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { getDbDialect } from '@/views/ops/db/dialect';
|
|
||||||
|
|
||||||
export interface ColumnFormItemProps {
|
export interface ColumnFormItemProps {
|
||||||
dbInst: DbInst;
|
dbInst: DbInst;
|
||||||
|
|||||||
@@ -12,15 +12,29 @@
|
|||||||
width="auto"
|
width="auto"
|
||||||
title="表格字段配置"
|
title="表格字段配置"
|
||||||
trigger="click"
|
trigger="click"
|
||||||
|
@hide="triggerCheckedColumns"
|
||||||
>
|
>
|
||||||
<div v-for="(item, index) in columns" :key="index">
|
<div><el-input v-model="checkedShowColumns.searchKey" size="small" placeholder="输入列名或备注过滤" /></div>
|
||||||
|
<div>
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
v-model="item.show"
|
v-model="checkedShowColumns.checkedAllColumn"
|
||||||
:label="`${!item.columnComment ? item.columnName : item.columnName + ' [' + item.columnComment + ']'}`"
|
:indeterminate="checkedShowColumns.isIndeterminate"
|
||||||
:true-value="true"
|
@change="handleCheckAllColumnChange"
|
||||||
:false-value="false"
|
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
>
|
||||||
|
选择所有
|
||||||
|
</el-checkbox>
|
||||||
|
|
||||||
|
<el-checkbox-group v-model="checkedShowColumns.columnNames" @change="handleCheckedColumnChange">
|
||||||
|
<div v-for="(item, index) in filterCheckedColumns" :key="index">
|
||||||
|
<el-checkbox
|
||||||
|
:key="index"
|
||||||
|
:label="`${!item.columnComment ? item.columnName : item.columnName + ' [' + item.columnComment + ']'}`"
|
||||||
|
:value="item.columnName"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-checkbox-group>
|
||||||
</div>
|
</div>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-link icon="Operation" size="small" :underline="false"></el-link>
|
<el-link icon="Operation" size="small" :underline="false"></el-link>
|
||||||
@@ -98,7 +112,7 @@
|
|||||||
<el-divider direction="vertical" />
|
<el-divider direction="vertical" />
|
||||||
|
|
||||||
<span style="color: var(--el-color-info-light-3)">
|
<span style="color: var(--el-color-info-light-3)">
|
||||||
{{ item.showDataType }}
|
{{ item.columnType }}
|
||||||
|
|
||||||
<template v-if="item.columnComment">
|
<template v-if="item.columnComment">
|
||||||
<el-divider direction="vertical" />
|
<el-divider direction="vertical" />
|
||||||
@@ -329,9 +343,17 @@ const state = reactive({
|
|||||||
tableHeight: '600px',
|
tableHeight: '600px',
|
||||||
hasUpdatedFileds: false,
|
hasUpdatedFileds: false,
|
||||||
dbDialect: {} as DbDialect,
|
dbDialect: {} as DbDialect,
|
||||||
|
|
||||||
|
checkedShowColumns: {
|
||||||
|
searchKey: '',
|
||||||
|
checkedAllColumn: true,
|
||||||
|
isIndeterminate: false,
|
||||||
|
columnNames: [] as any,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { datas, condition, loading, columns, pageNum, pageSize, pageSizes, sql, hasUpdatedFileds, conditionDialog, addDataDialog } = toRefs(state);
|
const { datas, condition, loading, columns, checkedShowColumns, pageNum, pageSize, pageSizes, sql, hasUpdatedFileds, conditionDialog, addDataDialog } =
|
||||||
|
toRefs(state);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.tableHeight,
|
() => props.tableHeight,
|
||||||
@@ -351,6 +373,8 @@ onMounted(async () => {
|
|||||||
|
|
||||||
state.dbDialect = getNowDbInst().getDialect();
|
state.dbDialect = getNowDbInst().getDialect();
|
||||||
useEventListener('click', handlerWindowClick);
|
useEventListener('click', handlerWindowClick);
|
||||||
|
|
||||||
|
state.checkedShowColumns.columnNames = state.columns.map((item: any) => item.columnName);
|
||||||
});
|
});
|
||||||
|
|
||||||
const handlerWindowClick = () => {
|
const handlerWindowClick = () => {
|
||||||
@@ -414,6 +438,7 @@ const handleSetPageNum = async () => {
|
|||||||
state.pageNum = state.setPageNum;
|
state.pageNum = state.setPageNum;
|
||||||
await selectData();
|
await selectData();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCount = async () => {
|
const handleCount = async () => {
|
||||||
state.counting = true;
|
state.counting = true;
|
||||||
|
|
||||||
@@ -431,6 +456,24 @@ const handleCount = async () => {
|
|||||||
state.counting = false;
|
state.counting = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCheckAllColumnChange = (val: boolean) => {
|
||||||
|
state.checkedShowColumns.columnNames = val ? state.columns.map((x: any) => x.columnName) : [];
|
||||||
|
state.checkedShowColumns.isIndeterminate = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCheckedColumnChange = (value: string[]) => {
|
||||||
|
const checkedCount = value.length;
|
||||||
|
state.checkedShowColumns.checkedAllColumn = checkedCount === state.columns.length;
|
||||||
|
state.checkedShowColumns.isIndeterminate = checkedCount > 0 && checkedCount < state.columns.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
const triggerCheckedColumns = () => {
|
||||||
|
const checkedColumnNames = state.checkedShowColumns.columnNames;
|
||||||
|
for (let column of state.columns) {
|
||||||
|
column.show = checkedColumnNames.includes(column.columnName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 完整的条件,每次选中后会重置条件框内容,故需要这个变量在获取建议时将文本框内容保存
|
// 完整的条件,每次选中后会重置条件框内容,故需要这个变量在获取建议时将文本框内容保存
|
||||||
let completeCond = '';
|
let completeCond = '';
|
||||||
// 是否存在列建议
|
// 是否存在列建议
|
||||||
@@ -490,16 +533,23 @@ const chooseCondColumnName = () => {
|
|||||||
* 过滤条件列名
|
* 过滤条件列名
|
||||||
*/
|
*/
|
||||||
const filterCondColumns = computed(() => {
|
const filterCondColumns = computed(() => {
|
||||||
|
return filterColumns(state.columnNameSearch);
|
||||||
|
});
|
||||||
|
|
||||||
|
const filterCheckedColumns = computed(() => {
|
||||||
|
return filterColumns(state.checkedShowColumns.searchKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
const filterColumns = (searchKey: string) => {
|
||||||
const columns = state.columns;
|
const columns = state.columns;
|
||||||
let columnNameSearch = state.columnNameSearch;
|
if (!searchKey) {
|
||||||
if (!columnNameSearch) {
|
|
||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
columnNameSearch = columnNameSearch.toLowerCase();
|
searchKey = searchKey.toLowerCase();
|
||||||
return columns.filter((data: any) => {
|
return columns.filter((data: any) => {
|
||||||
return data.columnName.toLowerCase().includes(columnNameSearch) || data.columnComment.toLowerCase().includes(columnNameSearch);
|
return data.columnName.toLowerCase().includes(searchKey) || data.columnComment.toLowerCase().includes(searchKey);
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 条件查询,点击列信息后显示输入对应的值
|
* 条件查询,点击列信息后显示输入对应的值
|
||||||
@@ -507,7 +557,7 @@ const filterCondColumns = computed(() => {
|
|||||||
const onConditionRowClick = (event: any) => {
|
const onConditionRowClick = (event: any) => {
|
||||||
const row = event[0];
|
const row = event[0];
|
||||||
state.conditionDialog.title = `请输入 [${row.columnName}] 的值`;
|
state.conditionDialog.title = `请输入 [${row.columnName}] 的值`;
|
||||||
state.conditionDialog.placeholder = `${row.showDataType} ${row.columnComment}`;
|
state.conditionDialog.placeholder = `${row.columnType} ${row.columnComment}`;
|
||||||
state.conditionDialog.columnRow = row;
|
state.conditionDialog.columnRow = row;
|
||||||
state.conditionDialog.visible = true;
|
state.conditionDialog.visible = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@@ -152,8 +152,8 @@ const props = defineProps({
|
|||||||
dbType: {
|
dbType: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
flowProcdefKey: {
|
flowProcdef: {
|
||||||
type: String,
|
type: Object,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -335,7 +335,7 @@ const submit = async () => {
|
|||||||
dbId: props.dbId as any,
|
dbId: props.dbId as any,
|
||||||
db: props.db as any,
|
db: props.db as any,
|
||||||
dbType: dbDialect.getInfo().formatSqlDialect,
|
dbType: dbDialect.getInfo().formatSqlDialect,
|
||||||
flowProcdefKey: props.flowProcdefKey,
|
flowProcdef: props.flowProcdef,
|
||||||
runSuccessCallback: () => {
|
runSuccessCallback: () => {
|
||||||
emit('submit-sql', { tableName: state.tableData.tableName });
|
emit('submit-sql', { tableName: state.tableData.tableName });
|
||||||
// cancel();
|
// cancel();
|
||||||
|
|||||||
@@ -82,7 +82,7 @@
|
|||||||
<el-dialog width="40%" :title="`${chooseTableName} 字段信息`" v-model="columnDialog.visible">
|
<el-dialog width="40%" :title="`${chooseTableName} 字段信息`" v-model="columnDialog.visible">
|
||||||
<el-table border stripe :data="columnDialog.columns" size="small">
|
<el-table border stripe :data="columnDialog.columns" size="small">
|
||||||
<el-table-column prop="columnName" label="名称" show-overflow-tooltip> </el-table-column>
|
<el-table-column prop="columnName" label="名称" show-overflow-tooltip> </el-table-column>
|
||||||
<el-table-column width="120" prop="showDataType" label="类型" show-overflow-tooltip> </el-table-column>
|
<el-table-column width="120" prop="columnType" label="类型" show-overflow-tooltip> </el-table-column>
|
||||||
<el-table-column width="80" prop="nullable" label="是否可为空" show-overflow-tooltip> </el-table-column>
|
<el-table-column width="80" prop="nullable" label="是否可为空" show-overflow-tooltip> </el-table-column>
|
||||||
<el-table-column prop="columnComment" label="备注" show-overflow-tooltip> </el-table-column>
|
<el-table-column prop="columnComment" label="备注" show-overflow-tooltip> </el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
:dbId="dbId"
|
:dbId="dbId"
|
||||||
:db="db"
|
:db="db"
|
||||||
:dbType="dbType"
|
:dbType="dbType"
|
||||||
:flow-procdef-key="props.flowProcdefKey"
|
:flow-procdef="props.flowProcdef"
|
||||||
:data="tableCreateDialog.data"
|
:data="tableCreateDialog.data"
|
||||||
v-model:visible="tableCreateDialog.visible"
|
v-model:visible="tableCreateDialog.visible"
|
||||||
@submit-sql="onSubmitSql"
|
@submit-sql="onSubmitSql"
|
||||||
@@ -150,8 +150,8 @@ const props = defineProps({
|
|||||||
type: [String],
|
type: [String],
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
flowProcdefKey: {
|
flowProcdef: {
|
||||||
type: [String],
|
type: [Object],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -327,7 +327,7 @@ const dropTable = async (row: any) => {
|
|||||||
sql: `DROP TABLE ${tableName}`,
|
sql: `DROP TABLE ${tableName}`,
|
||||||
dbId: props.dbId as any,
|
dbId: props.dbId as any,
|
||||||
db: props.db as any,
|
db: props.db as any,
|
||||||
flowProcdefKey: props.flowProcdefKey,
|
flowProcdef: props.flowProcdef,
|
||||||
runSuccessCallback: async () => {
|
runSuccessCallback: async () => {
|
||||||
await getTables();
|
await getTables();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ export class DbInst {
|
|||||||
type: string;
|
type: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 流程定义key,若存在则需要审批执行
|
* 流程定义,若存在则需要审批执行
|
||||||
*/
|
*/
|
||||||
flowProcdefKey: string;
|
flowProcdef: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dbName -> db
|
* dbName -> db
|
||||||
@@ -352,6 +352,7 @@ export class DbInst {
|
|||||||
* 弹框提示是否执行sql
|
* 弹框提示是否执行sql
|
||||||
*/
|
*/
|
||||||
promptExeSql = (db: string, sql: string, cancelFunc: any = null, successFunc: any = null) => {
|
promptExeSql = (db: string, sql: string, cancelFunc: any = null, successFunc: any = null) => {
|
||||||
|
console.log(this);
|
||||||
SqlExecBox({
|
SqlExecBox({
|
||||||
sql,
|
sql,
|
||||||
dbId: this.id,
|
dbId: this.id,
|
||||||
@@ -359,7 +360,7 @@ export class DbInst {
|
|||||||
dbType: this.getDialect().getInfo().formatSqlDialect,
|
dbType: this.getDialect().getInfo().formatSqlDialect,
|
||||||
runSuccessCallback: successFunc,
|
runSuccessCallback: successFunc,
|
||||||
cancelCallback: cancelFunc,
|
cancelCallback: cancelFunc,
|
||||||
flowProcdefKey: this.flowProcdefKey,
|
flowProcdef: this.flowProcdef,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -383,6 +384,11 @@ export class DbInst {
|
|||||||
}
|
}
|
||||||
let dbInst = dbInstCache.get(inst.id);
|
let dbInst = dbInstCache.get(inst.id);
|
||||||
if (dbInst) {
|
if (dbInst) {
|
||||||
|
// 更新可能更改的流程定义
|
||||||
|
if (inst.flowProcdef !== undefined) {
|
||||||
|
dbInst.flowProcdef = inst.flowProcdef;
|
||||||
|
dbInstCache.set(dbInst.id, dbInst);
|
||||||
|
}
|
||||||
return dbInst;
|
return dbInst;
|
||||||
}
|
}
|
||||||
console.info(`new dbInst: ${inst.id}, tagPath: ${inst.tagPath}`);
|
console.info(`new dbInst: ${inst.id}, tagPath: ${inst.tagPath}`);
|
||||||
@@ -393,7 +399,7 @@ export class DbInst {
|
|||||||
dbInst.name = inst.name;
|
dbInst.name = inst.name;
|
||||||
dbInst.type = inst.type;
|
dbInst.type = inst.type;
|
||||||
dbInst.databases = inst.databases;
|
dbInst.databases = inst.databases;
|
||||||
dbInst.flowProcdefKey = inst.flowProcdefKey;
|
dbInst.flowProcdef = inst.flowProcdef;
|
||||||
|
|
||||||
dbInstCache.set(dbInst.id, dbInst);
|
dbInstCache.set(dbInst.id, dbInst);
|
||||||
return dbInst;
|
return dbInst;
|
||||||
@@ -477,17 +483,17 @@ export class DbInst {
|
|||||||
}
|
}
|
||||||
for (let col of columns) {
|
for (let col of columns) {
|
||||||
if (col.charMaxLength > 0) {
|
if (col.charMaxLength > 0) {
|
||||||
col.showDataType = `${col.dataType}(${col.charMaxLength})`;
|
col.columnType = `${col.dataType}(${col.charMaxLength})`;
|
||||||
col.showLength = col.charMaxLength;
|
col.showLength = col.charMaxLength;
|
||||||
col.showScale = null;
|
col.showScale = null;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (col.numPrecision > 0) {
|
if (col.numPrecision > 0) {
|
||||||
if (col.numScale > 0) {
|
if (col.numScale > 0) {
|
||||||
col.showDataType = `${col.dataType}(${col.numPrecision},${col.numScale})`;
|
col.columnType = `${col.dataType}(${col.numPrecision},${col.numScale})`;
|
||||||
col.showScale = col.numScale;
|
col.showScale = col.numScale;
|
||||||
} else {
|
} else {
|
||||||
col.showDataType = `${col.dataType}(${col.numPrecision})`;
|
col.columnType = `${col.dataType}(${col.numPrecision})`;
|
||||||
col.showScale = null;
|
col.showScale = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,7 +501,7 @@ export class DbInst {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
col.showDataType = col.dataType;
|
col.columnType = col.dataType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #suffix="{ data }">
|
<template #suffix="{ data }">
|
||||||
<span style="color: #c4c9c4; font-size: 9px" v-if="data.type.value == MachineNodeType.AuthCert">{{
|
<span v-if="data.type.value == MachineNodeType.AuthCert">{{
|
||||||
` ${data.params.selectAuthCert.username}@${data.params.ip}:${data.params.port}`
|
` ${data.params.selectAuthCert.username}@${data.params.ip}:${data.params.port}`
|
||||||
}}</span>
|
}}</span>
|
||||||
</template>
|
</template>
|
||||||
@@ -368,7 +368,7 @@ const autoOpenTerminal = (codePath: string) => {
|
|||||||
|
|
||||||
const acNode = tagTreeRef.value.getNode(authCertName);
|
const acNode = tagTreeRef.value.getNode(authCertName);
|
||||||
openTerminal(acNode.data.params);
|
openTerminal(acNode.data.params);
|
||||||
}, 600);
|
}, 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
const openTerminal = (machine: any, ex?: boolean) => {
|
const openTerminal = (machine: any, ex?: boolean) => {
|
||||||
@@ -402,14 +402,14 @@ const openTerminal = (machine: any, ex?: boolean) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let { name, username } = machine;
|
let { name } = machine;
|
||||||
const labelName = `${machine.selectAuthCert.username}@${name}`;
|
const labelName = `${machine.selectAuthCert.username}@${name}`;
|
||||||
|
|
||||||
// 同一个机器的终端打开多次,key后添加下划线和数字区分
|
// 同一个机器的终端打开多次,key后添加下划线和数字区分
|
||||||
openIds[ac] = openIds[ac] ? ++openIds[ac] : 1;
|
openIds[ac] = openIds[ac] ? ++openIds[ac] : 1;
|
||||||
let sameIndex = openIds[ac];
|
let sameIndex = openIds[ac];
|
||||||
|
|
||||||
let key = `${ac}_${username}_${sameIndex}`;
|
let key = `${ac}_${sameIndex}`;
|
||||||
// 只保留name的15个字,超出部分只保留前后10个字符,中间用省略号代替
|
// 只保留name的15个字,超出部分只保留前后10个字符,中间用省略号代替
|
||||||
const label = labelName.length > 15 ? labelName.slice(0, 10) + '...' + labelName.slice(-10) : labelName;
|
const label = labelName.length > 15 ? labelName.slice(0, 10) + '...' + labelName.slice(-10) : labelName;
|
||||||
|
|
||||||
@@ -537,6 +537,9 @@ const onResizeTagTree = () => {
|
|||||||
|
|
||||||
const onTabChange = () => {
|
const onTabChange = () => {
|
||||||
fitTerminal();
|
fitTerminal();
|
||||||
|
|
||||||
|
const nowTab = state.tabs.get(state.activeTermName);
|
||||||
|
tagTreeRef.value.setCurrentKey(nowTab?.authCert);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fitTerminal = () => {
|
const fitTerminal = () => {
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mock-data-dialog">
|
<div class="mock-data-dialog">
|
||||||
<el-dialog
|
<el-drawer
|
||||||
:title="title"
|
:title="title"
|
||||||
v-model="dialogVisible"
|
v-model="dialogVisible"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
:before-close="cancel"
|
:before-close="cancel"
|
||||||
:show-close="true"
|
:show-close="true"
|
||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
width="900px"
|
size="40%"
|
||||||
>
|
>
|
||||||
|
<template #header>
|
||||||
|
<DrawerHeader :header="title" :back="cancel" />
|
||||||
|
</template>
|
||||||
|
|
||||||
<el-form :model="form" ref="formRef" :rules="rules" label-width="auto">
|
<el-form :model="form" ref="formRef" :rules="rules" label-width="auto">
|
||||||
<el-form-item prop="name" label="名称">
|
<el-form-item prop="name" label="名称">
|
||||||
<el-input v-model="form.name" placeholder="请输入名称"></el-input>
|
<el-input v-model="form.name" placeholder="请输入名称"></el-input>
|
||||||
@@ -34,19 +38,13 @@
|
|||||||
<el-input v-model="form.remark" placeholder="请输入备注"></el-input>
|
<el-input v-model="form.remark" placeholder="请输入备注"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="machineIds" label="关联机器">
|
|
||||||
<el-select multiple v-model="form.machineIds" filterable placeholder="请选关联机器" style="width: 100%">
|
|
||||||
<el-option v-for="ac in state.machines" :key="ac.id" :value="ac.id" :label="ac.ip">
|
|
||||||
{{ ac.ip }}
|
|
||||||
<el-divider direction="vertical" border-style="dashed" />
|
|
||||||
{{ ac.tagPath }}{{ ac.name }}
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item prop="script" label="执行脚本" required>
|
<el-form-item prop="script" label="执行脚本" required>
|
||||||
<monaco-editor style="width: 100%" v-model="form.script" language="shell" height="300px"
|
<monaco-editor style="width: 100%" v-model="form.script" language="shell" height="200px"
|
||||||
/></el-form-item>
|
/></el-form-item>
|
||||||
|
|
||||||
|
<el-form-item ref="tagSelectRef" prop="codePaths" label="关联机器">
|
||||||
|
<tag-tree-check height="200px" :tag-type="TagResourceTypeEnum.Machine.value" v-model="form.codePaths" />
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -55,7 +53,7 @@
|
|||||||
<el-button v-auth="'machine:script:save'" type="primary" :loading="btnLoading" @click="btnOk" :disabled="submitDisabled">保 存</el-button>
|
<el-button v-auth="'machine:script:save'" type="primary" :loading="btnLoading" @click="btnOk" :disabled="submitDisabled">保 存</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -67,6 +65,9 @@ import { CronJobStatusEnum, CronJobSaveExecResTypeEnum } from '../enums';
|
|||||||
import { notEmpty } from '@/common/assert';
|
import { notEmpty } from '@/common/assert';
|
||||||
import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
|
import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
|
||||||
import CrontabInput from '@/components/crontab/CrontabInput.vue';
|
import CrontabInput from '@/components/crontab/CrontabInput.vue';
|
||||||
|
import DrawerHeader from '@/components/drawer-header/DrawerHeader.vue';
|
||||||
|
import TagTreeCheck from '../../component/TagTreeCheck.vue';
|
||||||
|
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
@@ -130,11 +131,11 @@ const state = reactive({
|
|||||||
id: null,
|
id: null,
|
||||||
name: '',
|
name: '',
|
||||||
cron: '',
|
cron: '',
|
||||||
machineIds: [],
|
|
||||||
remark: '',
|
remark: '',
|
||||||
script: '',
|
script: '',
|
||||||
status: 1,
|
status: 1,
|
||||||
saveExecResType: -1,
|
saveExecResType: -1,
|
||||||
|
codePaths: [],
|
||||||
},
|
},
|
||||||
machines: [] as any,
|
machines: [] as any,
|
||||||
btnLoading: false,
|
btnLoading: false,
|
||||||
@@ -154,7 +155,7 @@ watch(props, async (newValue: any) => {
|
|||||||
}
|
}
|
||||||
if (newValue.data) {
|
if (newValue.data) {
|
||||||
state.form = { ...newValue.data };
|
state.form = { ...newValue.data };
|
||||||
state.form.machineIds = await cronJobApi.relateMachineIds.request({ cronJobId: state.form.id });
|
state.form.codePaths = newValue.data.tags?.map((tag: any) => tag.codePath);
|
||||||
} else {
|
} else {
|
||||||
state.form = { script: '', status: 1 } as any;
|
state.form = { script: '', status: 1 } as any;
|
||||||
state.chooseMachines = [];
|
state.chooseMachines = [];
|
||||||
|
|||||||
@@ -19,6 +19,10 @@
|
|||||||
<el-tag v-else type="danger" effect="plain">未运行</el-tag>
|
<el-tag v-else type="danger" effect="plain">未运行</el-tag>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #codePaths="{ data }">
|
||||||
|
<TagCodePath :path="data.tags?.map((tag: any) => tag.codePath)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #action="{ data }">
|
<template #action="{ data }">
|
||||||
<el-button :disabled="data.status == CronJobStatusEnum.Disable.value" v-auth="perms.saveCronJob" type="primary" @click="runCronJob(data)" link
|
<el-button :disabled="data.status == CronJobStatusEnum.Disable.value" v-auth="perms.saveCronJob" type="primary" @click="runCronJob(data)" link
|
||||||
>执行</el-button
|
>执行</el-button
|
||||||
@@ -41,6 +45,7 @@ import PageTable from '@/components/pagetable/PageTable.vue';
|
|||||||
import { TableColumn } from '@/components/pagetable';
|
import { TableColumn } from '@/components/pagetable';
|
||||||
import { CronJobStatusEnum, CronJobSaveExecResTypeEnum } from '../enums';
|
import { CronJobStatusEnum, CronJobSaveExecResTypeEnum } from '../enums';
|
||||||
import { SearchItem } from '@/components/SearchForm';
|
import { SearchItem } from '@/components/SearchForm';
|
||||||
|
import TagCodePath from '../../component/TagCodePath.vue';
|
||||||
|
|
||||||
const CronJobEdit = defineAsyncComponent(() => import('./CronJobEdit.vue'));
|
const CronJobEdit = defineAsyncComponent(() => import('./CronJobEdit.vue'));
|
||||||
const CronJobExecList = defineAsyncComponent(() => import('./CronJobExecList.vue'));
|
const CronJobExecList = defineAsyncComponent(() => import('./CronJobExecList.vue'));
|
||||||
@@ -61,6 +66,7 @@ const columns = ref([
|
|||||||
TableColumn.new('running', '运行状态').isSlot(),
|
TableColumn.new('running', '运行状态').isSlot(),
|
||||||
TableColumn.new('saveExecResType', '记录类型').typeTag(CronJobSaveExecResTypeEnum),
|
TableColumn.new('saveExecResType', '记录类型').typeTag(CronJobSaveExecResTypeEnum),
|
||||||
TableColumn.new('remark', '备注'),
|
TableColumn.new('remark', '备注'),
|
||||||
|
TableColumn.new('codePaths', '关联机器').isSlot().setMinWidth('250px'),
|
||||||
TableColumn.new('action', '操作').isSlot().setMinWidth(180).fixedRight().alignCenter(),
|
TableColumn.new('action', '操作').isSlot().setMinWidth(180).fixedRight().alignCenter(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="codePaths" label="关联机器" min-width="220px" show-overflow-tooltip>
|
<el-table-column prop="codePaths" label="关联机器" min-width="250px" show-overflow-tooltip>
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<TagCodePath :path="scope.row.tags.map((tag: any) => tag.codePath)" />
|
<TagCodePath :path="scope.row.tags.map((tag: any) => tag.codePath)" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -36,13 +36,8 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #label="{ data }">
|
<template #suffix="{ data }">
|
||||||
<span v-if="data.type.value == MongoNodeType.Dbs">
|
<span v-if="data.type.value == MongoNodeType.Dbs">{{ formatByteSize(data.params.size) }}</span>
|
||||||
{{ data.params.database }}
|
|
||||||
<span style="color: #8492a6; font-size: 13px"> [{{ formatByteSize(data.params.size) }}] </span>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span v-else>{{ data.label }}</span>
|
|
||||||
</template>
|
</template>
|
||||||
</tag-tree>
|
</tag-tree>
|
||||||
</Pane>
|
</Pane>
|
||||||
|
|||||||
@@ -35,6 +35,10 @@
|
|||||||
|
|
||||||
<SvgIcon v-if="data.type.value == RedisNodeType.Db" name="Coin" color="#67c23a" />
|
<SvgIcon v-if="data.type.value == RedisNodeType.Db" name="Coin" color="#67c23a" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #suffix="{ data }">
|
||||||
|
<span v-if="data.type.value == RedisNodeType.Db">{{ data.params.keys }}</span>
|
||||||
|
</template>
|
||||||
</tag-tree>
|
</tag-tree>
|
||||||
</Pane>
|
</Pane>
|
||||||
|
|
||||||
@@ -197,6 +201,7 @@ import { Splitpanes, Pane } from 'splitpanes';
|
|||||||
import { RedisInst } from './redis';
|
import { RedisInst } from './redis';
|
||||||
import { useAutoOpenResource } from '@/store/autoOpenResource';
|
import { useAutoOpenResource } from '@/store/autoOpenResource';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { procdefApi } from '@/views/flow/api';
|
||||||
|
|
||||||
const KeyDetail = defineAsyncComponent(() => import('./KeyDetail.vue'));
|
const KeyDetail = defineAsyncComponent(() => import('./KeyDetail.vue'));
|
||||||
|
|
||||||
@@ -244,11 +249,13 @@ const NodeTypeTagPath = new NodeType(TagTreeNode.TagPath).withLoadNodesFunc(asyn
|
|||||||
// redis实例节点类型
|
// redis实例节点类型
|
||||||
const NodeTypeRedis = new NodeType(RedisNodeType.Redis).withLoadNodesFunc(async (parentNode: TagTreeNode) => {
|
const NodeTypeRedis = new NodeType(RedisNodeType.Redis).withLoadNodesFunc(async (parentNode: TagTreeNode) => {
|
||||||
const redisInfo = parentNode.params;
|
const redisInfo = parentNode.params;
|
||||||
|
const flowProcdef = await procdefApi.getByResource.request({ resourceType: TagResourceTypeEnum.Redis.value, resourceCode: redisInfo.code });
|
||||||
|
|
||||||
let dbs: TagTreeNode[] = redisInfo.db.split(',').map((x: string) => {
|
let dbs: TagTreeNode[] = redisInfo.db.split(',').map((x: string) => {
|
||||||
return new TagTreeNode(x, `db${x}`, NodeTypeDb).withIsLeaf(true).withParams({
|
return new TagTreeNode(x, `db${x}`, NodeTypeDb).withIsLeaf(true).withParams({
|
||||||
id: redisInfo.id,
|
id: redisInfo.id,
|
||||||
db: x,
|
db: x,
|
||||||
flowProcdefKey: redisInfo.flowProcdefKey,
|
flowProcdef: flowProcdef,
|
||||||
name: `db${x}`,
|
name: `db${x}`,
|
||||||
keys: 0,
|
keys: 0,
|
||||||
});
|
});
|
||||||
@@ -268,7 +275,7 @@ const NodeTypeRedis = new NodeType(RedisNodeType.Redis).withLoadNodesFunc(async
|
|||||||
}
|
}
|
||||||
// 替换label
|
// 替换label
|
||||||
dbs.forEach((e: any) => {
|
dbs.forEach((e: any) => {
|
||||||
e.label = `${e.params.name} [${e.params.keys}]`;
|
e.label = `${e.params.name}`;
|
||||||
});
|
});
|
||||||
return dbs;
|
return dbs;
|
||||||
});
|
});
|
||||||
@@ -281,7 +288,7 @@ const NodeTypeDb = new NodeType(RedisNodeType.Db).withNodeClickFunc((nodeData: T
|
|||||||
|
|
||||||
redisInst.value.id = nodeData.params.id;
|
redisInst.value.id = nodeData.params.id;
|
||||||
redisInst.value.db = Number.parseInt(nodeData.params.db);
|
redisInst.value.db = Number.parseInt(nodeData.params.db);
|
||||||
redisInst.value.flowProcdefKey = nodeData.params.flowProcdefKey;
|
redisInst.value.flowProcdef = nodeData.params.flowProcdef;
|
||||||
|
|
||||||
scan();
|
scan();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -84,8 +84,6 @@
|
|||||||
<el-form-item prop="remark" label="备注">
|
<el-form-item prop="remark" label="备注">
|
||||||
<el-input v-model.trim="form.remark" auto-complete="off" type="textarea"></el-input>
|
<el-input v-model.trim="form.remark" auto-complete="off" type="textarea"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<procdef-select-form-item v-model="form.flowProcdefKey" />
|
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="其他配置" name="other">
|
<el-tab-pane label="其他配置" name="other">
|
||||||
@@ -113,7 +111,6 @@ import { redisApi } from './api';
|
|||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import TagTreeSelect from '../component/TagTreeSelect.vue';
|
import TagTreeSelect from '../component/TagTreeSelect.vue';
|
||||||
import SshTunnelSelect from '../component/SshTunnelSelect.vue';
|
import SshTunnelSelect from '../component/SshTunnelSelect.vue';
|
||||||
import ProcdefSelectFormItem from '@/views/flow/components/ProcdefSelectFormItem.vue';
|
|
||||||
import { ResourceCodePattern } from '@/common/pattern';
|
import { ResourceCodePattern } from '@/common/pattern';
|
||||||
import DrawerHeader from '@/components/drawer-header/DrawerHeader.vue';
|
import DrawerHeader from '@/components/drawer-header/DrawerHeader.vue';
|
||||||
|
|
||||||
@@ -199,7 +196,6 @@ const state = reactive({
|
|||||||
db: '',
|
db: '',
|
||||||
remark: '',
|
remark: '',
|
||||||
sshTunnelMachineId: -1,
|
sshTunnelMachineId: -1,
|
||||||
flowProcdefKey: '',
|
|
||||||
},
|
},
|
||||||
submitForm: {} as any,
|
submitForm: {} as any,
|
||||||
dbList: [0],
|
dbList: [0],
|
||||||
|
|||||||
@@ -128,7 +128,6 @@
|
|||||||
|
|
||||||
<el-descriptions-item :span="3" label="库">{{ detailDialog.data.db }}</el-descriptions-item>
|
<el-descriptions-item :span="3" label="库">{{ detailDialog.data.db }}</el-descriptions-item>
|
||||||
<el-descriptions-item :span="3" label="备注">{{ detailDialog.data.remark }}</el-descriptions-item>
|
<el-descriptions-item :span="3" label="备注">{{ detailDialog.data.remark }}</el-descriptions-item>
|
||||||
<el-descriptions-item :span="3" label="工单流程key">{{ detailDialog.data?.flowProcdefKey }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item :span="3" label="SSH隧道">{{ detailDialog.data.sshTunnelMachineId > 0 ? '是' : '否' }} </el-descriptions-item>
|
<el-descriptions-item :span="3" label="SSH隧道">{{ detailDialog.data.sshTunnelMachineId > 0 ? '是' : '否' }} </el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item :span="2" label="创建时间">{{ dateFormat(detailDialog.data.createTime) }} </el-descriptions-item>
|
<el-descriptions-item :span="2" label="创建时间">{{ dateFormat(detailDialog.data.createTime) }} </el-descriptions-item>
|
||||||
@@ -180,7 +179,6 @@ const columns = ref([
|
|||||||
TableColumn.new('name', '名称'),
|
TableColumn.new('name', '名称'),
|
||||||
TableColumn.new('host', 'host:port'),
|
TableColumn.new('host', 'host:port'),
|
||||||
TableColumn.new('mode', 'mode'),
|
TableColumn.new('mode', 'mode'),
|
||||||
TableColumn.new('flowProcdefKey', '关联流程'),
|
|
||||||
TableColumn.new('remark', '备注'),
|
TableColumn.new('remark', '备注'),
|
||||||
TableColumn.new('code', '编号'),
|
TableColumn.new('code', '编号'),
|
||||||
TableColumn.new('action', '操作').isSlot().setMinWidth(200).fixedRight().alignCenter(),
|
TableColumn.new('action', '操作').isSlot().setMinWidth(200).fixedRight().alignCenter(),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export type CmdExecProps = {
|
|||||||
id: number;
|
id: number;
|
||||||
db: number | string;
|
db: number | string;
|
||||||
cmd: any[];
|
cmd: any[];
|
||||||
flowProcdefKey?: string;
|
flowProcdef?: any;
|
||||||
visible?: boolean;
|
visible?: boolean;
|
||||||
runSuccessFn?: Function;
|
runSuccessFn?: Function;
|
||||||
cancelFn?: Function;
|
cancelFn?: Function;
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<el-input type="textarea" disabled v-model="state.cmdStr" class="mt5" rows="5" />
|
<el-input type="textarea" disabled v-model="state.cmdStr" class="mt5" rows="5" />
|
||||||
<el-input @keyup.enter="runCmd" ref="remarkInputRef" v-model="remark" placeholder="请输入执行备注" class="mt5" />
|
<el-input @keyup.enter="runCmd" ref="remarkInputRef" v-model="remark" placeholder="请输入执行备注" class="mt5" />
|
||||||
|
|
||||||
<div v-if="props.flowProcdefKey">
|
<div v-if="props.flowProcdef">
|
||||||
<el-divider content-position="left">审批节点</el-divider>
|
<el-divider content-position="left">审批节点</el-divider>
|
||||||
<procdef-tasks :procdef-key="props.flowProcdefKey" />
|
<procdef-tasks :procdef="props.flowProcdef" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -32,7 +32,7 @@ const props = withDefaults(defineProps<CmdExecProps>(), {});
|
|||||||
const remarkInputRef = ref<InputInstance>();
|
const remarkInputRef = ref<InputInstance>();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
flowProcdefKey: '' as any,
|
flowProcdef: null as any,
|
||||||
cmdStr: '',
|
cmdStr: '',
|
||||||
remark: '',
|
remark: '',
|
||||||
btnLoading: false,
|
btnLoading: false,
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ export class RedisInst {
|
|||||||
db: number;
|
db: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 流程定义key,若存在则需要审批执行
|
* 流程定义,若存在则需要审批执行
|
||||||
*/
|
*/
|
||||||
flowProcdefKey: string;
|
flowProcdef: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行命令
|
* 执行命令
|
||||||
@@ -24,11 +24,11 @@ export class RedisInst {
|
|||||||
*/
|
*/
|
||||||
async runCmd(cmd: any[]) {
|
async runCmd(cmd: any[]) {
|
||||||
// 工单流程定义存在,并且为写入命令时,弹窗输入工单相关信息并提交
|
// 工单流程定义存在,并且为写入命令时,弹窗输入工单相关信息并提交
|
||||||
if (this.flowProcdefKey && writeCmd[cmd[0].toUpperCase()]) {
|
if (this.flowProcdef && writeCmd[cmd[0].toUpperCase()]) {
|
||||||
showCmdExecBox({
|
showCmdExecBox({
|
||||||
id: this.id,
|
id: this.id,
|
||||||
db: this.db,
|
db: this.db,
|
||||||
flowProcdefKey: this.flowProcdefKey,
|
flowProcdef: this.flowProcdef,
|
||||||
cmd,
|
cmd,
|
||||||
});
|
});
|
||||||
// 报错,阻止后续继续执行
|
// 报错,阻止后续继续执行
|
||||||
|
|||||||
@@ -145,22 +145,23 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { toRefs, ref, watch, reactive, onMounted, Ref } from 'vue';
|
import { toRefs, ref, watch, reactive, onMounted, Ref, defineAsyncComponent } from 'vue';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
import { tagApi } from './api';
|
import { tagApi } from './api';
|
||||||
import { dateFormat } from '@/common/utils/date';
|
import { dateFormat } from '@/common/utils/date';
|
||||||
import { Contextmenu, ContextmenuItem } from '@/components/contextmenu/index';
|
import { Contextmenu, ContextmenuItem } from '@/components/contextmenu/index';
|
||||||
import { useUserInfo } from '@/store/userInfo';
|
import { useUserInfo } from '@/store/userInfo';
|
||||||
import { Splitpanes, Pane } from 'splitpanes';
|
import { Splitpanes, Pane } from 'splitpanes';
|
||||||
import MachineList from '../machine/MachineList.vue';
|
|
||||||
import RedisList from '../redis/RedisList.vue';
|
|
||||||
import MongoList from '../mongo/MongoList.vue';
|
|
||||||
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
||||||
import EnumTag from '@/components/enumtag/EnumTag.vue';
|
import EnumTag from '@/components/enumtag/EnumTag.vue';
|
||||||
import EnumValue from '@/common/Enum';
|
import EnumValue from '@/common/Enum';
|
||||||
import InstanceList from '../db/InstanceList.vue';
|
|
||||||
import TagCodePath from '../component/TagCodePath.vue';
|
import TagCodePath from '../component/TagCodePath.vue';
|
||||||
|
|
||||||
|
const MachineList = defineAsyncComponent(() => import('../machine/MachineList.vue'));
|
||||||
|
const InstanceList = defineAsyncComponent(() => import('../db/InstanceList.vue'));
|
||||||
|
const RedisList = defineAsyncComponent(() => import('../redis/RedisList.vue'));
|
||||||
|
const MongoList = defineAsyncComponent(() => import('../mongo/MongoList.vue'));
|
||||||
|
|
||||||
interface Tree {
|
interface Tree {
|
||||||
id: number;
|
id: number;
|
||||||
codePath: string;
|
codePath: string;
|
||||||
@@ -195,6 +196,9 @@ const contextmenuAdd = new ContextmenuItem('addTag', '添加子标签')
|
|||||||
const contextmenuEdit = new ContextmenuItem('edit', '编辑')
|
const contextmenuEdit = new ContextmenuItem('edit', '编辑')
|
||||||
.withIcon('edit')
|
.withIcon('edit')
|
||||||
.withPermission('tag:save')
|
.withPermission('tag:save')
|
||||||
|
.withHideFunc((data: any) => {
|
||||||
|
return data.type != TagResourceTypeEnum.Tag.value;
|
||||||
|
})
|
||||||
.withOnClick((data: any) => showEditTagDialog(data));
|
.withOnClick((data: any) => showEditTagDialog(data));
|
||||||
|
|
||||||
const contextmenuDel = new ContextmenuItem('delete', '删除')
|
const contextmenuDel = new ContextmenuItem('delete', '删除')
|
||||||
@@ -376,6 +380,11 @@ const search = async () => {
|
|||||||
state.data = res;
|
state.data = res;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getDetail = async (id: number) => {
|
||||||
|
const tags = await tagApi.listByQuery.request({ id });
|
||||||
|
return tags?.[0];
|
||||||
|
};
|
||||||
|
|
||||||
// 树节点右击事件
|
// 树节点右击事件
|
||||||
const nodeContextmenu = (event: any, data: any) => {
|
const nodeContextmenu = (event: any, data: any) => {
|
||||||
const { clientX, clientY } = event;
|
const { clientX, clientY } = event;
|
||||||
@@ -384,8 +393,8 @@ const nodeContextmenu = (event: any, data: any) => {
|
|||||||
contextmenuRef.value.openContextmenu(data);
|
contextmenuRef.value.openContextmenu(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const treeNodeClick = (data: any) => {
|
const treeNodeClick = async (data: any) => {
|
||||||
state.currentTag = data;
|
state.currentTag = await getDetail(data.id);
|
||||||
// 关闭可能存在的右击菜单
|
// 关闭可能存在的右击菜单
|
||||||
contextmenuRef.value.closeContextmenu();
|
contextmenuRef.value.closeContextmenu();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -114,19 +114,19 @@ watchEffect(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const btnOk = async () => {
|
const btnOk = async () => {
|
||||||
accountForm.value.validate(async (valid: boolean) => {
|
try {
|
||||||
if (!valid) {
|
await accountForm.value.validate();
|
||||||
ElMessage.error('表单填写有误');
|
} catch (e: any) {
|
||||||
return false;
|
ElMessage.error('请正确填写信息');
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
await saveAccountExec();
|
await saveAccountExec();
|
||||||
ElMessage.success('操作成功');
|
ElMessage.success('操作成功');
|
||||||
emit('val-change', state.form);
|
emit('val-change', state.form);
|
||||||
//重置表单域
|
//重置表单域
|
||||||
accountForm.value.resetFields();
|
accountForm.value.resetFields();
|
||||||
state.form = {} as any;
|
state.form = {} as any;
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
import { ref, toRefs, reactive, watch, watchEffect } from 'vue';
|
import { ref, toRefs, reactive, watch, watchEffect } from 'vue';
|
||||||
import { configApi, accountApi } from '../api';
|
import { configApi, accountApi } from '../api';
|
||||||
import { DynamicFormEdit } from '@/components/dynamic-form';
|
import { DynamicFormEdit } from '@/components/dynamic-form';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
@@ -125,22 +126,25 @@ const getAccount = (username: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const btnOk = async () => {
|
const btnOk = async () => {
|
||||||
configForm.value.validate(async (valid: boolean) => {
|
try {
|
||||||
if (valid) {
|
await configForm.value.validate();
|
||||||
if (state.params) {
|
} catch (e: any) {
|
||||||
state.form.params = JSON.stringify(state.params);
|
ElMessage.error('请正确填写信息');
|
||||||
}
|
return false;
|
||||||
if (state.permissionAccount.length > 0) {
|
}
|
||||||
state.form.permission = state.permissionAccount.join(',') + ',';
|
|
||||||
} else {
|
|
||||||
state.form.permission = 'all';
|
|
||||||
}
|
|
||||||
|
|
||||||
await saveConfigExec();
|
if (state.params) {
|
||||||
emit('val-change', state.form);
|
state.form.params = JSON.stringify(state.params);
|
||||||
cancel();
|
}
|
||||||
}
|
if (state.permissionAccount.length > 0) {
|
||||||
});
|
state.form.permission = state.permissionAccount.join(',') + ',';
|
||||||
|
} else {
|
||||||
|
state.form.permission = 'all';
|
||||||
|
}
|
||||||
|
|
||||||
|
await saveConfigExec();
|
||||||
|
emit('val-change', state.form);
|
||||||
|
cancel();
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss"></style>
|
<style lang="scss"></style>
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ const changeLinkType = () => {
|
|||||||
state.form.meta.component = '';
|
state.form.meta.component = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
const btnOk = () => {
|
const btnOk = async () => {
|
||||||
const submitForm = { ...state.form };
|
const submitForm = { ...state.form };
|
||||||
if (submitForm.type == 1) {
|
if (submitForm.type == 1) {
|
||||||
// 如果是菜单,则解析meta,如果值为false或者''则去除该值
|
// 如果是菜单,则解析meta,如果值为false或者''则去除该值
|
||||||
@@ -263,16 +263,19 @@ const btnOk = () => {
|
|||||||
submitForm.meta = null as any;
|
submitForm.meta = null as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
menuForm.value.validate(async (valid: any) => {
|
try {
|
||||||
if (valid) {
|
await menuForm.value.validate();
|
||||||
state.submitForm = submitForm;
|
} catch (e: any) {
|
||||||
await saveResouceExec();
|
ElMessage.error('请正确填写信息');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
emit('val-change', submitForm);
|
state.submitForm = submitForm;
|
||||||
ElMessage.success('保存成功');
|
await saveResouceExec();
|
||||||
cancel();
|
|
||||||
}
|
emit('val-change', submitForm);
|
||||||
});
|
ElMessage.success('保存成功');
|
||||||
|
cancel();
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseMenuMeta = (meta: any) => {
|
const parseMenuMeta = (meta: any) => {
|
||||||
|
|||||||
@@ -80,13 +80,15 @@ const cancel = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const btnOk = async () => {
|
const btnOk = async () => {
|
||||||
roleForm.value.validate(async (valid: boolean) => {
|
try {
|
||||||
if (valid) {
|
await roleForm.value.validate();
|
||||||
await saveRoleExec();
|
} catch (e: any) {
|
||||||
emit('val-change', state.form);
|
return false;
|
||||||
cancel();
|
}
|
||||||
}
|
|
||||||
});
|
await saveRoleExec();
|
||||||
|
emit('val-change', state.form);
|
||||||
|
cancel();
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss"></style>
|
<style lang="scss"></style>
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ require (
|
|||||||
gitee.com/liuzongyang/libpq v1.0.9
|
gitee.com/liuzongyang/libpq v1.0.9
|
||||||
github.com/buger/jsonparser v1.1.1
|
github.com/buger/jsonparser v1.1.1
|
||||||
github.com/emirpasic/gods v1.18.1
|
github.com/emirpasic/gods v1.18.1
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/glebarez/sqlite v1.11.0
|
github.com/glebarez/sqlite v1.11.0
|
||||||
github.com/go-gormigrate/gormigrate/v2 v2.1.0
|
github.com/go-gormigrate/gormigrate/v2 v2.1.0
|
||||||
github.com/go-ldap/ldap/v3 v3.4.8
|
github.com/go-ldap/ldap/v3 v3.4.8
|
||||||
github.com/go-playground/locales v0.14.1
|
github.com/go-playground/locales v0.14.1
|
||||||
github.com/go-playground/universal-translator v0.18.1
|
github.com/go-playground/universal-translator v0.18.1
|
||||||
github.com/go-playground/validator/v10 v10.14.0
|
github.com/go-playground/validator/v10 v10.20.0
|
||||||
github.com/go-sql-driver/mysql v1.8.1
|
github.com/go-sql-driver/mysql v1.8.1
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
@@ -28,12 +28,12 @@ require (
|
|||||||
github.com/pquerna/otp v1.4.0
|
github.com/pquerna/otp v1.4.0
|
||||||
github.com/redis/go-redis/v9 v9.5.1
|
github.com/redis/go-redis/v9 v9.5.1
|
||||||
github.com/robfig/cron/v3 v3.0.1 // 定时任务
|
github.com/robfig/cron/v3 v3.0.1 // 定时任务
|
||||||
github.com/sijms/go-ora/v2 v2.8.13
|
github.com/sijms/go-ora/v2 v2.8.16
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/veops/go-ansiterm v0.0.5
|
github.com/veops/go-ansiterm v0.0.5
|
||||||
go.mongodb.org/mongo-driver v1.15.0 // mongo
|
go.mongodb.org/mongo-driver v1.15.0 // mongo
|
||||||
golang.org/x/crypto v0.22.0 // ssh
|
golang.org/x/crypto v0.23.0 // ssh
|
||||||
golang.org/x/oauth2 v0.19.0
|
golang.org/x/oauth2 v0.20.0
|
||||||
golang.org/x/sync v0.7.0
|
golang.org/x/sync v0.7.0
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
@@ -46,13 +46,15 @@ require (
|
|||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||||
github.com/bytedance/sonic v1.9.1 // indirect
|
github.com/bytedance/sonic v1.11.6 // indirect
|
||||||
|
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||||
@@ -67,36 +69,36 @@ require (
|
|||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.16.5 // indirect
|
github.com/klauspost/compress v1.16.5 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||||
github.com/kr/fs v0.1.0 // indirect
|
github.com/kr/fs v0.1.0 // indirect
|
||||||
github.com/leodido/go-urn v1.2.4 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.17 // indirect
|
github.com/mattn/go-sqlite3 v1.14.17 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/montanaflynn/stats v0.7.0 // indirect
|
github.com/montanaflynn/stats v0.7.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/rivo/uniseg v0.4.3 // indirect
|
github.com/rivo/uniseg v0.4.3 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||||
github.com/xdg-go/scram v1.1.2 // indirect
|
github.com/xdg-go/scram v1.1.2 // indirect
|
||||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230519143937-03e91628a987 // indirect
|
golang.org/x/exp v0.0.0-20230519143937-03e91628a987 // indirect
|
||||||
golang.org/x/image v0.13.0 // indirect
|
golang.org/x/image v0.13.0 // indirect
|
||||||
golang.org/x/net v0.22.0 // indirect
|
golang.org/x/net v0.25.0 // indirect
|
||||||
golang.org/x/sys v0.19.0 // indirect
|
golang.org/x/sys v0.20.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.15.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 // indirect
|
google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 // indirect
|
||||||
google.golang.org/grpc v1.52.3 // indirect
|
google.golang.org/grpc v1.52.3 // indirect
|
||||||
google.golang.org/protobuf v1.31.0 // indirect
|
google.golang.org/protobuf v1.34.1 // indirect
|
||||||
modernc.org/libc v1.22.5 // indirect
|
modernc.org/libc v1.22.5 // indirect
|
||||||
modernc.org/mathutil v1.5.0 // indirect
|
modernc.org/mathutil v1.5.0 // indirect
|
||||||
modernc.org/memory v1.5.0 // indirect
|
modernc.org/memory v1.5.0 // indirect
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ func (a *Oauth2Login) doLoginAction(rc *req.Ctx, userId string, oauth *config.Oa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 进行登录
|
// 进行登录
|
||||||
account, err := a.AccountApp.GetById(new(sysentity.Account), accountId, "Id", "Name", "Username", "Password", "Status", "LastLoginTime", "LastLoginIp", "OtpSecret")
|
account, err := a.AccountApp.GetById(accountId, "Id", "Name", "Username", "Password", "Status", "LastLoginTime", "LastLoginIp", "OtpSecret")
|
||||||
biz.ErrIsNilAppendErr(err, "获取用户信息失败: %s")
|
biz.ErrIsNilAppendErr(err, "获取用户信息失败: %s")
|
||||||
|
|
||||||
clientIp := getIpAndRegion(rc)
|
clientIp := getIpAndRegion(rc)
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"mayfly-go/internal/common/consts"
|
|
||||||
"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/application/dto"
|
||||||
"mayfly-go/internal/db/config"
|
"mayfly-go/internal/db/config"
|
||||||
"mayfly-go/internal/db/dbm/dbi"
|
"mayfly-go/internal/db/dbm/dbi"
|
||||||
"mayfly-go/internal/db/domain/entity"
|
"mayfly-go/internal/db/domain/entity"
|
||||||
@@ -84,8 +84,6 @@ func (d *Db) DeleteDb(rc *req.Ctx) {
|
|||||||
dbId := cast.ToUint64(v)
|
dbId := cast.ToUint64(v)
|
||||||
biz.NotBlank(dbId, "存在错误dbId")
|
biz.NotBlank(dbId, "存在错误dbId")
|
||||||
biz.ErrIsNil(d.DbApp.Delete(ctx, dbId))
|
biz.ErrIsNil(d.DbApp.Delete(ctx, dbId))
|
||||||
// 删除该库的sql执行记录
|
|
||||||
d.DbSqlExecApp.DeleteBy(ctx, &entity.DbSqlExec{DbId: dbId})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,9 +95,9 @@ func (d *Db) ExecSql(rc *req.Ctx) {
|
|||||||
dbId := getDbId(rc)
|
dbId := getDbId(rc)
|
||||||
dbConn, err := d.DbApp.GetDbConn(dbId, form.Db)
|
dbConn, err := d.DbApp.GetDbConn(dbId, form.Db)
|
||||||
biz.ErrIsNil(err)
|
biz.ErrIsNil(err)
|
||||||
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.GetLoginAccount().Id, dbConn.Info.TagPath...), "%s")
|
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.GetLoginAccount().Id, dbConn.Info.CodePath...), "%s")
|
||||||
|
|
||||||
global.EventBus.Publish(rc.MetaCtx, event.EventTopicResourceOp, dbConn.Info.TagPath[0])
|
global.EventBus.Publish(rc.MetaCtx, event.EventTopicResourceOp, dbConn.Info.CodePath[0])
|
||||||
|
|
||||||
sqlBytes, err := base64.StdEncoding.DecodeString(form.Sql)
|
sqlBytes, err := base64.StdEncoding.DecodeString(form.Sql)
|
||||||
biz.ErrIsNilAppendErr(err, "sql解码失败: %s")
|
biz.ErrIsNilAppendErr(err, "sql解码失败: %s")
|
||||||
@@ -174,10 +172,8 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) {
|
|||||||
clientId := rc.Query("clientId")
|
clientId := rc.Query("clientId")
|
||||||
|
|
||||||
dbConn, err := d.DbApp.GetDbConn(dbId, dbName)
|
dbConn, err := d.DbApp.GetDbConn(dbId, dbName)
|
||||||
// 开启流程审批时,执行文件暂时还未处理
|
|
||||||
biz.IsTrue(dbConn.Info.FlowProcdefKey == "", "该库已开启流程审批,暂不支持该操作")
|
|
||||||
biz.ErrIsNil(err)
|
biz.ErrIsNil(err)
|
||||||
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.GetLoginAccount().Id, dbConn.Info.TagPath...), "%s")
|
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.GetLoginAccount().Id, dbConn.Info.CodePath...), "%s")
|
||||||
rc.ReqParam = fmt.Sprintf("filename: %s -> %s", filename, dbConn.Info.GetLogDesc())
|
rc.ReqParam = fmt.Sprintf("filename: %s -> %s", filename, dbConn.Info.GetLogDesc())
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -245,7 +241,7 @@ func (d *Db) ExecSqlFile(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
dbConn, err = d.DbApp.GetDbConn(dbId, stmtUse.DBName.String())
|
dbConn, err = d.DbApp.GetDbConn(dbId, stmtUse.DBName.String())
|
||||||
biz.ErrIsNil(err)
|
biz.ErrIsNil(err)
|
||||||
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(laId, dbConn.Info.TagPath...), "%s")
|
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(laId, dbConn.Info.CodePath...), "%s")
|
||||||
execReq.DbConn = dbConn
|
execReq.DbConn = dbConn
|
||||||
}
|
}
|
||||||
// 需要记录执行记录
|
// 需要记录执行记录
|
||||||
@@ -282,12 +278,12 @@ func (d *Db) DumpSql(rc *req.Ctx) {
|
|||||||
needData := dumpType == "2" || dumpType == "3"
|
needData := dumpType == "2" || dumpType == "3"
|
||||||
|
|
||||||
la := rc.GetLoginAccount()
|
la := rc.GetLoginAccount()
|
||||||
db, err := d.DbApp.GetById(new(entity.Db), dbId)
|
dbConn, err := d.DbApp.GetDbConn(dbId, dbName)
|
||||||
biz.ErrIsNil(err, "该数据库不存在")
|
biz.ErrIsNil(err)
|
||||||
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(la.Id, d.TagApp.ListTagPathByTypeAndCode(consts.ResourceTypeDb, db.Code)...), "%s")
|
biz.ErrIsNilAppendErr(d.TagApp.CanAccess(la.Id, dbConn.Info.CodePath...), "%s")
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
filename := fmt.Sprintf("%s-%s.%s.sql%s", db.Name, dbName, now.Format("20060102150405"), extName)
|
filename := fmt.Sprintf("%s-%s.%s.sql%s", dbConn.Info.Name, dbName, now.Format("20060102150405"), extName)
|
||||||
rc.Header("Content-Type", "application/octet-stream")
|
rc.Header("Content-Type", "application/octet-stream")
|
||||||
rc.Header("Content-Disposition", "attachment; filename="+filename)
|
rc.Header("Content-Disposition", "attachment; filename="+filename)
|
||||||
if extName != ".gz" {
|
if extName != ".gz" {
|
||||||
@@ -308,7 +304,7 @@ func (d *Db) DumpSql(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
biz.ErrIsNil(d.DbApp.DumpDb(rc.MetaCtx, &application.DumpDbReq{
|
biz.ErrIsNil(d.DbApp.DumpDb(rc.MetaCtx, &dto.DumpDb{
|
||||||
DbId: dbId,
|
DbId: dbId,
|
||||||
DbName: dbName,
|
DbName: dbName,
|
||||||
Tables: tables,
|
Tables: tables,
|
||||||
@@ -317,7 +313,7 @@ func (d *Db) DumpSql(rc *req.Ctx) {
|
|||||||
Writer: rc.GetWriter(),
|
Writer: rc.GetWriter(),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
rc.ReqParam = collx.Kvs("db", db, "database", dbName, "tables", tablesStr, "dumpType", dumpType)
|
rc.ReqParam = collx.Kvs("db", dbConn.Info, "database", dbName, "tables", tablesStr, "dumpType", dumpType)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Db) TableInfos(rc *req.Ctx) {
|
func (d *Db) TableInfos(rc *req.Ctx) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ type DbBackup struct {
|
|||||||
func (d *DbBackup) GetPageList(rc *req.Ctx) {
|
func (d *DbBackup) GetPageList(rc *req.Ctx) {
|
||||||
dbId := uint64(rc.PathParamInt("dbId"))
|
dbId := uint64(rc.PathParamInt("dbId"))
|
||||||
biz.IsTrue(dbId > 0, "无效的 dbId: %v", dbId)
|
biz.IsTrue(dbId > 0, "无效的 dbId: %v", dbId)
|
||||||
db, err := d.dbApp.GetById(new(entity.Db), dbId, "db_instance_id", "database")
|
db, err := d.dbApp.GetById(dbId)
|
||||||
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
||||||
|
|
||||||
queryCond, page := req.BindQueryAndPage[*entity.DbBackupQuery](rc, new(entity.DbBackupQuery))
|
queryCond, page := req.BindQueryAndPage[*entity.DbBackupQuery](rc, new(entity.DbBackupQuery))
|
||||||
@@ -49,7 +49,7 @@ func (d *DbBackup) Create(rc *req.Ctx) {
|
|||||||
|
|
||||||
dbId := uint64(rc.PathParamInt("dbId"))
|
dbId := uint64(rc.PathParamInt("dbId"))
|
||||||
biz.IsTrue(dbId > 0, "无效的 dbId: %v", dbId)
|
biz.IsTrue(dbId > 0, "无效的 dbId: %v", dbId)
|
||||||
db, err := d.dbApp.GetById(new(entity.Db), dbId, "instanceId")
|
db, err := d.dbApp.GetById(dbId)
|
||||||
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
||||||
jobs := make([]*entity.DbBackup, 0, len(dbNames))
|
jobs := make([]*entity.DbBackup, 0, len(dbNames))
|
||||||
for _, dbName := range dbNames {
|
for _, dbName := range dbNames {
|
||||||
@@ -134,7 +134,7 @@ func (d *DbBackup) Start(rc *req.Ctx) {
|
|||||||
// @router /api/dbs/:dbId/db-names-without-backup [GET]
|
// @router /api/dbs/:dbId/db-names-without-backup [GET]
|
||||||
func (d *DbBackup) GetDbNamesWithoutBackup(rc *req.Ctx) {
|
func (d *DbBackup) GetDbNamesWithoutBackup(rc *req.Ctx) {
|
||||||
dbId := uint64(rc.PathParamInt("dbId"))
|
dbId := uint64(rc.PathParamInt("dbId"))
|
||||||
db, err := d.dbApp.GetById(new(entity.Db), dbId, "instance_id", "database")
|
db, err := d.dbApp.GetById(dbId, "instance_id", "database")
|
||||||
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
||||||
dbNames := strings.Fields(db.Database)
|
dbNames := strings.Fields(db.Database)
|
||||||
dbNamesWithoutBackup, err := d.backupApp.GetDbNamesWithoutBackup(db.InstanceId, dbNames)
|
dbNamesWithoutBackup, err := d.backupApp.GetDbNamesWithoutBackup(db.InstanceId, dbNames)
|
||||||
@@ -147,7 +147,7 @@ func (d *DbBackup) GetDbNamesWithoutBackup(rc *req.Ctx) {
|
|||||||
func (d *DbBackup) GetHistoryPageList(rc *req.Ctx) {
|
func (d *DbBackup) GetHistoryPageList(rc *req.Ctx) {
|
||||||
dbId := uint64(rc.PathParamInt("dbId"))
|
dbId := uint64(rc.PathParamInt("dbId"))
|
||||||
biz.IsTrue(dbId > 0, "无效的 dbId: %v", dbId)
|
biz.IsTrue(dbId > 0, "无效的 dbId: %v", dbId)
|
||||||
db, err := d.dbApp.GetById(new(entity.Db), dbId, "db_instance_id", "database")
|
db, err := d.dbApp.GetById(dbId, "instance_id", "database")
|
||||||
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
||||||
|
|
||||||
backupHistoryCond, page := req.BindQueryAndPage[*entity.DbBackupHistoryQuery](rc, new(entity.DbBackupHistoryQuery))
|
backupHistoryCond, page := req.BindQueryAndPage[*entity.DbBackupHistoryQuery](rc, new(entity.DbBackupHistoryQuery))
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ func (d *DataSyncTask) ChangeStatus(rc *req.Ctx) {
|
|||||||
_ = d.DataSyncTaskApp.UpdateById(rc.MetaCtx, task)
|
_ = d.DataSyncTaskApp.UpdateById(rc.MetaCtx, task)
|
||||||
|
|
||||||
if task.Status == entity.DataSyncTaskStatusEnable {
|
if task.Status == entity.DataSyncTaskStatusEnable {
|
||||||
task, err := d.DataSyncTaskApp.GetById(new(entity.DataSyncTask), task.Id)
|
task, err := d.DataSyncTaskApp.GetById(task.Id)
|
||||||
biz.ErrIsNil(err, "该任务不存在")
|
biz.ErrIsNil(err, "该任务不存在")
|
||||||
d.DataSyncTaskApp.AddCronJob(rc.MetaCtx, task)
|
d.DataSyncTaskApp.AddCronJob(rc.MetaCtx, task)
|
||||||
} else {
|
} else {
|
||||||
@@ -92,7 +92,7 @@ func (d *DataSyncTask) Stop(rc *req.Ctx) {
|
|||||||
|
|
||||||
func (d *DataSyncTask) GetTask(rc *req.Ctx) {
|
func (d *DataSyncTask) GetTask(rc *req.Ctx) {
|
||||||
taskId := d.getTaskId(rc)
|
taskId := d.getTaskId(rc)
|
||||||
dbEntity, _ := d.DataSyncTaskApp.GetById(new(entity.DataSyncTask), taskId)
|
dbEntity, _ := d.DataSyncTaskApp.GetById(taskId)
|
||||||
rc.ResData = dbEntity
|
rc.ResData = dbEntity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"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/application/dto"
|
||||||
"mayfly-go/internal/db/domain/entity"
|
"mayfly-go/internal/db/domain/entity"
|
||||||
|
|
||||||
tagapp "mayfly-go/internal/tag/application"
|
tagapp "mayfly-go/internal/tag/application"
|
||||||
@@ -70,7 +71,7 @@ func (d *Instance) SaveInstance(rc *req.Ctx) {
|
|||||||
instance := req.BindJsonAndCopyTo[*entity.DbInstance](rc, form, new(entity.DbInstance))
|
instance := req.BindJsonAndCopyTo[*entity.DbInstance](rc, form, new(entity.DbInstance))
|
||||||
|
|
||||||
rc.ReqParam = form
|
rc.ReqParam = form
|
||||||
id, err := d.InstanceApp.SaveDbInstance(rc.MetaCtx, &application.SaveDbInstanceParam{
|
id, err := d.InstanceApp.SaveDbInstance(rc.MetaCtx, &dto.SaveDbInstance{
|
||||||
DbInstance: instance,
|
DbInstance: instance,
|
||||||
AuthCerts: form.AuthCerts,
|
AuthCerts: form.AuthCerts,
|
||||||
TagCodePaths: form.TagCodePaths,
|
TagCodePaths: form.TagCodePaths,
|
||||||
@@ -83,7 +84,7 @@ func (d *Instance) SaveInstance(rc *req.Ctx) {
|
|||||||
// @router /api/instances/:instance [GET]
|
// @router /api/instances/:instance [GET]
|
||||||
func (d *Instance) GetInstance(rc *req.Ctx) {
|
func (d *Instance) GetInstance(rc *req.Ctx) {
|
||||||
dbId := getInstanceId(rc)
|
dbId := getInstanceId(rc)
|
||||||
dbEntity, err := d.InstanceApp.GetById(new(entity.DbInstance), dbId)
|
dbEntity, err := d.InstanceApp.GetById(dbId)
|
||||||
biz.ErrIsNil(err, "获取数据库实例错误")
|
biz.ErrIsNil(err, "获取数据库实例错误")
|
||||||
rc.ResData = dbEntity
|
rc.ResData = dbEntity
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type DbRestore struct {
|
|||||||
func (d *DbRestore) GetPageList(rc *req.Ctx) {
|
func (d *DbRestore) GetPageList(rc *req.Ctx) {
|
||||||
dbId := uint64(rc.PathParamInt("dbId"))
|
dbId := uint64(rc.PathParamInt("dbId"))
|
||||||
biz.IsTrue(dbId > 0, "无效的 dbId: %v", dbId)
|
biz.IsTrue(dbId > 0, "无效的 dbId: %v", dbId)
|
||||||
db, err := d.dbApp.GetById(new(entity.Db), dbId, "db_instance_id", "database")
|
db, err := d.dbApp.GetById(dbId, "db_instance_id", "database")
|
||||||
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
||||||
|
|
||||||
var restores []vo.DbRestore
|
var restores []vo.DbRestore
|
||||||
@@ -43,7 +43,7 @@ func (d *DbRestore) Create(rc *req.Ctx) {
|
|||||||
|
|
||||||
dbId := uint64(rc.PathParamInt("dbId"))
|
dbId := uint64(rc.PathParamInt("dbId"))
|
||||||
biz.IsTrue(dbId > 0, "无效的 dbId: %v", dbId)
|
biz.IsTrue(dbId > 0, "无效的 dbId: %v", dbId)
|
||||||
db, err := d.dbApp.GetById(new(entity.Db), dbId, "instanceId")
|
db, err := d.dbApp.GetById(dbId, "instanceId")
|
||||||
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
||||||
|
|
||||||
job := &entity.DbRestore{
|
job := &entity.DbRestore{
|
||||||
@@ -123,7 +123,7 @@ func (d *DbRestore) Disable(rc *req.Ctx) {
|
|||||||
// @router /api/dbs/:dbId/db-names-without-backup [GET]
|
// @router /api/dbs/:dbId/db-names-without-backup [GET]
|
||||||
func (d *DbRestore) GetDbNamesWithoutRestore(rc *req.Ctx) {
|
func (d *DbRestore) GetDbNamesWithoutRestore(rc *req.Ctx) {
|
||||||
dbId := uint64(rc.PathParamInt("dbId"))
|
dbId := uint64(rc.PathParamInt("dbId"))
|
||||||
db, err := d.dbApp.GetById(new(entity.Db), dbId, "instance_id", "database")
|
db, err := d.dbApp.GetById(dbId, "instance_id", "database")
|
||||||
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
biz.ErrIsNilAppendErr(err, "获取数据库信息失败: %v")
|
||||||
dbNames := strings.Fields(db.Database)
|
dbNames := strings.Fields(db.Database)
|
||||||
dbNamesWithoutRestore, err := d.restoreApp.GetDbNamesWithoutRestore(db.InstanceId, dbNames)
|
dbNamesWithoutRestore, err := d.restoreApp.GetDbNamesWithoutRestore(db.InstanceId, dbNames)
|
||||||
|
|||||||
@@ -43,8 +43,7 @@ func (d *DbSql) GetSqlNames(rc *req.Ctx) {
|
|||||||
// 获取用于是否有该dbsql的保存记录,有则更改,否则新增
|
// 获取用于是否有该dbsql的保存记录,有则更改,否则新增
|
||||||
dbSql := &entity.DbSql{Type: 1, DbId: dbId, Db: dbName}
|
dbSql := &entity.DbSql{Type: 1, DbId: dbId, Db: dbName}
|
||||||
dbSql.CreatorId = rc.GetLoginAccount().Id
|
dbSql.CreatorId = rc.GetLoginAccount().Id
|
||||||
var sqls []entity.DbSql
|
sqls, _ := d.DbSqlApp.ListByCond(model.NewModelCond(dbSql).Columns("id", "name"))
|
||||||
d.DbSqlApp.ListByCond(model.NewModelCond(dbSql).Columns("id", "name"), &sqls)
|
|
||||||
|
|
||||||
rc.ResData = sqls
|
rc.ResData = sqls
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ type DbListVO struct {
|
|||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
|
|
||||||
FlowProcdefKey string `json:"flowProcdefKey"`
|
|
||||||
|
|
||||||
CreateTime *time.Time `json:"createTime"`
|
CreateTime *time.Time `json:"createTime"`
|
||||||
Creator *string `json:"creator"`
|
Creator *string `json:"creator"`
|
||||||
CreatorId *int64 `json:"creatorId"`
|
CreatorId *int64 `json:"creatorId"`
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ package application
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"mayfly-go/internal/db/application/dto"
|
||||||
"mayfly-go/internal/db/dbm"
|
"mayfly-go/internal/db/dbm"
|
||||||
"mayfly-go/internal/db/dbm/dbi"
|
"mayfly-go/internal/db/dbm/dbi"
|
||||||
"mayfly-go/internal/db/domain/entity"
|
"mayfly-go/internal/db/domain/entity"
|
||||||
"mayfly-go/internal/db/domain/repository"
|
"mayfly-go/internal/db/domain/repository"
|
||||||
tagapp "mayfly-go/internal/tag/application"
|
tagapp "mayfly-go/internal/tag/application"
|
||||||
|
tagdto "mayfly-go/internal/tag/application/dto"
|
||||||
tagentity "mayfly-go/internal/tag/domain/entity"
|
tagentity "mayfly-go/internal/tag/domain/entity"
|
||||||
"mayfly-go/pkg/base"
|
"mayfly-go/pkg/base"
|
||||||
"mayfly-go/pkg/biz"
|
"mayfly-go/pkg/biz"
|
||||||
@@ -40,7 +42,7 @@ type Db interface {
|
|||||||
GetDbConnByInstanceId(instanceId uint64) (*dbi.DbConn, error)
|
GetDbConnByInstanceId(instanceId uint64) (*dbi.DbConn, error)
|
||||||
|
|
||||||
// DumpDb dumpDb
|
// DumpDb dumpDb
|
||||||
DumpDb(ctx context.Context, reqParam *DumpDbReq) error
|
DumpDb(ctx context.Context, reqParam *dto.DumpDb) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type dbAppImpl struct {
|
type dbAppImpl struct {
|
||||||
@@ -48,10 +50,13 @@ type dbAppImpl struct {
|
|||||||
|
|
||||||
dbSqlRepo repository.DbSql `inject:"DbSqlRepo"`
|
dbSqlRepo repository.DbSql `inject:"DbSqlRepo"`
|
||||||
dbInstanceApp Instance `inject:"DbInstanceApp"`
|
dbInstanceApp Instance `inject:"DbInstanceApp"`
|
||||||
|
dbSqlExecApp DbSqlExec `inject:"DbSqlExecApp"`
|
||||||
tagApp tagapp.TagTree `inject:"TagTreeApp"`
|
tagApp tagapp.TagTree `inject:"TagTreeApp"`
|
||||||
resourceAuthCertApp tagapp.ResourceAuthCert `inject:"ResourceAuthCertApp"`
|
resourceAuthCertApp tagapp.ResourceAuthCert `inject:"ResourceAuthCertApp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ (Db) = (*dbAppImpl)(nil)
|
||||||
|
|
||||||
// 注入DbRepo
|
// 注入DbRepo
|
||||||
func (d *dbAppImpl) InjectDbRepo(repo repository.Db) {
|
func (d *dbAppImpl) InjectDbRepo(repo repository.Db) {
|
||||||
d.Repo = repo
|
d.Repo = repo
|
||||||
@@ -85,8 +90,8 @@ func (d *dbAppImpl) SaveDb(ctx context.Context, dbEntity *entity.Db) error {
|
|||||||
return d.Insert(ctx, dbEntity)
|
return d.Insert(ctx, dbEntity)
|
||||||
}, func(ctx context.Context) error {
|
}, func(ctx context.Context) error {
|
||||||
// 将库关联至指定数据库授权凭证下
|
// 将库关联至指定数据库授权凭证下
|
||||||
return d.tagApp.RelateTagsByCodeAndType(ctx, &tagapp.RelateTagsByCodeAndTypeParam{
|
return d.tagApp.RelateTagsByCodeAndType(ctx, &tagdto.RelateTagsByCodeAndType{
|
||||||
Tags: []*tagapp.ResourceTag{{
|
Tags: []*tagdto.ResourceTag{{
|
||||||
Code: dbEntity.Code,
|
Code: dbEntity.Code,
|
||||||
Type: tagentity.TagTypeDbName,
|
Type: tagentity.TagTypeDbName,
|
||||||
Name: dbEntity.Name,
|
Name: dbEntity.Name,
|
||||||
@@ -103,7 +108,7 @@ func (d *dbAppImpl) SaveDb(ctx context.Context, dbEntity *entity.Db) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbId := dbEntity.Id
|
dbId := dbEntity.Id
|
||||||
old, err := d.GetById(new(entity.Db), dbId)
|
old, err := d.GetById(dbId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorx.NewBiz("该数据库不存在")
|
return errorx.NewBiz("该数据库不存在")
|
||||||
}
|
}
|
||||||
@@ -142,7 +147,7 @@ func (d *dbAppImpl) SaveDb(ctx context.Context, dbEntity *entity.Db) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *dbAppImpl) Delete(ctx context.Context, id uint64) error {
|
func (d *dbAppImpl) Delete(ctx context.Context, id uint64) error {
|
||||||
db, err := d.GetById(new(entity.Db), id)
|
db, err := d.GetById(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorx.NewBiz("该数据库不存在")
|
return errorx.NewBiz("该数据库不存在")
|
||||||
}
|
}
|
||||||
@@ -160,7 +165,9 @@ func (d *dbAppImpl) Delete(ctx context.Context, id uint64) error {
|
|||||||
// 删除该库下用户保存的所有sql信息
|
// 删除该库下用户保存的所有sql信息
|
||||||
return d.dbSqlRepo.DeleteByCond(ctx, &entity.DbSql{DbId: id})
|
return d.dbSqlRepo.DeleteByCond(ctx, &entity.DbSql{DbId: id})
|
||||||
}, func(ctx context.Context) error {
|
}, func(ctx context.Context) error {
|
||||||
return d.tagApp.DeleteTagByParam(ctx, &tagapp.DelResourceTagParam{
|
return d.dbSqlExecApp.DeleteBy(ctx, &entity.DbSqlExec{DbId: id})
|
||||||
|
}, func(ctx context.Context) error {
|
||||||
|
return d.tagApp.DeleteTagByParam(ctx, &tagdto.DelResourceTag{
|
||||||
ResourceCode: db.Code,
|
ResourceCode: db.Code,
|
||||||
ResourceType: tagentity.TagTypeDbName,
|
ResourceType: tagentity.TagTypeDbName,
|
||||||
})
|
})
|
||||||
@@ -169,12 +176,12 @@ func (d *dbAppImpl) Delete(ctx context.Context, id uint64) error {
|
|||||||
|
|
||||||
func (d *dbAppImpl) GetDbConn(dbId uint64, dbName string) (*dbi.DbConn, error) {
|
func (d *dbAppImpl) GetDbConn(dbId uint64, dbName string) (*dbi.DbConn, error) {
|
||||||
return dbm.GetDbConn(dbId, dbName, func() (*dbi.DbInfo, error) {
|
return dbm.GetDbConn(dbId, dbName, func() (*dbi.DbInfo, error) {
|
||||||
db, err := d.GetById(new(entity.Db), dbId)
|
db, err := d.GetById(dbId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errorx.NewBiz("数据库信息不存在")
|
return nil, errorx.NewBiz("数据库信息不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
instance, err := d.dbInstanceApp.GetById(new(entity.DbInstance), db.InstanceId)
|
instance, err := d.dbInstanceApp.GetById(db.InstanceId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errorx.NewBiz("数据库实例不存在")
|
return nil, errorx.NewBiz("数据库实例不存在")
|
||||||
}
|
}
|
||||||
@@ -183,13 +190,9 @@ func (d *dbAppImpl) GetDbConn(dbId uint64, dbName string) (*dbi.DbConn, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
di.TagPath = d.tagApp.ListTagPathByTypeAndCode(int8(tagentity.TagTypeDbName), db.Code)
|
di.CodePath = d.tagApp.ListTagPathByTypeAndCode(int8(tagentity.TagTypeDbName), db.Code)
|
||||||
di.Id = db.Id
|
di.Id = db.Id
|
||||||
|
|
||||||
if db.FlowProcdefKey != nil {
|
|
||||||
di.FlowProcdefKey = *db.FlowProcdefKey
|
|
||||||
}
|
|
||||||
|
|
||||||
checkDb := di.GetDatabase()
|
checkDb := di.GetDatabase()
|
||||||
if !strings.Contains(" "+db.Database+" ", " "+checkDb+" ") {
|
if !strings.Contains(" "+db.Database+" ", " "+checkDb+" ") {
|
||||||
return nil, errorx.NewBiz("未配置数据库【%s】的操作权限", dbName)
|
return nil, errorx.NewBiz("未配置数据库【%s】的操作权限", dbName)
|
||||||
@@ -205,9 +208,8 @@ func (d *dbAppImpl) GetDbConnByInstanceId(instanceId uint64) (*dbi.DbConn, error
|
|||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var dbs []*entity.Db
|
dbs, err := d.ListByCond(&entity.Db{InstanceId: instanceId}, "id", "database")
|
||||||
|
if err != nil {
|
||||||
if err := d.ListByCond(model.NewModelCond(&entity.Db{InstanceId: instanceId}).Columns("id", "database"), &dbs); err != nil {
|
|
||||||
return nil, errorx.NewBiz("获取数据库列表失败")
|
return nil, errorx.NewBiz("获取数据库列表失败")
|
||||||
}
|
}
|
||||||
if len(dbs) == 0 {
|
if len(dbs) == 0 {
|
||||||
@@ -219,7 +221,7 @@ func (d *dbAppImpl) GetDbConnByInstanceId(instanceId uint64) (*dbi.DbConn, error
|
|||||||
return d.GetDbConn(firstDb.Id, strings.Split(firstDb.Database, " ")[0])
|
return d.GetDbConn(firstDb.Id, strings.Split(firstDb.Database, " ")[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dbAppImpl) DumpDb(ctx context.Context, reqParam *DumpDbReq) error {
|
func (d *dbAppImpl) DumpDb(ctx context.Context, reqParam *dto.DumpDb) error {
|
||||||
writer := newGzipWriter(reqParam.Writer)
|
writer := newGzipWriter(reqParam.Writer)
|
||||||
defer writer.Close()
|
defer writer.Close()
|
||||||
dbId := reqParam.DbId
|
dbId := reqParam.DbId
|
||||||
|
|||||||
@@ -63,21 +63,18 @@ func (app *DbBackupApp) Init() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *DbBackupApp) prune(ctx context.Context) error {
|
func (app *DbBackupApp) prune(ctx context.Context) error {
|
||||||
var jobs []*entity.DbBackup
|
jobs, err := app.backupRepo.SelectByCond(map[string]any{})
|
||||||
if err := app.backupRepo.ListByCond(map[string]any{}, &jobs); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, job := range jobs {
|
for _, job := range jobs {
|
||||||
if ctx.Err() != nil {
|
if ctx.Err() != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var histories []*entity.DbBackupHistory
|
|
||||||
historyCond := map[string]any{
|
historyCond := map[string]any{
|
||||||
"db_backup_id": job.Id,
|
"db_backup_id": job.Id,
|
||||||
}
|
}
|
||||||
if err := app.backupHistoryRepo.SelectByCond(historyCond, &histories); err != nil {
|
histories, _ := app.backupHistoryRepo.SelectByCond(historyCond)
|
||||||
return err
|
|
||||||
}
|
|
||||||
expiringTime := time.Now().Add(-math.MaxInt64)
|
expiringTime := time.Now().Add(-math.MaxInt64)
|
||||||
if job.MaxSaveDays > 0 {
|
if job.MaxSaveDays > 0 {
|
||||||
expiringTime = time.Now().Add(-time.Hour * 24 * time.Duration(job.MaxSaveDays+1))
|
expiringTime = time.Now().Add(-time.Hour * 24 * time.Duration(job.MaxSaveDays+1))
|
||||||
@@ -160,8 +157,8 @@ func (app *DbBackupApp) Enable(ctx context.Context, jobId uint64) error {
|
|||||||
defer app.mutex.Unlock()
|
defer app.mutex.Unlock()
|
||||||
|
|
||||||
repo := app.backupRepo
|
repo := app.backupRepo
|
||||||
job := &entity.DbBackup{}
|
job, err := repo.GetById(jobId)
|
||||||
if err := repo.GetById(job, jobId); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if job.IsEnabled() {
|
if job.IsEnabled() {
|
||||||
@@ -183,8 +180,8 @@ func (app *DbBackupApp) Disable(ctx context.Context, jobId uint64) error {
|
|||||||
defer app.mutex.Unlock()
|
defer app.mutex.Unlock()
|
||||||
|
|
||||||
repo := app.backupRepo
|
repo := app.backupRepo
|
||||||
job := &entity.DbBackup{}
|
job, err := repo.GetById(jobId)
|
||||||
if err := repo.GetById(job, jobId); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !job.IsEnabled() {
|
if !job.IsEnabled() {
|
||||||
@@ -202,8 +199,8 @@ func (app *DbBackupApp) StartNow(ctx context.Context, jobId uint64) error {
|
|||||||
app.mutex.Lock()
|
app.mutex.Lock()
|
||||||
defer app.mutex.Unlock()
|
defer app.mutex.Unlock()
|
||||||
|
|
||||||
job := &entity.DbBackup{}
|
job, err := app.backupRepo.GetById(jobId)
|
||||||
if err := app.backupRepo.GetById(job, jobId); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !job.IsEnabled() {
|
if !job.IsEnabled() {
|
||||||
@@ -267,8 +264,8 @@ func (app *DbBackupApp) DeleteHistory(ctx context.Context, historyId uint64) (re
|
|||||||
if !ok {
|
if !ok {
|
||||||
return errRestoringBackupHistory
|
return errRestoringBackupHistory
|
||||||
}
|
}
|
||||||
job := &entity.DbBackupHistory{}
|
job, err := app.backupHistoryRepo.GetById(historyId)
|
||||||
if err := app.backupHistoryRepo.GetById(job, historyId); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
conn, err := app.dbApp.GetDbConnByInstanceId(job.DbInstanceId)
|
conn, err := app.dbApp.GetDbConnByInstanceId(job.DbInstanceId)
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ func (app *DbBinlogApp) fetchBinlog(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *DbBinlogApp) pruneBinlog(ctx context.Context) error {
|
func (app *DbBinlogApp) pruneBinlog(ctx context.Context) error {
|
||||||
var jobs []*entity.DbBinlog
|
jobs, err := app.binlogRepo.SelectByCond(map[string]any{})
|
||||||
if err := app.binlogRepo.SelectByCond(map[string]any{}, &jobs); err != nil {
|
if err != nil {
|
||||||
logx.Error("DbBinlogApp: 获取 BINLOG 同步任务失败: ", err.Error())
|
logx.Error("DbBinlogApp: 获取 BINLOG 同步任务失败: ", err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ func (app *dataSyncAppImpl) Save(ctx context.Context, taskEntity *entity.DataSyn
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
task, err := app.GetById(new(entity.DataSyncTask), taskEntity.Id)
|
task, err := app.GetById(taskEntity.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ func (app *dataSyncAppImpl) AddCronJob(ctx context.Context, taskEntity *entity.D
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *dataSyncAppImpl) RemoveCronJobById(taskId uint64) {
|
func (app *dataSyncAppImpl) RemoveCronJobById(taskId uint64) {
|
||||||
task, err := app.GetById(new(entity.DataSyncTask), taskId)
|
task, err := app.GetById(taskId)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
scheduler.RemoveByKey(task.TaskKey)
|
scheduler.RemoveByKey(task.TaskKey)
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ func (app *dataSyncAppImpl) changeRunningState(id uint64, state int8) {
|
|||||||
|
|
||||||
func (app *dataSyncAppImpl) RunCronJob(ctx context.Context, id uint64) error {
|
func (app *dataSyncAppImpl) RunCronJob(ctx context.Context, id uint64) error {
|
||||||
// 查询最新的任务信息
|
// 查询最新的任务信息
|
||||||
task, err := app.GetById(new(entity.DataSyncTask), id)
|
task, err := app.GetById(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorx.NewBiz("任务不存在")
|
return errorx.NewBiz("任务不存在")
|
||||||
}
|
}
|
||||||
@@ -369,7 +369,7 @@ func (app *dataSyncAppImpl) srcData2TargetDb(srcRes []map[string]any, fieldMap [
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 运行过程中,判断状态是否为已关闭,是则结束运行,否则继续运行
|
// 运行过程中,判断状态是否为已关闭,是则结束运行,否则继续运行
|
||||||
taskParam, _ := app.GetById(new(entity.DataSyncTask), task.Id)
|
taskParam, _ := app.GetById(task.Id)
|
||||||
if taskParam.RunningState == entity.DataSyncTaskRunStateStop {
|
if taskParam.RunningState == entity.DataSyncTaskRunStateStop {
|
||||||
return errorx.NewBiz("该任务已被手动终止")
|
return errorx.NewBiz("该任务已被手动终止")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"mayfly-go/internal/common/consts"
|
"mayfly-go/internal/common/consts"
|
||||||
|
"mayfly-go/internal/db/application/dto"
|
||||||
"mayfly-go/internal/db/dbm"
|
"mayfly-go/internal/db/dbm"
|
||||||
"mayfly-go/internal/db/dbm/dbi"
|
"mayfly-go/internal/db/dbm/dbi"
|
||||||
"mayfly-go/internal/db/domain/entity"
|
"mayfly-go/internal/db/domain/entity"
|
||||||
"mayfly-go/internal/db/domain/repository"
|
"mayfly-go/internal/db/domain/repository"
|
||||||
tagapp "mayfly-go/internal/tag/application"
|
tagapp "mayfly-go/internal/tag/application"
|
||||||
|
tagdto "mayfly-go/internal/tag/application/dto"
|
||||||
tagentity "mayfly-go/internal/tag/domain/entity"
|
tagentity "mayfly-go/internal/tag/domain/entity"
|
||||||
"mayfly-go/pkg/base"
|
"mayfly-go/pkg/base"
|
||||||
"mayfly-go/pkg/biz"
|
"mayfly-go/pkg/biz"
|
||||||
@@ -21,12 +23,6 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SaveDbInstanceParam struct {
|
|
||||||
DbInstance *entity.DbInstance
|
|
||||||
AuthCerts []*tagentity.ResourceAuthCert
|
|
||||||
TagCodePaths []string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Instance interface {
|
type Instance interface {
|
||||||
base.App[*entity.DbInstance]
|
base.App[*entity.DbInstance]
|
||||||
|
|
||||||
@@ -35,7 +31,7 @@ type Instance interface {
|
|||||||
|
|
||||||
TestConn(instanceEntity *entity.DbInstance, authCert *tagentity.ResourceAuthCert) error
|
TestConn(instanceEntity *entity.DbInstance, authCert *tagentity.ResourceAuthCert) error
|
||||||
|
|
||||||
SaveDbInstance(ctx context.Context, instance *SaveDbInstanceParam) (uint64, error)
|
SaveDbInstance(ctx context.Context, instance *dto.SaveDbInstance) (uint64, error)
|
||||||
|
|
||||||
// Delete 删除数据库信息
|
// Delete 删除数据库信息
|
||||||
Delete(ctx context.Context, id uint64) error
|
Delete(ctx context.Context, id uint64) error
|
||||||
@@ -91,7 +87,7 @@ func (app *instanceAppImpl) TestConn(instanceEntity *entity.DbInstance, authCert
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *instanceAppImpl) SaveDbInstance(ctx context.Context, instance *SaveDbInstanceParam) (uint64, error) {
|
func (app *instanceAppImpl) SaveDbInstance(ctx context.Context, instance *dto.SaveDbInstance) (uint64, error) {
|
||||||
instanceEntity := instance.DbInstance
|
instanceEntity := instance.DbInstance
|
||||||
// 默认tcp连接
|
// 默认tcp连接
|
||||||
instanceEntity.Network = instanceEntity.GetNetwork()
|
instanceEntity.Network = instanceEntity.GetNetwork()
|
||||||
@@ -128,7 +124,7 @@ func (app *instanceAppImpl) SaveDbInstance(ctx context.Context, instance *SaveDb
|
|||||||
AuthCerts: authCerts,
|
AuthCerts: authCerts,
|
||||||
})
|
})
|
||||||
}, func(ctx context.Context) error {
|
}, func(ctx context.Context) error {
|
||||||
return app.tagApp.SaveResourceTag(ctx, &tagapp.SaveResourceTagParam{
|
return app.tagApp.SaveResourceTag(ctx, &tagdto.SaveResourceTag{
|
||||||
ResourceTag: app.genDbInstanceResourceTag(instanceEntity, authCerts),
|
ResourceTag: app.genDbInstanceResourceTag(instanceEntity, authCerts),
|
||||||
ParentTagCodePaths: tagCodePaths,
|
ParentTagCodePaths: tagCodePaths,
|
||||||
})
|
})
|
||||||
@@ -142,7 +138,7 @@ func (app *instanceAppImpl) SaveDbInstance(ctx context.Context, instance *SaveDb
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 根据host等未查到旧数据,则需要根据id重新获取,因为后续需要使用到code
|
// 根据host等未查到旧数据,则需要根据id重新获取,因为后续需要使用到code
|
||||||
oldInstance, err = app.GetById(new(entity.DbInstance), instanceEntity.Id)
|
oldInstance, err = app.GetById(instanceEntity.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errorx.NewBiz("该数据库实例不存在")
|
return 0, errorx.NewBiz("该数据库实例不存在")
|
||||||
}
|
}
|
||||||
@@ -162,7 +158,7 @@ func (app *instanceAppImpl) SaveDbInstance(ctx context.Context, instance *SaveDb
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return app.tagApp.SaveResourceTag(ctx, &tagapp.SaveResourceTagParam{
|
return app.tagApp.SaveResourceTag(ctx, &tagdto.SaveResourceTag{
|
||||||
ResourceTag: app.genDbInstanceResourceTag(instanceEntity, authCerts),
|
ResourceTag: app.genDbInstanceResourceTag(instanceEntity, authCerts),
|
||||||
ParentTagCodePaths: tagCodePaths,
|
ParentTagCodePaths: tagCodePaths,
|
||||||
})
|
})
|
||||||
@@ -170,7 +166,7 @@ func (app *instanceAppImpl) SaveDbInstance(ctx context.Context, instance *SaveDb
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *instanceAppImpl) Delete(ctx context.Context, instanceId uint64) error {
|
func (app *instanceAppImpl) Delete(ctx context.Context, instanceId uint64) error {
|
||||||
instance, err := app.GetById(new(entity.DbInstance), instanceId, "name")
|
instance, err := app.GetById(instanceId, "name")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorx.NewBiz("获取数据库实例错误,数据库实例ID为: %d", instance.Id)
|
return errorx.NewBiz("获取数据库实例错误,数据库实例ID为: %d", instance.Id)
|
||||||
}
|
}
|
||||||
@@ -201,18 +197,9 @@ func (app *instanceAppImpl) Delete(ctx context.Context, instanceId uint64) error
|
|||||||
biz.ErrIsNil(err, "删除数据库实例失败: %v", err)
|
biz.ErrIsNil(err, "删除数据库实例失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db := &entity.Db{
|
dbs, _ := app.dbApp.ListByCond(&entity.Db{
|
||||||
InstanceId: instanceId,
|
InstanceId: instanceId,
|
||||||
}
|
})
|
||||||
err = app.dbApp.GetByCond(db)
|
|
||||||
switch {
|
|
||||||
case err == nil:
|
|
||||||
biz.ErrNotNil(err, "不能删除数据库实例【%s】,请先删除关联的数据库资源。", instance.Name)
|
|
||||||
case errors.Is(err, gorm.ErrRecordNotFound):
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
biz.ErrIsNil(err, "删除数据库实例失败: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return app.Tx(ctx, func(ctx context.Context) error {
|
return app.Tx(ctx, func(ctx context.Context) error {
|
||||||
return app.DeleteById(ctx, instanceId)
|
return app.DeleteById(ctx, instanceId)
|
||||||
@@ -223,10 +210,18 @@ func (app *instanceAppImpl) Delete(ctx context.Context, instanceId uint64) error
|
|||||||
ResourceType: tagentity.TagType(consts.ResourceTypeDb),
|
ResourceType: tagentity.TagType(consts.ResourceTypeDb),
|
||||||
})
|
})
|
||||||
}, func(ctx context.Context) error {
|
}, func(ctx context.Context) error {
|
||||||
return app.tagApp.DeleteTagByParam(ctx, &tagapp.DelResourceTagParam{
|
return app.tagApp.DeleteTagByParam(ctx, &tagdto.DelResourceTag{
|
||||||
ResourceCode: instance.Code,
|
ResourceCode: instance.Code,
|
||||||
ResourceType: tagentity.TagType(consts.ResourceTypeDb),
|
ResourceType: tagentity.TagType(consts.ResourceTypeDb),
|
||||||
})
|
})
|
||||||
|
}, func(ctx context.Context) error {
|
||||||
|
// 删除所有库配置
|
||||||
|
for _, db := range dbs {
|
||||||
|
if err := app.dbApp.Delete(ctx, db.Id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,25 +271,25 @@ func (app *instanceAppImpl) toDbInfoByAc(instance *entity.DbInstance, ac *tagent
|
|||||||
return di
|
return di
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *instanceAppImpl) genDbInstanceResourceTag(me *entity.DbInstance, authCerts []*tagentity.ResourceAuthCert) *tagapp.ResourceTag {
|
func (m *instanceAppImpl) genDbInstanceResourceTag(me *entity.DbInstance, authCerts []*tagentity.ResourceAuthCert) *tagdto.ResourceTag {
|
||||||
authCertTags := collx.ArrayMap[*tagentity.ResourceAuthCert, *tagapp.ResourceTag](authCerts, func(val *tagentity.ResourceAuthCert) *tagapp.ResourceTag {
|
authCertTags := collx.ArrayMap[*tagentity.ResourceAuthCert, *tagdto.ResourceTag](authCerts, func(val *tagentity.ResourceAuthCert) *tagdto.ResourceTag {
|
||||||
return &tagapp.ResourceTag{
|
return &tagdto.ResourceTag{
|
||||||
Code: val.Name,
|
Code: val.Name,
|
||||||
Name: val.Username,
|
Name: val.Username,
|
||||||
Type: tagentity.TagTypeDbAuthCert,
|
Type: tagentity.TagTypeDbAuthCert,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var dbs []*entity.Db
|
dbs, err := m.dbApp.ListByCond(&entity.Db{
|
||||||
if err := m.dbApp.ListByCond(&entity.Db{
|
|
||||||
InstanceId: me.Id,
|
InstanceId: me.Id,
|
||||||
}, &dbs); err != nil {
|
})
|
||||||
|
if err != nil {
|
||||||
logx.Errorf("获取实例关联的数据库失败: %v", err)
|
logx.Errorf("获取实例关联的数据库失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
authCertName2DbTags := make(map[string][]*tagapp.ResourceTag)
|
authCertName2DbTags := make(map[string][]*tagdto.ResourceTag)
|
||||||
for _, db := range dbs {
|
for _, db := range dbs {
|
||||||
authCertName2DbTags[db.AuthCertName] = append(authCertName2DbTags[db.AuthCertName], &tagapp.ResourceTag{
|
authCertName2DbTags[db.AuthCertName] = append(authCertName2DbTags[db.AuthCertName], &tagdto.ResourceTag{
|
||||||
Code: db.Code,
|
Code: db.Code,
|
||||||
Name: db.Name,
|
Name: db.Name,
|
||||||
Type: tagentity.TagTypeDbName,
|
Type: tagentity.TagTypeDbName,
|
||||||
@@ -306,7 +301,7 @@ func (m *instanceAppImpl) genDbInstanceResourceTag(me *entity.DbInstance, authCe
|
|||||||
ac.Children = authCertName2DbTags[ac.Code]
|
ac.Children = authCertName2DbTags[ac.Code]
|
||||||
}
|
}
|
||||||
|
|
||||||
return &tagapp.ResourceTag{
|
return &tagdto.ResourceTag{
|
||||||
Code: me.Code,
|
Code: me.Code,
|
||||||
Type: tagentity.TagTypeDb,
|
Type: tagentity.TagTypeDb,
|
||||||
Name: me.Name,
|
Name: me.Name,
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ func (app *DbRestoreApp) Enable(ctx context.Context, jobId uint64) error {
|
|||||||
defer app.mutex.Unlock()
|
defer app.mutex.Unlock()
|
||||||
|
|
||||||
repo := app.restoreRepo
|
repo := app.restoreRepo
|
||||||
job := &entity.DbRestore{}
|
job, err := repo.GetById(jobId)
|
||||||
if err := repo.GetById(job, jobId); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if job.IsEnabled() {
|
if job.IsEnabled() {
|
||||||
@@ -101,8 +101,8 @@ func (app *DbRestoreApp) Disable(ctx context.Context, jobId uint64) error {
|
|||||||
defer app.mutex.Unlock()
|
defer app.mutex.Unlock()
|
||||||
|
|
||||||
repo := app.restoreRepo
|
repo := app.restoreRepo
|
||||||
job := &entity.DbRestore{}
|
job, err := repo.GetById(jobId)
|
||||||
if err := repo.GetById(job, jobId); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !job.IsEnabled() {
|
if !job.IsEnabled() {
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/sync/singleflight"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
"mayfly-go/internal/db/dbm/dbi"
|
"mayfly-go/internal/db/dbm/dbi"
|
||||||
"mayfly-go/internal/db/domain/entity"
|
"mayfly-go/internal/db/domain/entity"
|
||||||
"mayfly-go/internal/db/domain/repository"
|
"mayfly-go/internal/db/domain/repository"
|
||||||
@@ -14,6 +12,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sync/singleflight"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -173,8 +174,8 @@ func (s *dbScheduler) restore(ctx context.Context, dbProgram dbi.DbProgram, rest
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
backupHistory := &entity.DbBackupHistory{}
|
backupHistory, err := s.backupHistoryRepo.GetById(restore.DbBackupHistoryId)
|
||||||
if err := s.backupHistoryRepo.GetById(backupHistory, restore.DbBackupHistoryId); err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
err = errors.New("备份历史已删除")
|
err = errors.New("备份历史已删除")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"mayfly-go/internal/db/domain/entity"
|
"mayfly-go/internal/db/domain/entity"
|
||||||
"mayfly-go/internal/db/domain/repository"
|
"mayfly-go/internal/db/domain/repository"
|
||||||
flowapp "mayfly-go/internal/flow/application"
|
flowapp "mayfly-go/internal/flow/application"
|
||||||
|
flowdto "mayfly-go/internal/flow/application/dto"
|
||||||
flowentity "mayfly-go/internal/flow/domain/entity"
|
flowentity "mayfly-go/internal/flow/domain/entity"
|
||||||
"mayfly-go/pkg/contextx"
|
"mayfly-go/pkg/contextx"
|
||||||
"mayfly-go/pkg/errorx"
|
"mayfly-go/pkg/errorx"
|
||||||
@@ -56,7 +57,7 @@ type DbSqlExec interface {
|
|||||||
Exec(ctx context.Context, execSqlReq *DbSqlExecReq) (*DbSqlExecRes, error)
|
Exec(ctx context.Context, execSqlReq *DbSqlExecReq) (*DbSqlExecRes, error)
|
||||||
|
|
||||||
// 根据条件删除sql执行记录
|
// 根据条件删除sql执行记录
|
||||||
DeleteBy(ctx context.Context, condition *entity.DbSqlExec)
|
DeleteBy(ctx context.Context, condition *entity.DbSqlExec) error
|
||||||
|
|
||||||
// 分页获取
|
// 分页获取
|
||||||
GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
||||||
@@ -67,6 +68,7 @@ type dbSqlExecAppImpl struct {
|
|||||||
dbSqlExecRepo repository.DbSqlExec `inject:"DbSqlExecRepo"`
|
dbSqlExecRepo repository.DbSqlExec `inject:"DbSqlExecRepo"`
|
||||||
|
|
||||||
flowProcinstApp flowapp.Procinst `inject:"ProcinstApp"`
|
flowProcinstApp flowapp.Procinst `inject:"ProcinstApp"`
|
||||||
|
flowProcdefApp flowapp.Procdef `inject:"ProcdefApp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSqlExecRecord(ctx context.Context, execSqlReq *DbSqlExecReq) *entity.DbSqlExec {
|
func createSqlExecRecord(ctx context.Context, execSqlReq *DbSqlExecReq) *entity.DbSqlExec {
|
||||||
@@ -196,8 +198,8 @@ func (d *dbSqlExecAppImpl) FlowBizHandle(ctx context.Context, bizHandleParam *fl
|
|||||||
return d.dbSqlExecRepo.UpdateById(ctx, dbSqlExec)
|
return d.dbSqlExecRepo.UpdateById(ctx, dbSqlExec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dbSqlExecAppImpl) DeleteBy(ctx context.Context, condition *entity.DbSqlExec) {
|
func (d *dbSqlExecAppImpl) DeleteBy(ctx context.Context, condition *entity.DbSqlExec) error {
|
||||||
d.dbSqlExecRepo.DeleteByCond(ctx, condition)
|
return d.dbSqlExecRepo.DeleteByCond(ctx, condition)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dbSqlExecAppImpl) GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
|
func (d *dbSqlExecAppImpl) GetPageList(condition *entity.DbSqlExecQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
|
||||||
@@ -348,11 +350,11 @@ func (d *dbSqlExecAppImpl) doInsert(ctx context.Context, insert *sqlparser.Inser
|
|||||||
|
|
||||||
func (d *dbSqlExecAppImpl) doExec(ctx context.Context, execSqlReq *DbSqlExecReq, dbSqlExecRecord *entity.DbSqlExec) (*DbSqlExecRes, error) {
|
func (d *dbSqlExecAppImpl) doExec(ctx context.Context, execSqlReq *DbSqlExecReq, dbSqlExecRecord *entity.DbSqlExec) (*DbSqlExecRes, error) {
|
||||||
dbConn := execSqlReq.DbConn
|
dbConn := execSqlReq.DbConn
|
||||||
flowProcdefKey := dbConn.Info.FlowProcdefKey
|
|
||||||
if flowProcdefKey != "" {
|
if flowProcdefId := d.flowProcdefApp.GetProcdefIdByCodePath(ctx, dbConn.Info.CodePath...); flowProcdefId != 0 {
|
||||||
bizKey := stringx.Rand(24)
|
bizKey := stringx.Rand(24)
|
||||||
// 如果该库关联了审批流程,则启动流程实例即可
|
// 如果该库关联了审批流程,则启动流程实例即可
|
||||||
_, err := d.flowProcinstApp.StartProc(ctx, flowProcdefKey, &flowapp.StarProcParam{
|
_, err := d.flowProcinstApp.StartProc(ctx, flowProcdefId, &flowdto.StarProc{
|
||||||
BizType: DbSqlExecFlowBizType,
|
BizType: DbSqlExecFlowBizType,
|
||||||
BizKey: bizKey,
|
BizKey: bizKey,
|
||||||
Remark: dbSqlExecRecord.Remark,
|
Remark: dbSqlExecRecord.Remark,
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func (app *dbTransferAppImpl) CreateLog(ctx context.Context, taskId uint64) (uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *dbTransferAppImpl) Run(ctx context.Context, taskId uint64, logId uint64) {
|
func (app *dbTransferAppImpl) Run(ctx context.Context, taskId uint64, logId uint64) {
|
||||||
task, err := app.GetById(new(entity.DbTransferTask), taskId)
|
task, err := app.GetById(taskId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.Errorf("创建DBMS-执行数据迁移日志失败:%v", err)
|
logx.Errorf("创建DBMS-执行数据迁移日志失败:%v", err)
|
||||||
return
|
return
|
||||||
@@ -150,7 +150,7 @@ func (app *dbTransferAppImpl) Run(ctx context.Context, taskId uint64, logId uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *dbTransferAppImpl) Stop(ctx context.Context, taskId uint64) error {
|
func (app *dbTransferAppImpl) Stop(ctx context.Context, taskId uint64) error {
|
||||||
task, err := app.GetById(new(entity.DbTransferTask), taskId)
|
task, err := app.GetById(taskId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorx.NewBiz("任务不存在")
|
return errorx.NewBiz("任务不存在")
|
||||||
}
|
}
|
||||||
|
|||||||
23
server/internal/db/application/dto/dto.go
Normal file
23
server/internal/db/application/dto/dto.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package dto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"mayfly-go/internal/db/domain/entity"
|
||||||
|
tagentity "mayfly-go/internal/tag/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SaveDbInstance struct {
|
||||||
|
DbInstance *entity.DbInstance
|
||||||
|
AuthCerts []*tagentity.ResourceAuthCert
|
||||||
|
TagCodePaths []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type DumpDb struct {
|
||||||
|
DbId uint64
|
||||||
|
DbName string
|
||||||
|
Tables []string
|
||||||
|
DumpDDL bool // 是否dump ddl
|
||||||
|
DumpData bool // 是否dump data
|
||||||
|
|
||||||
|
Writer io.Writer
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package application
|
|
||||||
|
|
||||||
import "io"
|
|
||||||
|
|
||||||
type DumpDbReq struct {
|
|
||||||
DbId uint64
|
|
||||||
DbName string
|
|
||||||
Tables []string
|
|
||||||
DumpDDL bool // 是否dump ddl
|
|
||||||
DumpData bool // 是否dump data
|
|
||||||
|
|
||||||
Writer io.Writer
|
|
||||||
}
|
|
||||||
@@ -47,8 +47,7 @@ type DbInfo struct {
|
|||||||
Params string
|
Params string
|
||||||
Database string // 若有schema的库则为'database/scheam'格式
|
Database string // 若有schema的库则为'database/scheam'格式
|
||||||
|
|
||||||
FlowProcdefKey string // 流程定义key
|
CodePath []string
|
||||||
TagPath []string
|
|
||||||
SshTunnelMachineId int
|
SshTunnelMachineId int
|
||||||
|
|
||||||
Meta Meta
|
Meta Meta
|
||||||
@@ -56,7 +55,7 @@ type DbInfo struct {
|
|||||||
|
|
||||||
// 获取记录日志的描述
|
// 获取记录日志的描述
|
||||||
func (d *DbInfo) GetLogDesc() string {
|
func (d *DbInfo) GetLogDesc() string {
|
||||||
return fmt.Sprintf("DB[id=%d, tag=%s, name=%s, ip=%s:%d, database=%s]", d.Id, d.TagPath, d.Name, d.Host, d.Port, d.Database)
|
return fmt.Sprintf("DB[id=%d, tag=%s, name=%s, ip=%s:%d, database=%s]", d.Id, d.CodePath, d.Name, d.Host, d.Port, d.Database)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 连接数据库
|
// 连接数据库
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ func (md *MysqlDialect) BatchInsert(tx *sql.Tx, tableName string, columns []stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (md *MysqlDialect) CopyTable(copy *dbi.DbCopyTable) error {
|
func (md *MysqlDialect) CopyTable(copy *dbi.DbCopyTable) error {
|
||||||
|
|
||||||
tableName := copy.TableName
|
tableName := copy.TableName
|
||||||
|
|
||||||
// 生成新表名,为老表明+_copy_时间戳
|
// 生成新表名,为老表明+_copy_时间戳
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ func (md *MysqlMetaData) GenerateTableDDL(columns []dbi.Column, tableInfo dbi.Ta
|
|||||||
sqlArr := make([]string, 0)
|
sqlArr := make([]string, 0)
|
||||||
|
|
||||||
if dropBeforeCreate {
|
if dropBeforeCreate {
|
||||||
sqlArr = append(sqlArr, fmt.Sprintf("DROP TABLE IF EXISTS %s;", meta.QuoteIdentifier(tableInfo.TableName)))
|
sqlArr = append(sqlArr, fmt.Sprintf("DROP TABLE IF EXISTS %s", meta.QuoteIdentifier(tableInfo.TableName)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 组装建表语句
|
// 组装建表语句
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ import (
|
|||||||
type Db struct {
|
type Db struct {
|
||||||
model.Model
|
model.Model
|
||||||
|
|
||||||
Code string `orm:"column(code)" json:"code"`
|
Code string `orm:"column(code)" json:"code"`
|
||||||
Name string `orm:"column(name)" json:"name"`
|
Name string `orm:"column(name)" json:"name"`
|
||||||
Database string `orm:"column(database)" json:"database"`
|
Database string `orm:"column(database)" json:"database"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
InstanceId uint64
|
InstanceId uint64
|
||||||
AuthCertName string `json:"authCertName"`
|
AuthCertName string `json:"authCertName"`
|
||||||
FlowProcdefKey *string `json:"flowProcdefKey"` // 审批流-流程定义key(有值则说明关键操作需要进行审批执行),使用指针为了方便更新空字符串(取消流程审批)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,4 @@ type DbBackup interface {
|
|||||||
|
|
||||||
// GetPageList 分页获取数据库任务列表
|
// GetPageList 分页获取数据库任务列表
|
||||||
GetPageList(condition *entity.DbBackupQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
GetPageList(condition *entity.DbBackupQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
||||||
|
|
||||||
ListByCond(cond any, listModels any, cols ...string) error
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func NewDbBackupRepo() repository.DbBackup {
|
|||||||
|
|
||||||
func (d *dbBackupRepoImpl) GetDbNamesWithoutBackup(instanceId uint64, dbNames []string) ([]string, error) {
|
func (d *dbBackupRepoImpl) GetDbNamesWithoutBackup(instanceId uint64, dbNames []string) ([]string, error) {
|
||||||
var dbNamesWithBackup []string
|
var dbNamesWithBackup []string
|
||||||
err := global.Db.Model(d.GetModel()).
|
err := global.Db.Model(d.NewModel()).
|
||||||
Where("db_instance_id = ?", instanceId).
|
Where("db_instance_id = ?", instanceId).
|
||||||
Where("repeated = ?", true).
|
Where("repeated = ?", true).
|
||||||
Scopes(gormx.UndeleteScope).
|
Scopes(gormx.UndeleteScope).
|
||||||
@@ -41,7 +41,7 @@ func (d *dbBackupRepoImpl) GetDbNamesWithoutBackup(instanceId uint64, dbNames []
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *dbBackupRepoImpl) ListDbInstances(enabled bool, repeated bool, instanceIds *[]uint64) error {
|
func (d *dbBackupRepoImpl) ListDbInstances(enabled bool, repeated bool, instanceIds *[]uint64) error {
|
||||||
return global.Db.Model(d.GetModel()).
|
return global.Db.Model(d.NewModel()).
|
||||||
Where("enabled = ?", enabled).
|
Where("enabled = ?", enabled).
|
||||||
Where("repeated = ?", repeated).
|
Where("repeated = ?", repeated).
|
||||||
Scopes(gormx.UndeleteScope).
|
Scopes(gormx.UndeleteScope).
|
||||||
@@ -51,7 +51,7 @@ func (d *dbBackupRepoImpl) ListDbInstances(enabled bool, repeated bool, instance
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *dbBackupRepoImpl) ListToDo(jobs any) error {
|
func (d *dbBackupRepoImpl) ListToDo(jobs any) error {
|
||||||
db := global.Db.Model(d.GetModel())
|
db := global.Db.Model(d.NewModel())
|
||||||
err := db.Where("enabled = ?", true).
|
err := db.Where("enabled = ?", true).
|
||||||
Where(db.Where("repeated = ?", true).Or("last_status <> ?", entity.DbJobSuccess)).
|
Where(db.Where("repeated = ?", true).Or("last_status <> ?", entity.DbJobSuccess)).
|
||||||
Scopes(gormx.UndeleteScope).
|
Scopes(gormx.UndeleteScope).
|
||||||
@@ -70,7 +70,7 @@ func (d *dbBackupRepoImpl) GetPageList(condition *entity.DbBackupQuery, pagePara
|
|||||||
Eq0("repeated", condition.Repeated).
|
Eq0("repeated", condition.Repeated).
|
||||||
In0("db_name", condition.InDbNames).
|
In0("db_name", condition.InDbNames).
|
||||||
Like("db_name", condition.DbName)
|
Like("db_name", condition.DbName)
|
||||||
return d.PageByCond(qd, pageParam, toEntity)
|
return d.PageByCondToAny(qd, pageParam, toEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddJob 添加数据库任务
|
// AddJob 添加数据库任务
|
||||||
@@ -91,7 +91,3 @@ func (d *dbBackupRepoImpl) UpdateEnabled(ctx context.Context, jobId uint64, enab
|
|||||||
"enabled_desc": desc,
|
"enabled_desc": desc,
|
||||||
}, cond)
|
}, cond)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dbBackupRepoImpl) ListByCond(cond any, listModels any, cols ...string) error {
|
|
||||||
return d.dbJobBaseImpl.SelectByCond(model.NewModelCond(cond).Columns(cols...), listModels)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ func (repo *dbBackupHistoryRepoImpl) GetPageList(condition *entity.DbBackupHisto
|
|||||||
In0("db_name", condition.InDbNames).
|
In0("db_name", condition.InDbNames).
|
||||||
Eq("db_backup_id", condition.DbBackupId).
|
Eq("db_backup_id", condition.DbBackupId).
|
||||||
Eq("db_name", condition.DbName)
|
Eq("db_name", condition.DbName)
|
||||||
return repo.PageByCond(qd, pageParam, toEntity)
|
return repo.PageByCondToAny(qd, pageParam, toEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *dbBackupHistoryRepoImpl) GetHistories(backupHistoryIds []uint64, toEntity any) error {
|
func (repo *dbBackupHistoryRepoImpl) GetHistories(backupHistoryIds []uint64, toEntity any) error {
|
||||||
return global.Db.Model(repo.GetModel()).
|
return global.Db.Model(repo.NewModel()).
|
||||||
Where("id in ?", backupHistoryIds).
|
Where("id in ?", backupHistoryIds).
|
||||||
Where("deleting = false").
|
Where("deleting = false").
|
||||||
Scopes(gormx.UndeleteScope).
|
Scopes(gormx.UndeleteScope).
|
||||||
@@ -44,7 +44,7 @@ func (repo *dbBackupHistoryRepoImpl) GetHistories(backupHistoryIds []uint64, toE
|
|||||||
func (repo *dbBackupHistoryRepoImpl) GetLatestHistoryForBinlog(instanceId uint64, dbName string, bi *entity.BinlogInfo) (*entity.DbBackupHistory, error) {
|
func (repo *dbBackupHistoryRepoImpl) GetLatestHistoryForBinlog(instanceId uint64, dbName string, bi *entity.BinlogInfo) (*entity.DbBackupHistory, error) {
|
||||||
history := &entity.DbBackupHistory{}
|
history := &entity.DbBackupHistory{}
|
||||||
db := global.Db
|
db := global.Db
|
||||||
err := db.Model(repo.GetModel()).
|
err := db.Model(repo.NewModel()).
|
||||||
Where("db_instance_id = ?", instanceId).
|
Where("db_instance_id = ?", instanceId).
|
||||||
Where("db_name = ?", dbName).
|
Where("db_name = ?", dbName).
|
||||||
Where(db.Where("binlog_sequence < ?", bi.Sequence).
|
Where(db.Where("binlog_sequence < ?", bi.Sequence).
|
||||||
@@ -63,7 +63,7 @@ func (repo *dbBackupHistoryRepoImpl) GetLatestHistoryForBinlog(instanceId uint64
|
|||||||
|
|
||||||
func (repo *dbBackupHistoryRepoImpl) GetEarliestHistoryForBinlog(instanceId uint64) (*entity.DbBackupHistory, bool, error) {
|
func (repo *dbBackupHistoryRepoImpl) GetEarliestHistoryForBinlog(instanceId uint64) (*entity.DbBackupHistory, bool, error) {
|
||||||
history := &entity.DbBackupHistory{}
|
history := &entity.DbBackupHistory{}
|
||||||
db := global.Db.Model(repo.GetModel())
|
db := global.Db.Model(repo.NewModel())
|
||||||
err := db.Where("db_instance_id = ?", instanceId).
|
err := db.Where("db_instance_id = ?", instanceId).
|
||||||
Where("binlog_sequence > 0").
|
Where("binlog_sequence > 0").
|
||||||
Where("deleting = false").
|
Where("deleting = false").
|
||||||
@@ -81,7 +81,7 @@ func (repo *dbBackupHistoryRepoImpl) GetEarliestHistoryForBinlog(instanceId uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (repo *dbBackupHistoryRepoImpl) UpdateDeleting(deleting bool, backupHistoryId ...uint64) (bool, error) {
|
func (repo *dbBackupHistoryRepoImpl) UpdateDeleting(deleting bool, backupHistoryId ...uint64) (bool, error) {
|
||||||
db := global.Db.Model(repo.GetModel()).
|
db := global.Db.Model(repo.NewModel()).
|
||||||
Where("id in ?", backupHistoryId).
|
Where("id in ?", backupHistoryId).
|
||||||
Where("restoring = false").
|
Where("restoring = false").
|
||||||
Scopes(gormx.UndeleteScope).
|
Scopes(gormx.UndeleteScope).
|
||||||
@@ -96,7 +96,7 @@ func (repo *dbBackupHistoryRepoImpl) UpdateDeleting(deleting bool, backupHistory
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (repo *dbBackupHistoryRepoImpl) UpdateRestoring(restoring bool, backupHistoryId ...uint64) (bool, error) {
|
func (repo *dbBackupHistoryRepoImpl) UpdateRestoring(restoring bool, backupHistoryId ...uint64) (bool, error) {
|
||||||
db := global.Db.Model(repo.GetModel()).
|
db := global.Db.Model(repo.NewModel()).
|
||||||
Where("id in ?", backupHistoryId).
|
Where("id in ?", backupHistoryId).
|
||||||
Where("deleting = false").
|
Where("deleting = false").
|
||||||
Scopes(gormx.UndeleteScope).
|
Scopes(gormx.UndeleteScope).
|
||||||
@@ -111,7 +111,7 @@ func (repo *dbBackupHistoryRepoImpl) UpdateRestoring(restoring bool, backupHisto
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (repo *dbBackupHistoryRepoImpl) ZeroBinlogInfo(backupHistoryId uint64) error {
|
func (repo *dbBackupHistoryRepoImpl) ZeroBinlogInfo(backupHistoryId uint64) error {
|
||||||
return global.Db.Model(repo.GetModel()).
|
return global.Db.Model(repo.NewModel()).
|
||||||
Where("id = ?", backupHistoryId).
|
Where("id = ?", backupHistoryId).
|
||||||
Where("restoring = false").
|
Where("restoring = false").
|
||||||
Scopes(gormx.UndeleteScope).
|
Scopes(gormx.UndeleteScope).
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ func (repo *dbBinlogHistoryRepoImpl) GetHistories(instanceId uint64, start, targ
|
|||||||
Ge("sequence", start.Sequence).
|
Ge("sequence", start.Sequence).
|
||||||
Le("sequence", target.Sequence).
|
Le("sequence", target.Sequence).
|
||||||
OrderByAsc("sequence")
|
OrderByAsc("sequence")
|
||||||
var histories []*entity.DbBinlogHistory
|
histories, err := repo.SelectByCond(qc)
|
||||||
if err := repo.SelectByCond(qc, &histories); err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(histories) == 0 {
|
if len(histories) == 0 {
|
||||||
@@ -121,7 +121,7 @@ func (repo *dbBinlogHistoryRepoImpl) InsertWithBinlogFiles(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (repo *dbBinlogHistoryRepoImpl) GetHistoriesBeforeSequence(ctx context.Context, instanceId uint64, binlogSeq int64, histories *[]*entity.DbBinlogHistory) error {
|
func (repo *dbBinlogHistoryRepoImpl) GetHistoriesBeforeSequence(ctx context.Context, instanceId uint64, binlogSeq int64, histories *[]*entity.DbBinlogHistory) error {
|
||||||
return global.Db.Model(repo.GetModel()).
|
return global.Db.Model(repo.NewModel()).
|
||||||
Where("db_instance_id = ?", instanceId).
|
Where("db_instance_id = ?", instanceId).
|
||||||
Where("sequence < ?", binlogSeq).
|
Where("sequence < ?", binlogSeq).
|
||||||
Scopes(gormx.UndeleteScope).
|
Scopes(gormx.UndeleteScope).
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func (d *dataSyncTaskRepoImpl) GetTaskList(condition *entity.DataSyncTaskQuery,
|
|||||||
qd := model.NewCond().
|
qd := model.NewCond().
|
||||||
Like("task_name", condition.Name).
|
Like("task_name", condition.Name).
|
||||||
Eq("status", condition.Status)
|
Eq("status", condition.Status)
|
||||||
return d.PageByCond(qd, pageParam, toEntity)
|
return d.PageByCondToAny(qd, pageParam, toEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
type dataSyncLogRepoImpl struct {
|
type dataSyncLogRepoImpl struct {
|
||||||
@@ -31,7 +31,7 @@ type dataSyncLogRepoImpl struct {
|
|||||||
func (d *dataSyncLogRepoImpl) GetTaskLogList(condition *entity.DataSyncLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
|
func (d *dataSyncLogRepoImpl) GetTaskLogList(condition *entity.DataSyncLogQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
|
||||||
qd := model.NewCond().
|
qd := model.NewCond().
|
||||||
Eq("task_id", condition.TaskId)
|
Eq("task_id", condition.TaskId)
|
||||||
return d.PageByCond(qd, pageParam, toEntity)
|
return d.PageByCondToAny(qd, pageParam, toEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDataSyncLogRepo() repository.DataSyncLog {
|
func newDataSyncLogRepo() repository.DataSyncLog {
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func addJob[T entity.DbJob](ctx context.Context, repo dbJobBaseImpl[T], jobs any
|
|||||||
}
|
}
|
||||||
|
|
||||||
var res []string
|
var res []string
|
||||||
err := db.Model(repo.GetModel()).Select("db_name").
|
err := db.Model(repo.NewModel()).Select("db_name").
|
||||||
Where("db_instance_id = ?", instanceId).
|
Where("db_instance_id = ?", instanceId).
|
||||||
Where("db_name in ?", dbNames).
|
Where("db_name in ?", dbNames).
|
||||||
Where("repeated = true").
|
Where("repeated = true").
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func NewDbRestoreRepo() repository.DbRestore {
|
|||||||
|
|
||||||
func (d *dbRestoreRepoImpl) GetDbNamesWithoutRestore(instanceId uint64, dbNames []string) ([]string, error) {
|
func (d *dbRestoreRepoImpl) GetDbNamesWithoutRestore(instanceId uint64, dbNames []string) ([]string, error) {
|
||||||
var dbNamesWithRestore []string
|
var dbNamesWithRestore []string
|
||||||
err := global.Db.Model(d.GetModel()).
|
err := global.Db.Model(d.NewModel()).
|
||||||
Where("db_instance_id = ?", instanceId).
|
Where("db_instance_id = ?", instanceId).
|
||||||
Where("repeated = ?", true).
|
Where("repeated = ?", true).
|
||||||
Scopes(gormx.UndeleteScope).
|
Scopes(gormx.UndeleteScope).
|
||||||
@@ -42,7 +42,7 @@ func (d *dbRestoreRepoImpl) GetDbNamesWithoutRestore(instanceId uint64, dbNames
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *dbRestoreRepoImpl) ListToDo(jobs any) error {
|
func (d *dbRestoreRepoImpl) ListToDo(jobs any) error {
|
||||||
db := global.Db.Model(d.GetModel())
|
db := global.Db.Model(d.NewModel())
|
||||||
err := db.Where("enabled = ?", true).
|
err := db.Where("enabled = ?", true).
|
||||||
Where(db.Where("repeated = ?", true).Or("last_status <> ?", entity.DbJobSuccess)).
|
Where(db.Where("repeated = ?", true).Or("last_status <> ?", entity.DbJobSuccess)).
|
||||||
Scopes(gormx.UndeleteScope).
|
Scopes(gormx.UndeleteScope).
|
||||||
@@ -61,11 +61,11 @@ func (d *dbRestoreRepoImpl) GetPageList(condition *entity.DbRestoreQuery, pagePa
|
|||||||
Eq0("repeated", condition.Repeated).
|
Eq0("repeated", condition.Repeated).
|
||||||
In0("db_name", condition.InDbNames).
|
In0("db_name", condition.InDbNames).
|
||||||
Like("db_name", condition.DbName)
|
Like("db_name", condition.DbName)
|
||||||
return d.PageByCond(qd, pageParam, toEntity)
|
return d.PageByCondToAny(qd, pageParam, toEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dbRestoreRepoImpl) GetEnabledRestores(toEntity any, backupHistoryId ...uint64) error {
|
func (d *dbRestoreRepoImpl) GetEnabledRestores(toEntity any, backupHistoryId ...uint64) error {
|
||||||
return global.Db.Model(d.GetModel()).
|
return global.Db.Model(d.NewModel()).
|
||||||
Select("id", "db_backup_history_id", "last_status", "last_result", "last_time").
|
Select("id", "db_backup_history_id", "last_status", "last_result", "last_time").
|
||||||
Where("db_backup_history_id in ?", backupHistoryId).
|
Where("db_backup_history_id in ?", backupHistoryId).
|
||||||
Where("enabled = true").
|
Where("enabled = true").
|
||||||
|
|||||||
@@ -21,6 +21,6 @@ func (d *dbRestoreHistoryRepoImpl) GetDbRestoreHistories(condition *entity.DbRes
|
|||||||
qd := model.NewCond().
|
qd := model.NewCond().
|
||||||
Eq("id", condition.Id).
|
Eq("id", condition.Id).
|
||||||
Eq("db_backup_id", condition.DbRestoreId)
|
Eq("db_backup_id", condition.DbRestoreId)
|
||||||
return d.PageByCond(qd, pageParam, toEntity)
|
return d.PageByCondToAny(qd, pageParam, toEntity)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,5 +25,5 @@ func (d *dbSqlExecRepoImpl) GetPageList(condition *entity.DbSqlExecQuery, pagePa
|
|||||||
Eq("flow_biz_key", condition.FlowBizKey).
|
Eq("flow_biz_key", condition.FlowBizKey).
|
||||||
In("status", condition.Status).
|
In("status", condition.Status).
|
||||||
RLike("db", condition.Db).OrderBy(orderBy...)
|
RLike("db", condition.Db).OrderBy(orderBy...)
|
||||||
return d.PageByCond(qd, pageParam, toEntity)
|
return d.PageByCondToAny(qd, pageParam, toEntity)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,5 +20,5 @@ func (d *dbTransferTaskRepoImpl) GetTaskList(condition *entity.DbTransferTaskQue
|
|||||||
qd := model.NewCond()
|
qd := model.NewCond()
|
||||||
//Like("task_name", condition.Name).
|
//Like("task_name", condition.Name).
|
||||||
//Eq("status", condition.Status)
|
//Eq("status", condition.Status)
|
||||||
return d.PageByCond(qd, pageParam, toEntity)
|
return d.PageByCondToAny(qd, pageParam, toEntity)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,5 +23,5 @@ func (d *instanceRepoImpl) GetInstanceList(condition *entity.InstanceQuery, page
|
|||||||
Like("name", condition.Name).
|
Like("name", condition.Name).
|
||||||
Like("code", condition.Code).
|
Like("code", condition.Code).
|
||||||
In("code", condition.Codes)
|
In("code", condition.Codes)
|
||||||
return d.PageByCond(qd, pageParam, toEntity)
|
return d.PageByCondToAny(qd, pageParam, toEntity)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,4 +9,6 @@ type Procdef struct {
|
|||||||
Tasks string `json:"tasks" binding:"required"` // 审批节点任务信息
|
Tasks string `json:"tasks" binding:"required"` // 审批节点任务信息
|
||||||
Status entity.ProcdefStatus `json:"status" binding:"required"`
|
Status entity.ProcdefStatus `json:"status" binding:"required"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
|
|
||||||
|
CodePaths []string `json:"codePaths"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,39 +2,51 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"mayfly-go/internal/flow/api/form"
|
"mayfly-go/internal/flow/api/form"
|
||||||
|
"mayfly-go/internal/flow/api/vo"
|
||||||
"mayfly-go/internal/flow/application"
|
"mayfly-go/internal/flow/application"
|
||||||
|
"mayfly-go/internal/flow/application/dto"
|
||||||
"mayfly-go/internal/flow/domain/entity"
|
"mayfly-go/internal/flow/domain/entity"
|
||||||
|
tagapp "mayfly-go/internal/tag/application"
|
||||||
|
tagentity "mayfly-go/internal/tag/domain/entity"
|
||||||
"mayfly-go/pkg/biz"
|
"mayfly-go/pkg/biz"
|
||||||
"mayfly-go/pkg/req"
|
"mayfly-go/pkg/req"
|
||||||
|
"mayfly-go/pkg/utils/collx"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Procdef struct {
|
type Procdef struct {
|
||||||
ProcdefApp application.Procdef `inject:""`
|
ProcdefApp application.Procdef `inject:""`
|
||||||
|
TagTreeRelateApp tagapp.TagTreeRelate `inject:"TagTreeRelateApp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Procdef) GetProcdefPage(rc *req.Ctx) {
|
func (p *Procdef) GetProcdefPage(rc *req.Ctx) {
|
||||||
cond, page := req.BindQueryAndPage(rc, new(entity.Procdef))
|
cond, page := req.BindQueryAndPage(rc, new(entity.Procdef))
|
||||||
res, err := p.ProcdefApp.GetPageList(cond, page, new([]entity.Procdef))
|
var procdefs []*vo.Procdef
|
||||||
|
res, err := p.ProcdefApp.GetPageList(cond, page, &procdefs)
|
||||||
biz.ErrIsNil(err)
|
biz.ErrIsNil(err)
|
||||||
|
|
||||||
|
p.TagTreeRelateApp.FillTagInfo(tagentity.TagRelateTypeFlowDef, collx.ArrayMap(procdefs, func(mvo *vo.Procdef) tagentity.IRelateTag {
|
||||||
|
return mvo
|
||||||
|
})...)
|
||||||
|
|
||||||
rc.ResData = res
|
rc.ResData = res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Procdef) GetProcdef(rc *req.Ctx) {
|
func (p *Procdef) GetProcdef(rc *req.Ctx) {
|
||||||
defkey := rc.PathParam("key")
|
resourceType := rc.PathParamInt("resourceType")
|
||||||
biz.NotEmpty(defkey, "流程定义key不能为空")
|
resourceCode := rc.PathParam("resourceCode")
|
||||||
|
rc.ResData = p.ProcdefApp.GetProcdefByResource(rc.MetaCtx, int8(resourceType), resourceCode)
|
||||||
procdef := &entity.Procdef{DefKey: defkey}
|
|
||||||
biz.ErrIsNil(p.ProcdefApp.GetByCond(procdef), "该流程定义不存在")
|
|
||||||
rc.ResData = procdef
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Procdef) Save(rc *req.Ctx) {
|
func (a *Procdef) Save(rc *req.Ctx) {
|
||||||
form := &form.Procdef{}
|
form := &form.Procdef{}
|
||||||
procdef := req.BindJsonAndCopyTo(rc, form, new(entity.Procdef))
|
procdef := req.BindJsonAndCopyTo(rc, form, new(entity.Procdef))
|
||||||
rc.ReqParam = form
|
rc.ReqParam = form
|
||||||
biz.ErrIsNil(a.ProcdefApp.Save(rc.MetaCtx, procdef))
|
biz.ErrIsNil(a.ProcdefApp.SaveProcdef(rc.MetaCtx, &dto.SaveProcdef{
|
||||||
|
Procdef: procdef,
|
||||||
|
CodePaths: form.CodePaths,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Procdef) Delete(rc *req.Ctx) {
|
func (p *Procdef) Delete(rc *req.Ctx) {
|
||||||
|
|||||||
@@ -40,19 +40,19 @@ func (p *Procinst) ProcinstCancel(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Procinst) GetProcinstDetail(rc *req.Ctx) {
|
func (p *Procinst) GetProcinstDetail(rc *req.Ctx) {
|
||||||
pi, err := p.ProcinstApp.GetById(new(entity.Procinst), uint64(rc.PathParamInt("id")))
|
pi, err := p.ProcinstApp.GetById(uint64(rc.PathParamInt("id")))
|
||||||
biz.ErrIsNil(err, "流程实例不存在")
|
biz.ErrIsNil(err, "流程实例不存在")
|
||||||
pivo := new(vo.ProcinstVO)
|
pivo := new(vo.ProcinstVO)
|
||||||
structx.Copy(pivo, pi)
|
structx.Copy(pivo, pi)
|
||||||
|
|
||||||
// 流程定义信息
|
// 流程定义信息
|
||||||
procdef, _ := p.ProcdefApp.GetById(new(entity.Procdef), pi.ProcdefId)
|
procdef, _ := p.ProcdefApp.GetById(pi.ProcdefId)
|
||||||
pivo.Procdef = procdef
|
pivo.Procdef = procdef
|
||||||
|
|
||||||
// 流程实例任务信息
|
// 流程实例任务信息
|
||||||
instTasks := new([]*entity.ProcinstTask)
|
instTasks, err := p.ProcinstTaskRepo.SelectByCond(&entity.ProcinstTask{ProcinstId: pi.Id})
|
||||||
biz.ErrIsNil(p.ProcinstTaskRepo.SelectByCond(&entity.ProcinstTask{ProcinstId: pi.Id}, instTasks))
|
biz.ErrIsNil(err)
|
||||||
pivo.ProcinstTasks = *instTasks
|
pivo.ProcinstTasks = instTasks
|
||||||
|
|
||||||
rc.ResData = pivo
|
rc.ResData = pivo
|
||||||
}
|
}
|
||||||
@@ -69,9 +69,8 @@ func (p *Procinst) GetTasks(rc *req.Ctx) {
|
|||||||
biz.ErrIsNil(err)
|
biz.ErrIsNil(err)
|
||||||
|
|
||||||
instIds := collx.ArrayMap[*vo.ProcinstTask, uint64](*taskVos, func(val *vo.ProcinstTask) uint64 { return val.ProcinstId })
|
instIds := collx.ArrayMap[*vo.ProcinstTask, uint64](*taskVos, func(val *vo.ProcinstTask) uint64 { return val.ProcinstId })
|
||||||
insts := new([]*entity.Procinst)
|
insts, _ := p.ProcinstApp.GetByIds(instIds)
|
||||||
p.ProcinstApp.GetByIds(insts, instIds)
|
instId2Inst := collx.ArrayToMap[*entity.Procinst, uint64](insts, func(val *entity.Procinst) uint64 { return val.Id })
|
||||||
instId2Inst := collx.ArrayToMap[*entity.Procinst, uint64](*insts, func(val *entity.Procinst) uint64 { return val.Id })
|
|
||||||
|
|
||||||
// 赋值任务对应的流程实例
|
// 赋值任务对应的流程实例
|
||||||
for _, task := range *taskVos {
|
for _, task := range *taskVos {
|
||||||
|
|||||||
15
server/internal/flow/api/vo/procdef.go
Normal file
15
server/internal/flow/api/vo/procdef.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package vo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"mayfly-go/internal/flow/domain/entity"
|
||||||
|
tagentity "mayfly-go/internal/tag/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Procdef struct {
|
||||||
|
tagentity.RelateTags // 标签信息
|
||||||
|
entity.Procdef
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Procdef) GetRelateId() uint64 {
|
||||||
|
return p.Id
|
||||||
|
}
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
package application
|
package dto
|
||||||
|
|
||||||
|
import "mayfly-go/internal/flow/domain/entity"
|
||||||
|
|
||||||
|
type SaveProcdef struct {
|
||||||
|
Procdef *entity.Procdef
|
||||||
|
CodePaths []string
|
||||||
|
}
|
||||||
|
|
||||||
// 启动流程实例请求入参
|
// 启动流程实例请求入参
|
||||||
type StarProcParam struct {
|
type StarProc struct {
|
||||||
BizType string // 业务类型
|
BizType string // 业务类型
|
||||||
BizKey string // 业务key
|
BizKey string // 业务key
|
||||||
Remark string // 备注
|
Remark string // 备注
|
||||||
BizForm string // 业务表单信息
|
BizForm string // 业务表单信息
|
||||||
}
|
}
|
||||||
|
|
||||||
type CompleteProcinstTaskParam struct {
|
|
||||||
TaskId uint64
|
|
||||||
Remark string // 备注
|
|
||||||
}
|
|
||||||
@@ -2,8 +2,11 @@ package application
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"mayfly-go/internal/flow/application/dto"
|
||||||
"mayfly-go/internal/flow/domain/entity"
|
"mayfly-go/internal/flow/domain/entity"
|
||||||
"mayfly-go/internal/flow/domain/repository"
|
"mayfly-go/internal/flow/domain/repository"
|
||||||
|
tagapp "mayfly-go/internal/tag/application"
|
||||||
|
tagentity "mayfly-go/internal/tag/domain/entity"
|
||||||
"mayfly-go/pkg/base"
|
"mayfly-go/pkg/base"
|
||||||
"mayfly-go/pkg/errorx"
|
"mayfly-go/pkg/errorx"
|
||||||
"mayfly-go/pkg/model"
|
"mayfly-go/pkg/model"
|
||||||
@@ -15,18 +18,29 @@ type Procdef interface {
|
|||||||
GetPageList(condition *entity.Procdef, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
GetPageList(condition *entity.Procdef, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
||||||
|
|
||||||
// 保存流程实例信息
|
// 保存流程实例信息
|
||||||
Save(ctx context.Context, def *entity.Procdef) error
|
SaveProcdef(ctx context.Context, def *dto.SaveProcdef) error
|
||||||
|
|
||||||
// 删除流程实例信息
|
// 删除流程实例信息
|
||||||
DeleteProcdef(ctx context.Context, defId uint64) error
|
DeleteProcdef(ctx context.Context, defId uint64) error
|
||||||
|
|
||||||
|
// GetProcdefIdByCodePath 根据资源编号路径获取对应的流程定义id
|
||||||
|
GetProcdefIdByCodePath(ctx context.Context, codePaths ...string) uint64
|
||||||
|
|
||||||
|
// GetProcdefByResource 根据资源获取对应的流程定义
|
||||||
|
GetProcdefByResource(ctx context.Context, resourceType int8, resourceCode string) *entity.Procdef
|
||||||
}
|
}
|
||||||
|
|
||||||
type procdefAppImpl struct {
|
type procdefAppImpl struct {
|
||||||
base.AppImpl[*entity.Procdef, repository.Procdef]
|
base.AppImpl[*entity.Procdef, repository.Procdef]
|
||||||
|
|
||||||
procinstApp Procinst `inject:"ProcinstApp"`
|
procinstApp Procinst `inject:"ProcinstApp"`
|
||||||
|
|
||||||
|
tagTreeApp tagapp.TagTree `inject:"TagTreeApp"`
|
||||||
|
tagTreeRelateApp tagapp.TagTreeRelate `inject:"TagTreeRelateApp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ (Procdef) = (*procdefAppImpl)(nil)
|
||||||
|
|
||||||
// 注入repo
|
// 注入repo
|
||||||
func (p *procdefAppImpl) InjectProcdefRepo(procdefRepo repository.Procdef) {
|
func (p *procdefAppImpl) InjectProcdefRepo(procdefRepo repository.Procdef) {
|
||||||
p.Repo = procdefRepo
|
p.Repo = procdefRepo
|
||||||
@@ -36,24 +50,29 @@ func (p *procdefAppImpl) GetPageList(condition *entity.Procdef, pageParam *model
|
|||||||
return p.Repo.GetPageList(condition, pageParam, toEntity, orderBy...)
|
return p.Repo.GetPageList(condition, pageParam, toEntity, orderBy...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *procdefAppImpl) Save(ctx context.Context, def *entity.Procdef) error {
|
func (p *procdefAppImpl) SaveProcdef(ctx context.Context, defParam *dto.SaveProcdef) error {
|
||||||
|
def := defParam.Procdef
|
||||||
if err := entity.ProcdefStatusEnum.Valid(def.Status); err != nil {
|
if err := entity.ProcdefStatusEnum.Valid(def.Status); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if def.Id == 0 {
|
if def.Id == 0 {
|
||||||
if p.GetByCond(&entity.Procdef{DefKey: def.DefKey}) == nil {
|
if p.GetByCond(&entity.Procdef{DefKey: def.DefKey}) == nil {
|
||||||
return errorx.NewBiz("该流程实例key已存在")
|
return errorx.NewBiz("该流程实例key已存在")
|
||||||
}
|
}
|
||||||
return p.Insert(ctx, def)
|
} else {
|
||||||
|
// 防止误修改key
|
||||||
|
def.DefKey = ""
|
||||||
|
if err := p.canModify(def.Id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 防止误修改key
|
return p.Tx(ctx, func(ctx context.Context) error {
|
||||||
def.DefKey = ""
|
return p.Save(ctx, def)
|
||||||
if err := p.canModify(def.Id); err != nil {
|
}, func(ctx context.Context) error {
|
||||||
return err
|
return p.tagTreeRelateApp.RelateTag(ctx, tagentity.TagRelateTypeFlowDef, def.Id, defParam.CodePaths...)
|
||||||
}
|
})
|
||||||
|
|
||||||
return p.UpdateById(ctx, def)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *procdefAppImpl) DeleteProcdef(ctx context.Context, defId uint64) error {
|
func (p *procdefAppImpl) DeleteProcdef(ctx context.Context, defId uint64) error {
|
||||||
@@ -63,6 +82,31 @@ func (p *procdefAppImpl) DeleteProcdef(ctx context.Context, defId uint64) error
|
|||||||
return p.DeleteById(ctx, defId)
|
return p.DeleteById(ctx, defId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *procdefAppImpl) GetProcdefIdByCodePath(ctx context.Context, codePaths ...string) uint64 {
|
||||||
|
relateIds, err := p.tagTreeRelateApp.GetRelateIds(ctx, tagentity.TagRelateTypeFlowDef, codePaths...)
|
||||||
|
if err != nil || len(relateIds) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return relateIds[len(relateIds)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *procdefAppImpl) GetProcdefByResource(ctx context.Context, resourceType int8, resourceCode string) *entity.Procdef {
|
||||||
|
resourceCodePaths := p.tagTreeApp.ListTagPathByTypeAndCode(resourceType, resourceCode)
|
||||||
|
procdefId := p.GetProcdefIdByCodePath(ctx, resourceCodePaths...)
|
||||||
|
if procdefId == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
procdef, err := p.GetById(procdefId)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if procdef.Status == entity.ProcdefStatusDisable {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return procdef
|
||||||
|
}
|
||||||
|
|
||||||
// 判断该流程实例是否可以执行修改操作
|
// 判断该流程实例是否可以执行修改操作
|
||||||
func (p *procdefAppImpl) canModify(prodefId uint64) error {
|
func (p *procdefAppImpl) canModify(prodefId uint64) error {
|
||||||
if activeInstCount := p.procinstApp.CountByCond(&entity.Procinst{ProcdefId: prodefId, Status: entity.ProcinstStatusActive}); activeInstCount > 0 {
|
if activeInstCount := p.procinstApp.CountByCond(&entity.Procinst{ProcdefId: prodefId, Status: entity.ProcinstStatusActive}); activeInstCount > 0 {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package application
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"mayfly-go/internal/flow/application/dto"
|
||||||
"mayfly-go/internal/flow/domain/entity"
|
"mayfly-go/internal/flow/domain/entity"
|
||||||
"mayfly-go/internal/flow/domain/repository"
|
"mayfly-go/internal/flow/domain/repository"
|
||||||
"mayfly-go/pkg/base"
|
"mayfly-go/pkg/base"
|
||||||
@@ -19,8 +20,8 @@ type Procinst interface {
|
|||||||
// 获取流程实例审批节点任务
|
// 获取流程实例审批节点任务
|
||||||
GetProcinstTasks(condition *entity.ProcinstTaskQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
GetProcinstTasks(condition *entity.ProcinstTaskQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
||||||
|
|
||||||
// 根据流程定义key启动一个流程实例
|
// StartProc 根据流程定义启动一个流程实例
|
||||||
StartProc(ctx context.Context, procdefKey string, reqParam *StarProcParam) (*entity.Procinst, error)
|
StartProc(ctx context.Context, procdefId uint64, reqParam *dto.StarProc) (*entity.Procinst, error)
|
||||||
|
|
||||||
// 取消流程
|
// 取消流程
|
||||||
CancelProc(ctx context.Context, procinstId uint64) error
|
CancelProc(ctx context.Context, procinstId uint64) error
|
||||||
@@ -42,6 +43,8 @@ type procinstAppImpl struct {
|
|||||||
procdefApp Procdef `inject:"ProcdefApp"`
|
procdefApp Procdef `inject:"ProcdefApp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ (Procinst) = (*procinstAppImpl)(nil)
|
||||||
|
|
||||||
// 注入repo
|
// 注入repo
|
||||||
func (p *procinstAppImpl) InjectProcinstRepo(procinstRepo repository.Procinst) {
|
func (p *procinstAppImpl) InjectProcinstRepo(procinstRepo repository.Procinst) {
|
||||||
p.Repo = procinstRepo
|
p.Repo = procinstRepo
|
||||||
@@ -55,10 +58,10 @@ func (p *procinstAppImpl) GetProcinstTasks(condition *entity.ProcinstTaskQuery,
|
|||||||
return p.procinstTaskRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
|
return p.procinstTaskRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *procinstAppImpl) StartProc(ctx context.Context, procdefKey string, reqParam *StarProcParam) (*entity.Procinst, error) {
|
func (p *procinstAppImpl) StartProc(ctx context.Context, procdefId uint64, reqParam *dto.StarProc) (*entity.Procinst, error) {
|
||||||
procdef := &entity.Procdef{DefKey: procdefKey}
|
procdef, err := p.procdefApp.GetById(procdefId)
|
||||||
if err := p.procdefApp.GetByCond(procdef); err != nil {
|
if err != nil {
|
||||||
return nil, errorx.NewBiz("流程实例[%s]不存在", procdefKey)
|
return nil, errorx.NewBiz("流程实例[%d]不存在", procdefId)
|
||||||
}
|
}
|
||||||
|
|
||||||
if procdef.Status != entity.ProcdefStatusEnable {
|
if procdef.Status != entity.ProcdefStatusEnable {
|
||||||
@@ -86,7 +89,7 @@ func (p *procinstAppImpl) StartProc(ctx context.Context, procdefKey string, reqP
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *procinstAppImpl) CancelProc(ctx context.Context, procinstId uint64) error {
|
func (p *procinstAppImpl) CancelProc(ctx context.Context, procinstId uint64) error {
|
||||||
procinst, err := p.GetById(new(entity.Procinst), procinstId)
|
procinst, err := p.GetById(procinstId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorx.NewBiz("流程不存在")
|
return errorx.NewBiz("流程不存在")
|
||||||
}
|
}
|
||||||
@@ -122,11 +125,8 @@ func (p *procinstAppImpl) CompleteTask(ctx context.Context, instTaskId uint64, r
|
|||||||
instTask.Remark = remark
|
instTask.Remark = remark
|
||||||
instTask.SetEnd()
|
instTask.SetEnd()
|
||||||
|
|
||||||
procinst := new(entity.Procinst)
|
procinst, _ := p.GetById(instTask.ProcinstId)
|
||||||
p.GetById(procinst, instTask.ProcinstId)
|
procdef, _ := p.procdefApp.GetById(procinst.ProcdefId)
|
||||||
|
|
||||||
procdef := new(entity.Procdef)
|
|
||||||
p.procdefApp.GetById(procdef, procinst.ProcdefId)
|
|
||||||
|
|
||||||
// 获取下一实例审批任务
|
// 获取下一实例审批任务
|
||||||
task := p.getNextTask(procdef, instTask.TaskKey)
|
task := p.getNextTask(procdef, instTask.TaskKey)
|
||||||
@@ -163,8 +163,7 @@ func (p *procinstAppImpl) RejectTask(ctx context.Context, instTaskId uint64, rem
|
|||||||
instTask.Remark = remark
|
instTask.Remark = remark
|
||||||
instTask.SetEnd()
|
instTask.SetEnd()
|
||||||
|
|
||||||
procinst := new(entity.Procinst)
|
procinst, _ := p.GetById(instTask.ProcinstId)
|
||||||
p.GetById(procinst, instTask.ProcinstId)
|
|
||||||
// 更新流程实例为终止状态,无法重新提交
|
// 更新流程实例为终止状态,无法重新提交
|
||||||
procinst.Status = entity.ProcinstStatusTerminated
|
procinst.Status = entity.ProcinstStatusTerminated
|
||||||
procinst.BizStatus = entity.ProcinstBizStatusNo
|
procinst.BizStatus = entity.ProcinstBizStatusNo
|
||||||
@@ -189,8 +188,7 @@ func (p *procinstAppImpl) BackTask(ctx context.Context, instTaskId uint64, remar
|
|||||||
instTask.Status = entity.ProcinstTaskStatusBack
|
instTask.Status = entity.ProcinstTaskStatusBack
|
||||||
instTask.Remark = remark
|
instTask.Remark = remark
|
||||||
|
|
||||||
procinst := new(entity.Procinst)
|
procinst, _ := p.GetById(instTask.ProcinstId)
|
||||||
p.GetById(procinst, instTask.ProcinstId)
|
|
||||||
|
|
||||||
// 更新流程实例为挂起状态,等待重新提交
|
// 更新流程实例为挂起状态,等待重新提交
|
||||||
procinst.Status = entity.ProcinstStatusSuspended
|
procinst.Status = entity.ProcinstStatusSuspended
|
||||||
@@ -207,9 +205,8 @@ func (p *procinstAppImpl) BackTask(ctx context.Context, instTaskId uint64, remar
|
|||||||
// 取消处理中的流程实例任务
|
// 取消处理中的流程实例任务
|
||||||
func (p *procinstAppImpl) cancelInstTasks(ctx context.Context, procinstId uint64, cancelReason string) error {
|
func (p *procinstAppImpl) cancelInstTasks(ctx context.Context, procinstId uint64, cancelReason string) error {
|
||||||
// 流程实例任务信息
|
// 流程实例任务信息
|
||||||
instTasks := new([]*entity.ProcinstTask)
|
instTasks, _ := p.procinstTaskRepo.SelectByCond(&entity.ProcinstTask{ProcinstId: procinstId, Status: entity.ProcinstTaskStatusProcess})
|
||||||
p.procinstTaskRepo.SelectByCond(&entity.ProcinstTask{ProcinstId: procinstId, Status: entity.ProcinstTaskStatusProcess}, instTasks)
|
for _, instTask := range instTasks {
|
||||||
for _, instTask := range *instTasks {
|
|
||||||
instTask.Status = entity.ProcinstTaskStatusCanceled
|
instTask.Status = entity.ProcinstTaskStatusCanceled
|
||||||
instTask.Remark = cancelReason
|
instTask.Remark = cancelReason
|
||||||
instTask.SetEnd()
|
instTask.SetEnd()
|
||||||
@@ -250,8 +247,8 @@ func (p *procinstAppImpl) triggerProcinstStatusChangeEvent(ctx context.Context,
|
|||||||
|
|
||||||
// 获取并校验实例任务
|
// 获取并校验实例任务
|
||||||
func (p *procinstAppImpl) getAndValidInstTask(ctx context.Context, instTaskId uint64) (*entity.ProcinstTask, error) {
|
func (p *procinstAppImpl) getAndValidInstTask(ctx context.Context, instTaskId uint64) (*entity.ProcinstTask, error) {
|
||||||
instTask := new(entity.ProcinstTask)
|
instTask, err := p.procinstTaskRepo.GetById(instTaskId)
|
||||||
if err := p.procinstTaskRepo.GetById(instTask, instTaskId); err != nil {
|
if err != nil {
|
||||||
return nil, errorx.NewBiz("流程实例任务不存在")
|
return nil, errorx.NewBiz("流程实例任务不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,5 +19,5 @@ func (p *procdefImpl) GetPageList(condition *entity.Procdef, pageParam *model.Pa
|
|||||||
qd := model.NewCond().
|
qd := model.NewCond().
|
||||||
Like("name", condition.Name).
|
Like("name", condition.Name).
|
||||||
Like("def_key", condition.DefKey)
|
Like("def_key", condition.DefKey)
|
||||||
return p.PageByCond(qd, pageParam, toEntity)
|
return p.PageByCondToAny(qd, pageParam, toEntity)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ func newProcinstRepo() repository.Procinst {
|
|||||||
|
|
||||||
func (p *procinstImpl) GetPageList(condition *entity.ProcinstQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
|
func (p *procinstImpl) GetPageList(condition *entity.ProcinstQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
|
||||||
qd := model.NewModelCond(condition)
|
qd := model.NewModelCond(condition)
|
||||||
return p.PageByCond(qd, pageParam, toEntity)
|
return p.PageByCondToAny(qd, pageParam, toEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------procinst task--------------
|
//-----------procinst task--------------
|
||||||
@@ -32,5 +32,5 @@ func newProcinstTaskRepo() repository.ProcinstTask {
|
|||||||
|
|
||||||
func (p *procinstTaskImpl) GetPageList(condition *entity.ProcinstTaskQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
|
func (p *procinstTaskImpl) GetPageList(condition *entity.ProcinstTaskQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) {
|
||||||
qd := model.NewModelCond(condition)
|
qd := model.NewModelCond(condition)
|
||||||
return p.PageByCond(qd, pageParam, toEntity)
|
return p.PageByCondToAny(qd, pageParam, toEntity)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func InitProcdefouter(router *gin.RouterGroup) {
|
|||||||
reqs := [...]*req.Conf{
|
reqs := [...]*req.Conf{
|
||||||
req.NewGet("", p.GetProcdefPage),
|
req.NewGet("", p.GetProcdefPage),
|
||||||
|
|
||||||
req.NewGet("/:key", p.GetProcdef),
|
req.NewGet("/:resourceType/:resourceCode", p.GetProcdef),
|
||||||
|
|
||||||
req.NewPost("", p.Save).Log(req.NewLogSave("流程定义-保存")).RequiredPermissionCode("flow:procdef:save"),
|
req.NewPost("", p.Save).Log(req.NewLogSave("流程定义-保存")).RequiredPermissionCode("flow:procdef:save"),
|
||||||
|
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ type MachineCronJobForm struct {
|
|||||||
Script string `json:"script" binding:"required"`
|
Script string `json:"script" binding:"required"`
|
||||||
Status int `json:"status" binding:"required"`
|
Status int `json:"status" binding:"required"`
|
||||||
SaveExecResType int `json:"saveExecResType" binding:"required"`
|
SaveExecResType int `json:"saveExecResType" binding:"required"`
|
||||||
MachineIds []uint64 `json:"machineIds"`
|
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
|
CodePaths []string `json:"codePaths"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MachineCmdConfForm struct {
|
type MachineCmdConfForm struct {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package form
|
package form
|
||||||
|
|
||||||
import "mayfly-go/internal/machine/application"
|
import (
|
||||||
|
"mayfly-go/internal/machine/application/dto"
|
||||||
|
)
|
||||||
|
|
||||||
type MachineFileForm struct {
|
type MachineFileForm struct {
|
||||||
Id uint64 `json:"id"`
|
Id uint64 `json:"id"`
|
||||||
@@ -17,32 +19,32 @@ type MachineFileUpdateForm struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CreateFileForm struct {
|
type CreateFileForm struct {
|
||||||
*application.MachineFileOpParam
|
*dto.MachineFileOp
|
||||||
|
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WriteFileContentForm struct {
|
type WriteFileContentForm struct {
|
||||||
*application.MachineFileOpParam
|
*dto.MachineFileOp
|
||||||
|
|
||||||
Content string `json:"content" binding:"required"`
|
Content string `json:"content" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoveFileForm struct {
|
type RemoveFileForm struct {
|
||||||
*application.MachineFileOpParam
|
*dto.MachineFileOp
|
||||||
|
|
||||||
Paths []string `json:"paths" binding:"required"`
|
Paths []string `json:"paths" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CopyFileForm struct {
|
type CopyFileForm struct {
|
||||||
*application.MachineFileOpParam
|
*dto.MachineFileOp
|
||||||
|
|
||||||
Paths []string `json:"paths" binding:"required"`
|
Paths []string `json:"paths" binding:"required"`
|
||||||
ToPath string `json:"toPath" binding:"required"`
|
ToPath string `json:"toPath" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RenameForm struct {
|
type RenameForm struct {
|
||||||
*application.MachineFileOpParam
|
*dto.MachineFileOp
|
||||||
|
|
||||||
Newname string `json:"newname" binding:"required"`
|
Newname string `json:"newname" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"mayfly-go/internal/machine/api/form"
|
"mayfly-go/internal/machine/api/form"
|
||||||
"mayfly-go/internal/machine/api/vo"
|
"mayfly-go/internal/machine/api/vo"
|
||||||
"mayfly-go/internal/machine/application"
|
"mayfly-go/internal/machine/application"
|
||||||
|
"mayfly-go/internal/machine/application/dto"
|
||||||
"mayfly-go/internal/machine/config"
|
"mayfly-go/internal/machine/config"
|
||||||
"mayfly-go/internal/machine/domain/entity"
|
"mayfly-go/internal/machine/domain/entity"
|
||||||
"mayfly-go/internal/machine/guac"
|
"mayfly-go/internal/machine/guac"
|
||||||
@@ -99,7 +100,7 @@ func (m *Machine) SaveMachine(rc *req.Ctx) {
|
|||||||
|
|
||||||
rc.ReqParam = machineForm
|
rc.ReqParam = machineForm
|
||||||
|
|
||||||
biz.ErrIsNil(m.MachineApp.SaveMachine(rc.MetaCtx, &application.SaveMachineParam{
|
biz.ErrIsNil(m.MachineApp.SaveMachine(rc.MetaCtx, &dto.SaveMachine{
|
||||||
Machine: me,
|
Machine: me,
|
||||||
TagCodePaths: machineForm.TagCodePaths,
|
TagCodePaths: machineForm.TagCodePaths,
|
||||||
AuthCerts: machineForm.AuthCerts,
|
AuthCerts: machineForm.AuthCerts,
|
||||||
@@ -152,7 +153,7 @@ func (m *Machine) GetProcess(rc *req.Ctx) {
|
|||||||
|
|
||||||
cli, err := m.MachineApp.GetCli(GetMachineId(rc))
|
cli, err := m.MachineApp.GetCli(GetMachineId(rc))
|
||||||
biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
|
biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
|
||||||
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.GetLoginAccount().Id, cli.Info.TagPath...), "%s")
|
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.GetLoginAccount().Id, cli.Info.CodePath...), "%s")
|
||||||
|
|
||||||
res, err := cli.Run(cmd)
|
res, err := cli.Run(cmd)
|
||||||
biz.ErrIsNilAppendErr(err, "获取进程信息失败: %s")
|
biz.ErrIsNilAppendErr(err, "获取进程信息失败: %s")
|
||||||
@@ -166,7 +167,7 @@ func (m *Machine) KillProcess(rc *req.Ctx) {
|
|||||||
|
|
||||||
cli, err := m.MachineApp.GetCli(GetMachineId(rc))
|
cli, err := m.MachineApp.GetCli(GetMachineId(rc))
|
||||||
biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
|
biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
|
||||||
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.GetLoginAccount().Id, cli.Info.TagPath...), "%s")
|
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.GetLoginAccount().Id, cli.Info.CodePath...), "%s")
|
||||||
|
|
||||||
res, err := cli.Run("sudo kill -9 " + pid)
|
res, err := cli.Run("sudo kill -9 " + pid)
|
||||||
biz.ErrIsNil(err, "终止进程失败: %s", res)
|
biz.ErrIsNil(err, "终止进程失败: %s", res)
|
||||||
@@ -194,9 +195,9 @@ func (m *Machine) WsSSH(g *gin.Context) {
|
|||||||
cli, err := m.MachineApp.NewCli(GetMachineAc(rc))
|
cli, err := m.MachineApp.NewCli(GetMachineAc(rc))
|
||||||
biz.ErrIsNilAppendErr(err, mcm.GetErrorContentRn("获取客户端连接失败: %s"))
|
biz.ErrIsNilAppendErr(err, mcm.GetErrorContentRn("获取客户端连接失败: %s"))
|
||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.GetLoginAccount().Id, cli.Info.TagPath...), mcm.GetErrorContentRn("%s"))
|
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.GetLoginAccount().Id, cli.Info.CodePath...), mcm.GetErrorContentRn("%s"))
|
||||||
|
|
||||||
global.EventBus.Publish(rc.MetaCtx, event.EventTopicResourceOp, cli.Info.TagPath[0])
|
global.EventBus.Publish(rc.MetaCtx, event.EventTopicResourceOp, cli.Info.CodePath[0])
|
||||||
|
|
||||||
cols := rc.QueryIntDefault("cols", 80)
|
cols := rc.QueryIntDefault("cols", 80)
|
||||||
rows := rc.QueryIntDefault("rows", 32)
|
rows := rc.QueryIntDefault("rows", 32)
|
||||||
@@ -218,7 +219,7 @@ func (m *Machine) MachineTermOpRecords(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Machine) MachineTermOpRecord(rc *req.Ctx) {
|
func (m *Machine) MachineTermOpRecord(rc *req.Ctx) {
|
||||||
termOp, err := m.MachineTermOpApp.GetById(new(entity.MachineTermOp), uint64(rc.PathParamInt("recId")))
|
termOp, err := m.MachineTermOpApp.GetById(uint64(rc.PathParamInt("recId")))
|
||||||
biz.ErrIsNil(err)
|
biz.ErrIsNil(err)
|
||||||
|
|
||||||
bytes, err := os.ReadFile(path.Join(config.GetMachine().TerminalRecPath, termOp.RecordFilePath))
|
bytes, err := os.ReadFile(path.Join(config.GetMachine().TerminalRecPath, termOp.RecordFilePath))
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"mayfly-go/internal/machine/api/form"
|
"mayfly-go/internal/machine/api/form"
|
||||||
"mayfly-go/internal/machine/api/vo"
|
"mayfly-go/internal/machine/api/vo"
|
||||||
"mayfly-go/internal/machine/application"
|
"mayfly-go/internal/machine/application"
|
||||||
|
"mayfly-go/internal/machine/application/dto"
|
||||||
"mayfly-go/internal/machine/domain/entity"
|
"mayfly-go/internal/machine/domain/entity"
|
||||||
|
|
||||||
tagapp "mayfly-go/internal/tag/application"
|
tagapp "mayfly-go/internal/tag/application"
|
||||||
@@ -22,7 +23,7 @@ func (m *MachineCmdConf) MachineCmdConfs(rc *req.Ctx) {
|
|||||||
cond := req.BindQuery(rc, new(entity.MachineCmdConf))
|
cond := req.BindQuery(rc, new(entity.MachineCmdConf))
|
||||||
|
|
||||||
var vos []*vo.MachineCmdConfVO
|
var vos []*vo.MachineCmdConfVO
|
||||||
err := m.MachineCmdConfApp.ListByCond(cond, &vos)
|
err := m.MachineCmdConfApp.ListByCondToAny(cond, &vos)
|
||||||
biz.ErrIsNil(err)
|
biz.ErrIsNil(err)
|
||||||
|
|
||||||
m.TagTreeRelateApp.FillTagInfo(tagentity.TagRelateTypeMachineCmd, collx.ArrayMap(vos, func(mvo *vo.MachineCmdConfVO) tagentity.IRelateTag {
|
m.TagTreeRelateApp.FillTagInfo(tagentity.TagRelateTypeMachineCmd, collx.ArrayMap(vos, func(mvo *vo.MachineCmdConfVO) tagentity.IRelateTag {
|
||||||
@@ -37,7 +38,7 @@ func (m *MachineCmdConf) Save(rc *req.Ctx) {
|
|||||||
mcj := req.BindJsonAndCopyTo[*entity.MachineCmdConf](rc, cmdForm, new(entity.MachineCmdConf))
|
mcj := req.BindJsonAndCopyTo[*entity.MachineCmdConf](rc, cmdForm, new(entity.MachineCmdConf))
|
||||||
rc.ReqParam = cmdForm
|
rc.ReqParam = cmdForm
|
||||||
|
|
||||||
err := m.MachineCmdConfApp.SaveCmdConf(rc.MetaCtx, &application.SaveMachineCmdConfParam{
|
err := m.MachineCmdConfApp.SaveCmdConf(rc.MetaCtx, &dto.SaveMachineCmdConf{
|
||||||
CmdConf: mcj,
|
CmdConf: mcj,
|
||||||
CodePaths: cmdForm.CodePaths,
|
CodePaths: cmdForm.CodePaths,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,29 +4,39 @@ import (
|
|||||||
"mayfly-go/internal/machine/api/form"
|
"mayfly-go/internal/machine/api/form"
|
||||||
"mayfly-go/internal/machine/api/vo"
|
"mayfly-go/internal/machine/api/vo"
|
||||||
"mayfly-go/internal/machine/application"
|
"mayfly-go/internal/machine/application"
|
||||||
|
"mayfly-go/internal/machine/application/dto"
|
||||||
"mayfly-go/internal/machine/domain/entity"
|
"mayfly-go/internal/machine/domain/entity"
|
||||||
|
tagapp "mayfly-go/internal/tag/application"
|
||||||
|
tagentity "mayfly-go/internal/tag/domain/entity"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"mayfly-go/pkg/biz"
|
"mayfly-go/pkg/biz"
|
||||||
"mayfly-go/pkg/req"
|
"mayfly-go/pkg/req"
|
||||||
"mayfly-go/pkg/scheduler"
|
"mayfly-go/pkg/scheduler"
|
||||||
|
"mayfly-go/pkg/utils/collx"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MachineCronJob struct {
|
type MachineCronJob struct {
|
||||||
MachineCronJobApp application.MachineCronJob `inject:""`
|
MachineCronJobApp application.MachineCronJob `inject:""`
|
||||||
|
TagTreeRelateApp tagapp.TagTreeRelate `inject:"TagTreeRelateApp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MachineCronJob) MachineCronJobs(rc *req.Ctx) {
|
func (m *MachineCronJob) MachineCronJobs(rc *req.Ctx) {
|
||||||
cond, pageParam := req.BindQueryAndPage(rc, new(entity.MachineCronJob))
|
cond, pageParam := req.BindQueryAndPage(rc, new(entity.MachineCronJob))
|
||||||
|
|
||||||
vos := new([]*vo.MachineCronJobVO)
|
var vos []*vo.MachineCronJobVO
|
||||||
pageRes, err := m.MachineCronJobApp.GetPageList(cond, pageParam, vos)
|
pageRes, err := m.MachineCronJobApp.GetPageList(cond, pageParam, &vos)
|
||||||
biz.ErrIsNil(err)
|
biz.ErrIsNil(err)
|
||||||
for _, mcj := range *vos {
|
|
||||||
|
for _, mcj := range vos {
|
||||||
mcj.Running = scheduler.ExistKey(mcj.Key)
|
mcj.Running = scheduler.ExistKey(mcj.Key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m.TagTreeRelateApp.FillTagInfo(tagentity.TagRelateTypeMachineCronJob, collx.ArrayMap(vos, func(mvo *vo.MachineCronJobVO) tagentity.IRelateTag {
|
||||||
|
return mvo
|
||||||
|
})...)
|
||||||
|
|
||||||
rc.ResData = pageRes
|
rc.ResData = pageRes
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,11 +45,11 @@ func (m *MachineCronJob) Save(rc *req.Ctx) {
|
|||||||
mcj := req.BindJsonAndCopyTo[*entity.MachineCronJob](rc, jobForm, new(entity.MachineCronJob))
|
mcj := req.BindJsonAndCopyTo[*entity.MachineCronJob](rc, jobForm, new(entity.MachineCronJob))
|
||||||
rc.ReqParam = jobForm
|
rc.ReqParam = jobForm
|
||||||
|
|
||||||
cronJobId, err := m.MachineCronJobApp.SaveMachineCronJob(rc.MetaCtx, mcj)
|
err := m.MachineCronJobApp.SaveMachineCronJob(rc.MetaCtx, &dto.SaveMachineCronJob{
|
||||||
|
CronJob: mcj,
|
||||||
|
CodePaths: jobForm.CodePaths,
|
||||||
|
})
|
||||||
biz.ErrIsNil(err)
|
biz.ErrIsNil(err)
|
||||||
|
|
||||||
// 关联机器
|
|
||||||
m.MachineCronJobApp.CronJobRelateMachines(rc.MetaCtx, cronJobId, jobForm.MachineIds)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MachineCronJob) Delete(rc *req.Ctx) {
|
func (m *MachineCronJob) Delete(rc *req.Ctx) {
|
||||||
@@ -54,14 +64,6 @@ func (m *MachineCronJob) Delete(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MachineCronJob) GetRelateMachineIds(rc *req.Ctx) {
|
|
||||||
rc.ResData = m.MachineCronJobApp.GetRelateMachineIds(uint64(rc.QueryIntDefault("cronJobId", -1)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MachineCronJob) GetRelateCronJobIds(rc *req.Ctx) {
|
|
||||||
rc.ResData = m.MachineCronJobApp.GetRelateMachineIds(uint64(rc.QueryIntDefault("machineId", -1)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MachineCronJob) RunCronJob(rc *req.Ctx) {
|
func (m *MachineCronJob) RunCronJob(rc *req.Ctx) {
|
||||||
cronJobKey := rc.PathParam("key")
|
cronJobKey := rc.PathParam("key")
|
||||||
biz.NotEmpty(cronJobKey, "cronJob key不能为空")
|
biz.NotEmpty(cronJobKey, "cronJob key不能为空")
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"mayfly-go/internal/machine/api/form"
|
"mayfly-go/internal/machine/api/form"
|
||||||
"mayfly-go/internal/machine/api/vo"
|
"mayfly-go/internal/machine/api/vo"
|
||||||
"mayfly-go/internal/machine/application"
|
"mayfly-go/internal/machine/application"
|
||||||
|
"mayfly-go/internal/machine/application/dto"
|
||||||
"mayfly-go/internal/machine/config"
|
"mayfly-go/internal/machine/config"
|
||||||
"mayfly-go/internal/machine/domain/entity"
|
"mayfly-go/internal/machine/domain/entity"
|
||||||
"mayfly-go/internal/machine/mcm"
|
"mayfly-go/internal/machine/mcm"
|
||||||
@@ -71,10 +72,10 @@ func (m *MachineFile) CreateFile(rc *req.Ctx) {
|
|||||||
var err error
|
var err error
|
||||||
if opForm.Type == dir {
|
if opForm.Type == dir {
|
||||||
attrs["type"] = "目录"
|
attrs["type"] = "目录"
|
||||||
mi, err = m.MachineFileApp.MkDir(rc.MetaCtx, opForm.MachineFileOpParam)
|
mi, err = m.MachineFileApp.MkDir(rc.MetaCtx, opForm.MachineFileOp)
|
||||||
} else {
|
} else {
|
||||||
attrs["type"] = "文件"
|
attrs["type"] = "文件"
|
||||||
mi, err = m.MachineFileApp.CreateFile(rc.MetaCtx, opForm.MachineFileOpParam)
|
mi, err = m.MachineFileApp.CreateFile(rc.MetaCtx, opForm.MachineFileOp)
|
||||||
}
|
}
|
||||||
attrs["machine"] = mi
|
attrs["machine"] = mi
|
||||||
rc.ReqParam = attrs
|
rc.ReqParam = attrs
|
||||||
@@ -82,7 +83,7 @@ func (m *MachineFile) CreateFile(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MachineFile) ReadFileContent(rc *req.Ctx) {
|
func (m *MachineFile) ReadFileContent(rc *req.Ctx) {
|
||||||
opForm := req.BindQuery(rc, new(application.MachineFileOpParam))
|
opForm := req.BindQuery(rc, new(dto.MachineFileOp))
|
||||||
readPath := opForm.Path
|
readPath := opForm.Path
|
||||||
// 特殊处理rdp文件
|
// 特殊处理rdp文件
|
||||||
if opForm.Protocol == entity.MachineProtocolRdp {
|
if opForm.Protocol == entity.MachineProtocolRdp {
|
||||||
@@ -112,7 +113,7 @@ func (m *MachineFile) ReadFileContent(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MachineFile) DownloadFile(rc *req.Ctx) {
|
func (m *MachineFile) DownloadFile(rc *req.Ctx) {
|
||||||
opForm := req.BindQuery(rc, new(application.MachineFileOpParam))
|
opForm := req.BindQuery(rc, new(dto.MachineFileOp))
|
||||||
|
|
||||||
readPath := opForm.Path
|
readPath := opForm.Path
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ func (m *MachineFile) DownloadFile(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MachineFile) GetDirEntry(rc *req.Ctx) {
|
func (m *MachineFile) GetDirEntry(rc *req.Ctx) {
|
||||||
opForm := req.BindQuery(rc, new(application.MachineFileOpParam))
|
opForm := req.BindQuery(rc, new(dto.MachineFileOp))
|
||||||
readPath := opForm.Path
|
readPath := opForm.Path
|
||||||
rc.ReqParam = fmt.Sprintf("path: %s", readPath)
|
rc.ReqParam = fmt.Sprintf("path: %s", readPath)
|
||||||
|
|
||||||
@@ -173,7 +174,7 @@ func (m *MachineFile) GetDirEntry(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MachineFile) GetDirSize(rc *req.Ctx) {
|
func (m *MachineFile) GetDirSize(rc *req.Ctx) {
|
||||||
opForm := req.BindQuery(rc, new(application.MachineFileOpParam))
|
opForm := req.BindQuery(rc, new(dto.MachineFileOp))
|
||||||
|
|
||||||
size, err := m.MachineFileApp.GetDirSize(rc.MetaCtx, opForm)
|
size, err := m.MachineFileApp.GetDirSize(rc.MetaCtx, opForm)
|
||||||
biz.ErrIsNil(err)
|
biz.ErrIsNil(err)
|
||||||
@@ -181,7 +182,7 @@ func (m *MachineFile) GetDirSize(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MachineFile) GetFileStat(rc *req.Ctx) {
|
func (m *MachineFile) GetFileStat(rc *req.Ctx) {
|
||||||
opForm := req.BindQuery(rc, new(application.MachineFileOpParam))
|
opForm := req.BindQuery(rc, new(dto.MachineFileOp))
|
||||||
res, err := m.MachineFileApp.FileStat(rc.MetaCtx, opForm)
|
res, err := m.MachineFileApp.FileStat(rc.MetaCtx, opForm)
|
||||||
biz.ErrIsNil(err, res)
|
biz.ErrIsNil(err, res)
|
||||||
rc.ResData = res
|
rc.ResData = res
|
||||||
@@ -191,7 +192,7 @@ func (m *MachineFile) WriteFileContent(rc *req.Ctx) {
|
|||||||
opForm := req.BindJsonAndValid(rc, new(form.WriteFileContentForm))
|
opForm := req.BindJsonAndValid(rc, new(form.WriteFileContentForm))
|
||||||
path := opForm.Path
|
path := opForm.Path
|
||||||
|
|
||||||
mi, err := m.MachineFileApp.WriteFileContent(rc.MetaCtx, opForm.MachineFileOpParam, []byte(opForm.Content))
|
mi, err := m.MachineFileApp.WriteFileContent(rc.MetaCtx, opForm.MachineFileOp, []byte(opForm.Content))
|
||||||
rc.ReqParam = collx.Kvs("machine", mi, "path", path)
|
rc.ReqParam = collx.Kvs("machine", mi, "path", path)
|
||||||
biz.ErrIsNilAppendErr(err, "打开文件失败: %s")
|
biz.ErrIsNilAppendErr(err, "打开文件失败: %s")
|
||||||
}
|
}
|
||||||
@@ -219,7 +220,7 @@ func (m *MachineFile) UploadFile(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
opForm := &application.MachineFileOpParam{
|
opForm := &dto.MachineFileOp{
|
||||||
MachineId: machineId,
|
MachineId: machineId,
|
||||||
AuthCertName: authCertName,
|
AuthCertName: authCertName,
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
@@ -259,7 +260,7 @@ func (m *MachineFile) UploadFolder(rc *req.Ctx) {
|
|||||||
// protocol
|
// protocol
|
||||||
protocol := cast.ToInt(mf.Value["protocol"][0])
|
protocol := cast.ToInt(mf.Value["protocol"][0])
|
||||||
|
|
||||||
opForm := &application.MachineFileOpParam{
|
opForm := &dto.MachineFileOp{
|
||||||
MachineId: machineId,
|
MachineId: machineId,
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
AuthCertName: authCertName,
|
AuthCertName: authCertName,
|
||||||
@@ -347,28 +348,28 @@ func (m *MachineFile) UploadFolder(rc *req.Ctx) {
|
|||||||
func (m *MachineFile) RemoveFile(rc *req.Ctx) {
|
func (m *MachineFile) RemoveFile(rc *req.Ctx) {
|
||||||
opForm := req.BindJsonAndValid(rc, new(form.RemoveFileForm))
|
opForm := req.BindJsonAndValid(rc, new(form.RemoveFileForm))
|
||||||
|
|
||||||
mi, err := m.MachineFileApp.RemoveFile(rc.MetaCtx, opForm.MachineFileOpParam, opForm.Paths...)
|
mi, err := m.MachineFileApp.RemoveFile(rc.MetaCtx, opForm.MachineFileOp, opForm.Paths...)
|
||||||
rc.ReqParam = collx.Kvs("machine", mi, "path", opForm)
|
rc.ReqParam = collx.Kvs("machine", mi, "path", opForm)
|
||||||
biz.ErrIsNilAppendErr(err, "删除文件失败: %s")
|
biz.ErrIsNilAppendErr(err, "删除文件失败: %s")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MachineFile) CopyFile(rc *req.Ctx) {
|
func (m *MachineFile) CopyFile(rc *req.Ctx) {
|
||||||
opForm := req.BindJsonAndValid(rc, new(form.CopyFileForm))
|
opForm := req.BindJsonAndValid(rc, new(form.CopyFileForm))
|
||||||
mi, err := m.MachineFileApp.Copy(rc.MetaCtx, opForm.MachineFileOpParam, opForm.ToPath, opForm.Paths...)
|
mi, err := m.MachineFileApp.Copy(rc.MetaCtx, opForm.MachineFileOp, opForm.ToPath, opForm.Paths...)
|
||||||
biz.ErrIsNilAppendErr(err, "文件拷贝失败: %s")
|
biz.ErrIsNilAppendErr(err, "文件拷贝失败: %s")
|
||||||
rc.ReqParam = collx.Kvs("machine", mi, "cp", opForm)
|
rc.ReqParam = collx.Kvs("machine", mi, "cp", opForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MachineFile) MvFile(rc *req.Ctx) {
|
func (m *MachineFile) MvFile(rc *req.Ctx) {
|
||||||
opForm := req.BindJsonAndValid(rc, new(form.CopyFileForm))
|
opForm := req.BindJsonAndValid(rc, new(form.CopyFileForm))
|
||||||
mi, err := m.MachineFileApp.Mv(rc.MetaCtx, opForm.MachineFileOpParam, opForm.ToPath, opForm.Paths...)
|
mi, err := m.MachineFileApp.Mv(rc.MetaCtx, opForm.MachineFileOp, opForm.ToPath, opForm.Paths...)
|
||||||
rc.ReqParam = collx.Kvs("machine", mi, "mv", opForm)
|
rc.ReqParam = collx.Kvs("machine", mi, "mv", opForm)
|
||||||
biz.ErrIsNilAppendErr(err, "文件移动失败: %s")
|
biz.ErrIsNilAppendErr(err, "文件移动失败: %s")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MachineFile) Rename(rc *req.Ctx) {
|
func (m *MachineFile) Rename(rc *req.Ctx) {
|
||||||
renameForm := req.BindJsonAndValid(rc, new(form.RenameForm))
|
renameForm := req.BindJsonAndValid(rc, new(form.RenameForm))
|
||||||
mi, err := m.MachineFileApp.Rename(rc.MetaCtx, renameForm.MachineFileOpParam, renameForm.Newname)
|
mi, err := m.MachineFileApp.Rename(rc.MetaCtx, renameForm.MachineFileOp, renameForm.Newname)
|
||||||
rc.ReqParam = collx.Kvs("machine", mi, "rename", renameForm)
|
rc.ReqParam = collx.Kvs("machine", mi, "rename", renameForm)
|
||||||
biz.ErrIsNilAppendErr(err, "文件重命名失败: %s")
|
biz.ErrIsNilAppendErr(err, "文件重命名失败: %s")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func (m *MachineScript) DeleteMachineScript(rc *req.Ctx) {
|
|||||||
func (m *MachineScript) RunMachineScript(rc *req.Ctx) {
|
func (m *MachineScript) RunMachineScript(rc *req.Ctx) {
|
||||||
scriptId := GetMachineScriptId(rc)
|
scriptId := GetMachineScriptId(rc)
|
||||||
ac := GetMachineAc(rc)
|
ac := GetMachineAc(rc)
|
||||||
ms, err := m.MachineScriptApp.GetById(new(entity.MachineScript), scriptId, "MachineId", "Name", "Script")
|
ms, err := m.MachineScriptApp.GetById(scriptId, "MachineId", "Name", "Script")
|
||||||
biz.ErrIsNil(err, "该脚本不存在")
|
biz.ErrIsNil(err, "该脚本不存在")
|
||||||
|
|
||||||
script := ms.Script
|
script := ms.Script
|
||||||
@@ -62,7 +62,7 @@ func (m *MachineScript) RunMachineScript(rc *req.Ctx) {
|
|||||||
}
|
}
|
||||||
cli, err := m.MachineApp.GetCliByAc(ac)
|
cli, err := m.MachineApp.GetCliByAc(ac)
|
||||||
biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
|
biz.ErrIsNilAppendErr(err, "获取客户端连接失败: %s")
|
||||||
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.GetLoginAccount().Id, cli.Info.TagPath...), "%s")
|
biz.ErrIsNilAppendErr(m.TagApp.CanAccess(rc.GetLoginAccount().Id, cli.Info.CodePath...), "%s")
|
||||||
|
|
||||||
res, err := cli.Run(script)
|
res, err := cli.Run(script)
|
||||||
// 记录请求参数
|
// 记录请求参数
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ type MachineScriptVO struct {
|
|||||||
|
|
||||||
// 机器记录任务
|
// 机器记录任务
|
||||||
type MachineCronJobVO struct {
|
type MachineCronJobVO struct {
|
||||||
|
tagentity.RelateTags // 标签信息
|
||||||
|
|
||||||
Id uint64 `json:"id"`
|
Id uint64 `json:"id"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -57,6 +59,10 @@ type MachineCronJobVO struct {
|
|||||||
Running bool `json:"running" gorm:"-"` // 是否运行中
|
Running bool `json:"running" gorm:"-"` // 是否运行中
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mcj *MachineCronJobVO) GetRelateId() uint64 {
|
||||||
|
return mcj.Id
|
||||||
|
}
|
||||||
|
|
||||||
type MachineFileVO struct {
|
type MachineFileVO struct {
|
||||||
Id *int64 `json:"id"`
|
Id *int64 `json:"id"`
|
||||||
Name *string `json:"name"`
|
Name *string `json:"name"`
|
||||||
|
|||||||
29
server/internal/machine/application/dto/dto.go
Normal file
29
server/internal/machine/application/dto/dto.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package dto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"mayfly-go/internal/machine/domain/entity"
|
||||||
|
tagentity "mayfly-go/internal/tag/domain/entity"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SaveMachine struct {
|
||||||
|
Machine *entity.Machine
|
||||||
|
TagCodePaths []string
|
||||||
|
AuthCerts []*tagentity.ResourceAuthCert
|
||||||
|
}
|
||||||
|
|
||||||
|
type MachineFileOp struct {
|
||||||
|
MachineId uint64 `json:"machineId" binding:"required" form:"machineId"`
|
||||||
|
Protocol int `json:"protocol" binding:"required" form:"protocol"`
|
||||||
|
AuthCertName string `json:"authCertName" binding:"required" form:"authCertName"` // 授权凭证
|
||||||
|
Path string `json:"path" form:"path"` // 文件路径
|
||||||
|
}
|
||||||
|
|
||||||
|
type SaveMachineCmdConf struct {
|
||||||
|
CmdConf *entity.MachineCmdConf
|
||||||
|
CodePaths []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type SaveMachineCronJob struct {
|
||||||
|
CronJob *entity.MachineCronJob
|
||||||
|
CodePaths []string
|
||||||
|
}
|
||||||
@@ -4,11 +4,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"mayfly-go/internal/event"
|
"mayfly-go/internal/event"
|
||||||
|
"mayfly-go/internal/machine/application/dto"
|
||||||
"mayfly-go/internal/machine/domain/entity"
|
"mayfly-go/internal/machine/domain/entity"
|
||||||
"mayfly-go/internal/machine/domain/repository"
|
"mayfly-go/internal/machine/domain/repository"
|
||||||
"mayfly-go/internal/machine/infrastructure/cache"
|
"mayfly-go/internal/machine/infrastructure/cache"
|
||||||
"mayfly-go/internal/machine/mcm"
|
"mayfly-go/internal/machine/mcm"
|
||||||
tagapp "mayfly-go/internal/tag/application"
|
tagapp "mayfly-go/internal/tag/application"
|
||||||
|
tagdto "mayfly-go/internal/tag/application/dto"
|
||||||
tagentity "mayfly-go/internal/tag/domain/entity"
|
tagentity "mayfly-go/internal/tag/domain/entity"
|
||||||
"mayfly-go/pkg/base"
|
"mayfly-go/pkg/base"
|
||||||
"mayfly-go/pkg/errorx"
|
"mayfly-go/pkg/errorx"
|
||||||
@@ -19,16 +21,10 @@ import (
|
|||||||
"mayfly-go/pkg/utils/collx"
|
"mayfly-go/pkg/utils/collx"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SaveMachineParam struct {
|
|
||||||
Machine *entity.Machine
|
|
||||||
TagCodePaths []string
|
|
||||||
AuthCerts []*tagentity.ResourceAuthCert
|
|
||||||
}
|
|
||||||
|
|
||||||
type Machine interface {
|
type Machine interface {
|
||||||
base.App[*entity.Machine]
|
base.App[*entity.Machine]
|
||||||
|
|
||||||
SaveMachine(ctx context.Context, param *SaveMachineParam) error
|
SaveMachine(ctx context.Context, param *dto.SaveMachine) error
|
||||||
|
|
||||||
// 测试机器连接
|
// 测试机器连接
|
||||||
TestConn(me *entity.Machine, authCert *tagentity.ResourceAuthCert) error
|
TestConn(me *entity.Machine, authCert *tagentity.ResourceAuthCert) error
|
||||||
@@ -81,7 +77,7 @@ func (m *machineAppImpl) GetMachineList(condition *entity.MachineQuery, pagePara
|
|||||||
return m.GetRepo().GetMachineList(condition, pageParam, toEntity, orderBy...)
|
return m.GetRepo().GetMachineList(condition, pageParam, toEntity, orderBy...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineAppImpl) SaveMachine(ctx context.Context, param *SaveMachineParam) error {
|
func (m *machineAppImpl) SaveMachine(ctx context.Context, param *dto.SaveMachine) error {
|
||||||
me := param.Machine
|
me := param.Machine
|
||||||
tagCodePaths := param.TagCodePaths
|
tagCodePaths := param.TagCodePaths
|
||||||
authCerts := param.AuthCerts
|
authCerts := param.AuthCerts
|
||||||
@@ -119,7 +115,7 @@ func (m *machineAppImpl) SaveMachine(ctx context.Context, param *SaveMachinePara
|
|||||||
})
|
})
|
||||||
|
|
||||||
}, func(ctx context.Context) error {
|
}, func(ctx context.Context) error {
|
||||||
return m.tagApp.SaveResourceTag(ctx, &tagapp.SaveResourceTagParam{
|
return m.tagApp.SaveResourceTag(ctx, &tagdto.SaveResourceTag{
|
||||||
ResourceTag: m.genMachineResourceTag(me, authCerts),
|
ResourceTag: m.genMachineResourceTag(me, authCerts),
|
||||||
ParentTagCodePaths: tagCodePaths,
|
ParentTagCodePaths: tagCodePaths,
|
||||||
})
|
})
|
||||||
@@ -132,7 +128,7 @@ func (m *machineAppImpl) SaveMachine(ctx context.Context, param *SaveMachinePara
|
|||||||
}
|
}
|
||||||
// 如果调整了ssh username等会查不到旧数据,故需要根据id获取旧信息将code赋值给标签进行关联
|
// 如果调整了ssh username等会查不到旧数据,故需要根据id获取旧信息将code赋值给标签进行关联
|
||||||
if oldMachine.Code == "" {
|
if oldMachine.Code == "" {
|
||||||
oldMachine, _ = m.GetById(new(entity.Machine), me.Id)
|
oldMachine, _ = m.GetById(me.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭连接
|
// 关闭连接
|
||||||
@@ -153,7 +149,7 @@ func (m *machineAppImpl) SaveMachine(ctx context.Context, param *SaveMachinePara
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m.tagApp.SaveResourceTag(ctx, &tagapp.SaveResourceTagParam{
|
return m.tagApp.SaveResourceTag(ctx, &tagdto.SaveResourceTag{
|
||||||
ResourceTag: m.genMachineResourceTag(oldMachine, authCerts),
|
ResourceTag: m.genMachineResourceTag(oldMachine, authCerts),
|
||||||
ParentTagCodePaths: tagCodePaths,
|
ParentTagCodePaths: tagCodePaths,
|
||||||
})
|
})
|
||||||
@@ -201,7 +197,7 @@ func (m *machineAppImpl) ChangeStatus(ctx context.Context, id uint64, status int
|
|||||||
|
|
||||||
// 根据条件获取机器信息
|
// 根据条件获取机器信息
|
||||||
func (m *machineAppImpl) Delete(ctx context.Context, id uint64) error {
|
func (m *machineAppImpl) Delete(ctx context.Context, id uint64) error {
|
||||||
machine, err := m.GetById(new(entity.Machine), id)
|
machine, err := m.GetById(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorx.NewBiz("机器信息不存在")
|
return errorx.NewBiz("机器信息不存在")
|
||||||
}
|
}
|
||||||
@@ -216,8 +212,8 @@ func (m *machineAppImpl) Delete(ctx context.Context, id uint64) error {
|
|||||||
func(ctx context.Context) error {
|
func(ctx context.Context) error {
|
||||||
return m.DeleteById(ctx, id)
|
return m.DeleteById(ctx, id)
|
||||||
}, func(ctx context.Context) error {
|
}, func(ctx context.Context) error {
|
||||||
return m.tagApp.SaveResourceTag(ctx, &tagapp.SaveResourceTagParam{
|
return m.tagApp.SaveResourceTag(ctx, &tagdto.SaveResourceTag{
|
||||||
ResourceTag: &tagapp.ResourceTag{
|
ResourceTag: &tagdto.ResourceTag{
|
||||||
Code: machine.Code,
|
Code: machine.Code,
|
||||||
Type: tagentity.TagTypeMachine,
|
Type: tagentity.TagTypeMachine,
|
||||||
},
|
},
|
||||||
@@ -266,9 +262,8 @@ func (m *machineAppImpl) GetSshTunnelMachine(machineId int) (*mcm.SshTunnelMachi
|
|||||||
func (m *machineAppImpl) TimerUpdateStats() {
|
func (m *machineAppImpl) TimerUpdateStats() {
|
||||||
logx.Debug("开始定时收集并缓存服务器状态信息...")
|
logx.Debug("开始定时收集并缓存服务器状态信息...")
|
||||||
scheduler.AddFun("@every 2m", func() {
|
scheduler.AddFun("@every 2m", func() {
|
||||||
machineIds := new([]entity.Machine)
|
machineIds, _ := m.ListByCond(model.NewModelCond(&entity.Machine{Status: entity.MachineStatusEnable, Protocol: entity.MachineProtocolSsh}).Columns("id"))
|
||||||
m.ListByCond(model.NewModelCond(&entity.Machine{Status: entity.MachineStatusEnable, Protocol: entity.MachineProtocolSsh}).Columns("id"), machineIds)
|
for _, ma := range machineIds {
|
||||||
for _, ma := range *machineIds {
|
|
||||||
go func(mid uint64) {
|
go func(mid uint64) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
@@ -320,7 +315,7 @@ func (m *machineAppImpl) ToMachineInfoById(machineId uint64) (*mcm.MachineInfo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineAppImpl) getMachineAndAuthCert(machineId uint64) (*entity.Machine, *tagentity.ResourceAuthCert, error) {
|
func (m *machineAppImpl) getMachineAndAuthCert(machineId uint64) (*entity.Machine, *tagentity.ResourceAuthCert, error) {
|
||||||
me, err := m.GetById(new(entity.Machine), machineId)
|
me, err := m.GetById(machineId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errorx.NewBiz("[%d]机器信息不存在", machineId)
|
return nil, nil, errorx.NewBiz("[%d]机器信息不存在", machineId)
|
||||||
}
|
}
|
||||||
@@ -342,7 +337,7 @@ func (m *machineAppImpl) toMi(me *entity.Machine, authCert *tagentity.ResourceAu
|
|||||||
mi.Name = me.Name
|
mi.Name = me.Name
|
||||||
mi.Ip = me.Ip
|
mi.Ip = me.Ip
|
||||||
mi.Port = me.Port
|
mi.Port = me.Port
|
||||||
mi.TagPath = m.tagApp.ListTagPathByTypeAndCode(int8(tagentity.TagTypeMachineAuthCert), authCert.Name)
|
mi.CodePath = m.tagApp.ListTagPathByTypeAndCode(int8(tagentity.TagTypeMachineAuthCert), authCert.Name)
|
||||||
mi.EnableRecorder = me.EnableRecorder
|
mi.EnableRecorder = me.EnableRecorder
|
||||||
mi.Protocol = me.Protocol
|
mi.Protocol = me.Protocol
|
||||||
|
|
||||||
@@ -363,16 +358,16 @@ func (m *machineAppImpl) toMi(me *entity.Machine, authCert *tagentity.ResourceAu
|
|||||||
return mi, nil
|
return mi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineAppImpl) genMachineResourceTag(me *entity.Machine, authCerts []*tagentity.ResourceAuthCert) *tagapp.ResourceTag {
|
func (m *machineAppImpl) genMachineResourceTag(me *entity.Machine, authCerts []*tagentity.ResourceAuthCert) *tagdto.ResourceTag {
|
||||||
authCertTags := collx.ArrayMap[*tagentity.ResourceAuthCert, *tagapp.ResourceTag](authCerts, func(val *tagentity.ResourceAuthCert) *tagapp.ResourceTag {
|
authCertTags := collx.ArrayMap[*tagentity.ResourceAuthCert, *tagdto.ResourceTag](authCerts, func(val *tagentity.ResourceAuthCert) *tagdto.ResourceTag {
|
||||||
return &tagapp.ResourceTag{
|
return &tagdto.ResourceTag{
|
||||||
Code: val.Name,
|
Code: val.Name,
|
||||||
Name: val.Username,
|
Name: val.Username,
|
||||||
Type: tagentity.TagTypeMachineAuthCert,
|
Type: tagentity.TagTypeMachineAuthCert,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return &tagapp.ResourceTag{
|
return &tagdto.ResourceTag{
|
||||||
Code: me.Code,
|
Code: me.Code,
|
||||||
Type: tagentity.TagTypeMachine,
|
Type: tagentity.TagTypeMachine,
|
||||||
Name: me.Name,
|
Name: me.Name,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package application
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"mayfly-go/internal/machine/application/dto"
|
||||||
"mayfly-go/internal/machine/domain/entity"
|
"mayfly-go/internal/machine/domain/entity"
|
||||||
"mayfly-go/internal/machine/domain/repository"
|
"mayfly-go/internal/machine/domain/repository"
|
||||||
tagapp "mayfly-go/internal/tag/application"
|
tagapp "mayfly-go/internal/tag/application"
|
||||||
@@ -12,11 +13,6 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SaveMachineCmdConfParam struct {
|
|
||||||
CmdConf *entity.MachineCmdConf
|
|
||||||
CodePaths []string
|
|
||||||
}
|
|
||||||
|
|
||||||
type MachineCmd struct {
|
type MachineCmd struct {
|
||||||
CmdRegexp *regexp.Regexp // 命令正则表达式
|
CmdRegexp *regexp.Regexp // 命令正则表达式
|
||||||
Stratege string // 策略(拒绝或审批等)
|
Stratege string // 策略(拒绝或审批等)
|
||||||
@@ -25,11 +21,11 @@ type MachineCmd struct {
|
|||||||
type MachineCmdConf interface {
|
type MachineCmdConf interface {
|
||||||
base.App[*entity.MachineCmdConf]
|
base.App[*entity.MachineCmdConf]
|
||||||
|
|
||||||
SaveCmdConf(ctx context.Context, cmdConf *SaveMachineCmdConfParam) error
|
SaveCmdConf(ctx context.Context, cmdConf *dto.SaveMachineCmdConf) error
|
||||||
|
|
||||||
DeleteCmdConf(ctx context.Context, id uint64) error
|
DeleteCmdConf(ctx context.Context, id uint64) error
|
||||||
|
|
||||||
GetCmdConfsByMachineTags(tagPaths ...string) []*MachineCmd
|
GetCmdConfsByMachineTags(ctx context.Context, tagPaths ...string) []*MachineCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
type machineCmdConfAppImpl struct {
|
type machineCmdConfAppImpl struct {
|
||||||
@@ -45,7 +41,7 @@ func (m *machineCmdConfAppImpl) InjectMachineCmdConfRepo(repo repository.Machine
|
|||||||
m.Repo = repo
|
m.Repo = repo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineCmdConfAppImpl) SaveCmdConf(ctx context.Context, cmdConfParam *SaveMachineCmdConfParam) error {
|
func (m *machineCmdConfAppImpl) SaveCmdConf(ctx context.Context, cmdConfParam *dto.SaveMachineCmdConf) error {
|
||||||
cmdConf := cmdConfParam.CmdConf
|
cmdConf := cmdConfParam.CmdConf
|
||||||
|
|
||||||
return m.Tx(ctx, func(ctx context.Context) error {
|
return m.Tx(ctx, func(ctx context.Context) error {
|
||||||
@@ -56,7 +52,7 @@ func (m *machineCmdConfAppImpl) SaveCmdConf(ctx context.Context, cmdConfParam *S
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineCmdConfAppImpl) DeleteCmdConf(ctx context.Context, id uint64) error {
|
func (m *machineCmdConfAppImpl) DeleteCmdConf(ctx context.Context, id uint64) error {
|
||||||
_, err := m.GetById(new(entity.MachineCmdConf), id)
|
_, err := m.GetById(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorx.NewBiz("该命令配置不存在")
|
return errorx.NewBiz("该命令配置不存在")
|
||||||
}
|
}
|
||||||
@@ -71,9 +67,9 @@ func (m *machineCmdConfAppImpl) DeleteCmdConf(ctx context.Context, id uint64) er
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineCmdConfAppImpl) GetCmdConfsByMachineTags(tagPaths ...string) []*MachineCmd {
|
func (m *machineCmdConfAppImpl) GetCmdConfsByMachineTags(ctx context.Context, tagPaths ...string) []*MachineCmd {
|
||||||
var cmds []*MachineCmd
|
var cmds []*MachineCmd
|
||||||
cmdConfIds, err := m.tagTreeRelateApp.GetRelateIds(tagentity.TagRelateTypeMachineCmd, tagPaths...)
|
cmdConfIds, err := m.tagTreeRelateApp.GetRelateIds(ctx, tagentity.TagRelateTypeMachineCmd, tagPaths...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logx.Errorf("获取命令配置信息失败: %s", err.Error())
|
logx.Errorf("获取命令配置信息失败: %s", err.Error())
|
||||||
return cmds
|
return cmds
|
||||||
@@ -82,9 +78,7 @@ func (m *machineCmdConfAppImpl) GetCmdConfsByMachineTags(tagPaths ...string) []*
|
|||||||
return cmds
|
return cmds
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmdConfs []*entity.MachineCmdConf
|
cmdConfs, _ := m.GetByIds(cmdConfIds)
|
||||||
m.GetByIds(&cmdConfs, cmdConfIds)
|
|
||||||
|
|
||||||
for _, cmdConf := range cmdConfs {
|
for _, cmdConf := range cmdConfs {
|
||||||
for _, cmd := range cmdConf.Cmds {
|
for _, cmd := range cmdConf.Cmds {
|
||||||
if p, err := regexp.Compile(cmd); err != nil {
|
if p, err := regexp.Compile(cmd); err != nil {
|
||||||
|
|||||||
@@ -2,8 +2,11 @@ package application
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"mayfly-go/internal/machine/application/dto"
|
||||||
"mayfly-go/internal/machine/domain/entity"
|
"mayfly-go/internal/machine/domain/entity"
|
||||||
"mayfly-go/internal/machine/domain/repository"
|
"mayfly-go/internal/machine/domain/repository"
|
||||||
|
tagapp "mayfly-go/internal/tag/application"
|
||||||
|
tagentity "mayfly-go/internal/tag/domain/entity"
|
||||||
"mayfly-go/pkg/base"
|
"mayfly-go/pkg/base"
|
||||||
"mayfly-go/pkg/biz"
|
"mayfly-go/pkg/biz"
|
||||||
"mayfly-go/pkg/errorx"
|
"mayfly-go/pkg/errorx"
|
||||||
@@ -26,22 +29,10 @@ type MachineCronJob interface {
|
|||||||
// 获取分页执行结果列表
|
// 获取分页执行结果列表
|
||||||
GetExecPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
GetExecPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error)
|
||||||
|
|
||||||
SaveMachineCronJob(ctx context.Context, entity *entity.MachineCronJob) (uint64, error)
|
SaveMachineCronJob(ctx context.Context, param *dto.SaveMachineCronJob) error
|
||||||
|
|
||||||
Delete(ctx context.Context, id uint64)
|
Delete(ctx context.Context, id uint64)
|
||||||
|
|
||||||
// 获取计划任务关联的机器列表id
|
|
||||||
GetRelateMachineIds(cronJobId uint64) []uint64
|
|
||||||
|
|
||||||
// 获取机器关联的计划任务列表
|
|
||||||
GetRelateCronJobIds(machineId uint64) []uint64
|
|
||||||
|
|
||||||
// 计划任务关联机器
|
|
||||||
CronJobRelateMachines(ctx context.Context, cronJobId uint64, machineIds []uint64)
|
|
||||||
|
|
||||||
// 机器关联计划任务
|
|
||||||
MachineRelateCronJobs(ctx context.Context, machineId uint64, cronJobs []uint64)
|
|
||||||
|
|
||||||
// 初始化计划任务
|
// 初始化计划任务
|
||||||
InitCronJob()
|
InitCronJob()
|
||||||
|
|
||||||
@@ -53,11 +44,15 @@ type MachineCronJob interface {
|
|||||||
type machineCronJobAppImpl struct {
|
type machineCronJobAppImpl struct {
|
||||||
base.AppImpl[*entity.MachineCronJob, repository.MachineCronJob]
|
base.AppImpl[*entity.MachineCronJob, repository.MachineCronJob]
|
||||||
|
|
||||||
machineCronJobRelateRepo repository.MachineCronJobRelate `inject:"MachineCronJobRelateRepo"`
|
machineCronJobExecRepo repository.MachineCronJobExec `inject:"MachineCronJobExecRepo"`
|
||||||
machineCronJobExecRepo repository.MachineCronJobExec `inject:"MachineCronJobExecRepo"`
|
machineApp Machine `inject:"MachineApp"`
|
||||||
machineApp Machine `inject:"MachineApp"`
|
|
||||||
|
tagTreeApp tagapp.TagTree `inject:"TagTreeApp"`
|
||||||
|
tagTreeRelateApp tagapp.TagTreeRelate `inject:"TagTreeRelateApp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ (MachineCronJob) = (*machineCronJobAppImpl)(nil)
|
||||||
|
|
||||||
// 注入MachineCronJobRepo
|
// 注入MachineCronJobRepo
|
||||||
func (m *machineCronJobAppImpl) InjectMachineCronJobRepo(repo repository.MachineCronJob) {
|
func (m *machineCronJobAppImpl) InjectMachineCronJobRepo(repo repository.MachineCronJob) {
|
||||||
m.Repo = repo
|
m.Repo = repo
|
||||||
@@ -74,79 +69,36 @@ func (m *machineCronJobAppImpl) GetExecPageList(condition *entity.MachineCronJob
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 保存机器任务信息
|
// 保存机器任务信息
|
||||||
func (m *machineCronJobAppImpl) SaveMachineCronJob(ctx context.Context, mcj *entity.MachineCronJob) (uint64, error) {
|
func (m *machineCronJobAppImpl) SaveMachineCronJob(ctx context.Context, param *dto.SaveMachineCronJob) error {
|
||||||
// 更新操作
|
mcj := param.CronJob
|
||||||
if mcj.Id != 0 {
|
|
||||||
m.UpdateById(ctx, mcj)
|
// 赋值cron job key
|
||||||
cj, err := m.GetById(new(entity.MachineCronJob), mcj.Id)
|
if mcj.Id == 0 {
|
||||||
|
mcj.Key = stringx.Rand(16)
|
||||||
|
} else {
|
||||||
|
oldMcj, err := m.GetById(mcj.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errorx.NewBiz("该任务不存在")
|
return errorx.NewBiz("该计划任务不存在")
|
||||||
}
|
}
|
||||||
// 处理最新的计划任务
|
mcj.Key = oldMcj.Key
|
||||||
m.addCronJob(cj)
|
}
|
||||||
return mcj.Id, nil
|
|
||||||
|
err := m.Tx(ctx, func(ctx context.Context) error {
|
||||||
|
return m.Save(ctx, mcj)
|
||||||
|
}, func(ctx context.Context) error {
|
||||||
|
return m.tagTreeRelateApp.RelateTag(ctx, tagentity.TagRelateTypeMachineCronJob, mcj.Id, param.CodePaths...)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
m.addCronJob(mcj)
|
m.addCronJob(mcj)
|
||||||
if err := m.Insert(ctx, mcj); err != nil {
|
return nil
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return mcj.Id, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineCronJobAppImpl) Delete(ctx context.Context, id uint64) {
|
func (m *machineCronJobAppImpl) Delete(ctx context.Context, id uint64) {
|
||||||
m.DeleteById(ctx, id)
|
m.DeleteById(ctx, id)
|
||||||
m.machineCronJobExecRepo.DeleteByCond(ctx, &entity.MachineCronJobExec{CronJobId: id})
|
m.machineCronJobExecRepo.DeleteByCond(ctx, &entity.MachineCronJobExec{CronJobId: id})
|
||||||
m.machineCronJobRelateRepo.DeleteByCond(ctx, &entity.MachineCronJobRelate{CronJobId: id})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *machineCronJobAppImpl) GetRelateMachineIds(cronJobId uint64) []uint64 {
|
|
||||||
return m.machineCronJobRelateRepo.GetMachineIds(cronJobId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *machineCronJobAppImpl) GetRelateCronJobIds(machineId uint64) []uint64 {
|
|
||||||
return m.machineCronJobRelateRepo.GetCronJobIds(machineId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *machineCronJobAppImpl) CronJobRelateMachines(ctx context.Context, cronJobId uint64, machineIds []uint64) {
|
|
||||||
oldMachineIds := m.machineCronJobRelateRepo.GetMachineIds(cronJobId)
|
|
||||||
addIds, delIds, _ := collx.ArrayCompare[uint64](machineIds, oldMachineIds)
|
|
||||||
addVals := make([]*entity.MachineCronJobRelate, 0)
|
|
||||||
|
|
||||||
for _, addId := range addIds {
|
|
||||||
addVals = append(addVals, &entity.MachineCronJobRelate{
|
|
||||||
MachineId: addId,
|
|
||||||
CronJobId: cronJobId,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
m.machineCronJobRelateRepo.BatchInsert(ctx, addVals)
|
|
||||||
|
|
||||||
for _, delId := range delIds {
|
|
||||||
m.machineCronJobRelateRepo.DeleteByCond(ctx, &entity.MachineCronJobRelate{CronJobId: cronJobId, MachineId: delId})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *machineCronJobAppImpl) MachineRelateCronJobs(ctx context.Context, machineId uint64, cronJobs []uint64) {
|
|
||||||
if len(cronJobs) == 0 {
|
|
||||||
m.machineCronJobRelateRepo.DeleteByCond(ctx, &entity.MachineCronJobRelate{MachineId: machineId})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
oldCronIds := m.machineCronJobRelateRepo.GetCronJobIds(machineId)
|
|
||||||
addIds, delIds, _ := collx.ArrayCompare[uint64](cronJobs, oldCronIds)
|
|
||||||
addVals := make([]*entity.MachineCronJobRelate, 0)
|
|
||||||
|
|
||||||
for _, addId := range addIds {
|
|
||||||
addVals = append(addVals, &entity.MachineCronJobRelate{
|
|
||||||
MachineId: machineId,
|
|
||||||
CronJobId: addId,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
m.machineCronJobRelateRepo.BatchInsert(ctx, addVals)
|
|
||||||
|
|
||||||
for _, delId := range delIds {
|
|
||||||
m.machineCronJobRelateRepo.DeleteByCond(ctx, &entity.MachineCronJobRelate{CronJobId: delId, MachineId: machineId})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineCronJobAppImpl) InitCronJob() {
|
func (m *machineCronJobAppImpl) InitCronJob() {
|
||||||
@@ -160,17 +112,16 @@ func (m *machineCronJobAppImpl) InitCronJob() {
|
|||||||
PageSize: 100,
|
PageSize: 100,
|
||||||
PageNum: 1,
|
PageNum: 1,
|
||||||
}
|
}
|
||||||
cond := new(entity.MachineCronJob)
|
|
||||||
cond.Status = entity.MachineCronJobStatusEnable
|
|
||||||
mcjs := new([]entity.MachineCronJob)
|
|
||||||
|
|
||||||
pr, _ := m.GetPageList(cond, pageParam, mcjs)
|
var mcjs []*entity.MachineCronJob
|
||||||
|
cond := &entity.MachineCronJob{Status: entity.MachineCronJobStatusEnable}
|
||||||
|
pr, _ := m.GetPageList(cond, pageParam, &mcjs)
|
||||||
total := pr.Total
|
total := pr.Total
|
||||||
add := 0
|
add := 0
|
||||||
|
|
||||||
for {
|
for {
|
||||||
for _, mcj := range *mcjs {
|
for _, mcj := range mcjs {
|
||||||
m.addCronJob(&mcj)
|
m.addCronJob(mcj)
|
||||||
add++
|
add++
|
||||||
}
|
}
|
||||||
if add >= int(total) {
|
if add >= int(total) {
|
||||||
@@ -197,26 +148,24 @@ func (m *machineCronJobAppImpl) RunCronJob(key string) {
|
|||||||
// 不存在或禁用,则移除该任务
|
// 不存在或禁用,则移除该任务
|
||||||
if err != nil || cronJob.Status == entity.MachineCronJobStatusDisable {
|
if err != nil || cronJob.Status == entity.MachineCronJobStatusDisable {
|
||||||
scheduler.RemoveByKey(key)
|
scheduler.RemoveByKey(key)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
machienIds := m.machineCronJobRelateRepo.GetMachineIds(cronJob.Id)
|
relateCodePaths := m.tagTreeRelateApp.GetTagPathsByRelate(tagentity.TagRelateTypeMachineCronJob, cronJob.Id)
|
||||||
for _, machineId := range machienIds {
|
var machineTags []tagentity.TagTree
|
||||||
go m.runCronJob0(machineId, cronJob)
|
m.tagTreeApp.ListByQuery(&tagentity.TagTreeQuery{CodePathLikes: relateCodePaths, Type: tagentity.TagTypeMachine}, &machineTags)
|
||||||
|
machines, _ := m.machineApp.ListByCond(model.NewCond().In("code", collx.ArrayMap(machineTags, func(tag tagentity.TagTree) string {
|
||||||
|
return tag.Code
|
||||||
|
})), "id")
|
||||||
|
|
||||||
|
for _, machine := range machines {
|
||||||
|
go m.runCronJob0(machine.Id, cronJob)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineCronJobAppImpl) addCronJob(mcj *entity.MachineCronJob) {
|
func (m *machineCronJobAppImpl) addCronJob(mcj *entity.MachineCronJob) {
|
||||||
var key string
|
key := mcj.Key
|
||||||
isDisable := mcj.Status == entity.MachineCronJobStatusDisable
|
isDisable := mcj.Status == entity.MachineCronJobStatusDisable
|
||||||
if mcj.Id == 0 {
|
|
||||||
key = stringx.Rand(16)
|
|
||||||
mcj.Key = key
|
|
||||||
if isDisable {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
key = mcj.Key
|
|
||||||
}
|
|
||||||
|
|
||||||
if isDisable {
|
if isDisable {
|
||||||
scheduler.RemoveByKey(key)
|
scheduler.RemoveByKey(key)
|
||||||
@@ -227,6 +176,7 @@ func (m *machineCronJobAppImpl) addCronJob(mcj *entity.MachineCronJob) {
|
|||||||
m.RunCronJob(key)
|
m.RunCronJob(key)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineCronJobAppImpl) runCronJob0(mid uint64, cronJob *entity.MachineCronJob) {
|
func (m *machineCronJobAppImpl) runCronJob0(mid uint64, cronJob *entity.MachineCronJob) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
"mayfly-go/internal/machine/application/dto"
|
||||||
"mayfly-go/internal/machine/config"
|
"mayfly-go/internal/machine/config"
|
||||||
"mayfly-go/internal/machine/domain/entity"
|
"mayfly-go/internal/machine/domain/entity"
|
||||||
"mayfly-go/internal/machine/domain/repository"
|
"mayfly-go/internal/machine/domain/repository"
|
||||||
@@ -25,14 +26,6 @@ import (
|
|||||||
"github.com/pkg/sftp"
|
"github.com/pkg/sftp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MachineFileOpParam struct {
|
|
||||||
Ua *model.LoginAccount
|
|
||||||
MachineId uint64 `json:"machineId" binding:"required" form:"machineId"`
|
|
||||||
Protocol int `json:"protocol" binding:"required" form:"protocol"`
|
|
||||||
AuthCertName string `json:"authCertName" binding:"required" form:"authCertName"` // 授权凭证
|
|
||||||
Path string `json:"path" form:"path"` // 文件路径
|
|
||||||
}
|
|
||||||
|
|
||||||
type MachineFile interface {
|
type MachineFile interface {
|
||||||
base.App[*entity.MachineFile]
|
base.App[*entity.MachineFile]
|
||||||
|
|
||||||
@@ -52,39 +45,39 @@ type MachineFile interface {
|
|||||||
/** sftp 相关操作 **/
|
/** sftp 相关操作 **/
|
||||||
|
|
||||||
// 创建目录
|
// 创建目录
|
||||||
MkDir(ctx context.Context, opParam *MachineFileOpParam) (*mcm.MachineInfo, error)
|
MkDir(ctx context.Context, opParam *dto.MachineFileOp) (*mcm.MachineInfo, error)
|
||||||
|
|
||||||
// 创建文件
|
// 创建文件
|
||||||
CreateFile(ctx context.Context, opParam *MachineFileOpParam) (*mcm.MachineInfo, error)
|
CreateFile(ctx context.Context, opParam *dto.MachineFileOp) (*mcm.MachineInfo, error)
|
||||||
|
|
||||||
// 读取目录
|
// 读取目录
|
||||||
ReadDir(ctx context.Context, opParam *MachineFileOpParam) ([]fs.FileInfo, error)
|
ReadDir(ctx context.Context, opParam *dto.MachineFileOp) ([]fs.FileInfo, error)
|
||||||
|
|
||||||
// 获取指定目录内容大小
|
// 获取指定目录内容大小
|
||||||
GetDirSize(ctx context.Context, opParam *MachineFileOpParam) (string, error)
|
GetDirSize(ctx context.Context, opParam *dto.MachineFileOp) (string, error)
|
||||||
|
|
||||||
// 获取文件stat
|
// 获取文件stat
|
||||||
FileStat(ctx context.Context, opParam *MachineFileOpParam) (string, error)
|
FileStat(ctx context.Context, opParam *dto.MachineFileOp) (string, error)
|
||||||
|
|
||||||
// 读取文件内容
|
// 读取文件内容
|
||||||
ReadFile(ctx context.Context, opParam *MachineFileOpParam) (*sftp.File, *mcm.MachineInfo, error)
|
ReadFile(ctx context.Context, opParam *dto.MachineFileOp) (*sftp.File, *mcm.MachineInfo, error)
|
||||||
|
|
||||||
// 写文件
|
// 写文件
|
||||||
WriteFileContent(ctx context.Context, opParam *MachineFileOpParam, content []byte) (*mcm.MachineInfo, error)
|
WriteFileContent(ctx context.Context, opParam *dto.MachineFileOp, content []byte) (*mcm.MachineInfo, error)
|
||||||
|
|
||||||
// 文件上传
|
// 文件上传
|
||||||
UploadFile(ctx context.Context, opParam *MachineFileOpParam, filename string, reader io.Reader) (*mcm.MachineInfo, error)
|
UploadFile(ctx context.Context, opParam *dto.MachineFileOp, filename string, reader io.Reader) (*mcm.MachineInfo, error)
|
||||||
|
|
||||||
UploadFiles(ctx context.Context, opParam *MachineFileOpParam, basePath string, fileHeaders []*multipart.FileHeader, paths []string) (*mcm.MachineInfo, error)
|
UploadFiles(ctx context.Context, opParam *dto.MachineFileOp, basePath string, fileHeaders []*multipart.FileHeader, paths []string) (*mcm.MachineInfo, error)
|
||||||
|
|
||||||
// 移除文件
|
// 移除文件
|
||||||
RemoveFile(ctx context.Context, opParam *MachineFileOpParam, path ...string) (*mcm.MachineInfo, error)
|
RemoveFile(ctx context.Context, opParam *dto.MachineFileOp, path ...string) (*mcm.MachineInfo, error)
|
||||||
|
|
||||||
Copy(ctx context.Context, opParam *MachineFileOpParam, toPath string, path ...string) (*mcm.MachineInfo, error)
|
Copy(ctx context.Context, opParam *dto.MachineFileOp, toPath string, path ...string) (*mcm.MachineInfo, error)
|
||||||
|
|
||||||
Mv(ctx context.Context, opParam *MachineFileOpParam, toPath string, path ...string) (*mcm.MachineInfo, error)
|
Mv(ctx context.Context, opParam *dto.MachineFileOp, toPath string, path ...string) (*mcm.MachineInfo, error)
|
||||||
|
|
||||||
Rename(ctx context.Context, opParam *MachineFileOpParam, newname string) (*mcm.MachineInfo, error)
|
Rename(ctx context.Context, opParam *dto.MachineFileOp, newname string) (*mcm.MachineInfo, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type machineFileAppImpl struct {
|
type machineFileAppImpl struct {
|
||||||
@@ -110,7 +103,7 @@ func (m *machineFileAppImpl) GetMachineFile(condition *entity.MachineFile, cols
|
|||||||
|
|
||||||
// 保存机器文件配置
|
// 保存机器文件配置
|
||||||
func (m *machineFileAppImpl) Save(ctx context.Context, mf *entity.MachineFile) error {
|
func (m *machineFileAppImpl) Save(ctx context.Context, mf *entity.MachineFile) error {
|
||||||
_, err := m.machineApp.GetById(new(entity.Machine), mf.MachineId, "Name")
|
_, err := m.machineApp.GetById(mf.MachineId, "Name")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorx.NewBiz("该机器不存在")
|
return errorx.NewBiz("该机器不存在")
|
||||||
}
|
}
|
||||||
@@ -122,7 +115,7 @@ func (m *machineFileAppImpl) Save(ctx context.Context, mf *entity.MachineFile) e
|
|||||||
return m.Insert(ctx, mf)
|
return m.Insert(ctx, mf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineFileAppImpl) ReadDir(ctx context.Context, opParam *MachineFileOpParam) ([]fs.FileInfo, error) {
|
func (m *machineFileAppImpl) ReadDir(ctx context.Context, opParam *dto.MachineFileOp) ([]fs.FileInfo, error) {
|
||||||
path := opParam.Path
|
path := opParam.Path
|
||||||
if !strings.HasSuffix(path, "/") {
|
if !strings.HasSuffix(path, "/") {
|
||||||
path = path + "/"
|
path = path + "/"
|
||||||
@@ -148,7 +141,7 @@ func (m *machineFileAppImpl) ReadDir(ctx context.Context, opParam *MachineFileOp
|
|||||||
return sftpCli.ReadDir(path)
|
return sftpCli.ReadDir(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineFileAppImpl) GetDirSize(ctx context.Context, opParam *MachineFileOpParam) (string, error) {
|
func (m *machineFileAppImpl) GetDirSize(ctx context.Context, opParam *dto.MachineFileOp) (string, error) {
|
||||||
path := opParam.Path
|
path := opParam.Path
|
||||||
|
|
||||||
if opParam.Protocol == entity.MachineProtocolRdp {
|
if opParam.Protocol == entity.MachineProtocolRdp {
|
||||||
@@ -197,7 +190,7 @@ func (m *machineFileAppImpl) GetDirSize(ctx context.Context, opParam *MachineFil
|
|||||||
return strings.Split(res, "\t")[0], nil
|
return strings.Split(res, "\t")[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineFileAppImpl) FileStat(ctx context.Context, opParam *MachineFileOpParam) (string, error) {
|
func (m *machineFileAppImpl) FileStat(ctx context.Context, opParam *dto.MachineFileOp) (string, error) {
|
||||||
path := opParam.Path
|
path := opParam.Path
|
||||||
if opParam.Protocol == entity.MachineProtocolRdp {
|
if opParam.Protocol == entity.MachineProtocolRdp {
|
||||||
path = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), path)
|
path = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), path)
|
||||||
@@ -212,7 +205,7 @@ func (m *machineFileAppImpl) FileStat(ctx context.Context, opParam *MachineFileO
|
|||||||
return mcli.Run(fmt.Sprintf("stat -L %s", path))
|
return mcli.Run(fmt.Sprintf("stat -L %s", path))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineFileAppImpl) MkDir(ctx context.Context, opParam *MachineFileOpParam) (*mcm.MachineInfo, error) {
|
func (m *machineFileAppImpl) MkDir(ctx context.Context, opParam *dto.MachineFileOp) (*mcm.MachineInfo, error) {
|
||||||
path := opParam.Path
|
path := opParam.Path
|
||||||
if !strings.HasSuffix(path, "/") {
|
if !strings.HasSuffix(path, "/") {
|
||||||
path = path + "/"
|
path = path + "/"
|
||||||
@@ -221,7 +214,7 @@ func (m *machineFileAppImpl) MkDir(ctx context.Context, opParam *MachineFileOpPa
|
|||||||
if opParam.Protocol == entity.MachineProtocolRdp {
|
if opParam.Protocol == entity.MachineProtocolRdp {
|
||||||
path = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), path)
|
path = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), path)
|
||||||
os.MkdirAll(path, os.ModePerm)
|
os.MkdirAll(path, os.ModePerm)
|
||||||
return nil, nil
|
return &mcm.MachineInfo{Name: opParam.AuthCertName, Ip: opParam.AuthCertName}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mi, sftpCli, err := m.GetMachineSftpCli(opParam)
|
mi, sftpCli, err := m.GetMachineSftpCli(opParam)
|
||||||
@@ -233,13 +226,16 @@ func (m *machineFileAppImpl) MkDir(ctx context.Context, opParam *MachineFileOpPa
|
|||||||
return mi, err
|
return mi, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineFileAppImpl) CreateFile(ctx context.Context, opParam *MachineFileOpParam) (*mcm.MachineInfo, error) {
|
func (m *machineFileAppImpl) CreateFile(ctx context.Context, opParam *dto.MachineFileOp) (*mcm.MachineInfo, error) {
|
||||||
path := opParam.Path
|
path := opParam.Path
|
||||||
if opParam.Protocol == entity.MachineProtocolRdp {
|
if opParam.Protocol == entity.MachineProtocolRdp {
|
||||||
path = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), path)
|
path = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), path)
|
||||||
file, err := os.Create(path)
|
file, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
return nil, err
|
return &mcm.MachineInfo{Name: opParam.AuthCertName, Ip: opParam.AuthCertName}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mi, sftpCli, err := m.GetMachineSftpCli(opParam)
|
mi, sftpCli, err := m.GetMachineSftpCli(opParam)
|
||||||
@@ -254,7 +250,7 @@ func (m *machineFileAppImpl) CreateFile(ctx context.Context, opParam *MachineFil
|
|||||||
return mi, err
|
return mi, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineFileAppImpl) ReadFile(ctx context.Context, opParam *MachineFileOpParam) (*sftp.File, *mcm.MachineInfo, error) {
|
func (m *machineFileAppImpl) ReadFile(ctx context.Context, opParam *dto.MachineFileOp) (*sftp.File, *mcm.MachineInfo, error) {
|
||||||
mi, sftpCli, err := m.GetMachineSftpCli(opParam)
|
mi, sftpCli, err := m.GetMachineSftpCli(opParam)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@@ -266,17 +262,17 @@ func (m *machineFileAppImpl) ReadFile(ctx context.Context, opParam *MachineFileO
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 写文件内容
|
// 写文件内容
|
||||||
func (m *machineFileAppImpl) WriteFileContent(ctx context.Context, opParam *MachineFileOpParam, content []byte) (*mcm.MachineInfo, error) {
|
func (m *machineFileAppImpl) WriteFileContent(ctx context.Context, opParam *dto.MachineFileOp, content []byte) (*mcm.MachineInfo, error) {
|
||||||
path := opParam.Path
|
path := opParam.Path
|
||||||
if opParam.Protocol == entity.MachineProtocolRdp {
|
if opParam.Protocol == entity.MachineProtocolRdp {
|
||||||
path = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), path)
|
path = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), path)
|
||||||
file, err := os.Create(path)
|
file, err := os.Create(path)
|
||||||
defer file.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer file.Close()
|
||||||
file.Write(content)
|
file.Write(content)
|
||||||
return nil, err
|
return &mcm.MachineInfo{Name: opParam.AuthCertName, Ip: opParam.AuthCertName}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mi, sftpCli, err := m.GetMachineSftpCli(opParam)
|
mi, sftpCli, err := m.GetMachineSftpCli(opParam)
|
||||||
@@ -294,7 +290,7 @@ func (m *machineFileAppImpl) WriteFileContent(ctx context.Context, opParam *Mach
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 上传文件
|
// 上传文件
|
||||||
func (m *machineFileAppImpl) UploadFile(ctx context.Context, opParam *MachineFileOpParam, filename string, reader io.Reader) (*mcm.MachineInfo, error) {
|
func (m *machineFileAppImpl) UploadFile(ctx context.Context, opParam *dto.MachineFileOp, filename string, reader io.Reader) (*mcm.MachineInfo, error) {
|
||||||
path := opParam.Path
|
path := opParam.Path
|
||||||
if !strings.HasSuffix(path, "/") {
|
if !strings.HasSuffix(path, "/") {
|
||||||
path = path + "/"
|
path = path + "/"
|
||||||
@@ -303,12 +299,12 @@ func (m *machineFileAppImpl) UploadFile(ctx context.Context, opParam *MachineFil
|
|||||||
if opParam.Protocol == entity.MachineProtocolRdp {
|
if opParam.Protocol == entity.MachineProtocolRdp {
|
||||||
path = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), path)
|
path = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), path)
|
||||||
file, err := os.Create(path + filename)
|
file, err := os.Create(path + filename)
|
||||||
defer file.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer file.Close()
|
||||||
io.Copy(file, reader)
|
io.Copy(file, reader)
|
||||||
return nil, nil
|
return &mcm.MachineInfo{Name: opParam.AuthCertName, Ip: opParam.AuthCertName}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mi, sftpCli, err := m.GetMachineSftpCli(opParam)
|
mi, sftpCli, err := m.GetMachineSftpCli(opParam)
|
||||||
@@ -325,7 +321,7 @@ func (m *machineFileAppImpl) UploadFile(ctx context.Context, opParam *MachineFil
|
|||||||
return mi, err
|
return mi, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineFileAppImpl) UploadFiles(ctx context.Context, opParam *MachineFileOpParam, basePath string, fileHeaders []*multipart.FileHeader, paths []string) (*mcm.MachineInfo, error) {
|
func (m *machineFileAppImpl) UploadFiles(ctx context.Context, opParam *dto.MachineFileOp, basePath string, fileHeaders []*multipart.FileHeader, paths []string) (*mcm.MachineInfo, error) {
|
||||||
if opParam.Protocol == entity.MachineProtocolRdp {
|
if opParam.Protocol == entity.MachineProtocolRdp {
|
||||||
baseFolder := m.GetRdpFilePath(contextx.GetLoginAccount(ctx), basePath)
|
baseFolder := m.GetRdpFilePath(contextx.GetLoginAccount(ctx), basePath)
|
||||||
|
|
||||||
@@ -342,7 +338,7 @@ func (m *machineFileAppImpl) UploadFiles(ctx context.Context, opParam *MachineFi
|
|||||||
rdpBaseDir = rdpBaseDir + "/"
|
rdpBaseDir = rdpBaseDir + "/"
|
||||||
}
|
}
|
||||||
rdpDir := filepath.Dir(rdpBaseDir + paths[i])
|
rdpDir := filepath.Dir(rdpBaseDir + paths[i])
|
||||||
m.MkDir(ctx, &MachineFileOpParam{
|
m.MkDir(ctx, &dto.MachineFileOp{
|
||||||
MachineId: opParam.MachineId,
|
MachineId: opParam.MachineId,
|
||||||
Protocol: opParam.Protocol,
|
Protocol: opParam.Protocol,
|
||||||
Path: rdpDir,
|
Path: rdpDir,
|
||||||
@@ -364,11 +360,11 @@ func (m *machineFileAppImpl) UploadFiles(ctx context.Context, opParam *MachineFi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return &mcm.MachineInfo{Name: opParam.AuthCertName, Ip: opParam.AuthCertName}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除文件
|
// 删除文件
|
||||||
func (m *machineFileAppImpl) RemoveFile(ctx context.Context, opParam *MachineFileOpParam, path ...string) (*mcm.MachineInfo, error) {
|
func (m *machineFileAppImpl) RemoveFile(ctx context.Context, opParam *dto.MachineFileOp, path ...string) (*mcm.MachineInfo, error) {
|
||||||
if opParam.Protocol == entity.MachineProtocolRdp {
|
if opParam.Protocol == entity.MachineProtocolRdp {
|
||||||
for _, pt := range path {
|
for _, pt := range path {
|
||||||
pt = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), pt)
|
pt = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), pt)
|
||||||
@@ -404,7 +400,7 @@ func (m *machineFileAppImpl) RemoveFile(ctx context.Context, opParam *MachineFil
|
|||||||
return minfo, err
|
return minfo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineFileAppImpl) Copy(ctx context.Context, opParam *MachineFileOpParam, toPath string, path ...string) (*mcm.MachineInfo, error) {
|
func (m *machineFileAppImpl) Copy(ctx context.Context, opParam *dto.MachineFileOp, toPath string, path ...string) (*mcm.MachineInfo, error) {
|
||||||
if opParam.Protocol == entity.MachineProtocolRdp {
|
if opParam.Protocol == entity.MachineProtocolRdp {
|
||||||
for _, pt := range path {
|
for _, pt := range path {
|
||||||
srcPath := m.GetRdpFilePath(contextx.GetLoginAccount(ctx), pt)
|
srcPath := m.GetRdpFilePath(contextx.GetLoginAccount(ctx), pt)
|
||||||
@@ -440,7 +436,7 @@ func (m *machineFileAppImpl) Copy(ctx context.Context, opParam *MachineFileOpPar
|
|||||||
return mi, err
|
return mi, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineFileAppImpl) Mv(ctx context.Context, opParam *MachineFileOpParam, toPath string, path ...string) (*mcm.MachineInfo, error) {
|
func (m *machineFileAppImpl) Mv(ctx context.Context, opParam *dto.MachineFileOp, toPath string, path ...string) (*mcm.MachineInfo, error) {
|
||||||
if opParam.Protocol == entity.MachineProtocolRdp {
|
if opParam.Protocol == entity.MachineProtocolRdp {
|
||||||
for _, pt := range path {
|
for _, pt := range path {
|
||||||
// 获取文件名
|
// 获取文件名
|
||||||
@@ -469,7 +465,7 @@ func (m *machineFileAppImpl) Mv(ctx context.Context, opParam *MachineFileOpParam
|
|||||||
return mi, err
|
return mi, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *machineFileAppImpl) Rename(ctx context.Context, opParam *MachineFileOpParam, newname string) (*mcm.MachineInfo, error) {
|
func (m *machineFileAppImpl) Rename(ctx context.Context, opParam *dto.MachineFileOp, newname string) (*mcm.MachineInfo, error) {
|
||||||
oldname := opParam.Path
|
oldname := opParam.Path
|
||||||
if opParam.Protocol == entity.MachineProtocolRdp {
|
if opParam.Protocol == entity.MachineProtocolRdp {
|
||||||
oldname = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), oldname)
|
oldname = m.GetRdpFilePath(contextx.GetLoginAccount(ctx), oldname)
|
||||||
@@ -490,7 +486,7 @@ func (m *machineFileAppImpl) GetMachineCli(authCertName string) (*mcm.Cli, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取文件机器 sftp cli
|
// 获取文件机器 sftp cli
|
||||||
func (m *machineFileAppImpl) GetMachineSftpCli(opParam *MachineFileOpParam) (*mcm.MachineInfo, *sftp.Client, error) {
|
func (m *machineFileAppImpl) GetMachineSftpCli(opParam *dto.MachineFileOp) (*mcm.MachineInfo, *sftp.Client, error) {
|
||||||
mcli, err := m.GetMachineCli(opParam.AuthCertName)
|
mcli, err := m.GetMachineCli(opParam.AuthCertName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func (m *machineScriptAppImpl) GetPageList(condition *entity.MachineScript, page
|
|||||||
func (m *machineScriptAppImpl) Save(ctx context.Context, ms *entity.MachineScript) error {
|
func (m *machineScriptAppImpl) Save(ctx context.Context, ms *entity.MachineScript) error {
|
||||||
// 如果机器id不为公共脚本id,则校验机器是否存在
|
// 如果机器id不为公共脚本id,则校验机器是否存在
|
||||||
if machineId := ms.MachineId; machineId != Common_Script_Machine_Id {
|
if machineId := ms.MachineId; machineId != Common_Script_Machine_Id {
|
||||||
_, err := m.machineApp.GetById(new(entity.Machine), machineId, "Name")
|
_, err := m.machineApp.GetById(machineId, "Name")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorx.NewBiz("该机器不存在")
|
return errorx.NewBiz("该机器不存在")
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user