✨ 双击终端会话 tab 复制.
This commit is contained in:
@@ -6,9 +6,12 @@
|
||||
|
||||
🐞 修复 SFTP 加载失败后一直 loading
|
||||
🐞 修复 SSH 配置未启用还可以连接
|
||||
🐞 修复 主机配置保存后无法修改状态
|
||||
🐞 修复 主机配置保存后无法修改状态
|
||||
🐞 修复 添加快捷命令时编辑器无代码提示
|
||||
🔨 修改 菜单路由命名逻辑修改
|
||||
🔨 优化 前端组件命名规范化
|
||||
🔨 优化 前端组件命名规范化
|
||||
🌈 新增 双击终端会话 Tab 快速复制
|
||||
🌈 新增 执行模板功能
|
||||
|
||||
[如何升级](/about/update.md?id=_v102)
|
||||
|
||||
|
||||
@@ -37,3 +37,38 @@
|
||||
> SFTP
|
||||
|
||||
* 预览: 默认只能预览 2MB 以内的普通文件, 这个大小可以在前端 env 文件中修改 `VITE_SFTP_PREVIEW_MB`
|
||||
|
||||
> 终端面板
|
||||
|
||||
⭐ 双击终端标签可快速复制会话
|
||||
|
||||
### 执行模板
|
||||
|
||||
用来维护批量执行的命令模板, 支持动态参数, 使用 `@{{ xxx }}` 来替换命令参数。
|
||||
|
||||
* 新增: 新增执行模板
|
||||
* 执行: 使用此命令模板批量执行主机命令
|
||||
* 修改: 修改执行模板
|
||||
* 删除: 删除执行模板
|
||||
|
||||
> 内置参数
|
||||
|
||||
| 参数 | 描述 |
|
||||
|:----------------|:-------------------------|
|
||||
| hostId | 执行主机id |
|
||||
| hostName | 执行主机名称 |
|
||||
| hostCode | 执行主机编码 |
|
||||
| hostAddress | 执行主机地址 |
|
||||
| userId | 执行用户id |
|
||||
| username | 执行用户名 |
|
||||
| execId | 执行记录id |
|
||||
| execHostId | 执行主机记录id |
|
||||
| uuid | 生成任务维度 uuid |
|
||||
| uuidShort | 生成任务维度 uuid 无 '-' |
|
||||
| hostUuid | 生成机器维度 uuid |
|
||||
| hostUuidShort | 生成机器维度 uuid 无 '-' |
|
||||
| timestampMillis | 时间戳毫秒 |
|
||||
| timestamp | 时间戳 |
|
||||
| date | 执行时间 yyyy-MM-dd |
|
||||
| datetime | 执行时间 yyyy-MM-dd HH:mm:ss |
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
#end
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -154,6 +155,7 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
|
||||
// 转换
|
||||
return list.stream()
|
||||
.map(${type}Convert.MAPPER::to)
|
||||
.sorted(Comparator.comparing(${type}VO::getId).reversed())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -276,7 +278,8 @@ public class ${table.serviceImplName} implements ${table.serviceName} {
|
||||
#foreach($field in ${table.fields})
|
||||
.eq(${type}DO::get${field.capitalName}, searchValue)#if($foreach.hasNext).or()#end
|
||||
#end
|
||||
);
|
||||
)
|
||||
.orderByDesc(${type}DO::getId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -134,8 +134,6 @@
|
||||
|
||||
const emits = defineEmits(['openAdd', 'openUpdate']);
|
||||
|
||||
const list = ref<${vue.featureEntity}QueryResponse[]>([]);
|
||||
|
||||
const cardColLayout = useColLayout();
|
||||
const pagination = usePagination();
|
||||
const { loading, setLoading } = useLoading();
|
||||
@@ -143,6 +141,7 @@
|
||||
const { toOptions, getDictValue } = useDictStore();
|
||||
#end
|
||||
|
||||
const list = ref<${vue.featureEntity}QueryResponse[]>([]);
|
||||
const formRef = ref();
|
||||
const formModel = reactive<${vue.featureEntity}QueryRequest>({
|
||||
searchValue: undefined,
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
import { useDictStore } from '@/store';
|
||||
#end
|
||||
|
||||
const emits = defineEmits(['added', 'updated']);
|
||||
|
||||
const { visible, setVisible } = useVisible();
|
||||
const { loading, setLoading } = useLoading();
|
||||
#if($dictMap.entrySet().size() > 0)
|
||||
@@ -78,6 +80,8 @@
|
||||
|
||||
const title = ref<string>();
|
||||
const isAddHandle = ref<boolean>(true);
|
||||
const formRef = ref<any>();
|
||||
const formModel = ref<${vue.featureEntity}UpdateRequest>({});
|
||||
|
||||
const defaultForm = (): ${vue.featureEntity}UpdateRequest => {
|
||||
return {
|
||||
@@ -87,11 +91,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
const formRef = ref<any>();
|
||||
const formModel = ref<${vue.featureEntity}UpdateRequest>({});
|
||||
|
||||
const emits = defineEmits(['added', 'updated']);
|
||||
|
||||
// 打开新增
|
||||
const openAdd = () => {
|
||||
title.value = '添加${table.comment}';
|
||||
|
||||
@@ -74,6 +74,8 @@
|
||||
import { useDictStore } from '@/store';
|
||||
#end
|
||||
|
||||
const emits = defineEmits(['added', 'updated']);
|
||||
|
||||
const { visible, setVisible } = useVisible();
|
||||
const { loading, setLoading } = useLoading();
|
||||
#if($dictMap.entrySet().size() > 0)
|
||||
@@ -82,6 +84,8 @@
|
||||
|
||||
const title = ref<string>();
|
||||
const isAddHandle = ref<boolean>(true);
|
||||
const formRef = ref<any>();
|
||||
const formModel = ref<${vue.featureEntity}UpdateRequest>({});
|
||||
|
||||
const defaultForm = (): ${vue.featureEntity}UpdateRequest => {
|
||||
return {
|
||||
@@ -91,11 +95,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
const formRef = ref<any>();
|
||||
const formModel = ref<${vue.featureEntity}UpdateRequest>({});
|
||||
|
||||
const emits = defineEmits(['added', 'updated']);
|
||||
|
||||
// 打开新增
|
||||
const openAdd = () => {
|
||||
title.value = '添加${table.comment}';
|
||||
|
||||
@@ -157,11 +157,6 @@
|
||||
|
||||
const emits = defineEmits(['openAdd', 'openUpdate']);
|
||||
|
||||
#if($vue.enableRowSelection)
|
||||
const selectedKeys = ref<number[]>([]);
|
||||
#end
|
||||
const tableRenderData = ref<${vue.featureEntity}QueryResponse[]>([]);
|
||||
|
||||
const pagination = usePagination();
|
||||
#if($vue.enableRowSelection)
|
||||
const rowSelection = useRowSelection();
|
||||
@@ -171,6 +166,10 @@
|
||||
const { toOptions, getDictValue } = useDictStore();
|
||||
#end
|
||||
|
||||
#if($vue.enableRowSelection)
|
||||
const selectedKeys = ref<number[]>([]);
|
||||
#end
|
||||
const tableRenderData = ref<${vue.featureEntity}QueryResponse[]>([]);
|
||||
const formModel = reactive<${vue.featureEntity}QueryRequest>({
|
||||
#foreach($field in ${table.fields})
|
||||
${field.propertyName}: undefined,
|
||||
|
||||
@@ -62,6 +62,13 @@
|
||||
#else
|
||||
import ${vue.featureEntity}FormModal from './components/${vue.feature}-form-modal.vue';
|
||||
#end
|
||||
#if($vue.enableCardView)
|
||||
|
||||
const appStore = useAppStore();
|
||||
|
||||
// FIXME 这里需要修改一下字段名称 并且在 appStore 定义该字段
|
||||
const renderTable = computed(() => appStore.${vue.featureEntityFirstLower}View === 'table');
|
||||
#end
|
||||
|
||||
const render = ref(false);
|
||||
const table = ref();
|
||||
@@ -73,12 +80,6 @@
|
||||
#else
|
||||
const modal = ref();
|
||||
#end
|
||||
#if($vue.enableCardView)
|
||||
const appStore = useAppStore();
|
||||
|
||||
// FIXME 这里需要修改一下字段名称 并且在 appStore 定义该字段
|
||||
const renderTable = computed(() => appStore.${vue.featureEntityFirstLower}View === 'table');
|
||||
#end
|
||||
|
||||
// 添加回调
|
||||
const modalAddCallback = () => {
|
||||
|
||||
@@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -99,6 +100,7 @@ public class ExecTemplateServiceImpl implements ExecTemplateService {
|
||||
// 转换
|
||||
return list.stream()
|
||||
.map(ExecTemplateConvert.MAPPER::to)
|
||||
.sorted(Comparator.comparing(ExecTemplateVO::getId).reversed())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -153,7 +155,8 @@ public class ExecTemplateServiceImpl implements ExecTemplateService {
|
||||
return execTemplateDAO.wrapper()
|
||||
.eq(ExecTemplateDO::getId, request.getId())
|
||||
.like(ExecTemplateDO::getName, request.getName())
|
||||
.like(ExecTemplateDO::getCommand, request.getCommand());
|
||||
.like(ExecTemplateDO::getCommand, request.getCommand())
|
||||
.orderByDesc(ExecTemplateDO::getId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,39 +9,51 @@ export interface TemplateParam {
|
||||
export const builtinsParams: Array<TemplateParam> = [
|
||||
{
|
||||
name: 'hostId',
|
||||
desc: '主机id'
|
||||
desc: '执行主机id'
|
||||
}, {
|
||||
name: 'hostName',
|
||||
desc: '主机名称'
|
||||
desc: '执行主机名称'
|
||||
}, {
|
||||
name: 'hostCode',
|
||||
desc: '主机编码'
|
||||
desc: '执行主机编码'
|
||||
}, {
|
||||
name: 'hostAddress',
|
||||
desc: '执行主机地址'
|
||||
}, {
|
||||
name: 'userId',
|
||||
desc: '执行用户id'
|
||||
}, {
|
||||
name: 'username',
|
||||
desc: '执行用户名称'
|
||||
desc: '执行用户名'
|
||||
}, {
|
||||
name: 'execId',
|
||||
desc: '执行id'
|
||||
desc: '执行记录id'
|
||||
}, {
|
||||
name: 'execHostId',
|
||||
desc: '执行主机记录id'
|
||||
}, {
|
||||
name: 'uuid',
|
||||
desc: 'uuid'
|
||||
desc: '生成任务维度 uuid'
|
||||
}, {
|
||||
name: 'uuidShort',
|
||||
desc: 'uuid 无 \'-\''
|
||||
desc: '生成任务维度 uuid 无 \'-\''
|
||||
}, {
|
||||
name: 'timeMillis',
|
||||
name: 'hostUuid',
|
||||
desc: '生成机器维度 uuid'
|
||||
}, {
|
||||
name: 'hostUuidShort',
|
||||
desc: '生成机器维度 uuid 无 \'-\''
|
||||
}, {
|
||||
name: 'timestampMillis',
|
||||
desc: '时间戳毫秒'
|
||||
}, {
|
||||
name: 'timestamp',
|
||||
desc: '时间戳'
|
||||
}, {
|
||||
name: 'date',
|
||||
desc: '时间 yyyy-MM-dd'
|
||||
desc: '执行时间 yyyy-MM-dd'
|
||||
}, {
|
||||
name: 'datetime',
|
||||
desc: '时间 yyyy-MM-dd HH:mm:ss'
|
||||
desc: '执行时间 yyyy-MM-dd HH:mm:ss'
|
||||
},
|
||||
];
|
||||
|
||||
@@ -21,8 +21,9 @@
|
||||
:key="tab.key">
|
||||
<!-- 标题 -->
|
||||
<template #title>
|
||||
<span class="tab-title-wrapper"
|
||||
:style="{ 'border-bottom': `2px ${tab.color || 'transparent'} solid` }">
|
||||
<span class="tab-title-wrapper usn"
|
||||
:style="{ 'border-bottom': `2px ${tab.color || 'transparent'} solid` }"
|
||||
@dblclick="copySession(tab, index)">
|
||||
<span class="tab-title-icon">
|
||||
<component :is="tab.icon" />
|
||||
</span>
|
||||
@@ -59,7 +60,7 @@
|
||||
|
||||
const emits = defineEmits(['close', 'openNewConnect']);
|
||||
|
||||
const { sessionManager } = useTerminalStore();
|
||||
const { sessionManager, copySession } = useTerminalStore();
|
||||
|
||||
// 监听 tab 切换
|
||||
watch(() => props.panel.active, (active, before) => {
|
||||
|
||||
Reference in New Issue
Block a user