mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-18 22:22:59 +08:00
fix: 默认本地连接信息,连接错误信息统一返回
This commit is contained in:
parent
c74883bde9
commit
6fefe29298
@ -28,7 +28,7 @@ func (b *BaseApi) CreateHost(c *gin.Context) {
|
||||
helper.SuccessWithData(c, host)
|
||||
}
|
||||
|
||||
func (b *BaseApi) TestConn(c *gin.Context) {
|
||||
func (b *BaseApi) TestByInfo(c *gin.Context) {
|
||||
var req dto.HostConnTest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
@ -41,17 +41,26 @@ func (b *BaseApi) TestConn(c *gin.Context) {
|
||||
|
||||
var connInfo ssh.ConnInfo
|
||||
if err := copier.Copy(&connInfo, &req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, constant.ErrStructTransform)
|
||||
return
|
||||
helper.SuccessWithData(c, false)
|
||||
}
|
||||
client, err := connInfo.NewClient()
|
||||
if err != nil {
|
||||
helper.SuccessWithData(c, false)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
helper.SuccessWithData(c, true)
|
||||
}
|
||||
|
||||
func (b *BaseApi) TestByID(c *gin.Context) {
|
||||
id, err := helper.GetParamID(c)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
helper.SuccessWithData(c, nil)
|
||||
connStatus := hostService.TestLocalConn(id)
|
||||
helper.SuccessWithData(c, connStatus)
|
||||
}
|
||||
|
||||
func (b *BaseApi) HostTree(c *gin.Context) {
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
type HostOperate struct {
|
||||
ID uint `json:"id"`
|
||||
GroupBelong string `json:"groupBelong" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Name string `json:"name"`
|
||||
Addr string `json:"addr" validate:"required,ip"`
|
||||
Port uint `json:"port" validate:"required,number,max=65535,min=1"`
|
||||
User string `json:"user" validate:"required"`
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/ssh"
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -13,6 +14,7 @@ import (
|
||||
type HostService struct{}
|
||||
|
||||
type IHostService interface {
|
||||
TestLocalConn(id uint) bool
|
||||
GetHostInfo(id uint) (*model.Host, error)
|
||||
SearchForTree(search dto.SearchForTree) ([]dto.HostTree, error)
|
||||
Create(hostDto dto.HostOperate) (*dto.HostInfo, error)
|
||||
@ -24,6 +26,35 @@ func NewIHostService() IHostService {
|
||||
return &HostService{}
|
||||
}
|
||||
|
||||
func (u *HostService) TestLocalConn(id uint) bool {
|
||||
var (
|
||||
host model.Host
|
||||
err error
|
||||
)
|
||||
if id == 0 {
|
||||
host, err = hostRepo.Get(hostRepo.WithByAddr("127.0.0.1"))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
host, err = hostRepo.Get(commonRepo.WithByID(id))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
var connInfo ssh.ConnInfo
|
||||
if err := copier.Copy(&connInfo, &host); err != nil {
|
||||
return false
|
||||
}
|
||||
client, err := connInfo.NewClient()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (u *HostService) GetHostInfo(id uint) (*model.Host, error) {
|
||||
host, err := hostRepo.Get(commonRepo.WithByID(id))
|
||||
if err != nil {
|
||||
@ -49,7 +80,7 @@ func (u *HostService) SearchForTree(search dto.SearchForTree) ([]dto.HostTree, e
|
||||
for _, host := range hosts {
|
||||
label := fmt.Sprintf("%s@%s:%d", host.User, host.Addr, host.Port)
|
||||
if len(host.Name) != 0 {
|
||||
label = fmt.Sprintf("%s-%s@%s:%d", host.Name, host.User, host.Addr, host.Port)
|
||||
label = fmt.Sprintf("%s - %s@%s:%d", host.Name, host.User, host.Addr, host.Port)
|
||||
}
|
||||
if host.GroupBelong == group.Name {
|
||||
data.Children = append(data.Children, dto.TreeChild{ID: host.ID, Label: label})
|
||||
@ -113,6 +144,9 @@ func (u *HostService) Delete(id uint) error {
|
||||
if host.ID == 0 {
|
||||
return constant.ErrRecordNotFound
|
||||
}
|
||||
if host.Addr == "127.0.0.1" {
|
||||
return errors.New("the local connection information cannot be deleted!")
|
||||
}
|
||||
return hostRepo.Delete(commonRepo.WithByID(id))
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,12 @@ var AddTableHost = &gormigrate.Migration{
|
||||
if err := tx.Create(&group).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
host := model.Host{
|
||||
Name: "localhost", Addr: "127.0.0.1", User: "root", Port: 22, GroupBelong: "default",
|
||||
}
|
||||
if err := tx.Create(&host).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -20,7 +20,8 @@ func (s *HostRouter) InitHostRouter(Router *gin.RouterGroup) {
|
||||
hostRouter.POST("/del", baseApi.DeleteHost)
|
||||
hostRouter.POST("/update", baseApi.UpdateHost)
|
||||
hostRouter.POST("/search", baseApi.HostTree)
|
||||
hostRouter.POST("/testconn", baseApi.TestConn)
|
||||
hostRouter.POST("/test/byinfo", baseApi.TestByInfo)
|
||||
hostRouter.POST("/test/byid/:id", baseApi.TestByID)
|
||||
hostRouter.GET(":id", baseApi.GetHostInfo)
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,12 @@ export const addHost = (params: Host.HostOperate) => {
|
||||
return http.post<Host.HostOperate>(`/hosts`, params);
|
||||
};
|
||||
|
||||
export const testConn = (params: Host.HostConnTest) => {
|
||||
return http.post(`/hosts/testconn`, params);
|
||||
export const testByInfo = (params: Host.HostConnTest) => {
|
||||
return http.post<boolean>(`/hosts/test/byinfo`, params);
|
||||
};
|
||||
|
||||
export const testByID = (id: number) => {
|
||||
return http.post<boolean>(`/hosts/test/byid/${id}`);
|
||||
};
|
||||
|
||||
export const editHost = (params: Host.HostOperate) => {
|
||||
|
@ -560,6 +560,7 @@ export default {
|
||||
testConn: 'Test connection',
|
||||
saveAndConn: 'Save and Connect',
|
||||
connTestOk: 'Connection information available',
|
||||
connTestFailed: 'Connection unavailable, please check connection information!',
|
||||
hostList: 'Host information',
|
||||
createConn: 'Create a connection',
|
||||
createGroup: 'Create a group',
|
||||
@ -572,9 +573,10 @@ export default {
|
||||
quickCmd: 'Quick command',
|
||||
addHost: 'Add Host',
|
||||
localhost: 'Localhost',
|
||||
ip: 'Address',
|
||||
name: 'Name',
|
||||
port: 'Port',
|
||||
user: 'User',
|
||||
user: 'Username',
|
||||
authMode: 'Auth Mode',
|
||||
passwordMode: 'password',
|
||||
keyMode: 'PrivateKey',
|
||||
|
@ -573,6 +573,7 @@ export default {
|
||||
testConn: '连接测试',
|
||||
saveAndConn: '保存并连接',
|
||||
connTestOk: '连接信息可用',
|
||||
connTestFailed: '连接不可用,请检查连接信息!',
|
||||
hostList: '主机信息',
|
||||
createConn: '创建连接',
|
||||
createGroup: '创建分组',
|
||||
@ -585,9 +586,10 @@ export default {
|
||||
command: '命令',
|
||||
addHost: '添加主机',
|
||||
localhost: '本地服务器',
|
||||
ip: '主机地址',
|
||||
name: '名称',
|
||||
port: '端口',
|
||||
user: '用户',
|
||||
user: '用户名',
|
||||
authMode: '认证方式',
|
||||
passwordMode: '密码输入',
|
||||
keyMode: '密钥输入',
|
||||
|
@ -58,7 +58,12 @@
|
||||
v-if="!(node.level === 1 && data.label === 'default') && data.id === hover"
|
||||
>
|
||||
<el-button v-if="!data.onEdit" icon="Edit" link @click="onEdit(node, data)" />
|
||||
<el-button v-if="!data.onEdit" icon="Delete" link @click="onDelete(node, data)" />
|
||||
<el-button
|
||||
v-if="!data.onEdit && node.label.indexOf('@127.0.0.1:') === -1"
|
||||
icon="Delete"
|
||||
link
|
||||
@click="onDelete(node, data)"
|
||||
/>
|
||||
<el-button v-if="data.onEdit" icon="Check" link @click="onUpdateGroup()" />
|
||||
<el-button v-if="data.onEdit" icon="Close" link @click="data.onEdit = false" />
|
||||
</div>
|
||||
@ -70,7 +75,7 @@
|
||||
<el-col :span="16">
|
||||
<el-card class="el-card">
|
||||
<el-form ref="hostInfoRef" label-width="100px" :model="hostInfo" :rules="rules">
|
||||
<el-form-item label="IP" prop="addr">
|
||||
<el-form-item :label="$t('terminal.ip')" prop="addr">
|
||||
<el-input clearable v-model="hostInfo.addr" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('terminal.user')" prop="user">
|
||||
@ -146,7 +151,7 @@ import type { ElForm } from 'element-plus';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { Host } from '@/api/interface/host';
|
||||
import { Group } from '@/api/interface/group';
|
||||
import { testConn, getHostTree, getHostInfo, addHost, editHost, deleteHost } from '@/api/modules/host';
|
||||
import { getHostTree, getHostInfo, addHost, editHost, deleteHost, testByInfo } from '@/api/modules/host';
|
||||
import { getGroupList, addGroup, editGroup, deleteGroup } from '@/api/modules/group';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import { ElMessage } from 'element-plus';
|
||||
@ -157,7 +162,7 @@ type FormInstance = InstanceType<typeof ElForm>;
|
||||
const hostInfoRef = ref<FormInstance>();
|
||||
const rules = reactive({
|
||||
groupBelong: [Rules.requiredSelect],
|
||||
addr: [Rules.requiredInput, Rules.ip],
|
||||
addr: [Rules.requiredInput],
|
||||
port: [Rules.requiredInput, Rules.port],
|
||||
user: [Rules.requiredInput],
|
||||
authMode: [Rules.requiredSelect],
|
||||
@ -251,8 +256,13 @@ const submitAddHost = (formEl: FormInstance | undefined, ops: string) => {
|
||||
loadHostTree();
|
||||
break;
|
||||
case 'testconn':
|
||||
await testConn(hostInfo);
|
||||
ElMessage.success(i18n.global.t('terminal.connTestOk'));
|
||||
await testByInfo(hostInfo).then((res) => {
|
||||
if (res.data) {
|
||||
ElMessage.success(i18n.global.t('terminal.connTestOk'));
|
||||
} else {
|
||||
ElMessage.success(i18n.global.t('terminal.connTestFailed'));
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
@ -2,6 +2,7 @@
|
||||
<div>
|
||||
<el-dialog v-model="dialogVisiable" :title="$t('terminal.addHost')" width="30%">
|
||||
<el-alert
|
||||
v-if="isLocal"
|
||||
style="margin-bottom: 20px"
|
||||
center
|
||||
:title="$t('terminal.connLocalErr')"
|
||||
@ -9,7 +10,7 @@
|
||||
type="warning"
|
||||
/>
|
||||
<el-form ref="hostRef" label-width="100px" :model="hostInfo" :rules="rules">
|
||||
<el-form-item label="IP" prop="addr">
|
||||
<el-form-item :label="$t('terminal.ip')" prop="addr">
|
||||
<el-input v-if="!isLocal" clearable v-model="hostInfo.addr" />
|
||||
<span v-if="isLocal">{{ hostInfo.addr }}</span>
|
||||
</el-form-item>
|
||||
@ -57,7 +58,7 @@
|
||||
import { ElForm, ElMessage } from 'element-plus';
|
||||
import { Host } from '@/api/interface/host';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { addHost, testConn } from '@/api/modules/host';
|
||||
import { addHost, testByInfo } from '@/api/modules/host';
|
||||
import i18n from '@/lang';
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
@ -79,7 +80,7 @@ let hostInfo = reactive<Host.HostOperate>({
|
||||
});
|
||||
|
||||
const rules = reactive({
|
||||
addr: [Rules.requiredInput, Rules.ip],
|
||||
addr: [Rules.requiredInput],
|
||||
port: [Rules.requiredInput, Rules.port],
|
||||
user: [Rules.requiredInput],
|
||||
authMode: [Rules.requiredSelect],
|
||||
@ -92,9 +93,10 @@ interface DialogProps {
|
||||
isLocal: boolean;
|
||||
}
|
||||
const acceptParams = (props: DialogProps) => {
|
||||
isLocal.value = props.isLocal;
|
||||
if (props.isLocal) {
|
||||
isLocal.value = props.isLocal;
|
||||
hostInfo.addr = '127.0.0.1';
|
||||
hostInfo.user = 'root';
|
||||
}
|
||||
dialogVisiable.value = true;
|
||||
};
|
||||
@ -108,8 +110,13 @@ const submitAddHost = (formEl: FormInstance | undefined, ops: string) => {
|
||||
hostInfo.groupBelong = 'default';
|
||||
switch (ops) {
|
||||
case 'testConn':
|
||||
await testConn(hostInfo);
|
||||
ElMessage.success(i18n.global.t('terminal.connTestOk'));
|
||||
await testByInfo(hostInfo).then((res) => {
|
||||
if (res.data) {
|
||||
ElMessage.success(i18n.global.t('terminal.connTestOk'));
|
||||
} else {
|
||||
ElMessage.success(i18n.global.t('terminal.connTestFailed'));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'saveAndConn':
|
||||
const res = await addHost(hostInfo);
|
||||
@ -118,7 +125,7 @@ const submitAddHost = (formEl: FormInstance | undefined, ops: string) => {
|
||||
if (res.data.name.length !== 0) {
|
||||
title = res.data.name + '-' + title;
|
||||
}
|
||||
emit('on-conn-terminal', title, res.data.id, res.data.addr);
|
||||
emit('on-conn-terminal', title, res.data.id, res.data.addr, '');
|
||||
emit('load-host-tree');
|
||||
}
|
||||
});
|
||||
|
@ -129,7 +129,7 @@ import { ElTree } from 'element-plus';
|
||||
import screenfull from 'screenfull';
|
||||
import i18n from '@/lang';
|
||||
import { Host } from '@/api/interface/host';
|
||||
import { getHostTree } from '@/api/modules/host';
|
||||
import { getHostTree, testByID } from '@/api/modules/host';
|
||||
import { getCommandList } from '@/api/modules/command';
|
||||
|
||||
const dialogRef = ref();
|
||||
@ -168,33 +168,35 @@ interface Tree {
|
||||
children?: Tree[];
|
||||
}
|
||||
|
||||
const acceptParams = () => {
|
||||
loadHostTree();
|
||||
const acceptParams = async () => {
|
||||
loadCommand();
|
||||
const res = await getHostTree({});
|
||||
hostTree.value = res.data;
|
||||
timer = setInterval(() => {
|
||||
syncTerminal();
|
||||
}, 1000 * 5);
|
||||
// for (const item of hostTree.value) {
|
||||
// if (!item.children) {
|
||||
// continue;
|
||||
// }
|
||||
// for (const host of item.children) {
|
||||
// if (host.label.indexOf('127.0.0.1') !== -1) {
|
||||
// localHostID.value = host.id;
|
||||
// if (terminalTabs.value.length === 0) {
|
||||
// onConnTerminal(i18n.global.t('terminal.localhost'), localHostID.value, '127.0.0.1');
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
for (const item of hostTree.value) {
|
||||
if (!item.children) {
|
||||
continue;
|
||||
}
|
||||
for (const host of item.children) {
|
||||
if (host.label.indexOf('127.0.0.1') !== -1) {
|
||||
localHostID.value = host.id;
|
||||
if (terminalTabs.value.length !== 0) {
|
||||
return;
|
||||
}
|
||||
onNewLocal();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const cleanTimer = () => {
|
||||
clearInterval(Number(timer));
|
||||
timer = null;
|
||||
for (const terminal of terminalTabs.value) {
|
||||
if (ctx && ctx.refs[`t-${terminal.key}`][0]) {
|
||||
terminal.status = ctx.refs[`t-${terminal.key}`][0].onClose();
|
||||
if (ctx && ctx.refs[`t-${terminal.index}`][0]) {
|
||||
terminal.status = ctx.refs[`t-${terminal.index}`][0].onClose();
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -239,11 +241,15 @@ const loadCommand = async () => {
|
||||
};
|
||||
|
||||
function quickInput(val: any) {
|
||||
if (val !== '') {
|
||||
if (ctx) {
|
||||
ctx.refs[`t-${terminalValue.value}`] && ctx.refs[`t-${terminalValue.value}`][0].onSendMsg(val + '\n');
|
||||
quickCmd.value = '';
|
||||
if (val !== '' && ctx) {
|
||||
if (isBatch.value) {
|
||||
for (const tab of terminalTabs.value) {
|
||||
ctx.refs[`t-${tab.index}`] && ctx.refs[`t-${tab.index}`][0].onSendMsg(val + '\n');
|
||||
}
|
||||
return;
|
||||
}
|
||||
ctx.refs[`t-${terminalValue.value}`] && ctx.refs[`t-${terminalValue.value}`][0].onSendMsg(val + '\n');
|
||||
quickCmd.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,7 +259,7 @@ function batchInput() {
|
||||
}
|
||||
if (isBatch.value) {
|
||||
for (const tab of terminalTabs.value) {
|
||||
ctx.refs[`t-${tab.key}`] && ctx.refs[`t-${tab.key}`][0].onSendMsg(batchVal.value + '\n');
|
||||
ctx.refs[`t-${tab.index}`] && ctx.refs[`t-${tab.index}`][0].onSendMsg(batchVal.value + '\n');
|
||||
}
|
||||
batchVal.value = '';
|
||||
return;
|
||||
@ -272,7 +278,7 @@ const onNewSsh = () => {
|
||||
dialogRef.value!.acceptParams({ isLocal: false });
|
||||
};
|
||||
const onNewLocal = () => {
|
||||
onConnTerminal(i18n.global.t('terminal.localhost'), localHostID.value);
|
||||
onConnTerminal(i18n.global.t('terminal.localhost'), localHostID.value, true);
|
||||
};
|
||||
|
||||
const onClickConn = (node: Node, data: Tree) => {
|
||||
@ -284,26 +290,39 @@ const onClickConn = (node: Node, data: Tree) => {
|
||||
|
||||
const onReconnect = async (item: any) => {
|
||||
if (ctx) {
|
||||
ctx.refs[`t-${item.key}`] && ctx.refs[`t-${item.key}`][0].onClose();
|
||||
ctx.refs[`t-${item.index}`] && ctx.refs[`t-${item.index}`][0].onClose();
|
||||
}
|
||||
item.Refresh = !item.Refresh;
|
||||
ctx.refs[`t-${item.key}`];
|
||||
const res = await testByID(item.wsID);
|
||||
nextTick(() => {
|
||||
ctx.refs[`t-${item.index}`] &&
|
||||
ctx.refs[`t-${item.index}`][0].acceptParams({
|
||||
wsID: item.wsID,
|
||||
terminalID: item.index,
|
||||
error: res.data ? '' : 'Failed to set up the connection. Please check the host information',
|
||||
});
|
||||
});
|
||||
syncTerminal();
|
||||
};
|
||||
|
||||
const onConnTerminal = (title: string, wsID: number) => {
|
||||
const onConnTerminal = async (title: string, wsID: number, isLocal?: boolean) => {
|
||||
const res = await testByID(wsID);
|
||||
terminalTabs.value.push({
|
||||
index: tabIndex,
|
||||
title: title,
|
||||
wsID: wsID,
|
||||
status: 'online',
|
||||
status: res.data ? 'online' : 'closed',
|
||||
});
|
||||
terminalValue.value = tabIndex;
|
||||
if (!res.data && isLocal) {
|
||||
dialogRef.value!.acceptParams({ isLocal: true });
|
||||
}
|
||||
nextTick(() => {
|
||||
ctx.refs[`t-${terminalValue.value}`] &&
|
||||
ctx.refs[`t-${terminalValue.value}`][0].acceptParams({
|
||||
wsID: wsID,
|
||||
terminalID: terminalValue.value,
|
||||
error: res.data ? '' : 'Failed to set up the connection. Please check the host information !',
|
||||
});
|
||||
});
|
||||
tabIndex++;
|
||||
@ -356,7 +375,7 @@ defineExpose({
|
||||
.fullScreen {
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
top: 86px;
|
||||
top: 80px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
@ -15,13 +15,18 @@ const wsID = ref();
|
||||
interface WsProps {
|
||||
terminalID: string;
|
||||
wsID: number;
|
||||
error: string;
|
||||
}
|
||||
const acceptParams = (props: WsProps) => {
|
||||
terminalID.value = props.terminalID;
|
||||
wsID.value = props.wsID;
|
||||
nextTick(() => {
|
||||
initTerm();
|
||||
window.addEventListener('resize', changeTerminalSize);
|
||||
if (props.error.length !== 0) {
|
||||
initErrorTerm(props.error);
|
||||
} else {
|
||||
initTerm();
|
||||
window.addEventListener('resize', changeTerminalSize);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -57,13 +62,34 @@ const errorRealTerminal = (ex: any) => {
|
||||
let message = ex.message;
|
||||
if (!message) message = 'disconnected';
|
||||
term.write(`\x1b[31m${message}\x1b[m\r\n`);
|
||||
console.log('err');
|
||||
};
|
||||
|
||||
const closeRealTerminal = (ev: CloseEvent) => {
|
||||
term.write(ev.reason);
|
||||
};
|
||||
|
||||
const initErrorTerm = (errorInfo: string) => {
|
||||
let ifm = document.getElementById('terminal-' + terminalID.value) as HTMLInputElement | null;
|
||||
term = new Terminal({
|
||||
lineHeight: 1.2,
|
||||
fontSize: 12,
|
||||
fontFamily: "Monaco, Menlo, Consolas, 'Courier New', monospace",
|
||||
theme: {
|
||||
background: '#000000',
|
||||
},
|
||||
cursorBlink: true,
|
||||
cursorStyle: 'underline',
|
||||
scrollback: 100,
|
||||
tabStopWidth: 4,
|
||||
});
|
||||
if (ifm) {
|
||||
term.open(ifm);
|
||||
term.write(errorInfo);
|
||||
term.loadAddon(fitAddon);
|
||||
fitAddon.fit();
|
||||
}
|
||||
};
|
||||
|
||||
const initTerm = () => {
|
||||
let ifm = document.getElementById('terminal-' + terminalID.value) as HTMLInputElement | null;
|
||||
let href = window.location.href;
|
||||
@ -127,8 +153,12 @@ const isWsOpen = () => {
|
||||
|
||||
function onClose() {
|
||||
window.removeEventListener('resize', changeTerminalSize);
|
||||
terminalSocket && terminalSocket.close();
|
||||
term && term.dispose();
|
||||
try {
|
||||
terminalSocket.close();
|
||||
} catch {}
|
||||
try {
|
||||
term.dispose();
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function onSendMsg(command: string) {
|
||||
|
Loading…
Reference in New Issue
Block a user