easynode/web/src/store/index.js
2024-10-21 22:08:55 +08:00

201 lines
6.9 KiB
JavaScript

import { io } from 'socket.io-client'
import { defineStore, acceptHMRUpdate } from 'pinia'
import dayjs from 'dayjs'
import $api from '@/api'
import config from '@/config'
import { isHttps } from '@/utils'
const { defaultClientPort } = config
const useStore = defineStore({
id: 'global',
state: () => ({
serviceURI: null,
hostList: [],
groupList: [],
sshList: [],
scriptList: [],
localScriptList: [],
HostStatusSocket: null,
user: localStorage.getItem('user') || null,
token: sessionStorage.getItem('token') || localStorage.getItem('token') || null,
title: '',
isDark: false,
menuCollapse: localStorage.getItem('menuCollapse') === 'true',
defaultBackgroundImages: [
'linear-gradient(-225deg, #CBBACC 0%, #2580B3 100%)',
'linear-gradient(to top, #a18cd1 0%, #fbc2eb 100%)',
'linear-gradient(to top, #6a85b6 0%, #bac8e0 100%)',
'linear-gradient(to top, #7028e4 0%, #e5b2ca 100%)',
'linear-gradient(to top, #9be15d 0%, #00e3ae 100%)',
'linear-gradient(60deg, #abecd6 0%, #fbed96 100%)',
'linear-gradient(-20deg, #2b5876 0%, #4e4376 100%)',
'linear-gradient(to top, #1e3c72 0%, #1e3c72 1%, #2a5298 100%)',
'linear-gradient(to right, #243949 0%, #517fa4 100%)',
],
terminalConfig: {
...{
fontSize: 16,
themeName: 'Afterglow',
background: 'linear-gradient(-225deg, #CBBACC 0%, #2580B3 100%)',
quickCopy: isHttps(),
quickPaste: isHttps(),
autoExecuteScript: false
},
...(localStorage.getItem('terminalConfig') ? JSON.parse(localStorage.getItem('terminalConfig')) : {})
}
}),
actions: {
async setJwtToken(token, isSession = true) {
if (isSession) sessionStorage.setItem('token', token)
else localStorage.setItem('token', token)
this.$patch({ token })
},
async setUser(username) {
localStorage.setItem('user', username)
this.$patch({ user: username })
},
async setTitle(title) {
this.$patch({ title })
},
async removeJwtToken() {
localStorage.removeItem('token')
sessionStorage.removeItem('token')
this.$patch({ token: null })
},
async getMainData() {
await this.getGroupList()
await this.getHostList()
await this.getSSHList()
await this.getScriptList()
this.wsClientsStatus()
},
async getHostList() {
let { data: newHostList } = await $api.getHostList()
newHostList = newHostList.map(newHostObj => {
newHostObj.expired = dayjs(newHostObj.expired).format('YYYY-MM-DD')
const oldHostObj = this.hostList.find(({ id }) => id === newHostObj.id)
return oldHostObj ? Object.assign({}, { ...oldHostObj }, { ...newHostObj }) : newHostObj
})
this.$patch({ hostList: newHostList })
this.HostStatusSocket?.emit('refresh_clients_data')
},
async getGroupList() {
const { data: groupList } = await $api.getGroupList()
this.$patch({ groupList })
},
async getSSHList() {
const { data: sshList } = await $api.getSSHList()
this.$patch({ sshList })
},
async getScriptList() {
const { data: scriptList } = await $api.getScriptList()
this.$patch({ scriptList })
},
async getLocalScriptList() {
const { data: localScriptList } = await $api.getLocalScriptList()
this.$patch({ localScriptList })
},
setTerminalSetting(setTarget = {}) {
let newConfig = { ...this.terminalConfig, ...setTarget }
localStorage.setItem('terminalConfig', JSON.stringify(newConfig))
this.$patch({ terminalConfig: newConfig })
},
async wsClientsStatus() {
// if (this.HostStatusSocket) this.HostStatusSocket.close()
let socketInstance = io(this.serviceURI, {
path: '/clients',
forceNew: true,
reconnectionDelay: 5000,
reconnectionAttempts: 1000
})
this.HostStatusSocket = socketInstance
socketInstance.on('connect', () => {
console.log('clients websocket 已连接: ', socketInstance.id)
let token = this.token
socketInstance.emit('init_clients_data', { token })
socketInstance.on('clients_data', (data) => {
// console.log(data)
this.hostList.forEach(item => {
const { host, clientPort } = item
return Object.assign(item, { monitorData: Object.freeze(data[`${ host }:${ clientPort || defaultClientPort }`]) })
})
})
socketInstance.on('token_verify_fail', (message) => {
console.log('token 验证失败:', message)
// $router.push('/login')
})
})
socketInstance.on('disconnect', () => {
console.error('clients websocket 连接断开')
})
socketInstance.on('connect_error', (message) => {
console.error('clients websocket 连接出错: ', message)
})
},
setTheme(isDark, animate = true) {
// $store.setThemeConfig({ isDark: val })
const html = document.documentElement
let setAttribute = () => {
if (isDark) html.setAttribute('class', 'dark')
else html.setAttribute('class', '')
localStorage.setItem('isDark', isDark)
this.$patch({ isDark })
}
if (animate) {
let transition = document.startViewTransition(() => {
document.documentElement.classList.toggle('dark')
})
transition.ready.then(() => {
const centerX = 0
const centerY = 0
const radius = Math.hypot(
Math.max(centerX, window.innerWidth - centerX),
Math.max(centerY, window.innerHeight - centerY)
)
// console.log('radius: ', innerWidth, innerHeight, radius)
// 自定义动画
document.documentElement.animate(
{
clipPath: [
`circle(0% at ${ centerX }px ${ centerY }px)`,
`circle(${ radius }px at ${ centerX }px ${ centerY }px)`,
]
},
{
duration: 500,
pseudoElement: '::view-transition-new(root)'
}
)
setAttribute()
})
} else {
setAttribute()
}
},
setDefaultTheme() {
let isDark = false
if (localStorage.getItem('isDark')) {
isDark = localStorage.getItem('isDark') === 'true' ? true : false
} else {
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)')
const systemTheme = prefersDarkScheme.matches
console.log('当前系统使用的是深色模式:', systemTheme ? '是' : '否')
isDark = systemTheme
}
this.setTheme(isDark, false)
},
setMenuCollapse() {
let newState = !this.menuCollapse
localStorage.setItem('menuCollapse', newState)
this.$patch({ menuCollapse: newState })
}
}
})
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useStore, import.meta.hot))
}
export default useStore