feat: 添加代码片段.
This commit is contained in:
@@ -24,6 +24,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -107,6 +108,7 @@ public class CommandSnippetGroupServiceImpl implements CommandSnippetGroupServic
|
|||||||
// 转换
|
// 转换
|
||||||
return list.stream()
|
return list.stream()
|
||||||
.map(CommandSnippetGroupConvert.MAPPER::to)
|
.map(CommandSnippetGroupConvert.MAPPER::to)
|
||||||
|
.sorted(Comparator.comparing(CommandSnippetGroupVO::getId))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.orion.ops.module.asset.service.impl;
|
|||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
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.constant.ErrorMessage;
|
||||||
import com.orion.ops.framework.common.utils.Valid;
|
import com.orion.ops.framework.common.utils.Valid;
|
||||||
import com.orion.ops.framework.redis.core.utils.RedisMaps;
|
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 org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.Iterator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@@ -138,6 +137,7 @@ public class CommandSnippetServiceImpl implements CommandSnippetService {
|
|||||||
// 转换
|
// 转换
|
||||||
return list.stream()
|
return list.stream()
|
||||||
.map(CommandSnippetConvert.MAPPER::to)
|
.map(CommandSnippetConvert.MAPPER::to)
|
||||||
|
.sorted(Comparator.comparing(CommandSnippetVO::getId))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,15 +45,20 @@ export interface Options {
|
|||||||
disableLayerHinting?: boolean;
|
disableLayerHinting?: boolean;
|
||||||
// 行亮
|
// 行亮
|
||||||
renderLineHighlight?: RenderLineHighlight;
|
renderLineHighlight?: RenderLineHighlight;
|
||||||
// 显示行号
|
// 点击行号时是否应该选择相应的行
|
||||||
selectOnLineNumbers?: boolean;
|
selectOnLineNumbers?: boolean;
|
||||||
|
// 行号最小字符
|
||||||
|
lineNumbersMinChars?: number;
|
||||||
|
// 输入提示
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
// 小地图
|
||||||
minimap?: {
|
minimap?: {
|
||||||
// 关闭小地图
|
// 关闭小地图
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
|
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
};
|
};
|
||||||
|
// 字体大小
|
||||||
fontSize?: number;
|
fontSize?: number;
|
||||||
// 取消代码后面一大段空白
|
// 取消代码后面一大段空白
|
||||||
scrollBeyondLastLine?: boolean;
|
scrollBeyondLastLine?: boolean;
|
||||||
@@ -80,6 +85,7 @@ export const createDefaultOptions = (): Options => {
|
|||||||
showFoldingControls: 'always',
|
showFoldingControls: 'always',
|
||||||
renderLineHighlight: 'line',
|
renderLineHighlight: 'line',
|
||||||
selectOnLineNumbers: true,
|
selectOnLineNumbers: true,
|
||||||
|
lineNumbersMinChars: 2,
|
||||||
disableLayerHinting: true,
|
disableLayerHinting: true,
|
||||||
minimap: {
|
minimap: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ import { getHostList } from '@/api/asset/host';
|
|||||||
import { getHostGroupTree } from '@/api/asset/host-group';
|
import { getHostGroupTree } from '@/api/asset/host-group';
|
||||||
import { getMenuList } from '@/api/system/menu';
|
import { getMenuList } from '@/api/system/menu';
|
||||||
import { getCurrentAuthorizedHostIdentity, getCurrentAuthorizedHostKey } from '@/api/asset/asset-authorized-data';
|
import { getCurrentAuthorizedHostIdentity, getCurrentAuthorizedHostKey } from '@/api/asset/asset-authorized-data';
|
||||||
|
import { getCommandSnippetGroupList } from '@/api/asset/command-snippet-group';
|
||||||
|
|
||||||
export type CacheType = 'users' | 'menus' | 'roles'
|
export type CacheType = 'users' | 'menus' | 'roles'
|
||||||
| 'hosts' | 'hostGroups' | 'hostKeys' | 'hostIdentities'
|
| 'hosts' | 'hostGroups' | 'hostKeys' | 'hostIdentities'
|
||||||
| 'dictKeys'
|
| 'dictKeys'
|
||||||
| 'authorizedHostKeys' | 'authorizedHostIdentities'
|
| 'authorizedHostKeys' | 'authorizedHostIdentities'
|
||||||
|
| 'commandSnippetGroups'
|
||||||
| string
|
| string
|
||||||
|
|
||||||
export default defineStore('cache', {
|
export default defineStore('cache', {
|
||||||
@@ -111,5 +113,10 @@ export default defineStore('cache', {
|
|||||||
return await this.load('authorizedHostIdentities', getCurrentAuthorizedHostIdentity, force);
|
return await this.load('authorizedHostIdentities', getCurrentAuthorizedHostIdentity, force);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 获取命令片段分组
|
||||||
|
async loadCommandSnippetGroups(force = false) {
|
||||||
|
return await this.load('commandSnippetGroups', getCommandSnippetGroupList, force);
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-drawer v-model:visible="visible"
|
<a-drawer v-model:visible="visible"
|
||||||
:title="title"
|
:title="title"
|
||||||
:width="488"
|
:width="388"
|
||||||
:mask-closable="false"
|
:mask-closable="false"
|
||||||
:unmount-on-close="true"
|
:unmount-on-close="true"
|
||||||
:ok-button-props="{ disabled: loading }"
|
:ok-button-props="{ disabled: loading }"
|
||||||
@@ -16,18 +16,20 @@
|
|||||||
:label-col-props="{ span: 6 }"
|
:label-col-props="{ span: 6 }"
|
||||||
:wrapper-col-props="{ span: 18 }"
|
:wrapper-col-props="{ span: 18 }"
|
||||||
:rules="formRules">
|
:rules="formRules">
|
||||||
<!-- 分组 -->
|
|
||||||
<a-form-item field="groupId" label="命令分组">
|
|
||||||
<a-input-number v-model="formModel.groupId"
|
|
||||||
placeholder="请输入命令分组"
|
|
||||||
hide-button />
|
|
||||||
</a-form-item>
|
|
||||||
<!-- 名称 -->
|
<!-- 名称 -->
|
||||||
<a-form-item field="name" label="名称">
|
<a-form-item field="name" label="名称">
|
||||||
<a-input v-model="formModel.name" placeholder="请输入名称" allow-clear />
|
<a-input v-model="formModel.name"
|
||||||
|
placeholder="请输入名称"
|
||||||
|
allow-clear />
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 分组 -->
|
||||||
|
<a-form-item field="groupId" label="命令分组">
|
||||||
|
<command-snippet-group-select v-model="formModel.groupId" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 代码片段 -->
|
<!-- 代码片段 -->
|
||||||
<a-form-item field="command" label="代码片段">
|
<a-form-item field="command"
|
||||||
|
label="代码片段"
|
||||||
|
style="margin: 0;">
|
||||||
<editor v-model="formModel.command"
|
<editor v-model="formModel.command"
|
||||||
containerClass="command-editor"
|
containerClass="command-editor"
|
||||||
language="shell"
|
language="shell"
|
||||||
@@ -50,10 +52,11 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import useVisible from '@/hooks/visible';
|
import useVisible from '@/hooks/visible';
|
||||||
import formRules from '../types/form.rules';
|
|
||||||
import { createCommandSnippet, updateCommandSnippet } from '@/api/asset/command-snippet';
|
import { createCommandSnippet, updateCommandSnippet } from '@/api/asset/command-snippet';
|
||||||
|
import formRules from '../types/form.rules';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { useTerminalStore } from '@/store';
|
import { useTerminalStore } from '@/store';
|
||||||
|
import CommandSnippetGroupSelect from './command-snippet-group-select.vue';
|
||||||
|
|
||||||
const { preference } = useTerminalStore();
|
const { preference } = useTerminalStore();
|
||||||
const { visible, setVisible } = useVisible();
|
const { visible, setVisible } = useVisible();
|
||||||
@@ -110,14 +113,15 @@
|
|||||||
}
|
}
|
||||||
if (isAddHandle.value) {
|
if (isAddHandle.value) {
|
||||||
// 新增
|
// 新增
|
||||||
await createCommandSnippet(formModel.value);
|
const { data: id } = await createCommandSnippet(formModel.value);
|
||||||
|
formModel.value.id = id;
|
||||||
Message.success('创建成功');
|
Message.success('创建成功');
|
||||||
emits('added');
|
emits('added', formModel.value);
|
||||||
} else {
|
} else {
|
||||||
// 修改
|
// 修改
|
||||||
await updateCommandSnippet(formModel.value);
|
await updateCommandSnippet(formModel.value);
|
||||||
Message.success('修改成功');
|
Message.success('修改成功');
|
||||||
emits('updated');
|
emits('updated', formModel.value);
|
||||||
}
|
}
|
||||||
// 清空
|
// 清空
|
||||||
handlerClear();
|
handlerClear();
|
||||||
@@ -146,7 +150,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.command-editor {
|
.command-editor {
|
||||||
height: 340px;
|
height: calc(100vh - 330px);
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
<template>
|
||||||
|
<a-select v-model:model-value="value"
|
||||||
|
placeholder="请选择命令分组"
|
||||||
|
:options="optionData"
|
||||||
|
:loading="loading"
|
||||||
|
:allow-create="true"
|
||||||
|
allow-clear />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'commandSnippetGroupSelect'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { SelectOptionData } from '@arco-design/web-vue';
|
||||||
|
import type { CommandSnippetGroupQueryResponse } from '@/api/asset/command-snippet-group';
|
||||||
|
import { ref, computed, onBeforeMount } from 'vue';
|
||||||
|
import { useCacheStore } from '@/store';
|
||||||
|
import useLoading from '@/hooks/loading';
|
||||||
|
import { createCommandSnippetGroup } from '@/api/asset/command-snippet-group';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: number | undefined
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emits = defineEmits(['update:modelValue']);
|
||||||
|
|
||||||
|
const { loading, setLoading } = useLoading();
|
||||||
|
const cacheStore = useCacheStore();
|
||||||
|
|
||||||
|
const value = computed<number | string>({
|
||||||
|
get() {
|
||||||
|
return props.modelValue as number;
|
||||||
|
},
|
||||||
|
async set(e) {
|
||||||
|
const val = await checkCreateGroup(e);
|
||||||
|
emits('update:modelValue', val);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const optionData = ref<SelectOptionData[]>([]);
|
||||||
|
|
||||||
|
// 检查是否可以创建分组
|
||||||
|
const checkCreateGroup = async (val: string | number): Promise<number> => {
|
||||||
|
// 清空
|
||||||
|
if (!val) {
|
||||||
|
return undefined as unknown as number;
|
||||||
|
}
|
||||||
|
// 为 number 代表为 id 已存在
|
||||||
|
if (typeof val === 'number') {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
// 已存在则跳过
|
||||||
|
const find = optionData.value.find((o) => o.label === val);
|
||||||
|
if (find) {
|
||||||
|
return find.value as number;
|
||||||
|
}
|
||||||
|
// 不存在则创建
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
return await doCreateGroup(val);
|
||||||
|
} catch (e) {
|
||||||
|
return undefined as unknown as number;
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建分组
|
||||||
|
const doCreateGroup = async (name: string) => {
|
||||||
|
const { data: id } = await createCommandSnippetGroup({
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
// 插入缓存
|
||||||
|
const groups = await cacheStore.loadCommandSnippetGroups();
|
||||||
|
groups && groups.push({ id, name } as CommandSnippetGroupQueryResponse);
|
||||||
|
// 插入 options
|
||||||
|
optionData.value.push({
|
||||||
|
label: name,
|
||||||
|
value: id,
|
||||||
|
});
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 初始化选项
|
||||||
|
onBeforeMount(async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const tags = await cacheStore.loadCommandSnippetGroups();
|
||||||
|
optionData.value = tags.map(s => {
|
||||||
|
return {
|
||||||
|
label: s.name,
|
||||||
|
value: s.id,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
||||||
@@ -45,11 +45,11 @@
|
|||||||
<!-- 命令片段 -->
|
<!-- 命令片段 -->
|
||||||
<div v-else class="snippet-list-container">
|
<div v-else class="snippet-list-container">
|
||||||
<!-- 命令片段组 -->
|
<!-- 命令片段组 -->
|
||||||
<command-snippet-group :snippet="snippet" />
|
<command-snippet-list-group :snippet="snippet" />
|
||||||
<!-- 未分组命令片段 -->
|
<!-- 未分组命令片段 -->
|
||||||
<div class="ungrouped-snippet-container">
|
<div class="ungrouped-snippet-container">
|
||||||
<template v-for="item in snippet.ungroupedItems">
|
<template v-for="item in snippet.ungroupedItems">
|
||||||
<command-snippet-item v-if="item.visible"
|
<command-snippet-list-item v-if="item.visible"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:item="item" />
|
:item="item" />
|
||||||
</template>
|
</template>
|
||||||
@@ -57,7 +57,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 命令编辑抽屉 -->
|
<!-- 命令编辑抽屉 -->
|
||||||
<command-snippet-form-drawer ref="formDrawer" />
|
<command-snippet-form-drawer ref="formDrawer"
|
||||||
|
@added="onAdded"
|
||||||
|
@updated="onUpdated" />
|
||||||
</a-drawer>
|
</a-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -73,15 +75,16 @@
|
|||||||
import useVisible from '@/hooks/visible';
|
import useVisible from '@/hooks/visible';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import { deleteCommandSnippet, getCommandSnippetList } from '@/api/asset/command-snippet';
|
import { deleteCommandSnippet, getCommandSnippetList } from '@/api/asset/command-snippet';
|
||||||
import { useTerminalStore } from '@/store';
|
import { useCacheStore, useTerminalStore } from '@/store';
|
||||||
import { openUpdateSnippetKey, removeSnippetKey } from '../types/const';
|
import { openUpdateSnippetKey, removeSnippetKey } from '../types/const';
|
||||||
import CommandSnippetItem from './command-snippet-item.vue';
|
import CommandSnippetListItem from './command-snippet-list-item.vue';
|
||||||
import CommandSnippetGroup from './command-snippet-group.vue';
|
import CommandSnippetListGroup from './command-snippet-list-group.vue';
|
||||||
import CommandSnippetFormDrawer from './command-snippet-form-drawer.vue';
|
import CommandSnippetFormDrawer from './command-snippet-form-drawer.vue';
|
||||||
|
|
||||||
const { loading, setLoading } = useLoading();
|
const { loading, setLoading } = useLoading();
|
||||||
const { visible, setVisible } = useVisible();
|
const { visible, setVisible } = useVisible();
|
||||||
const { getCurrentTerminalSession } = useTerminalStore();
|
const { getCurrentTerminalSession } = useTerminalStore();
|
||||||
|
const cacheStore = useCacheStore();
|
||||||
|
|
||||||
const formDrawer = ref();
|
const formDrawer = ref();
|
||||||
const filterValue = ref<string>();
|
const filterValue = ref<string>();
|
||||||
@@ -135,19 +138,8 @@
|
|||||||
formDrawer.value.openAdd();
|
formDrawer.value.openAdd();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 打开修改
|
|
||||||
provide(openUpdateSnippetKey, (e: CommandSnippetQueryResponse) => {
|
|
||||||
formDrawer.value.openUpdate(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 删除
|
|
||||||
provide(removeSnippetKey, async (id: number) => {
|
|
||||||
if (!snippet.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查找并且删除
|
// 查找并且删除
|
||||||
function findAndSplice(items: Array<CommandSnippetQueryResponse>) {
|
const findAndSplice = (id: number, items: Array<CommandSnippetQueryResponse>) => {
|
||||||
if (items) {
|
if (items) {
|
||||||
const index = items.findIndex(s => s.id === id);
|
const index = items.findIndex(s => s.id === id);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
@@ -156,24 +148,123 @@
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// 暴露 修改抽屉
|
||||||
|
provide(openUpdateSnippetKey, (e: CommandSnippetQueryResponse) => {
|
||||||
|
formDrawer.value.openUpdate(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 暴露 删除
|
||||||
|
provide(removeSnippetKey, async (id: number) => {
|
||||||
|
if (!snippet.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// 删除
|
// 删除
|
||||||
await deleteCommandSnippet(id);
|
await deleteCommandSnippet(id);
|
||||||
|
|
||||||
// 查找并且删除未分组的数据
|
// 查找并且删除未分组的数据
|
||||||
if (findAndSplice(snippet.value.ungroupedItems)) {
|
if (findAndSplice(id, snippet.value.ungroupedItems)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 查找并且删除分组内数据
|
// 查找并且删除分组内数据
|
||||||
for (let group of snippet.value.groups) {
|
for (let group of snippet.value.groups) {
|
||||||
if (findAndSplice(group.items)) {
|
if (findAndSplice(id, group.items)) {
|
||||||
return;
|
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 = () => {
|
const onClose = () => {
|
||||||
// 聚焦终端
|
// 聚焦终端
|
||||||
getCurrentTerminalSession(false)?.focus();
|
getCurrentTerminalSession(false)?.focus();
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<!-- snippet -->
|
<!-- snippet -->
|
||||||
<template v-for="item in group.items">
|
<template v-for="item in group.items">
|
||||||
<command-snippet-item v-if="item.visible"
|
<command-snippet-list-item v-if="item.visible"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:item="item" />
|
:item="item" />
|
||||||
</template>
|
</template>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { CommandSnippetGroupQueryResponse } from '@/api/asset/command-snippet-group';
|
import type { CommandSnippetGroupQueryResponse } from '@/api/asset/command-snippet-group';
|
||||||
import type { CommandSnippetWrapperResponse } from '@/api/asset/command-snippet';
|
import type { CommandSnippetWrapperResponse } from '@/api/asset/command-snippet';
|
||||||
import CommandSnippetItem from './command-snippet-item.vue';
|
import CommandSnippetListItem from './command-snippet-list-item.vue';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
snippet: CommandSnippetWrapperResponse
|
snippet: CommandSnippetWrapperResponse
|
||||||
@@ -131,10 +131,10 @@
|
|||||||
let clickCount = 0;
|
let clickCount = 0;
|
||||||
|
|
||||||
// 修改
|
// 修改
|
||||||
const openUpdateSnippet = inject<(item: CommandSnippetQueryResponse) => void>(openUpdateSnippetKey);
|
const openUpdateSnippet = inject(openUpdateSnippetKey) as (item: CommandSnippetQueryResponse) => void;
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
const removeSnippet = inject<(id: number) => void>(removeSnippetKey);
|
const removeSnippet = inject(removeSnippetKey) as (id: number) => void;
|
||||||
|
|
||||||
// 点击命令
|
// 点击命令
|
||||||
const clickItem = () => {
|
const clickItem = () => {
|
||||||
@@ -210,7 +210,7 @@
|
|||||||
color: var(--color-text-1);
|
color: var(--color-text-1);
|
||||||
text-overflow: unset;
|
text-overflow: unset;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
white-space: unset;
|
white-space: pre-wrap;
|
||||||
user-select: unset;
|
user-select: unset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -268,7 +268,7 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: pre;
|
white-space: nowrap;
|
||||||
width: @item-inline-width;
|
width: @item-inline-width;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
@@ -218,8 +218,8 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 打开配置 FIXME
|
// 打开配置
|
||||||
const openSetting = inject<(record: HostQueryResponse) => void>(openSshModalKey);
|
const openSetting = inject(openSshModalKey) as (record: HostQueryResponse) => void;
|
||||||
|
|
||||||
// 设置收藏
|
// 设置收藏
|
||||||
const setFavorite = async (item: HostQueryResponse) => {
|
const setFavorite = async (item: HostQueryResponse) => {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@
|
|||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
// 卸载时清除 cache
|
// 卸载时清除 cache
|
||||||
cacheStore.reset('authorizedHostKeys', 'authorizedHostIdentities');
|
cacheStore.reset('authorizedHostKeys', 'authorizedHostIdentities', 'commandSnippetGroups');
|
||||||
// 移除关闭视口事件
|
// 移除关闭视口事件
|
||||||
window.removeEventListener('beforeunload', handleBeforeUnload);
|
window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||||
// 去除 body style
|
// 去除 body style
|
||||||
|
|||||||
Reference in New Issue
Block a user