mirror of
https://github.com/chaos-zhu/easynode.git
synced 2026-06-07 22:49:27 +08:00
✨ 支持终端右键菜单
This commit is contained in:
@@ -4,16 +4,16 @@
|
||||
* serv00 SFTP修复
|
||||
* 连接服务器下拉菜单分组展示
|
||||
* 新增服务器定时任务功能
|
||||
* AI对话生成脚本支持一键发送到终端(TODO
|
||||
|
||||
## [3.0.6](https://github.com/chaos-zhu/easynode/releases) (2025-04-xx)
|
||||
## [3.0.6](https://github.com/chaos-zhu/easynode/releases) (2025-05-05)
|
||||
|
||||
* AI问答支持历史记录&标题生成
|
||||
* AI对话生成脚本支持一键发送到终端(TODO
|
||||
* 新增终端选中多功能菜单(一键询问AI、docker容器ID识别快捷操作. 欢迎issue反馈更多快捷功能)(TODO
|
||||
* 新增终端选中多功能菜单(一键询问AI、docker容器ID识别快捷操作. 欢迎issue反馈更多快捷功能)
|
||||
* 添加一些新的内置脚本
|
||||
* 新增终端链接跳转需按住ctrl|alt键(防止误触)
|
||||
* 修复粘贴情景下多终端tab同步会话无效bug
|
||||
* 修复跳板机提示多余空格
|
||||
* 修复xx情景下多终端tab同步会话bug(TODO
|
||||
|
||||
## [3.0.5](https://github.com/chaos-zhu/easynode/releases) (2025-04-04)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "server",
|
||||
"version": "3.0.5",
|
||||
"version": "3.0.6",
|
||||
"description": "easynode-server",
|
||||
"bin": "./bin/www",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
[
|
||||
{
|
||||
"version": "v3.0.5",
|
||||
"date": "2025-04-05",
|
||||
"version": "v3.0.6",
|
||||
"date": "2025-05-05",
|
||||
"features": [
|
||||
"新增AI问答组件及相关配置项,支持deepseekR1、qwq思维链",
|
||||
"脚本库菜单自定义展示(可在本地设置中配置)",
|
||||
"支持在面板配置全局API-IP白名单",
|
||||
"修复终端工具栏高度塌陷",
|
||||
"修复多页面在内容数量超出视窗时溢出样式问题",
|
||||
"全局字体优化统一"
|
||||
"AI问答支持历史记录&标题生成",
|
||||
"新增终端选中多功能菜单(一键询问AI、docker容器ID识别快捷操作. 欢迎issue反馈更多快捷功能)",
|
||||
"添加一些新的内置脚本",
|
||||
"新增终端链接跳转需按住ctrl|alt键(防止误触)",
|
||||
"修复粘贴情景下多终端tab同步会话无效bug",
|
||||
"修复跳板机提示多余空格"
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "web",
|
||||
"version": "3.0.5",
|
||||
"version": "3.0.6",
|
||||
"description": "easynode-web",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -153,3 +153,12 @@ export const isMobile = () => {
|
||||
export const handlePlusSupport = () => {
|
||||
window.open('https://en.221022.xyz/buy-plus', '_blank')
|
||||
}
|
||||
|
||||
export const isDockerId = (id) => {
|
||||
return /^[a-f0-9]{12}|[a-f0-9]{64}$/.test(id)
|
||||
}
|
||||
|
||||
export const isDockerComposeYml = (str) => {
|
||||
return /^docker-compose\.yml$/.test(str)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div class="form_footer">
|
||||
<el-button type="primary" :loading="loading" @click="handleUpdate">立即激活</el-button>
|
||||
<el-button type="success" @click="handlePlusSupport">
|
||||
购买Plus
|
||||
<el-button type="success" :loading="loading" @click="handleUpdate">立即激活</el-button>
|
||||
<el-button type="primary" @click="handlePlusSupport">
|
||||
获取 Plus Key
|
||||
<el-icon class="el-icon--right"><TopRight /></el-icon>
|
||||
</el-button>
|
||||
<span v-if="!isPlusActive && discount" class="discount_wrapper" @click="handlePlusSupport">
|
||||
|
||||
@@ -25,12 +25,12 @@ import socketIo from 'socket.io-client'
|
||||
import themeList from 'xterm-theme'
|
||||
import { terminalStatus } from '@/utils/enum'
|
||||
import { useContextMenu } from '@/composables/useContextMenu'
|
||||
import { EventBus } from '@/utils'
|
||||
import { EventBus, isDockerId, isDockerComposeYml } from '@/utils'
|
||||
|
||||
const { CONNECTING, CONNECT_SUCCESS, CONNECT_FAIL } = terminalStatus
|
||||
|
||||
const { io } = socketIo
|
||||
const { proxy: { $api, $store, $serviceURI, $notification, $router, $message } } = getCurrentInstance()
|
||||
const { proxy: { $api, $store, $serviceURI, $notification, $router, $message, $messageBox } } = getCurrentInstance()
|
||||
|
||||
const props = defineProps({
|
||||
hostObj: {
|
||||
@@ -57,7 +57,6 @@ const timer = ref(null)
|
||||
const pingTimer = ref(null)
|
||||
const fitAddon = ref(null)
|
||||
// const searchBar = ref(null)
|
||||
const showContextMenu = ref(false)
|
||||
const socketConnected = ref(false)
|
||||
const curStatus = ref(CONNECTING)
|
||||
const terminal = ref(null)
|
||||
@@ -267,6 +266,7 @@ const shellResize = () => {
|
||||
let { rows, cols } = term.value
|
||||
socket.value?.emit('resize', { rows, cols })
|
||||
}
|
||||
|
||||
const onResize = () => {
|
||||
fitAddon.value = new FitAddon()
|
||||
term.value.loadAddon(fitAddon.value)
|
||||
@@ -416,6 +416,22 @@ const handleMouseUp = async (e) => {
|
||||
}
|
||||
}
|
||||
|
||||
const plusTips = () => {
|
||||
if (!isPlusActive.value) {
|
||||
// $message.warning('Plus功能未激活')
|
||||
$messageBox.confirm('Plus功能未激活', 'Warning', {
|
||||
confirmButtonText: '前往设置',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
$router.push('/setting?tabKey=plus')
|
||||
})
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const handleRightClick = async (e) => {
|
||||
let str = term.value.getSelection().trim()
|
||||
const sendToAI = str ? {
|
||||
@@ -449,12 +465,121 @@ const handleRightClick = async (e) => {
|
||||
handleClear()
|
||||
}
|
||||
}
|
||||
const dockerId = isDockerId(str) ? {
|
||||
label: 'docker容器ID',
|
||||
children: [
|
||||
{
|
||||
label: '[plus]检测选中内容可能为docker容器ID',
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
label: `登录: docker exec -it ${ str } bash`,
|
||||
onClick: () => {
|
||||
if (!plusTips()) return
|
||||
focusTab()
|
||||
inputCommand(`docker exec -it ${ str } bash`)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: `日志: docker logs -f ${ str }`,
|
||||
onClick: () => {
|
||||
if (!plusTips()) return
|
||||
focusTab()
|
||||
inputCommand(`docker logs -f ${ str }`)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: `重启: docker restart ${ str }`,
|
||||
onClick: () => {
|
||||
if (!plusTips()) return
|
||||
focusTab()
|
||||
inputCommand(`docker restart ${ str }`)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: `删除: docker rm -f ${ str }`,
|
||||
onClick: () => {
|
||||
if (!plusTips()) return
|
||||
$messageBox.confirm(`确认删除该容器:${ str }`, 'Warning', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
focusTab()
|
||||
inputCommand(`docker rm -f ${ str }`)
|
||||
})
|
||||
}
|
||||
},
|
||||
]
|
||||
} : null
|
||||
|
||||
const dockerComposeYml = isDockerComposeYml(str) ? {
|
||||
label: 'docker-compose文件',
|
||||
children: [
|
||||
{
|
||||
label: '[plus]检测选中内容可能为docker-compose文件',
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
label: '启动: docker-compose up -d',
|
||||
onClick: () => {
|
||||
if (!plusTips()) return
|
||||
focusTab()
|
||||
inputCommand('docker-compose up -d')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '停止并删除: docker-compose down',
|
||||
onClick: () => {
|
||||
if (!plusTips()) return
|
||||
focusTab()
|
||||
inputCommand('docker-compose down')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '重启: docker-compose restart',
|
||||
onClick: () => {
|
||||
if (!plusTips()) return
|
||||
focusTab()
|
||||
inputCommand('docker-compose restart')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '查看日志: docker-compose logs -f',
|
||||
onClick: () => {
|
||||
if (!plusTips()) return
|
||||
focusTab()
|
||||
inputCommand('docker-compose logs -f')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '拉取新镜像: docker-compose pull',
|
||||
onClick: () => {
|
||||
if (!plusTips()) return
|
||||
focusTab()
|
||||
inputCommand('docker-compose pull')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '重建: docker-compose up -d --force-recreate',
|
||||
onClick: () => {
|
||||
if (!plusTips()) return
|
||||
focusTab()
|
||||
inputCommand('docker-compose up -d --force-recreate')
|
||||
}
|
||||
},
|
||||
]
|
||||
} : null
|
||||
|
||||
const menu = [
|
||||
sendToAI,
|
||||
copySelection,
|
||||
paste,
|
||||
pasteSelection,
|
||||
clear,
|
||||
dockerId,
|
||||
dockerComposeYml,
|
||||
].filter(Boolean)
|
||||
showMenu(e, menu)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user