complete tomcat manage page features

This commit is contained in:
idiotalex@163.com 2021-02-24 15:21:49 +08:00
parent 23107784ab
commit b6fbdbd56b
4 changed files with 435 additions and 23 deletions

View File

@ -94,7 +94,7 @@ export function getTomcatLogList(params) {
* params.filename 日志名称
* params.id 编辑修改时判断 ID
*/
export function deleteTomcatLog(params) {
export function deleteTomcatFile(params) {
return axios({
url: '/node/tomcat/deleteFile',
method: 'post',
@ -163,3 +163,59 @@ export function restartTomcat(params) {
data: params
})
}
/**
* Tomcat 项目命令操作
* @param {
* nodeId: 节点 ID
* id: Tomcat ID
* path: 项目目录
* op: 操作符
* } params
*/
export function doTomcatProjectCommand(params) {
return axios({
url: '/node/tomcat/tomcatProjectManage',
method: 'post',
data: params
})
}
/**
* Tomcat 项目文件列表
* @param {
* nodeId: 节点 ID
* id: 项目 ID
* path: Tomcat 项目目录
* except: dir 固定值
* } params
*/
export function getTomcatFileList(params) {
return axios({
url: '/node/tomcat/getFileList',
method: 'post',
data: params
})
}
/**
* 上传 Tomcat 项目文件
* @param {
* file: 文件 multipart/form-data
* nodeId: 节点 ID
* id: 项目 ID
* path: 目录地址
* } formData
*/
export function uploadTomcatProjectFile(formData) {
return axios({
url: '/node/tomcat/upload',
headers: {
'Content-Type': 'multipart/form-data;charset=UTF-8'
},
method: 'post',
// 0 表示无超时时间
timeout: 0,
data: formData
})
}

View File

@ -27,7 +27,7 @@
</a-layout>
</template>
<script>
import { getTomcatLogList, downloadTomcatFile, deleteTomcatLog } from '../../../../api/node-other'
import { getTomcatLogList, downloadTomcatFile, deleteTomcatFile } from '../../../../api/node-other'
import { mapGetters } from 'vuex';
export default {
props: {
@ -161,7 +161,7 @@ export default {
id: this.tomcatId
}
//
deleteTomcatLog(params).then(res => {
deleteTomcatFile(params).then(res => {
if(res.code === 200) {
this.$notification.success({
message: res.msg,

View File

@ -0,0 +1,299 @@
<template>
<!-- 布局 -->
<a-layout class="file-layout">
<!-- 目录树 -->
<a-layout-sider theme="light" class="sider" width="25%">
<a-empty v-if="treeList.length === 0" />
<a-directory-tree :treeData="treeList" :replaceFields="replaceFields" @select="onSelect">
</a-directory-tree>
</a-layout-sider>
<!-- 表格 -->
<a-layout-content class="file-content">
<div ref="filter" class="filter">
<a-button type="primary" @click="handleUpload">上传文件</a-button>
<a-button type="primary" @click="loadFileList">刷新</a-button>
</div>
<a-table :data-source="fileList" :loading="loading" :columns="columns" :scroll="{y: tableHeight}" :pagination="false" bordered :rowKey="(record, index) => index">
<a-tooltip slot="filename" slot-scope="text" placement="topLeft" :title="text">
<span>{{ text }}</span>
</a-tooltip>
<a-tooltip slot="isDirectory" slot-scope="text" placement="topLeft" :title="text">
<span>{{ text ? '目录' : '文件' }}</span>
</a-tooltip>
<a-tooltip slot="fileSize" slot-scope="text" placement="topLeft" :title="text">
<span>{{ text }}</span>
</a-tooltip>
<template slot="operation" slot-scope="text, record">
<a-button type="primary" @click="handleDownload(record)">下载</a-button>
<a-button type="danger" @click="handleDelete(record)">删除</a-button>
</template>
</a-table>
<!-- 上传文件 -->
<a-modal v-model="uploadFileVisible" width="300px" title="上传项目文件" :footer="null" :maskClosable="true">
<a-upload :file-list="uploadFileList" :remove="handleRemove" :before-upload="beforeUpload" multiple>
<a-button><a-icon type="upload" />选择文件</a-button>
</a-upload>
<br/>
<a-button type="primary" :disabled="uploadFileList.length === 0" @click="startUpload">开始上传</a-button>
</a-modal>
</a-layout-content>
</a-layout>
</template>
<script>
import { getTomcatFileList, downloadTomcatFile, deleteTomcatFile, uploadTomcatProjectFile } from '../../../../api/node-other';
export default {
props: {
nodeId: {
type: String
},
tomcatId: {
type: String
},
path: {
type: String
}
},
data() {
return {
loading: false,
treeList: [],
fileList: [],
uploadFileList: [],
tempNode: {},
temp: {},
uploadFileVisible: false,
tableHeight: '80vh',
replaceFields: {
children: 'children',
title: 'title',
key: 'key'
},
columns: [
{title: '文件名称', dataIndex: 'filename', width: 100, ellipsis: true, scopedSlots: {customRender: 'filename'}},
{title: '文件类型', dataIndex: 'isDirectory', width: 100, ellipsis: true, scopedSlots: {customRender: 'isDirectory'}},
{title: '文件大小', dataIndex: 'fileSize', width: 120, ellipsis: true, scopedSlots: {customRender: 'fileSize'}},
{title: '修改时间', dataIndex: 'modifyTime', width: 180, ellipsis: true},
{title: '操作', dataIndex: 'operation', scopedSlots: {customRender: 'operation'}, width: 120}
]
}
},
mounted() {
this.calcTableHeight()
this.loadData();
},
methods: {
//
calcTableHeight() {
this.tableHeight = window.innerHeight - this.$refs['filter'].clientHeight - 185;
},
//
loadData() {
this.loading = true;
this.treeList.push({
key: '1',
title: this.path,
path: this.path
})
this.loading = false;
},
//
handleUpload() {
if (Object.keys(this.tempNode).length === 0) {
this.$notification.error({
message: '请选择一个节点',
duration: 2
});
return;
}
this.uploadFileVisible = true;
},
handleRemove(file) {
const index = this.uploadFileList.indexOf(file);
const newFileList = this.uploadFileList.slice();
newFileList.splice(index, 1);
this.uploadFileList = newFileList;
},
beforeUpload(file) {
this.uploadFileList = [...this.uploadFileList, file];
return false;
},
//
startUpload() {
this.uploadFileList.forEach(file => {
const formData = new FormData();
formData.append('file', file);
formData.append('nodeId', this.nodeId);
formData.append('id', this.tomcatId);
formData.append('path', this.tempNode.path);
//
uploadTomcatProjectFile(formData).then(res => {
if (res.code === 200) {
this.$notification.success({
message: res.msg,
duration: 2
});
}
})
})
setTimeout(() => {
this.loadFileList();
}, 1000 * 3);
this.uploadFileList = [];
},
//
onSelect(selectedKeys, {node}) {
return new Promise(resolve => {
this.tempNode = node.dataRef;
if (node.dataRef.disabled) {
resolve();
return;
}
//
const params = {
nodeId: this.nodeId,
id: this.tomcatId,
path: node.dataRef.path,
// except: 'dir'
}
this.fileList = [];
this.loading = true;
//
getTomcatFileList(params).then(res => {
if (res.code === 200) {
let children = [];
//
res.data.forEach(element => {
if (element.isDirectory) {
children.push({
key: element.id,
title: element.filename,
path: `${node.dataRef.path}/${element.filename}`,
isLeaf: element.isDirectory ? false : true
})
} else {
//
this.fileList.push({
...element
});
}
})
//
node.dataRef.children = children;
this.treeList = [...this.treeList];
}
this.loading = false;
})
resolve();
});
},
//
loadFileList() {
if (Object.keys(this.tempNode).length === 0) {
this.$notification.warn({
message: '请选择一个节点',
duration: 2
});
return false;
}
//
const params = {
nodeId: this.nodeId,
id: this.tomcatId,
path: this.path
}
this.fileList = [];
this.loading = true;
//
getTomcatFileList(params).then(res => {
if (res.code === 200) {
//
res.data.forEach(element => {
if (!element.isDirectory) {
//
this.fileList.push({
...element
});
}
})
}
this.loading = false;
})
},
//
handleDownload(record) {
this.$notification.info({
message: '正在下载,请稍等...',
duration: 5
});
//
const params = {
nodeId: this.nodeId,
id: this.tomcatId,
path: record.parentPath,
filename: record.filename
}
// blob
downloadTomcatFile(params).then(blob => {
const url = window.URL.createObjectURL(blob);
let link = document.createElement('a');
link.style.display = 'none';
link.href = url;
link.setAttribute('download', record.filename);
document.body.appendChild(link);
link.click();
})
},
//
handleDelete(record) {
this.$confirm({
title: '系统提示',
content: '真的要删除文件么?',
okText: '确认',
cancelText: '取消',
onOk: () => {
//
const params = {
nodeId: this.nodeId,
id: this.tomcatId,
path: record.parentPath,
filename: record.filename
}
//
deleteTomcatFile(params).then((res) => {
if (res.code === 200) {
this.$notification.success({
message: res.msg,
duration: 2
});
this.loadFileList();
}
})
}
});
}
}
}
</script>
<style scoped>
.file-layout {
padding: 0;
}
.sider {
border: 1px solid #e2e2e2;
height: calc(100vh - 80px);
overflow-y: auto;
}
.file-content {
height: calc(100vh - 100px);
overflow-y: auto;
margin: 10px 10px 0;
padding: 10px;
background-color: #fff;
}
.filter {
margin: 0 0 10px;
}
.ant-btn {
margin-right: 10px;
}
</style>

View File

@ -30,12 +30,13 @@
<a-tooltip slot="status" slot-scope="text" placement="topLeft" :title="text">
<span>{{ text === 'running' ? '运行中' : '未运行' }}</span>
</a-tooltip>
<template slot="operation" slot-scope="text, record">
<a-button type="primary" @click="handleFile(record)">管理</a-button>
<a-button type="danger" @click="handleMonitor(record)">停止</a-button>
<a-button type="danger" @click="handleReplica(record)">重启</a-button>
<a-button type="danger" @click="handleDelete(record)">删除</a-button>
</template>
<template slot="operation" slot-scope="operation, record">
<a-button type="primary" @click="handleProjectFile(record, text)">管理</a-button>
<a-button :disabled="record.status === 'running'" type="primary" @click="handleProjectCommand(record, text, 'start')">启动</a-button>
<a-button :disabled="record.status === 'stopped'" type="danger" @click="handleProjectCommand(record, text, 'stop')">停止</a-button>
<a-button :disabled="record.status === 'stopped'" type="danger" @click="handleProjectCommand(record, text, 'reload')">重启</a-button>
<a-button type="danger" @click="handleProjectCommand(record, text, 'undeploy')">删除</a-button>
</template>
</a-table>
</a-table>
<!-- 编辑区 -->
@ -60,14 +61,21 @@
:visible="drawerLogVisible" @close="onLogClose">
<tomcat-log v-if="drawerLogVisible" :nodeId="node.id" :tomcatId="temp.id" />
</a-drawer>
<!-- 项目文件组件 -->
<a-drawer :title="drawerTitle" placement="right" width="85vw"
:visible="drawerFileVisible" @close="onFileClose">
<tomcat-project-file v-if="drawerFileVisible" :nodeId="node.id" :tomcatId="temp.id" :path="temp.projectPath" />
</a-drawer>
</div>
</template>
<script>
import { getTomcatList, editTomcat, deleteTomcat, getTomcatProjectList, getTomcatStatus, startTomcat, stopTomcat, restartTomcat } from '../../../../api/node-other';
import { getTomcatList, editTomcat, deleteTomcat, getTomcatProjectList, getTomcatStatus, startTomcat, stopTomcat, restartTomcat, doTomcatProjectCommand } from '../../../../api/node-other';
import TomcatLog from './tomcat-log';
import TomcatProjectFile from './tomcat-project-file';
export default {
components: {
TomcatLog
TomcatLog,
TomcatProjectFile
},
props: {
node: {
@ -83,6 +91,7 @@ export default {
editTomcatVisible: false,
drawerTitle: '',
drawerLogVisible: false,
drawerFileVisible: false,
columns: [
{title: 'Tomcat 名称', dataIndex: 'name', width: 150, ellipsis: true, scopedSlots: {customRender: 'name'}},
{title: 'Tomcat 路径', dataIndex: 'path', width: 150, ellipsis: true, scopedSlots: {customRender: 'path'}},
@ -207,20 +216,24 @@ export default {
//
expand(expanded, record) {
if (expanded) {
//
this.childLoading = true;
const params = {
nodeId: this.node.id,
id: record.id
}
getTomcatProjectList(params).then(res => {
if (res.code === 200) {
record.children = res.data;
}
this.childLoading = false;
})
this.loadTomcatProjectList(record);
}
},
// Tomcat
loadTomcatProjectList(record) {
//
this.childLoading = true;
const params = {
nodeId: this.node.id,
id: record.id
}
getTomcatProjectList(params).then(res => {
if (res.code === 200) {
record.children = res.data;
}
this.childLoading = false;
})
},
//
handleLog(record) {
this.temp = Object.assign(record);
@ -305,6 +318,50 @@ export default {
})
}
});
},
// Tomcat
handleProjectCommand(record, tomcatRecord, op) {
const map = {
'start': '启动',
'stop': '停止',
'reload': '重启',
'undeploy': '删除'
}
this.$confirm({
title: '系统提示',
content: `确认执行【${map[op]}】命令么?`,
okText: '确认',
cancelText: '取消',
onOk: () => {
const params = {
nodeId: this.node.id,
id: tomcatRecord.id,
path: record.path,
op: op,
}
doTomcatProjectCommand(params).then(res => {
if (res.code === 200) {
this.$notification.success({
message: res.msg,
duration: 2
});
// Tomcat
this.loadTomcatProjectList(tomcatRecord);
}
})
}
});
},
// Tomcat
handleProjectFile(record, tomcatRecord) {
this.temp = Object.assign(tomcatRecord);
this.temp.projectPath = record.path;
this.drawerTitle = `Tomcat 文件管理(${this.temp.name})`
this.drawerFileVisible = true;
},
//
onFileClose() {
this.drawerFileVisible = false;
}
}
}