diff --git a/server/app/controller/host.js b/server/app/controller/host.js index 4a7fc47..7971e1e 100644 --- a/server/app/controller/host.js +++ b/server/app/controller/host.js @@ -86,38 +86,38 @@ async function removeHost({ if (hostIdx === -1) return res.fail({ msg: `${ host }不存在` }) hostList.splice(hostIdx, 1) writeHostList(hostList) - // 查询是否存在ssh记录 - // let sshRecord = await readSSHRecord() - // let sshIdx = sshRecord.findIndex(item => item.host === host) - // let flag = sshIdx !== -1 - // if (flag) sshRecord.splice(sshIdx, 1) - // writeSSHRecord(sshRecord) - - // res.success({ data: `${ host }已移除, ${ flag ? '并移除ssh记录' : '' }` }) res.success({ data: `${ host }已移除` }) } -// 原手动排序接口-废弃 -// async function updateHostSort({ res, request }) { -// let { body: { list } } = request -// if (!list) return res.fail({ msg: '参数错误' }) -// let hostList = await readHostList() -// if (hostList.length !== list.length) return res.fail({ msg: '失败: host数量不匹配' }) -// let sortResult = [] -// for (let i = 0; i < list.length; i++) { -// const curHost = list[i] -// let temp = hostList.find(({ host }) => curHost.host === host) -// if (!temp) return res.fail({ msg: `查找失败: ${ curHost.name }` }) -// sortResult.push(temp) -// } -// writeHostList(sortResult) -// res.success({ msg: 'success' }) -// } +async function importHost({ + res, request +}) { + let { body: { importHost } } = request + if (!Array.isArray(importHost)) return res.fail({ msg: '参数错误' }) + let hostList = await readHostList() + // 过滤已存在的host + let hostListSet = new Set(hostList.map(item => item.host)) + let newHostList = importHost.filter(item => !hostListSet.has(item.host)) + if (newHostList.length === 0) return res.fail({ msg: '导入的实例已存在' }) + + let extraFiels = { + expired: null, expiredNotify: false, group: 'default', consoleUrl: '', remark: '', + authType: 'privateKey', password: '', privateKey: '', credential: '', command: '' + } + newHostList = newHostList.map((item, index) => { + item.port = Number(item.port) || 0 + item.index = hostList.length + index + 1 + return Object.assign(item, { ...extraFiels }) + }) + hostList.push(...newHostList) + writeHostList(hostList) + res.success({ data: { len: newHostList.length } }) +} module.exports = { getHostList, addHost, updateHost, - removeHost - // updateHostSort + removeHost, + importHost } diff --git a/server/app/router/routes.js b/server/app/router/routes.js index b4794d8..6298eb2 100644 --- a/server/app/router/routes.js +++ b/server/app/router/routes.js @@ -1,5 +1,5 @@ const { getSSHList, addSSH, updateSSH, removeSSH, getCommand } = require('../controller/ssh') -const { getHostList, addHost, updateHost, removeHost } = require('../controller/host') +const { getHostList, addHost, updateHost, removeHost, importHost } = require('../controller/host') const { login, getpublicKey, updatePwd, getLoginRecord } = require('../controller/user') const { getSupportEmailList, getUserEmailList, updateUserEmailList, removeUserEmail, pushEmail, getNotifyList, updateNotifyList } = require('../controller/notify') const { getGroupList, addGroupList, updateGroupList, removeGroup } = require('../controller/group') @@ -51,12 +51,12 @@ const host = [ method: 'post', path: '/host-remove', controller: removeHost + }, + { + method: 'post', + path: '/import-host', + controller: importHost } - // { - // method: 'put', - // path: '/host-sort', - // controller: updateHostSort - // } ] const user = [ { diff --git a/web/index.html b/web/index.html index 58e00dd..ab3049e 100644 --- a/web/index.html +++ b/web/index.html @@ -4,7 +4,7 @@ EasyNode - + diff --git a/web/package.json b/web/package.json index 8f97ef5..eadee20 100644 --- a/web/package.json +++ b/web/package.json @@ -32,6 +32,7 @@ "axios": "^1.7.2", "codemirror": "^6.0.1", "crypto-js": "^4.2.0", + "csv-parse": "^5.5.6", "element-plus": "^2.7.6", "jsencrypt": "^3.3.2", "pinia": "^2.1.7", diff --git a/web/src/api/index.js b/web/src/api/index.js index 69393fd..16d2a2c 100644 --- a/web/src/api/index.js +++ b/web/src/api/index.js @@ -37,6 +37,9 @@ export default { removeHost(data) { return axios({ url: '/host-remove', method: 'post', data }) }, + importHost(data) { + return axios({ url: '/import-host', method: 'post', data }) + }, getPubPem() { return axios({ url: '/get-pub-pem', method: 'get' }) }, diff --git a/web/src/views/server/components/host-form.vue b/web/src/views/server/components/host-form.vue index 587f03b..a03656d 100644 --- a/web/src/views/server/components/host-form.vue +++ b/web/src/views/server/components/host-form.vue @@ -1,28 +1,78 @@ @@ -45,15 +52,18 @@ import { ref, getCurrentInstance, computed, watch } from 'vue' import HostCard from './components/host-card.vue' import HostForm from './components/host-form.vue' +import ImportHost from './components/import-host.vue' const { proxy: { $store, $message } } = getCurrentInstance() -const updateHostData = ref(null) -const hostFormVisible = ref(false) -const hiddenIp = ref(Number(localStorage.getItem('hiddenIp') || 0)) -const activeGroup = ref([]) +let updateHostData = ref(null) +let hostFormVisible = ref(false) +let importVisible = ref(false) -const handleUpdateList = async () => { +let hiddenIp = ref(Number(localStorage.getItem('hiddenIp') || 0)) +let activeGroup = ref([]) + +let handleUpdateList = async () => { try { await $store.getHostList() } catch (err) { @@ -62,12 +72,12 @@ const handleUpdateList = async () => { } } -const handleUpdateHost = (defaultData) => { +let handleUpdateHost = (defaultData) => { hostFormVisible.value = true updateHostData.value = defaultData } -const handleHiddenIP = () => { +let handleHiddenIP = () => { hiddenIp.value = hiddenIp.value ? 0 : 1 localStorage.setItem('hiddenIp', String(hiddenIp.value)) } @@ -124,6 +134,11 @@ let isNoHost = computed(() => Object.keys(groupHostList.value).length === 0) .host_card_container { padding-top: 25px; } + .or { + color: var(--el-text-color-secondary); + font-size: var(--el-font-size-base); + margin: 0 25px; + } } } diff --git a/yarn.lock b/yarn.lock index 016cf39..6109467 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1909,6 +1909,11 @@ csstype@^3.1.3: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== +csv-parse@^5.5.6: + version "5.5.6" + resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-5.5.6.tgz#0d726d58a60416361358eec291a9f93abe0b6b1a" + integrity sha512-uNpm30m/AGSkLxxy7d9yRXpJQFrZzVWLFBkS+6ngPcZkw/5k3L/jjFuj7tVnEpRn+QgmiXr21nDlhCiUK4ij2A== + date-fns@^2.30.0: version "2.30.0" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0"