mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-04 00:10:25 +08:00
fix: 资源关联多标签删除、数据库实例删除等问题修复与数据库等名称过滤优化
This commit is contained in:
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
### 介绍
|
### 介绍
|
||||||
|
|
||||||
web 版 **linux(终端[终端回放、命令过滤] 文件 脚本 进程 计划任务)、数据库(mysql postgres oracle sqlserver 达梦 高斯 sqlite)数据同步 数据迁移、redis(单机 哨兵 集群)、mongo 等集工单流程审批于一体的统一管理操作平台**
|
web 版 **linux(终端[终端回放、命令过滤] 文件 脚本 进程 计划任务)、数据库(mysql postgres oracle sqlserver 达梦 高斯 sqlite)数据操作 数据同步 数据迁移、redis(单机 哨兵 集群)、mongo 等集工单流程审批于一体的统一管理操作平台**
|
||||||
|
|
||||||
### 开发语言与主要框架
|
### 开发语言与主要框架
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"cropperjs": "^1.6.1",
|
"cropperjs": "^1.6.1",
|
||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
"echarts": "^5.5.0",
|
"echarts": "^5.5.0",
|
||||||
"element-plus": "^2.7.3",
|
"element-plus": "^2.7.4",
|
||||||
"js-base64": "^3.7.7",
|
"js-base64": "^3.7.7",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"sass": "^1.77.1",
|
"sass": "^1.77.1",
|
||||||
"typescript": "^5.4.5",
|
"typescript": "^5.4.5",
|
||||||
"vite": "^5.2.11",
|
"vite": "^5.2.12",
|
||||||
"vue-eslint-parser": "^9.4.2"
|
"vue-eslint-parser": "^9.4.2"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
|
|||||||
@@ -97,43 +97,6 @@ export function getTextWidth(str: string) {
|
|||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取内容所需要占用的宽度
|
|
||||||
*/
|
|
||||||
export function getContentWidth(content: any): number {
|
|
||||||
if (!content) {
|
|
||||||
return 50;
|
|
||||||
}
|
|
||||||
// 以下分配的单位长度可根据实际需求进行调整
|
|
||||||
let flexWidth = 0;
|
|
||||||
for (const char of content) {
|
|
||||||
if (flexWidth > 500) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((char >= '0' && char <= '9') || (char >= 'a' && char <= 'z')) {
|
|
||||||
// 小写字母、数字字符
|
|
||||||
flexWidth += 9.3;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (char >= 'A' && char <= 'Z') {
|
|
||||||
flexWidth += 9;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (char >= '\u4e00' && char <= '\u9fa5') {
|
|
||||||
// 如果是中文字符,为字符分配16个单位宽度
|
|
||||||
flexWidth += 20;
|
|
||||||
} else {
|
|
||||||
// 其他种类字符
|
|
||||||
flexWidth += 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if (flexWidth > 450) {
|
|
||||||
// // 设置最大宽度
|
|
||||||
// flexWidth = 450;
|
|
||||||
// }
|
|
||||||
return flexWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @returns uuid
|
* @returns uuid
|
||||||
@@ -179,3 +142,38 @@ export async function copyToClipboard(txt: string, selector: string = '#copyValu
|
|||||||
clipboard.destroy();
|
clipboard.destroy();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function fuzzyMatchField(keyword: string, fields: any[], ...valueExtractFuncs: Function[]) {
|
||||||
|
keyword = keyword?.toLowerCase();
|
||||||
|
return fields.filter((field) => {
|
||||||
|
for (let valueExtractFunc of valueExtractFuncs) {
|
||||||
|
const value = valueExtractFunc(field)?.toLowerCase();
|
||||||
|
if (isPrefixSubsequence(keyword, value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 匹配是否为前缀子序列 targetTemplate=username prefix=uname -> true,prefix=uname2 -> false
|
||||||
|
* @param prefix 字符串前缀(不连续也可以,但不改变字符的相对顺序)
|
||||||
|
* @param targetTemplate 目标模板
|
||||||
|
* @returns 是否匹配
|
||||||
|
*/
|
||||||
|
export function isPrefixSubsequence(prefix: string, targetTemplate: string) {
|
||||||
|
let i = 0; // 指向prefix的索引
|
||||||
|
let j = 0; // 指向targetTemplate的索引
|
||||||
|
|
||||||
|
while (i < prefix.length && j < targetTemplate.length) {
|
||||||
|
if (prefix[i] === targetTemplate[j]) {
|
||||||
|
// 字符匹配,两个指针都向前移动
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
j++; // 目标字符串指针始终向前移动
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果prefix的所有字符都被找到,返回true
|
||||||
|
return i === prefix.length;
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ import { NodeType, TagTreeNode } from './tag';
|
|||||||
import TagInfo from './TagInfo.vue';
|
import TagInfo from './TagInfo.vue';
|
||||||
import { Contextmenu } from '@/components/contextmenu';
|
import { Contextmenu } from '@/components/contextmenu';
|
||||||
import { tagApi } from '../tag/api';
|
import { tagApi } from '../tag/api';
|
||||||
|
import { isPrefixSubsequence } from '@/common/utils/string';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
resourceType: {
|
resourceType: {
|
||||||
@@ -105,8 +106,7 @@ watch(filterText, (val) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const filterNode = (value: string, data: any) => {
|
const filterNode = (value: string, data: any) => {
|
||||||
if (!value) return true;
|
return !value || isPrefixSubsequence(value, data.label);
|
||||||
return data.label.includes(value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ 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';
|
||||||
|
import { isPrefixSubsequence } from '@/common/utils/string';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
height: {
|
height: {
|
||||||
@@ -102,10 +103,7 @@ const search = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const filterNode = (value: string, data: any) => {
|
const filterNode = (value: string, data: any) => {
|
||||||
if (!value) {
|
return !value || isPrefixSubsequence(value, data.codePath) || isPrefixSubsequence(value, data.name);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return data.codePath.toLowerCase().includes(value) || data.name.includes(value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onFilterValChanged = (val: string) => {
|
const onFilterValChanged = (val: string) => {
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ import DbTableData from './DbTableData.vue';
|
|||||||
import { DbDialect } from '@/views/ops/db/dialect';
|
import { DbDialect } from '@/views/ops/db/dialect';
|
||||||
import SvgIcon from '@/components/svgIcon/index.vue';
|
import SvgIcon from '@/components/svgIcon/index.vue';
|
||||||
import { useEventListener, useStorage } from '@vueuse/core';
|
import { useEventListener, useStorage } from '@vueuse/core';
|
||||||
import { copyToClipboard } from '@/common/utils/string';
|
import { copyToClipboard, fuzzyMatchField } from '@/common/utils/string';
|
||||||
import DbTableDataForm from './DbTableDataForm.vue';
|
import DbTableDataForm from './DbTableDataForm.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -476,10 +476,7 @@ const getColumnTips = (queryString: string, callback: any) => {
|
|||||||
|
|
||||||
let res = [];
|
let res = [];
|
||||||
if (columnNameSearch) {
|
if (columnNameSearch) {
|
||||||
columnNameSearch = columnNameSearch.toLowerCase();
|
res = fuzzyMatchField(columnNameSearch, columns, (x: any) => x.columnName);
|
||||||
res = columns.filter((data: any) => {
|
|
||||||
return data.columnName.toLowerCase().includes(columnNameSearch);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
completeCond = condition.value;
|
completeCond = condition.value;
|
||||||
@@ -534,10 +531,12 @@ const filterColumns = (searchKey: string) => {
|
|||||||
if (!searchKey) {
|
if (!searchKey) {
|
||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
searchKey = searchKey.toLowerCase();
|
return fuzzyMatchField(
|
||||||
return columns.filter((data: any) => {
|
searchKey,
|
||||||
return data.columnName.toLowerCase().includes(searchKey) || data.columnComment.toLowerCase().includes(searchKey);
|
columns,
|
||||||
});
|
(x: any) => x.columnName,
|
||||||
|
(x: any) => x.columnComment
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ import { compatibleMysql, editDbTypes, getDbDialect } from '../../dialect/index'
|
|||||||
import { DbInst } from '../../db';
|
import { DbInst } from '../../db';
|
||||||
import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
|
import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
|
||||||
import { format as sqlFormatter } from 'sql-formatter';
|
import { format as sqlFormatter } from 'sql-formatter';
|
||||||
|
import { fuzzyMatchField } from '@/common/utils/string';
|
||||||
|
|
||||||
const DbTableOp = defineAsyncComponent(() => import('./DbTableOp.vue'));
|
const DbTableOp = defineAsyncComponent(() => import('./DbTableOp.vue'));
|
||||||
|
|
||||||
@@ -219,17 +220,11 @@ const filterTableInfos = computed(() => {
|
|||||||
if (!tableNameSearch && !tableCommentSearch) {
|
if (!tableNameSearch && !tableCommentSearch) {
|
||||||
return tables;
|
return tables;
|
||||||
}
|
}
|
||||||
return tables.filter((data: any) => {
|
|
||||||
let tnMatch = true;
|
|
||||||
let tcMatch = true;
|
|
||||||
if (tableNameSearch) {
|
if (tableNameSearch) {
|
||||||
tnMatch = data.tableName.toLowerCase().includes(tableNameSearch.toLowerCase());
|
return fuzzyMatchField(tableNameSearch, tables, (table: any) => table.tableName);
|
||||||
}
|
}
|
||||||
if (tableCommentSearch) {
|
return fuzzyMatchField(tableCommentSearch, tables, (table: any) => table.tableComment);
|
||||||
tcMatch = data.tableComment.includes(tableCommentSearch);
|
|
||||||
}
|
|
||||||
return tnMatch && tcMatch;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const getTables = async () => {
|
const getTables = async () => {
|
||||||
|
|||||||
@@ -293,6 +293,7 @@ import { getToken } from '@/common/utils/storage';
|
|||||||
import { convertToBytes, formatByteSize } from '@/common/utils/format';
|
import { convertToBytes, formatByteSize } from '@/common/utils/format';
|
||||||
import { getMachineConfig } from '@/common/sysconfig';
|
import { getMachineConfig } from '@/common/sysconfig';
|
||||||
import { MachineProtocolEnum } from '../enums';
|
import { MachineProtocolEnum } from '../enums';
|
||||||
|
import { fuzzyMatchField } from '@/common/utils/string';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
machineId: { type: Number },
|
machineId: { type: Number },
|
||||||
@@ -371,33 +372,7 @@ onMounted(async () => {
|
|||||||
state.machineConfig = await getMachineConfig();
|
state.machineConfig = await getMachineConfig();
|
||||||
});
|
});
|
||||||
|
|
||||||
// watch(
|
const filterFiles = computed(() => fuzzyMatchField(state.fileNameFilter, state.files, (file: any) => file.name));
|
||||||
// () => props.machineId,
|
|
||||||
// () => {
|
|
||||||
// if (props.protocol != MachineProtocolEnum.Ssh.value) {
|
|
||||||
// userMap.clear();
|
|
||||||
// groupMap.clear();
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const machineId = props.machineId;
|
|
||||||
// machineApi.users.request({ machineId }).then((res: any) => {
|
|
||||||
// for (let user of res) {
|
|
||||||
// userMap.set(user.uid, user);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// machineApi.groups.request({ machineId }).then((res: any) => {
|
|
||||||
// for (let group of res) {
|
|
||||||
// groupMap.set(group.gid, group);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
|
|
||||||
const filterFiles = computed(() =>
|
|
||||||
state.files.filter((data: any) => !state.fileNameFilter || data.name.toLowerCase().includes(state.fileNameFilter.toLowerCase()))
|
|
||||||
);
|
|
||||||
|
|
||||||
const filePathNav = computed(() => {
|
const filePathNav = computed(() => {
|
||||||
let basePath = state.basePath;
|
let basePath = state.basePath;
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ 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 TagCodePath from '../component/TagCodePath.vue';
|
import TagCodePath from '../component/TagCodePath.vue';
|
||||||
|
import { isPrefixSubsequence } from '@/common/utils/string';
|
||||||
|
|
||||||
const MachineList = defineAsyncComponent(() => import('../machine/MachineList.vue'));
|
const MachineList = defineAsyncComponent(() => import('../machine/MachineList.vue'));
|
||||||
const InstanceList = defineAsyncComponent(() => import('../db/InstanceList.vue'));
|
const InstanceList = defineAsyncComponent(() => import('../db/InstanceList.vue'));
|
||||||
@@ -371,8 +372,7 @@ const setNowTabData = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const filterNode = (value: string, data: Tree) => {
|
const filterNode = (value: string, data: Tree) => {
|
||||||
if (!value) return true;
|
return !value || isPrefixSubsequence(value, data.codePath) || isPrefixSubsequence(value, data.name);
|
||||||
return data.codePath.toLowerCase().includes(value) || data.name.includes(value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ import { formatDate } from '@/common/utils/format';
|
|||||||
import EnumTag from '@/components/enumtag/EnumTag.vue';
|
import EnumTag from '@/components/enumtag/EnumTag.vue';
|
||||||
import { Contextmenu, ContextmenuItem } from '@/components/contextmenu';
|
import { Contextmenu, ContextmenuItem } from '@/components/contextmenu';
|
||||||
import { Splitpanes, Pane } from 'splitpanes';
|
import { Splitpanes, Pane } from 'splitpanes';
|
||||||
|
import { isPrefixSubsequence } from '@/common/utils/string';
|
||||||
|
|
||||||
const menuTypeValue = ResourceTypeEnum.Menu.value;
|
const menuTypeValue = ResourceTypeEnum.Menu.value;
|
||||||
const permissionTypeValue = ResourceTypeEnum.Permission.value;
|
const permissionTypeValue = ResourceTypeEnum.Permission.value;
|
||||||
@@ -209,10 +210,7 @@ watch(filterResource, (val) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const filterNode = (value: string, data: any) => {
|
const filterNode = (value: string, data: any) => {
|
||||||
if (!value) {
|
return !value || isPrefixSubsequence(value, data.name);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return data.name.includes(value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ require (
|
|||||||
github.com/stretchr/testify v1.9.0
|
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.23.0 // ssh
|
golang.org/x/crypto v0.24.0 // ssh
|
||||||
golang.org/x/oauth2 v0.20.0
|
golang.org/x/oauth2 v0.21.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
|
||||||
@@ -94,8 +94,8 @@ require (
|
|||||||
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.25.0 // indirect
|
golang.org/x/net v0.25.0 // indirect
|
||||||
golang.org/x/sys v0.20.0 // indirect
|
golang.org/x/sys v0.21.0 // indirect
|
||||||
golang.org/x/text v0.15.0 // indirect
|
golang.org/x/text v0.16.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.34.1 // indirect
|
google.golang.org/protobuf v1.34.1 // indirect
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package application
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"mayfly-go/internal/common/consts"
|
"mayfly-go/internal/common/consts"
|
||||||
"mayfly-go/internal/db/application/dto"
|
"mayfly-go/internal/db/application/dto"
|
||||||
"mayfly-go/internal/db/dbm"
|
"mayfly-go/internal/db/dbm"
|
||||||
@@ -13,14 +12,11 @@ import (
|
|||||||
tagdto "mayfly-go/internal/tag/application/dto"
|
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/errorx"
|
"mayfly-go/pkg/errorx"
|
||||||
"mayfly-go/pkg/logx"
|
"mayfly-go/pkg/logx"
|
||||||
"mayfly-go/pkg/model"
|
"mayfly-go/pkg/model"
|
||||||
"mayfly-go/pkg/utils/collx"
|
"mayfly-go/pkg/utils/collx"
|
||||||
"mayfly-go/pkg/utils/structx"
|
"mayfly-go/pkg/utils/structx"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Instance interface {
|
type Instance interface {
|
||||||
@@ -171,7 +167,7 @@ func (app *instanceAppImpl) SaveDbInstance(ctx context.Context, instance *dto.Sa
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (app *instanceAppImpl) Delete(ctx context.Context, instanceId uint64) error {
|
func (app *instanceAppImpl) Delete(ctx context.Context, instanceId uint64) error {
|
||||||
instance, err := app.GetById(instanceId, "name")
|
instance, err := app.GetById(instanceId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorx.NewBiz("获取数据库实例错误,数据库实例ID为: %d", instance.Id)
|
return errorx.NewBiz("获取数据库实例错误,数据库实例ID为: %d", instance.Id)
|
||||||
}
|
}
|
||||||
@@ -180,26 +176,16 @@ func (app *instanceAppImpl) Delete(ctx context.Context, instanceId uint64) error
|
|||||||
DbInstanceId: instanceId,
|
DbInstanceId: instanceId,
|
||||||
}
|
}
|
||||||
err = app.restoreApp.restoreRepo.GetByCond(restore)
|
err = app.restoreApp.restoreRepo.GetByCond(restore)
|
||||||
switch {
|
if err != nil {
|
||||||
case err == nil:
|
return errorx.NewBiz("不能删除数据库实例【%s】,请先删除关联的数据库恢复任务。", instance.Name)
|
||||||
biz.ErrNotNil(err, "不能删除数据库实例【%s】,请先删除关联的数据库恢复任务。", instance.Name)
|
|
||||||
case errors.Is(err, gorm.ErrRecordNotFound):
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
biz.ErrIsNil(err, "删除数据库实例失败: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backup := &entity.DbBackup{
|
backup := &entity.DbBackup{
|
||||||
DbInstanceId: instanceId,
|
DbInstanceId: instanceId,
|
||||||
}
|
}
|
||||||
err = app.backupApp.backupRepo.GetByCond(backup)
|
err = app.backupApp.backupRepo.GetByCond(backup)
|
||||||
switch {
|
if err != nil {
|
||||||
case err == nil:
|
return errorx.NewBiz("不能删除数据库实例【%s】,请先删除关联的数据库备份任务。", instance.Name)
|
||||||
biz.ErrNotNil(err, "不能删除数据库实例【%s】,请先删除关联的数据库备份任务。", instance.Name)
|
|
||||||
case errors.Is(err, gorm.ErrRecordNotFound):
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
biz.ErrIsNil(err, "删除数据库实例失败: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dbs, _ := app.dbApp.ListByCond(&entity.Db{
|
dbs, _ := app.dbApp.ListByCond(&entity.Db{
|
||||||
|
|||||||
@@ -264,6 +264,9 @@ func getInterfaceInfo(iInfo string, stats *Stats) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getCPU(cpuInfo string, stats *Stats) (err error) {
|
func getCPU(cpuInfo string, stats *Stats) (err error) {
|
||||||
|
if !strings.Contains(cpuInfo, ":") {
|
||||||
|
return
|
||||||
|
}
|
||||||
// %Cpu(s): 6.1 us, 3.0 sy, 0.0 ni, 90.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
// %Cpu(s): 6.1 us, 3.0 sy, 0.0 ni, 90.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||||
value := strings.Split(cpuInfo, ":")[1]
|
value := strings.Split(cpuInfo, ":")[1]
|
||||||
values := strings.Split(value, ",")
|
values := strings.Split(value, ",")
|
||||||
|
|||||||
@@ -312,6 +312,7 @@ func (p *tagTreeAppImpl) DeleteTagByParam(ctx context.Context, param *dto.DelRes
|
|||||||
}
|
}
|
||||||
|
|
||||||
delTagType := param.ChildType
|
delTagType := param.ChildType
|
||||||
|
var childrenTagIds []uint64
|
||||||
for _, resourceTag := range resourceTags {
|
for _, resourceTag := range resourceTags {
|
||||||
// 获取所有关联的子标签
|
// 获取所有关联的子标签
|
||||||
childrenTag, _ := p.ListByCond(model.NewCond().RLike("code_path", resourceTag.CodePath).Eq("type", delTagType))
|
childrenTag, _ := p.ListByCond(model.NewCond().RLike("code_path", resourceTag.CodePath).Eq("type", delTagType))
|
||||||
@@ -319,15 +320,17 @@ func (p *tagTreeAppImpl) DeleteTagByParam(ctx context.Context, param *dto.DelRes
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
childrenTagIds := collx.ArrayMap(childrenTag, func(item *entity.TagTree) uint64 {
|
childrenTagIds = append(childrenTagIds, collx.ArrayMap(childrenTag, func(item *entity.TagTree) uint64 {
|
||||||
return item.Id
|
return item.Id
|
||||||
})
|
})...)
|
||||||
// 删除code_path下的所有子标签
|
|
||||||
return p.deleteByIds(ctx, childrenTagIds)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(childrenTagIds) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// 删除code_path下的所有子标签
|
||||||
|
return p.deleteByIds(ctx, collx.ArrayDeduplicate(childrenTagIds))
|
||||||
|
}
|
||||||
|
|
||||||
func (p *tagTreeAppImpl) ListByQuery(condition *entity.TagTreeQuery, toEntity any) {
|
func (p *tagTreeAppImpl) ListByQuery(condition *entity.TagTreeQuery, toEntity any) {
|
||||||
p.GetRepo().SelectByCondition(condition, toEntity)
|
p.GetRepo().SelectByCondition(condition, toEntity)
|
||||||
|
|||||||
Reference in New Issue
Block a user