diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/CommandSnippetGroupServiceImpl.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/CommandSnippetGroupServiceImpl.java index 34812f1e..a19efd1d 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/CommandSnippetGroupServiceImpl.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/CommandSnippetGroupServiceImpl.java @@ -24,6 +24,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -107,6 +108,7 @@ public class CommandSnippetGroupServiceImpl implements CommandSnippetGroupServic // 转换 return list.stream() .map(CommandSnippetGroupConvert.MAPPER::to) + .sorted(Comparator.comparing(CommandSnippetGroupVO::getId)) .collect(Collectors.toList()); } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/CommandSnippetServiceImpl.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/CommandSnippetServiceImpl.java index 0a4ddc22..53c7824c 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/CommandSnippetServiceImpl.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/CommandSnippetServiceImpl.java @@ -3,7 +3,6 @@ package com.orion.ops.module.asset.service.impl; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.orion.lang.utils.collect.Lists; import com.orion.ops.framework.common.constant.ErrorMessage; import com.orion.ops.framework.common.utils.Valid; import com.orion.ops.framework.redis.core.utils.RedisMaps; @@ -26,7 +25,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; -import java.util.Iterator; +import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -138,6 +137,7 @@ public class CommandSnippetServiceImpl implements CommandSnippetService { // 转换 return list.stream() .map(CommandSnippetConvert.MAPPER::to) + .sorted(Comparator.comparing(CommandSnippetVO::getId)) .collect(Collectors.toList()); } diff --git a/orion-ops-ui/src/components/view/editor/core.ts b/orion-ops-ui/src/components/view/editor/core.ts index a0cf4861..3b9cf24f 100644 --- a/orion-ops-ui/src/components/view/editor/core.ts +++ b/orion-ops-ui/src/components/view/editor/core.ts @@ -45,15 +45,20 @@ export interface Options { disableLayerHinting?: boolean; // 行亮 renderLineHighlight?: RenderLineHighlight; - // 显示行号 + // 点击行号时是否应该选择相应的行 selectOnLineNumbers?: boolean; + // 行号最小字符 + lineNumbersMinChars?: number; + // 输入提示 placeholder?: string; + // 小地图 minimap?: { // 关闭小地图 enabled?: boolean; [key: string]: unknown; }; + // 字体大小 fontSize?: number; // 取消代码后面一大段空白 scrollBeyondLastLine?: boolean; @@ -80,6 +85,7 @@ export const createDefaultOptions = (): Options => { showFoldingControls: 'always', renderLineHighlight: 'line', selectOnLineNumbers: true, + lineNumbersMinChars: 2, disableLayerHinting: true, minimap: { enabled: false, diff --git a/orion-ops-ui/src/store/modules/cache/index.ts b/orion-ops-ui/src/store/modules/cache/index.ts index 1ee39e0f..3ae86ab9 100644 --- a/orion-ops-ui/src/store/modules/cache/index.ts +++ b/orion-ops-ui/src/store/modules/cache/index.ts @@ -12,11 +12,13 @@ import { getHostList } from '@/api/asset/host'; import { getHostGroupTree } from '@/api/asset/host-group'; import { getMenuList } from '@/api/system/menu'; import { getCurrentAuthorizedHostIdentity, getCurrentAuthorizedHostKey } from '@/api/asset/asset-authorized-data'; +import { getCommandSnippetGroupList } from '@/api/asset/command-snippet-group'; export type CacheType = 'users' | 'menus' | 'roles' | 'hosts' | 'hostGroups' | 'hostKeys' | 'hostIdentities' | 'dictKeys' | 'authorizedHostKeys' | 'authorizedHostIdentities' + | 'commandSnippetGroups' | string export default defineStore('cache', { @@ -111,5 +113,10 @@ export default defineStore('cache', { return await this.load('authorizedHostIdentities', getCurrentAuthorizedHostIdentity, force); }, + // 获取命令片段分组 + async loadCommandSnippetGroups(force = false) { + return await this.load('commandSnippetGroups', getCommandSnippetGroupList, force); + }, + } }); diff --git a/orion-ops-ui/src/views/host/command-snippet/components/command-snippet-form-drawer.vue b/orion-ops-ui/src/views/host/command-snippet/components/command-snippet-form-drawer.vue index 827e7631..76876a22 100644 --- a/orion-ops-ui/src/views/host/command-snippet/components/command-snippet-form-drawer.vue +++ b/orion-ops-ui/src/views/host/command-snippet/components/command-snippet-form-drawer.vue @@ -1,7 +1,7 @@ @@ -73,15 +75,16 @@ import useVisible from '@/hooks/visible'; import useLoading from '@/hooks/loading'; import { deleteCommandSnippet, getCommandSnippetList } from '@/api/asset/command-snippet'; - import { useTerminalStore } from '@/store'; + import { useCacheStore, useTerminalStore } from '@/store'; import { openUpdateSnippetKey, removeSnippetKey } from '../types/const'; - import CommandSnippetItem from './command-snippet-item.vue'; - import CommandSnippetGroup from './command-snippet-group.vue'; + import CommandSnippetListItem from './command-snippet-list-item.vue'; + import CommandSnippetListGroup from './command-snippet-list-group.vue'; import CommandSnippetFormDrawer from './command-snippet-form-drawer.vue'; const { loading, setLoading } = useLoading(); const { visible, setVisible } = useVisible(); const { getCurrentTerminalSession } = useTerminalStore(); + const cacheStore = useCacheStore(); const formDrawer = ref(); const filterValue = ref(); @@ -135,45 +138,133 @@ formDrawer.value.openAdd(); }; - // 打开修改 + // 查找并且删除 + const findAndSplice = (id: number, items: Array) => { + if (items) { + const index = items.findIndex(s => s.id === id); + if (index !== -1) { + items.splice(index, 1); + return true; + } + return false; + } + }; + + // 暴露 修改抽屉 provide(openUpdateSnippetKey, (e: CommandSnippetQueryResponse) => { formDrawer.value.openUpdate(e); }); - // 删除 + // 暴露 删除 provide(removeSnippetKey, async (id: number) => { if (!snippet.value) { return; } - - // 查找并且删除 - function findAndSplice(items: Array) { - if (items) { - const index = items.findIndex(s => s.id === id); - if (index !== -1) { - items.splice(index, 1); - return true; - } - return false; - } - } - // 删除 await deleteCommandSnippet(id); - // 查找并且删除未分组的数据 - if (findAndSplice(snippet.value.ungroupedItems)) { + if (findAndSplice(id, snippet.value.ungroupedItems)) { return; } // 查找并且删除分组内数据 for (let group of snippet.value.groups) { - if (findAndSplice(group.items)) { + if (findAndSplice(id, group.items)) { return; } } }); - // 关闭 + // 添加回调 + const onAdded = async (item: CommandSnippetQueryResponse) => { + if (item.groupId) { + let group = snippet.value?.groups.find(g => g.id === item.groupId); + if (group) { + group?.items.push(item); + } else { + const cacheGroups = await cacheStore.loadCommandSnippetGroups(); + const findGroup = cacheGroups.find(s => s.id === item.groupId); + if (findGroup) { + snippet.value?.groups.push({ + id: item.groupId, + name: findGroup.name, + items: [item] + }); + } + } + } else { + snippet.value?.ungroupedItems.push(item); + } + // 重置过滤 + filterSnippet(); + }; + + // 修改回调 + const onUpdated = async (item: CommandSnippetQueryResponse) => { + if (!snippet.value) { + return; + } + // 查找原始数据 + let originItem; + const findInUngrouped = snippet.value.ungroupedItems.find(s => s.id === item.id); + if (findInUngrouped) { + originItem = findInUngrouped; + } else { + for (let group of snippet.value.groups) { + const find = group.items.find(s => s.id === item.id); + if (find) { + originItem = find; + break; + } + } + } + if (!originItem) { + return; + } + // 检查分组是否存在 + const findGroup = snippet.value.groups.find(s => s.id === item.groupId); + if (!findGroup) { + const cacheGroups = await cacheStore.loadCommandSnippetGroups(); + const cacheGroup = cacheGroups.find(s => s.id === item.groupId); + if (cacheGroup) { + snippet.value.groups.push({ + id: item.groupId, + name: cacheGroup.name, + items: [] + }); + } + } + // 设置数据 + const originGroupId = originItem.groupId; + originItem.groupId = item.groupId; + originItem.name = item.name; + originItem.command = item.command; + // 移动分组 + if (item.groupId !== originGroupId) { + // 从原始分组移除 + if (originGroupId) { + const findGroup = snippet.value.groups.find(s => s.id === originGroupId); + if (findGroup) { + findAndSplice(item.id, findGroup.items); + } + } else { + // 从未分组数据中移除 + findAndSplice(item.id, snippet.value.ungroupedItems); + } + // 添加到新分组 + if (item.groupId) { + const findGroup = snippet.value.groups.find(s => s.id === item.groupId); + if (findGroup) { + findGroup.items.push(item); + } + } else { + snippet.value.ungroupedItems.push(originItem); + } + } + // 重置过滤 + filterSnippet(); + }; + + // 关闭回调 const onClose = () => { // 聚焦终端 getCurrentTerminalSession(false)?.focus(); diff --git a/orion-ops-ui/src/views/host/command-snippet/components/command-snippet-group.vue b/orion-ops-ui/src/views/host/command-snippet/components/command-snippet-list-group.vue similarity index 85% rename from orion-ops-ui/src/views/host/command-snippet/components/command-snippet-group.vue rename to orion-ops-ui/src/views/host/command-snippet/components/command-snippet-list-group.vue index 3585baea..0eacbd3d 100644 --- a/orion-ops-ui/src/views/host/command-snippet/components/command-snippet-group.vue +++ b/orion-ops-ui/src/views/host/command-snippet/components/command-snippet-list-group.vue @@ -10,9 +10,9 @@ @@ -28,7 +28,7 @@