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 @@
-
-
+
+
-
+
-
+
-
-
+
+
-
-
+
+
-
+
{{ item.value }}
@@ -33,23 +83,56 @@
密码
凭据
-
+
本地私钥...
-
-
+
+
-
-
+
+
-
+
@@ -59,7 +142,12 @@
-
+
{{ item.name }}
@@ -70,28 +158,61 @@
-
+
+
-
+
-
+
-
+
-
+
-
+
@@ -195,7 +316,7 @@ const handleSelectPrivateKeyFile = (event) => {
let reader = new FileReader()
reader.onload = (e) => {
hostForm.privateKey = e.target.result
- privateKeyRef.value.value = ''
+ privateKeyRef.value = ''
}
reader.readAsText(file)
}
diff --git a/web/src/views/server/components/import-host.vue b/web/src/views/server/components/import-host.vue
new file mode 100644
index 0000000..4b1f9e8
--- /dev/null
+++ b/web/src/views/server/components/import-host.vue
@@ -0,0 +1,221 @@
+
+
+ 选择要导入的文件类型
+
+
+
+
+
+
+
diff --git a/web/src/views/server/index.vue b/web/src/views/server/index.vue
index 8a11d53..7acc992 100644
--- a/web/src/views/server/index.vue
+++ b/web/src/views/server/index.vue
@@ -5,11 +5,14 @@
{{ hiddenIp ? '显示IP' : '隐藏IP' }}
+ 导入实例
- 添加第一台实例配置
+ 添加实例配置
+ 或
+ 批量导入实例
@@ -38,6 +41,10 @@
@update-list="handleUpdateList"
@closed="updateHostData = null"
/>
+
@@ -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"