diff --git a/backend/services/connection_service.go b/backend/services/connection_service.go index 2dbd532..4f5727d 100644 --- a/backend/services/connection_service.go +++ b/backend/services/connection_service.go @@ -367,10 +367,30 @@ func (c *connectionService) SaveLastDB(name string, db int) (resp types.JSResp) return } - param.LastDB = db - if err := c.conns.UpdateConnection(name, param.ConnectionConfig); err != nil { - resp.Msg = "save connection fail:" + err.Error() - return + if param.LastDB != db { + param.LastDB = db + if err := c.conns.UpdateConnection(name, param.ConnectionConfig); err != nil { + resp.Msg = "save connection fail:" + err.Error() + return + } + } + resp.Success = true + return +} + +// SaveRefreshInterval save auto refresh interval +func (c *connectionService) SaveRefreshInterval(name string, interval int) (resp types.JSResp) { + param := c.conns.GetConnection(name) + if param == nil { + resp.Msg = "no connection named \"" + name + "\"" + return + } + if param.RefreshInterval != interval { + param.RefreshInterval = interval + if err := c.conns.UpdateConnection(name, param.ConnectionConfig); err != nil { + resp.Msg = "save connection fail:" + err.Error() + return + } } resp.Success = true return diff --git a/backend/storage/connections.go b/backend/storage/connections.go index 4065441..9681e79 100644 --- a/backend/storage/connections.go +++ b/backend/storage/connections.go @@ -26,19 +26,20 @@ func (c *ConnectionsStorage) defaultConnections() types.Connections { func (c *ConnectionsStorage) defaultConnectionItem() types.ConnectionConfig { return types.ConnectionConfig{ - Name: "", - Addr: "127.0.0.1", - Port: 6379, - Username: "", - Password: "", - DefaultFilter: "*", - KeySeparator: ":", - ConnTimeout: 60, - ExecTimeout: 60, - DBFilterType: "none", - DBFilterList: []int{}, - LoadSize: consts.DEFAULT_LOAD_SIZE, - MarkColor: "", + Name: "", + Addr: "127.0.0.1", + Port: 6379, + Username: "", + Password: "", + DefaultFilter: "*", + KeySeparator: ":", + ConnTimeout: 60, + ExecTimeout: 60, + DBFilterType: "none", + DBFilterList: []int{}, + LoadSize: consts.DEFAULT_LOAD_SIZE, + MarkColor: "", + RefreshInterval: 5, Sentinel: types.ConnectionSentinel{ Master: "mymaster", }, diff --git a/backend/types/connection.go b/backend/types/connection.go index 1135b7b..dbebb3a 100644 --- a/backend/types/connection.go +++ b/backend/types/connection.go @@ -3,26 +3,27 @@ package types type ConnectionCategory int type ConnectionConfig struct { - Name string `json:"name" yaml:"name"` - Group string `json:"group,omitempty" yaml:"-"` - LastDB int `json:"lastDB" yaml:"last_db"` - Addr string `json:"addr,omitempty" yaml:"addr,omitempty"` - Port int `json:"port,omitempty" yaml:"port,omitempty"` - Username string `json:"username,omitempty" yaml:"username,omitempty"` - Password string `json:"password,omitempty" yaml:"password,omitempty"` - DefaultFilter string `json:"defaultFilter,omitempty" yaml:"default_filter,omitempty"` - KeySeparator string `json:"keySeparator,omitempty" yaml:"key_separator,omitempty"` - ConnTimeout int `json:"connTimeout,omitempty" yaml:"conn_timeout,omitempty"` - ExecTimeout int `json:"execTimeout,omitempty" yaml:"exec_timeout,omitempty"` - DBFilterType string `json:"dbFilterType" yaml:"db_filter_type,omitempty"` - DBFilterList []int `json:"dbFilterList" yaml:"db_filter_list,omitempty"` - KeyView int `json:"keyView,omitempty" yaml:"key_view,omitempty"` - LoadSize int `json:"loadSize,omitempty" yaml:"load_size,omitempty"` - MarkColor string `json:"markColor,omitempty" yaml:"mark_color,omitempty"` - SSL ConnectionSSL `json:"ssl,omitempty" yaml:"ssl,omitempty"` - SSH ConnectionSSH `json:"ssh,omitempty" yaml:"ssh,omitempty"` - Sentinel ConnectionSentinel `json:"sentinel,omitempty" yaml:"sentinel,omitempty"` - Cluster ConnectionCluster `json:"cluster,omitempty" yaml:"cluster,omitempty"` + Name string `json:"name" yaml:"name"` + Group string `json:"group,omitempty" yaml:"-"` + LastDB int `json:"lastDB" yaml:"last_db"` + Addr string `json:"addr,omitempty" yaml:"addr,omitempty"` + Port int `json:"port,omitempty" yaml:"port,omitempty"` + Username string `json:"username,omitempty" yaml:"username,omitempty"` + Password string `json:"password,omitempty" yaml:"password,omitempty"` + DefaultFilter string `json:"defaultFilter,omitempty" yaml:"default_filter,omitempty"` + KeySeparator string `json:"keySeparator,omitempty" yaml:"key_separator,omitempty"` + ConnTimeout int `json:"connTimeout,omitempty" yaml:"conn_timeout,omitempty"` + ExecTimeout int `json:"execTimeout,omitempty" yaml:"exec_timeout,omitempty"` + DBFilterType string `json:"dbFilterType" yaml:"db_filter_type,omitempty"` + DBFilterList []int `json:"dbFilterList" yaml:"db_filter_list,omitempty"` + KeyView int `json:"keyView,omitempty" yaml:"key_view,omitempty"` + LoadSize int `json:"loadSize,omitempty" yaml:"load_size,omitempty"` + MarkColor string `json:"markColor,omitempty" yaml:"mark_color,omitempty"` + RefreshInterval int `json:"refreshInterval,omitempty" yaml:"refreshInterval,omitempty"` + SSL ConnectionSSL `json:"ssl,omitempty" yaml:"ssl,omitempty"` + SSH ConnectionSSH `json:"ssh,omitempty" yaml:"ssh,omitempty"` + Sentinel ConnectionSentinel `json:"sentinel,omitempty" yaml:"sentinel,omitempty"` + Cluster ConnectionCluster `json:"cluster,omitempty" yaml:"cluster,omitempty"` } type Connection struct { diff --git a/frontend/package.json.md5 b/frontend/package.json.md5 index 0df9029..a3c5b28 100755 --- a/frontend/package.json.md5 +++ b/frontend/package.json.md5 @@ -1 +1 @@ -0024a462d0c3d76d35aeb433518d8b5e +c2681c210327633ae1a043d772209dc7 \ No newline at end of file diff --git a/frontend/src/components/content/ContentPane.vue b/frontend/src/components/content/ContentPane.vue index 13e5935..b1d95cd 100644 --- a/frontend/src/components/content/ContentPane.vue +++ b/frontend/src/components/content/ContentPane.vue @@ -124,7 +124,9 @@ watch( {{ $t('interface.sub_tab.status') }} - + diff --git a/frontend/src/components/content_value/ContentServerStatus.vue b/frontend/src/components/content_value/ContentServerStatus.vue index 206fed8..f080456 100644 --- a/frontend/src/components/content_value/ContentServerStatus.vue +++ b/frontend/src/components/content_value/ContentServerStatus.vue @@ -13,13 +13,16 @@ import dayjs from 'dayjs' import { convertBytes, formatBytes } from '@/utils/byte_convert.js' import usePreferencesStore from 'stores/preferences.js' import { useI18n } from 'vue-i18n' +import useConnectionStore from 'stores/connections.js' const props = defineProps({ server: String, + pause: Boolean, }) const browserStore = useBrowserStore() const prefStore = usePreferencesStore() +const connectionStore = useConnectionStore() const i18n = useI18n() const themeVars = useThemeVars() const serverInfo = ref({}) @@ -125,13 +128,19 @@ const isLoading = computed(() => { }) const startAutoRefresh = async () => { + // connectionStore.getRefreshInterval() let lastExec = Date.now() do { if (!pageState.autoRefresh) { break } await timeout(100) - if (pageState.loading || pageState.autoLoading || Date.now() - lastExec < pageState.refreshInterval * 1000) { + if ( + props.pause || + pageState.loading || + pageState.autoLoading || + Date.now() - lastExec < pageState.refreshInterval * 1000 + ) { continue } lastExec = Date.now() @@ -147,13 +156,23 @@ const stopAutoRefresh = () => { const onToggleRefresh = (on) => { if (on) { tabVal.value = 'activity' + connectionStore.saveRefreshInterval(props.server, pageState.refreshInterval || 5) startAutoRefresh() } else { + connectionStore.saveRefreshInterval(props.server, -1) stopAutoRefresh() } } onMounted(() => { + const interval = connectionStore.getRefreshInterval(props.server) + if (interval >= 0) { + pageState.autoRefresh = true + pageState.refreshInterval = interval === 0 ? 5 : interval + onToggleRefresh(true) + } else { + setTimeout(refreshInfo, 5000) + } refreshInfo() }) @@ -208,15 +227,15 @@ const totalKeys = computed(() => { return sum(toArray(nums)) }) -const tabVal = ref('info') -const envFilter = reactive({ +const tabVal = ref('activity') +const infoFilter = reactive({ keyword: '', group: 'CPU', }) -const env = computed(() => { - if (!isEmpty(envFilter.group)) { - const val = serverInfo.value[envFilter.group] +const info = computed(() => { + if (!isEmpty(infoFilter.group)) { + const val = serverInfo.value[infoFilter.group] if (!isEmpty(val)) { return map(val, (v, k) => ({ key: k, @@ -235,10 +254,10 @@ const env = computed(() => { }) const onFilterGroup = (group) => { - if (group === envFilter.group) { - envFilter.group = '' + if (group === infoFilter.group) { + infoFilter.group = '' } else { - envFilter.group = group + infoFilter.group = group } } @@ -345,6 +364,7 @@ const chartOption = { scales: { y: { beginAtZero: true, + stepSize: 1024, suggestedMin: 0, ticks: { precision: 0, @@ -365,7 +385,7 @@ const byteChartOption = { precision: 0, // format display y axios tag callback: function (value, index, values) { - return formatBytes(value, 0) + return formatBytes(value, 1) }, }, }, @@ -429,32 +449,30 @@ const byteChartOption = { @toggle="onToggleRefresh" /> - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - {{ k }} - - - - - - + + + + + + + {{ k }} + + + + + diff --git a/frontend/src/langs/en-us.json b/frontend/src/langs/en-us.json index 56d5903..56f90fa 100644 --- a/frontend/src/langs/en-us.json +++ b/frontend/src/langs/en-us.json @@ -359,8 +359,7 @@ "connected_clients": "Clients", "total_keys": "Keys", "memory_used": "Memory", - "all_info": "Information", - "env_info": "Environment", + "server_info": "Server Info", "activity_status": "Activity", "act_cmd": "Commands Per Second", "act_network_input": "Network Input", diff --git a/frontend/src/langs/zh-cn.json b/frontend/src/langs/zh-cn.json index a880b49..8a7a774 100644 --- a/frontend/src/langs/zh-cn.json +++ b/frontend/src/langs/zh-cn.json @@ -359,8 +359,7 @@ "connected_clients": "已连客户端", "total_keys": "键总数", "memory_used": "内存使用", - "all_info": "全部信息", - "env_info": "运行环境", + "server_info": "状态信息", "activity_status": "活动状态", "act_cmd": "命令执行数/秒", "act_network_input": "网络输入", diff --git a/frontend/src/stores/connections.js b/frontend/src/stores/connections.js index f856baa..d0dd572 100644 --- a/frontend/src/stores/connections.js +++ b/frontend/src/stores/connections.js @@ -9,6 +9,7 @@ import { RenameGroup, SaveConnection, SaveLastDB, + SaveRefreshInterval, SaveSortedConnection, } from 'wailsjs/go/services/connectionService.js' import { ConnectionType } from '@/consts/connection_type.js' @@ -31,6 +32,7 @@ const useConnectionStore = defineStore('connections', { * @property {string} defaultFilter * @property {string} keySeparator * @property {string} markColor + * @property {number} refreshInterval */ /** @@ -63,7 +65,7 @@ const useConnectionStore = defineStore('connections', { const conns = [] const groups = [] const profiles = {} - const { data = [{ groupName: '', connections: [] }] } = await ListConnection() + const { data = [{ groupName: '', connections: [], refreshInterval: 5 }] } = await ListConnection() for (const conn of data) { if (conn.type !== 'group') { // top level @@ -79,6 +81,7 @@ const useConnectionStore = defineStore('connections', { defaultFilter: conn.defaultFilter, keySeparator: conn.keySeparator, markColor: conn.markColor, + refreshInterval: conn.refreshInterval, } } else { // custom group @@ -99,6 +102,7 @@ const useConnectionStore = defineStore('connections', { defaultFilter: item.defaultFilter, keySeparator: item.keySeparator, markColor: item.markColor, + refreshInterval: conn.refreshInterval, } } conns.push({ @@ -369,6 +373,32 @@ const useConnectionStore = defineStore('connections', { const { keySeparator = ':' } = this.serverProfile[name] || {} return keySeparator }, + + /** + * get default status refresh interval by server name + * @param {string} name + * @return {number} + */ + getRefreshInterval(name) { + const { refreshInterval = 5 } = this.serverProfile[name] || {} + return refreshInterval + }, + + /** + * set and save default refresh interval + * @param {string} name + * @param {number} interval + * @return {Promise<{success: boolean}|{msg: undefined, success: boolean}>} + */ + async saveRefreshInterval(name, interval) { + const profile = this.serverProfile[name] || {} + profile.refreshInterval = interval + const { success, msg } = await SaveRefreshInterval(name, interval) + if (!success) { + return { success: false, msg } + } + return { success: true } + }, }, }) diff --git a/frontend/src/stores/preferences.js b/frontend/src/stores/preferences.js index c3f5ad0..9ccf470 100644 --- a/frontend/src/stores/preferences.js +++ b/frontend/src/stores/preferences.js @@ -277,10 +277,6 @@ const usePreferencesStore = defineStore('preferences', { return false }, - setAsideWidth(width) { - this.behavior.asideWidth = Math.max(width, 300) - }, - async checkForUpdate(manual = false) { let msgRef = null if (manual) { diff --git a/frontend/src/utils/theme.js b/frontend/src/utils/theme.js index c04c0a2..91a4797 100644 --- a/frontend/src/utils/theme.js +++ b/frontend/src/utils/theme.js @@ -71,6 +71,9 @@ export const themeOverrides = { optionTextColorHover: '#FFF', optionHeightMedium: '28px', }, + Divider: { + color: '#AAAAAB', + }, } /**