调整分组配置

This commit is contained in:
chaoszhu 2024-07-19 10:52:09 +08:00
parent 483f17a591
commit 514c9499e6
10 changed files with 155 additions and 89 deletions

View File

@ -1,30 +1,30 @@
const { readHostList, writeHostList, readSSHRecord, writeSSHRecord } = require('../utils') const { readHostList, writeHostList, readSSHRecord, writeSSHRecord } = require('../utils')
async function getHostList({ res }) { async function getHostList({ res }) {
console.log('get - host - list') // console.log('get-host-list')
const data = await readHostList() const data = await readHostList()
res.success({ data }) res.success({ data })
} }
async function saveHost({ res, request }) { async function saveHost({ res, request }) {
let { body: { host: newHost, name, expired, expiredNotify, group, consoleUrl, remark } } = request let { body: { host: newHost, name, index, expired, expiredNotify, group, consoleUrl, remark } } = request
console.log(request) // console.log(request)
if (!newHost || !name) return res.fail({ msg: 'missing params: name or host' }) if (!newHost || !name) return res.fail({ msg: 'missing params: name or host' })
let hostList = await readHostList() let hostList = await readHostList()
if (hostList?.some(({ host }) => host === newHost)) return res.fail({ msg: `主机${ newHost }已存在` }) if (hostList?.some(({ host }) => host === newHost)) return res.fail({ msg: `主机${ newHost }已存在` })
if (!Array.isArray(hostList)) hostList = [] if (!Array.isArray(hostList)) hostList = []
hostList.push({ host: newHost, name, expired, expiredNotify, group, consoleUrl, remark }) hostList.push({ host: newHost, name, index, expired, expiredNotify, group, consoleUrl, remark })
await writeHostList(hostList) await writeHostList(hostList)
res.success() res.success()
} }
async function updateHost({ res, request }) { async function updateHost({ res, request }) {
let { body: { host: newHost, name: newName, oldHost, expired, expiredNotify, group, consoleUrl, remark } } = request let { body: { host: newHost, name: newName, index, oldHost, expired, expiredNotify, group, consoleUrl, remark } } = request
if (!newHost || !newName || !oldHost) return res.fail({ msg: '参数错误' }) if (!newHost || !newName || !oldHost) return res.fail({ msg: '参数错误' })
let hostList = await readHostList() let hostList = await readHostList()
if (!hostList.some(({ host }) => host === oldHost)) return res.fail({ msg: `主机${ newHost }不存在` }) if (!hostList.some(({ host }) => host === oldHost)) return res.fail({ msg: `主机${ newHost }不存在` })
let targetIdx = hostList.findIndex(({ host }) => host === oldHost) let targetIdx = hostList.findIndex(({ host }) => host === oldHost)
hostList.splice(targetIdx, 1, { name: newName, host: newHost, expired, expiredNotify, group, consoleUrl, remark }) hostList.splice(targetIdx, 1, { name: newName, host: newHost, index, expired, expiredNotify, group, consoleUrl, remark })
writeHostList(hostList) writeHostList(hostList)
res.success() res.success()
} }
@ -46,26 +46,27 @@ async function removeHost({ res, request }) {
res.success({ data: `${ host }已移除, ${ flag ? '并移除ssh记录' : '' }` }) res.success({ data: `${ host }已移除, ${ flag ? '并移除ssh记录' : '' }` })
} }
async function updateHostSort({ res, request }) { // 原手动排序接口-废弃
let { body: { list } } = request // async function updateHostSort({ res, request }) {
if (!list) return res.fail({ msg: '参数错误' }) // let { body: { list } } = request
let hostList = await readHostList() // if (!list) return res.fail({ msg: '参数错误' })
if (hostList.length !== list.length) return res.fail({ msg: '失败: host数量不匹配' }) // let hostList = await readHostList()
let sortResult = [] // if (hostList.length !== list.length) return res.fail({ msg: '失败: host数量不匹配' })
for (let i = 0; i < list.length; i++) { // let sortResult = []
const curHost = list[i] // for (let i = 0; i < list.length; i++) {
let temp = hostList.find(({ host }) => curHost.host === host) // const curHost = list[i]
if (!temp) return res.fail({ msg: `查找失败: ${ curHost.name }` }) // let temp = hostList.find(({ host }) => curHost.host === host)
sortResult.push(temp) // if (!temp) return res.fail({ msg: `查找失败: ${ curHost.name }` })
} // sortResult.push(temp)
writeHostList(sortResult) // }
res.success({ msg: 'success' }) // writeHostList(sortResult)
} // res.success({ msg: 'success' })
// }
module.exports = { module.exports = {
getHostList, getHostList,
saveHost, saveHost,
updateHost, updateHost,
removeHost, removeHost
updateHostSort // updateHostSort
} }

View File

@ -1,5 +1,5 @@
const { updateSSH, removeSSH, existSSH, getCommand } = require('../controller/ssh') const { updateSSH, removeSSH, existSSH, getCommand } = require('../controller/ssh')
const { getHostList, saveHost, updateHost, removeHost, updateHostSort } = require('../controller/host') const { getHostList, saveHost, updateHost, removeHost } = require('../controller/host')
const { login, getpublicKey, updatePwd, getLoginRecord } = require('../controller/user') const { login, getpublicKey, updatePwd, getLoginRecord } = require('../controller/user')
const { getSupportEmailList, getUserEmailList, updateUserEmailList, removeUserEmail, pushEmail, getNotifyList, updateNotifyList } = require('../controller/notify') const { getSupportEmailList, getUserEmailList, updateUserEmailList, removeUserEmail, pushEmail, getNotifyList, updateNotifyList } = require('../controller/notify')
const { getGroupList, addGroupList, updateGroupList, removeGroup } = require('../controller/group') const { getGroupList, addGroupList, updateGroupList, removeGroup } = require('../controller/group')
@ -46,12 +46,12 @@ const host = [
method: 'post', method: 'post',
path: '/host-remove', path: '/host-remove',
controller: removeHost controller: removeHost
},
{
method: 'put',
path: '/host-sort',
controller: updateHostSort
} }
// {
// method: 'put',
// path: '/host-sort',
// controller: updateHostSort
// }
] ]
const user = [ const user = [
{ {

View File

@ -4,7 +4,7 @@
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=0,user-scalable=yes"> <meta name="viewport" content="width=device-width, initial-scale=0,user-scalable=yes">
<title>EasyNode</title> <title>EasyNode</title>
<script src="//at.alicdn.com/t/c/font_3309550_flid0kihu36.js"></script> <script src="//at.alicdn.com/t/c/font_3309550_ezojxo1wj3.js"></script>
</head> </head>
<body> <body>

View File

@ -43,9 +43,9 @@ export default {
updatePwd(data) { updatePwd(data) {
return axios({ url: '/pwd', method: 'put', data }) return axios({ url: '/pwd', method: 'put', data })
}, },
updateHostSort(data) { // updateHostSort(data) {
return axios({ url: '/host-sort', method: 'put', data }) // return axios({ url: '/host-sort', method: 'put', data })
}, // },
getUserEmailList() { getUserEmailList() {
return axios({ url: '/user-email', method: 'get' }) return axios({ url: '/user-email', method: 'get' })
}, },

View File

@ -1,5 +1,6 @@
<template> <template>
<svg class="icon" aria-hidden="true"> <svg class="icon" aria-hidden="true">
<title v-if="title">{{ title }}</title>
<use :xlink:href="href" /> <use :xlink:href="href" />
</svg> </svg>
</template> </template>
@ -8,6 +9,12 @@ export default {
name: 'IconSvg', name: 'IconSvg',
props: { props: {
name: { name: {
required: true,
type: String,
default: ''
},
title: {
required: false,
type: String, type: String,
default: '' default: ''
} }

View File

@ -7,6 +7,7 @@
:inline="true" :inline="true"
:hide-required-asterisk="true" :hide-required-asterisk="true"
label-suffix="" label-suffix=""
:show-message="false"
> >
<el-form-item label="" prop="name" style="width: 200px;"> <el-form-item label="" prop="name" style="width: 200px;">
<el-input <el-input
@ -171,7 +172,7 @@ const getGroupList = () => {
$api.getGroupList() $api.getGroupList()
.then(({ data }) => { .then(({ data }) => {
groupList.value = data groupList.value = data
groupForm.index = data.length // groupForm.index = data.length
}) })
.finally(() => loading.value = false) .finally(() => loading.value = false)
} }

View File

@ -132,20 +132,32 @@
<span> {{ $tools.formatNetSpeed(netstatInfo.netTotal?.inputMb) || 0 }}</span> <span> {{ $tools.formatNetSpeed(netstatInfo.netTotal?.inputMb) || 0 }}</span>
</div> </div>
</div> </div>
<div class="fields terminal"> <div class="field actions">
<el-dropdown class="web-ssh" type="primary" trigger="click"> <svg-icon
<!-- <el-button type="primary" @click="handleSSH">Web SSH</el-button> --> name="icon-zhongduanguanli24"
<el-button type="primary">功能</el-button> title="终端"
<template #dropdown> class="actions-icon"
<el-dropdown-menu> @click="handleSSH"
<el-dropdown-item @click="handleSSH">连接终端</el-dropdown-item> />
<el-dropdown-item v-if="consoleUrl" @click="handleToConsole">控制台</el-dropdown-item> <svg-icon
<el-dropdown-item @click="handleUpdate">修改服务器</el-dropdown-item> v-show="consoleUrl"
<el-dropdown-item @click="handleRemoveHost"><span style="color: #727272;">移除主机</span></el-dropdown-item> name="icon-a-zu391"
<el-dropdown-item @click="handleRemoveSSH"><span style="color: #727272;">移除凭证</span></el-dropdown-item> title="服务商控制台"
</el-dropdown-menu> class="actions-icon"
</template> @click="handleToConsole"
</el-dropdown> />
<svg-icon
name="icon-bianji1"
title="编辑"
class="actions-icon"
@click="handleUpdate"
/>
<svg-icon
name="icon-shanchu1"
title="删除"
class="actions-icon"
@click="handleRemoveHost"
/>
</div> </div>
</div> </div>
<SSHForm v-model:show="sshFormVisible" :temp-host="tempHost" :name="name" /> <SSHForm v-model:show="sshFormVisible" :temp-host="tempHost" :name="name" />
@ -155,6 +167,7 @@
<script setup> <script setup>
import { ref, computed, getCurrentInstance } from 'vue' import { ref, computed, getCurrentInstance } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import SSHForm from './ssh-form.vue' import SSHForm from './ssh-form.vue'
const { proxy: { $api, $tools } } = getCurrentInstance() const { proxy: { $api, $tools } } = getCurrentInstance()
@ -208,8 +221,8 @@ const setColor = (num) => {
} }
const handleUpdate = () => { const handleUpdate = () => {
let { expired, expiredNotify, group, consoleUrl, remark } = props.hostInfo let { expired, expiredNotify, group, consoleUrl, remark, index } = props.hostInfo
emit('update-host', { name: name.value, host: host.value, expired, expiredNotify, group, consoleUrl, remark }) emit('update-host', { name: name.value, host: host.value, index, expired, expiredNotify, group, consoleUrl, remark })
} }
const handleToConsole = () => { const handleToConsole = () => {
@ -353,6 +366,16 @@ const handleRemoveHost = async () => {
} }
} }
.actions {
.actions-icon {
margin: 0 10px;
width: 16px;
height: 16px;
color: #1989fa;
cursor: pointer;
}
}
.web-ssh { .web-ssh {
// ::v-deep has been deprecated. Use :deep(<inner-selector>) instead. // ::v-deep has been deprecated. Use :deep(<inner-selector>) instead.

View File

@ -14,6 +14,7 @@
:hide-required-asterisk="true" :hide-required-asterisk="true"
label-suffix="" label-suffix=""
label-width="100px" label-width="100px"
:show-message="false"
> >
<transition-group <transition-group
name="list" name="list"
@ -34,27 +35,27 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item key="name" label="主机别名" prop="name"> <el-form-item key="name" label="服务器名称" prop="name">
<el-input <el-input
v-model.trim="hostForm.name" v-model.trim="hostForm.name"
clearable clearable
placeholder="主机别名" placeholder=""
autocomplete="off" autocomplete="off"
/> />
</el-form-item> </el-form-item>
<el-form-item key="host" label="IP/域名" prop="host"> <el-form-item key="host" label="服务器IP" prop="host">
<el-input <el-input
v-model.trim="hostForm.host" v-model.trim="hostForm.host"
clearable clearable
placeholder="IP/域名" placeholder=""
autocomplete="off" autocomplete="off"
@keyup.enter="handleSave"
/> />
</el-form-item> </el-form-item>
<el-form-item key="expired" label="到期时间" prop="expired"> <el-form-item key="expired" label="到期时间" prop="expired">
<el-date-picker <el-date-picker
v-model="hostForm.expired" v-model="hostForm.expired"
type="date" type="date"
style="width: 100%;"
value-format="x" value-format="x"
placeholder="服务器到期时间" placeholder="服务器到期时间"
/> />
@ -73,11 +74,19 @@
/> />
</el-tooltip> </el-tooltip>
</el-form-item> </el-form-item>
<el-form-item key="index" label="序号" prop="index">
<el-input
v-model.trim.number="hostForm.index"
clearable
placeholder="用于服务器列表中排序(填写数字)"
autocomplete="off"
/>
</el-form-item>
<el-form-item key="consoleUrl" label="控制台URL" prop="consoleUrl"> <el-form-item key="consoleUrl" label="控制台URL" prop="consoleUrl">
<el-input <el-input
v-model.trim="hostForm.consoleUrl" v-model.trim="hostForm.consoleUrl"
clearable clearable
placeholder="用于直达服务器控制台" placeholder="用于直达云服务商控制台"
autocomplete="off" autocomplete="off"
@keyup.enter="handleSave" @keyup.enter="handleSave"
/> />
@ -89,7 +98,7 @@
:rows="3" :rows="3"
clearable clearable
autocomplete="off" autocomplete="off"
placeholder="用于简单记录服务器用途" placeholder="简单记录服务器用途"
/> />
</el-form-item> </el-form-item>
</transition-group> </transition-group>
@ -125,6 +134,7 @@ const resetForm = () => ({
group: 'default', group: 'default',
name: '', name: '',
host: '', host: '',
index: 0,
expired: null, expired: null,
expiredNotify: false, expiredNotify: false,
consoleUrl: '', consoleUrl: '',
@ -138,6 +148,7 @@ const rules = reactive({
group: { required: true, message: '选择一个分组' }, group: { required: true, message: '选择一个分组' },
name: { required: true, message: '输入主机别名', trigger: 'change' }, name: { required: true, message: '输入主机别名', trigger: 'change' },
host: { required: true, message: '输入IP/域名', trigger: 'change' }, host: { required: true, message: '输入IP/域名', trigger: 'change' },
index: { required: true, type: 'number', message: '输入数字', trigger: 'change' },
expired: { required: false }, expired: { required: false },
expiredNotify: { required: false }, expiredNotify: { required: false },
consoleUrl: { required: false }, consoleUrl: { required: false },
@ -174,9 +185,10 @@ const handleClosed = () => {
const setDefaultData = () => { const setDefaultData = () => {
if (!props.defaultData) return if (!props.defaultData) return
let { name, host, expired, expiredNotify, consoleUrl, group, remark } = props.defaultData console.log(props.defaultData)
let { name, host, index, expired, expiredNotify, consoleUrl, group, remark } = props.defaultData
oldHost.value = host oldHost.value = host
Object.assign(hostForm, { name, host, expired, expiredNotify, consoleUrl, group, remark }) Object.assign(hostForm, { name, host, index, expired, expiredNotify, consoleUrl, group, remark })
} }
const handleSave = () => { const handleSave = () => {

View File

@ -1,4 +1,11 @@
<template> <template>
<div class="server_group_container">
<div class="server_group_header">
<el-button type="primary" @click="hostFormVisible = true">添加服务器</el-button>
<el-button type="primary" @click="handleHiddenIP">
{{ hiddenIp ? '显示IP' : '隐藏IP' }}
</el-button>
</div>
<div class="server_group_collapse"> <div class="server_group_collapse">
<el-collapse v-model="activeGroup"> <el-collapse v-model="activeGroup">
<el-collapse-item v-for="(servers, groupName) in resList" :key="groupName" :name="groupName"> <el-collapse-item v-for="(servers, groupName) in resList" :key="groupName" :name="groupName">
@ -20,6 +27,13 @@
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>
</div> </div>
<HostForm
v-model:show="hostFormVisible"
:default-data="updateHostData"
@update-list="handleUpdateList"
@closed="updateHostData = null"
/>
</div>
</template> </template>
<script setup> <script setup>
@ -150,6 +164,13 @@ onBeforeUnmount(() => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.server_group_container {
.server_group_header {
padding: 15px;
display: flex;
align-items: center;
justify-content: end;
}
.server_group_collapse { .server_group_collapse {
.group_title { .group_title {
margin: 0 15px; margin: 0 15px;
@ -161,4 +182,5 @@ onBeforeUnmount(() => {
padding-top: 25px; padding-top: 25px;
} }
} }
}
</style> </style>

View File

@ -10,9 +10,9 @@
<el-tab-pane label="登录日志"> <el-tab-pane label="登录日志">
<Record /> <Record />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="主机排序" lazy> <!-- <el-tab-pane label="主机排序" lazy>
<Sort @update-list="emitUpdateList" /> <Sort @update-list="emitUpdateList" />
</el-tab-pane> </el-tab-pane> -->
<el-tab-pane label="全局通知" lazy> <el-tab-pane label="全局通知" lazy>
<NotifyList /> <NotifyList />
</el-tab-pane> </el-tab-pane>
@ -27,7 +27,7 @@
import { computed } from 'vue' import { computed } from 'vue'
import NotifyList from './components/notify-list.vue' import NotifyList from './components/notify-list.vue'
import EmailList from './components/email-list.vue' import EmailList from './components/email-list.vue'
import Sort from './components/sort.vue' // import Sort from './components/sort.vue'
import Record from './components/record.vue' import Record from './components/record.vue'
// import Group from './components/group.vue' // import Group from './components/group.vue'
import Password from './components/password.vue' import Password from './components/password.vue'