diff --git a/mayfly_go_web/src/store/modules/themeConfig.ts b/mayfly_go_web/src/store/modules/themeConfig.ts index 0f22a192..50ec7425 100644 --- a/mayfly_go_web/src/store/modules/themeConfig.ts +++ b/mayfly_go_web/src/store/modules/themeConfig.ts @@ -107,11 +107,11 @@ const themeConfigModule: Module = { layout: 'classic', // ssh终端字体颜色 - terminalForeground: '#d0d0d0', + terminalForeground: '#c5c8c6', // ssh终端背景色 - terminalBackground: '#1c1c1c', + terminalBackground: '#121212', // ssh终端cursor色 - terminalCursor: '#e4c9af', + terminalCursor: '#f0cc09', terminalFontSize: 15, diff --git a/mayfly_go_web/src/views/ops/machine/SshTerminal.vue b/mayfly_go_web/src/views/ops/machine/SshTerminal.vue index 071edd40..259afe74 100644 --- a/mayfly_go_web/src/views/ops/machine/SshTerminal.vue +++ b/mayfly_go_web/src/views/ops/machine/SshTerminal.vue @@ -65,9 +65,9 @@ export default defineComponent({ // cursorStyle: 'underline', //光标样式 disableStdin: false, theme: { - foreground: getThemeConfig.value.terminalForeground || '#d0d0d0', //字体 - background: getThemeConfig.value.terminalBackground || '#1c1c1c', //背景色 - cursor: getThemeConfig.value.terminalCursor || '#e4c9af', //设置光标 + foreground: getThemeConfig.value.terminalForeground || '#c5c8c6', //字体 + background: getThemeConfig.value.terminalBackground || '#121212', //背景色 + cursor: getThemeConfig.value.terminalCursor || '#f0cc09', //设置光标 } as any, }); const fitAddon = new FitAddon(); diff --git a/mayfly_go_web/src/views/ops/redis/DataEdit.vue b/mayfly_go_web/src/views/ops/redis/DataEdit.vue deleted file mode 100644 index 6dea4b9c..00000000 --- a/mayfly_go_web/src/views/ops/redis/DataEdit.vue +++ /dev/null @@ -1,313 +0,0 @@ - - - \ No newline at end of file diff --git a/mayfly_go_web/src/views/ops/redis/DataOperation.vue b/mayfly_go_web/src/views/ops/redis/DataOperation.vue index 480043b0..2fa4cd59 100644 --- a/mayfly_go_web/src/views/ops/redis/DataOperation.vue +++ b/mayfly_go_web/src/views/ops/redis/DataOperation.vue @@ -23,7 +23,7 @@ scan - + + + string + hash + set +
keys: {{ dbsize }} @@ -69,17 +76,32 @@
- + - + + @@ -91,13 +113,17 @@ import { redisApi } from './api'; import { toRefs, reactive, defineComponent } from 'vue'; import { ElMessage, ElMessageBox } from 'element-plus'; import ProjectEnvSelect from '../component/ProjectEnvSelect.vue'; -import DataEdit from './DataEdit.vue'; +import HashValue from './HashValue.vue'; +import StringValue from './StringValue.vue'; +import SetValue from './SetValue.vue'; import { isTrue, notBlank, notNull } from '@/common/assert'; export default defineComponent({ name: 'DataOperation', components: { - DataEdit, + StringValue, + HashValue, + SetValue, ProjectEnvSelect, }, setup() { @@ -113,10 +139,6 @@ export default defineComponent({ count: 10, cursor: {}, }, - valueDialog: { - visible: false, - value: {}, - }, dataEdit: { visible: false, title: '新增数据', @@ -126,9 +148,15 @@ export default defineComponent({ timed: -1, key: '', }, - stringValue: '', - hashValue: [{ key: '', value: '' }], - setValue: [{ value: '' }], + }, + hashValueDialog: { + visible: false, + }, + stringValueDialog: { + visible: false, + }, + setValueDialog: { + visible: false, }, keys: [], dbsize: 0, @@ -158,10 +186,15 @@ export default defineComponent({ const scan = async () => { isTrue(state.scanParam.id != null, '请先选择redis'); notBlank(state.scanParam.count, 'count不能为空'); - isTrue(state.scanParam.count < 20001, 'count不能超过20000'); + + const match = state.scanParam.match; + if (!match || match == '*') { + isTrue(state.scanParam.count <= 200, 'match为空或者*时, count不能超过200'); + } else { + isTrue(state.scanParam.count <= 20000, 'count不能超过20000'); + } state.loading = true; - try { const res = await redisApi.scan.request(state.scanParam); state.keys = res.keys; @@ -207,60 +240,43 @@ export default defineComponent({ const getValue = async (row: any) => { const type = row.type; - const key = row.key; - - let res: any; - const reqParam = { - key: row.key, - id: state.scanParam.id, - }; - switch (type) { - case 'string': - res = await redisApi.getStringValue.request(reqParam); - break; - case 'hash': - res = await redisApi.getHashValue.request(reqParam); - break; - case 'set': - res = await redisApi.getSetValue.request(reqParam); - break; - default: - res = null; - break; - } - notNull(res, '暂不支持该类型数据查看'); - - if (type == 'string') { - state.dataEdit.stringValue = res; - } - if (type == 'set') { - state.dataEdit.setValue = res.map((x: any) => { - return { - value: x, - }; - }); - } - if (type == 'hash') { - const hash = []; - //遍历key和value - const keys = Object.keys(res); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - const value = res[key]; - hash.push({ - key, - value, - }); - } - state.dataEdit.hashValue = hash; - } state.dataEdit.keyInfo.type = type; state.dataEdit.keyInfo.timed = row.ttl; - state.dataEdit.keyInfo.key = key; + state.dataEdit.keyInfo.key = row.key; state.dataEdit.operationType = 2; - state.dataEdit.title = '修改数据'; - state.dataEdit.visible = true; + state.dataEdit.title = '查看数据'; + + if (type == 'hash') { + state.hashValueDialog.visible = true; + } else if (type == 'string') { + state.stringValueDialog.visible = true; + } else if (type == 'set') { + state.setValueDialog.visible = true; + } else { + ElMessage.warning('暂不支持该类型'); + } + }; + + const onAddData = (type: string) => { + notNull(state.scanParam.id, '请先选择redis'); + state.dataEdit.operationType = 1; + state.dataEdit.title = '新增数据'; + state.dataEdit.keyInfo.type = type; + state.dataEdit.keyInfo.timed = -1; + if (type == 'hash') { + state.hashValueDialog.visible = true; + } else if (type == 'string') { + state.stringValueDialog.visible = true; + } else if (type == 'set') { + state.setValueDialog.visible = true; + } else { + ElMessage.warning('暂不支持该类型'); + } + }; + + const onCancelDataEdit = () => { + state.dataEdit.keyInfo = {} as any; }; const del = (key: string) => { @@ -331,20 +347,6 @@ export default defineComponent({ } }; - const onAddData = () => { - notNull(state.scanParam.id, '请先选择redis'); - state.dataEdit.operationType = 1; - state.dataEdit.title = '新增数据'; - state.dataEdit.visible = true; - }; - - const onCancelDataEdit = () => { - state.dataEdit.keyInfo = {} as any; - state.dataEdit.stringValue = ''; - state.dataEdit.setValue = []; - state.dataEdit.hashValue = []; - }; - return { ...toRefs(state), changeProjectEnv, diff --git a/mayfly_go_web/src/views/ops/redis/HashValue.vue b/mayfly_go_web/src/views/ops/redis/HashValue.vue new file mode 100644 index 00000000..5ba5259a --- /dev/null +++ b/mayfly_go_web/src/views/ops/redis/HashValue.vue @@ -0,0 +1,254 @@ + + + \ No newline at end of file diff --git a/mayfly_go_web/src/views/ops/redis/SetValue.vue b/mayfly_go_web/src/views/ops/redis/SetValue.vue new file mode 100644 index 00000000..31d7292f --- /dev/null +++ b/mayfly_go_web/src/views/ops/redis/SetValue.vue @@ -0,0 +1,157 @@ + + + \ No newline at end of file diff --git a/mayfly_go_web/src/views/ops/redis/StringValue.vue b/mayfly_go_web/src/views/ops/redis/StringValue.vue new file mode 100644 index 00000000..b7f8b927 --- /dev/null +++ b/mayfly_go_web/src/views/ops/redis/StringValue.vue @@ -0,0 +1,169 @@ + + + \ No newline at end of file diff --git a/mayfly_go_web/src/views/ops/redis/api.ts b/mayfly_go_web/src/views/ops/redis/api.ts index 0962b72d..1cee5165 100644 --- a/mayfly_go_web/src/views/ops/redis/api.ts +++ b/mayfly_go_web/src/views/ops/redis/api.ts @@ -12,6 +12,9 @@ export const redisApi = { getStringValue: Api.create("/redis/{id}/string-value", 'get'), saveStringValue: Api.create("/redis/{id}/string-value", 'post'), getHashValue: Api.create("/redis/{id}/hash-value", 'get'), + hscan: Api.create("/redis/{id}/hscan", 'get'), + hget: Api.create("/redis/{id}/hget", 'get'), + hdel: Api.create("/redis/{id}/hdel", 'delete'), saveHashValue: Api.create("/redis/{id}/hash-value", 'post'), getSetValue: Api.create("/redis/{id}/set-value", 'get'), saveSetValue: Api.create("/redis/{id}/set-value", 'post'), diff --git a/server/internal/devops/api/redis.go b/server/internal/devops/api/redis.go index d89e3b0d..1d4bddb2 100644 --- a/server/internal/devops/api/redis.go +++ b/server/internal/devops/api/redis.go @@ -285,13 +285,6 @@ func (r *Redis) GetStringValue(rc *ctx.ReqCtx) { rc.ResData = str } -func (r *Redis) GetHashValue(rc *ctx.ReqCtx) { - ri, key := r.checkKey(rc) - res, err := ri.GetCmdable().HGetAll(context.TODO(), key).Result() - biz.ErrIsNilAppendErr(err, "获取hash值失败: %s") - rc.ResData = res -} - func (r *Redis) SetStringValue(rc *ctx.ReqCtx) { g := rc.GinCtx keyValue := new(form.StringValue) @@ -305,6 +298,45 @@ func (r *Redis) SetStringValue(rc *ctx.ReqCtx) { rc.ResData = str } +func (r *Redis) Hscan(rc *ctx.ReqCtx) { + ri, key := r.checkKey(rc) + g := rc.GinCtx + count := ginx.QueryInt(g, "count", 10) + match := g.Query("match") + cursor := ginx.QueryInt(g, "cursor", 0) + contextTodo := context.TODO() + + cmdable := ri.GetCmdable() + keys, nextCursor, err := cmdable.HScan(contextTodo, key, uint64(cursor), match, int64(count)).Result() + biz.ErrIsNilAppendErr(err, "hcan err: %s") + keySize, err := cmdable.HLen(contextTodo, key).Result() + biz.ErrIsNilAppendErr(err, "hlen err: %s") + + rc.ResData = map[string]interface{}{ + "keys": keys, + "cursor": nextCursor, + "keySize": keySize, + } +} + +func (r *Redis) Hdel(rc *ctx.ReqCtx) { + ri, key := r.checkKey(rc) + field := rc.GinCtx.Query("field") + + delRes, err := ri.GetCmdable().HDel(context.TODO(), key, field).Result() + biz.ErrIsNilAppendErr(err, "hdel err: %s") + rc.ResData = delRes +} + +func (r *Redis) Hget(rc *ctx.ReqCtx) { + ri, key := r.checkKey(rc) + field := rc.GinCtx.Query("field") + + res, err := ri.GetCmdable().HGet(context.TODO(), key, field).Result() + biz.ErrIsNilAppendErr(err, "hget err: %s") + rc.ResData = res +} + func (r *Redis) SetHashValue(rc *ctx.ReqCtx) { g := rc.GinCtx hashValue := new(form.HashValue) @@ -315,13 +347,12 @@ func (r *Redis) SetHashValue(rc *ctx.ReqCtx) { cmd := ri.GetCmdable() key := hashValue.Key - // 简单处理->先删除,后新增 - cmd.Del(context.TODO(), key) + contextTodo := context.TODO() for _, v := range hashValue.Value { - res := cmd.HSet(context.TODO(), key, v["key"].(string), v["value"]) + res := cmd.HSet(contextTodo, key, v["field"].(string), v["value"]) biz.ErrIsNilAppendErr(res.Err(), "保存hash值失败: %s") } - if hashValue.Timed != -1 { + if hashValue.Timed != 0 && hashValue.Timed != -1 { cmd.Expire(context.TODO(), key, time.Second*time.Duration(hashValue.Timed)) } } diff --git a/server/internal/devops/router/redis.go b/server/internal/devops/router/redis.go index 63a07e33..51a43626 100644 --- a/server/internal/devops/router/redis.go +++ b/server/internal/devops/router/redis.go @@ -64,9 +64,17 @@ func InitRedisRouter(router *gin.RouterGroup) { ctx.NewReqCtxWithGin(c).Handle(rs.SetStringValue) }) - // 获取hash类型值 - redis.GET(":id/hash-value", func(c *gin.Context) { - ctx.NewReqCtxWithGin(c).Handle(rs.GetHashValue) + // hscan + redis.GET(":id/hscan", func(c *gin.Context) { + ctx.NewReqCtxWithGin(c).Handle(rs.Hscan) + }) + + redis.GET(":id/hget", func(c *gin.Context) { + ctx.NewReqCtxWithGin(c).Handle(rs.Hget) + }) + + redis.DELETE(":id/hdel", func(c *gin.Context) { + ctx.NewReqCtxWithGin(c).Handle(rs.Hdel) }) // 设置hash类型值