mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-02 07:20:24 +08:00
fix: fixed some minor issues
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
# 构建前端资源
|
# 构建前端资源
|
||||||
FROM m.daocloud.io/docker.io/node:18-bookworm-slim as fe-builder
|
FROM m.daocloud.io/docker.io/node:18-bookworm-slim AS fe-builder
|
||||||
|
|
||||||
WORKDIR /mayfly
|
WORKDIR /mayfly
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ RUN yarn config set registry 'https://registry.npmmirror.com' && \
|
|||||||
yarn build
|
yarn build
|
||||||
|
|
||||||
# 构建后端资源
|
# 构建后端资源
|
||||||
FROM m.daocloud.io/docker.io/golang:1.23 as be-builder
|
FROM m.daocloud.io/docker.io/golang:1.23 AS be-builder
|
||||||
|
|
||||||
ENV GOPROXY https://goproxy.cn
|
ENV GOPROXY https://goproxy.cn
|
||||||
WORKDIR /mayfly
|
WORKDIR /mayfly
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ function build() {
|
|||||||
if [ "${os}" == "windows" ];then
|
if [ "${os}" == "windows" ];then
|
||||||
execFileName="${execFileName}.exe"
|
execFileName="${execFileName}.exe"
|
||||||
fi
|
fi
|
||||||
|
go mod tidy
|
||||||
CGO_ENABLE=0 GOOS=${os} GOARCH=${arch} go build -ldflags=-w -o ${execFileName} main.go
|
CGO_ENABLE=0 GOOS=${os} GOARCH=${arch} go build -ldflags=-w -o ${execFileName} main.go
|
||||||
|
|
||||||
if [ -d ${toFolder} ] ; then
|
if [ -d ${toFolder} ] ; then
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"@vueuse/core": "^11.2.0",
|
"@vueuse/core": "^11.3.0",
|
||||||
"asciinema-player": "^3.8.1",
|
"asciinema-player": "^3.8.1",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
"clipboard": "^2.0.11",
|
"clipboard": "^2.0.11",
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
"monaco-sql-languages": "^0.12.2",
|
"monaco-sql-languages": "^0.12.2",
|
||||||
"monaco-themes": "^0.4.4",
|
"monaco-themes": "^0.4.4",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pinia": "^2.2.6",
|
"pinia": "^2.2.7",
|
||||||
"qrcode.vue": "^3.5.1",
|
"qrcode.vue": "^3.5.1",
|
||||||
"screenfull": "^6.0.2",
|
"screenfull": "^6.0.2",
|
||||||
"sortablejs": "^1.15.3",
|
"sortablejs": "^1.15.3",
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-i18n": "^10.0.4",
|
"vue-i18n": "^10.0.4",
|
||||||
"vue-router": "^4.4.5",
|
"vue-router": "^4.5.0",
|
||||||
"xterm": "^5.3.0",
|
"xterm": "^5.3.0",
|
||||||
"xterm-addon-fit": "^0.8.0",
|
"xterm-addon-fit": "^0.8.0",
|
||||||
"xterm-addon-search": "^0.13.0",
|
"xterm-addon-search": "^0.13.0",
|
||||||
@@ -52,16 +52,16 @@
|
|||||||
"@types/sortablejs": "^1.15.8",
|
"@types/sortablejs": "^1.15.8",
|
||||||
"@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.2.0",
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
"@vue/compiler-sfc": "^3.5.13",
|
"@vue/compiler-sfc": "^3.5.13",
|
||||||
"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.28.0",
|
"eslint-plugin-vue": "^9.31.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"sass": "^1.81.0",
|
"sass": "^1.81.0",
|
||||||
"typescript": "^5.6.3",
|
"typescript": "^5.7.2",
|
||||||
"vite": "^5.4.11",
|
"vite": "^6.0.1",
|
||||||
"vue-eslint-parser": "^9.4.3"
|
"vue-eslint-parser": "^9.4.3"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
|
|||||||
@@ -196,6 +196,9 @@ watch(
|
|||||||
(newValue: any) => {
|
(newValue: any) => {
|
||||||
if (!monacoEditorIns.hasTextFocus()) {
|
if (!monacoEditorIns.hasTextFocus()) {
|
||||||
state.languageMode = props.language;
|
state.languageMode = props.language;
|
||||||
|
if (newValue == null) {
|
||||||
|
newValue = '';
|
||||||
|
}
|
||||||
monacoEditorIns?.setValue(newValue);
|
monacoEditorIns?.setValue(newValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export default {
|
|||||||
copy: 'Copy',
|
copy: 'Copy',
|
||||||
pleaseInput: 'Please enter {label}',
|
pleaseInput: 'Please enter {label}',
|
||||||
pleaseSelect: 'Please select {label}',
|
pleaseSelect: 'Please select {label}',
|
||||||
formValidationError: 'Please fill in the form information correctly',
|
formValidationError: 'Please check the form',
|
||||||
createTitle: 'Create {name}',
|
createTitle: 'Create {name}',
|
||||||
editTitle: 'Edit {name}',
|
editTitle: 'Edit {name}',
|
||||||
detailTitle: '{name} Details',
|
detailTitle: '{name} Details',
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ export default {
|
|||||||
newTabOpen: 'New tab opens',
|
newTabOpen: 'New tab opens',
|
||||||
redisSelectErr: 'Select redis first',
|
redisSelectErr: 'Select redis first',
|
||||||
flushDbTips: 'Make sure to clear all keys of the [{db}] library?',
|
flushDbTips: 'Make sure to clear all keys of the [{db}] library?',
|
||||||
keyNotEmpty: 'The Key cannot be empty',
|
|
||||||
|
|
||||||
// info
|
// info
|
||||||
redisInfoTitle: 'Redis server information',
|
redisInfoTitle: 'Redis server information',
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export default {
|
|||||||
copy: '复制',
|
copy: '复制',
|
||||||
pleaseInput: '请输入{label}',
|
pleaseInput: '请输入{label}',
|
||||||
pleaseSelect: '请选择{label}',
|
pleaseSelect: '请选择{label}',
|
||||||
formValidationError: '请正确填写表单信息',
|
formValidationError: '信息填写有误,请检查',
|
||||||
createTitle: '创建{name}',
|
createTitle: '创建{name}',
|
||||||
editTitle: '编辑{name}',
|
editTitle: '编辑{name}',
|
||||||
detailTitle: '{name}详情',
|
detailTitle: '{name}详情',
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ export default {
|
|||||||
newTabOpen: '新tab打开',
|
newTabOpen: '新tab打开',
|
||||||
redisSelectErr: '请先选择redis',
|
redisSelectErr: '请先选择redis',
|
||||||
flushDbTips: '确定清空[{db}]库的所有key?',
|
flushDbTips: '确定清空[{db}]库的所有key?',
|
||||||
keyNotEmpty: 'Key不能为空',
|
|
||||||
|
|
||||||
// info
|
// info
|
||||||
redisInfoTitle: 'Redis服务器信息',
|
redisInfoTitle: 'Redis服务器信息',
|
||||||
|
|||||||
@@ -303,17 +303,17 @@ const onRunSql = async (newTab = false) => {
|
|||||||
|
|
||||||
const sqls = splitSql(sql);
|
const sqls = splitSql(sql);
|
||||||
|
|
||||||
// 简单截取前十个字符
|
|
||||||
const sqlPrefix = sql.slice(0, 10).toLowerCase();
|
|
||||||
const nonQuery =
|
|
||||||
sqlPrefix.startsWith('update') ||
|
|
||||||
sqlPrefix.startsWith('insert') ||
|
|
||||||
sqlPrefix.startsWith('delete') ||
|
|
||||||
sqlPrefix.startsWith('alter') ||
|
|
||||||
sqlPrefix.startsWith('drop') ||
|
|
||||||
sqlPrefix.startsWith('create');
|
|
||||||
|
|
||||||
if (sqls.length == 1) {
|
if (sqls.length == 1) {
|
||||||
|
const oneSql = sqls[0];
|
||||||
|
// 简单截取前十个字符
|
||||||
|
const sqlPrefix = oneSql.slice(0, 10).toLowerCase();
|
||||||
|
const nonQuery =
|
||||||
|
sqlPrefix.startsWith('update') ||
|
||||||
|
sqlPrefix.startsWith('insert') ||
|
||||||
|
sqlPrefix.startsWith('delete') ||
|
||||||
|
sqlPrefix.startsWith('alter') ||
|
||||||
|
sqlPrefix.startsWith('drop') ||
|
||||||
|
sqlPrefix.startsWith('create');
|
||||||
let execRemark;
|
let execRemark;
|
||||||
if (nonQuery) {
|
if (nonQuery) {
|
||||||
const res: any = await ElMessageBox.prompt(t('db.enterExecRemarkTips'), 'Tip', {
|
const res: any = await ElMessageBox.prompt(t('db.enterExecRemarkTips'), 'Tip', {
|
||||||
@@ -323,7 +323,7 @@ const onRunSql = async (newTab = false) => {
|
|||||||
});
|
});
|
||||||
execRemark = res.value;
|
execRemark = res.value;
|
||||||
}
|
}
|
||||||
runSql(sql, execRemark, newTab);
|
runSql(oneSql, execRemark, newTab);
|
||||||
} else {
|
} else {
|
||||||
let isFirst = true;
|
let isFirst = true;
|
||||||
for (let s of sqls) {
|
for (let s of sqls) {
|
||||||
|
|||||||
@@ -483,7 +483,6 @@ const setTableColumns = (columns: any) => {
|
|||||||
x.dataType = dbDialect.getDataType(x.columnType);
|
x.dataType = dbDialect.getDataType(x.columnType);
|
||||||
x.dataTypeSubscript = ColumnTypeSubscript[x.dataType];
|
x.dataTypeSubscript = ColumnTypeSubscript[x.dataType];
|
||||||
x.remark = `${x.columnType} ${x.columnComment ? ' | ' + x.columnComment : ''}`;
|
x.remark = `${x.columnType} ${x.columnComment ? ' | ' + x.columnComment : ''}`;
|
||||||
console.log(x);
|
|
||||||
return {
|
return {
|
||||||
...x,
|
...x,
|
||||||
key: columnName,
|
key: columnName,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<tag-tree
|
<tag-tree
|
||||||
class="machine-terminal-tree"
|
class="machine-terminal-tree"
|
||||||
ref="tagTreeRef"
|
ref="tagTreeRef"
|
||||||
:resource-type="TagResourceTypeEnum.Machine.value"
|
:resource-type="TagResourceTypePath.MachineAuthCert"
|
||||||
:tag-path-node-type="NodeTypeTagPath"
|
:tag-path-node-type="NodeTypeTagPath"
|
||||||
:default-expanded-keys="state.defaultExpendKey"
|
:default-expanded-keys="state.defaultExpendKey"
|
||||||
>
|
>
|
||||||
@@ -168,7 +168,7 @@ import { useRouter } from 'vue-router';
|
|||||||
import { getMachineTerminalSocketUrl, machineApi } from './api';
|
import { getMachineTerminalSocketUrl, machineApi } from './api';
|
||||||
import { formatDate } from '@/common/utils/format';
|
import { formatDate } from '@/common/utils/format';
|
||||||
import { hasPerms } from '@/components/auth/auth';
|
import { hasPerms } from '@/components/auth/auth';
|
||||||
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
import { TagResourceTypeEnum, TagResourceTypePath } from '@/common/commonEnum';
|
||||||
import { NodeType, TagTreeNode, getTagTypeCodeByPath } from '../component/tag';
|
import { NodeType, TagTreeNode, getTagTypeCodeByPath } from '../component/tag';
|
||||||
import TagTree from '../component/TagTree.vue';
|
import TagTree from '../component/TagTree.vue';
|
||||||
import { Pane, Splitpanes } from 'splitpanes';
|
import { Pane, Splitpanes } from 'splitpanes';
|
||||||
|
|||||||
@@ -160,7 +160,7 @@
|
|||||||
<div style="text-align: center; margin-top: 10px"></div>
|
<div style="text-align: center; margin-top: 10px"></div>
|
||||||
|
|
||||||
<el-dialog :title="$t('redis.addKey')" v-model="newKeyDialog.visible" width="500px" :destroy-on-close="true" :close-on-click-modal="false">
|
<el-dialog :title="$t('redis.addKey')" v-model="newKeyDialog.visible" width="500px" :destroy-on-close="true" :close-on-click-modal="false">
|
||||||
<el-form ref="keyForm" label-width="auto">
|
<el-form ref="keyForm" label-width="auto" :rules="keyFormRules" :model="newKeyDialog.keyInfo">
|
||||||
<el-form-item prop="key" label="Key" required>
|
<el-form-item prop="key" label="Key" required>
|
||||||
<el-input v-model.trim="newKeyDialog.keyInfo.key"></el-input>
|
<el-input v-model.trim="newKeyDialog.keyInfo.key"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -187,9 +187,9 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { redisApi } from './api';
|
import { redisApi } from './api';
|
||||||
import { ref, defineAsyncComponent, toRefs, reactive, onMounted, nextTick, Ref, watch } from 'vue';
|
import { ref, defineAsyncComponent, toRefs, reactive, onMounted, nextTick, Ref, watch, useTemplateRef } from 'vue';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { ElMessageBox } from 'element-plus';
|
||||||
import { isTrue, notBlank, notNull } from '@/common/assert';
|
import { isTrue, notNull } from '@/common/assert';
|
||||||
import { copyToClipboard } from '@/common/utils/string';
|
import { copyToClipboard } from '@/common/utils/string';
|
||||||
import { TagTreeNode, NodeType, getTagTypeCodeByPath } from '../component/tag';
|
import { TagTreeNode, NodeType, getTagTypeCodeByPath } from '../component/tag';
|
||||||
import TagTree from '../component/TagTree.vue';
|
import TagTree from '../component/TagTree.vue';
|
||||||
@@ -202,13 +202,21 @@ import { RedisInst } from './redis';
|
|||||||
import { useAutoOpenResource } from '@/store/autoOpenResource';
|
import { useAutoOpenResource } from '@/store/autoOpenResource';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useI18nDeleteConfirm, useI18nDeleteSuccessMsg, useI18nOperateSuccessMsg } from '@/hooks/useI18n';
|
import { useI18nDeleteConfirm, useI18nDeleteSuccessMsg, useI18nFormValidate, useI18nOperateSuccessMsg, useI18nPleaseInput } from '@/hooks/useI18n';
|
||||||
|
|
||||||
const KeyDetail = defineAsyncComponent(() => import('./KeyDetail.vue'));
|
const KeyDetail = defineAsyncComponent(() => import('./KeyDetail.vue'));
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const contextmenuRef = ref();
|
const keyFormRules = {
|
||||||
|
key: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: useI18nPleaseInput('Key'),
|
||||||
|
trigger: ['change', 'blur'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
const cmCopyKey = new ContextmenuItem('copyValue', 'Copy')
|
const cmCopyKey = new ContextmenuItem('copyValue', 'Copy')
|
||||||
.withIcon('CopyDocument')
|
.withIcon('CopyDocument')
|
||||||
@@ -301,8 +309,11 @@ const treeProps = {
|
|||||||
|
|
||||||
const defaultCount = 250;
|
const defaultCount = 250;
|
||||||
|
|
||||||
|
const contextmenuRef = ref();
|
||||||
const keyTreeRef: any = ref(null);
|
const keyTreeRef: any = ref(null);
|
||||||
const tagTreeRef: any = ref(null);
|
const tagTreeRef: any = ref(null);
|
||||||
|
const keyFormRef = useTemplateRef('keyForm');
|
||||||
|
|
||||||
const redisInst: Ref<RedisInst> = ref(new RedisInst());
|
const redisInst: Ref<RedisInst> = ref(new RedisInst());
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
@@ -573,9 +584,9 @@ const cancelNewKey = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const newKey = async () => {
|
const newKey = async () => {
|
||||||
|
await useI18nFormValidate(keyFormRef);
|
||||||
const keyInfo = state.newKeyDialog.keyInfo;
|
const keyInfo = state.newKeyDialog.keyInfo;
|
||||||
const key = keyInfo.key;
|
const key = keyInfo.key;
|
||||||
notBlank(key, t('redis.keyNotEmpty'));
|
|
||||||
|
|
||||||
showKeyDetail(
|
showKeyDetail(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -370,12 +370,9 @@ func (p *tagTreeAppImpl) GetAccountTags(accountId uint64, query *entity.TagTreeQ
|
|||||||
}
|
}
|
||||||
|
|
||||||
codePathLikes := accountTagPaths
|
codePathLikes := accountTagPaths
|
||||||
needFilterAccountTagPaths := accountTagPaths
|
needFilterAccountTagPaths := make(map[string][]string, 0)
|
||||||
|
|
||||||
needFilter := false
|
|
||||||
typePaths := query.TypePaths
|
typePaths := query.TypePaths
|
||||||
if len(typePaths) > 0 {
|
if len(typePaths) > 0 {
|
||||||
needFilterAccountTagPaths = make([]string, 0)
|
|
||||||
codePathLikes = []string{}
|
codePathLikes = []string{}
|
||||||
|
|
||||||
for _, typePath := range typePaths {
|
for _, typePath := range typePaths {
|
||||||
@@ -391,14 +388,13 @@ func (p *tagTreeAppImpl) GetAccountTags(accountId uint64, query *entity.TagTreeQ
|
|||||||
return cast.ToString(int8(tt)) + entity.CodePathResourceSeparator + "%"
|
return cast.ToString(int8(tt)) + entity.CodePathResourceSeparator + "%"
|
||||||
}), entity.CodePathSeparator) + entity.CodePathSeparator
|
}), entity.CodePathSeparator) + entity.CodePathSeparator
|
||||||
|
|
||||||
// 根据用户拥有的标签路径,赋值要过滤匹配的标签路径条件
|
// 根据用户拥有的标签路径,赋值要过滤匹配的标签类型路径
|
||||||
for _, accountTag := range accountTagPaths {
|
for _, accountTag := range accountTagPaths {
|
||||||
accountTagCodePath := entity.CodePath(accountTag)
|
accountTagCodePath := entity.CodePath(accountTag)
|
||||||
// 标签路径,不包含资源段,如tag1/tag2/1|xxx => tag1/tag2/
|
// 标签路径,不包含资源段,如tag1/tag2/1|xxx => tag1/tag2/
|
||||||
tagPath := accountTagCodePath.GetTag()
|
tagPath := accountTagCodePath.GetTag()
|
||||||
// 纯纯的标签类型(不包含资源段),则直接在该标签路径上补上对应的子资源类型匹配表达式
|
// 纯纯的标签类型(不包含资源段),则直接在该标签路径上补上对应的子资源类型匹配表达式
|
||||||
if tagPath == accountTagCodePath {
|
if tagPath == accountTagCodePath {
|
||||||
needFilterAccountTagPaths = append(needFilterAccountTagPaths, accountTag)
|
|
||||||
// 查询标签类型为标签时,特殊处理
|
// 查询标签类型为标签时,特殊处理
|
||||||
if len(childOrderTypes) == 1 && childOrderTypes[0] == entity.TagTypeTag {
|
if len(childOrderTypes) == 1 && childOrderTypes[0] == entity.TagTypeTag {
|
||||||
codePathLikes = append(codePathLikes, accountTag)
|
codePathLikes = append(codePathLikes, accountTag)
|
||||||
@@ -410,7 +406,7 @@ func (p *tagTreeAppImpl) GetAccountTags(accountId uint64, query *entity.TagTreeQ
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将用户有权限操作的标签如 tag1/tag2/1|xxx 替换为tag1/tag2/1|%,并与需要查询的资源类型进行匹配
|
// 将用户有权限操作的标签如 tag1/tag2/type|code 替换为tag1/tag2/type|%,并与需要查询的资源类型进行匹配
|
||||||
accountTagCodePathSections := accountTagCodePath.GetPathSections()
|
accountTagCodePathSections := accountTagCodePath.GetPathSections()
|
||||||
for _, section := range accountTagCodePathSections {
|
for _, section := range accountTagCodePathSections {
|
||||||
if section.Type == entity.TagTypeTag {
|
if section.Type == entity.TagTypeTag {
|
||||||
@@ -419,21 +415,33 @@ func (p *tagTreeAppImpl) GetAccountTags(accountId uint64, query *entity.TagTreeQ
|
|||||||
section.Code = "%"
|
section.Code = "%"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tag1/tag2/type1|%/type2|%
|
||||||
codePathLike := string(tagPath) + childOrderTypesMatch
|
codePathLike := string(tagPath) + childOrderTypesMatch
|
||||||
if entity.CodePath(accountTagCodePathSections.ToCodePath()).CanAccess(codePathLike) {
|
accountMatchPath := accountTagCodePathSections.ToCodePath()
|
||||||
codePathLikes = append(codePathLikes, codePathLike)
|
// 用户有权限操作该标签则直接添加即可
|
||||||
needFilterAccountTagPaths = append(needFilterAccountTagPaths, accountTag)
|
if entity.CodePath(accountMatchPath).CanAccess(codePathLike) {
|
||||||
|
codePathLikes = append(codePathLikes, accountTag)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如用户分配了: "default/type1|code1/type2|code2/type3|code3/", 需要查询的codePathLike为: default/type1|%/type2|%/,即用户分配的标签路径是查询的子节点。
|
||||||
|
// 若需要获取所有子节点,则codePathLike 使用default/type1|code1/type2|code2/去查。否则需要单独再去查一遍
|
||||||
|
if strings.HasPrefix(accountMatchPath, codePathLike) {
|
||||||
|
actualMatchCodePath := accountTagCodePathSections[len(entity.CodePath(codePathLike).GetPathSections())-1].Path
|
||||||
|
needFilterAccountTagPaths[actualMatchCodePath] = append(needFilterAccountTagPaths[actualMatchCodePath], accountTag)
|
||||||
|
if query.GetAllChildren {
|
||||||
|
codePathLikes = append(codePathLikes, actualMatchCodePath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 去重处理
|
// 去重处理
|
||||||
codePathLikes = collx.ArrayDeduplicate(codePathLikes)
|
codePathLikes = collx.ArrayDeduplicate(codePathLikes)
|
||||||
needFilter = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 账号权限经过处理为空,则说明没有用户可以操作的标签,直接返回即可
|
// 账号权限经过处理为空,则说明没有用户可以操作的标签,直接返回即可
|
||||||
if needFilter && len(needFilterAccountTagPaths) == 0 {
|
if len(codePathLikes) == 0 {
|
||||||
return tagResources
|
return tagResources
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,11 +449,28 @@ func (p *tagTreeAppImpl) GetAccountTags(accountId uint64, query *entity.TagTreeQ
|
|||||||
tagResourceQuery.CodePathLikes = codePathLikes
|
tagResourceQuery.CodePathLikes = codePathLikes
|
||||||
p.ListByQuery(tagResourceQuery, &tagResources)
|
p.ListByQuery(tagResourceQuery, &tagResources)
|
||||||
|
|
||||||
if needFilter {
|
// 不是获取所有子节点,则需要额外查询需要过滤的节点信息。如用户分配了default/2|db_local/5|db_local_root/22|cWMpm6137g/标签,但是typePath为default/2|%/5|%/
|
||||||
|
// 由于不是获取所有子节点,则会被追加Type进行过滤,故获取不到default/2|db_local/5|db_local_root/的信息,需要额外查询
|
||||||
|
if !query.GetAllChildren && len(needFilterAccountTagPaths) > 0 {
|
||||||
|
var otherTags []*dto.SimpleTagTree
|
||||||
|
p.ListByQuery(&entity.TagTreeQuery{
|
||||||
|
CodePaths: collx.MapKeys(needFilterAccountTagPaths),
|
||||||
|
}, &otherTags)
|
||||||
|
tagResources = append(tagResources, otherTags...)
|
||||||
|
// 清空,因为不是获取所有子节点,so 后续不需要进行过滤
|
||||||
|
clear(needFilterAccountTagPaths)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(needFilterAccountTagPaths) > 0 {
|
||||||
tagResources = collx.ArrayFilter(tagResources, func(tr *dto.SimpleTagTree) bool {
|
tagResources = collx.ArrayFilter(tagResources, func(tr *dto.SimpleTagTree) bool {
|
||||||
return slices.ContainsFunc(needFilterAccountTagPaths, func(accountTagPath string) bool {
|
for codePathLike, accountTags := range needFilterAccountTagPaths {
|
||||||
return entity.CodePath(accountTagPath).CanAccess(tr.CodePath)
|
if strings.HasPrefix(tr.CodePath, codePathLike) {
|
||||||
})
|
return slices.ContainsFunc(accountTags, func(accountTag string) bool {
|
||||||
|
return entity.CodePath(accountTag).CanAccess(tr.CodePath)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,13 @@ func TestTagPathMatch(t *testing.T) {
|
|||||||
codePathLike := "default/2|%/22|%/"
|
codePathLike := "default/2|%/22|%/"
|
||||||
accountCodePath := "default/2|db_local/5|db_local_root/"
|
accountCodePath := "default/2|db_local/5|db_local_root/"
|
||||||
|
|
||||||
|
// strings.HasPrefix(resourceTagPath, accountPath)
|
||||||
|
// resourceTagPath -> default/2|%/5|%/
|
||||||
|
// account -> default/2|%/5|%/22|%/ "default/2|db_local/5|db_local_root/22|cWMpm6137g/"
|
||||||
|
|
||||||
|
// resourceTagPath -> default/2|%/5|%/
|
||||||
|
// account -> default/2|%/ "default/2|db_local/"
|
||||||
|
|
||||||
sections := entity.CodePath(accountCodePath).GetPathSections()
|
sections := entity.CodePath(accountCodePath).GetPathSections()
|
||||||
for _, section := range sections {
|
for _, section := range sections {
|
||||||
if section.Type == entity.TagTypeTag {
|
if section.Type == entity.TagTypeTag {
|
||||||
|
|||||||
@@ -198,6 +198,12 @@ func (tps PathSections) ToCodePath() string {
|
|||||||
}), CodePathSeparator) + CodePathSeparator
|
}), CodePathSeparator) + CodePathSeparator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tps PathSections) GetSection(tagType TagType) []*PathSection {
|
||||||
|
return collx.ArrayFilter(tps, func(tp *PathSection) bool {
|
||||||
|
return tp.Type == tagType
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// GetCodesByCodePaths 从codePaths中提取指定标签类型的所有tagCode并去重
|
// GetCodesByCodePaths 从codePaths中提取指定标签类型的所有tagCode并去重
|
||||||
// 如:codePaths = tag1/tag2/1|xxxcode/11|yyycode/, tagType = 1 -> xxxcode, tagType = 11 -> yyycode
|
// 如:codePaths = tag1/tag2/1|xxxcode/11|yyycode/, tagType = 1 -> xxxcode, tagType = 11 -> yyycode
|
||||||
func GetCodesByCodePaths(tagType TagType, codePaths ...string) []string {
|
func GetCodesByCodePaths(tagType TagType, codePaths ...string) []string {
|
||||||
|
|||||||
Reference in New Issue
Block a user