diff --git a/server/app/controller/host.js b/server/app/controller/host.js index 1a0a84a..7f2d971 100644 --- a/server/app/controller/host.js +++ b/server/app/controller/host.js @@ -5,11 +5,15 @@ async function getHostList({ res }) { let data = await readHostList() data?.sort((a, b) => Number(b.index || 0) - Number(a.index || 0)) for (const item of data) { - let { username, port, authType, _id: id, credential } = item - // console.log('解密凭证title: ', credential) - if (credential) credential = await AESDecryptSync(credential) - const isConfig = Boolean(username && port && (item[authType])) - Object.assign(item, { id, isConfig, password: '', privateKey: '', credential }) + try { + let { username, port, authType, _id: id, credential } = item + // console.log('解密凭证title: ', credential) + if (credential) credential = await AESDecryptSync(credential) + const isConfig = Boolean(username && port && (item[authType])) + Object.assign(item, { id, isConfig, password: '', privateKey: '', credential }) + } catch (error) { + consola.error('getHostList error: ', error.message) + } } res.success({ data }) } @@ -119,13 +123,13 @@ async function removeHost({ hostList.splice(hostIdx, 1) } writeHostList(hostList) - res.success({ data: `${ host }已移除` }) + res.success({ data: '已移除' }) } async function importHost({ res, request }) { - let { body: { importHost } } = request + let { body: { importHost, isEasyNodeJson = false } } = request if (!Array.isArray(importHost)) return res.fail({ msg: '参数错误' }) let hostList = await readHostList() // 过滤已存在的host @@ -134,15 +138,26 @@ async function importHost({ let newHostListLen = newHostList.length if (newHostListLen === 0) return res.fail({ msg: '导入的实例已存在' }) - let extraFiels = { - expired: null, expiredNotify: false, group: 'default', consoleUrl: '', remark: '', - authType: 'privateKey', password: '', privateKey: '', credential: '', command: '' + if (isEasyNodeJson) { + newHostList = newHostList.map((item) => { + item.credential = '' + item.isConfig = false + delete item.id + delete item.isConfig + return item + }) + } else { + 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 = newHostListLen - index + return Object.assign(item, { ...extraFiels }) + }) + } - newHostList = newHostList.map((item, index) => { - item.port = Number(item.port) || 0 - item.index = newHostListLen - index - return Object.assign(item, { ...extraFiels }) - }) hostList.push(...newHostList) writeHostList(hostList) res.success({ data: { len: newHostList.length } }) diff --git a/server/app/socket/clients.js b/server/app/socket/clients.js index 631f89b..63fc8be 100644 --- a/server/app/socket/clients.js +++ b/server/app/socket/clients.js @@ -15,7 +15,7 @@ async function getClientsInfo(clientSockets) { }) hostList .map(({ host, name }) => { - if (clientSockets.some(item => item.host === host)) return { name, isIo: true } // 已经建立io连接(无论是否连接成功)的host不再重复建立连接 + if (clientSockets.some(item => item.host === host)) return { name, isIo: true } // 已经建立io连接(无论是否连接成功)的host不再重复建立连接,因为存在多次(reconnectionAttempts)的重试机制 let clientSocket = ClientIO(`http://${ host }:${ clientPort }`, { path: '/client/os-info', forceNew: true, @@ -34,7 +34,7 @@ async function getClientsInfo(clientSockets) { .forEach((item) => { if (item.isIo) return // console.log('已经建立io连接的host不再重复建立连接', item.name) const { host, name, clientSocket } = item - clientsData[host] = { connect: false } + // clientsData[host] = { connect: false } clientSocket .on('connect', () => { consola.success('client connect success:', host, name) diff --git a/web/src/plugins/tools.js b/web/src/plugins/tools.js index 4f92f65..ce6e9c3 100644 --- a/web/src/plugins/tools.js +++ b/web/src/plugins/tools.js @@ -17,7 +17,7 @@ export default { return `${ (netSpeedMB * 1024).toFixed(1) } KB/s` }, // format: time OR date - formatTimestamp: (timestamp, format = 'time') => { + formatTimestamp: (timestamp, format = 'time', afterSeparator = ':') => { if(typeof(timestamp) !== 'number') return '--' let date = new Date(timestamp) let padZero = (num) => String(num).padStart(2, '0') @@ -31,9 +31,9 @@ export default { case 'date': return `${ year }-${ mounth }-${ day }` case 'time': - return `${ year }-${ mounth }-${ day } ${ hours }:${ minute }:${ second }` + return `${ year }-${ mounth }-${ day } ${ hours }${ afterSeparator }${ minute }${ afterSeparator }${ second }` default: - return `${ year }-${ mounth }-${ day } ${ hours }:${ minute }:${ second }` + return `${ year }-${ mounth }-${ day } ${ hours }${ afterSeparator }${ minute }${ afterSeparator }${ second }` } }, ping diff --git a/web/src/utils/index.js b/web/src/utils/index.js index bb8492d..713e216 100644 --- a/web/src/utils/index.js +++ b/web/src/utils/index.js @@ -114,3 +114,17 @@ export const downloadFile = ({ buffer, name }) => { export const getSuffix = (name = '') => { return String(name).split(/\./).pop() } + +export const exportFile = (data, filename, mimeType = 'application/json') =>{ + const blob = new Blob([JSON.stringify(data),], { type: mimeType }) + const url = window.URL.createObjectURL(blob) + + const link = document.createElement('a') + link.href = url + link.setAttribute('download', filename) + + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + window.URL.revokeObjectURL(url) +} diff --git a/web/src/views/server/components/host-table.vue b/web/src/views/server/components/host-table.vue index 54153d8..5cdb8da 100644 --- a/web/src/views/server/components/host-table.vue +++ b/web/src/views/server/components/host-table.vue @@ -4,6 +4,8 @@ ref="tableRef" :data="hosts" row-key="host" + :default-sort="defaultSort" + @sort-change="handleSortChange" @selection-change="handleSelectionChange" > @@ -43,8 +45,18 @@ - - + + @@ -53,9 +65,15 @@ - + @@ -70,7 +88,7 @@ > 连接终端 - 修改 + 配置 删除 @@ -127,6 +145,15 @@ const handleOnekey = async (row) => { $router.push({ path: '/onekey', query: { host, execClientInstallScript: 'true' } }) } +let defaultSortLocal = localStorage.getItem('host_table_sort') +defaultSortLocal = defaultSortLocal ? JSON.parse(defaultSortLocal) : { prop: 'index', order: 'ascending' } +let defaultSort = ref(defaultSortLocal) + +const handleSortChange = (sortObj) => { + defaultSort.value = sortObj + localStorage.setItem('host_table_sort', JSON.stringify(sortObj)) +} + let selectHosts = ref([]) const handleSelectionChange = (val) => { // console.log('select: ', val) diff --git a/web/src/views/server/components/import-host.vue b/web/src/views/server/components/import-host.vue index 4b1f9e8..82cd421 100644 --- a/web/src/views/server/components/import-host.vue +++ b/web/src/views/server/components/import-host.vue @@ -24,7 +24,7 @@ @change="handleCsvFile" > -
  • +
  • FinalShell (json) @@ -35,19 +35,24 @@ multiple name="jsonInput" style="display: none;" + @click.stop @change="handleJsonFile" >
  • +
  • + + EadyNode + (json) +
  • - -