perf: file transfer

This commit is contained in:
zhaojisen 2024-06-28 17:19:51 +08:00
parent ada6479177
commit 4e79074cef
7 changed files with 300 additions and 151 deletions

View File

@ -16,6 +16,3 @@ export default {
}
}
</script>
<style>
</style>

View File

@ -1,42 +1,21 @@
<template>
<div class="term-wrapper">
<div class="term-header">
<div class="header-text">{{ $tc('Output') }}</div>
<div style="position: relative;">
<div v-if="showToolBar" class="actions">
<div
v-if="executionInfo.status"
class="header-status"
v-for="(item,index) in toolbar"
:key="index"
style="display: inline-block"
>
<span class="status-item">
<span>{{ $tc('Status') }}: </span>
<span
:class="{'status_success':executionInfo.status==='success',
'status_warning':executionInfo.status==='timeout',
'status_danger':executionInfo.status==='failed'
}"
>{{ $tc('' + executionInfo.status) }}</span>
</span>
<span class="status-item">
<span>{{ $tc('TimeDelta') }}: </span>
<span>{{ executionInfo.timeCost.toFixed(2) }}s</span>
</span>
</div>
<div v-if="showToolBar" class="actions">
<div
v-for="(item,index) in toolbar"
:key="index"
class="action-item"
>
<el-tooltip :content="item.tip" :open-delay="500">
<el-button
v-if="!item.isScrollButton || showScrollButton"
size="mini"
type="primary"
@click="item.callback()"
>
<svg-icon :icon-class="item.icon" />
</el-button>
</el-tooltip>
</div>
<el-tooltip :content="item.tip" :open-delay="500">
<el-button
v-if="!item.isScrollButton || showScrollButton"
size="mini"
type="default"
@click="item.callback()"
>
<svg-icon :icon-class="item.icon" />
</el-button>
</el-tooltip>
</div>
</div>
<div id="terminal" ref="terminal" class="xterm" />
@ -62,10 +41,6 @@ export default {
type: Object,
default: () => {
}
},
executionInfo: {
type: Object,
default: () => {}
}
},
data() {
@ -85,13 +60,17 @@ export default {
{
tip: this.$tc('ScrollToTop'),
icon: 'arrow-up',
callback: this.scrollToTop,
callback: () => {
this.xterm.scrollToTop()
},
isScrollButton: true
},
{
tip: this.$tc('ScrollToBottom'),
icon: 'arrow-down',
callback: this.scrollToBottom,
callback: () => {
this.xterm.scrollToBottom()
},
isScrollButton: true
},
{
@ -136,113 +115,34 @@ export default {
},
checkScroll(position) {
this.showScrollButton = position > 0
},
scrollToTop() {
//
this.$nextTick(() => {
this.xterm.scrollToTop()
})
setTimeout(() => {
this.showScrollButton = true
})
},
scrollToBottom() {
setTimeout(() => {
this.showScrollButton = true
this.xterm.scrollToBottom()
})
}
}
}
</script>
<style scoped lang="scss">
$header-bg-color: #F5F6F7;
$actions-hover-bg-color: #d2d2d2;
<style scoped>
.xterm {
overflow: auto;
padding-left: 5px;
background-color: #FFFFFF;
}
.term-wrapper {
position: relative;
.actions {
text-align: right;
background-color: #FFF;
padding-right: 5px;
padding-top: 2px
}
.term-header {
position: relative;
display: flex;
align-items: center;
height: 45px;
padding-left: 15px;
background-color: $header-bg-color;
.header-text {
font-size: 16px;
font-weight: 500;
letter-spacing: 1px;
}
.header-status {
margin-left: 10px;
font-weight: 400;
.status-item {
letter-spacing: 0.5px;
padding-left: 25px;
.status_success {
color: var(--color-primary);
}
.status_warning {
color: var(--color-warning);
}
.status_danger {
color: var(--color-danger);
}
}
}
.actions {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
display: flex;
justify-content: flex-end;
align-items: center;
margin-right: 10px;
background-color: $header-bg-color;
.action-item {
display: flex;
align-items: center;
.el-button {
border: none;
padding: 2px;
font-size: 14px;
width: 26px;
height: 26px;
color: #888;
background-color: transparent;
margin-left: 2px;
&:hover {
background-color: $actions-hover-bg-color !important;
color: var(--color-text-primary);
}
&:focus {
background-color: $actions-hover-bg-color !important;
color: var(--color-text-primary);
}
}
}
}
}
.xterm {
overflow: auto;
padding: 10px 0 0 20px;
background-color: #FFFFFF;
}
.el-button {
border: none;
padding: 2px;
font-size: 14px;
width: 26px;
height: 26px;
color: #888;
background-color: transparent;
margin-left: 2px;
}
</style>

View File

@ -139,7 +139,6 @@ $cursor: #fff;
}
}
/* reset element-ui css */
.login-container {
.el-input {
display: inline-block;

View File

@ -20,7 +20,7 @@
/>
<span v-if="executionInfo.status" style="float: right" />
<div class="xterm-container">
<Term
<QuickJobTerm
ref="xterm"
:show-tool-bar="true"
:xterm-config="xtermConfig"
@ -36,7 +36,7 @@
<script>
import AssetTreeTable from '@/components/Apps/AssetTreeTable'
import Term from '@/components/Widgets/Term'
import QuickJobTerm from '@/views/ops/Adhoc/components/QuickJobTerm.vue'
import CodeEditor from '@/components/Form/FormFields/CodeEditor'
import Page from '@/layout/components/Page'
import AdhocOpenDialog from './AdhocOpenDialog.vue'
@ -52,7 +52,7 @@ export default {
AdhocOpenDialog,
AssetTreeTable,
Page,
Term,
QuickJobTerm,
CodeEditor
},
data() {

View File

@ -0,0 +1,251 @@
<template>
<div class="term-wrapper">
<div class="term-header">
<div class="header-text">{{ $tc('Output') }}</div>
<div
v-if="executionInfo.status"
class="header-status"
>
<span class="status-item">
<span>{{ $tc('Status') }}: </span>
<span
:class="{'status_success':executionInfo.status==='success',
'status_warning':executionInfo.status==='timeout',
'status_danger':executionInfo.status==='failed'
}"
>{{ $tc('' + executionInfo.status) }}</span>
</span>
<span class="status-item">
<span>{{ $tc('TimeDelta') }}: </span>
<span>{{ executionInfo.timeCost.toFixed(2) }}s</span>
</span>
</div>
<div v-if="showToolBar" class="actions">
<div
v-for="(item,index) in toolbar"
:key="index"
class="action-item"
>
<el-tooltip :content="item.tip" :open-delay="500">
<el-button
v-if="!item.isScrollButton || showScrollButton"
size="mini"
type="primary"
@click="item.callback()"
>
<svg-icon :icon-class="item.icon" />
</el-button>
</el-tooltip>
</div>
</div>
</div>
<div id="terminal" ref="terminal" class="xterm" />
</div>
</template>
<script>
import 'xterm/css/xterm.css'
import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
import { downloadText } from '@/utils/common'
export default {
name: 'Term',
props: {
showToolBar: {
type: [Boolean, Object],
default: () => {
return false
}
},
xtermConfig: {
type: Object,
default: () => {
}
},
executionInfo: {
type: Object,
// eslint-disable-next-line vue/require-valid-default-prop
default: {
status: 'success'
}
}
},
data() {
return {
xterm: new Terminal(Object.assign({
fontFamily: 'monaco, Consolas, "Lucida Console", monospace',
lineHeight: 1.2,
fontSize: 13,
rightClickSelectsWord: true,
theme: {
background: '#fff',
foreground: '#000',
selection: '#363535'
}
}, this.xtermConfig)),
toolbar: [
{
tip: this.$tc('ScrollToTop'),
icon: 'arrow-up',
callback: this.scrollToTop,
isScrollButton: true
},
{
tip: this.$tc('ScrollToBottom'),
icon: 'arrow-down',
callback: this.scrollToBottom,
isScrollButton: true
},
{
tip: this.$tc('ClearScreen'),
icon: 'refresh',
callback: () => {
this.xterm.reset()
}
},
{
tip: this.$tc('Export'),
icon: 'download',
callback: () => {
this.xterm.selectAll()
const text = this.xterm.getSelection()
const filename = `${this.xtermConfig?.type}_${this.xtermConfig?.taskId}.log`
downloadText(text, filename)
}
}
],
showScrollButton: false
}
},
mounted: function() {
const terminalContainer = this.$refs.terminal
const fitAddon = new FitAddon()
this.xterm.loadAddon(fitAddon)
this.xterm.open(terminalContainer)
fitAddon.fit()
this.xterm.scrollToBottom()
this.xterm.onScroll(this.checkScroll)
},
beforeDestroy() {
this.xterm.dispose()
},
methods: {
reset: function() {
this.xterm.reset()
},
write: function(val) {
this.xterm.write(val)
},
checkScroll(position) {
this.showScrollButton = position > 0
},
scrollToTop() {
//
this.$nextTick(() => {
this.xterm.scrollToTop()
})
setTimeout(() => {
this.showScrollButton = true
})
},
scrollToBottom() {
setTimeout(() => {
this.showScrollButton = true
this.xterm.scrollToBottom()
})
}
}
}
</script>
<style scoped lang="scss">
$header-bg-color: #F5F6F7;
$actions-hover-bg-color: #d2d2d2;
.term-wrapper {
position: relative;
.term-header {
position: relative;
display: flex;
align-items: center;
height: 45px;
padding-left: 15px;
background-color: $header-bg-color;
.header-text {
font-size: 16px;
font-weight: 500;
letter-spacing: 1px;
}
.header-status {
margin-left: 10px;
font-weight: 400;
.status-item {
letter-spacing: 0.5px;
padding-left: 25px;
.status_success {
color: var(--color-primary);
}
.status_warning {
color: var(--color-warning);
}
.status_danger {
color: var(--color-danger);
}
}
}
.actions {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
display: flex;
justify-content: flex-end;
align-items: center;
margin-right: 10px;
background-color: $header-bg-color;
.action-item {
display: flex;
align-items: center;
.el-button {
border: none;
padding: 2px;
font-size: 14px;
width: 26px;
height: 26px;
color: #888;
background-color: transparent;
margin-left: 2px;
&:hover {
background-color: $actions-hover-bg-color !important;
color: var(--color-text-primary);
}
&:focus {
background-color: $actions-hover-bg-color !important;
color: var(--color-text-primary);
}
}
}
}
}
.xterm {
overflow: auto;
padding: 10px 0 0 20px;
background-color: #FFFFFF;
}
}
</style>

View File

@ -121,7 +121,7 @@
/>
<div style="height: 2px" />
</div>
<div style="display: flex;margin-top:10px;justify-content: space-between" />
<div style="display: flex; margin-top:10px; justify-content: space-between" />
</div>
</template>
</AssetTreeTable>
@ -167,7 +167,9 @@ export default {
type: 'primary'
},
callback: () => {
this.execute()
setTimeout(() => {
this.execute()
}, 300)
}
},
runAsInput: {