Compare commits

...

5 Commits

Author SHA1 Message Date
李佳航
1b2753a2b7 Merge pull request #44 from dromara/dev
Dev
2024-07-26 11:11:47 +08:00
lijiahang
29b44b8b77 🚨 修复 ts 构建报错. 2024-07-26 10:56:36 +08:00
lijiahang
7290b1364c 🔖 升级版本. 2024-07-26 10:25:38 +08:00
lijiahang
3851ead8bb 💄 修改滚动条样式. 2024-07-26 10:18:39 +08:00
lijiahang
305312cc26 🐛 修复文件上传列表显示错误. 2024-07-25 13:46:48 +08:00
56 changed files with 207 additions and 176 deletions

View File

@@ -53,7 +53,7 @@
* 🔗 演示地址: http://101.43.254.243:1081/ * 🔗 演示地址: http://101.43.254.243:1081/
* 🔏 演示账号: admin/admin * 🔏 演示账号: admin/admin
* ⭐ 体验后可以点一下 `star` 这对我很重要! [github](https://github.com/dromara/orion-visor) [gitee](https://gitee.com/dromara/orion-visor) [gitcode](https://gitcode.com/qq_41011894/orion-visor/overview) * ⭐ 体验后可以点一下 `star` 这对我很重要! [github](https://github.com/dromara/orion-visor) [gitee](https://gitee.com/dromara/orion-visor) [gitcode](https://gitcode.com/dromara/orion-visor/overview)
* 🌈 如果本项目对你有帮助请帮忙推广一下 让更多的人知道此项目! * 🌈 如果本项目对你有帮助请帮忙推广一下 让更多的人知道此项目!
* 🎭 演示环境部分功能不可用, 完整功能请本地部署! * 🎭 演示环境部分功能不可用, 完整功能请本地部署!
* 📛 演示环境请不要随便删除数据! * 📛 演示环境请不要随便删除数据!

View File

@@ -1,7 +1,7 @@
version: '3.3' version: '3.3'
services: services:
orion-visor-service: orion-visor-service:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.1.0 image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.1.1
privileged: true privileged: true
ports: ports:
- 1081:80 - 1081:80
@@ -32,7 +32,7 @@ services:
- orion-visor-mysql - orion-visor-mysql
- orion-visor-redis - orion-visor-redis
orion-visor-mysql: orion-visor-mysql:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.1.0 image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.1.1
privileged: true privileged: true
ports: ports:
- 3307:3306 - 3307:3306
@@ -52,7 +52,7 @@ services:
retries: 10 retries: 10
start_period: 3s start_period: 3s
orion-visor-redis: orion-visor-redis:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.1.0 image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.1.1
privileged: true privileged: true
ports: ports:
- 6380:6379 - 6380:6379

View File

@@ -1,7 +1,7 @@
version: '3.3' version: '3.3'
services: services:
orion-visor-service: orion-visor-service:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.1.0 image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.1.1
privileged: true privileged: true
ports: ports:
- 1081:80 - 1081:80
@@ -32,7 +32,7 @@ services:
- orion-visor-mysql - orion-visor-mysql
- orion-visor-redis - orion-visor-redis
orion-visor-mysql: orion-visor-mysql:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.1.0 image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.1.1
privileged: true privileged: true
ports: ports:
- 3307:3306 - 3307:3306
@@ -52,7 +52,7 @@ services:
retries: 10 retries: 10
start_period: 3s start_period: 3s
orion-visor-redis: orion-visor-redis:
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.1.0 image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.1.1
privileged: true privileged: true
ports: ports:
- 6380:6379 - 6380:6379

View File

@@ -1,5 +1,5 @@
#/bin/bash #/bin/bash
version=2.1.0 version=2.1.1
cp -r ../../sql ./sql cp -r ../../sql ./sql
docker build -t orion-visor-mysql:${version} . docker build -t orion-visor-mysql:${version} .
rm -rf ./sql rm -rf ./sql

View File

@@ -1,5 +1,5 @@
#/bin/bash #/bin/bash
version=2.1.0 version=2.1.1
docker build -t orion-visor-redis:${version} . docker build -t orion-visor-redis:${version} .
docker tag orion-visor-redis:${version} registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:${version} docker tag orion-visor-redis:${version} registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:${version}
docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:${version} docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:${version}

View File

@@ -1,5 +1,5 @@
#/bin/bash #/bin/bash
version=2.1.0 version=2.1.1
mv ../../orion-visor-launch/target/orion-visor-launch.jar ./orion-visor-launch.jar mv ../../orion-visor-launch/target/orion-visor-launch.jar ./orion-visor-launch.jar
mv ../../orion-visor-ui/dist ./dist mv ../../orion-visor-ui/dist ./dist
docker build -t orion-visor-service:${version} . docker build -t orion-visor-service:${version} .

View File

@@ -14,7 +14,7 @@
<url>https://github.com/dromara/orion-visor</url> <url>https://github.com/dromara/orion-visor</url>
<properties> <properties>
<revision>2.1.0</revision> <revision>2.1.1</revision>
<spring.boot.version>2.7.17</spring.boot.version> <spring.boot.version>2.7.17</spring.boot.version>
<spring.boot.admin.version>2.7.15</spring.boot.admin.version> <spring.boot.admin.version>2.7.15</spring.boot.admin.version>
<flatten.maven.plugin.version>1.5.0</flatten.maven.plugin.version> <flatten.maven.plugin.version>1.5.0</flatten.maven.plugin.version>

View File

@@ -14,7 +14,7 @@ public interface AppConst extends OrionConst {
/** /**
* 同 ${orion.version} 迭代时候需要手动更改 * 同 ${orion.version} 迭代时候需要手动更改
*/ */
String VERSION = "2.1.0"; String VERSION = "2.1.1";
/** /**
* 同 ${spring.application.name} * 同 ${spring.application.name}

View File

@@ -94,8 +94,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
#foreach($field in ${table.fields}) #foreach($field in ${table.fields})
#if(${dictMap.containsKey(${field.propertyName})}) #if(${dictMap.containsKey(${field.propertyName})})
<!-- $field.comment --> <!-- $field.comment -->

View File

@@ -1,6 +1,6 @@
VITE_API_BASE_URL= 'http://127.0.0.1:9200/orion-visor/api' VITE_API_BASE_URL= 'http://127.0.0.1:9200/orion-visor/api'
VITE_WS_BASE_URL= 'ws://127.0.0.1:9200/orion-visor/keep-alive' VITE_WS_BASE_URL= 'ws://127.0.0.1:9200/orion-visor/keep-alive'
VITE_APP_VERSION= '2.1.0' VITE_APP_VERSION= '2.1.1'
VITE_APP_RELEASE= 'community' VITE_APP_RELEASE= 'community'
VITE_SFTP_PREVIEW_MB= 2 VITE_SFTP_PREVIEW_MB= 2
VITE_DEMO_MODE= false VITE_DEMO_MODE= false

View File

@@ -1,6 +1,6 @@
VITE_API_BASE_URL= '/orion-visor/api' VITE_API_BASE_URL= '/orion-visor/api'
VITE_WS_BASE_URL= '/orion-visor/keep-alive' VITE_WS_BASE_URL= '/orion-visor/keep-alive'
VITE_APP_VERSION= '2.1.0' VITE_APP_VERSION= '2.1.1'
VITE_APP_RELEASE= 'community' VITE_APP_RELEASE= 'community'
VITE_SFTP_PREVIEW_MB= 2 VITE_SFTP_PREVIEW_MB= 2
VITE_DEMO_MODE= false VITE_DEMO_MODE= false

View File

@@ -1,7 +1,7 @@
{ {
"name": "orion-visor-ui", "name": "orion-visor-ui",
"description": "Orion Visor UI", "description": "Orion Visor UI",
"version": "2.1.0", "version": "2.1.1",
"private": true, "private": true,
"author": "Jiahang Li", "author": "Jiahang Li",
"license": "Apache 2.0", "license": "Apache 2.0",

View File

@@ -50,7 +50,7 @@
</template> </template>
</a-button> </a-button>
</a-tooltip> </a-tooltip>
<a-dropdown trigger="click" @select="s => changeLocale(s as string)"> <a-dropdown trigger="click" @select="(s: string) => changeLocale(s)">
<div ref="localeRef" class="trigger-btn" /> <div ref="localeRef" class="trigger-btn" />
<template #content> <template #content>
<a-doption v-for="item in locales" <a-doption v-for="item in locales"

View File

@@ -12,7 +12,7 @@
:checkable="checkable" :checkable="checkable"
:check-strictly="true" :check-strictly="true"
@drop="moveGroup" @drop="moveGroup"
@select="(s) => emits('onSelected', s)"> @select="(s: any) => emits('onSelected', s)">
<!-- 标题 --> <!-- 标题 -->
<template #title="node"> <template #title="node">
<!-- 修改名称输入框 --> <!-- 修改名称输入框 -->

View File

@@ -119,11 +119,6 @@
align-items: center; align-items: center;
} }
} }
.exec-host-items {
width: 100%;
height: calc(100% - 38px);
}
} }
:deep(.log-header) { :deep(.log-header) {

View File

@@ -13,23 +13,26 @@
</div> </div>
<!-- 主机列表 --> <!-- 主机列表 -->
<div class="exec-host-items"> <div class="exec-host-items">
<div v-for="item in hosts" <a-scrollbar>
:key="item.id" <div v-for="(item, index) in hosts"
class="exec-host-item" :key="item.id"
:class="[ current === item.id ? 'exec-host-item-selected' : '' ]" class="exec-host-item"
@click="emits('selected', item.id)"> :class="[ current === item.id ? 'exec-host-item-selected' : '' ]"
<!-- 主机名称 --> :style="{ marginBottom: index === hosts.length -1 ? 0 : '8px' }"
<div class="exec-host-item-name"> @click="emits('selected', item.id)">
<span class="host-name">{{ item.hostName }}</span> <!-- 主机名称 -->
<span class="host-address">{{ item.hostAddress }}</span> <div class="exec-host-item-name">
<span class="host-name">{{ item.hostName }}</span>
<span class="host-address">{{ item.hostAddress }}</span>
</div>
<!-- 状态 -->
<div class="exec-host-item-status">
<a-tag :color="getDictValue(execHostStatusKey, item.status, 'execColor')">
{{ getDictValue(execHostStatusKey, item.status) }}
</a-tag>
</div>
</div> </div>
<!-- 状态 --> </a-scrollbar>
<div class="exec-host-item-status">
<a-tag :color="getDictValue(execHostStatusKey, item.status, 'execColor')">
{{ getDictValue(execHostStatusKey, item.status) }}
</a-tag>
</div>
</div>
</div> </div>
</div> </div>
</template> </template>
@@ -78,13 +81,19 @@
} }
.exec-host-items { .exec-host-items {
position: absolute; position: relative;
width: calc(100% - 32px); width: 100%;
height: calc(100% - 68px); height: calc(100% - 38px);
overflow: auto;
&::-webkit-scrollbar-track { :deep(.arco-scrollbar) {
display: none; position: absolute;
width: 100%;
height: 100%;
&-container {
height: 100%;
overflow-y: auto;
}
} }
} }
@@ -99,7 +108,6 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 8px;
background: var(--color-fill-2); background: var(--color-fill-2);
transition: all .2s; transition: all .2s;
user-select: none; user-select: none;

View File

@@ -51,8 +51,8 @@
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
:scroll="{ x: '100%', y: '60vh' }" :scroll="{ x: '100%', y: '60vh' }"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 模板名称 --> <!-- 模板名称 -->
<template #name="{ record }"> <template #name="{ record }">
<span class="span-blue">{{ record.name }}</span> <span class="span-blue">{{ record.name }}</span>

View File

@@ -34,8 +34,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 修改前 --> <!-- 修改前 -->
<template #beforeValue="{ record }"> <template #beforeValue="{ record }">
<span class="copy-left" <span class="copy-left"

View File

@@ -13,7 +13,7 @@
<!-- 一级菜单 --> <!-- 一级菜单 -->
<a-menu-item v-if="!menu.children?.length" <a-menu-item v-if="!menu.children?.length"
:key="menu.name" :key="menu.name"
@click="(e) => goto(e, menu)"> @click="(e: any) => goto(e, menu)">
<!-- 图标 --> <!-- 图标 -->
<template #icon> <template #icon>
<component v-if="menu.meta?.icon" :is="menu.meta?.icon" /> <component v-if="menu.meta?.icon" :is="menu.meta?.icon" />
@@ -34,7 +34,7 @@
<!-- 子菜单 --> <!-- 子菜单 -->
<a-menu-item v-for="child in menu.children" <a-menu-item v-for="child in menu.children"
:key="child.name" :key="child.name"
@click="(e) => goto(e, child)"> @click="(e: any) => goto(e, child)">
<!-- 图标 --> <!-- 图标 -->
<template #icon v-if="child.meta?.icon"> <template #icon v-if="child.meta?.icon">
<component :is="child.meta?.icon" /> <component :is="child.meta?.icon" />

View File

@@ -14,8 +14,8 @@
v-model:page-size="(pagination as any).pageSize" v-model:page-size="(pagination as any).pageSize"
v-bind="pagination as any" v-bind="pagination as any"
:auto-adjust="false" :auto-adjust="false"
@change="page => bubblesEmitter(HeaderEmitter.PAGE_CHANGE, page, (pagination as any).pageSize)" @change="(page: number) => bubblesEmitter(HeaderEmitter.PAGE_CHANGE, page, (pagination as any).pageSize)"
@page-size-change="limit => bubblesEmitter(HeaderEmitter.PAGE_CHANGE, 1, limit)" /> @page-size-change="(limit: number) => bubblesEmitter(HeaderEmitter.PAGE_CHANGE, 1, limit)" />
</div> </div>
</div> </div>
<!-- 操作部分 --> <!-- 操作部分 -->
@@ -48,8 +48,8 @@
:placeholder="searchInputPlaceholder as string" :placeholder="searchInputPlaceholder as string"
size="small" size="small"
allow-clear allow-clear
@input="(e) => bubblesEmitter(HeaderEmitter.UPDATE_SEARCH_VALUE, e)" @input="(e: string) => bubblesEmitter(HeaderEmitter.UPDATE_SEARCH_VALUE, e)"
@change="(e) => bubblesEmitter(HeaderEmitter.UPDATE_SEARCH_VALUE, e)" @change="(e: string) => bubblesEmitter(HeaderEmitter.UPDATE_SEARCH_VALUE, e)"
@keyup.enter="bubblesEmitter(HeaderEmitter.SEARCH)" /> @keyup.enter="bubblesEmitter(HeaderEmitter.SEARCH)" />
</div> </div>
<!-- 过滤条件 --> <!-- 过滤条件 -->

View File

@@ -1,4 +1,4 @@
import type { CacheState } from './types'; import type { CacheState, CacheType } from './types';
import type { AxiosResponse } from 'axios'; import type { AxiosResponse } from 'axios';
import type { TagType } from '@/api/meta/tag'; import type { TagType } from '@/api/meta/tag';
import { getTagList } from '@/api/meta/tag'; import { getTagList } from '@/api/meta/tag';
@@ -19,14 +19,6 @@ import { getCommandSnippetGroupList } from '@/api/asset/command-snippet-group';
import { getExecJobList } from '@/api/job/exec-job'; import { getExecJobList } from '@/api/job/exec-job';
import { getPathBookmarkGroupList } from '@/api/asset/path-bookmark-group'; import { getPathBookmarkGroupList } from '@/api/asset/path-bookmark-group';
export type CacheType = 'users' | 'menus' | 'roles'
| 'hostGroups' | 'hostKeys' | 'hostIdentities'
| 'dictKeys'
| 'authorizedHostKeys' | 'authorizedHostIdentities'
| 'commandSnippetGroups' | 'pathBookmarkGroups'
| 'execJob'
| string
export default defineStore('cache', { export default defineStore('cache', {
state: (): CacheState => ({}), state: (): CacheState => ({}),

View File

@@ -1,23 +1,12 @@
import type { UserQueryResponse } from '@/api/user/user'; // 缓存类型
import type { MenuQueryResponse } from '@/api/system/menu'; export type CacheType = 'users' | 'menus' | 'roles'
import type { RoleQueryResponse } from '@/api/user/role'; | 'hostGroups' | 'hostKeys' | 'hostIdentities'
import type { HostQueryResponse } from '@/api/asset/host'; | 'dictKeys'
import type { HostGroupQueryResponse } from '@/api/asset/host-group'; | 'authorizedHostKeys' | 'authorizedHostIdentities'
import type { HostKeyQueryResponse } from '@/api/asset/host-key'; | 'commandSnippetGroups' | 'pathBookmarkGroups'
import type { HostIdentityQueryResponse } from '@/api/asset/host-identity'; | 'execJob'
import type { DictKeyQueryResponse } from '@/api/system/dict-key'; | string
export interface CacheState { export interface CacheState {
users?: UserQueryResponse[]; [key: CacheType]: unknown;
menus?: MenuQueryResponse[];
roles?: RoleQueryResponse[];
hosts?: HostQueryResponse[];
hostGroups?: HostGroupQueryResponse[];
hostKeys?: HostKeyQueryResponse[];
hostIdentities?: HostIdentityQueryResponse[];
dictKeys?: DictKeyQueryResponse[];
authorizedHostKeys?: HostKeyQueryResponse[];
authorizedHostIdentities?: HostIdentityQueryResponse[];
[key: string]: unknown;
} }

View File

@@ -1,10 +1,10 @@
import type { RouteMeta, RouteRecordNormalized } from 'vue-router'; import type { RouteMeta, RouteRecordNormalized } from 'vue-router';
import type { MenuState } from './types'; import type { MenuState } from './types';
import type { MenuQueryResponse } from '@/api/system/menu'; import type { MenuQueryResponse } from '@/api/system/menu';
import router from '@/router';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { Notification } from '@arco-design/web-vue'; import { Notification } from '@arco-design/web-vue';
import { getMenuList } from '@/api/user/auth'; import { getMenuList } from '@/api/user/auth';
import router from '@/router';
import { EnabledStatus } from '@/types/const'; import { EnabledStatus } from '@/types/const';
export default defineStore('menu', { export default defineStore('menu', {

View File

@@ -100,8 +100,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 连接用户 --> <!-- 连接用户 -->
<template #username="{ record }"> <template #username="{ record }">
{{ record.username }} {{ record.username }}

View File

@@ -84,8 +84,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 操作用户 --> <!-- 操作用户 -->
<template #username="{ record }"> <template #username="{ record }">
{{ record.username }} {{ record.username }}

View File

@@ -102,8 +102,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 类型 --> <!-- 类型 -->
<template #type="{ record }"> <template #type="{ record }">
<a-tag :color="getDictValue(identityTypeKey, record.type, 'color')"> <a-tag :color="getDictValue(identityTypeKey, record.type, 'color')">

View File

@@ -87,8 +87,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 操作 --> <!-- 操作 -->
<template #handle="{ record }"> <template #handle="{ record }">
<div class="table-handle-wrapper"> <div class="table-handle-wrapper">

View File

@@ -127,8 +127,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 主机类型 --> <!-- 主机类型 -->
<template #type="{ record }"> <template #type="{ record }">
<a-tag :color="getDictValue(hostTypeKey, record.type, 'color')"> <a-tag :color="getDictValue(hostTypeKey, record.type, 'color')">

View File

@@ -108,8 +108,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)" @page-size-change="(size: number) => fetchTableData(1, size)"
@expand="loadExecHost"> @expand="loadExecHost">
<!-- 展开表格 --> <!-- 展开表格 -->
<template #expand-row="{ record }"> <template #expand-row="{ record }">
@@ -165,7 +165,7 @@
type="text" type="text"
size="mini" size="mini"
title="ctrl + 左键新页面打开" title="ctrl + 左键新页面打开"
@click="(e) => emits('viewLog', record.id, e.ctrlKey)"> @click="(e: any) => emits('viewLog', record.id, e.ctrlKey)">
日志 日志
</a-button> </a-button>
<!-- 中断 --> <!-- 中断 -->

View File

@@ -18,9 +18,10 @@
<a-empty description="无执行记录" /> <a-empty description="无执行记录" />
</div> </div>
<!-- 批量执行日志 --> <!-- 批量执行日志 -->
<div v-else class="exec-history-rows"> <a-scrollbar v-else>
<div v-for="record in historyLogs" <div v-for="(record, index) in historyLogs"
:key="record.id" :key="record.id"
:style="{ marginBottom: index === historyLogs.length -1 ? 0 : '8px' }"
class="exec-history" class="exec-history"
@click="emits('selected', record)"> @click="emits('selected', record)">
<!-- 机器数量 --> <!-- 机器数量 -->
@@ -32,7 +33,7 @@
{{ record.description }} {{ record.description }}
</span> </span>
</div> </div>
</div> </a-scrollbar>
</div> </div>
</template> </template>
@@ -110,14 +111,16 @@
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.exec-history-rows { .container {
position: absolute; :deep(.arco-scrollbar) {
width: calc(100% - 32px); position: absolute;
height: calc(100% - 64px); width: calc(100% - 32px);
overflow: auto; height: calc(100% - 64px);
&::-webkit-scrollbar-track { &-container {
display: none; height: 100%;
overflow-y: auto;
}
} }
} }
@@ -127,7 +130,6 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 8px;
background: var(--color-fill-2); background: var(--color-fill-2);
transition: all .2s; transition: all .2s;
user-select: none; user-select: none;

View File

@@ -77,8 +77,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 模板命令 --> <!-- 模板命令 -->
<template #command="{ record }"> <template #command="{ record }">
<span class="copy-left" @click="copy(record.command, '已复制')"> <span class="copy-left" @click="copy(record.command, '已复制')">

View File

@@ -107,8 +107,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 上传路径 --> <!-- 上传路径 -->
<template #remotePath="{ record }"> <template #remotePath="{ record }">
<span class="text-copy span-blue" @click="copy(record.remotePath)"> <span class="text-copy span-blue" @click="copy(record.remotePath)">

View File

@@ -320,6 +320,18 @@
height: calc(100% - 56px); height: calc(100% - 56px);
overflow: auto; overflow: auto;
padding-bottom: 4px; padding-bottom: 4px;
&::-webkit-scrollbar-track {
display: none;
}
&::-webkit-scrollbar-thumb {
background: transparent;
}
&:hover::-webkit-scrollbar-thumb {
background: var(--color-fill-4);
}
} }
.loading-skeleton { .loading-skeleton {

View File

@@ -75,9 +75,8 @@
import type { HostQueryResponse } from '@/api/asset/host'; import type { HostQueryResponse } from '@/api/asset/host';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { useTerminalStore } from '@/store'; import { useTerminalStore } from '@/store';
import { PanelSessionType, TerminalTabs } from '../../types/const'; import { PanelSessionType, TerminalTabs, emptyRecommendCount } from '../../types/const';
const totalCount = 7;
const { tabManager, hosts, openSession } = useTerminalStore(); const { tabManager, hosts, openSession } = useTerminalStore();
const combinedHandlers = ref<Array<CombinedHandlerItem>>([{ const combinedHandlers = ref<Array<CombinedHandlerItem>>([{
@@ -103,7 +102,7 @@
...hosts.hostList.filter(s => s.favorite).map(s => s.id), ...hosts.hostList.filter(s => s.favorite).map(s => s.id),
...hosts.hostList.map(s => s.id) ...hosts.hostList.map(s => s.id)
]) ])
].slice(0, totalCount - 1) ].slice(0, emptyRecommendCount - 1)
.map(s => hosts.hostList.find(t => t.id === s) as HostQueryResponse) .map(s => hosts.hostList.find(t => t.id === s) as HostQueryResponse)
.filter(Boolean) .filter(Boolean)
.map(s => { .map(s => {
@@ -116,10 +115,10 @@
// 插入主机列表 // 插入主机列表
combinedHandlers.value.push(...combinedHosts); combinedHandlers.value.push(...combinedHosts);
// 不足显示的行数用设置补充 // 不足显示的行数用设置补充
if (totalCount - 1 - combinedHosts.length > 0) { if (emptyRecommendCount - 1 - combinedHosts.length > 0) {
const fillTabs = Object.values(TerminalTabs) const fillTabs = Object.values(TerminalTabs)
.filter(s => s.key !== TerminalTabs.NEW_CONNECTION.key) .filter(s => s.key !== TerminalTabs.NEW_CONNECTION.key)
.slice(0, totalCount - 1 - combinedHosts.length) .slice(0, emptyRecommendCount - 1 - combinedHosts.length)
.map(s => { .map(s => {
return { return {
title: s.title, title: s.title,
@@ -147,23 +146,19 @@
.combined-container { .combined-container {
padding: 12px; padding: 12px;
margin: 64px auto 0 auto; margin: 32px auto 0 auto;
width: @container-width; width: @container-width;
height: @container-height; max-height: @container-height;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
box-sizing: content-box; box-sizing: content-box;
overflow: hidden; overflow: hidden;
&:hover {
overflow: auto;
}
} }
.combined-handler { .combined-handler {
width: @container-width - @transform-x; width: @container-width - @transform-x;
height: @handler-height; max-height: @handler-height;
border-radius: 4px; border-radius: 4px;
margin-bottom: 6px; margin-bottom: 6px;
color: var(--color-content-text-1); color: var(--color-content-text-1);

View File

@@ -14,8 +14,8 @@
:editable="true" :editable="true"
:hide-content="true" :hide-content="true"
:auto-switch="true" :auto-switch="true"
@tab-click="k => tabManager.clickTab(k as string)" @tab-click="(k: string) => tabManager.clickTab(k)"
@delete="k => tabManager.deleteTab(k as string)"> @delete="(k: string) => tabManager.deleteTab(k)">
<a-tab-pane v-for="tab in tabManager.items" <a-tab-pane v-for="tab in tabManager.items"
:key="tab.key"> :key="tab.key">
<!-- 标题 --> <!-- 标题 -->

View File

@@ -6,8 +6,8 @@
:auto-switch="true" :auto-switch="true"
:show-add-button="true" :show-add-button="true"
@add="openNewConnect" @add="openNewConnect"
@tab-click="k => panel.clickTab(k as string)" @tab-click="(k: string) => panel.clickTab(k)"
@delete="k => panel.deleteTab(k as string)"> @delete="(k: string) => panel.deleteTab(k)">
<!-- 右侧按钮 --> <!-- 右侧按钮 -->
<template #extra> <template #extra>
<a-space class="panel-extra"> <a-space class="panel-extra">

View File

@@ -134,10 +134,4 @@
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.list-view-container {
max-height: 100%;
width: 100%;
overflow: auto;
position: relative;
}
</style> </style>

View File

@@ -10,7 +10,7 @@
type="button" type="button"
class="usn" class="usn"
:options="toRadioOptions(newConnectionTypeKey)" :options="toRadioOptions(newConnectionTypeKey)"
@change="s => updateTerminalPreference(TerminalPreferenceItem.NEW_CONNECTION_TYPE, s as string, true)" /> @change="(s: string) => updateTerminalPreference(TerminalPreferenceItem.NEW_CONNECTION_TYPE, s, true)" />
<!-- 过滤 --> <!-- 过滤 -->
<a-auto-complete v-model="filterValue" <a-auto-complete v-model="filterValue"
class="host-filter" class="host-filter"

View File

@@ -320,6 +320,18 @@
height: calc(100% - 56px); height: calc(100% - 56px);
overflow: auto; overflow: auto;
padding-bottom: 4px; padding-bottom: 4px;
&::-webkit-scrollbar-track {
display: none;
}
&::-webkit-scrollbar-thumb {
background: transparent;
}
&:hover::-webkit-scrollbar-thumb {
background: var(--color-fill-4);
}
} }
.loading-skeleton { .loading-skeleton {

View File

@@ -20,7 +20,7 @@
<a-input size="small" <a-input size="small"
:ref="setAutoFocus as unknown as VNodeRef" :ref="setAutoFocus as unknown as VNodeRef"
:model-value="filterValue[0]" :model-value="filterValue[0]"
@input="(value) => setFilterValue([value])" @input="(value: string) => setFilterValue([value])"
@press-enter="handleFilterConfirm" /> @press-enter="handleFilterConfirm" />
<!-- 按钮 --> <!-- 按钮 -->
<div class="name-filter-footer"> <div class="name-filter-footer">

View File

@@ -10,13 +10,15 @@
:unmount-on-close="true" :unmount-on-close="true"
:on-before-ok="handlerOk" :on-before-ok="handlerOk"
@cancel="handleClose"> @cancel="handleClose">
<!-- 上传目录 --> <div class="upload-container">
<div class="item-wrapper"> <!-- 上传目录 -->
<div class="form-item"> <div class="item-wrapper">
<span class="item-label">上传至文件夹</span> <div class="form-item">
<a-input class="item-input" <span class="item-label">上传至文件夹</span>
v-model="parentPath" <a-input class="item-input"
placeholder="上传目录" /> v-model="parentPath"
placeholder="上传目录" />
</div>
</div> </div>
<a-space> <a-space>
<!-- 选择文件 --> <!-- 选择文件 -->
@@ -112,7 +114,7 @@
} }
// 获取上传的文件 // 获取上传的文件
const files = fileList.value.map(s => s.file as File); const files = fileList.value.map(s => s.file as File);
// 上传 // 普通上传
transferManager.addUpload(hostId.value, parentPath.value, files); transferManager.addUpload(hostId.value, parentPath.value, files);
Message.success('已开始上传, 点击右侧传输列表查看进度'); Message.success('已开始上传, 点击右侧传输列表查看进度');
// 清空 // 清空
@@ -136,6 +138,11 @@
@file-size-width: 82px; @file-size-width: 82px;
@item-label: 104px; @item-label: 104px;
.upload-container {
width: 100%;
padding: 20px;
}
.item-wrapper { .item-wrapper {
margin-bottom: 24px; margin-bottom: 24px;
display: flex; display: flex;
@@ -163,6 +170,11 @@
width: 376px; width: 376px;
} }
.form-help {
margin: 4px 0 0 @item-label;
font-size: 12px;
color: var(--color-text-2);
}
} }
.file-list-uploader { .file-list-uploader {

View File

@@ -242,7 +242,7 @@
width: 100%; width: 100%;
height: calc(100% - @ssh-header-height); height: calc(100% - @ssh-header-height);
position: relative; position: relative;
padding: 6px 0 0 6px; padding: 8px;
.ssh-inst { .ssh-inst {
width: 100%; width: 100%;

View File

@@ -1,4 +1,5 @@
import type { ISftpSession, ISftpSessionResolver, ITerminalChannel, TerminalPanelTabItem } from '../types/define'; import type { ISftpSession, ISftpSessionResolver, ITerminalChannel, TerminalPanelTabItem } from '../types/define';
import { h } from 'vue';
import { InputProtocol } from '@/types/protocol/terminal.protocol'; import { InputProtocol } from '@/types/protocol/terminal.protocol';
import { PanelSessionType } from '../types/const'; import { PanelSessionType } from '../types/const';
import { Modal } from '@arco-design/web-vue'; import { Modal } from '@arco-design/web-vue';
@@ -77,15 +78,32 @@ export default class SftpSession extends BaseSession implements ISftpSession {
}; };
// 删除文件 // 删除文件
remove(path: string[]) { remove(paths: string[]) {
// 内容
const contentNode = h('div', {
style: {
display: 'flex',
flexDirection: 'column',
maxHeight: '40vh',
overflowY: 'auto'
}
},
paths.map(s => {
return h('span', { style: { marginTop: '4px' } }, s);
}));
// 提示
Modal.confirm({ Modal.confirm({
title: '删除确认', title: '确定后将立即删除这些文件且无法恢复!',
content: `确定要删除 ${path.join(',')} 吗? 确定后将立即删除且无法恢复!`, modalStyle: { padding: '24px 32px' },
bodyStyle: { marginTop: '-14px' },
okButtonProps: { status: 'danger' },
okText: '删除',
content: () => contentNode,
onOk: () => { onOk: () => {
this.resolver.setLoading(true); this.resolver.setLoading(true);
this.channel.send(InputProtocol.SFTP_REMOVE, { this.channel.send(InputProtocol.SFTP_REMOVE, {
sessionId: this.sessionId, sessionId: this.sessionId,
path: path.join('|') path: paths.join('|')
}); });
} }
}); });

View File

@@ -43,7 +43,6 @@ export default class SftpTransferManager implements ISftpTransferManager {
file: s file: s
}; };
}); });
this.transferList.push(...items);
// 开始传输 // 开始传输
this.startTransfer(items); this.startTransfer(items);
} }

View File

@@ -1,5 +1,8 @@
import type { ShortcutKeyItem } from './define'; import type { ShortcutKeyItem } from './define';
// 首页推荐数量
export const emptyRecommendCount = 7;
// 终端 tab // 终端 tab
export const TerminalTabs = { export const TerminalTabs = {
NEW_CONNECTION: { NEW_CONNECTION: {

View File

@@ -93,8 +93,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)" @page-size-change="(size: number) => fetchTableData(1, size)"
@expand="loadExecHost"> @expand="loadExecHost">
<!-- 展开表格 --> <!-- 展开表格 -->
<template #expand-row="{ record }"> <template #expand-row="{ record }">
@@ -148,7 +148,7 @@
type="text" type="text"
size="mini" size="mini"
title="ctrl + 左键新页面打开" title="ctrl + 左键新页面打开"
@click="(e) => emits('viewLog', record.id, e.ctrlKey)"> @click="(e: any) => emits('viewLog', record.id, e.ctrlKey)">
日志 日志
</a-button> </a-button>
<!-- 中断 --> <!-- 中断 -->

View File

@@ -421,7 +421,7 @@
.command-editor { .command-editor {
width: 100%; width: 100%;
height: calc(100vh - 318px); height: calc(100vh - 324px);
} }
:deep(.arco-input-append) { :deep(.arco-input-append) {

View File

@@ -84,8 +84,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- cron --> <!-- cron -->
<template #expression="{ record }"> <template #expression="{ record }">
<span class="copy-left" <span class="copy-left"
@@ -118,7 +118,7 @@
:unchecked-text="getDictValue(execJobStatusKey, ExecJobStatus.DISABLED)" :unchecked-text="getDictValue(execJobStatusKey, ExecJobStatus.DISABLED)"
:checked-value="ExecJobStatus.ENABLED" :checked-value="ExecJobStatus.ENABLED"
:unchecked-value="ExecJobStatus.DISABLED" :unchecked-value="ExecJobStatus.DISABLED"
:before-change="s => updateStatus(record.id, s as number)" /> :before-change="(s: number) => updateStatus(record.id, s)" />
<!-- 状态 不可编辑 --> <!-- 状态 不可编辑 -->
<a-tag v-else :color="getDictValue(execJobStatusKey, record.status, 'color')"> <a-tag v-else :color="getDictValue(execJobStatusKey, record.status, 'color')">
{{ getDictValue(execJobStatusKey, record.status) }} {{ getDictValue(execJobStatusKey, record.status) }}

View File

@@ -91,8 +91,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 配置项 --> <!-- 配置项 -->
<template #keyName="{ record }"> <template #keyName="{ record }">
<span class="text-copy" @click="copy(record.keyName)">{{ record.keyName }}</span> <span class="text-copy" @click="copy(record.keyName)">{{ record.keyName }}</span>

View File

@@ -77,8 +77,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 配置项 --> <!-- 配置项 -->
<template #keyName="{record}"> <template #keyName="{record}">
{{ record.keyName }}<span style="margin: 0 4px;">-</span>{{ record.keyDescription }} {{ record.keyName }}<span style="margin: 0 4px;">-</span>{{ record.keyDescription }}

View File

@@ -5,7 +5,7 @@
position="left" position="left"
:lazy-load="true" :lazy-load="true"
:destroy-on-hide="true" :destroy-on-hide="true"
@tab-click="k => clickTab(k as string)"> @tab-click="(k: string) => clickTab(k)">
<!-- 个人信息 --> <!-- 个人信息 -->
<a-tab-pane key="mineInfo" <a-tab-pane key="mineInfo"
v-if="!user || hasPermission('infra:system-user:update')" v-if="!user || hasPermission('infra:system-user:update')"

View File

@@ -7,8 +7,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 操作模块 --> <!-- 操作模块 -->
<template #module="{ record }"> <template #module="{ record }">
<span>{{ getDictValue(operatorLogModuleKey, record.module) }}</span> <span>{{ getDictValue(operatorLogModuleKey, record.module) }}</span>

View File

@@ -55,8 +55,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 操作模块 --> <!-- 操作模块 -->
<template #module="{ record }"> <template #module="{ record }">
<span>{{ getDictValue(operatorLogModuleKey, record.module) }}</span> <span>{{ getDictValue(operatorLogModuleKey, record.module) }}</span>

View File

@@ -60,8 +60,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 编码 --> <!-- 编码 -->
<template #code="{ record }"> <template #code="{ record }">
<a-tag>{{ record.code }}</a-tag> <a-tag>{{ record.code }}</a-tag>
@@ -77,7 +77,7 @@
:unchecked-text="getDictValue(roleStatusKey, RoleStatus.DISABLED)" :unchecked-text="getDictValue(roleStatusKey, RoleStatus.DISABLED)"
:checked-value="RoleStatus.ENABLED" :checked-value="RoleStatus.ENABLED"
:unchecked-value="RoleStatus.DISABLED" :unchecked-value="RoleStatus.DISABLED"
:before-change="(s) => updateStatus(record.id, s as number)" /> :before-change="(s: number) => updateStatus(record.id, s)" />
<!-- 无修改权限 --> <!-- 无修改权限 -->
<span v-else> <span v-else>
<span class="circle" :style="{ <span class="circle" :style="{

View File

@@ -88,8 +88,8 @@
:data="tableRenderData" :data="tableRenderData"
:pagination="pagination" :pagination="pagination"
:bordered="false" :bordered="false"
@page-change="(page) => fetchTableData(page, pagination.pageSize)" @page-change="(page: number) => fetchTableData(page, pagination.pageSize)"
@page-size-change="(size) => fetchTableData(1, size)"> @page-size-change="(size: number) => fetchTableData(1, size)">
<!-- 用户名 --> <!-- 用户名 -->
<template #username="{ record }"> <template #username="{ record }">
<span class="text-copy" @click="copy(record.username)"> <span class="text-copy" @click="copy(record.username)">
@@ -107,7 +107,7 @@
:unchecked-text="getDictValue(userStatusKey, UserStatus.DISABLED)" :unchecked-text="getDictValue(userStatusKey, UserStatus.DISABLED)"
:checked-value="UserStatus.ENABLED" :checked-value="UserStatus.ENABLED"
:unchecked-value="UserStatus.DISABLED" :unchecked-value="UserStatus.DISABLED"
:before-change="(s) => updateStatus(record.id, s as number)" /> :before-change="(s: number) => updateStatus(record.id, s)" />
<!-- 无修改权限 --> <!-- 无修改权限 -->
<span v-else> <span v-else>
<span class="circle" :style="{ <span class="circle" :style="{

View File

@@ -22,7 +22,7 @@
</modules> </modules>
<properties> <properties>
<revision>2.1.0</revision> <revision>2.1.1</revision>
<maven.compiler.source>8</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target> <maven.compiler.target>8</maven.compiler.target>
<maven.surefire.plugin.version>3.0.0-M5</maven.surefire.plugin.version> <maven.surefire.plugin.version>3.0.0-M5</maven.surefire.plugin.version>