🎉 重构前端代码.

This commit is contained in:
lijiahangmax
2025-06-25 14:49:36 +08:00
parent 5183b7ccb4
commit 6149010bf4
49 changed files with 564 additions and 573 deletions

View File

@@ -2,7 +2,7 @@ import type { Plugin } from 'vite';
import compressPlugin from 'vite-plugin-compression';
/**
* gzip压缩
* gzip 压缩
* https://github.com/anncwb/vite-plugin-compression
*/
export default function configCompressPlugin(
@@ -19,7 +19,7 @@ export default function configCompressPlugin(
})
);
}
// br 压缩
if (compress === 'brotli') {
plugins.push(
compressPlugin({

View File

@@ -32,6 +32,10 @@ export default defineConfig({
find: 'vue',
replacement: 'vue/dist/vue.esm-bundler.js', // compile template
},
{
find: 'guacamole-common-js',
replacement: resolve(__dirname, '../libs/guacamole-common-js')
},
],
extensions: ['.ts', '.js'],
},

View File

@@ -67,6 +67,7 @@
"@commitlint/cli": "^17.1.2",
"@commitlint/config-conventional": "^17.1.0",
"@types/file-saver": "^2.0.7",
"@types/guacamole-common-js": "^1.5.3",
"@types/lodash": "^4.14.186",
"@types/mockjs": "^1.0.7",
"@types/nprogress": "^0.2.0",

View File

@@ -119,6 +119,9 @@ importers:
'@types/file-saver':
specifier: ^2.0.7
version: 2.0.7
'@types/guacamole-common-js':
specifier: ^1.5.3
version: 1.5.3
'@types/lodash':
specifier: ^4.14.186
version: 4.17.14
@@ -1181,6 +1184,9 @@ packages:
'@types/glob@7.2.0':
resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==}
'@types/guacamole-common-js@1.5.3':
resolution: {integrity: sha512-PDW2kRwwIgzw0ys82X65g13+OHRPW4Ek/919vIoacWGEUU8jGGfULmH+6TuufLDGMO0cqXR03nxer8ceRDmy3g==}
'@types/imagemin-gifsicle@7.0.4':
resolution: {integrity: sha512-ZghMBd/Jgqg5utTJNPmvf6DkuHzMhscJ8vgf/7MUGCpO+G+cLrhYltL+5d+h3A1B4W73S2SrmJZ1jS5LACpX+A==}
@@ -7207,6 +7213,8 @@ snapshots:
'@types/minimatch': 5.1.2
'@types/node': 22.10.5
'@types/guacamole-common-js@1.5.3': {}
'@types/imagemin-gifsicle@7.0.4':
dependencies:
'@types/imagemin': 7.0.1
@@ -10828,7 +10836,7 @@ snapshots:
dependencies:
htmlparser2: 3.10.1
postcss: 7.0.39
postcss-syntax: 0.36.2(postcss-html@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-jsx@0.36.4(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-less@3.1.4)(postcss-markdown@0.36.0)(postcss-scss@2.1.1)(postcss@7.0.39)
postcss-syntax: 0.36.2(postcss-html@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-jsx@0.36.4(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-less@3.1.4)(postcss-markdown@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-scss@2.1.1)(postcss@7.0.39)
postcss-html@1.7.0:
dependencies:
@@ -10841,7 +10849,7 @@ snapshots:
dependencies:
'@babel/core': 7.26.0
postcss: 7.0.39
postcss-syntax: 0.36.2(postcss-html@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-jsx@0.36.4(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-less@3.1.4)(postcss-markdown@0.36.0)(postcss-scss@2.1.1)(postcss@7.0.39)
postcss-syntax: 0.36.2(postcss-html@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-jsx@0.36.4(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-less@3.1.4)(postcss-markdown@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-scss@2.1.1)(postcss@7.0.39)
transitivePeerDependencies:
- supports-color
@@ -10852,7 +10860,7 @@ snapshots:
postcss-markdown@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39):
dependencies:
postcss: 7.0.39
postcss-syntax: 0.36.2(postcss-html@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-jsx@0.36.4(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-less@3.1.4)(postcss-markdown@0.36.0)(postcss-scss@2.1.1)(postcss@7.0.39)
postcss-syntax: 0.36.2(postcss-html@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-jsx@0.36.4(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-less@3.1.4)(postcss-markdown@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-scss@2.1.1)(postcss@7.0.39)
remark: 10.0.1
unist-util-find-all-after: 1.0.5
@@ -10913,7 +10921,7 @@ snapshots:
dependencies:
postcss: 8.4.49
postcss-syntax@0.36.2(postcss-html@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-jsx@0.36.4(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-less@3.1.4)(postcss-markdown@0.36.0)(postcss-scss@2.1.1)(postcss@7.0.39):
postcss-syntax@0.36.2(postcss-html@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-jsx@0.36.4(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-less@3.1.4)(postcss-markdown@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-scss@2.1.1)(postcss@7.0.39):
dependencies:
postcss: 7.0.39
optionalDependencies:
@@ -11789,7 +11797,7 @@ snapshots:
postcss-sass: 0.3.5
postcss-scss: 2.1.1
postcss-selector-parser: 3.1.2
postcss-syntax: 0.36.2(postcss-html@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-jsx@0.36.4(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-less@3.1.4)(postcss-markdown@0.36.0)(postcss-scss@2.1.1)(postcss@7.0.39)
postcss-syntax: 0.36.2(postcss-html@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-jsx@0.36.4(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-less@3.1.4)(postcss-markdown@0.36.0(postcss-syntax@0.36.2(postcss-html@1.7.0)(postcss@8.4.49))(postcss@7.0.39))(postcss-scss@2.1.1)(postcss@7.0.39)
postcss-value-parser: 3.3.1
resolve-from: 4.0.0
signal-exit: 3.0.7

View File

@@ -2,7 +2,7 @@
<a-config-provider :locale="locale">
<!-- 路由 -->
<router-view />
<!-- 应用设置 -->
<!-- 偏好设置 -->
<app-setting ref="appSettingRef" />
</a-config-provider>
</template>

View File

@@ -36,6 +36,21 @@ export interface HostSshConfig extends HostBaseConfig {
fileContentCharset?: string;
}
// 主机 RDP 配置
export interface HostRdpConfig extends HostBaseConfig {
identityId?: number;
versionGt81?: boolean;
timezone?: string;
keyboardLayout?: string;
clipboardNormalize?: string;
domain?: string;
preConnectionId?: string;
preConnectionBlob?: string;
remoteApp?: string;
remoteAppDir?: string;
remoteAppArgs?: string;
}
/**
* 更新主机配置
*/

View File

@@ -25,6 +25,13 @@ export interface HostSshExtraSettingModel {
identityId: number;
}
// RDP 额外配置
export interface HostRdpExtraSettingModel {
authType: string;
identityId: number;
lowBandwidthMode: boolean;
}
// 标签额外配置
export interface HostLabelExtraSettingModel {
alias: string;

View File

@@ -1,6 +1,6 @@
import type { HostExtraUpdateRequest, HostSpecExtraModel } from './host-extra';
import type { TableData } from '@arco-design/web-vue';
import type { DataGrid, OrderDirection, Pagination } from '@/types/global';
import type { DataGrid, FavoriteItem, OrderDirection, Pagination } from '@/types/global';
import axios from 'axios';
import qs from 'query-string';
@@ -58,9 +58,9 @@ export interface HostQueryRequest extends Pagination, OrderDirection {
}
/**
* 主机查询响应
* 主机查询基础响应
*/
export interface HostQueryResponse extends TableData, HostQueryResponseExtra {
export interface HostQueryBaseResponse {
id: number;
types: Array<string>;
osType: string;
@@ -74,7 +74,12 @@ export interface HostQueryResponse extends TableData, HostQueryResponseExtra {
updateTime: number;
creator: string;
updater: string;
favorite: boolean;
}
/**
* 主机查询响应
*/
export interface HostQueryResponse extends HostQueryBaseResponse, TableData, FavoriteItem, HostQueryResponseExtra {
alias: string;
color: string;
tags: Array<{ id: number, name: string }>;

View File

@@ -1,73 +0,0 @@
import axios from 'axios';
import { createAppWebSocket } from '@/utils/http';
// 终端主题
export interface TerminalTheme {
name: string;
dark: boolean;
schema: TerminalThemeSchema;
}
// 终端主题 schema
export interface TerminalThemeSchema {
background: string;
foreground: string;
cursor: string;
cursorAccent?: string;
selectionBackground?: string;
selectionForeground?: string;
selectionInactiveBackground?: string;
black: string;
red: string;
green: string;
yellow: string;
blue: string;
magenta: string;
cyan: string;
white: string;
brightBlack: string;
brightRed: string;
brightGreen: string;
brightYellow: string;
brightBlue: string;
brightMagenta: string;
brightCyan: string;
brightWhite: string;
[key: string]: unknown;
}
/**
* 获取终端主题
*/
export function getTerminalThemes() {
return axios.get<Array<TerminalTheme>>('/asset/terminal/themes');
}
/**
* 获取终端 accessToken
*/
export function getTerminalAccessToken() {
return axios.get<string>('/asset/terminal/access');
}
/**
* 获取终端 transferToken
*/
export function getTerminalTransferToken() {
return axios.get<string>('/asset/terminal/transfer');
}
/**
* 打开终端 websocket
*/
export const openTerminalAccessChannel = (accessToken: string) => {
return createAppWebSocket(`/terminal/access/${accessToken}`);
};
/**
* 打开终端传输 websocket
*/
export const openTerminalTransferChannel = (accessToken: string) => {
return createAppWebSocket(`/terminal/transfer/${accessToken}`);
};

View File

@@ -14,35 +14,35 @@ import qs from 'query-string';
* 分页查询批量执行日志
*/
export function getExecCommandLogPage(request: ExecLogQueryRequest) {
return axios.post<DataGrid<ExecLogQueryResponse>>('/asset/exec-command-log/query', request);
return axios.post<DataGrid<ExecLogQueryResponse>>('/exec/exec-command-log/query', request);
}
/**
* 查询批量执行日志
*/
export function getExecCommandLog(id: number) {
return axios.get<ExecLogQueryResponse>('/asset/exec-command-log/get', { params: { id } });
return axios.get<ExecLogQueryResponse>('/exec/exec-command-log/get', { params: { id } });
}
/**
* 查询主机计划任务日志
*/
export function getExecCommandHostLog(id: number) {
return axios.get<ExecHostLogQueryResponse>('/asset/exec-command-log/get-host', { params: { id } });
return axios.get<ExecHostLogQueryResponse>('/exec/exec-command-log/get-host', { params: { id } });
}
/**
* 查询主机批量执行日志
*/
export function getExecCommandHostLogList(logId: number) {
return axios.get<Array<ExecHostLogQueryResponse>>('/asset/exec-command-log/host-list', { params: { logId } });
return axios.get<Array<ExecHostLogQueryResponse>>('/exec/exec-command-log/host-list', { params: { logId } });
}
/**
* 查询命令执行状态
*/
export function getExecCommandLogStatus(idList: Array<number>) {
return axios.get<ExecLogStatusResponse>('/asset/exec-command-log/status', {
return axios.get<ExecLogStatusResponse>('/exec/exec-command-log/status', {
params: { idList },
promptBizErrorMessage: false,
promptRequestErrorMessage: false,
@@ -56,21 +56,21 @@ export function getExecCommandLogStatus(idList: Array<number>) {
* 查询历史批量执行日志
*/
export function getExecCommandLogHistory(limit: number) {
return axios.get<Array<ExecLogQueryResponse>>('/asset/exec-command-log/history', { params: { page: 1, limit } });
return axios.get<Array<ExecLogQueryResponse>>('/exec/exec-command-log/history', { params: { page: 1, limit } });
}
/**
* 删除批量执行日志
*/
export function deleteExecCommandLog(id: number) {
return axios.delete('/asset/exec-command-log/delete', { params: { id } });
return axios.delete('/exec/exec-command-log/delete', { params: { id } });
}
/**
* 批量删除批量执行日志
*/
export function batchDeleteExecCommandLog(idList: Array<number>) {
return axios.delete('/asset/exec-command-log/batch-delete', {
return axios.delete('/exec/exec-command-log/batch-delete', {
params: { idList },
paramsSerializer: params => {
return qs.stringify(params, { arrayFormat: 'comma' });
@@ -82,21 +82,21 @@ export function batchDeleteExecCommandLog(idList: Array<number>) {
* 删除主机批量执行日志
*/
export function deleteExecCommandHostLog(id: number) {
return axios.delete('/asset/exec-command-log/delete-host', { params: { id } });
return axios.delete('/exec/exec-command-log/delete-host', { params: { id } });
}
/**
* 查询批量执行日志数量
*/
export function getExecCommandLogCount(request: ExecLogQueryRequest) {
return axios.post<number>('/asset/exec-command-log/count', request);
return axios.post<number>('/exec/exec-command-log/count', request);
}
/**
* 清空批量执行日志
*/
export function clearExecCommandLog(request: ExecLogClearRequest) {
return axios.post<number>('/asset/exec-command-log/clear', request, {
return axios.post<number>('/exec/exec-command-log/clear', request, {
timeout: 60000,
});
}
@@ -105,14 +105,14 @@ export function clearExecCommandLog(request: ExecLogClearRequest) {
* 查看批量执行日志
*/
export function getExecCommandLogTailToken(id: number) {
return axios.get<string>('/asset/exec-command-log/tail', { params: { id } });
return axios.get<string>('/exec/exec-command-log/tail', { params: { id } });
}
/**
* 下载批量执行日志文件
*/
export function downloadExecCommandLogFile(id: number) {
return axios.get('/asset/exec-command-log/download', {
return axios.get('/exec/exec-command-log/download', {
unwrap: true,
responseType: 'blob',
params: { id },
@@ -123,12 +123,12 @@ export function downloadExecCommandLogFile(id: number) {
* 中断执行命令
*/
export function interruptExecCommand(request: ExecLogInterruptRequest) {
return axios.put('/asset/exec-command-log/interrupt', request);
return axios.put('/exec/exec-command-log/interrupt', request);
}
/**
* 中断执行主机命令
*/
export function interruptHostExecCommand(request: ExecLogInterruptRequest) {
return axios.put('/asset/exec-command-log/interrupt-host', request);
return axios.put('/exec/exec-command-log/interrupt-host', request);
}

View File

@@ -18,12 +18,12 @@ export interface ExecCommandRequest {
* 批量执行命令
*/
export function batchExecCommand(request: ExecCommandRequest) {
return axios.post<ExecLogQueryResponse>('/asset/exec-command/exec', request);
return axios.post<ExecLogQueryResponse>('/exec/exec-command/exec', request);
}
/**
* 重新执行命令
*/
export function reExecCommand(request: ExecCommandRequest) {
return axios.post<ExecLogQueryResponse>('/asset/exec-command/re-exec', request);
return axios.post<ExecLogQueryResponse>('/exec/exec-command/re-exec', request);
}

View File

@@ -6,7 +6,7 @@ import type {
ExecLogQueryRequest,
ExecLogQueryResponse,
ExecLogStatusResponse,
} from './exec-log';
} from '../exec/exec-log';
import axios from 'axios';
import qs from 'query-string';
@@ -14,35 +14,35 @@ import qs from 'query-string';
* 分页查询计划任务日志
*/
export function getExecJobLogPage(request: ExecLogQueryRequest) {
return axios.post<DataGrid<ExecLogQueryResponse>>('/asset/exec-job-log/query', request);
return axios.post<DataGrid<ExecLogQueryResponse>>('/exec/exec-job-log/query', request);
}
/**
* 查询计划任务日志
*/
export function getExecJobLog(id: number) {
return axios.get<ExecLogQueryResponse>('/asset/exec-job-log/get', { params: { id } });
return axios.get<ExecLogQueryResponse>('/exec/exec-job-log/get', { params: { id } });
}
/**
* 查询主机计划任务日志
*/
export function getExecJobHostLog(id: number) {
return axios.get<ExecHostLogQueryResponse>('/asset/exec-job-log/get-host', { params: { id } });
return axios.get<ExecHostLogQueryResponse>('/exec/exec-job-log/get-host', { params: { id } });
}
/**
* 查询主机计划任务日志
*/
export function getExecJobHostLogList(logId: number) {
return axios.get<Array<ExecHostLogQueryResponse>>('/asset/exec-job-log/host-list', { params: { logId } });
return axios.get<Array<ExecHostLogQueryResponse>>('/exec/exec-job-log/host-list', { params: { logId } });
}
/**
* 查询命令执行状态
*/
export function getExecJobLogStatus(idList: Array<number>) {
return axios.get<ExecLogStatusResponse>('/asset/exec-job-log/status', {
return axios.get<ExecLogStatusResponse>('/exec/exec-job-log/status', {
params: { idList },
promptBizErrorMessage: false,
promptRequestErrorMessage: false,
@@ -56,14 +56,14 @@ export function getExecJobLogStatus(idList: Array<number>) {
* 删除计划任务日志
*/
export function deleteExecJobLog(id: number) {
return axios.delete('/asset/exec-job-log/delete', { params: { id } });
return axios.delete('/exec/exec-job-log/delete', { params: { id } });
}
/**
* 批量删除计划任务日志
*/
export function batchDeleteExecJobLog(idList: Array<number>) {
return axios.delete('/asset/exec-job-log/batch-delete', {
return axios.delete('/exec/exec-job-log/batch-delete', {
params: { idList },
paramsSerializer: params => {
return qs.stringify(params, { arrayFormat: 'comma' });
@@ -75,21 +75,21 @@ export function batchDeleteExecJobLog(idList: Array<number>) {
* 删除主机计划任务日志
*/
export function deleteExecJobHostLog(id: number) {
return axios.delete('/asset/exec-job-log/delete-host', { params: { id } });
return axios.delete('/exec/exec-job-log/delete-host', { params: { id } });
}
/**
* 查询计划任务日志数量
*/
export function getExecJobLogCount(request: ExecLogQueryRequest) {
return axios.post<number>('/asset/exec-job-log/count', request);
return axios.post<number>('/exec/exec-job-log/count', request);
}
/**
* 清空计划任务日志
*/
export function clearExecJobLog(request: ExecLogClearRequest) {
return axios.post<number>('/asset/exec-job-log/clear', request, {
return axios.post<number>('/exec/exec-job-log/clear', request, {
timeout: 60000,
});
}
@@ -98,14 +98,14 @@ export function clearExecJobLog(request: ExecLogClearRequest) {
* 查看计划任务日志
*/
export function getExecJobLogTailToken(id: number) {
return axios.get<string>('/asset/exec-job-log/tail', { params: { id } });
return axios.get<string>('/exec/exec-job-log/tail', { params: { id } });
}
/**
* 下载计划任务日志文件
*/
export function downloadExecJobLogFile(id: number) {
return axios.get('/asset/exec-job-log/download', {
return axios.get('/exec/exec-job-log/download', {
unwrap: true,
responseType: 'blob',
params: { id },
@@ -116,12 +116,12 @@ export function downloadExecJobLogFile(id: number) {
* 中断计划任务执行
*/
export function interruptExecJob(request: ExecLogInterruptRequest) {
return axios.put('/asset/exec-job-log/interrupt', request);
return axios.put('/exec/exec-job-log/interrupt', request);
}
/**
* 中断计划任务执行主机
*/
export function interruptHostExecJob(request: ExecLogInterruptRequest) {
return axios.put('/asset/exec-job-log/interrupt-host', request);
return axios.put('/exec/exec-job-log/interrupt-host', request);
}

View File

@@ -81,63 +81,70 @@ export interface ExecJobQueryResponse extends TableData {
* 创建计划任务
*/
export function createExecJob(request: ExecJobCreateRequest) {
return axios.post('/asset/exec-job/create', request);
return axios.post('/exec/exec-job/create', request);
}
/**
* 更新计划任务
*/
export function updateExecJob(request: ExecJobUpdateRequest) {
return axios.put('/asset/exec-job/update', request);
return axios.put('/exec/exec-job/update', request);
}
/**
* 更新计划任务状态
*/
export function updateExecJobStatus(request: ExecJobUpdateStatusRequest) {
return axios.put('/asset/exec-job/update-status', request);
return axios.put('/exec/exec-job/update-status', request);
}
/**
* 更新计划任务执行用户
*/
export function updateExecJobExecUser(request: ExecJobUpdateExecUserRequest) {
return axios.put<number>('/asset/exec-job/update-exec-user', request);
return axios.put<number>('/exec/exec-job/update-exec-user', request);
}
/**
* 查询计划任务
*/
export function getExecJob(id: number) {
return axios.get<ExecJobQueryResponse>('/asset/exec-job/get', { params: { id } });
return axios.get<ExecJobQueryResponse>('/exec/exec-job/get', { params: { id } });
}
/**
* 查询全部计划任务
*/
export function getExecJobList() {
return axios.get<Array<ExecJobQueryResponse>>('/asset/exec-job/list');
return axios.get<Array<ExecJobQueryResponse>>('/exec/exec-job/list');
}
/**
* 分页查询计划任务
*/
export function getExecJobPage(request: ExecJobQueryRequest) {
return axios.post<DataGrid<ExecJobQueryResponse>>('/asset/exec-job/query', request);
return axios.post<DataGrid<ExecJobQueryResponse>>('/exec/exec-job/query', request);
}
/**
* 查询计划任务数量
*/
export function getExecJobCount(request: ExecJobQueryRequest) {
return axios.post<number>('/exec/exec-job/count', request);
}
/**
* 删除计划任务
*/
export function deleteExecJob(id: number) {
return axios.delete('/asset/exec-job/delete', { params: { id } });
return axios.delete('/exec/exec-job/delete', { params: { id } });
}
/**
* 批量删除计划任务
*/
export function batchDeleteExecJob(idList: Array<number>) {
return axios.delete('/asset/exec-job/batch-delete', {
return axios.delete('/exec/exec-job/batch-delete', {
params: { idList },
paramsSerializer: params => {
return qs.stringify(params, { arrayFormat: 'comma' });
@@ -149,5 +156,5 @@ export function batchDeleteExecJob(idList: Array<number>) {
* 手动触发计划任务
*/
export function triggerExecJob(id: number) {
return axios.post('/asset/exec-job/trigger', { id });
return axios.post('/exec/exec-job/trigger', { id });
}

View File

@@ -52,49 +52,56 @@ export interface ExecTemplateQueryResponse extends TableData {
* 创建执行模板
*/
export function createExecTemplate(request: ExecTemplateCreateRequest) {
return axios.post('/asset/exec-template/create', request);
return axios.post('/exec/exec-template/create', request);
}
/**
* 更新执行模板
*/
export function updateExecTemplate(request: ExecTemplateUpdateRequest) {
return axios.put('/asset/exec-template/update', request);
return axios.put('/exec/exec-template/update', request);
}
/**
* 查询执行模板
*/
export function getExecTemplate(id: number) {
return axios.get<ExecTemplateQueryResponse>('/asset/exec-template/get', { params: { id } });
return axios.get<ExecTemplateQueryResponse>('/exec/exec-template/get', { params: { id } });
}
/**
* 查询执行模板
*/
export function getExecTemplateWithAuthorized(id: number) {
return axios.get<ExecTemplateQueryResponse>('/asset/exec-template/get-with-authorized', { params: { id } });
return axios.get<ExecTemplateQueryResponse>('/exec/exec-template/get-with-authorized', { params: { id } });
}
/**
* 分页查询执行模板
*/
export function getExecTemplatePage(request: ExecTemplateQueryRequest) {
return axios.post<DataGrid<ExecTemplateQueryResponse>>('/asset/exec-template/query', request);
return axios.post<DataGrid<ExecTemplateQueryResponse>>('/exec/exec-template/query', request);
}
/**
* 查询执行模板数量
*/
export function getExecTemplateCount(request: ExecTemplateQueryRequest) {
return axios.post<number>('/exec/exec-template/count', request);
}
/**
* 删除执行模板
*/
export function deleteExecTemplate(id: number) {
return axios.delete('/asset/exec-template/delete', { params: { id } });
return axios.delete('/exec/exec-template/delete', { params: { id } });
}
/**
* 批量删除执行模板
*/
export function batchDeleteExecTemplate(idList: Array<number>) {
return axios.delete('/asset/exec-template/batch-delete', {
return axios.delete('/exec/exec-template/batch-delete', {
params: { idList },
paramsSerializer: params => {
return qs.stringify(params, { arrayFormat: 'comma' });

View File

@@ -110,48 +110,48 @@ export interface UploadTaskStatusResponse extends TableData {
* 创建上传任务
*/
export function createUploadTask(request: UploadTaskCreateRequest) {
return axios.post<UploadTaskCreateResponse>('/asset/upload-task/create', request);
return axios.post<UploadTaskCreateResponse>('/exec/upload-task/create', request);
}
/**
* 创建上传任务
*/
export function startUploadTask(id: number) {
return axios.post('/asset/upload-task/start', { id });
return axios.post('/exec/upload-task/start', { id });
}
/**
* 创建上传任务
*/
export function cancelUploadTask(id: number, failed: boolean) {
return axios.post('/asset/upload-task/cancel', { id, failed });
return axios.post('/exec/upload-task/cancel', { id, failed });
}
/**
* 查询上传任务
*/
export function getUploadTask(id: number) {
return axios.get<UploadTaskQueryResponse>('/asset/upload-task/get', { params: { id } });
return axios.get<UploadTaskQueryResponse>('/exec/upload-task/get', { params: { id } });
}
/**
* 分页查询上传任务
*/
export function getUploadTaskPage(request: UploadTaskQueryRequest) {
return axios.post<DataGrid<UploadTaskQueryResponse>>('/asset/upload-task/query', request);
return axios.post<DataGrid<UploadTaskQueryResponse>>('/exec/upload-task/query', request);
}
/**
* 查询上传任务状态
*/
export function getUploadTaskStatus(idList: Array<number>, queryFiles: boolean) {
return axios.get<Array<UploadTaskStatusResponse>>('/asset/upload-task/status', {
return axios.get<Array<UploadTaskStatusResponse>>('/exec/upload-task/status', {
params: { idList, queryFiles },
promptBizErrorMessage: false,
promptRequestErrorMessage: false,
paramsSerializer: params => {
return qs.stringify(params, { arrayFormat: 'comma' });
}
},
});
}
@@ -159,14 +159,14 @@ export function getUploadTaskStatus(idList: Array<number>, queryFiles: boolean)
* 删除上传任务
*/
export function deleteUploadTask(id: number) {
return axios.delete('/asset/upload-task/delete', { params: { id } });
return axios.delete('/exec/upload-task/delete', { params: { id } });
}
/**
* 批量删除上传任务
*/
export function batchDeleteUploadTask(idList: Array<number>) {
return axios.delete('/asset/upload-task/batch-delete', {
return axios.delete('/exec/upload-task/batch-delete', {
params: { idList },
paramsSerializer: params => {
return qs.stringify(params, { arrayFormat: 'comma' });
@@ -178,14 +178,14 @@ export function batchDeleteUploadTask(idList: Array<number>) {
* 查询批量上传任务数量
*/
export function getUploadTaskCount(request: UploadTaskQueryRequest) {
return axios.post<number>('/asset/upload-task/count', request);
return axios.post<number>('/exec/upload-task/count', request);
}
/**
* 清空查询批量上传任务
* 清空批量上传任务
*/
export function clearUploadTask(request: UploadTaskClearRequest) {
return axios.post<number>('/asset/upload-task/clear', request, {
return axios.post<number>('/exec/upload-task/clear', request, {
timeout: 60000,
});
}

View File

@@ -1,26 +1,9 @@
import type { LineSingleChartData } from '@/types/global';
import type { TerminalConnectLogQueryResponse } from '@/api/asset/terminal-connect-log';
import type { ExecLogQueryResponse } from '@/api/exec/exec-log';
import type { PieChartData } from '@/types/global';
import axios from 'axios';
/**
* 资产模块工作台响应
* 查询主机类型图表
*/
export interface AssetWorkplaceStatisticsResponse {
execJobCount: number;
todayTerminalConnectCount: number;
todayExecCommandCount: number;
weekTerminalConnectCount: number;
weekExecCommandCount: number;
execCommandChart: LineSingleChartData;
terminalConnectChart: LineSingleChartData;
terminalConnectList: Array<TerminalConnectLogQueryResponse>;
execLogList: Array<ExecLogQueryResponse>;
}
/**
* 查询资产模块工作台统计信息
*/
export function getAssetWorkplaceStatisticsData() {
return axios.get<AssetWorkplaceStatisticsResponse>('/asset/statistics/get-workplace');
export function getHostTypeChart() {
return axios.get<PieChartData>('/asset/statistics/host-type-chart');
}

View File

@@ -0,0 +1,21 @@
import type { LineSingleChartData } from '@/types/global';
import type { ExecLogQueryResponse } from '@/api/exec/exec-log';
import axios from 'axios';
/**
* 执行模块工作台响应
*/
export interface ExecWorkplaceStatisticsResponse {
execJobCount: number;
todayExecCommandCount: number;
weekExecCommandCount: number;
execCommandChart: LineSingleChartData;
execLogList: Array<ExecLogQueryResponse>;
}
/**
* 查询执行模块工作台统计信息
*/
export function getExecWorkplaceStatisticsData() {
return axios.get<ExecWorkplaceStatisticsResponse>('/exec/statistics/get-workplace');
}

View File

@@ -0,0 +1,23 @@
import type { LineSingleChartData } from '@/types/global';
import type { TerminalConnectLogQueryResponse } from '@/api/terminal/terminal-connect-log';
import axios from 'axios';
/**
* 终端模块工作台响应
*/
export interface TerminalWorkplaceStatisticsResponse {
todayTerminalConnectCount: number;
todayTerminalCommandCount: number;
weekTerminalConnectCount: number;
weekTerminalCommandCount: number;
terminalConnectChart: LineSingleChartData;
terminalCommandChart: LineSingleChartData;
terminalConnectList: Array<TerminalConnectLogQueryResponse>;
}
/**
* 查询终端模块工作台统计信息
*/
export function getTerminalWorkplaceStatisticsData() {
return axios.get<TerminalWorkplaceStatisticsResponse>('/terminal/statistics/get-workplace');
}

View File

@@ -1,4 +1,4 @@
import type { DataGrid, Options, OrderDirection, Pagination } from '@/types/global';
import type { DataGrid, OrderDirection, Options, Pagination } from '@/types/global';
import type { TableData } from '@arco-design/web-vue';
import axios from 'axios';
import qs from 'query-string';

View File

@@ -28,27 +28,27 @@ export interface CommandSnippetGroupQueryResponse {
*
*/
export function createCommandSnippetGroup(request: CommandSnippetGroupCreateRequest) {
return axios.post('/asset/command-snippet-group/create', request);
return axios.post('/terminal/command-snippet-group/create', request);
}
/**
*
*/
export function updateCommandSnippetGroup(request: CommandSnippetGroupUpdateRequest) {
return axios.put('/asset/command-snippet-group/update', request);
return axios.put('/terminal/command-snippet-group/update', request);
}
/**
*
*/
export function getCommandSnippetGroupList() {
return axios.get<Array<CommandSnippetGroupQueryResponse>>('/asset/command-snippet-group/list');
return axios.get<Array<CommandSnippetGroupQueryResponse>>('/terminal/command-snippet-group/list');
}
/**
*
*/
export function deleteCommandSnippetGroup(id: number) {
return axios.delete('/asset/command-snippet-group/delete', { params: { id } });
return axios.delete('/terminal/command-snippet-group/delete', { params: { id } });
}

View File

@@ -43,26 +43,26 @@ export interface CommandSnippetWrapperResponse {
*
*/
export function createCommandSnippet(request: CommandSnippetCreateRequest) {
return axios.post('/asset/command-snippet/create', request);
return axios.post('/terminal/command-snippet/create', request);
}
/**
*
*/
export function updateCommandSnippet(request: CommandSnippetUpdateRequest) {
return axios.put('/asset/command-snippet/update', request);
return axios.put('/terminal/command-snippet/update', request);
}
/**
*
*/
export function getCommandSnippetList() {
return axios.get<CommandSnippetWrapperResponse>('/asset/command-snippet/list');
return axios.get<CommandSnippetWrapperResponse>('/terminal/command-snippet/list');
}
/**
*
*/
export function deleteCommandSnippet(id: number) {
return axios.delete('/asset/command-snippet/delete', { params: { id } });
return axios.delete('/terminal/command-snippet/delete', { params: { id } });
}

View File

@@ -28,27 +28,27 @@ export interface PathBookmarkGroupQueryResponse {
*
*/
export function createPathBookmarkGroup(request: PathBookmarkGroupCreateRequest) {
return axios.post('/asset/path-bookmark-group/create', request);
return axios.post('/terminal/path-bookmark-group/create', request);
}
/**
*
*/
export function updatePathBookmarkGroup(request: PathBookmarkGroupUpdateRequest) {
return axios.put('/asset/path-bookmark-group/update', request);
return axios.put('/terminal/path-bookmark-group/update', request);
}
/**
*
*/
export function getPathBookmarkGroupList() {
return axios.get<Array<PathBookmarkGroupQueryResponse>>('/asset/path-bookmark-group/list');
return axios.get<Array<PathBookmarkGroupQueryResponse>>('/terminal/path-bookmark-group/list');
}
/**
*
*/
export function deletePathBookmarkGroup(id: number) {
return axios.delete('/asset/path-bookmark-group/delete', { params: { id } });
return axios.delete('/terminal/path-bookmark-group/delete', { params: { id } });
}

View File

@@ -45,26 +45,26 @@ export interface PathBookmarkWrapperResponse {
*
*/
export function createPathBookmark(request: PathBookmarkCreateRequest) {
return axios.post('/asset/path-bookmark/create', request);
return axios.post('/terminal/path-bookmark/create', request);
}
/**
*
*/
export function updatePathBookmark(request: PathBookmarkUpdateRequest) {
return axios.put('/asset/path-bookmark/update', request);
return axios.put('/terminal/path-bookmark/update', request);
}
/**
*
*/
export function getPathBookmarkList() {
return axios.get<PathBookmarkWrapperResponse>('/asset/path-bookmark/list');
return axios.get<PathBookmarkWrapperResponse>('/terminal/path-bookmark/list');
}
/**
*
*/
export function deletePathBookmark(id: number) {
return axios.delete('/asset/path-bookmark/delete', { params: { id } });
return axios.delete('/terminal/path-bookmark/delete', { params: { id } });
}

View File

@@ -46,6 +46,7 @@ export interface TerminalConnectLogQueryResponse extends TableData {
*/
export interface TerminalConnectLogExtra {
traceId: string;
channel: string;
channelId: string;
sessionId: string;
address: string;
@@ -58,21 +59,21 @@ export interface TerminalConnectLogExtra {
*
*/
export function getTerminalConnectLogPage(request: TerminalConnectLogQueryRequest) {
return axios.post<DataGrid<TerminalConnectLogQueryResponse>>('/asset/terminal-connect-log/query', request);
return axios.post<DataGrid<TerminalConnectLogQueryResponse>>('/terminal/terminal-connect-log/query', request);
}
/**
*
*/
export function getTerminalConnectSessions(request: TerminalConnectLogQueryRequest) {
return axios.post<Array<TerminalConnectLogQueryResponse>>('/asset/terminal-connect-log/sessions', request);
return axios.post<Array<TerminalConnectLogQueryResponse>>('/terminal/terminal-connect-log/sessions', request);
}
/**
*
*/
export function getLatestConnectHostId(type: string, limit: number) {
return axios.post<Array<number>>('/asset/terminal-connect-log/latest-connect', {
return axios.post<Array<number>>('/terminal/terminal-connect-log/latest-connect', {
type,
limit
});
@@ -82,7 +83,7 @@ export function getLatestConnectHostId(type: string, limit: number) {
*
*/
export function deleteTerminalConnectLog(idList: Array<number>) {
return axios.delete('/asset/terminal-connect-log/delete', {
return axios.delete('/terminal/terminal-connect-log/delete', {
params: { idList },
paramsSerializer: params => {
return qs.stringify(params, { arrayFormat: 'comma' });
@@ -94,14 +95,14 @@ export function deleteTerminalConnectLog(idList: Array<number>) {
*
*/
export function getTerminalConnectLogCount(request: TerminalConnectLogQueryRequest) {
return axios.post<number>('/asset/terminal-connect-log/count', request);
return axios.post<number>('/terminal/terminal-connect-log/count', request);
}
/**
*
*/
export function clearTerminalConnectLog(request: TerminalConnectLogClearRequest) {
return axios.post<number>('/asset/terminal-connect-log/clear', request, {
return axios.post<number>('/terminal/terminal-connect-log/clear', request, {
timeout: 60000,
});
}
@@ -110,5 +111,5 @@ export function clearTerminalConnectLog(request: TerminalConnectLogClearRequest)
*
*/
export function hostForceOffline(request: TerminalConnectLogQueryRequest) {
return axios.put('/asset/terminal-connect-log/force-offline', request);
return axios.put('/terminal/terminal-connect-log/force-offline', request);
}

View File

@@ -48,14 +48,21 @@ export interface TerminalSftpLogExtra {
* SFTP
*/
export function getTerminalSftpLogPage(request: TerminalSftpLogQueryRequest) {
return axios.post<DataGrid<TerminalSftpLogQueryResponse>>('/asset/terminal-sftp/query-log', request);
return axios.post<DataGrid<TerminalSftpLogQueryResponse>>('/terminal/terminal-sftp/query-log', request);
}
/**
* SFTP
*/
export function getTerminalSftpLogCount(request: TerminalSftpLogQueryRequest) {
return axios.post<number>('/terminal/terminal-sftp/log-count', request);
}
/**
* SFTP
*/
export function deleteTerminalSftpLog(idList: Array<number>) {
return axios.delete('/asset/terminal-sftp/delete-log', {
return axios.delete('/terminal/terminal-sftp/delete-log', {
params: { idList },
paramsSerializer: params => {
return qs.stringify(params, { arrayFormat: 'comma' });
@@ -67,7 +74,7 @@ export function deleteTerminalSftpLog(idList: Array<number>) {
* SFTP
*/
export function getSftpFileContent(token: string) {
return axios.get<string>('/asset/terminal-sftp/get-content', {
return axios.get<string>('/terminal/terminal-sftp/get-content', {
unwrap: true,
params: { token },
timeout: 60000
@@ -81,7 +88,7 @@ export function setSftpFileContent(token: string, content: string) {
const formData = new FormData();
formData.append('token', token);
formData.append('file', new File([content], Date.now() + '', { type: 'text/plain' }));
return axios.post<boolean>('/asset/terminal-sftp/set-content', formData, {
return axios.post<boolean>('/terminal/terminal-sftp/set-content', formData, {
timeout: 60000,
headers: {
'Content-Type': 'multipart/form-data'
@@ -93,5 +100,5 @@ export function setSftpFileContent(token: string, content: string) {
*
*/
export function getDownloadTransferUrl(channelId: string, transferToken: string) {
return `${httpBaseUrl}/asset/terminal-sftp/download?channelId=${channelId}&transferToken=${transferToken}`;
return `${httpBaseUrl}/terminal/terminal-sftp/download?channelId=${channelId}&transferToken=${transferToken}`;
}

View File

@@ -0,0 +1,46 @@
import type { TerminalTheme } from '@/views/terminal/interfaces';
import axios from 'axios';
import { createAppWebSocket } from '@/utils/http';
// 终端访问请求
export interface TerminalAccessRequest {
hostId?: number;
connectType?: string;
extra?: Record<string, any>;
}
/**
* 获取主机终端主题
*/
export function getTerminalThemes() {
return axios.get<Array<TerminalTheme>>('/terminal/terminal/themes');
}
/**
* 获取主机终端 accessToken
*/
export function getTerminalAccessToken(request: TerminalAccessRequest) {
return axios.post<string>('/terminal/terminal/access', request);
}
/**
* 获取主机终端 transferToken
*/
export function getTerminalTransferToken() {
return axios.get<string>('/terminal/terminal/transfer');
}
/**
* 打开主机终端 websocket
*/
export const openTerminalAccessChannel = (protocol: string, accessToken: string) => {
return createAppWebSocket(`/terminal/access/${protocol}/${accessToken}`);
};
/**
* 打开主机传输 websocket
*/
export const openTerminalTransferChannel = (accessToken: string) => {
return createAppWebSocket(`/terminal/transfer/${accessToken}`);
};

View File

@@ -19,14 +19,6 @@ export interface RoleUpdateRequest extends RoleCreateRequest {
id?: number;
}
/**
* 角色 分配绑定请求
*/
export interface RoleGrantMenuRequest extends RoleCreateRequest {
roleId: number;
menuIdList: Array<number>;
}
/**
* 角色查询请求
*/
@@ -38,6 +30,14 @@ export interface RoleQueryRequest extends Pagination, OrderDirection {
description?: string;
}
/**
* 角色 分配绑定请求
*/
export interface RoleGrantMenuRequest extends RoleCreateRequest {
roleId: number;
menuIdList: Array<number>;
}
/**
* 角色查询响应
*/

View File

@@ -34,11 +34,9 @@ export interface UserQueryRequest extends Pagination, OrderDirection {
username?: string;
password?: string;
nickname?: string;
avatar?: string;
mobile?: string;
email?: string;
status?: number;
lastLoginTime?: string;
description?: string;
}
@@ -158,6 +156,13 @@ export function getUserPage(request: UserQueryRequest) {
return axios.post<DataGrid<UserQueryResponse>>('/infra/system-user/query', request);
}
/**
* 查询用户数量
*/
export function getUserCount(request: UserQueryRequest) {
return axios.post<number>('/infra/system-user/count', request);
}
/**
* 通过 id 删除用户
*/

View File

@@ -205,6 +205,10 @@ body {
padding-bottom: 8px;
}
.pb12 {
padding-bottom: 12px;
}
.px8 {
padding-left: 8px;
padding-right: 8px;

View File

@@ -1,7 +1,7 @@
// 亮色主题配色常量
body {
--color-bg-header: #232323;
--color-bg-sidebar: #EBEBEB;
--color-bg-sidebar: #E3E6E9;
--color-bg-panel: var(--color-bg-sidebar);
--color-bg-content: #FEFEFE;
--color-sidebar-icon: #737070;
@@ -17,7 +17,7 @@ body {
--color-bg-panel-tabs: var(--color-bg-panel);
--color-bg-panel-tabs-active: #F9F9F9;
--color-bg-panel-icon-1: #F5F5F5;
--color-bg-panel-bar: #F0F0F0;
--color-bg-panel-bar: #F1F2F3;
--color-panel-text-1: var(--color-content-text-1);
--color-panel-text-2: var(--color-content-text-3);
--color-panel-gradient-start: rgba(218, 218, 218, 1);
@@ -32,12 +32,14 @@ body {
--search-bg-icon-hover-focus: rgba(12, 12, 12, .08);
--search-bg-icon-selected: rgba(12, 12, 12, .06);
--search-bg-icon-selected-focus: rgba(12, 12, 12, .10);
--color-bg-rdp-toolbar: rgba(255, 255, 255, .4);
--color-bg-rdp-toolbar-hover: rgba(255, 255, 255, .6);
}
// 暗色主题配色常量
body[terminal-theme='dark'] {
--color-bg-header: #232323;
--color-bg-sidebar: #2C2E31;
--color-bg-sidebar: #2A2A2A;
--color-bg-panel: var(--color-bg-sidebar);
--color-bg-content: #1A1B1C;
--color-sidebar-icon: #C3C6C9;
@@ -53,7 +55,7 @@ body[terminal-theme='dark'] {
--color-bg-panel-tabs: var(--color-bg-panel);
--color-bg-panel-tabs-active: #383838;
--color-bg-panel-icon-1: var(--color-bg-panel-tabs-active);
--color-bg-panel-bar: #323538;
--color-bg-panel-bar: #343434;
--color-panel-text-1: var(--color-content-text-1);
--color-panel-text-2: var(--color-content-text-3);
--color-panel-gradient-start: rgba(38, 38, 38, 1);

View File

@@ -18,7 +18,7 @@ export const copy = async (value: string | undefined, tips: string | boolean = `
};
// 获取剪切板内容
export const readText = () => {
export const readText = (tips: boolean = true) => {
if (navigator.clipboard) {
return navigator.clipboard.readText();
} else {
@@ -30,7 +30,7 @@ export const readText = () => {
textarea.select();
try {
const success = document.execCommand('paste');
if (!success) {
if (!success && tips) {
Message.error('当前环境无法读取剪切板内容');
}
resolve(textarea.value);

View File

@@ -1,31 +1,37 @@
import type { FavoriteItem } from '@/types/global';
import type { FavoriteType } from '@/api/meta/favorite';
import { addFavorite, cancelFavorite } from '@/api/meta/favorite';
import { ref } from 'vue';
export default function useFavorite(type: FavoriteType) {
const loading = ref(false);
const toggle = async (record: any, id: number, cancelField = 'favorite') => {
const toggle = async <T extends FavoriteItem>(record: T, id: number) => {
// 防抖
if (loading.value) {
return;
}
const request = { relId: id, type };
try {
loading.value = true;
if (record[cancelField]) {
if (record.favorite) {
// 取消收藏
await cancelFavorite(request);
record[cancelField] = false;
record.favorite = false;
} else {
// 添加收藏
await addFavorite(request);
record[cancelField] = true;
record.favorite = true;
}
} catch (e) {
} finally {
loading.value = false;
}
};
return {
loading,
toggle
};
}

View File

@@ -0,0 +1,26 @@
import { ref } from 'vue';
import { Message } from '@arco-design/web-vue';
export default function useLimit(limit = 500) {
const last = ref(0);
const checkLimited = (tips: string | boolean = true) => {
const now = Date.now();
if (now > last.value + limit) {
last.value = now;
return true;
} else {
if (tips === true) {
Message.error('操作频率过快, 请稍后再试');
} else if (tips) {
Message.error(tips);
}
return false;
}
};
return {
last,
checkLimited,
};
}

View File

@@ -1,27 +1,29 @@
import type { AppRouteRecordRaw } from '../types';
import { DEFAULT_LAYOUT } from '../base';
const ASSET_AUDIT: AppRouteRecordRaw = {
name: 'assetAuditModule',
path: '/asset-audit-module',
component: DEFAULT_LAYOUT,
children: [
{
name: 'connectLog',
path: '/audit/connect-log',
component: () => import('@/views/asset-audit/connect-log/index.vue'),
},
{
name: 'connectSession',
path: '/audit/connect-session',
component: () => import('@/views/asset-audit/connect-session/index.vue'),
},
{
name: 'sftpLog',
path: '/audit/sftp-log',
component: () => import('@/views/asset-audit/sftp-log/index.vue'),
},
],
};
const ASSET_AUDIT: AppRouteRecordRaw[] = [
{
name: 'assetAuditModule',
path: '/asset-audit-module',
component: DEFAULT_LAYOUT,
children: [
{
name: 'connectLog',
path: '/audit/connect-log',
component: () => import('@/views/asset-audit/connect-log/index.vue'),
},
{
name: 'connectSession',
path: '/audit/connect-session',
component: () => import('@/views/asset-audit/connect-session/index.vue'),
},
{
name: 'sftpLog',
path: '/audit/sftp-log',
component: () => import('@/views/asset-audit/sftp-log/index.vue'),
},
],
},
];
export default ASSET_AUDIT;

View File

@@ -43,7 +43,8 @@ const EXEC: Array<AppRouteRecordRaw> = [
component: () => import('@/views/exec/exec-template/index.vue'),
},
],
}, {
},
{
name: 'execFullModule',
path: '/exec-full-module',
component: FULL_LAYOUT,

View File

@@ -1,15 +1,15 @@
import type { AppRouteRecordRaw } from '../types';
import { FULL_LAYOUT } from '../base';
const HOST: AppRouteRecordRaw = {
name: 'hostModule',
path: '/host-module',
const TERMINAL: AppRouteRecordRaw = {
name: 'terminalModule',
path: '/terminal-module',
component: FULL_LAYOUT,
children: [
{
name: 'terminal',
path: '/terminal',
component: () => import('@/views/host/terminal/index.vue'),
component: () => import('@/views/terminal/index.vue'),
meta: {
noAffix: true
}
@@ -17,4 +17,4 @@ const HOST: AppRouteRecordRaw = {
],
};
export default HOST;
export default TERMINAL;

View File

@@ -1,5 +1,5 @@
import type { NavigationGuard, RouteMeta } from 'vue-router';
import { defineComponent } from 'vue';
import type { defineComponent } from 'vue';
export type Component<T = any> =
| ReturnType<typeof defineComponent>

View File

@@ -2,12 +2,13 @@ import type { CacheState, CacheType } from './types';
import type { AxiosResponse } from 'axios';
import type { TagType } from '@/api/meta/tag';
import { getTagList } from '@/api/meta/tag';
import type { HostGroupQueryResponse } from '@/api/asset/host-group';
import { getHostGroupTree } from '@/api/asset/host-group';
import { getSystemAggregateSetting } from '@/api/system/setting';
import type { HostType } from '@/api/asset/host';
import { getHostList } from '@/api/asset/host';
import type { PreferenceType } from '@/api/user/preference';
import { getPreference } from '@/api/user/preference';
import type { HostGroupQueryResponse } from '@/api/asset/host-group';
import { getHostGroupTree } from '@/api/asset/host-group';
import usePermission from '@/hooks/permission';
import { defineStore } from 'pinia';
import { flatNodes } from '@/utils/tree';
@@ -18,12 +19,11 @@ import { getHostKeyList } from '@/api/asset/host-key';
import { getHostIdentityList } from '@/api/asset/host-identity';
import { getMenuList } from '@/api/system/menu';
import { getCurrentAuthorizedHost, getCurrentAuthorizedHostIdentity, getCurrentAuthorizedHostKey } from '@/api/asset/asset-authorized-data';
import { getCommandSnippetGroupList } from '@/api/asset/command-snippet-group';
import { getCommandSnippetGroupList } from '@/api/terminal/command-snippet-group';
import { getExecJobList } from '@/api/exec/exec-job';
import { getPathBookmarkGroupList } from '@/api/asset/path-bookmark-group';
import { getCommandSnippetList } from '@/api/asset/command-snippet';
import { getPathBookmarkList } from '@/api/asset/path-bookmark';
import { getSystemAggregateSetting } from '@/api/system/setting';
import { getPathBookmarkGroupList } from '@/api/terminal/path-bookmark-group';
import { getCommandSnippetList } from '@/api/terminal/command-snippet';
import { getPathBookmarkList } from '@/api/terminal/path-bookmark';
export default defineStore('cache', {
state: (): CacheState => ({}),
@@ -170,7 +170,7 @@ export default defineStore('cache', {
// 获取执行计划列表
async loadExecJobs(force = false) {
return await this.load('execJob', getExecJobList, ['asset:exec-job:query'], force);
return await this.load('execJob', getExecJobList, ['exec:exec-job:query'], force);
},
// 加载偏好

View File

@@ -7,7 +7,8 @@ export type CacheType = 'users' | 'menus' | 'roles'
| 'authorizedHostKeys' | 'authorizedHostIdentities'
| 'commandSnippetGroups' | 'pathBookmarkGroups'
| 'commandSnippets' | 'pathBookmarks'
| '*_Tags' | 'preference_*' | 'system_setting'
| 'system_setting'
| '*_Tags' | 'preference_*'
| string
export interface CacheState {

View File

@@ -4,6 +4,8 @@ import type { Options } from '@/types/global';
import { defineStore } from 'pinia';
import { getDictValueList } from '@/api/system/dict-value';
export const ALL_OPTION: Options = { label: '全部', value: '' };
export default defineStore('dict', {
state: (): DictState => ({}),
@@ -25,13 +27,41 @@ export default defineStore('dict', {
},
// 获取字典选项
toOptions(key: string) {
return this.$state[key];
toOptions(key: string, firstOption: boolean | Record<string, any> = false): Options[] {
if (firstOption === true) {
return [{ ...ALL_OPTION }, ...this.$state[key]];
} else if (firstOption) {
return [{ ...ALL_OPTION, ...firstOption }, ...this.$state[key]];
} else {
return this.$state[key];
}
},
// 转为 unref 的字典选项
toUnrefOptions(key: string, firstOption: boolean | Record<string, any> = false): Options[] {
return this.toOptions(key, firstOption)
.map(s => {
return { ...s };
});
},
// 获取字典选项
toRadioOptions(key: string) {
return this.$state[key] as RadioOption[];
toRadioOptions(key: string, firstOption: boolean | Record<string, any> = false): RadioOption[] {
if (firstOption === true) {
return [{ ...ALL_OPTION }, ...this.$state[key]] as RadioOption[];
} else if (firstOption) {
return [{ ...ALL_OPTION, ...firstOption }, ...this.$state[key]] as RadioOption[];
} else {
return this.$state[key] as RadioOption[];
}
},
// 转为 unref 的字典选项
toUnrefRadioOptions(key: string, firstOption: boolean | Record<string, any> = false): RadioOption[] {
return this.toRadioOptions(key, firstOption)
.map(s => {
return { ...s };
});
},
// 获取字典值

View File

@@ -1,31 +1,40 @@
import type {
TerminalActionBarSetting,
TerminalDisplaySetting,
TerminalInteractSetting,
TerminalPluginsSetting,
TerminalPreference,
TerminalRdpActionBarSetting,
TerminalRdpGraphSetting,
TerminalSessionSetting,
TerminalShortcutSetting,
TerminalSshActionBarSetting,
TerminalSshDisplaySetting,
TerminalState
} from './types';
import type { ISshSession, ITerminalSession, PanelSessionTabType, TerminalPanelTabItem } from '@/views/host/terminal/types/define';
import type {
IDomViewportHandler,
ISshSession,
ITerminalSession,
TerminalSessionTabItem,
TerminalSessionType,
TerminalTheme,
TerminalThemeSchema
} from '@/views/terminal/interfaces';
import type { AuthorizedHostQueryResponse } from '@/api/asset/asset-authorized-data';
import type { HostQueryResponse } from '@/api/asset/host';
import type { TerminalTheme, TerminalThemeSchema } from '@/api/asset/terminal';
import { getTerminalThemes } from '@/api/asset/terminal';
import { markRaw } from 'vue';
import { getTerminalThemes } from '@/api/terminal/terminal';
import { defineStore } from 'pinia';
import { getPreference, updatePreference } from '@/api/user/preference';
import { getLatestConnectHostId } from '@/api/asset/terminal-connect-log';
import { getLatestConnectHostId } from '@/api/terminal/terminal-connect-log';
import { useCacheStore } from '@/store';
import { nextId } from '@/utils';
import { isObject } from '@/utils/is';
import { Message } from '@arco-design/web-vue';
import { useCacheStore } from '@/store';
import { PanelSessionType, TerminalTabs } from '@/views/host/terminal/types/const';
import TerminalTabManager from '@/views/host/terminal/handler/terminal-tab-manager';
import TerminalSessionManager from '@/views/host/terminal/handler/terminal-session-manager';
import TerminalPanelManager from '@/views/host/terminal/handler/terminal-panel-manager';
import SftpTransferManager from '@/views/host/terminal/handler/sftp-transfer-manager';
import { TerminalSessionTypes, TerminalTabs } from '@/views/terminal/types/const';
import TerminalTabManager from '@/views/terminal/service/tab/terminal-tab-manager';
import TerminalPanelManager from '@/views/terminal/service/tab/terminal-panel-manager';
import TerminalSessionManager from '@/views/terminal/service/session/terminal-session-manager';
import SftpTransferManager from '@/views/terminal/service/transfer/sftp-transfer-manager';
// 终端偏好项
export const TerminalPreferenceItem = {
@@ -33,10 +42,14 @@ export const TerminalPreferenceItem = {
NEW_CONNECTION_TYPE: 'newConnectionType',
// 终端主题
THEME: 'theme',
// 显示设置
DISPLAY_SETTING: 'displaySetting',
// 操作栏设置
ACTION_BAR_SETTING: 'actionBarSetting',
// ssh 显示设置
SSH_DISPLAY_SETTING: 'sshDisplaySetting',
// rdp 图形化设置
RDP_GRAPH_SETTING: 'rdpGraphSetting',
// ssh 操作栏设置
SSH_ACTION_BAR_SETTING: 'sshActionBarSetting',
// rdp 操作栏设置
RDP_ACTION_BAR_SETTING: 'rdpActionBarSetting',
// 右键菜单设置
RIGHT_MENU_SETTING: 'rightMenuSetting',
// 交互设置
@@ -56,8 +69,10 @@ export default defineStore('terminal', {
theme: {
schema: {} as TerminalThemeSchema
} as TerminalTheme,
displaySetting: {} as TerminalDisplaySetting,
actionBarSetting: {} as TerminalActionBarSetting,
sshDisplaySetting: {} as TerminalSshDisplaySetting,
rdpGraphSetting: {} as TerminalRdpGraphSetting,
sshActionBarSetting: {} as TerminalSshActionBarSetting,
rdpActionBarSetting: {} as TerminalRdpActionBarSetting,
rightMenuSetting: [],
interactSetting: {} as TerminalInteractSetting,
pluginsSetting: {} as TerminalPluginsSetting,
@@ -147,7 +162,10 @@ export default defineStore('terminal', {
},
// 打开会话
openSession(record: HostQueryResponse, type: PanelSessionTabType, panelIndex: number = 0) {
openSession(record: HostQueryResponse, type: TerminalSessionType, panelIndex: number | undefined = undefined) {
if (panelIndex === undefined) {
panelIndex = this.panelManager.active;
}
// 添加到最近连接
this.hosts.latestHosts = [...new Set([record.id, ...this.hosts.latestHosts])];
// 切换到终端面板页面
@@ -163,39 +181,41 @@ export default defineStore('terminal', {
? Math.max(...seqArr) + 1
: 1;
// 打开 tab
const sessionId = nextId(10);
this.panelManager.getPanel(panelIndex).openTab({
key: sessionId,
sessionId,
key: nextId(),
panelIndex: panelIndex,
seq: nextSeq,
name: record.alias || record.name,
title: `(${nextSeq}) ${record.alias || record.name}`,
hostId: record.id,
address: record.address,
color: record.color,
icon: type.icon,
type: type.type
type: type.type,
extra: record.extra,
});
},
// 重新打开会话
async reOpenSession(sessionId: string, panelIndex: number = 0) {
async reOpenSession(sessionKey: string) {
// 切换到终端面板页面
this.tabManager.openTab(TerminalTabs.TERMINAL_PANEL);
// 获取当前面板 tab 并且分配新的 sessionId
const panel = this.panelManager.getPanel(panelIndex);
const tab = panel.items.find(s => s.sessionId === sessionId);
// 获取当前面板 tab
const tab = this.panelManager.panels
.map(s => s.items)
.flat()
.find(s => s.key === sessionKey);
if (!tab) {
return;
}
const newSessionId = tab.sessionId = nextId(10);
// 添加到最近连接
this.hosts.latestHosts = [...new Set([tab.hostId, ...this.hosts.latestHosts])];
// 重新打开会话
await this.sessionManager.reOpenSession(sessionId, newSessionId);
await this.sessionManager.reOpenSession(sessionKey);
},
// 复制并且打开会话
copySession(item: TerminalPanelTabItem, panelIndex: number = 0) {
copySession(item: TerminalSessionTabItem, panelIndex: number) {
const host = this.hosts.hostList
.find(s => s.id === item.hostId);
if (host) {
@@ -207,83 +227,90 @@ export default defineStore('terminal', {
}
},
// 获取当前会话类型
getCurrentSessionType(tips: boolean = false) {
// 检查是否在终端面板
checkTerminalPanelActive(): boolean {
// 获取当前 activeTab
const activeTab = this.tabManager.active;
if (activeTab !== TerminalTabs.TERMINAL_PANEL.key) {
if (tips) {
Message.warning('请切换到终端标签页');
}
return;
Message.warning('请切换到终端标签页');
return false;
}
// 获取面板会话
const type = this.panelManager
return true;
},
// 获取当前会话类型
getCurrentSessionType() {
return this.panelManager
.getCurrentPanel()
.getCurrentTab()
?.type;
if (!type && tips) {
Message.warning(`请打开 ${type}`);
},
// 获取当前 domViewportHandler
getCurrentDomViewportHandler(): IDomViewportHandler | undefined {
// 获取当前会话
const session = this._getCurrentSession<ISshSession>();
if (!session) {
return;
}
return type;
return session as unknown as IDomViewportHandler;
},
// 获取当前会话
getCurrentSession<T extends ITerminalSession>(type: string, tips: boolean = false) {
getCurrentSession<T extends ITerminalSession>(type?: string, check: boolean = false) {
// 获取当前 activeTab
const activeTab = this.tabManager.active;
if (activeTab !== TerminalTabs.TERMINAL_PANEL.key) {
if (tips) {
Message.warning('请切换到终端标签页');
}
if (check && !this.checkTerminalPanelActive()) {
return;
}
// 获取当前会话
const session = this._getCurrentSession<T>(type);
if (!session && tips) {
Message.warning(`请打开 ${type}`);
if (!session && check) {
Message.warning(`请打开 ${type || '终端'}`);
return;
}
return session;
},
// 获取当前会话
_getCurrentSession<T extends ITerminalSession>(type: string): T | undefined {
_getCurrentSession<T extends ITerminalSession>(type?: string): T | undefined {
// 获取面板会话
const sessionTab = this.panelManager
.getCurrentPanel()
.getCurrentTab();
if (!sessionTab || sessionTab.type !== type) {
if (!sessionTab) {
return;
}
if (type && sessionTab.type !== type) {
return;
}
// 获取会话
return this.sessionManager.getSession<T>(sessionTab.sessionId);
return this.sessionManager.getSession<T>(sessionTab.key);
},
// 拼接命令到当前会话
appendCommandToCurrentSession(command: string, newLine: boolean = false) {
this.appendCommandToSession(this.getCurrentSession<ISshSession>(PanelSessionType.SSH.type, true), command, newLine);
appendCommandToCurrentSession(command: string, newLine: boolean = false, focus?: boolean) {
this.appendCommandToSession(this.getCurrentSession<ISshSession>(TerminalSessionTypes.SSH.type, true), command, newLine, focus);
},
// 拼接命令到会话
appendCommandToSession(session: ISshSession | undefined, command: string, newLine: boolean = false) {
appendCommandToSession(session: ISshSession | undefined, command: string, newLine: boolean = false, focus?: boolean) {
const handler = session?.handler;
if (handler && handler.enabledStatus('checkAppendMissing')) {
if (newLine) {
command = `${command}\r\n`;
}
handler.checkAppendMissing(command);
handler.checkAppendMissing(command, focus);
}
},
// 粘贴命令到会话
pasteCommandToSession(session: ISshSession | undefined, command: string, newLine: boolean = false) {
pasteCommandToSession(session: ISshSession | undefined, command: string, newLine: boolean = false, focus?: boolean) {
const handler = session?.handler;
if (handler && handler.enabledStatus('pasteOrigin')) {
if (newLine) {
command = `${command}\r\n`;
}
handler.pasteOrigin(command);
handler.pasteOrigin(command, focus);
}
},

View File

@@ -1,6 +1,5 @@
import type { ISftpTransferManager, ITerminalPanelManager, ITerminalSessionManager, ITerminalTabManager } from '@/views/host/terminal/types/define';
import type { ISftpTransferManager, ITerminalPanelManager, ITerminalSessionManager, ITerminalTabManager, TerminalTheme } from '@/views/terminal/interfaces';
import type { AuthorizedHostQueryResponse } from '@/api/asset/asset-authorized-data';
import type { TerminalTheme } from '@/api/asset/terminal';
export interface TerminalState {
preference: TerminalPreference;
@@ -16,8 +15,10 @@ export interface TerminalState {
export interface TerminalPreference {
newConnectionType: string;
theme: TerminalTheme;
displaySetting: TerminalDisplaySetting;
actionBarSetting: TerminalActionBarSetting;
sshDisplaySetting: TerminalSshDisplaySetting;
rdpGraphSetting: TerminalRdpGraphSetting;
sshActionBarSetting: TerminalSshActionBarSetting;
rdpActionBarSetting: TerminalRdpActionBarSetting;
rightMenuSetting: Array<string>,
interactSetting: TerminalInteractSetting;
pluginsSetting: TerminalPluginsSetting;
@@ -25,8 +26,8 @@ export interface TerminalPreference {
shortcutSetting: TerminalShortcutSetting;
}
// 显示设置
export interface TerminalDisplaySetting {
// SSH 显示设置
export interface TerminalSshDisplaySetting {
fontFamily?: string;
fontSize?: number;
lineHeight?: number;
@@ -37,9 +38,44 @@ export interface TerminalDisplaySetting {
cursorBlink?: boolean;
}
// 操作栏设置
export interface TerminalActionBarSetting {
// RDP 图形化设置
export interface TerminalRdpGraphSetting {
displaySize?: string;
displayWidth?: number;
displayHeight?: number;
enableAudioInput?: boolean;
enableAudioOutput?: boolean;
colorDepth?: number;
forceLossless?: boolean;
enableWallpaper?: boolean;
enableTheming?: boolean;
enableFontSmoothing?: boolean;
enableFullWindowDrag?: boolean;
enableDesktopComposition?: boolean;
enableMenuAnimations?: boolean;
disableBitmapCaching?: boolean;
disableOffscreenCaching?: boolean;
disableGlyphCaching?: boolean;
}
// SSH 操作栏设置
export interface TerminalSshActionBarSetting {
connectStatus?: boolean;
share?: boolean;
[key: string]: unknown;
}
// RDP 操作栏设置
export interface TerminalRdpActionBarSetting {
position?: string;
display?: boolean;
combinationKey?: boolean;
clipboard?: boolean;
upload?: boolean;
saveRdp?: boolean;
disconnect?: boolean;
close?: boolean;
[key: string]: unknown;
}

View File

@@ -31,6 +31,10 @@ export interface PostData {
url: string;
}
export interface FavoriteItem {
favorite: boolean;
}
export interface OrderDirection {
order?: number;
}
@@ -57,7 +61,25 @@ export interface DataGrid<T> {
export type TimeRanger = [string, string];
export interface StatisticsRangeRequest {
range: string;
startTime: number;
}
export interface LineSingleChartData {
x: string[];
data: Array<number>;
}
export interface LineChartData {
x: string[];
data: Record<string, Array<number>>;
}
export interface PieChartData {
data: Record<string, number>;
}
export interface BarSingleChartData {
data: Record<string, number>;
}

View File

@@ -1,242 +0,0 @@
// 终端协议
export interface Protocol {
type: string;
template: string[];
[key: string]: unknown;
}
// 终端输入消息内容
export interface InputPayload {
type?: string;
sessionId?: string;
[key: string]: unknown;
}
// 终端输出消息内容
export interface OutputPayload {
type: string;
sessionId: string;
[key: string]: string;
}
// 分隔符
export const SEPARATOR = '|';
// 输入协议
export const InputProtocol = {
// 主机连接检查
CHECK: {
type: 'ck',
template: ['type', 'sessionId', 'hostId', 'connectType']
},
// 连接主机
CONNECT: {
type: 'co',
template: ['type', 'sessionId', 'terminalType', 'cols', 'rows']
},
// 关闭连接
CLOSE: {
type: 'cl',
template: ['type', 'sessionId']
},
// ping
PING: {
type: 'p',
template: ['type']
},
// SSH 修改大小
SSH_RESIZE: {
type: 'rs',
template: ['type', 'sessionId', 'cols', 'rows']
},
// SSH 输入
SSH_INPUT: {
type: 'i',
template: ['type', 'sessionId', 'command']
},
// SFTP 文件列表
SFTP_LIST: {
type: 'ls',
template: ['type', 'sessionId', 'showHiddenFile', 'path']
},
// SFTP 创建文件夹
SFTP_MKDIR: {
type: 'mk',
template: ['type', 'sessionId', 'path']
},
// SFTP 创建文件
SFTP_TOUCH: {
type: 'to',
template: ['type', 'sessionId', 'path']
},
// SFTP 移动文件
SFTP_MOVE: {
type: 'mv',
template: ['type', 'sessionId', 'path', 'target']
},
// SFTP 删除文件
SFTP_REMOVE: {
type: 'rm',
template: ['type', 'sessionId', 'path']
},
// SFTP 修改文件权限
SFTP_CHMOD: {
type: 'cm',
template: ['type', 'sessionId', 'path', 'mod']
},
// SFTP 修改文件权限
SFTP_DOWNLOAD_FLAT_DIRECTORY: {
type: 'df',
template: ['type', 'sessionId', 'currentPath', 'path']
},
// SFTP 获取内容
SFTP_GET_CONTENT: {
type: 'gc',
template: ['type', 'sessionId', 'path']
},
// SFTP 修改内容
SFTP_SET_CONTENT: {
type: 'sc',
template: ['type', 'sessionId', 'path']
},
};
// 输出协议
export const OutputProtocol = {
// 主机连接检查
CHECK: {
type: 'ck',
template: ['type', 'sessionId', 'result', 'msg'],
processMethod: 'processCheck'
},
// 主机连接
CONNECT: {
type: 'co',
template: ['type', 'sessionId', 'result', 'msg'],
processMethod: 'processConnect'
},
// 主机连接关闭
CLOSE: {
type: 'cl',
template: ['type', 'sessionId', 'forceClose', 'msg'],
processMethod: 'processClose'
},
// pong
PONG: {
type: 'p',
template: ['type'],
processMethod: 'processPong'
},
// SSH 输出
SSH_OUTPUT: {
type: 'o',
template: ['type', 'sessionId', 'body'],
processMethod: 'processSshOutput'
},
// SFTP 文件列表
SFTP_LIST: {
type: 'ls',
template: ['type', 'sessionId', 'path', 'result', 'msg', 'body'],
processMethod: 'processSftpList'
},
// SFTP 创建文件夹
SFTP_MKDIR: {
type: 'mk',
template: ['type', 'sessionId', 'result', 'msg'],
processMethod: 'processSftpMkdir'
},
// SFTP 创建文件
SFTP_TOUCH: {
type: 'to',
template: ['type', 'sessionId', 'result', 'msg'],
processMethod: 'processSftpTouch'
},
// SFTP 移动文件
SFTP_MOVE: {
type: 'mv',
template: ['type', 'sessionId', 'result', 'msg'],
processMethod: 'processSftpMove'
},
// SFTP 删除文件
SFTP_REMOVE: {
type: 'rm',
template: ['type', 'sessionId', 'result', 'msg'],
processMethod: 'processSftpRemove'
},
// SFTP 修改文件权限
SFTP_CHMOD: {
type: 'cm',
template: ['type', 'sessionId', 'result', 'msg'],
processMethod: 'processSftpChmod'
},
// SFTP 修改文件权限
SFTP_DOWNLOAD_FLAT_DIRECTORY: {
type: 'df',
template: ['type', 'sessionId', 'currentPath', 'result', 'msg', 'body'],
processMethod: 'processDownloadFlatDirectory'
},
// SFTP 获取文件内容
SFTP_GET_CONTENT: {
type: 'gc',
template: ['type', 'sessionId', 'result', 'msg', 'token'],
processMethod: 'processSftpGetContent'
},
// SFTP 修改文件内容
SFTP_SET_CONTENT: {
type: 'sc',
template: ['type', 'sessionId', 'result', 'msg', 'token'],
processMethod: 'processSftpSetContent'
},
};
// 解析参数
export const parse = (payload: string) => {
const protocols = Object.values(OutputProtocol);
const useProtocol = protocols.find(p => payload.startsWith(p.type + SEPARATOR) || p.type === payload);
if (!useProtocol) {
return undefined;
}
const template = useProtocol.template;
const res = {} as OutputPayload;
let curr = 0;
let len = payload.length;
for (let i = 0, pl = template.length; i < pl; i++) {
if (i == pl - 1) {
// 最后一次
res[template[i]] = payload.substring(curr, len);
} else {
// 非最后一次
let tmp = '';
for (; curr < len; curr++) {
const c = payload.charAt(curr);
if (c == SEPARATOR) {
res[template[i]] = tmp;
curr++;
break;
} else {
tmp += c;
}
}
}
}
return res;
};
// 格式化参数
export const format = (protocol: Protocol, payload: InputPayload | OutputPayload) => {
payload.type = protocol.type;
return protocol.template
.map(i => getPayloadValueString(payload[i]))
.join(SEPARATOR);
};
// 获取默认值
export const getPayloadValueString = (value: unknown): any => {
if (value === undefined || value === null) {
return '';
}
return value;
};

View File

@@ -14,7 +14,7 @@ export const isStandaloneMode = (() => (
// http base url
export const httpBaseUrl = (() => {
const configBase = import.meta.env.VITE_API_BASE_URL;
const configBase = import.meta.env.VITE_API_BASE_URL || '';
if (configBase.startsWith('http')) {
// 固定
return configBase;
@@ -28,7 +28,7 @@ export const httpBaseUrl = (() => {
// websocket base url
export const webSocketBaseUrl = (() => {
const configBase = import.meta.env.VITE_WS_BASE_URL;
const configBase = import.meta.env.VITE_WS_BASE_URL || '';
if (configBase.startsWith('ws')) {
// 固定
return configBase;

View File

@@ -1,6 +1,6 @@
// 添加事件监听器
import type { Ref } from 'vue';
// 添加事件监听器
export function addEventListen(
target: Window | HTMLElement,
event: string,

View File

@@ -27,7 +27,11 @@ export function readBlobText(blob: Blob) {
export function readFileText(e: File, encoding = 'UTF-8'): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsText(e, encoding);
if (encoding === 'base64') {
reader.readAsDataURL(e);
} else {
reader.readAsText(e, encoding);
}
reader.onload = res => {
resolve(res.target?.result as string);
};

View File

@@ -167,6 +167,11 @@ export const sleep = (ms: number) => {
return new Promise(resolve => setTimeout(resolve, ms));
};
// ansi 着色
export const ansi = (code: number | string, msg: string, newLine: boolean = true) => {
return `[${code}m${msg}${newLine ? '\r\n' : ''}`;
};
// 添加后缀
export const addSuffix = (value: any, suffix: string) => {
if (value === undefined || value === '') {
@@ -206,7 +211,7 @@ export function getUUID() {
/**
* 获取会话id
*/
export const nextId = (len: number): string => {
export const nextId = (len: number = 10): string => {
return getUUID().replaceAll('-', '').substring(0, len);
};

View File

@@ -1,4 +1,4 @@
import { App, ComponentPublicInstance } from 'vue';
import type { App, ComponentPublicInstance } from 'vue';
import axios from 'axios';
export default function handleError(Vue: App, baseUrl: string) {