complete nginx page feature

This commit is contained in:
idiotalex@163.com 2021-02-25 16:02:48 +08:00
parent ca26c4385b
commit 574f593826
3 changed files with 534 additions and 5 deletions

View File

@ -1,5 +1,6 @@
package io.jpom.controller.node.system.nginx;
import cn.jiangzeyin.common.JsonMessage;
import com.alibaba.fastjson.JSONObject;
import io.jpom.common.BaseServerController;
import io.jpom.common.forward.NodeForward;
@ -75,6 +76,29 @@ public class NginxController extends BaseServerController {
return "node/system/nginxSetting";
}
/**
* @author Hotstrip
* load Nginx white list data
* @return
*/
@RequestMapping(value = "white-list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public String loadWhiteList() {
List<String> list = whitelistDirectoryService.getNgxDirectory(getNode());
return JsonMessage.getString(200, "success", list);
}
/**
* @author Hotstrip
* load Nginx config data
* @return
*/
@RequestMapping(value = "load-config", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public String loadConfig() {
JSONObject data = NodeForward.requestData(getNode(), NodeUrl.System_Nginx_item_data, getRequest(), JSONObject.class);
return JsonMessage.getString(200, "success", data);
}
@RequestMapping(value = "updateNgx", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody

View File

@ -0,0 +1,139 @@
import axios from './config';
/**
* Nginx 目录列表
* @param {
* nodeId: 节点 ID
* } params
*/
export function getNginxDirectoryList(params) {
return axios({
url: '/node/system/nginx/tree.json',
method: 'post',
data: params
})
}
/**
* Nginx 配置文件数据
* @param {
* nodeId: 节点 ID
* whitePath: nginx 白名单目录
* name: 子级目录
* } params
*/
export function getNginxFileList(params) {
return axios({
url: '/node/system/nginx/list_data.json',
method: 'post',
data: params
})
}
/**
* 编辑 Nginx 配置文件
* @param {
* nodeId: 节点 ID
* genre: 操作类型
* whitePath: 白名单目录
* name: 文件名称
* context: 内容
* } params
*/
export function editNginxConfig(params) {
return axios({
url: '/node/system/nginx/updateNgx',
method: 'post',
data: params
})
}
/**
* 删除
* @param {
* nodeId: 节点 ID
* path: 路径
* name: 文件名称
* } params
*/
export function deleteNginxConfig(params) {
return axios({
url: '/node/system/nginx/delete',
method: 'post',
data: params
})
}
/**
* 加载 Nginx 白名单列表
* @param {
* nodeId: 节点 ID
* } params
*/
export function loadNginxWhiteList(params) {
return axios({
url: '/node/system/nginx/white-list',
method: 'post',
data: params
})
}
/**
* 加载 Nginx 配置内容
* @param {
* nodeId: 节点 ID
* path: 白名单目录
* name: 文件名称
* } params
*/
export function loadNginxConfig(params) {
return axios({
url: '/node/system/nginx/load-config',
method: 'post',
data: params
})
}
/**
* 加载 Nginx 状态
* @param {
* nodeId: 节点 ID
* } params
*/
export function loadNginxData(params) {
return axios({
url: '/node/system/nginx/status',
method: 'post',
data: params
})
}
/**
* 管理 Nginx 服务
* @param {
* nodeId: 节点 ID
* command: 命令 {open || reload || stop}
* } params
*/
export function doNginxCommand(params) {
return axios({
url: `/node/system/nginx/${params.command}`,
method: 'post',
data: params
})
}
/**
* 编辑 Nginx 服务名称
* @param {
* nodeId: 节点 ID
* name: Nginx 服务名称
* } params
*/
export function editNginxServerName(params) {
return axios({
url: '/node/system/nginx/updateConf',
method: 'post',
data: params
})
}

View File

@ -1,14 +1,380 @@
<template>
<div>
Nginx List Page
</div>
<!-- 布局 -->
<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="handleAdd">新增 Nginx 配置</a-button>
<a-button type="primary" @click="handleFilter">刷新</a-button>
<a-switch v-model="nginxData.status" checked-children="运行中" un-checked-children="未运行" disabled />
<a-button type="primary" @click="handleEditNginx">编辑 Nginx 服务</a-button>
<a-button :disabled="nginxData.status" type="primary" @click="handleNginxCommand('open')">启动 Nginx</a-button>
<a-button :disabled="!nginxData.status" type="danger" @click="handleNginxCommand('reload')">重启 Nginx</a-button>
<a-button :disabled="!nginxData.status" type="danger" @click="handleNginxCommand('stop')">停止 Nginx</a-button>
</div>
<a-table :data-source="fileList" :loading="loading" :columns="columns" :scroll="{x: '80vw', y: tableHeight}" :pagination="false" bordered :rowKey="(record, index) => index">
<a-tooltip slot="name" 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>
<template slot="operation" slot-scope="text, record">
<a-button type="primary" @click="handleEdit(record)">编辑</a-button>
<a-button type="danger" @click="handleDelete(record)">删除</a-button>
</template>
</a-table>
<!-- 编辑区 -->
<a-modal v-model="editNginxVisible" title="编辑 Nginx 配置文件" @ok="handleEditNginxOk" :maskClosable="false" width="700px">
<a-form-model ref="editNginxForm" :rules="rules" :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
<a-form-model-item label="白名单路径" prop="whitePath">
<a-select v-model="temp.whitePath" placeholder="请选择白名单路径">
<a-select-option v-for="element in whiteList" :key="element">{{ element }}</a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item label="文件名称" prop="name">
<a-input v-model="temp.name" placeholder="需要以 .conf 结尾"/>
</a-form-model-item>
<a-form-model-item label="配置内容" prop="context">
<a-input v-model="temp.context" type="textarea" :rows="10" style="resize: none" placeholder="配置内容"/>
</a-form-model-item>
</a-form-model>
</a-modal>
<!-- 编辑 Nginx 服务名 -->
<a-modal v-model="editNginxNameVisible" title="编辑 Nginx 服务名称" @ok="handleEditNginxNameOk" :maskClosable="false" width="500px">
<a-form-model ref="editNginxNameForm" :rules="rules" :model="nginxData" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
<a-form-model-item label="服务名称" prop="name">
<a-input v-model="nginxData.name" placeholder="请输入 Nginx 服务名称"/>
</a-form-model-item>
</a-form-model>
</a-modal>
</a-layout-content>
</a-layout>
</template>
<script>
import { getNginxDirectoryList, getNginxFileList, editNginxConfig, deleteNginxConfig, loadNginxWhiteList, loadNginxConfig, loadNginxData, doNginxCommand, editNginxServerName } from '../../../../api/node-nginx';
export default {
props: {
node: {
type: Object
}
},
data() {
return {
loading: false,
whiteList: [],
treeList: [],
fileList: [],
nginxData: {},
temp: {},
tempNode: {},
tableHeight: '80vh',
editNginxVisible: false,
editNginxNameVisible: false,
replaceFields: {
children: 'children',
title: 'title',
key: 'key'
},
columns: [
{title: '文件名称', dataIndex: 'name', width: 100, ellipsis: true, scopedSlots: {customRender: 'name'}},
{title: '文件类型', dataIndex: 'isDirectory', width: 80, ellipsis: true, scopedSlots: {customRender: 'isDirectory'}},
{title: '数量', dataIndex: 'serverCount', width: 80, ellipsis: true, scopedSlots: {customRender: 'serverCount'}},
{title: '域名', dataIndex: 'serverName', width: 120, ellipsis: true, scopedSlots: {customRender: 'serverName'}},
{title: 'location', dataIndex: 'location', width: 120, ellipsis: true, scopedSlots: {customRender: 'location'}},
{title: '修改时间', dataIndex: 'time', width: 180, ellipsis: true},
{title: '操作', dataIndex: 'operation', scopedSlots: {customRender: 'operation'}, width: 130}
],
rules: {
name: [
{ required: true, message: 'Please input name', trigger: 'blur' }
],
whitePath: [
{ required: true, message: 'Please select item', trigger: 'blur' }
],
context: [
{ required: true, message: 'Please input context', trigger: 'blur' }
]
}
}
},
mounted() {
this.calcTableHeight();
this.handleFilter();
},
methods: {
//
calcTableHeight() {
this.tableHeight = window.innerHeight - this.$refs['filter'].clientHeight - 185;
},
// Nginx
loadNginxData() {
const params = {
nodeId: this.node.id
}
loadNginxData(params).then(res => {
this.nginxData = res.data;
})
},
//
loadDirectoryList() {
this.treeList = [];
this.loading = true;
//
const params = {
nodeId: this.node.id
}
getNginxDirectoryList(params).then(res => {
if (res.code === 200) {
res.data.forEach(ele => {
this.treeList.push({
key: ele.path,
title: ele.title,
whitePath: ele.whitePath,
path: ele.path,
isLeaf: false
})
})
}
this.loading = false;
})
},
//
handleFilter() {
this.loadDirectoryList();
this.loadNginxData();
this.loadNginxWhiteList();
},
//
onSelect(selectedKeys, {node}) {
return new Promise(resolve => {
this.tempNode = node.dataRef;
//
const params = {
nodeId: this.node.id,
whitePath: node.dataRef.whitePath,
name: node.dataRef.path
}
this.fileList = [];
this.loading = true;
//
getNginxFileList(params).then(res => {
if (res.code === 200) {
let children = [];
//
res.data.forEach(element => {
if (element.isDirectory) {
children.push({
key: element.relativePath,
title: element.name,
whitePath: node.dataRef.whitePath,
path: element.relativePath,
isLeaf: element.isDirectory ? false : true
})
} else {
//
this.fileList.push({
...element
});
}
})
//
node.dataRef.children = children;
this.treeList = [...this.treeList];
}
this.loading = false;
})
resolve();
});
},
//
loadFileList() {
this.fileList = [];
this.loading = true;
//
const params = {
nodeId: this.node.id,
whitePath: this.tempNode.whitePath,
name: this.tempNode.path
}
//
getNginxFileList(params).then(res => {
if (res.code === 200) {
let children = [];
//
res.data.forEach(element => {
if (element.isDirectory) {
children.push({
key: element.relativePath,
title: element.name,
whitePath: this.tempNode.whitePath,
path: element.relativePath,
isLeaf: element.isDirectory ? false : true
})
} else {
//
this.fileList.push({
...element
});
}
})
}
this.loading = false;
})
},
// Nginx
loadNginxWhiteList() {
const params = {
nodeId: this.node.id
}
loadNginxWhiteList(params).then(res => {
if (res.code === 200) {
this.whiteList = res.data;
}
})
},
//
handleAdd() {
this.temp = {};
this.editNginxVisible = true;
},
//
handleEdit(record) {
const params = {
nodeId: this.node.id,
path: record.path,
name: record.relativePath
}
loadNginxConfig(params).then(res => {
if (res.code === 200) {
this.temp = res.data;
this.editNginxVisible = true;
}
})
},
// Nginx
handleEditNginxOk() {
//
this.$refs['editNginxForm'].validate((valid) => {
if (!valid) {
return false;
}
this.temp.nodeId = this.node.id;
//
editNginxConfig(this.temp).then(res => {
if (res.code === 200) {
//
this.$notification.success({
message: res.msg,
duration: 2
});
this.$refs['editNginxForm'].resetFields();
this.editNginxVisible = false;
this.loadDirectoryList();
}
})
})
},
//
handleDelete(record) {
this.$confirm({
title: '系统提示',
content: '真的要删除文件么?',
okText: '确认',
cancelText: '取消',
onOk: () => {
//
const params = {
nodeId: this.node.id,
path: record.path,
name: record.relativePath
}
//
deleteNginxConfig(params).then((res) => {
if (res.code === 200) {
this.$notification.success({
message: res.msg,
duration: 2
});
this.loadFileList();
}
})
}
});
},
// Nginx
handleEditNginx() {
this.editNginxNameVisible = true;
},
// Nginx
handleEditNginxNameOk() {
//
this.$refs['editNginxNameForm'].validate((valid) => {
if (!valid) {
return false;
}
const params = {
nodeId: this.node.id,
name: this.nginxData.name
}
editNginxServerName(params).then(res => {
if (res.code === 200) {
this.$notification.success({
message: res.msg,
duration: 2
});
this.$refs['editNginxNameForm'].resetFields();
this.editNginxNameVisible = false;
this.loadNginxData();
}
})
})
},
// Nginx
handleNginxCommand(command) {
const params = {
nodeId: this.node.id,
command
}
doNginxCommand(params).then(res => {
if (res.code === 200) {
this.$notification.success({
message: res.msg,
duration: 2
});
this.loadNginxData();
}
})
}
}
}
</script>
</script>
<style scoped>
.file-layout {
padding: 0;
}
.sider {
border: 1px solid #e2e2e2;
height: calc(100vh - 130px);
overflow-y: auto;
}
.file-content {
height: calc(100vh - 150px);
overflow-y: auto;
margin: 10px 10px 0;
padding: 10px;
background-color: #fff;
}
.filter {
margin: 0 0 10px;
}
.ant-btn {
margin-right: 10px;
}
</style>