✨ 兼容移动端UI
This commit is contained in:
parent
d8f0938a11
commit
6b5f882808
@ -1,3 +1,12 @@
|
||||
## [2.2.8](https://github.com/chaos-zhu/easynode/releases) (2024-10-20)
|
||||
|
||||
### Features
|
||||
|
||||
* 兼容移动端UI
|
||||
* 调整终端功能菜单
|
||||
* 修复终端选中文本无法复制的bug
|
||||
* 修复无法展示服务端ping客户端延迟ms的bug
|
||||
|
||||
## [2.2.7](https://github.com/chaos-zhu/easynode/releases) (2024-10-17)
|
||||
|
||||
### Features
|
||||
|
@ -258,7 +258,7 @@ module.exports = (httpServer) => {
|
||||
return sftpClient.list('/')
|
||||
})
|
||||
.then((rootLs) => {
|
||||
// 普通文件-、目录文件d、链接文件l
|
||||
// 普通文件-、目录文件d、链接文件l
|
||||
socket.emit('root_ls', rootLs) // 先返回根目录
|
||||
listenInput(sftpClient, socket) // 监听前端请求
|
||||
})
|
||||
|
@ -1,8 +1,11 @@
|
||||
<html lang="zh">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0,user-scalable=yes">
|
||||
<meta name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0">
|
||||
<!-- <meta name="viewport" content="width=device-width, initial-scale=0,user-scalable=yes"> -->
|
||||
<title>EasyNode</title>
|
||||
<script src="//at.alicdn.com/t/c/font_3309550_x7zmcgwaxf.js"></script>
|
||||
</head>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "web",
|
||||
"version": "2.2.7",
|
||||
"version": "2.2.8",
|
||||
"description": "easynode-web",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@ -45,6 +45,7 @@
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
||||
"code-inspector-plugin": "^0.17.2",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-plugin-vue": "^9.27.0",
|
||||
"sass": "^1.77.7",
|
||||
|
@ -1,4 +1,7 @@
|
||||
// 滚动条
|
||||
html {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
div,
|
||||
|
84
web/src/assets/scss/mobile.scss
Normal file
84
web/src/assets/scss/mobile.scss
Normal file
@ -0,0 +1,84 @@
|
||||
.mobile_menu_btn {
|
||||
margin-right: auto;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.mobile_menu_drawer {
|
||||
width: auto !important;
|
||||
.mobile_logo_wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 15px;
|
||||
img {
|
||||
width: 30px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 14px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
}
|
||||
.el-drawer__body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media screen and (min-width: 969px) {
|
||||
[class^="mobile_"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 968px) {
|
||||
.view_container {
|
||||
.aside_container {
|
||||
display: none;
|
||||
}
|
||||
.top_bar_container {
|
||||
width: 100%;
|
||||
.bar_wrap {
|
||||
h2 {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.terminal_container {
|
||||
.terminal_link_tips {
|
||||
width: 100%;
|
||||
}
|
||||
.terminal_wrap {
|
||||
.terminal_and_sftp_wrap {
|
||||
flex: auto;
|
||||
.sftp_tab_container {
|
||||
section {
|
||||
.left {
|
||||
min-width: 150px;
|
||||
max-width: 150px;
|
||||
}
|
||||
.right {
|
||||
.filter_input {
|
||||
width: auto;
|
||||
min-width: auto;
|
||||
margin: 0 5px;
|
||||
}
|
||||
.path {
|
||||
display: inline-block;
|
||||
padding-right: 15px;
|
||||
}
|
||||
.path_input {
|
||||
width: auto;
|
||||
min-width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-dialog {
|
||||
--el-dialog-width: 94%!important;
|
||||
}
|
||||
}
|
@ -6,25 +6,7 @@
|
||||
<h1 v-show="!menuCollapse">EasyNode</h1>
|
||||
</Transition>
|
||||
</div>
|
||||
<el-menu
|
||||
:default-active="defaultActiveMenu"
|
||||
:collapse="menuCollapse"
|
||||
class="menu"
|
||||
:collapse-transition="true"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<el-menu-item v-for="(item, index) in menuList" :key="index" :index="item.index">
|
||||
<el-icon>
|
||||
<component :is="item.icon" />
|
||||
</el-icon>
|
||||
<template #title>
|
||||
<span>{{ item.name }}</span>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
<!-- <div class="logout_wrap">
|
||||
<el-button type="info" link @click="handleLogout">退出登录</el-button>
|
||||
</div> -->
|
||||
<MenuList />
|
||||
<div class="collapse" @click="handleCollapse">
|
||||
<el-icon v-if="menuCollapse"><Expand /></el-icon>
|
||||
<el-icon v-else><Fold /></el-icon>
|
||||
@ -33,82 +15,17 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, markRaw, getCurrentInstance, computed, watchEffect } from 'vue'
|
||||
import { getCurrentInstance, computed } from 'vue'
|
||||
import {
|
||||
Menu as IconMenu,
|
||||
Key,
|
||||
Setting,
|
||||
ScaleToOriginal,
|
||||
ArrowRight,
|
||||
Pointer,
|
||||
FolderOpened,
|
||||
Expand,
|
||||
Fold
|
||||
} from '@element-plus/icons-vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import MenuList from './menuList.vue'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const { proxy: { $router, $store } } = getCurrentInstance()
|
||||
|
||||
let menuList = reactive([
|
||||
{
|
||||
name: '实例配置',
|
||||
icon: markRaw(IconMenu),
|
||||
index: '/server'
|
||||
},
|
||||
{
|
||||
name: '连接终端',
|
||||
icon: markRaw(ScaleToOriginal),
|
||||
index: '/terminal'
|
||||
},
|
||||
{
|
||||
name: '凭据管理',
|
||||
icon: markRaw(Key),
|
||||
index: '/credentials'
|
||||
},
|
||||
{
|
||||
name: '分组管理',
|
||||
icon: markRaw(FolderOpened),
|
||||
index: '/group'
|
||||
},
|
||||
{
|
||||
name: '脚本库',
|
||||
icon: markRaw(ArrowRight),
|
||||
index: '/scripts'
|
||||
},
|
||||
{
|
||||
name: '批量指令',
|
||||
icon: markRaw(Pointer),
|
||||
index: '/onekey'
|
||||
},
|
||||
{
|
||||
name: '系统设置',
|
||||
icon: markRaw(Setting),
|
||||
index: '/setting'
|
||||
},
|
||||
])
|
||||
const { proxy: { $store } } = getCurrentInstance()
|
||||
|
||||
let menuCollapse = computed(() => $store.menuCollapse)
|
||||
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
const regex = /^\/([^\/]+)/
|
||||
let defaultActiveMenu = computed(() => {
|
||||
const match = route.path.match(regex)
|
||||
return match[0]
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
let idx = route.path.match(regex)[0]
|
||||
let targetRoute = menuList.find(item => item.index === idx)
|
||||
$store.setTitle(targetRoute?.name || '')
|
||||
})
|
||||
|
||||
const handleSelect = (path) => {
|
||||
// console.log(path)
|
||||
$router.push(path)
|
||||
}
|
||||
|
||||
const handleCollapse = () => {
|
||||
$store.setMenuCollapse(!menuCollapse.value)
|
||||
}
|
||||
@ -136,7 +53,8 @@ const handleCollapse = () => {
|
||||
position: absolute;
|
||||
left: 52px;
|
||||
font-size: 14px;
|
||||
// color: #1890ff;
|
||||
color: var(--el-menu-active-color);
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
.collapse {
|
||||
|
@ -23,7 +23,7 @@
|
||||
<template #footer>
|
||||
<footer>
|
||||
<div class="btns">
|
||||
<el-button type="primary" @click="handleSave">执行</el-button>
|
||||
<el-button type="primary" @click="handleSave">发送到终端</el-button>
|
||||
<el-button type="info" @click="visible = false">关闭</el-button>
|
||||
</div>
|
||||
</footer>
|
||||
|
96
web/src/components/menuList.vue
Normal file
96
web/src/components/menuList.vue
Normal file
@ -0,0 +1,96 @@
|
||||
<template>
|
||||
<el-menu
|
||||
:default-active="defaultActiveMenu"
|
||||
:collapse="menuCollapse"
|
||||
class="menu"
|
||||
:collapse-transition="true"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<el-menu-item v-for="(item, index) in list" :key="index" :index="item.index">
|
||||
<el-icon>
|
||||
<component :is="item.icon" />
|
||||
</el-icon>
|
||||
<template #title>
|
||||
<span>{{ item.name }}</span>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, markRaw, getCurrentInstance, computed, watchEffect, defineEmits } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import {
|
||||
Menu as IconMenu,
|
||||
Key,
|
||||
Setting,
|
||||
ScaleToOriginal,
|
||||
ArrowRight,
|
||||
Pointer,
|
||||
FolderOpened
|
||||
} from '@element-plus/icons-vue'
|
||||
const { proxy: { $router, $store } } = getCurrentInstance()
|
||||
|
||||
const emit = defineEmits(['select',])
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const list = reactive([
|
||||
{
|
||||
name: '实例配置',
|
||||
icon: markRaw(IconMenu),
|
||||
index: '/server'
|
||||
},
|
||||
{
|
||||
name: '连接终端',
|
||||
icon: markRaw(ScaleToOriginal),
|
||||
index: '/terminal'
|
||||
},
|
||||
{
|
||||
name: '凭据管理',
|
||||
icon: markRaw(Key),
|
||||
index: '/credentials'
|
||||
},
|
||||
{
|
||||
name: '分组管理',
|
||||
icon: markRaw(FolderOpened),
|
||||
index: '/group'
|
||||
},
|
||||
{
|
||||
name: '脚本库',
|
||||
icon: markRaw(ArrowRight),
|
||||
index: '/scripts'
|
||||
},
|
||||
{
|
||||
name: '批量指令',
|
||||
icon: markRaw(Pointer),
|
||||
index: '/onekey'
|
||||
},
|
||||
{
|
||||
name: '系统设置',
|
||||
icon: markRaw(Setting),
|
||||
index: '/setting'
|
||||
},
|
||||
])
|
||||
|
||||
const menuCollapse = computed(() => $store.menuCollapse)
|
||||
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
const regex = /^\/([^\/]+)/
|
||||
const defaultActiveMenu = computed(() => {
|
||||
const match = route.path.match(regex)
|
||||
return match[0]
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
const idx = route.path.match(regex)[0]
|
||||
const targetRoute = list.find(item => item.index === idx)
|
||||
$store.setTitle(targetRoute?.name || '')
|
||||
})
|
||||
|
||||
const handleSelect = (path) => {
|
||||
// console.log(path)
|
||||
$router.push(path)
|
||||
emit('select', path)
|
||||
}
|
||||
</script>
|
@ -1,8 +1,10 @@
|
||||
<template>
|
||||
<div class="top_bar_container">
|
||||
<div class="bar_wrap">
|
||||
<div class="mobile_menu_btn">
|
||||
<el-icon @click="handleCollapse"><Fold /></el-icon>
|
||||
</div>
|
||||
<h2>{{ title }}</h2>
|
||||
<!-- <el-icon><UserFilled /></el-icon> -->
|
||||
<el-switch
|
||||
v-model="isDark"
|
||||
inline-prompt
|
||||
@ -33,6 +35,7 @@
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
title="关于"
|
||||
top="10vh"
|
||||
width="30%"
|
||||
:append-to-body="false"
|
||||
>
|
||||
@ -55,31 +58,50 @@
|
||||
</p>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-drawer
|
||||
v-model="menuCollapse"
|
||||
:with-header="false"
|
||||
direction="ltr"
|
||||
class="mobile_menu_drawer"
|
||||
>
|
||||
<div class="mobile_logo_wrap">
|
||||
<img src="@/assets/logo.png" alt="logo">
|
||||
<h1>EasyNode</h1>
|
||||
</div>
|
||||
<MenuList @select="() => menuCollapse = false" />
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, getCurrentInstance, computed } from 'vue'
|
||||
import { User, Sunny, Moon } from '@element-plus/icons-vue'
|
||||
import { User, Sunny, Moon, Fold } from '@element-plus/icons-vue'
|
||||
import packageJson from '../../package.json'
|
||||
import MenuList from './menuList.vue'
|
||||
|
||||
const { proxy: { $router, $store, $message } } = getCurrentInstance()
|
||||
|
||||
let visible = ref(false)
|
||||
let checkVersionErr = ref(false)
|
||||
let currentVersion = ref(`v${ packageJson.version }`)
|
||||
let latestVersion = ref(null)
|
||||
const visible = ref(false)
|
||||
const checkVersionErr = ref(false)
|
||||
const currentVersion = ref(`v${ packageJson.version }`)
|
||||
const latestVersion = ref(null)
|
||||
const menuCollapse = ref(false)
|
||||
|
||||
let isNew = computed(() => latestVersion.value && latestVersion.value !== currentVersion.value)
|
||||
let user = computed(() => $store.user)
|
||||
let title = computed(() => $store.title)
|
||||
let isDark = computed({
|
||||
const isNew = computed(() => latestVersion.value && latestVersion.value !== currentVersion.value)
|
||||
const user = computed(() => $store.user)
|
||||
const title = computed(() => $store.title)
|
||||
const isDark = computed({
|
||||
get: () => $store.isDark,
|
||||
set: (isDark) => {
|
||||
$store.setTheme(isDark)
|
||||
}
|
||||
})
|
||||
|
||||
const handleCollapse = () => {
|
||||
menuCollapse.value = !menuCollapse.value
|
||||
}
|
||||
|
||||
const handleLogout = () => {
|
||||
$store.clearJwtToken()
|
||||
$message({ type: 'success', message: '已安全退出', center: true })
|
||||
|
18
web/src/composables/useMobileWidth.js
Normal file
18
web/src/composables/useMobileWidth.js
Normal file
@ -0,0 +1,18 @@
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
|
||||
export default function useMobileWidth(maxWidth = 968) {
|
||||
const isMobileScreen = ref(window.innerWidth < maxWidth)
|
||||
function updateScreenWidth() {
|
||||
isMobileScreen.value = window.innerWidth < maxWidth
|
||||
}
|
||||
onMounted(() => {
|
||||
console.log('window.innerWidth: ', window.innerWidth)
|
||||
console.log('window.innerWidth: ', window.innerWidth)
|
||||
window.addEventListener('resize', updateScreenWidth)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', updateScreenWidth)
|
||||
})
|
||||
return { isMobileScreen }
|
||||
}
|
@ -10,6 +10,7 @@ import api from './api'
|
||||
import App from './app.vue'
|
||||
import './assets/scss/reset.scss'
|
||||
import './assets/scss/global.scss'
|
||||
import './assets/scss/mobile.scss'
|
||||
|
||||
const app = createApp(App)
|
||||
elementPlugins(app)
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import { reactive } from 'vue'
|
||||
import JSRsaEncrypt from 'jsencrypt'
|
||||
import CryptoJS from 'crypto-js'
|
||||
@ -93,7 +92,20 @@ export const sortDirTree = (tree = []) => {
|
||||
}
|
||||
sort(dirsAndlinks)
|
||||
sort(others)
|
||||
return [].concat(dirsAndlinks, others)
|
||||
let res = [].concat(dirsAndlinks, others)
|
||||
let homeDirIndex = res.findIndex(item => item.name === 'home')
|
||||
if (homeDirIndex !== -1) {
|
||||
let homeDir = res[homeDirIndex]
|
||||
res.splice(homeDirIndex, 1)
|
||||
res.unshift(homeDir)
|
||||
}
|
||||
let rootDirIndex = res.findIndex(item => item.name === 'root')
|
||||
if (rootDirIndex !== -1) {
|
||||
let rootDir = res[rootDirIndex]
|
||||
res.splice(rootDirIndex, 1)
|
||||
res.unshift(rootDir)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
export const downloadFile = ({ buffer, name }) => {
|
||||
@ -132,3 +144,8 @@ export const exportFile = (data, filename, mimeType = 'application/json') =>{
|
||||
export const isHttps = () => {
|
||||
return window.location.protocol === 'https:'
|
||||
}
|
||||
|
||||
export const isMobile = () => {
|
||||
let userAgent = navigator.userAgent || navigator.vendor || window.opera
|
||||
return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent)
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
{{ row.authType === 'privateKey' ? '密钥' : '密码' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<el-table-column width="160px" label="操作">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" @click="handleChange(row)">修改</el-button>
|
||||
<el-button v-show="row.id !== 'default'" type="danger" @click="removeSSH(row)">删除</el-button>
|
||||
|
@ -4,9 +4,9 @@
|
||||
<el-button type="primary" @click="addGroup">添加分组</el-button>
|
||||
</div>
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column prop="index" label="序号" width="100px" />
|
||||
<el-table-column prop="index" label="序号" />
|
||||
<el-table-column prop="name" label="分组名称" />
|
||||
<el-table-column label="关联实例数量">
|
||||
<el-table-column label="关联实例数量" min-width="115px">
|
||||
<template #default="{ row }">
|
||||
<el-popover
|
||||
v-if="row.hosts.list.length !== 0"
|
||||
@ -28,7 +28,7 @@
|
||||
<u v-else class="host_count">0</u>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<el-table-column label="操作" fixed="right" width="160px">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" @click="handleChange(row)">修改</el-button>
|
||||
<el-button v-show="row.id !== 'default'" type="danger" @click="deleteGroup(row)">删除</el-button>
|
||||
|
@ -32,26 +32,41 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="实例">
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="实例"
|
||||
show-overflow-tooltip
|
||||
min-width="120px"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<span style="letter-spacing: 2px;"> {{ row.name }} </span> -
|
||||
<span style="letter-spacing: 2px;"> {{ row.host }} </span> :
|
||||
<span style="letter-spacing: 2px;"> {{ row.port }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="command" label="指令" show-overflow-tooltip>
|
||||
<el-table-column
|
||||
prop="command"
|
||||
label="指令"
|
||||
show-overflow-tooltip
|
||||
min-width="150px"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<span> {{ row.command }} </span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="执行结果" show-overflow-tooltip>
|
||||
<el-table-column
|
||||
prop="status"
|
||||
label="执行结果"
|
||||
show-overflow-tooltip
|
||||
min-width="100px"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :color="getStatusType(row.status)">
|
||||
<span style="color: rgb(54, 52, 52);">{{ row.status }}</span>
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<el-table-column label="操作" fixed="right" width="90px">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
v-if="!row.pending"
|
||||
|
@ -8,7 +8,7 @@
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column prop="description" label="描述" />
|
||||
<el-table-column prop="command" label="指令内容" show-overflow-tooltip />
|
||||
<el-table-column label="操作">
|
||||
<el-table-column label="操作" fixed="right" width="160px">
|
||||
<template #default="{ row }">
|
||||
<template v-if="row.index !== '--'">
|
||||
<el-button type="primary" @click="handleChange(row)">修改</el-button>
|
||||
|
@ -41,7 +41,7 @@
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div v-else class="no_client_data">
|
||||
监控客户端服务未连接,无法获取实例监控数据。<span class="link" @click="handleOnekey(row)">去安装</span>
|
||||
客户端监控服务未安装或连接失败,无法获取实例监控数据。<span class="link" @click="handleOnekey(row)">去安装</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -79,7 +79,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column property="isConfig" label="登录配置" /> -->
|
||||
<el-table-column label="操作" width="300px">
|
||||
<el-table-column label="操作" fixed="right" width="260px">
|
||||
<template #default="{ row }">
|
||||
<el-tooltip
|
||||
:disabled="row.isConfig"
|
||||
|
@ -197,7 +197,7 @@
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-divider content-position="center">FEATURE</el-divider>
|
||||
<!-- <el-divider content-position="center">FEATURE</el-divider> -->
|
||||
<!-- <el-button
|
||||
:type="sftpStatus ? 'primary' : 'success'"
|
||||
style="display: block;width: 80%;margin: 30px auto;"
|
||||
@ -205,13 +205,13 @@
|
||||
>
|
||||
{{ sftpStatus ? '关闭SFTP' : '连接SFTP' }}
|
||||
</el-button> -->
|
||||
<el-button
|
||||
<!-- <el-button
|
||||
:type="inputCommandStyle ? 'primary' : 'success'"
|
||||
style="display: block;width: 80%;margin: 15px auto;"
|
||||
@click="clickInputCommand"
|
||||
>
|
||||
长指令输入
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
@ -238,7 +238,7 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:inputCommandStyle', 'connect-sftp', 'click-input-command',])
|
||||
// const emit = defineEmits(['update:inputCommandStyle', 'click-input-command',])
|
||||
|
||||
const socket = ref(null)
|
||||
const pingTimer = ref(null)
|
||||
@ -275,12 +275,12 @@ const input = computed(() => {
|
||||
if (inputMb >= 1) return `${ inputMb.toFixed(2) } MB/s`
|
||||
return `${ (inputMb * 1024).toFixed(1) } KB/s`
|
||||
})
|
||||
const inputCommandStyle = computed({
|
||||
get: () => props.showInputCommand,
|
||||
set: (val) => {
|
||||
emit('update:inputCommandStyle', val)
|
||||
}
|
||||
})
|
||||
// const inputCommandStyle = computed({
|
||||
// get: () => props.showInputCommand,
|
||||
// set: (val) => {
|
||||
// emit('update:inputCommandStyle', val)
|
||||
// }
|
||||
// })
|
||||
|
||||
const pingMs = computed(() => {
|
||||
let curPingData = props.pingData[host.value] || {}
|
||||
@ -288,16 +288,11 @@ const pingMs = computed(() => {
|
||||
return Number(curPingData?.time).toFixed(0)
|
||||
})
|
||||
|
||||
// const handleSftp = () => {
|
||||
// sftpStatus.value = !sftpStatus.value
|
||||
// emit('connect-sftp', sftpStatus.value)
|
||||
// const clickInputCommand = () => {
|
||||
// inputCommandStyle.value = true
|
||||
// emit('click-input-command')
|
||||
// }
|
||||
|
||||
const clickInputCommand = () => {
|
||||
inputCommandStyle.value = true
|
||||
emit('click-input-command')
|
||||
}
|
||||
|
||||
const handleCopy = async () => {
|
||||
await navigator.clipboard.writeText(host.value)
|
||||
$message.success({ message: 'success', center: true })
|
||||
|
@ -92,7 +92,7 @@
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<div class="filter-input">
|
||||
<div class="filter_input">
|
||||
<el-input
|
||||
v-model="filterKey"
|
||||
size="small"
|
||||
@ -104,7 +104,7 @@
|
||||
v-if="showPathInput"
|
||||
ref="pathInputRef"
|
||||
v-model="pathInput"
|
||||
class="path-input"
|
||||
class="path_input"
|
||||
size="small"
|
||||
clearable
|
||||
@blur="showPathInput = false"
|
||||
@ -159,7 +159,7 @@
|
||||
import { ref, computed, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import socketIo from 'socket.io-client'
|
||||
import CodeEdit from '@/components/code-edit/index.vue'
|
||||
import { EventBus, isDir, isFile, sortDirTree, downloadFile } from '@/utils'
|
||||
import { EventBus, isDir, isFile, sortDirTree, downloadFile, isMobile } from '@/utils'
|
||||
import dirIcon from '@/assets/image/system/dir.png'
|
||||
import linkIcon from '@/assets/image/system/link.png'
|
||||
import fileIcon from '@/assets/image/system/file.png'
|
||||
@ -408,6 +408,7 @@ const handleClosedCode = () => {
|
||||
}
|
||||
|
||||
const selectFile = (item) => {
|
||||
if (isMobile()) openTarget(item)
|
||||
curTarget.value = item
|
||||
}
|
||||
|
||||
@ -696,12 +697,12 @@ defineExpose({
|
||||
}
|
||||
}
|
||||
}
|
||||
.filter-input {
|
||||
.filter_input {
|
||||
width: 200px;
|
||||
min-width: 200px;
|
||||
margin: 0 20px 0 10px;
|
||||
}
|
||||
.path-input {
|
||||
.path_input {
|
||||
width: 450px;
|
||||
min-width: 450px;
|
||||
}
|
||||
@ -730,7 +731,7 @@ defineExpose({
|
||||
}
|
||||
li {
|
||||
font-size: 14px;
|
||||
padding: 5px 3px;
|
||||
padding: 5px 0 5px 3px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// cursor: pointer;
|
||||
@ -749,7 +750,7 @@ defineExpose({
|
||||
}
|
||||
}
|
||||
.left {
|
||||
width: 200px;
|
||||
min-width: 200px;
|
||||
border-right: 1px solid #dcdfe6;
|
||||
.dir-list {
|
||||
li:nth-child(n+2){
|
||||
|
@ -179,7 +179,7 @@ const changeBackground = (url) => {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
li {
|
||||
width: 130px;
|
||||
width: 126px;
|
||||
height: 75px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 3px;
|
||||
|
@ -277,6 +277,7 @@ const onSelectionChange = () => {
|
||||
term.value.onSelectionChange(() => {
|
||||
if (!quickCopy.value) return
|
||||
let str = term.value.getSelection()
|
||||
console.log(str)
|
||||
if (!str) return
|
||||
const text = new Blob([str,], { type: 'text/plain' })
|
||||
const item = new ClipboardItem({
|
||||
|
@ -3,7 +3,7 @@
|
||||
<div class="terminal_top">
|
||||
<div class="left_menu">
|
||||
<el-dropdown trigger="click">
|
||||
<span class="link_text">连接管理<el-icon><arrow-down /></el-icon></span>
|
||||
<span class="link_text">连接<el-icon><arrow-down /></el-icon></span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item class="link_close_all" @click="handleCloseAllTab">
|
||||
@ -47,9 +47,12 @@
|
||||
</template>
|
||||
</el-dropdown> -->
|
||||
<el-dropdown trigger="click">
|
||||
<span class="link_text">首选项<el-icon><arrow-down /></el-icon></span>
|
||||
<span class="link_text">功能项<el-icon><arrow-down /></el-icon></span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="showInputCommand = true">
|
||||
<span>长指令输入</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click="handleFullScreen">
|
||||
<span>启用全屏</span>
|
||||
</el-dropdown-item>
|
||||
@ -61,6 +64,11 @@
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<div class="right_overview">
|
||||
<div v-if="isMobileScreen" class="switch_wrap">
|
||||
<el-button :type="curHost?.monitorData?.connect ? 'success' : 'danger'" text @click="() => showMobileInfoSideDialog = true">
|
||||
状态
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="switch_wrap">
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
@ -98,17 +106,30 @@
|
||||
</el-icon> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="info_box">
|
||||
|
||||
<el-drawer
|
||||
v-if="isMobileScreen"
|
||||
v-model="showMobileInfoSideDialog"
|
||||
:with-header="false"
|
||||
direction="ltr"
|
||||
class="mobile_menu_drawer"
|
||||
>
|
||||
<InfoSide
|
||||
ref="infoSideRef"
|
||||
:host-info="curHost"
|
||||
:visible="visible"
|
||||
:ping-data="pingData"
|
||||
/>
|
||||
</el-drawer>
|
||||
<div v-else class="info_box">
|
||||
<InfoSide
|
||||
ref="infoSideRef"
|
||||
v-model:show-input-command="showInputCommand"
|
||||
:host-info="curHost"
|
||||
:visible="visible"
|
||||
:ping-data="pingData"
|
||||
@click-input-command="clickInputCommand"
|
||||
/>
|
||||
</div>
|
||||
<div class="terminals_sftp_wrap">
|
||||
<div class="terminal_and_sftp_wrap">
|
||||
<el-tabs
|
||||
v-model="activeTabIndex"
|
||||
type="border-card"
|
||||
@ -162,13 +183,14 @@
|
||||
<script setup>
|
||||
import { ref, computed, getCurrentInstance, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
|
||||
import { ArrowDown } from '@element-plus/icons-vue'
|
||||
import useMobileWidth from '@/composables/useMobileWidth'
|
||||
import InputCommand from '@/components/input-command/index.vue'
|
||||
import { terminalStatusList } from '@/utils/enum'
|
||||
import TerminalTab from './terminal-tab.vue'
|
||||
import InfoSide from './info-side.vue'
|
||||
import Sftp from './sftp.vue'
|
||||
import InputCommand from '@/components/input-command/index.vue'
|
||||
import HostForm from '../../server/components/host-form.vue'
|
||||
import TerminalSetting from './terminal-setting.vue'
|
||||
import { terminalStatusList } from '@/utils/enum'
|
||||
|
||||
const { proxy: { $nextTick, $store, $message } } = getCurrentInstance()
|
||||
|
||||
@ -180,7 +202,7 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const emit = defineEmits(['closed', 'close-all-tab', 'removeTab', 'add-host',])
|
||||
|
||||
const { isMobileScreen } = useMobileWidth()
|
||||
const showInputCommand = ref(false)
|
||||
const infoSideRef = ref(null)
|
||||
const pingData = ref({})
|
||||
@ -194,6 +216,7 @@ const isSyncAllSession = ref(false)
|
||||
const hostFormVisible = ref(false)
|
||||
const updateHostData = ref(null)
|
||||
const showSetting = ref(false)
|
||||
const showMobileInfoSideDialog = ref(false)
|
||||
|
||||
const terminalTabs = computed(() => props.terminalTabs)
|
||||
const terminalTabsLen = computed(() => props.terminalTabs.length)
|
||||
@ -227,7 +250,7 @@ const handleUpdateList = async ({ host }) => {
|
||||
|
||||
const handleResizeTerminalSftp = () => {
|
||||
$nextTick(() => {
|
||||
mainHeight.value = document.querySelector('.terminals_sftp_wrap')?.offsetHeight - 45 // 45 is tab-header height+15
|
||||
mainHeight.value = document.querySelector('.terminal_and_sftp_wrap')?.offsetHeight - 45 // 45 is tab-header height+15
|
||||
})
|
||||
}
|
||||
|
||||
@ -311,10 +334,6 @@ watch(showSftp, () => {
|
||||
// }
|
||||
// }
|
||||
|
||||
const clickInputCommand = () => {
|
||||
showInputCommand.value = true
|
||||
}
|
||||
|
||||
const removeTab = (index) => {
|
||||
emit('removeTab', index)
|
||||
if (index === activeTabIndex.value) {
|
||||
@ -325,7 +344,7 @@ const removeTab = (index) => {
|
||||
}
|
||||
|
||||
const handleFullScreen = () => {
|
||||
document.getElementsByClassName('terminals_sftp_wrap')[0].requestFullscreen()
|
||||
document.getElementsByClassName('terminal_and_sftp_wrap')[0].requestFullscreen()
|
||||
}
|
||||
|
||||
// const registryDbClick = () => {
|
||||
@ -387,7 +406,7 @@ const handleInputCommand = async (command) => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 15px;
|
||||
padding: 0 5px 0 15px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: var(--el-fill-color-light);
|
||||
@ -410,7 +429,7 @@ const handleInputCommand = async (command) => {
|
||||
color: var(--el-text-color-regular);
|
||||
// color: var(--el-color-primary);
|
||||
cursor: pointer;
|
||||
margin-right: 15px;
|
||||
margin-right: 10px;
|
||||
|
||||
.hidden_icon {
|
||||
opacity: 0;
|
||||
@ -448,7 +467,7 @@ const handleInputCommand = async (command) => {
|
||||
border: var(--el-descriptions-table-border);
|
||||
}
|
||||
|
||||
.terminals_sftp_wrap {
|
||||
.terminal_and_sftp_wrap {
|
||||
height: calc(100% - $terminalTopHeight);
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
|
@ -10,7 +10,7 @@
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-show="!isAllConfssh">
|
||||
<el-table-column v-show="!isAllConfssh" fixed="right" width="80px">
|
||||
<template #default="{ row }">
|
||||
<div class="actios_btns">
|
||||
<el-button
|
||||
@ -124,7 +124,7 @@ onActivated(async () => {
|
||||
height: calc(100vh - 60px - 20px);
|
||||
overflow: auto;
|
||||
.terminal_link_tips {
|
||||
width: 50%;
|
||||
width: 735px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { fileURLToPath, URL } from 'url'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
@ -7,6 +6,7 @@ import AutoImport from 'unplugin-auto-import/vite'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||
import viteCompression from 'vite-plugin-compression'
|
||||
import { codeInspectorPlugin } from 'code-inspector-plugin'
|
||||
|
||||
const serviceURI = 'http://localhost:8082/'
|
||||
const serviceApiPrefix = '/api/v1'
|
||||
@ -16,7 +16,7 @@ export default defineConfig({
|
||||
server: {
|
||||
host: '0.0.0.0',
|
||||
port: 18090,
|
||||
strictPort: true,
|
||||
// strictPort: true,
|
||||
cors: true,
|
||||
proxy: {
|
||||
[serviceApiPrefix]: {
|
||||
@ -57,12 +57,19 @@ export default defineConfig({
|
||||
algorithm: 'gzip',
|
||||
deleteOriginFile: false
|
||||
}),
|
||||
codeInspectorPlugin({
|
||||
bundler: 'vite'
|
||||
}),
|
||||
],
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
additionalData: '@use "@/assets/scss/element/index.scss" as *;'
|
||||
}
|
||||
},
|
||||
postcss: {
|
||||
plugins: [
|
||||
]
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
|
128
yarn.lock
128
yarn.lock
@ -206,11 +206,21 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d"
|
||||
integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==
|
||||
|
||||
"@babel/helper-string-parser@^7.25.7":
|
||||
version "7.25.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz#d50e8d37b1176207b4fe9acedec386c565a44a54"
|
||||
integrity sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.24.7":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db"
|
||||
integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.25.7":
|
||||
version "7.25.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz#77b7f60c40b15c97df735b38a66ba1d7c3e93da5"
|
||||
integrity sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==
|
||||
|
||||
"@babel/helper-validator-option@^7.24.8":
|
||||
version "7.24.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d"
|
||||
@ -244,6 +254,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.8.tgz#58a4dbbcad7eb1d48930524a3fd93d93e9084c6f"
|
||||
integrity sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==
|
||||
|
||||
"@babel/parser@^7.25.3":
|
||||
version "7.25.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.8.tgz#f6aaf38e80c36129460c1657c0762db584c9d5e2"
|
||||
integrity sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==
|
||||
dependencies:
|
||||
"@babel/types" "^7.25.8"
|
||||
|
||||
"@babel/plugin-syntax-jsx@^7.23.3":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz#39a1fa4a7e3d3d7f34e2acc6be585b718d30e02d"
|
||||
@ -318,6 +335,15 @@
|
||||
"@babel/helper-validator-identifier" "^7.24.7"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.25.8":
|
||||
version "7.25.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.8.tgz#5cf6037258e8a9bcad533f4979025140cb9993e1"
|
||||
integrity sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.25.7"
|
||||
"@babel/helper-validator-identifier" "^7.25.7"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@codemirror/autocomplete@^6.0.0", "@codemirror/autocomplete@^6.3.2", "@codemirror/autocomplete@^6.7.1":
|
||||
version "6.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.17.0.tgz#24ff5fc37fd91f6439df6f4ff9c8e910cde1b053"
|
||||
@ -1274,6 +1300,17 @@
|
||||
estree-walker "^2.0.2"
|
||||
source-map-js "^1.2.0"
|
||||
|
||||
"@vue/compiler-core@3.5.12":
|
||||
version "3.5.12"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.12.tgz#bd70b7dabd12b0b6f31bc53418ba3da77994c437"
|
||||
integrity sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.25.3"
|
||||
"@vue/shared" "3.5.12"
|
||||
entities "^4.5.0"
|
||||
estree-walker "^2.0.2"
|
||||
source-map-js "^1.2.0"
|
||||
|
||||
"@vue/compiler-dom@3.4.31":
|
||||
version "3.4.31"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.31.tgz#30961ca847f5d6ad18ffa26236c219f61b195f6b"
|
||||
@ -1282,6 +1319,14 @@
|
||||
"@vue/compiler-core" "3.4.31"
|
||||
"@vue/shared" "3.4.31"
|
||||
|
||||
"@vue/compiler-dom@^3.2.47":
|
||||
version "3.5.12"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz#456d631d11102535b7ee6fd954cf2c93158d0354"
|
||||
integrity sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==
|
||||
dependencies:
|
||||
"@vue/compiler-core" "3.5.12"
|
||||
"@vue/shared" "3.5.12"
|
||||
|
||||
"@vue/compiler-sfc@3.4.31", "@vue/compiler-sfc@^3.4.15":
|
||||
version "3.4.31"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.31.tgz#cc6bfccda17df8268cc5440842277f61623c591f"
|
||||
@ -1348,6 +1393,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.31.tgz#af9981f57def2c3f080c14bf219314fc0dc808a0"
|
||||
integrity sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==
|
||||
|
||||
"@vue/shared@3.5.12":
|
||||
version "3.5.12"
|
||||
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.12.tgz#f9e45b7f63f2c3f40d84237b1194b7f67de192e3"
|
||||
integrity sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==
|
||||
|
||||
"@vueuse/core@^9.1.0":
|
||||
version "9.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-9.13.0.tgz#2f69e66d1905c1e4eebc249a01759cf88ea00cf4"
|
||||
@ -1497,6 +1547,13 @@ async-validator@^4.2.5:
|
||||
resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339"
|
||||
integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==
|
||||
|
||||
async@^2.6.4:
|
||||
version "2.6.4"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221"
|
||||
integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==
|
||||
dependencies:
|
||||
lodash "^4.17.14"
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
@ -1666,6 +1723,14 @@ caniuse-lite@^1.0.30001640:
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz#6aa6610eb24067c246d30c57f055a9d0a7f8d05f"
|
||||
integrity sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==
|
||||
|
||||
chalk@4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
|
||||
integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==
|
||||
dependencies:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chalk@^2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
@ -1675,7 +1740,7 @@ chalk@^2.4.2:
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chalk@^4.0.0, chalk@^4.1.2:
|
||||
chalk@^4.0.0, chalk@^4.1.1, chalk@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
@ -1742,6 +1807,26 @@ co@^4.6.0:
|
||||
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
||||
integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==
|
||||
|
||||
code-inspector-core@0.17.2:
|
||||
version "0.17.2"
|
||||
resolved "https://registry.yarnpkg.com/code-inspector-core/-/code-inspector-core-0.17.2.tgz#4109c21a4582fe86fc1658771b715634d0f1b938"
|
||||
integrity sha512-3Y46plc5CYO/+p3wLmi3Rx0H5gmFrktRLkxBBVSSH8vG8UhNDCc5xOv/UxBBB0iwCznDu5/VnzGR0Ru4yi5Z6g==
|
||||
dependencies:
|
||||
"@vue/compiler-dom" "^3.2.47"
|
||||
chalk "^4.1.1"
|
||||
portfinder "^1.0.28"
|
||||
|
||||
code-inspector-plugin@^0.17.2:
|
||||
version "0.17.2"
|
||||
resolved "https://registry.yarnpkg.com/code-inspector-plugin/-/code-inspector-plugin-0.17.2.tgz#b757c6199e4061e354ae201e645e466ad221d16b"
|
||||
integrity sha512-dKir/M3uoJVocw05FfBNO3GOBZnwECzvwsiILs4RsYfwQToUp5plCg3HGS83CYgr/1MxzJyr04hiXFheQbbOpw==
|
||||
dependencies:
|
||||
chalk "4.1.1"
|
||||
code-inspector-core "0.17.2"
|
||||
esbuild-code-inspector-plugin "0.17.2"
|
||||
vite-code-inspector-plugin "0.17.2"
|
||||
webpack-code-inspector-plugin "0.17.2"
|
||||
|
||||
codemirror@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-6.0.1.tgz#62b91142d45904547ee3e0e0e4c1a79158035a29"
|
||||
@ -1956,7 +2041,7 @@ debug@4, debug@^4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^3.1.0:
|
||||
debug@^3.1.0, debug@^3.2.7:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
|
||||
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
|
||||
@ -2175,6 +2260,13 @@ es-errors@^1.3.0:
|
||||
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
||||
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
||||
|
||||
esbuild-code-inspector-plugin@0.17.2:
|
||||
version "0.17.2"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-code-inspector-plugin/-/esbuild-code-inspector-plugin-0.17.2.tgz#b36f7354c4736e22462156eab6e65c6d21076751"
|
||||
integrity sha512-cHk/QYaGSV1E3YgJARC3RUTdnknUSGyfLFtczHXO1FHYBiXKFFD9dr5z43u/ApD5PaE7Eb1f3/eaLlEtD0hdUQ==
|
||||
dependencies:
|
||||
code-inspector-core "0.17.2"
|
||||
|
||||
esbuild@^0.21.3:
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d"
|
||||
@ -3294,7 +3386,7 @@ lodash.once@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
||||
integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
|
||||
|
||||
lodash@^4.17.21:
|
||||
lodash@^4.17.14, lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
@ -3432,6 +3524,13 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
|
||||
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
|
||||
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
|
||||
|
||||
mkdirp@^0.5.6:
|
||||
version "0.5.6"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
|
||||
integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
|
||||
dependencies:
|
||||
minimist "^1.2.6"
|
||||
|
||||
mlly@^1.4.2, mlly@^1.7.1:
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.1.tgz#e0336429bb0731b6a8e887b438cbdae522c8f32f"
|
||||
@ -3766,6 +3865,15 @@ pkg@5.8:
|
||||
resolve "^1.22.0"
|
||||
stream-meter "^1.0.4"
|
||||
|
||||
portfinder@^1.0.28:
|
||||
version "1.0.32"
|
||||
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81"
|
||||
integrity sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==
|
||||
dependencies:
|
||||
async "^2.6.4"
|
||||
debug "^3.2.7"
|
||||
mkdirp "^0.5.6"
|
||||
|
||||
possible-typed-array-names@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f"
|
||||
@ -4588,6 +4696,13 @@ vary@^1, vary@^1.1.2:
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
|
||||
|
||||
vite-code-inspector-plugin@0.17.2:
|
||||
version "0.17.2"
|
||||
resolved "https://registry.yarnpkg.com/vite-code-inspector-plugin/-/vite-code-inspector-plugin-0.17.2.tgz#4d993efed826144fb8fc5df1a754b48498c3a8d0"
|
||||
integrity sha512-EM4BIY1ulqrmgpbMM+RYi+IRp2SiA1VSE4hrnOw9XRFwr11y73n/An+RW3k29GmdHnSESiF8xKVzm919GMkmDw==
|
||||
dependencies:
|
||||
code-inspector-core "0.17.2"
|
||||
|
||||
vite-plugin-compression@^0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz#a75b0d8f48357ebb377b65016da9f20885ef39b6"
|
||||
@ -4664,6 +4779,13 @@ webidl-conversions@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
||||
|
||||
webpack-code-inspector-plugin@0.17.2:
|
||||
version "0.17.2"
|
||||
resolved "https://registry.yarnpkg.com/webpack-code-inspector-plugin/-/webpack-code-inspector-plugin-0.17.2.tgz#bd6038fbbd8a76e723d03716471827e90486a7ee"
|
||||
integrity sha512-NGsApY7c87MrIwFo8JzU70w7xRBnDQYOgLtuNQo2iUKTrFHqcgCwejazZv51ub2HuAoOTx86A6VQ/SONXPntTQ==
|
||||
dependencies:
|
||||
code-inspector-core "0.17.2"
|
||||
|
||||
webpack-sources@^3.2.3:
|
||||
version "3.2.3"
|
||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
|
||||
|
Loading…
x
Reference in New Issue
Block a user