mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-12-17 21:08:25 +08:00
Merge branch 'first-commit' of https://github.com/1Panel-dev/1Panel into first-commit
This commit is contained in:
commit
0a11f07087
20 changed files with 153 additions and 36 deletions
|
|
@ -9,13 +9,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *BaseApi) GetOperationList(c *gin.Context) {
|
func (b *BaseApi) GetOperationList(c *gin.Context) {
|
||||||
pagenation, isOK := helper.GeneratePaginationFromReq(c)
|
var req dto.PageInfo
|
||||||
if !isOK {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, constant.ErrPageGenerate)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
total, list, err := operationService.Page(pagenation.Page, pagenation.PageSize)
|
total, list, err := operationService.Page(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -68,13 +68,13 @@ func (b *BaseApi) Register(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BaseApi) PageUsers(c *gin.Context) {
|
func (b *BaseApi) PageUsers(c *gin.Context) {
|
||||||
pagenation, isOK := helper.GeneratePaginationFromReq(c)
|
var req dto.UserPage
|
||||||
if !isOK {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, constant.ErrPageGenerate)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
total, list, err := userService.Page(pagenation.Page, pagenation.PageSize)
|
total, list, err := userService.Page(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package dto
|
||||||
type PageInfo struct {
|
type PageInfo struct {
|
||||||
Page int `json:"page" validate:"required,number"`
|
Page int `json:"page" validate:"required,number"`
|
||||||
PageSize int `json:"pageSize" validate:"required,number"`
|
PageSize int `json:"pageSize" validate:"required,number"`
|
||||||
Limit int `json:"limit" validate:"required,number"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type OperationWithName struct {
|
type OperationWithName struct {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import (
|
||||||
type OperationService struct{}
|
type OperationService struct{}
|
||||||
|
|
||||||
type IOperationService interface {
|
type IOperationService interface {
|
||||||
Page(page, size int) (int64, interface{}, error)
|
Page(search dto.PageInfo) (int64, interface{}, error)
|
||||||
Create(operation model.OperationLog) error
|
Create(operation model.OperationLog) error
|
||||||
BatchDelete(ids []uint) error
|
BatchDelete(ids []uint) error
|
||||||
}
|
}
|
||||||
|
|
@ -27,8 +27,8 @@ func (u *OperationService) Create(operation model.OperationLog) error {
|
||||||
return operationRepo.Create(&operation)
|
return operationRepo.Create(&operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *OperationService) Page(page, size int) (int64, interface{}, error) {
|
func (u *OperationService) Page(search dto.PageInfo) (int64, interface{}, error) {
|
||||||
total, ops, err := operationRepo.Page(page, size, commonRepo.WithOrderBy("created_at desc"))
|
total, ops, err := operationRepo.Page(search.Page, search.PageSize, commonRepo.WithOrderBy("created_at desc"))
|
||||||
var dtoOps []dto.OperationLogBack
|
var dtoOps []dto.OperationLogBack
|
||||||
for _, op := range ops {
|
for _, op := range ops {
|
||||||
var item dto.OperationLogBack
|
var item dto.OperationLogBack
|
||||||
|
|
@ -57,7 +57,7 @@ func (u *OperationService) BatchDelete(ids []uint) error {
|
||||||
|
|
||||||
func filterSensitive(vars string) string {
|
func filterSensitive(vars string) string {
|
||||||
var Sensitives = []string{"password", "Password"}
|
var Sensitives = []string{"password", "Password"}
|
||||||
ops := make(map[string]string)
|
ops := make(map[string]interface{})
|
||||||
if err := json.Unmarshal([]byte(vars), &ops); err != nil {
|
if err := json.Unmarshal([]byte(vars), &ops); err != nil {
|
||||||
return vars
|
return vars
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ type UserService struct{}
|
||||||
|
|
||||||
type IUserService interface {
|
type IUserService interface {
|
||||||
Get(name uint) (*dto.UserBack, error)
|
Get(name uint) (*dto.UserBack, error)
|
||||||
Page(page, size int) (int64, interface{}, error)
|
Page(search dto.UserPage) (int64, interface{}, error)
|
||||||
Register(userDto dto.UserCreate) error
|
Register(userDto dto.UserCreate) error
|
||||||
Login(c *gin.Context, info dto.Login) (*dto.UserLoginInfo, error)
|
Login(c *gin.Context, info dto.Login) (*dto.UserLoginInfo, error)
|
||||||
LogOut(c *gin.Context) error
|
LogOut(c *gin.Context) error
|
||||||
|
|
@ -44,8 +44,8 @@ func (u *UserService) Get(id uint) (*dto.UserBack, error) {
|
||||||
return &dtoUser, err
|
return &dtoUser, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserService) Page(page, size int) (int64, interface{}, error) {
|
func (u *UserService) Page(search dto.UserPage) (int64, interface{}, error) {
|
||||||
total, users, err := userRepo.Page(page, size, commonRepo.WithOrderBy("created_at desc"))
|
total, users, err := userRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Name))
|
||||||
var dtoUsers []dto.UserBack
|
var dtoUsers []dto.UserBack
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
var item dto.UserBack
|
var item dto.UserBack
|
||||||
|
|
|
||||||
BIN
backend/cmd/gotty/gotty
Executable file
BIN
backend/cmd/gotty/gotty
Executable file
Binary file not shown.
23
backend/init/binary/gotty.go
Normal file
23
backend/init/binary/gotty.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package binary
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StartTTY() {
|
||||||
|
cmd := "gotty"
|
||||||
|
params := []string{"--permit-write", "bash"}
|
||||||
|
go func() {
|
||||||
|
c := exec.Command(cmd, params...)
|
||||||
|
c.Env = append(c.Env, os.Environ()...)
|
||||||
|
c.Stdout = io.Discard
|
||||||
|
c.Stderr = io.Discard
|
||||||
|
if err := c.Run(); err != nil {
|
||||||
|
global.LOG.Error(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
@ -14,7 +14,7 @@ func (s *OperationLogRouter) InitOperationLogRouter(Router *gin.RouterGroup) {
|
||||||
operationRouter.Use(middleware.JwtAuth()).Use(middleware.SessionAuth())
|
operationRouter.Use(middleware.JwtAuth()).Use(middleware.SessionAuth())
|
||||||
baseApi := v1.ApiGroupApp.BaseApi
|
baseApi := v1.ApiGroupApp.BaseApi
|
||||||
{
|
{
|
||||||
operationRouter.GET("", baseApi.GetOperationList)
|
operationRouter.POST("", baseApi.GetOperationList)
|
||||||
operationRouter.POST("/del", baseApi.DeleteOperation)
|
operationRouter.POST("/del", baseApi.DeleteOperation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ func (s *UserRouter) InitUserRouter(Router *gin.RouterGroup) {
|
||||||
{
|
{
|
||||||
withRecordRouter.POST("", baseApi.Register)
|
withRecordRouter.POST("", baseApi.Register)
|
||||||
withRecordRouter.POST("/del", baseApi.DeleteUser)
|
withRecordRouter.POST("/del", baseApi.DeleteUser)
|
||||||
userRouter.GET("", baseApi.PageUsers)
|
userRouter.POST("/search", baseApi.PageUsers)
|
||||||
userRouter.GET(":id", baseApi.GetUserInfo)
|
userRouter.GET(":id", baseApi.GetUserInfo)
|
||||||
userRouter.POST(":id", baseApi.UpdateUser)
|
userRouter.PUT(":id", baseApi.UpdateUser)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/global"
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
|
"github.com/1Panel-dev/1Panel/init/binary"
|
||||||
"github.com/1Panel-dev/1Panel/init/db"
|
"github.com/1Panel-dev/1Panel/init/db"
|
||||||
"github.com/1Panel-dev/1Panel/init/log"
|
"github.com/1Panel-dev/1Panel/init/log"
|
||||||
"github.com/1Panel-dev/1Panel/init/migration"
|
"github.com/1Panel-dev/1Panel/init/migration"
|
||||||
|
|
@ -29,6 +30,7 @@ func Start() {
|
||||||
gob.Register(psession.SessionUser{})
|
gob.Register(psession.SessionUser{})
|
||||||
cache.Init()
|
cache.Init()
|
||||||
session.Init()
|
session.Init()
|
||||||
|
binary.StartTTY()
|
||||||
routers := router.Routers()
|
routers := router.Routers()
|
||||||
address := fmt.Sprintf(":%d", global.CONF.System.Port)
|
address := fmt.Sprintf(":%d", global.CONF.System.Port)
|
||||||
s := initServer(address, routers)
|
s := initServer(address, routers)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import http from '@/api';
|
import http from '@/api';
|
||||||
import { ResPage } from '../interface';
|
import { ResPage, ReqPage } from '../interface';
|
||||||
import { ResOperationLog } from '../interface/operation-log';
|
import { ResOperationLog } from '../interface/operation-log';
|
||||||
|
|
||||||
export const getOperationList = (currentPage: number, pageSize: number) => {
|
export const getOperationList = (info: ReqPage) => {
|
||||||
return http.get<ResPage<ResOperationLog>>(`/operations?page=${currentPage}&pageSize=${pageSize}`);
|
return http.post<ResPage<ResOperationLog>>(`/operations`, info);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deleteOperation = (params: { ids: number[] }) => {
|
export const deleteOperation = (params: { ids: number[] }) => {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ import http from '@/api';
|
||||||
import { ResPage } from '../interface';
|
import { ResPage } from '../interface';
|
||||||
import { User } from '../interface/user';
|
import { User } from '../interface/user';
|
||||||
|
|
||||||
export const getUserList = (currentPage: number, pageSize: number) => {
|
export const getUserList = (params: User.ReqGetUserParams) => {
|
||||||
return http.get<ResPage<User.User>>(`/users?page=${currentPage}&pageSize=${pageSize}`);
|
return http.post<ResPage<User.User>>(`/users/search`, params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addUser = (params: User.User) => {
|
export const addUser = (params: User.User) => {
|
||||||
|
|
@ -15,7 +15,7 @@ export const getUserById = (id: number) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const editUser = (params: User.User) => {
|
export const editUser = (params: User.User) => {
|
||||||
return http.post(`/users/` + params.id, params);
|
return http.put(`/users/` + params.id, params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deleteUser = (params: { ids: number[] }) => {
|
export const deleteUser = (params: { ids: number[] }) => {
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ export default {
|
||||||
menu: {
|
menu: {
|
||||||
home: 'Dashboard',
|
home: 'Dashboard',
|
||||||
demo: 'Demo',
|
demo: 'Demo',
|
||||||
|
terminal: 'Terminal',
|
||||||
operations: 'Operation logs',
|
operations: 'Operation logs',
|
||||||
},
|
},
|
||||||
home: {
|
home: {
|
||||||
|
|
@ -83,6 +84,7 @@ export default {
|
||||||
login: ' login',
|
login: ' login',
|
||||||
logout: ' logout',
|
logout: ' logout',
|
||||||
post: ' create',
|
post: ' create',
|
||||||
|
put: ' update',
|
||||||
update: ' update',
|
update: ' update',
|
||||||
delete: ' delete',
|
delete: ' delete',
|
||||||
del: 'delete',
|
del: 'delete',
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ export default {
|
||||||
menu: {
|
menu: {
|
||||||
home: '概览',
|
home: '概览',
|
||||||
demo: '样例',
|
demo: '样例',
|
||||||
|
terminal: '终端管理',
|
||||||
operations: '操作记录',
|
operations: '操作记录',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -82,6 +83,7 @@ export default {
|
||||||
users: '用户',
|
users: '用户',
|
||||||
auth: '用户',
|
auth: '用户',
|
||||||
post: '创建',
|
post: '创建',
|
||||||
|
put: '更新',
|
||||||
update: '更新',
|
update: '更新',
|
||||||
delete: '删除',
|
delete: '删除',
|
||||||
login: '登录',
|
login: '登录',
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
:header="header"
|
:header="header"
|
||||||
v-if="showBack"
|
v-if="showBack"
|
||||||
></back-button>
|
></back-button>
|
||||||
<!-- {{ header }} -->
|
{{ header }}
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-container__toolbar" v-if="slots.toolbar">
|
<div class="content-container__toolbar" v-if="slots.toolbar">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Layout } from '@/routers/constant';
|
import { Layout } from '@/routers/constant';
|
||||||
|
|
||||||
const operationRouter = {
|
const operationRouter = {
|
||||||
sort: 2,
|
sort: 3,
|
||||||
path: '/operations',
|
path: '/operations',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/operation',
|
redirect: '/operation',
|
||||||
|
|
|
||||||
26
frontend/src/routers/modules/terminal.ts
Normal file
26
frontend/src/routers/modules/terminal.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { Layout } from '@/routers/constant';
|
||||||
|
|
||||||
|
const terminalRouter = {
|
||||||
|
sort: 2,
|
||||||
|
path: '/terminals',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/terminal',
|
||||||
|
meta: {
|
||||||
|
title: 'menu.terminal',
|
||||||
|
icon: 'monitor',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/terminal',
|
||||||
|
name: 'Terminal',
|
||||||
|
component: () => import('@/views/terminal/index.vue'),
|
||||||
|
meta: {
|
||||||
|
keepAlive: true,
|
||||||
|
requiresAuth: true,
|
||||||
|
key: 'Terminal',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default terminalRouter;
|
||||||
|
|
@ -41,10 +41,14 @@ const router = useRouter();
|
||||||
const data = ref();
|
const data = ref();
|
||||||
const selects = ref<any>([]);
|
const selects = ref<any>([]);
|
||||||
const paginationConfig = reactive({
|
const paginationConfig = reactive({
|
||||||
currentPage: 1,
|
page: 1,
|
||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
total: 0,
|
total: 0,
|
||||||
});
|
});
|
||||||
|
const userSearch = reactive({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
});
|
||||||
|
|
||||||
const openOperate = (row: User.User | null) => {
|
const openOperate = (row: User.User | null) => {
|
||||||
let params: { [key: string]: any } = {
|
let params: { [key: string]: any } = {
|
||||||
|
|
@ -84,8 +88,9 @@ const buttons = [
|
||||||
];
|
];
|
||||||
|
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
const { currentPage, pageSize } = paginationConfig;
|
userSearch.page = paginationConfig.page;
|
||||||
const res = await getUserList(currentPage, pageSize);
|
userSearch.pageSize = paginationConfig.pageSize;
|
||||||
|
const res = await getUserList(userSearch);
|
||||||
data.value = res.data.items;
|
data.value = res.data.items;
|
||||||
paginationConfig.total = res.data.total;
|
paginationConfig.total = res.data.total;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,11 @@ const paginationConfig = reactive({
|
||||||
total: 0,
|
total: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const logSearch = reactive({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
});
|
||||||
|
|
||||||
const selects = ref<any>([]);
|
const selects = ref<any>([]);
|
||||||
const batchDelete = async (row: ResOperationLog | null) => {
|
const batchDelete = async (row: ResOperationLog | null) => {
|
||||||
let ids: Array<number> = [];
|
let ids: Array<number> = [];
|
||||||
|
|
@ -95,7 +100,6 @@ const batchDelete = async (row: ResOperationLog | null) => {
|
||||||
} else {
|
} else {
|
||||||
ids.push(row.id);
|
ids.push(row.id);
|
||||||
}
|
}
|
||||||
console.log(ids);
|
|
||||||
await useDeleteData(deleteOperation, { ids: ids }, 'commons.msg.delete');
|
await useDeleteData(deleteOperation, { ids: ids }, 'commons.msg.delete');
|
||||||
search();
|
search();
|
||||||
};
|
};
|
||||||
|
|
@ -109,20 +113,35 @@ const buttons = [
|
||||||
];
|
];
|
||||||
|
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
const { currentPage, pageSize } = paginationConfig;
|
logSearch.page = paginationConfig.currentPage;
|
||||||
const res = await getOperationList(currentPage, pageSize);
|
logSearch.pageSize = paginationConfig.pageSize;
|
||||||
|
const res = await getOperationList(logSearch);
|
||||||
data.value = res.data.items;
|
data.value = res.data.items;
|
||||||
paginationConfig.total = res.data.total;
|
paginationConfig.total = res.data.total;
|
||||||
};
|
};
|
||||||
|
|
||||||
const fmtOperation = (row: ResOperationLog) => {
|
const fmtOperation = (row: ResOperationLog) => {
|
||||||
if (row.source == '' && row.action == '') {
|
if (row.method.toLocaleLowerCase() !== 'put') {
|
||||||
|
if (row.source == '' && row.action == '') {
|
||||||
|
return (
|
||||||
|
i18n.global.t('operations.detail.' + row.group.toLocaleLowerCase()) +
|
||||||
|
i18n.global.t('operations.detail.' + row.method.toLocaleLowerCase())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (row.action == '') {
|
||||||
|
return (
|
||||||
|
i18n.global.t('operations.detail.' + row.group.toLocaleLowerCase()) +
|
||||||
|
i18n.global.t('operations.detail.' + row.source.toLocaleLowerCase())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (row.action == '') {
|
||||||
return (
|
return (
|
||||||
i18n.global.t('operations.detail.' + row.group.toLocaleLowerCase()) +
|
i18n.global.t('operations.detail.' + row.group.toLocaleLowerCase()) +
|
||||||
i18n.global.t('operations.detail.' + row.method.toLocaleLowerCase())
|
i18n.global.t('operations.detail.' + row.method.toLocaleLowerCase())
|
||||||
);
|
);
|
||||||
}
|
} else {
|
||||||
if (row.action == '') {
|
|
||||||
return (
|
return (
|
||||||
i18n.global.t('operations.detail.' + row.group.toLocaleLowerCase()) +
|
i18n.global.t('operations.detail.' + row.group.toLocaleLowerCase()) +
|
||||||
i18n.global.t('operations.detail.' + row.source.toLocaleLowerCase())
|
i18n.global.t('operations.detail.' + row.source.toLocaleLowerCase())
|
||||||
|
|
|
||||||
39
frontend/src/views/terminal/index.vue
Normal file
39
frontend/src/views/terminal/index.vue
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
<template>
|
||||||
|
<LayoutContent :header="$t('menu.terminal')">
|
||||||
|
<div>
|
||||||
|
<el-tabs v-model="terminalValue">
|
||||||
|
<el-tab-pane :key="item.name" v-for="item in terminalTabs" :label="item.title" :name="item.name">
|
||||||
|
<iframe id="iframeTerminal" name="iframeTerminal" width="100%" frameborder="0" :src="item.src" />
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
</LayoutContent>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref, nextTick } from 'vue';
|
||||||
|
import LayoutContent from '@/layout/layout-content.vue';
|
||||||
|
|
||||||
|
const terminalValue = ref();
|
||||||
|
const terminalTabs = ref([]) as any;
|
||||||
|
|
||||||
|
function changeFrameHeight() {
|
||||||
|
let ifm = document.getElementById('iframeTerminal') as HTMLInputElement | null;
|
||||||
|
if (ifm) {
|
||||||
|
ifm.style.height = document.documentElement.clientHeight - 280 + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onresize = function () {
|
||||||
|
changeFrameHeight();
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
terminalTabs.value.push({ name: '本地服务器', title: '本地服务器', src: 'http://localhost:8080' });
|
||||||
|
terminalValue.value = '本地服务器';
|
||||||
|
nextTick(() => {
|
||||||
|
changeFrameHeight();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
Loading…
Add table
Reference in a new issue