Compare commits
No commits in common. "21c63e2ac2ffa22d6bd589b07f73e62ae32d8abe" and "e6b28c9edc4c7de7fd175959bb6febb1fdbce03b" have entirely different histories.
21c63e2ac2
...
e6b28c9edc
|
@ -1,6 +1,6 @@
|
||||||
## Tiny RDM Contribute Guide
|
## Tiny RDM Contribute Guide
|
||||||
|
|
||||||
### Multi-language Contributions
|
### Multi-language Contributions {#language}
|
||||||
|
|
||||||
#### Adding New Language
|
#### Adding New Language
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
```
|
```
|
||||||
4. Submit review once there are no issues with the translation context in the application. (learn how to submit)
|
4. Submit review once there are no issues with the translation context in the application. (learn how to submit)
|
||||||
|
|
||||||
### Code Submission`(To be completed)`
|
### Code Submission`(To be completed)` {#pull_request}
|
||||||
|
|
||||||
#### Pull Request Title
|
#### Pull Request Title
|
||||||
The format of PR's title like "<type>: <description>"
|
The format of PR's title like "<type>: <description>"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
## Tiny RDM 代码贡献指南
|
## Tiny RDM 代码贡献指南
|
||||||
|
|
||||||
### 多国语言贡献
|
### 多国语言贡献 {#language}
|
||||||
|
|
||||||
#### 增加新的语言
|
#### 增加新的语言
|
||||||
1. 创建文件:在[frontend/src/langs](../frontend/src/langs/)目录下新增语言配置JSON文件,文件名格式为“{语言}-{地区}.json”,如英文为“en-us.json”,简体中文为“zh-cn.json”,建议直接复制[en-us.json](../frontend/src/langs/en-us.json)文件进行改名。
|
1. 创建文件:在[frontend/src/langs](../frontend/src/langs/)目录下新增语言配置JSON文件,文件名格式为“{语言}-{地区}.json”,如英文为“en-us.json”,简体中文为“zh-cn.json”,建议直接复制[en-us.json](../frontend/src/langs/en-us.json)文件进行改名。
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
```
|
```
|
||||||
4. 检查应用中对应翻译语境无问题后,可提交审核([查看如何提交](#pull_request))
|
4. 检查应用中对应翻译语境无问题后,可提交审核([查看如何提交](#pull_request))
|
||||||
|
|
||||||
### 代码提交`(待完善)`
|
### 代码提交`(待完善)` {#pull_request}
|
||||||
|
|
||||||
#### PR提交规范
|
#### PR提交规范
|
||||||
PR提交格式为“<type>: <description>”
|
PR提交格式为“<type>: <description>”
|
||||||
|
|
|
@ -29,21 +29,11 @@ type slowLogItem struct {
|
||||||
Cost int64 `json:"cost"`
|
Cost int64 `json:"cost"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type entryCursor struct {
|
|
||||||
DB int
|
|
||||||
Type string
|
|
||||||
Key string
|
|
||||||
Pattern string
|
|
||||||
Cursor uint64
|
|
||||||
XLast string // last stream pos
|
|
||||||
}
|
|
||||||
|
|
||||||
type connectionItem struct {
|
type connectionItem struct {
|
||||||
client redis.UniversalClient
|
client redis.UniversalClient
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancelFunc context.CancelFunc
|
cancelFunc context.CancelFunc
|
||||||
cursor map[int]uint64 // current cursor of databases
|
cursor map[int]uint64 // current cursor of databases
|
||||||
entryCursor map[int]entryCursor // current entry cursor of databases
|
|
||||||
stepSize int64
|
stepSize int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +265,6 @@ func (b *browserService) getRedisClient(connName string, db int) (item connectio
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancelFunc: cancelFunc,
|
cancelFunc: cancelFunc,
|
||||||
cursor: map[int]uint64{},
|
cursor: map[int]uint64{},
|
||||||
entryCursor: map[int]entryCursor{},
|
|
||||||
stepSize: int64(selConn.LoadSize),
|
stepSize: int64(selConn.LoadSize),
|
||||||
}
|
}
|
||||||
if item.stepSize <= 0 {
|
if item.stepSize <= 0 {
|
||||||
|
@ -490,355 +479,14 @@ func (b *browserService) LoadAllKeys(connName string, db int, match, keyType str
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b.setClientCursor(connName, db, 0)
|
b.setClientCursor(connName, db, 0)
|
||||||
maxKeys := b.loadDBSize(ctx, client)
|
|
||||||
|
|
||||||
resp.Success = true
|
resp.Success = true
|
||||||
resp.Data = map[string]any{
|
resp.Data = map[string]any{
|
||||||
"keys": keys,
|
"keys": keys,
|
||||||
"maxKeys": maxKeys,
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetKeySummary get key summary info
|
|
||||||
func (b *browserService) GetKeySummary(param types.KeySummaryParam) (resp types.JSResp) {
|
|
||||||
item, err := b.getRedisClient(param.Server, param.DB)
|
|
||||||
if err != nil {
|
|
||||||
resp.Msg = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
client, ctx := item.client, item.ctx
|
|
||||||
key := strutil.DecodeRedisKey(param.Key)
|
|
||||||
var keyType string
|
|
||||||
var dur time.Duration
|
|
||||||
keyType, err = client.Type(ctx, key).Result()
|
|
||||||
if err != nil {
|
|
||||||
resp.Msg = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if keyType == "none" {
|
|
||||||
resp.Msg = "key not exists"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var data types.KeySummary
|
|
||||||
data.Type = strings.ToLower(keyType)
|
|
||||||
if dur, err = client.TTL(ctx, key).Result(); err != nil {
|
|
||||||
data.TTL = -1
|
|
||||||
} else {
|
|
||||||
if dur < 0 {
|
|
||||||
data.TTL = -1
|
|
||||||
} else {
|
|
||||||
data.TTL = int64(dur.Seconds())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.Size, _ = client.MemoryUsage(ctx, key, 0).Result()
|
|
||||||
switch data.Type {
|
|
||||||
case "string":
|
|
||||||
data.Length, _ = client.StrLen(ctx, key).Result()
|
|
||||||
case "list":
|
|
||||||
data.Length, _ = client.LLen(ctx, key).Result()
|
|
||||||
case "hash":
|
|
||||||
data.Length, _ = client.HLen(ctx, key).Result()
|
|
||||||
case "set":
|
|
||||||
data.Length, _ = client.SCard(ctx, key).Result()
|
|
||||||
case "zset":
|
|
||||||
data.Length, _ = client.ZCard(ctx, key).Result()
|
|
||||||
case "stream":
|
|
||||||
data.Length, _ = client.XLen(ctx, key).Result()
|
|
||||||
default:
|
|
||||||
resp.Msg = "unknown key type"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.Success = true
|
|
||||||
resp.Data = data
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeyDetail get key detail
|
|
||||||
func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JSResp) {
|
|
||||||
item, err := b.getRedisClient(param.Server, param.DB)
|
|
||||||
if err != nil {
|
|
||||||
resp.Msg = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
client, ctx, entryCors := item.client, item.ctx, item.entryCursor
|
|
||||||
key := strutil.DecodeRedisKey(param.Key)
|
|
||||||
var keyType string
|
|
||||||
keyType, err = client.Type(ctx, key).Result()
|
|
||||||
if err != nil {
|
|
||||||
resp.Msg = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if keyType == "none" {
|
|
||||||
resp.Msg = "key not exists"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var data types.KeyDetail
|
|
||||||
//var cursor uint64
|
|
||||||
matchPattern := param.MatchPattern
|
|
||||||
if len(matchPattern) <= 0 {
|
|
||||||
matchPattern = "*"
|
|
||||||
}
|
|
||||||
|
|
||||||
// define get entry cursor function
|
|
||||||
getEntryCursor := func() (uint64, string) {
|
|
||||||
if entry, ok := entryCors[param.DB]; !ok || entry.Key != key || entry.Pattern != matchPattern {
|
|
||||||
// not the same key or match pattern, reset cursor
|
|
||||||
entry = entryCursor{
|
|
||||||
DB: param.DB,
|
|
||||||
Key: key,
|
|
||||||
Pattern: matchPattern,
|
|
||||||
Cursor: 0,
|
|
||||||
}
|
|
||||||
entryCors[param.DB] = entry
|
|
||||||
return 0, ""
|
|
||||||
} else {
|
|
||||||
return entry.Cursor, entry.XLast
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// define set entry cursor function
|
|
||||||
setEntryCursor := func(cursor uint64) {
|
|
||||||
entryCors[param.DB] = entryCursor{
|
|
||||||
DB: param.DB,
|
|
||||||
Type: "",
|
|
||||||
Key: key,
|
|
||||||
Pattern: matchPattern,
|
|
||||||
Cursor: cursor,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// define set last stream pos function
|
|
||||||
setEntryXLast := func(last string) {
|
|
||||||
entryCors[param.DB] = entryCursor{
|
|
||||||
DB: param.DB,
|
|
||||||
Type: "",
|
|
||||||
Key: key,
|
|
||||||
Pattern: matchPattern,
|
|
||||||
XLast: last,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch strings.ToLower(keyType) {
|
|
||||||
case "string":
|
|
||||||
var str string
|
|
||||||
str, err = client.Get(ctx, key).Result()
|
|
||||||
data.Value, data.DecodeType, data.ViewAs = strutil.ConvertTo(str, param.DecodeType, param.ViewAs)
|
|
||||||
|
|
||||||
case "list":
|
|
||||||
loadListHandle := func() ([]string, bool, error) {
|
|
||||||
var items []string
|
|
||||||
var cursor uint64
|
|
||||||
if param.Full {
|
|
||||||
// load all
|
|
||||||
cursor = 0
|
|
||||||
items, err = client.LRange(ctx, key, 0, -1).Result()
|
|
||||||
} else {
|
|
||||||
cursor, _ = getEntryCursor()
|
|
||||||
scanSize := int64(Preferences().GetScanSize())
|
|
||||||
items, err = client.LRange(ctx, key, int64(cursor), int64(cursor)+scanSize-1).Result()
|
|
||||||
cursor = cursor + uint64(scanSize)
|
|
||||||
if len(items) < int(scanSize) {
|
|
||||||
cursor = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setEntryCursor(cursor)
|
|
||||||
if err != nil {
|
|
||||||
return items, false, err
|
|
||||||
}
|
|
||||||
return items, cursor == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data.Value, data.End, err = loadListHandle()
|
|
||||||
|
|
||||||
case "hash":
|
|
||||||
loadHashHandle := func() (map[string]string, bool, error) {
|
|
||||||
items := map[string]string{}
|
|
||||||
scanSize := int64(Preferences().GetScanSize())
|
|
||||||
var loadedVal []string
|
|
||||||
var cursor uint64
|
|
||||||
if param.Full {
|
|
||||||
// load all
|
|
||||||
cursor = 0
|
|
||||||
for {
|
|
||||||
loadedVal, cursor, err = client.HScan(ctx, key, cursor, "*", scanSize).Result()
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
for i := 0; i < len(loadedVal); i += 2 {
|
|
||||||
items[loadedVal[i]] = loadedVal[i+1]
|
|
||||||
}
|
|
||||||
if cursor == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cursor, _ = getEntryCursor()
|
|
||||||
loadedVal, cursor, err = client.HScan(ctx, key, cursor, matchPattern, scanSize).Result()
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
for i := 0; i < len(loadedVal); i += 2 {
|
|
||||||
items[loadedVal[i]] = loadedVal[i+1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setEntryCursor(cursor)
|
|
||||||
return items, cursor == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data.Value, data.End, err = loadHashHandle()
|
|
||||||
if err != nil {
|
|
||||||
resp.Msg = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case "set":
|
|
||||||
loadSetHandle := func() ([]string, bool, error) {
|
|
||||||
var items []string
|
|
||||||
var cursor uint64
|
|
||||||
scanSize := int64(Preferences().GetScanSize())
|
|
||||||
var loadedKey []string
|
|
||||||
if param.Full {
|
|
||||||
// load all
|
|
||||||
cursor = 0
|
|
||||||
for {
|
|
||||||
loadedKey, cursor, err = client.SScan(ctx, key, cursor, param.MatchPattern, scanSize).Result()
|
|
||||||
if err != nil {
|
|
||||||
return items, false, err
|
|
||||||
}
|
|
||||||
items = append(items, loadedKey...)
|
|
||||||
if cursor == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cursor, _ = getEntryCursor()
|
|
||||||
loadedKey, cursor, err = client.SScan(ctx, key, cursor, param.MatchPattern, scanSize).Result()
|
|
||||||
items = append(items, loadedKey...)
|
|
||||||
}
|
|
||||||
setEntryCursor(cursor)
|
|
||||||
return items, cursor == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data.Value, data.End, err = loadSetHandle()
|
|
||||||
if err != nil {
|
|
||||||
resp.Msg = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case "zset":
|
|
||||||
loadZSetHandle := func() ([]types.ZSetItem, bool, error) {
|
|
||||||
var items []types.ZSetItem
|
|
||||||
var cursor uint64
|
|
||||||
scanSize := int64(Preferences().GetScanSize())
|
|
||||||
var loadedVal []string
|
|
||||||
if param.Full {
|
|
||||||
// load all
|
|
||||||
cursor = 0
|
|
||||||
for {
|
|
||||||
loadedVal, cursor, err = client.ZScan(ctx, key, cursor, param.MatchPattern, scanSize).Result()
|
|
||||||
if err != nil {
|
|
||||||
return items, false, err
|
|
||||||
}
|
|
||||||
var score float64
|
|
||||||
for i := 0; i < len(loadedVal); i += 2 {
|
|
||||||
if score, err = strconv.ParseFloat(loadedVal[i+1], 64); err == nil {
|
|
||||||
items = append(items, types.ZSetItem{
|
|
||||||
Value: loadedVal[i],
|
|
||||||
Score: score,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cursor == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cursor, _ = getEntryCursor()
|
|
||||||
loadedVal, cursor, err = client.ZScan(ctx, key, cursor, param.MatchPattern, scanSize).Result()
|
|
||||||
var score float64
|
|
||||||
for i := 0; i < len(loadedVal); i += 2 {
|
|
||||||
if score, err = strconv.ParseFloat(loadedVal[i+1], 64); err == nil {
|
|
||||||
items = append(items, types.ZSetItem{
|
|
||||||
Value: loadedVal[i],
|
|
||||||
Score: score,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setEntryCursor(cursor)
|
|
||||||
return items, cursor == 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data.Value, data.End, err = loadZSetHandle()
|
|
||||||
if err != nil {
|
|
||||||
resp.Msg = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case "stream":
|
|
||||||
loadStreamHandle := func() ([]types.StreamItem, bool, error) {
|
|
||||||
var msgs []redis.XMessage
|
|
||||||
var items []types.StreamItem
|
|
||||||
var last string
|
|
||||||
if param.Full {
|
|
||||||
// load all
|
|
||||||
last = ""
|
|
||||||
msgs, err = client.XRevRange(ctx, key, "+", "-").Result()
|
|
||||||
} else {
|
|
||||||
scanSize := int64(Preferences().GetScanSize())
|
|
||||||
_, last = getEntryCursor()
|
|
||||||
if len(last) <= 0 {
|
|
||||||
last = "+"
|
|
||||||
}
|
|
||||||
if last != "+" {
|
|
||||||
// add 1 more item when continue scan
|
|
||||||
msgs, err = client.XRevRangeN(ctx, key, last, "-", scanSize+1).Result()
|
|
||||||
msgs = msgs[1:]
|
|
||||||
} else {
|
|
||||||
msgs, err = client.XRevRangeN(ctx, key, last, "-", scanSize).Result()
|
|
||||||
}
|
|
||||||
scanCount := len(msgs)
|
|
||||||
if scanCount <= 0 || scanCount < int(scanSize) {
|
|
||||||
last = ""
|
|
||||||
} else if scanCount > 0 {
|
|
||||||
last = msgs[scanCount-1].ID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setEntryXLast(last)
|
|
||||||
for _, msg := range msgs {
|
|
||||||
items = append(items, types.StreamItem{
|
|
||||||
ID: msg.ID,
|
|
||||||
Value: msg.Values,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return items, false, err
|
|
||||||
}
|
|
||||||
return items, last == "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data.Value, data.End, err = loadStreamHandle()
|
|
||||||
if err != nil {
|
|
||||||
resp.Msg = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
resp.Msg = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp.Success = true
|
|
||||||
resp.Data = data
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetKeyValue get value by key
|
// GetKeyValue get value by key
|
||||||
func (b *browserService) GetKeyValue(connName string, db int, k any, viewAs, decodeType string) (resp types.JSResp) {
|
func (b *browserService) GetKeyValue(connName string, db int, k any, viewAs, decodeType string) (resp types.JSResp) {
|
||||||
item, err := b.getRedisClient(connName, db)
|
item, err := b.getRedisClient(connName, db)
|
||||||
|
@ -1126,7 +774,6 @@ func (b *browserService) SetHashValue(connName string, db int, k any, field, new
|
||||||
key := strutil.DecodeRedisKey(k)
|
key := strutil.DecodeRedisKey(k)
|
||||||
var removedField []string
|
var removedField []string
|
||||||
updatedField := map[string]string{}
|
updatedField := map[string]string{}
|
||||||
replacedField := map[string]string{}
|
|
||||||
if len(field) <= 0 {
|
if len(field) <= 0 {
|
||||||
// old filed is empty, add new field
|
// old filed is empty, add new field
|
||||||
_, err = client.HSet(ctx, key, newField, value).Result()
|
_, err = client.HSet(ctx, key, newField, value).Result()
|
||||||
|
@ -1148,7 +795,6 @@ func (b *browserService) SetHashValue(connName string, db int, k any, field, new
|
||||||
_, err = client.HSet(ctx, key, newField, value).Result()
|
_, err = client.HSet(ctx, key, newField, value).Result()
|
||||||
removedField = append(removedField, field)
|
removedField = append(removedField, field)
|
||||||
updatedField[newField] = value
|
updatedField[newField] = value
|
||||||
replacedField[field] = newField
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.Msg = err.Error()
|
resp.Msg = err.Error()
|
||||||
|
@ -1159,7 +805,6 @@ func (b *browserService) SetHashValue(connName string, db int, k any, field, new
|
||||||
resp.Data = map[string]any{
|
resp.Data = map[string]any{
|
||||||
"removed": removedField,
|
"removed": removedField,
|
||||||
"updated": updatedField,
|
"updated": updatedField,
|
||||||
"replaced": replacedField,
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1299,11 +944,10 @@ func (b *browserService) SetSetItem(connName string, db int, k any, remove bool,
|
||||||
|
|
||||||
client, ctx := item.client, item.ctx
|
client, ctx := item.client, item.ctx
|
||||||
key := strutil.DecodeRedisKey(k)
|
key := strutil.DecodeRedisKey(k)
|
||||||
var affected int64
|
|
||||||
if remove {
|
if remove {
|
||||||
affected, err = client.SRem(ctx, key, members...).Result()
|
_, err = client.SRem(ctx, key, members...).Result()
|
||||||
} else {
|
} else {
|
||||||
affected, err = client.SAdd(ctx, key, members...).Result()
|
_, err = client.SAdd(ctx, key, members...).Result()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.Msg = err.Error()
|
resp.Msg = err.Error()
|
||||||
|
@ -1311,9 +955,6 @@ func (b *browserService) SetSetItem(connName string, db int, k any, remove bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Success = true
|
resp.Success = true
|
||||||
resp.Data = map[string]any{
|
|
||||||
"affected": affected,
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1362,9 +1003,6 @@ func (b *browserService) UpdateZSetValue(connName string, db int, k any, value,
|
||||||
Score: score,
|
Score: score,
|
||||||
Member: value,
|
Member: value,
|
||||||
}).Result()
|
}).Result()
|
||||||
if err == nil {
|
|
||||||
updated[value] = score
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// remove old value and add new one
|
// remove old value and add new one
|
||||||
_, err = client.ZRem(ctx, key, value).Result()
|
_, err = client.ZRem(ctx, key, value).Result()
|
||||||
|
@ -1437,8 +1075,7 @@ func (b *browserService) AddStreamValue(connName string, db int, k any, ID strin
|
||||||
|
|
||||||
client, ctx := item.client, item.ctx
|
client, ctx := item.client, item.ctx
|
||||||
key := strutil.DecodeRedisKey(k)
|
key := strutil.DecodeRedisKey(k)
|
||||||
var updateID string
|
_, err = client.XAdd(ctx, &redis.XAddArgs{
|
||||||
updateID, err = client.XAdd(ctx, &redis.XAddArgs{
|
|
||||||
Stream: key,
|
Stream: key,
|
||||||
ID: ID,
|
ID: ID,
|
||||||
Values: fieldItems,
|
Values: fieldItems,
|
||||||
|
@ -1449,9 +1086,6 @@ func (b *browserService) AddStreamValue(connName string, db int, k any, ID strin
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Success = true
|
resp.Success = true
|
||||||
resp.Data = map[string]any{
|
|
||||||
"updateID": updateID,
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1465,18 +1099,8 @@ func (b *browserService) RemoveStreamValues(connName string, db int, k any, IDs
|
||||||
|
|
||||||
client, ctx := item.client, item.ctx
|
client, ctx := item.client, item.ctx
|
||||||
key := strutil.DecodeRedisKey(k)
|
key := strutil.DecodeRedisKey(k)
|
||||||
|
_, err = client.XDel(ctx, key, IDs...).Result()
|
||||||
var affected int64
|
|
||||||
affected, err = client.XDel(ctx, key, IDs...).Result()
|
|
||||||
if err != nil {
|
|
||||||
resp.Msg = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.Success = true
|
resp.Success = true
|
||||||
resp.Data = map[string]any{
|
|
||||||
"affected": affected,
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1522,25 +1146,23 @@ func (b *browserService) DeleteKey(connName string, db int, k any, async bool) (
|
||||||
if strings.HasSuffix(key, "*") {
|
if strings.HasSuffix(key, "*") {
|
||||||
// delete by prefix
|
// delete by prefix
|
||||||
var mutex sync.Mutex
|
var mutex sync.Mutex
|
||||||
supportUnlink := true
|
|
||||||
del := func(ctx context.Context, cli redis.UniversalClient) error {
|
del := func(ctx context.Context, cli redis.UniversalClient) error {
|
||||||
handleDel := func(ks []string) error {
|
handleDel := func(ks []string) error {
|
||||||
var delErr error
|
pipe := cli.Pipeline()
|
||||||
if async && supportUnlink {
|
for _, k2 := range ks {
|
||||||
supportUnlink = false
|
if async {
|
||||||
if delErr = cli.Unlink(ctx, ks...).Err(); delErr != nil {
|
cli.Unlink(ctx, k2)
|
||||||
// not support unlink? try del command
|
|
||||||
delErr = cli.Del(ctx, ks...).Err()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
delErr = cli.Del(ctx, ks...).Err()
|
cli.Del(ctx, k2)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
pipe.Exec(ctx)
|
||||||
|
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
deletedKeys = append(deletedKeys, ks...)
|
deletedKeys = append(deletedKeys, ks...)
|
||||||
mutex.Unlock()
|
mutex.Unlock()
|
||||||
|
|
||||||
return delErr
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
scanSize := int64(Preferences().GetScanSize())
|
scanSize := int64(Preferences().GetScanSize())
|
||||||
|
@ -1548,7 +1170,7 @@ func (b *browserService) DeleteKey(connName string, db int, k any, async bool) (
|
||||||
resultKeys := make([]string, 0, 100)
|
resultKeys := make([]string, 0, 100)
|
||||||
for iter.Next(ctx) {
|
for iter.Next(ctx) {
|
||||||
resultKeys = append(resultKeys, iter.Val())
|
resultKeys = append(resultKeys, iter.Val())
|
||||||
if len(resultKeys) >= 20 {
|
if len(resultKeys) >= 3 {
|
||||||
handleDel(resultKeys)
|
handleDel(resultKeys)
|
||||||
resultKeys = resultKeys[:0:cap(resultKeys)]
|
resultKeys = resultKeys[:0:cap(resultKeys)]
|
||||||
}
|
}
|
||||||
|
@ -1576,14 +1198,12 @@ func (b *browserService) DeleteKey(connName string, db int, k any, async bool) (
|
||||||
} else {
|
} else {
|
||||||
// delete key only
|
// delete key only
|
||||||
if async {
|
if async {
|
||||||
if err = client.Unlink(ctx, key).Err(); err != nil {
|
if _, err = client.Unlink(ctx, key).Result(); err != nil {
|
||||||
if err = client.Del(ctx, key).Err(); err != nil {
|
|
||||||
resp.Msg = err.Error()
|
resp.Msg = err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if err = client.Del(ctx, key).Err(); err != nil {
|
if _, err = client.Del(ctx, key).Result(); err != nil {
|
||||||
resp.Msg = err.Error()
|
resp.Msg = err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1607,8 +1227,8 @@ func (b *browserService) FlushDB(connName string, db int, async bool) (resp type
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
flush := func(ctx context.Context, cli redis.UniversalClient, async bool) error {
|
flush := func(ctx context.Context, cli redis.UniversalClient) {
|
||||||
_, e := cli.TxPipelined(ctx, func(pipe redis.Pipeliner) error {
|
cli.TxPipelined(ctx, func(pipe redis.Pipeliner) error {
|
||||||
pipe.Select(ctx, db)
|
pipe.Select(ctx, db)
|
||||||
if async {
|
if async {
|
||||||
pipe.FlushDBAsync(ctx)
|
pipe.FlushDBAsync(ctx)
|
||||||
|
@ -1617,26 +1237,17 @@ func (b *browserService) FlushDB(connName string, db int, async bool) (resp type
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return e
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client, ctx := item.client, item.ctx
|
client, ctx := item.client, item.ctx
|
||||||
if cluster, ok := client.(*redis.ClusterClient); ok {
|
if cluster, ok := client.(*redis.ClusterClient); ok {
|
||||||
// cluster mode
|
// cluster mode
|
||||||
err = cluster.ForEachMaster(ctx, func(ctx context.Context, cli *redis.Client) error {
|
err = cluster.ForEachMaster(ctx, func(ctx context.Context, cli *redis.Client) error {
|
||||||
return flush(ctx, cli, async)
|
flush(ctx, cli)
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
// try sync mode if error cause
|
|
||||||
if err != nil && async {
|
|
||||||
err = cluster.ForEachMaster(ctx, func(ctx context.Context, cli *redis.Client) error {
|
|
||||||
return flush(ctx, cli, false)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if err = flush(ctx, client, async); err != nil && async {
|
flush(ctx, client)
|
||||||
// try sync mode if error cause
|
|
||||||
err = flush(ctx, client, false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -5,35 +5,3 @@ type JSResp struct {
|
||||||
Msg string `json:"msg"`
|
Msg string `json:"msg"`
|
||||||
Data any `json:"data,omitempty"`
|
Data any `json:"data,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type KeySummaryParam struct {
|
|
||||||
Server string `json:"server"`
|
|
||||||
DB int `json:"db"`
|
|
||||||
Key any `json:"key"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type KeySummary struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
TTL int64 `json:"ttl"`
|
|
||||||
Size int64 `json:"size"`
|
|
||||||
Length int64 `json:"length"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type KeyDetailParam struct {
|
|
||||||
Server string `json:"server"`
|
|
||||||
DB int `json:"db"`
|
|
||||||
Key any `json:"key"`
|
|
||||||
ViewAs string `json:"viewAs,omitempty"`
|
|
||||||
DecodeType string `json:"decodeType,omitempty"`
|
|
||||||
MatchPattern string `json:"matchPattern,omitempty"`
|
|
||||||
Reset bool `json:"reset"`
|
|
||||||
Full bool `json:"full"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type KeyDetail struct {
|
|
||||||
Value any `json:"value"`
|
|
||||||
Length int64 `json:"length,omitempty"`
|
|
||||||
ViewAs string `json:"viewAs,omitempty"`
|
|
||||||
DecodeType string `json:"decodeType,omitempty"`
|
|
||||||
End bool `json:"end"`
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,17 +14,17 @@
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"sass": "^1.69.5",
|
"sass": "^1.69.5",
|
||||||
"vue": "^3.3.8",
|
"vue": "^3.3.7",
|
||||||
"vue-i18n": "^9.6.5",
|
"vue-i18n": "^9.6.2",
|
||||||
"xterm": "^5.3.0",
|
"xterm": "^5.3.0",
|
||||||
"xterm-addon-fit": "^0.8.0"
|
"xterm-addon-fit": "^0.8.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^4.4.1",
|
"@vitejs/plugin-vue": "^4.4.0",
|
||||||
"naive-ui": "^2.35.0",
|
"naive-ui": "^2.35.0",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"unplugin-auto-import": "^0.16.7",
|
"unplugin-auto-import": "^0.16.7",
|
||||||
"unplugin-icons": "^0.17.3",
|
"unplugin-icons": "^0.17.1",
|
||||||
"unplugin-vue-components": "^0.25.2",
|
"unplugin-vue-components": "^0.25.2",
|
||||||
"vite": "^4.5.0"
|
"vite": "^4.5.0"
|
||||||
}
|
}
|
||||||
|
@ -465,23 +465,23 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@intlify/core-base": {
|
"node_modules/@intlify/core-base": {
|
||||||
"version": "9.6.5",
|
"version": "9.6.2",
|
||||||
"resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.6.5.tgz",
|
"resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.6.2.tgz",
|
||||||
"integrity": "sha512-LzbGXiZkMWPIHnHI0g6q554S87Cmh2mmCmjytK/3pDQfjI84l+dgGoeQuKj02q7EbULRuUUgYVZVqAwEUawXGg==",
|
"integrity": "sha512-ci0j2nbEL/pamvqgcCqyIVeQ3LS41F1IRqI5rCBNnpSp0FjNnH8bpha8R3OifkhqatzlP4wGOuN/UqfLYVDv7g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@intlify/message-compiler": "9.6.5",
|
"@intlify/message-compiler": "9.6.2",
|
||||||
"@intlify/shared": "9.6.5"
|
"@intlify/shared": "9.6.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 16"
|
"node": ">= 16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@intlify/message-compiler": {
|
"node_modules/@intlify/message-compiler": {
|
||||||
"version": "9.6.5",
|
"version": "9.6.2",
|
||||||
"resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.6.5.tgz",
|
"resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.6.2.tgz",
|
||||||
"integrity": "sha512-WeJ499thIj0p7JaIO1V3JaJbqdqfBykS5R8fElFs5hNeotHtPAMBs4IiA+8/KGFkAbjJusgFefCq6ajP7F7+4Q==",
|
"integrity": "sha512-kgZQL9zeJDeEB5vvD93Y++HvFUELnT48PjnpfCcF3EJaLLVs9he8IzODiNK42Z40lWbFyja0SXJZjsalybQygA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@intlify/shared": "9.6.5",
|
"@intlify/shared": "9.6.2",
|
||||||
"source-map-js": "^1.0.2"
|
"source-map-js": "^1.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -489,9 +489,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@intlify/shared": {
|
"node_modules/@intlify/shared": {
|
||||||
"version": "9.6.5",
|
"version": "9.6.2",
|
||||||
"resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-9.6.5.tgz",
|
"resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-9.6.2.tgz",
|
||||||
"integrity": "sha512-gD7Ey47Xi4h/t6P+S04ymMSoA3wVRxGqjxuIMglwRO8POki9h164Epu2N8wk/GHXM/hR6ZGcsx2HArCCENjqSQ==",
|
"integrity": "sha512-9KBcXmJNxElp7QMnU8V0/tScTOitDqyFi4HceEZqJyyDkMi8K5DBPMTIuXIAMmtMlXpe/nj5pke7tRw97VeQRA==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 16"
|
"node": ">= 16"
|
||||||
}
|
}
|
||||||
|
@ -592,9 +592,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vitejs/plugin-vue": {
|
"node_modules/@vitejs/plugin-vue": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-4.4.1.tgz",
|
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-4.4.0.tgz",
|
||||||
"integrity": "sha512-HCQG8VDFDM7YDAdcj5QI5DvUi+r6xvo9LgvYdk7LSkUNwdpempdB5horkMSZsbdey9Ywsf5aaU8kEPw9M5kREA==",
|
"integrity": "sha512-xdguqb+VUwiRpSg+nsc2HtbAUSGak25DXYvpQQi4RVU1Xq1uworyoH/md9Rfd8zMmPR/pSghr309QNcftUVseg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.18.0 || >=16.0.0"
|
"node": "^14.18.0 || >=16.0.0"
|
||||||
|
@ -605,36 +605,36 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/compiler-core": {
|
"node_modules/@vue/compiler-core": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.3.7.tgz",
|
||||||
"integrity": "sha512-hN/NNBUECw8SusQvDSqqcVv6gWq8L6iAktUR0UF3vGu2OhzRqcOiAno0FmBJWwxhYEXRlQJT5XnoKsVq1WZx4g==",
|
"integrity": "sha512-pACdY6YnTNVLXsB86YD8OF9ihwpolzhhtdLVHhBL6do/ykr6kKXNYABRtNMGrsQXpEXXyAdwvWWkuTbs4MFtPQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.23.0",
|
"@babel/parser": "^7.23.0",
|
||||||
"@vue/shared": "3.3.8",
|
"@vue/shared": "3.3.7",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"source-map-js": "^1.0.2"
|
"source-map-js": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/compiler-dom": {
|
"node_modules/@vue/compiler-dom": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.3.7.tgz",
|
||||||
"integrity": "sha512-+PPtv+p/nWDd0AvJu3w8HS0RIm/C6VGBIRe24b9hSyNWOAPEUosFZ5diwawwP8ip5sJ8n0Pe87TNNNHnvjs0FQ==",
|
"integrity": "sha512-0LwkyJjnUPssXv/d1vNJ0PKfBlDoQs7n81CbO6Q0zdL7H1EzqYRrTVXDqdBVqro0aJjo/FOa1qBAPVI4PGSHBw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-core": "3.3.8",
|
"@vue/compiler-core": "3.3.7",
|
||||||
"@vue/shared": "3.3.8"
|
"@vue/shared": "3.3.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/compiler-sfc": {
|
"node_modules/@vue/compiler-sfc": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.3.7.tgz",
|
||||||
"integrity": "sha512-WMzbUrlTjfYF8joyT84HfwwXo+8WPALuPxhy+BZ6R4Aafls+jDBnSz8PDz60uFhuqFbl3HxRfxvDzrUf3THwpA==",
|
"integrity": "sha512-7pfldWy/J75U/ZyYIXRVqvLRw3vmfxDo2YLMwVtWVNew8Sm8d6wodM+OYFq4ll/UxfqVr0XKiVwti32PCrruAw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.23.0",
|
"@babel/parser": "^7.23.0",
|
||||||
"@vue/compiler-core": "3.3.8",
|
"@vue/compiler-core": "3.3.7",
|
||||||
"@vue/compiler-dom": "3.3.8",
|
"@vue/compiler-dom": "3.3.7",
|
||||||
"@vue/compiler-ssr": "3.3.8",
|
"@vue/compiler-ssr": "3.3.7",
|
||||||
"@vue/reactivity-transform": "3.3.8",
|
"@vue/reactivity-transform": "3.3.7",
|
||||||
"@vue/shared": "3.3.8",
|
"@vue/shared": "3.3.7",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"magic-string": "^0.30.5",
|
"magic-string": "^0.30.5",
|
||||||
"postcss": "^8.4.31",
|
"postcss": "^8.4.31",
|
||||||
|
@ -642,12 +642,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/compiler-ssr": {
|
"node_modules/@vue/compiler-ssr": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.3.7.tgz",
|
||||||
"integrity": "sha512-hXCqQL/15kMVDBuoBYpUnSYT8doDNwsjvm3jTefnXr+ytn294ySnT8NlsFHmTgKNjwpuFy7XVV8yTeLtNl/P6w==",
|
"integrity": "sha512-TxOfNVVeH3zgBc82kcUv+emNHo+vKnlRrkv8YvQU5+Y5LJGJwSNzcmLUoxD/dNzv0bhQ/F0s+InlgV0NrApJZg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-dom": "3.3.8",
|
"@vue/compiler-dom": "3.3.7",
|
||||||
"@vue/shared": "3.3.8"
|
"@vue/shared": "3.3.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/devtools-api": {
|
"node_modules/@vue/devtools-api": {
|
||||||
|
@ -656,41 +656,41 @@
|
||||||
"integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
|
"integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
|
||||||
},
|
},
|
||||||
"node_modules/@vue/reactivity": {
|
"node_modules/@vue/reactivity": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.3.7.tgz",
|
||||||
"integrity": "sha512-ctLWitmFBu6mtddPyOKpHg8+5ahouoTCRtmAHZAXmolDtuZXfjL2T3OJ6DL6ezBPQB1SmMnpzjiWjCiMYmpIuw==",
|
"integrity": "sha512-cZNVjWiw00708WqT0zRpyAgduG79dScKEPYJXq2xj/aMtk3SKvL3FBt2QKUlh6EHBJ1m8RhBY+ikBUzwc7/khg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/shared": "3.3.8"
|
"@vue/shared": "3.3.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/reactivity-transform": {
|
"node_modules/@vue/reactivity-transform": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.3.7.tgz",
|
||||||
"integrity": "sha512-49CvBzmZNtcHua0XJ7GdGifM8GOXoUMOX4dD40Y5DxI3R8OUhMlvf2nvgUAcPxaXiV5MQQ1Nwy09ADpnLQUqRw==",
|
"integrity": "sha512-APhRmLVbgE1VPGtoLQoWBJEaQk4V8JUsqrQihImVqKT+8U6Qi3t5ATcg4Y9wGAPb3kIhetpufyZ1RhwbZCIdDA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.23.0",
|
"@babel/parser": "^7.23.0",
|
||||||
"@vue/compiler-core": "3.3.8",
|
"@vue/compiler-core": "3.3.7",
|
||||||
"@vue/shared": "3.3.8",
|
"@vue/shared": "3.3.7",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"magic-string": "^0.30.5"
|
"magic-string": "^0.30.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/runtime-core": {
|
"node_modules/@vue/runtime-core": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.3.7.tgz",
|
||||||
"integrity": "sha512-qurzOlb6q26KWQ/8IShHkMDOuJkQnQcTIp1sdP4I9MbCf9FJeGVRXJFr2mF+6bXh/3Zjr9TDgURXrsCr9bfjUw==",
|
"integrity": "sha512-LHq9du3ubLZFdK/BP0Ysy3zhHqRfBn80Uc+T5Hz3maFJBGhci1MafccnL3rpd5/3wVfRHAe6c+PnlO2PAavPTQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/reactivity": "3.3.8",
|
"@vue/reactivity": "3.3.7",
|
||||||
"@vue/shared": "3.3.8"
|
"@vue/shared": "3.3.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/runtime-dom": {
|
"node_modules/@vue/runtime-dom": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.3.7.tgz",
|
||||||
"integrity": "sha512-Noy5yM5UIf9UeFoowBVgghyGGPIDPy1Qlqt0yVsUdAVbqI8eeMSsTqBtauaEoT2UFXUk5S64aWVNJN4MJ2vRdA==",
|
"integrity": "sha512-PFQU1oeJxikdDmrfoNQay5nD4tcPNYixUBruZzVX/l0eyZvFKElZUjW4KctCcs52nnpMGO6UDK+jF5oV4GT5Lw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/runtime-core": "3.3.8",
|
"@vue/runtime-core": "3.3.7",
|
||||||
"@vue/shared": "3.3.8",
|
"@vue/shared": "3.3.7",
|
||||||
"csstype": "^3.1.2"
|
"csstype": "^3.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -700,21 +700,21 @@
|
||||||
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
|
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@vue/server-renderer": {
|
"node_modules/@vue/server-renderer": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.3.7.tgz",
|
||||||
"integrity": "sha512-zVCUw7RFskvPuNlPn/8xISbrf0zTWsTSdYTsUTN1ERGGZGVnRxM2QZ3x1OR32+vwkkCm0IW6HmJ49IsPm7ilLg==",
|
"integrity": "sha512-UlpKDInd1hIZiNuVVVvLgxpfnSouxKQOSE2bOfQpBuGwxRV/JqqTCyyjXUWiwtVMyeRaZhOYYqntxElk8FhBhw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-ssr": "3.3.8",
|
"@vue/compiler-ssr": "3.3.7",
|
||||||
"@vue/shared": "3.3.8"
|
"@vue/shared": "3.3.7"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"vue": "3.3.8"
|
"vue": "3.3.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/shared": {
|
"node_modules/@vue/shared": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.3.7.tgz",
|
||||||
"integrity": "sha512-8PGwybFwM4x8pcfgqEQFy70NaQxASvOC5DJwLQfpArw1UDfUXrJkdxD3BhVTMS+0Lef/TU7YO0Jvr0jJY8T+mw=="
|
"integrity": "sha512-N/tbkINRUDExgcPTBvxNkvHGu504k8lzlNQRITVnm6YjOjwa4r0nnbd4Jb01sNpur5hAllyRJzSK5PvB9PPwRg=="
|
||||||
},
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.10.0",
|
"version": "8.10.0",
|
||||||
|
@ -1744,9 +1744,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/unplugin-icons": {
|
"node_modules/unplugin-icons": {
|
||||||
"version": "0.17.3",
|
"version": "0.17.1",
|
||||||
"resolved": "https://registry.npmmirror.com/unplugin-icons/-/unplugin-icons-0.17.3.tgz",
|
"resolved": "https://registry.npmmirror.com/unplugin-icons/-/unplugin-icons-0.17.1.tgz",
|
||||||
"integrity": "sha512-uvopA4I6QYWYpwAyRvG/4NNvR1Cd4GnF/mtOkybgP2YPkHjRX02l/ALm20VUla31Jt9eZHxHyODtNf/Upx5uaw==",
|
"integrity": "sha512-KsWejBPCHokYCNDQUzGu6R3E3XDYH/YpewgQwrVBXgpl1iR0RdW1NEGNdjlbuapwVnZXVgA5eiDTfNaQCawSdg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@antfu/install-pkg": "^0.1.1",
|
"@antfu/install-pkg": "^0.1.1",
|
||||||
|
@ -1906,15 +1906,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vue": {
|
"node_modules/vue": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.3.7.tgz",
|
||||||
"integrity": "sha512-5VSX/3DabBikOXMsxzlW8JyfeLKlG9mzqnWgLQLty88vdZL7ZJgrdgBOmrArwxiLtmS+lNNpPcBYqrhE6TQW5w==",
|
"integrity": "sha512-YEMDia1ZTv1TeBbnu6VybatmSteGOS3A3YgfINOfraCbf85wdKHzscD6HSS/vB4GAtI7sa1XPX7HcQaJ1l24zA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-dom": "3.3.8",
|
"@vue/compiler-dom": "3.3.7",
|
||||||
"@vue/compiler-sfc": "3.3.8",
|
"@vue/compiler-sfc": "3.3.7",
|
||||||
"@vue/runtime-dom": "3.3.8",
|
"@vue/runtime-dom": "3.3.7",
|
||||||
"@vue/server-renderer": "3.3.8",
|
"@vue/server-renderer": "3.3.7",
|
||||||
"@vue/shared": "3.3.8"
|
"@vue/shared": "3.3.7"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "*"
|
"typescript": "*"
|
||||||
|
@ -1926,12 +1926,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vue-i18n": {
|
"node_modules/vue-i18n": {
|
||||||
"version": "9.6.5",
|
"version": "9.6.2",
|
||||||
"resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.6.5.tgz",
|
"resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.6.2.tgz",
|
||||||
"integrity": "sha512-dpUEjKHg7pEsaS7ZPPxp1CflaR7bGmsvZJEhnszHPKl9OTNyno5j/DvMtMSo41kpddq4felLA7GK2prjpnXVlw==",
|
"integrity": "sha512-J43grTQjPR8LCUxvx3mkoM+11xhTnej1Al4lvJCEeKmQqf8eqbuYPQb54HXnEg/UzZyaxLBAwPAUTbrZ8V7hcg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@intlify/core-base": "9.6.5",
|
"@intlify/core-base": "9.6.2",
|
||||||
"@intlify/shared": "9.6.5",
|
"@intlify/shared": "9.6.2",
|
||||||
"@vue/devtools-api": "^6.5.0"
|
"@vue/devtools-api": "^6.5.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -2238,27 +2238,27 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@intlify/core-base": {
|
"@intlify/core-base": {
|
||||||
"version": "9.6.5",
|
"version": "9.6.2",
|
||||||
"resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.6.5.tgz",
|
"resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.6.2.tgz",
|
||||||
"integrity": "sha512-LzbGXiZkMWPIHnHI0g6q554S87Cmh2mmCmjytK/3pDQfjI84l+dgGoeQuKj02q7EbULRuUUgYVZVqAwEUawXGg==",
|
"integrity": "sha512-ci0j2nbEL/pamvqgcCqyIVeQ3LS41F1IRqI5rCBNnpSp0FjNnH8bpha8R3OifkhqatzlP4wGOuN/UqfLYVDv7g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@intlify/message-compiler": "9.6.5",
|
"@intlify/message-compiler": "9.6.2",
|
||||||
"@intlify/shared": "9.6.5"
|
"@intlify/shared": "9.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@intlify/message-compiler": {
|
"@intlify/message-compiler": {
|
||||||
"version": "9.6.5",
|
"version": "9.6.2",
|
||||||
"resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.6.5.tgz",
|
"resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.6.2.tgz",
|
||||||
"integrity": "sha512-WeJ499thIj0p7JaIO1V3JaJbqdqfBykS5R8fElFs5hNeotHtPAMBs4IiA+8/KGFkAbjJusgFefCq6ajP7F7+4Q==",
|
"integrity": "sha512-kgZQL9zeJDeEB5vvD93Y++HvFUELnT48PjnpfCcF3EJaLLVs9he8IzODiNK42Z40lWbFyja0SXJZjsalybQygA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@intlify/shared": "9.6.5",
|
"@intlify/shared": "9.6.2",
|
||||||
"source-map-js": "^1.0.2"
|
"source-map-js": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@intlify/shared": {
|
"@intlify/shared": {
|
||||||
"version": "9.6.5",
|
"version": "9.6.2",
|
||||||
"resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-9.6.5.tgz",
|
"resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-9.6.2.tgz",
|
||||||
"integrity": "sha512-gD7Ey47Xi4h/t6P+S04ymMSoA3wVRxGqjxuIMglwRO8POki9h164Epu2N8wk/GHXM/hR6ZGcsx2HArCCENjqSQ=="
|
"integrity": "sha512-9KBcXmJNxElp7QMnU8V0/tScTOitDqyFi4HceEZqJyyDkMi8K5DBPMTIuXIAMmtMlXpe/nj5pke7tRw97VeQRA=="
|
||||||
},
|
},
|
||||||
"@jridgewell/sourcemap-codec": {
|
"@jridgewell/sourcemap-codec": {
|
||||||
"version": "1.4.15",
|
"version": "1.4.15",
|
||||||
|
@ -2336,43 +2336,43 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@vitejs/plugin-vue": {
|
"@vitejs/plugin-vue": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-4.4.1.tgz",
|
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-4.4.0.tgz",
|
||||||
"integrity": "sha512-HCQG8VDFDM7YDAdcj5QI5DvUi+r6xvo9LgvYdk7LSkUNwdpempdB5horkMSZsbdey9Ywsf5aaU8kEPw9M5kREA==",
|
"integrity": "sha512-xdguqb+VUwiRpSg+nsc2HtbAUSGak25DXYvpQQi4RVU1Xq1uworyoH/md9Rfd8zMmPR/pSghr309QNcftUVseg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
"@vue/compiler-core": {
|
"@vue/compiler-core": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.3.7.tgz",
|
||||||
"integrity": "sha512-hN/NNBUECw8SusQvDSqqcVv6gWq8L6iAktUR0UF3vGu2OhzRqcOiAno0FmBJWwxhYEXRlQJT5XnoKsVq1WZx4g==",
|
"integrity": "sha512-pACdY6YnTNVLXsB86YD8OF9ihwpolzhhtdLVHhBL6do/ykr6kKXNYABRtNMGrsQXpEXXyAdwvWWkuTbs4MFtPQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/parser": "^7.23.0",
|
"@babel/parser": "^7.23.0",
|
||||||
"@vue/shared": "3.3.8",
|
"@vue/shared": "3.3.7",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"source-map-js": "^1.0.2"
|
"source-map-js": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@vue/compiler-dom": {
|
"@vue/compiler-dom": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.3.7.tgz",
|
||||||
"integrity": "sha512-+PPtv+p/nWDd0AvJu3w8HS0RIm/C6VGBIRe24b9hSyNWOAPEUosFZ5diwawwP8ip5sJ8n0Pe87TNNNHnvjs0FQ==",
|
"integrity": "sha512-0LwkyJjnUPssXv/d1vNJ0PKfBlDoQs7n81CbO6Q0zdL7H1EzqYRrTVXDqdBVqro0aJjo/FOa1qBAPVI4PGSHBw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@vue/compiler-core": "3.3.8",
|
"@vue/compiler-core": "3.3.7",
|
||||||
"@vue/shared": "3.3.8"
|
"@vue/shared": "3.3.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@vue/compiler-sfc": {
|
"@vue/compiler-sfc": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.3.7.tgz",
|
||||||
"integrity": "sha512-WMzbUrlTjfYF8joyT84HfwwXo+8WPALuPxhy+BZ6R4Aafls+jDBnSz8PDz60uFhuqFbl3HxRfxvDzrUf3THwpA==",
|
"integrity": "sha512-7pfldWy/J75U/ZyYIXRVqvLRw3vmfxDo2YLMwVtWVNew8Sm8d6wodM+OYFq4ll/UxfqVr0XKiVwti32PCrruAw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/parser": "^7.23.0",
|
"@babel/parser": "^7.23.0",
|
||||||
"@vue/compiler-core": "3.3.8",
|
"@vue/compiler-core": "3.3.7",
|
||||||
"@vue/compiler-dom": "3.3.8",
|
"@vue/compiler-dom": "3.3.7",
|
||||||
"@vue/compiler-ssr": "3.3.8",
|
"@vue/compiler-ssr": "3.3.7",
|
||||||
"@vue/reactivity-transform": "3.3.8",
|
"@vue/reactivity-transform": "3.3.7",
|
||||||
"@vue/shared": "3.3.8",
|
"@vue/shared": "3.3.7",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"magic-string": "^0.30.5",
|
"magic-string": "^0.30.5",
|
||||||
"postcss": "^8.4.31",
|
"postcss": "^8.4.31",
|
||||||
|
@ -2380,12 +2380,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@vue/compiler-ssr": {
|
"@vue/compiler-ssr": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.3.7.tgz",
|
||||||
"integrity": "sha512-hXCqQL/15kMVDBuoBYpUnSYT8doDNwsjvm3jTefnXr+ytn294ySnT8NlsFHmTgKNjwpuFy7XVV8yTeLtNl/P6w==",
|
"integrity": "sha512-TxOfNVVeH3zgBc82kcUv+emNHo+vKnlRrkv8YvQU5+Y5LJGJwSNzcmLUoxD/dNzv0bhQ/F0s+InlgV0NrApJZg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@vue/compiler-dom": "3.3.8",
|
"@vue/compiler-dom": "3.3.7",
|
||||||
"@vue/shared": "3.3.8"
|
"@vue/shared": "3.3.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@vue/devtools-api": {
|
"@vue/devtools-api": {
|
||||||
|
@ -2394,41 +2394,41 @@
|
||||||
"integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
|
"integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
|
||||||
},
|
},
|
||||||
"@vue/reactivity": {
|
"@vue/reactivity": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.3.7.tgz",
|
||||||
"integrity": "sha512-ctLWitmFBu6mtddPyOKpHg8+5ahouoTCRtmAHZAXmolDtuZXfjL2T3OJ6DL6ezBPQB1SmMnpzjiWjCiMYmpIuw==",
|
"integrity": "sha512-cZNVjWiw00708WqT0zRpyAgduG79dScKEPYJXq2xj/aMtk3SKvL3FBt2QKUlh6EHBJ1m8RhBY+ikBUzwc7/khg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@vue/shared": "3.3.8"
|
"@vue/shared": "3.3.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@vue/reactivity-transform": {
|
"@vue/reactivity-transform": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.3.7.tgz",
|
||||||
"integrity": "sha512-49CvBzmZNtcHua0XJ7GdGifM8GOXoUMOX4dD40Y5DxI3R8OUhMlvf2nvgUAcPxaXiV5MQQ1Nwy09ADpnLQUqRw==",
|
"integrity": "sha512-APhRmLVbgE1VPGtoLQoWBJEaQk4V8JUsqrQihImVqKT+8U6Qi3t5ATcg4Y9wGAPb3kIhetpufyZ1RhwbZCIdDA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/parser": "^7.23.0",
|
"@babel/parser": "^7.23.0",
|
||||||
"@vue/compiler-core": "3.3.8",
|
"@vue/compiler-core": "3.3.7",
|
||||||
"@vue/shared": "3.3.8",
|
"@vue/shared": "3.3.7",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"magic-string": "^0.30.5"
|
"magic-string": "^0.30.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@vue/runtime-core": {
|
"@vue/runtime-core": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.3.7.tgz",
|
||||||
"integrity": "sha512-qurzOlb6q26KWQ/8IShHkMDOuJkQnQcTIp1sdP4I9MbCf9FJeGVRXJFr2mF+6bXh/3Zjr9TDgURXrsCr9bfjUw==",
|
"integrity": "sha512-LHq9du3ubLZFdK/BP0Ysy3zhHqRfBn80Uc+T5Hz3maFJBGhci1MafccnL3rpd5/3wVfRHAe6c+PnlO2PAavPTQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@vue/reactivity": "3.3.8",
|
"@vue/reactivity": "3.3.7",
|
||||||
"@vue/shared": "3.3.8"
|
"@vue/shared": "3.3.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@vue/runtime-dom": {
|
"@vue/runtime-dom": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.3.7.tgz",
|
||||||
"integrity": "sha512-Noy5yM5UIf9UeFoowBVgghyGGPIDPy1Qlqt0yVsUdAVbqI8eeMSsTqBtauaEoT2UFXUk5S64aWVNJN4MJ2vRdA==",
|
"integrity": "sha512-PFQU1oeJxikdDmrfoNQay5nD4tcPNYixUBruZzVX/l0eyZvFKElZUjW4KctCcs52nnpMGO6UDK+jF5oV4GT5Lw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@vue/runtime-core": "3.3.8",
|
"@vue/runtime-core": "3.3.7",
|
||||||
"@vue/shared": "3.3.8",
|
"@vue/shared": "3.3.7",
|
||||||
"csstype": "^3.1.2"
|
"csstype": "^3.1.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -2440,18 +2440,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@vue/server-renderer": {
|
"@vue/server-renderer": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.3.7.tgz",
|
||||||
"integrity": "sha512-zVCUw7RFskvPuNlPn/8xISbrf0zTWsTSdYTsUTN1ERGGZGVnRxM2QZ3x1OR32+vwkkCm0IW6HmJ49IsPm7ilLg==",
|
"integrity": "sha512-UlpKDInd1hIZiNuVVVvLgxpfnSouxKQOSE2bOfQpBuGwxRV/JqqTCyyjXUWiwtVMyeRaZhOYYqntxElk8FhBhw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@vue/compiler-ssr": "3.3.8",
|
"@vue/compiler-ssr": "3.3.7",
|
||||||
"@vue/shared": "3.3.8"
|
"@vue/shared": "3.3.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@vue/shared": {
|
"@vue/shared": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.3.7.tgz",
|
||||||
"integrity": "sha512-8PGwybFwM4x8pcfgqEQFy70NaQxASvOC5DJwLQfpArw1UDfUXrJkdxD3BhVTMS+0Lef/TU7YO0Jvr0jJY8T+mw=="
|
"integrity": "sha512-N/tbkINRUDExgcPTBvxNkvHGu504k8lzlNQRITVnm6YjOjwa4r0nnbd4Jb01sNpur5hAllyRJzSK5PvB9PPwRg=="
|
||||||
},
|
},
|
||||||
"acorn": {
|
"acorn": {
|
||||||
"version": "8.10.0",
|
"version": "8.10.0",
|
||||||
|
@ -3236,9 +3236,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"unplugin-icons": {
|
"unplugin-icons": {
|
||||||
"version": "0.17.3",
|
"version": "0.17.1",
|
||||||
"resolved": "https://registry.npmmirror.com/unplugin-icons/-/unplugin-icons-0.17.3.tgz",
|
"resolved": "https://registry.npmmirror.com/unplugin-icons/-/unplugin-icons-0.17.1.tgz",
|
||||||
"integrity": "sha512-uvopA4I6QYWYpwAyRvG/4NNvR1Cd4GnF/mtOkybgP2YPkHjRX02l/ALm20VUla31Jt9eZHxHyODtNf/Upx5uaw==",
|
"integrity": "sha512-KsWejBPCHokYCNDQUzGu6R3E3XDYH/YpewgQwrVBXgpl1iR0RdW1NEGNdjlbuapwVnZXVgA5eiDTfNaQCawSdg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@antfu/install-pkg": "^0.1.1",
|
"@antfu/install-pkg": "^0.1.1",
|
||||||
|
@ -3311,24 +3311,24 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vue": {
|
"vue": {
|
||||||
"version": "3.3.8",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.3.8.tgz",
|
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.3.7.tgz",
|
||||||
"integrity": "sha512-5VSX/3DabBikOXMsxzlW8JyfeLKlG9mzqnWgLQLty88vdZL7ZJgrdgBOmrArwxiLtmS+lNNpPcBYqrhE6TQW5w==",
|
"integrity": "sha512-YEMDia1ZTv1TeBbnu6VybatmSteGOS3A3YgfINOfraCbf85wdKHzscD6HSS/vB4GAtI7sa1XPX7HcQaJ1l24zA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@vue/compiler-dom": "3.3.8",
|
"@vue/compiler-dom": "3.3.7",
|
||||||
"@vue/compiler-sfc": "3.3.8",
|
"@vue/compiler-sfc": "3.3.7",
|
||||||
"@vue/runtime-dom": "3.3.8",
|
"@vue/runtime-dom": "3.3.7",
|
||||||
"@vue/server-renderer": "3.3.8",
|
"@vue/server-renderer": "3.3.7",
|
||||||
"@vue/shared": "3.3.8"
|
"@vue/shared": "3.3.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vue-i18n": {
|
"vue-i18n": {
|
||||||
"version": "9.6.5",
|
"version": "9.6.2",
|
||||||
"resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.6.5.tgz",
|
"resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.6.2.tgz",
|
||||||
"integrity": "sha512-dpUEjKHg7pEsaS7ZPPxp1CflaR7bGmsvZJEhnszHPKl9OTNyno5j/DvMtMSo41kpddq4felLA7GK2prjpnXVlw==",
|
"integrity": "sha512-J43grTQjPR8LCUxvx3mkoM+11xhTnej1Al4lvJCEeKmQqf8eqbuYPQb54HXnEg/UzZyaxLBAwPAUTbrZ8V7hcg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@intlify/core-base": "9.6.5",
|
"@intlify/core-base": "9.6.2",
|
||||||
"@intlify/shared": "9.6.5",
|
"@intlify/shared": "9.6.2",
|
||||||
"@vue/devtools-api": "^6.5.0"
|
"@vue/devtools-api": "^6.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,17 +15,17 @@
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"sass": "^1.69.5",
|
"sass": "^1.69.5",
|
||||||
"vue": "^3.3.8",
|
"vue": "^3.3.7",
|
||||||
"vue-i18n": "^9.6.5",
|
"vue-i18n": "^9.6.2",
|
||||||
"xterm": "^5.3.0",
|
"xterm": "^5.3.0",
|
||||||
"xterm-addon-fit": "^0.8.0"
|
"xterm-addon-fit": "^0.8.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^4.4.1",
|
"@vitejs/plugin-vue": "^4.4.0",
|
||||||
"naive-ui": "^2.35.0",
|
"naive-ui": "^2.35.0",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"unplugin-auto-import": "^0.16.7",
|
"unplugin-auto-import": "^0.16.7",
|
||||||
"unplugin-icons": "^0.17.3",
|
"unplugin-icons": "^0.17.1",
|
||||||
"unplugin-vue-components": "^0.25.2",
|
"unplugin-vue-components": "^0.25.2",
|
||||||
"vite": "^4.5.0"
|
"vite": "^4.5.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
3a2923aff6e49c16c4ca2e7fc8811eeb
|
24a0be173ef3e3939a15eb9c7fff5e1a
|
|
@ -26,7 +26,7 @@ const props = defineProps({
|
||||||
|
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
navMenuWidth: 60,
|
navMenuWidth: 60,
|
||||||
toolbarHeight: 38,
|
toolbarHeight: 45,
|
||||||
})
|
})
|
||||||
|
|
||||||
const tabStore = useTabStore()
|
const tabStore = useTabStore()
|
||||||
|
@ -135,7 +135,7 @@ onMounted(async () => {
|
||||||
paddingLeft: `${logoPaddingLeft}px`,
|
paddingLeft: `${logoPaddingLeft}px`,
|
||||||
}">
|
}">
|
||||||
<n-space :size="3" :wrap="false" :wrap-item="false" align="center">
|
<n-space :size="3" :wrap="false" :wrap-item="false" align="center">
|
||||||
<n-avatar :size="32" :src="iconUrl" color="#0000" style="min-width: 32px" />
|
<n-avatar :size="35" :src="iconUrl" color="#0000" style="min-width: 35px" />
|
||||||
<div style="min-width: 68px; font-weight: 800">Tiny RDM</div>
|
<div style="min-width: 68px; font-weight: 800">Tiny RDM</div>
|
||||||
<transition name="fade">
|
<transition name="fade">
|
||||||
<n-text v-if="tabStore.nav === 'browser'" class="ellipsis" strong style="font-size: 13px">
|
<n-text v-if="tabStore.nav === 'browser'" class="ellipsis" strong style="font-size: 13px">
|
||||||
|
|
|
@ -56,13 +56,11 @@ const tabContent = computed(() => {
|
||||||
length: tab.length || 0,
|
length: tab.length || 0,
|
||||||
viewAs: tab.viewAs,
|
viewAs: tab.viewAs,
|
||||||
decode: tab.decode,
|
decode: tab.decode,
|
||||||
end: tab.end,
|
|
||||||
loading: tab.loading === true,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const isBlankValue = computed(() => {
|
const isBlankValue = computed(() => {
|
||||||
return tabContent.value?.keyPath == null
|
return tabContent.value.value == null
|
||||||
})
|
})
|
||||||
|
|
||||||
const selectedSubTab = computed(() => {
|
const selectedSubTab = computed(() => {
|
||||||
|
@ -135,7 +133,19 @@ watch(
|
||||||
<span>{{ $t('interface.sub_tab.key_detail') }}</span>
|
<span>{{ $t('interface.sub_tab.key_detail') }}</span>
|
||||||
</n-space>
|
</n-space>
|
||||||
</template>
|
</template>
|
||||||
<content-value-wrapper :blank="isBlankValue" :content="tabContent" />
|
<content-value-wrapper
|
||||||
|
:blank="isBlankValue"
|
||||||
|
:db="tabContent.db"
|
||||||
|
:decode="tabContent.decode"
|
||||||
|
:key-code="tabContent.keyCode"
|
||||||
|
:key-path="tabContent.keyPath"
|
||||||
|
:length="tabContent.length"
|
||||||
|
:name="tabContent.name"
|
||||||
|
:size="tabContent.size"
|
||||||
|
:ttl="tabContent.ttl"
|
||||||
|
:type="tabContent.type"
|
||||||
|
:value="tabContent.value"
|
||||||
|
:view-as="tabContent.viewAs" />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
|
|
||||||
<!-- cli pane -->
|
<!-- cli pane -->
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { h, onMounted, onUnmounted, reactive, ref } from 'vue'
|
import { h, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||||
import Refresh from '@/components/icons/Refresh.vue'
|
import Refresh from '@/components/icons/Refresh.vue'
|
||||||
import { debounce, isEmpty, map, size } from 'lodash'
|
import { debounce, isEmpty, map, size, split } from 'lodash'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
import { useThemeVars } from 'naive-ui'
|
import { useThemeVars } from 'naive-ui'
|
||||||
import useBrowserStore from 'stores/browser.js'
|
import useBrowserStore from 'stores/browser.js'
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,9 @@ import IconButton from '@/components/common/IconButton.vue'
|
||||||
import Copy from '@/components/icons/Copy.vue'
|
import Copy from '@/components/icons/Copy.vue'
|
||||||
import { ClipboardSetText } from 'wailsjs/runtime/runtime.js'
|
import { ClipboardSetText } from 'wailsjs/runtime/runtime.js'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { padStart } from 'lodash'
|
import { isEmpty, padStart } from 'lodash'
|
||||||
|
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
||||||
|
import useBrowserStore from 'stores/browser.js'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
server: String,
|
server: String,
|
||||||
|
@ -32,18 +34,32 @@ const props = defineProps({
|
||||||
type: Number,
|
type: Number,
|
||||||
default: -1,
|
default: -1,
|
||||||
},
|
},
|
||||||
loading: Boolean,
|
viewAs: {
|
||||||
|
type: String,
|
||||||
|
default: formatTypes.PLAIN_TEXT,
|
||||||
|
},
|
||||||
|
decode: {
|
||||||
|
type: String,
|
||||||
|
default: decodeTypes.NONE,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['reload', 'rename', 'delete'])
|
|
||||||
|
|
||||||
const dialogStore = useDialog()
|
const dialogStore = useDialog()
|
||||||
|
const browserStore = useBrowserStore()
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
|
|
||||||
const binaryKey = computed(() => {
|
const binaryKey = computed(() => {
|
||||||
return !!props.keyCode
|
return !!props.keyCode
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {ComputedRef<string|number[]>}
|
||||||
|
*/
|
||||||
|
const keyName = computed(() => {
|
||||||
|
return !isEmpty(props.keyCode) ? props.keyCode : props.keyPath
|
||||||
|
})
|
||||||
|
|
||||||
const ttlString = computed(() => {
|
const ttlString = computed(() => {
|
||||||
let s = ''
|
let s = ''
|
||||||
if (props.ttl > 0) {
|
if (props.ttl > 0) {
|
||||||
|
@ -61,6 +77,10 @@ const ttlString = computed(() => {
|
||||||
return s
|
return s
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const onReloadKey = () => {
|
||||||
|
browserStore.loadKeyValue(props.server, props.db, keyName.value, props.viewAs, props.decode)
|
||||||
|
}
|
||||||
|
|
||||||
const onCopyKey = () => {
|
const onCopyKey = () => {
|
||||||
ClipboardSetText(props.keyPath)
|
ClipboardSetText(props.keyPath)
|
||||||
.then((succ) => {
|
.then((succ) => {
|
||||||
|
@ -72,20 +92,33 @@ const onCopyKey = () => {
|
||||||
$message.error(e.message)
|
$message.error(e.message)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onRenameKey = () => {
|
||||||
|
if (binaryKey.value) {
|
||||||
|
$message.error(i18n.t('dialogue.rename_binary_key_fail'))
|
||||||
|
} else {
|
||||||
|
dialogStore.openRenameKeyDialog(props.server, props.db, props.keyPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDeleteKey = () => {
|
||||||
|
$dialog.warning(i18n.t('dialogue.remove_tip', { name: props.keyPath }), () => {
|
||||||
|
browserStore.deleteKey(props.server, props.db, keyName.value).then((success) => {
|
||||||
|
if (success) {
|
||||||
|
$message.success(i18n.t('dialogue.delete_key_succ', { key: props.keyPath }))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="content-toolbar flex-box-h">
|
<div class="content-toolbar flex-box-h">
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<redis-type-tag :binary-key="binaryKey" :type="props.keyType" size="large" />
|
<redis-type-tag :binary-key="binaryKey" :type="props.keyType" size="large" />
|
||||||
<n-input v-model:value="props.keyPath" readonly>
|
<n-input v-model:value="props.keyPath">
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<icon-button
|
<icon-button :icon="Refresh" size="18" t-tooltip="interface.reload" @click="onReloadKey" />
|
||||||
:icon="Refresh"
|
|
||||||
:loading="props.loading"
|
|
||||||
size="18"
|
|
||||||
t-tooltip="interface.reload"
|
|
||||||
@click="emit('reload')" />
|
|
||||||
</template>
|
</template>
|
||||||
</n-input>
|
</n-input>
|
||||||
<icon-button :icon="Copy" border size="18" t-tooltip="interface.copy_key" @click="onCopyKey" />
|
<icon-button :icon="Copy" border size="18" t-tooltip="interface.copy_key" @click="onCopyKey" />
|
||||||
|
@ -102,11 +135,11 @@ const onCopyKey = () => {
|
||||||
</template>
|
</template>
|
||||||
TTL{{ `${ttl > 0 ? ': ' + ttl + $t('common.second') : ''}` }}
|
TTL{{ `${ttl > 0 ? ': ' + ttl + $t('common.second') : ''}` }}
|
||||||
</n-tooltip>
|
</n-tooltip>
|
||||||
<icon-button :icon="Edit" border size="18" t-tooltip="interface.rename_key" @click="emit('rename')" />
|
<icon-button :icon="Edit" border size="18" t-tooltip="interface.rename_key" @click="onRenameKey" />
|
||||||
</n-button-group>
|
</n-button-group>
|
||||||
<n-tooltip :show-arrow="false">
|
<n-tooltip :show-arrow="false">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<n-button :focusable="false" @click="emit('delete')">
|
<n-button :focusable="false" @click="onDeleteKey">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon :component="Delete" size="18" />
|
<n-icon :component="Delete" size="18" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -7,13 +7,10 @@ import { NButton, NCode, NIcon, NInput, useThemeVars } from 'naive-ui'
|
||||||
import { types, types as redisTypes } from '@/consts/support_redis_type.js'
|
import { types, types as redisTypes } from '@/consts/support_redis_type.js'
|
||||||
import EditableTableColumn from '@/components/common/EditableTableColumn.vue'
|
import EditableTableColumn from '@/components/common/EditableTableColumn.vue'
|
||||||
import useDialogStore from 'stores/dialog.js'
|
import useDialogStore from 'stores/dialog.js'
|
||||||
import { isEmpty, size } from 'lodash'
|
import { isEmpty } from 'lodash'
|
||||||
import bytes from 'bytes'
|
import bytes from 'bytes'
|
||||||
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
||||||
import useBrowserStore from 'stores/browser.js'
|
import useBrowserStore from 'stores/browser.js'
|
||||||
import LoadList from '@/components/icons/LoadList.vue'
|
|
||||||
import LoadAll from '@/components/icons/LoadAll.vue'
|
|
||||||
import IconButton from '@/components/common/IconButton.vue'
|
|
||||||
|
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
const themeVars = useThemeVars()
|
const themeVars = useThemeVars()
|
||||||
|
@ -41,12 +38,8 @@ const props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: decodeTypes.NONE,
|
default: decodeTypes.NONE,
|
||||||
},
|
},
|
||||||
end: Boolean,
|
|
||||||
loading: Boolean,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['loadmore', 'loadall', 'reload', 'rename', 'delete'])
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {ComputedRef<string|number[]>}
|
* @type {ComputedRef<string|number[]>}
|
||||||
|
@ -156,7 +149,14 @@ const actionColumn = {
|
||||||
row.key,
|
row.key,
|
||||||
)
|
)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
browserStore.loadKeyValue(props.name, props.db, keyName.value).then((r) => {})
|
||||||
$message.success(i18n.t('dialogue.delete_key_succ', { key: row.key }))
|
$message.success(i18n.t('dialogue.delete_key_succ', { key: row.key }))
|
||||||
|
// update display value
|
||||||
|
// if (!isEmpty(removed)) {
|
||||||
|
// for (const elem of removed) {
|
||||||
|
// delete props.value[elem]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,14 @@ const actionColumn = {
|
||||||
currentEditRow.value.value,
|
currentEditRow.value.value,
|
||||||
)
|
)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
browserStore.loadKeyValue(props.name, props.db, keyName.value).then((r) => {})
|
||||||
$message.success(i18n.t('dialogue.save_value_succ'))
|
$message.success(i18n.t('dialogue.save_value_succ'))
|
||||||
|
// update display value
|
||||||
|
// if (!isEmpty(updated)) {
|
||||||
|
// for (const key in updated) {
|
||||||
|
// props.value[key] = updated[key]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
}
|
}
|
||||||
|
@ -216,12 +223,6 @@ const tableData = computed(() => {
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
})
|
})
|
||||||
|
|
||||||
const entries = computed(() => {
|
|
||||||
const len = size(tableData.value)
|
|
||||||
return `${len} / ${Math.max(len, props.length)}`
|
|
||||||
})
|
|
||||||
|
|
||||||
const onAddRow = () => {
|
const onAddRow = () => {
|
||||||
dialogStore.openAddFieldsDialog(props.name, props.db, props.keyPath, props.keyCode, types.HASH)
|
dialogStore.openAddFieldsDialog(props.name, props.db, props.keyPath, props.keyCode, types.HASH)
|
||||||
}
|
}
|
||||||
|
@ -261,28 +262,20 @@ const onUpdateFilter = (filters, sourceColumn) => {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
reset: () => {
|
|
||||||
clearFilter()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="content-wrapper flex-box-v">
|
<div class="content-wrapper flex-box-v">
|
||||||
<content-toolbar
|
<content-toolbar
|
||||||
:db="props.db"
|
:db="props.db"
|
||||||
|
:decode="props.decode"
|
||||||
:key-code="props.keyCode"
|
:key-code="props.keyCode"
|
||||||
:key-path="props.keyPath"
|
:key-path="props.keyPath"
|
||||||
:key-type="keyType"
|
:key-type="keyType"
|
||||||
:loading="props.loading"
|
|
||||||
:server="props.name"
|
:server="props.name"
|
||||||
:ttl="ttl"
|
:ttl="ttl"
|
||||||
class="value-item-part"
|
:view-as="props.viewAs"
|
||||||
@delete="emit('delete')"
|
class="value-item-part" />
|
||||||
@reload="emit('reload')"
|
|
||||||
@rename="emit('rename')" />
|
|
||||||
<div class="tb2 value-item-part flex-box-h">
|
<div class="tb2 value-item-part flex-box-h">
|
||||||
<div class="flex-box-h">
|
<div class="flex-box-h">
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
|
@ -301,22 +294,6 @@ defineExpose({
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-item-expand"></div>
|
<div class="flex-item-expand"></div>
|
||||||
<n-button-group>
|
|
||||||
<icon-button
|
|
||||||
:disabled="props.end || props.loading"
|
|
||||||
:icon="LoadList"
|
|
||||||
border
|
|
||||||
size="18"
|
|
||||||
t-tooltip="interface.load_more_entries"
|
|
||||||
@click="emit('loadmore')" />
|
|
||||||
<icon-button
|
|
||||||
:disabled="props.end || props.loading"
|
|
||||||
:icon="LoadAll"
|
|
||||||
border
|
|
||||||
size="18"
|
|
||||||
t-tooltip="interface.load_all_entries"
|
|
||||||
@click="emit('loadall')" />
|
|
||||||
</n-button-group>
|
|
||||||
<n-button :focusable="false" plain @click="onAddRow">
|
<n-button :focusable="false" plain @click="onAddRow">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon :component="AddLink" size="18" />
|
<n-icon :component="AddLink" size="18" />
|
||||||
|
@ -324,25 +301,24 @@ defineExpose({
|
||||||
{{ $t('interface.add_row') }}
|
{{ $t('interface.add_row') }}
|
||||||
</n-button>
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="value-wrapper value-item-part flex-box-v flex-item-expand">
|
<div class="value-wrapper value-item-part fill-height flex-box-h">
|
||||||
<n-data-table
|
<n-data-table
|
||||||
:key="(row) => row.no"
|
:key="(row) => row.no"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
:bottom-bordered="false"
|
:bottom-bordered="false"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:loading="props.loading"
|
|
||||||
:single-column="true"
|
:single-column="true"
|
||||||
:single-line="false"
|
:single-line="false"
|
||||||
class="flex-item-expand"
|
|
||||||
flex-height
|
flex-height
|
||||||
|
max-height="100%"
|
||||||
size="small"
|
size="small"
|
||||||
striped
|
striped
|
||||||
virtual-scroll
|
virtual-scroll
|
||||||
@update:filters="onUpdateFilter" />
|
@update:filters="onUpdateFilter" />
|
||||||
</div>
|
</div>
|
||||||
<div class="value-footer flex-box-h">
|
<div class="value-footer flex-box-h">
|
||||||
<n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ entries }}</n-text>
|
<n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ props.length }}</n-text>
|
||||||
<n-divider v-if="!isNaN(props.length)" vertical />
|
<n-divider v-if="!isNaN(props.length)" vertical />
|
||||||
<n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text>
|
<n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text>
|
||||||
<div class="flex-item-expand"></div>
|
<div class="flex-item-expand"></div>
|
||||||
|
|
|
@ -11,9 +11,6 @@ import useDialogStore from 'stores/dialog.js'
|
||||||
import bytes from 'bytes'
|
import bytes from 'bytes'
|
||||||
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
||||||
import useBrowserStore from 'stores/browser.js'
|
import useBrowserStore from 'stores/browser.js'
|
||||||
import LoadList from '@/components/icons/LoadList.vue'
|
|
||||||
import LoadAll from '@/components/icons/LoadAll.vue'
|
|
||||||
import IconButton from '@/components/common/IconButton.vue'
|
|
||||||
|
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
const themeVars = useThemeVars()
|
const themeVars = useThemeVars()
|
||||||
|
@ -41,12 +38,8 @@ const props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: decodeTypes.NONE,
|
default: decodeTypes.NONE,
|
||||||
},
|
},
|
||||||
end: Boolean,
|
|
||||||
loading: Boolean,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['loadmore', 'loadall', 'reload', 'rename', 'delete'])
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {ComputedRef<string|number[]>}
|
* @type {ComputedRef<string|number[]>}
|
||||||
|
@ -113,7 +106,12 @@ const actionColumn = {
|
||||||
row.no - 1,
|
row.no - 1,
|
||||||
)
|
)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
browserStore.loadKeyValue(props.name, props.db, keyName.value).then((r) => {})
|
||||||
$message.success(i18n.t('dialogue.delete_key_succ', { key: '#' + row.no }))
|
$message.success(i18n.t('dialogue.delete_key_succ', { key: '#' + row.no }))
|
||||||
|
// update display value
|
||||||
|
// if (!isEmpty(removed)) {
|
||||||
|
// props.value.splice(removed[0], 1)
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
}
|
}
|
||||||
|
@ -131,7 +129,14 @@ const actionColumn = {
|
||||||
currentEditRow.value.value,
|
currentEditRow.value.value,
|
||||||
)
|
)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
browserStore.loadKeyValue(props.name, props.db, keyName.value).then((r) => {})
|
||||||
$message.success(i18n.t('dialogue.save_value_succ'))
|
$message.success(i18n.t('dialogue.save_value_succ'))
|
||||||
|
// update display value
|
||||||
|
// if (!isEmpty(updated)) {
|
||||||
|
// for (const key in updated) {
|
||||||
|
// props.value[key] = updated[key]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
}
|
}
|
||||||
|
@ -173,11 +178,6 @@ const tableData = computed(() => {
|
||||||
return data
|
return data
|
||||||
})
|
})
|
||||||
|
|
||||||
const entries = computed(() => {
|
|
||||||
const len = size(tableData.value)
|
|
||||||
return `${len} / ${Math.max(len, props.length)}`
|
|
||||||
})
|
|
||||||
|
|
||||||
const onAddValue = (value) => {
|
const onAddValue = (value) => {
|
||||||
dialogStore.openAddFieldsDialog(props.name, props.db, props.keyPath, props.keyCode, types.LIST)
|
dialogStore.openAddFieldsDialog(props.name, props.db, props.keyPath, props.keyCode, types.LIST)
|
||||||
}
|
}
|
||||||
|
@ -194,28 +194,20 @@ const clearFilter = () => {
|
||||||
const onUpdateFilter = (filters, sourceColumn) => {
|
const onUpdateFilter = (filters, sourceColumn) => {
|
||||||
valueColumn.filterOptionValue = filters[sourceColumn.key]
|
valueColumn.filterOptionValue = filters[sourceColumn.key]
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
reset: () => {
|
|
||||||
clearFilter()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="content-wrapper flex-box-v">
|
<div class="content-wrapper flex-box-v">
|
||||||
<content-toolbar
|
<content-toolbar
|
||||||
:db="props.db"
|
:db="props.db"
|
||||||
|
:decode="props.decode"
|
||||||
:key-code="props.keyCode"
|
:key-code="props.keyCode"
|
||||||
:key-path="props.keyPath"
|
:key-path="props.keyPath"
|
||||||
:key-type="keyType"
|
:key-type="keyType"
|
||||||
:loading="props.loading"
|
|
||||||
:server="props.name"
|
:server="props.name"
|
||||||
:ttl="ttl"
|
:ttl="ttl"
|
||||||
class="value-item-part"
|
:view-as="props.viewAs"
|
||||||
@delete="emit('delete')"
|
class="value-item-part" />
|
||||||
@reload="emit('reload')"
|
|
||||||
@rename="emit('rename')" />
|
|
||||||
<div class="tb2 value-item-part flex-box-h">
|
<div class="tb2 value-item-part flex-box-h">
|
||||||
<div class="flex-box-h">
|
<div class="flex-box-h">
|
||||||
<n-input
|
<n-input
|
||||||
|
@ -226,22 +218,6 @@ defineExpose({
|
||||||
@update:value="onFilterInput" />
|
@update:value="onFilterInput" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-item-expand"></div>
|
<div class="flex-item-expand"></div>
|
||||||
<n-button-group>
|
|
||||||
<icon-button
|
|
||||||
:disabled="props.end || props.loading"
|
|
||||||
:icon="LoadList"
|
|
||||||
border
|
|
||||||
size="18"
|
|
||||||
t-tooltip="interface.load_more_entries"
|
|
||||||
@click="emit('loadmore')" />
|
|
||||||
<icon-button
|
|
||||||
:disabled="props.end || props.loading"
|
|
||||||
:icon="LoadAll"
|
|
||||||
border
|
|
||||||
size="18"
|
|
||||||
t-tooltip="interface.load_all_entries"
|
|
||||||
@click="emit('loadall')" />
|
|
||||||
</n-button-group>
|
|
||||||
<n-button :focusable="false" plain @click="onAddValue">
|
<n-button :focusable="false" plain @click="onAddValue">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon :component="AddLink" size="18" />
|
<n-icon :component="AddLink" size="18" />
|
||||||
|
@ -249,25 +225,24 @@ defineExpose({
|
||||||
{{ $t('interface.add_row') }}
|
{{ $t('interface.add_row') }}
|
||||||
</n-button>
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="value-wrapper value-item-part flex-box-v flex-item-expand">
|
<div class="value-wrapper value-item-part fill-height flex-box-h">
|
||||||
<n-data-table
|
<n-data-table
|
||||||
:key="(row) => row.no"
|
:key="(row) => row.no"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
:bottom-bordered="false"
|
:bottom-bordered="false"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:loading="props.loading"
|
|
||||||
:single-column="true"
|
:single-column="true"
|
||||||
:single-line="false"
|
:single-line="false"
|
||||||
class="flex-item-expand"
|
|
||||||
flex-height
|
flex-height
|
||||||
|
max-height="100%"
|
||||||
size="small"
|
size="small"
|
||||||
striped
|
striped
|
||||||
virtual-scroll
|
virtual-scroll
|
||||||
@update:filters="onUpdateFilter" />
|
@update:filters="onUpdateFilter" />
|
||||||
</div>
|
</div>
|
||||||
<div class="value-footer flex-box-h">
|
<div class="value-footer flex-box-h">
|
||||||
<n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ entries }}</n-text>
|
<n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ props.length }}</n-text>
|
||||||
<n-divider v-if="!isNaN(props.length)" vertical />
|
<n-divider v-if="!isNaN(props.length)" vertical />
|
||||||
<n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text>
|
<n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text>
|
||||||
<div class="flex-item-expand"></div>
|
<div class="flex-item-expand"></div>
|
||||||
|
|
|
@ -11,9 +11,6 @@ import EditableTableColumn from '@/components/common/EditableTableColumn.vue'
|
||||||
import bytes from 'bytes'
|
import bytes from 'bytes'
|
||||||
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
||||||
import useBrowserStore from 'stores/browser.js'
|
import useBrowserStore from 'stores/browser.js'
|
||||||
import LoadList from '@/components/icons/LoadList.vue'
|
|
||||||
import LoadAll from '@/components/icons/LoadAll.vue'
|
|
||||||
import IconButton from '@/components/common/IconButton.vue'
|
|
||||||
|
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
const themeVars = useThemeVars()
|
const themeVars = useThemeVars()
|
||||||
|
@ -41,12 +38,8 @@ const props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: decodeTypes.NONE,
|
default: decodeTypes.NONE,
|
||||||
},
|
},
|
||||||
end: Boolean,
|
|
||||||
loading: Boolean,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['loadmore', 'loadall', 'reload', 'rename', 'delete'])
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {ComputedRef<string|number[]>}
|
* @type {ComputedRef<string|number[]>}
|
||||||
|
@ -114,7 +107,10 @@ const actionColumn = {
|
||||||
row.value,
|
row.value,
|
||||||
)
|
)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
browserStore.loadKeyValue(props.name, props.db, keyName.value).then((r) => {})
|
||||||
$message.success(i18n.t('dialogue.delete_key_succ', { key: row.value }))
|
$message.success(i18n.t('dialogue.delete_key_succ', { key: row.value }))
|
||||||
|
// update display value
|
||||||
|
// props.value.splice(row.no - 1, 1)
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
}
|
}
|
||||||
|
@ -132,7 +128,10 @@ const actionColumn = {
|
||||||
currentEditRow.value.value,
|
currentEditRow.value.value,
|
||||||
)
|
)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
browserStore.loadKeyValue(props.name, props.db, keyName.value).then((r) => {})
|
||||||
$message.success(i18n.t('dialogue.save_value_succ'))
|
$message.success(i18n.t('dialogue.save_value_succ'))
|
||||||
|
// update display value
|
||||||
|
// props.value[row.no - 1] = currentEditRow.value.value
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
}
|
}
|
||||||
|
@ -174,11 +173,6 @@ const tableData = computed(() => {
|
||||||
return data
|
return data
|
||||||
})
|
})
|
||||||
|
|
||||||
const entries = computed(() => {
|
|
||||||
const len = size(tableData.value)
|
|
||||||
return `${len} / ${Math.max(len, props.length)}`
|
|
||||||
})
|
|
||||||
|
|
||||||
const onAddValue = (value) => {
|
const onAddValue = (value) => {
|
||||||
dialogStore.openAddFieldsDialog(props.name, props.db, props.keyPath, props.keyCode, types.SET)
|
dialogStore.openAddFieldsDialog(props.name, props.db, props.keyPath, props.keyCode, types.SET)
|
||||||
}
|
}
|
||||||
|
@ -195,28 +189,20 @@ const clearFilter = () => {
|
||||||
const onUpdateFilter = (filters, sourceColumn) => {
|
const onUpdateFilter = (filters, sourceColumn) => {
|
||||||
valueColumn.filterOptionValue = filters[sourceColumn.key]
|
valueColumn.filterOptionValue = filters[sourceColumn.key]
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
reset: () => {
|
|
||||||
clearFilter()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="content-wrapper flex-box-v">
|
<div class="content-wrapper flex-box-v">
|
||||||
<content-toolbar
|
<content-toolbar
|
||||||
:db="props.db"
|
:db="props.db"
|
||||||
|
:decode="props.decode"
|
||||||
:key-code="props.keyCode"
|
:key-code="props.keyCode"
|
||||||
:key-path="props.keyPath"
|
:key-path="props.keyPath"
|
||||||
:key-type="keyType"
|
:key-type="keyType"
|
||||||
:loading="props.loading"
|
|
||||||
:server="props.name"
|
:server="props.name"
|
||||||
:ttl="ttl"
|
:ttl="ttl"
|
||||||
class="value-item-part"
|
:view-as="props.viewAs"
|
||||||
@delete="emit('delete')"
|
class="value-item-part" />
|
||||||
@reload="emit('reload')"
|
|
||||||
@rename="emit('rename')" />
|
|
||||||
<div class="tb2 value-item-part flex-box-h">
|
<div class="tb2 value-item-part flex-box-h">
|
||||||
<div class="flex-box-h">
|
<div class="flex-box-h">
|
||||||
<n-input
|
<n-input
|
||||||
|
@ -227,22 +213,6 @@ defineExpose({
|
||||||
@update:value="onFilterInput" />
|
@update:value="onFilterInput" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-item-expand"></div>
|
<div class="flex-item-expand"></div>
|
||||||
<n-button-group>
|
|
||||||
<icon-button
|
|
||||||
:disabled="props.end || props.loading"
|
|
||||||
:icon="LoadList"
|
|
||||||
border
|
|
||||||
size="18"
|
|
||||||
t-tooltip="interface.load_more_entries"
|
|
||||||
@click="emit('loadmore')" />
|
|
||||||
<icon-button
|
|
||||||
:disabled="props.end || props.loading"
|
|
||||||
:icon="LoadAll"
|
|
||||||
border
|
|
||||||
size="18"
|
|
||||||
t-tooltip="interface.load_all_entries"
|
|
||||||
@click="emit('loadall')" />
|
|
||||||
</n-button-group>
|
|
||||||
<n-button :focusable="false" plain @click="onAddValue">
|
<n-button :focusable="false" plain @click="onAddValue">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon :component="AddLink" size="18" />
|
<n-icon :component="AddLink" size="18" />
|
||||||
|
@ -250,25 +220,24 @@ defineExpose({
|
||||||
{{ $t('interface.add_row') }}
|
{{ $t('interface.add_row') }}
|
||||||
</n-button>
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="value-wrapper value-item-part flex-box-v flex-item-expand">
|
<div class="value-wrapper value-item-part fill-height flex-box-h">
|
||||||
<n-data-table
|
<n-data-table
|
||||||
:key="(row) => row.no"
|
:key="(row) => row.no"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
:bottom-bordered="false"
|
:bottom-bordered="false"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:loading="props.loading"
|
|
||||||
:single-column="true"
|
:single-column="true"
|
||||||
:single-line="false"
|
:single-line="false"
|
||||||
class="flex-item-expand"
|
|
||||||
flex-height
|
flex-height
|
||||||
|
max-height="100%"
|
||||||
size="small"
|
size="small"
|
||||||
striped
|
striped
|
||||||
virtual-scroll
|
virtual-scroll
|
||||||
@update:filters="onUpdateFilter" />
|
@update:filters="onUpdateFilter" />
|
||||||
</div>
|
</div>
|
||||||
<div class="value-footer flex-box-h">
|
<div class="value-footer flex-box-h">
|
||||||
<n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ entries }}</n-text>
|
<n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ props.length }}</n-text>
|
||||||
<n-divider v-if="!isNaN(props.length)" vertical />
|
<n-divider v-if="!isNaN(props.length)" vertical />
|
||||||
<n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text>
|
<n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text>
|
||||||
<div class="flex-item-expand"></div>
|
<div class="flex-item-expand"></div>
|
||||||
|
|
|
@ -7,13 +7,10 @@ import { NButton, NCode, NIcon, NInput, useThemeVars } from 'naive-ui'
|
||||||
import { types, types as redisTypes } from '@/consts/support_redis_type.js'
|
import { types, types as redisTypes } from '@/consts/support_redis_type.js'
|
||||||
import EditableTableColumn from '@/components/common/EditableTableColumn.vue'
|
import EditableTableColumn from '@/components/common/EditableTableColumn.vue'
|
||||||
import useDialogStore from 'stores/dialog.js'
|
import useDialogStore from 'stores/dialog.js'
|
||||||
import { includes, isEmpty, keys, size, some, values } from 'lodash'
|
import { includes, isEmpty, keys, some, values } from 'lodash'
|
||||||
import bytes from 'bytes'
|
import bytes from 'bytes'
|
||||||
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
||||||
import useBrowserStore from 'stores/browser.js'
|
import useBrowserStore from 'stores/browser.js'
|
||||||
import LoadList from '@/components/icons/LoadList.vue'
|
|
||||||
import LoadAll from '@/components/icons/LoadAll.vue'
|
|
||||||
import IconButton from '@/components/common/IconButton.vue'
|
|
||||||
|
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
const themeVars = useThemeVars()
|
const themeVars = useThemeVars()
|
||||||
|
@ -30,10 +27,7 @@ const props = defineProps({
|
||||||
type: Number,
|
type: Number,
|
||||||
default: -1,
|
default: -1,
|
||||||
},
|
},
|
||||||
value: {
|
value: Object,
|
||||||
type: Array,
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
size: Number,
|
size: Number,
|
||||||
length: Number,
|
length: Number,
|
||||||
viewAs: {
|
viewAs: {
|
||||||
|
@ -44,12 +38,8 @@ const props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: decodeTypes.NONE,
|
default: decodeTypes.NONE,
|
||||||
},
|
},
|
||||||
end: Boolean,
|
|
||||||
loading: Boolean,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['loadmore', 'loadall', 'reload', 'rename', 'delete'])
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {ComputedRef<string|number[]>}
|
* @type {ComputedRef<string|number[]>}
|
||||||
|
@ -125,7 +115,14 @@ const actionColumn = {
|
||||||
row.id,
|
row.id,
|
||||||
)
|
)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
browserStore.loadKeyValue(props.name, props.db, keyName.value).then((r) => {})
|
||||||
$message.success(i18n.t('dialogue.delete_key_succ', { key: row.id }))
|
$message.success(i18n.t('dialogue.delete_key_succ', { key: row.id }))
|
||||||
|
// update display value
|
||||||
|
// if (!isEmpty(removed)) {
|
||||||
|
// for (const elem of removed) {
|
||||||
|
// delete props.value[elem]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
}
|
}
|
||||||
|
@ -140,22 +137,15 @@ const columns = reactive([idColumn, valueColumn, actionColumn])
|
||||||
|
|
||||||
const tableData = computed(() => {
|
const tableData = computed(() => {
|
||||||
const data = []
|
const data = []
|
||||||
if (!isEmpty(props.value)) {
|
|
||||||
for (const elem of props.value) {
|
for (const elem of props.value) {
|
||||||
data.push({
|
data.push({
|
||||||
id: elem.id,
|
id: elem.id,
|
||||||
value: elem.value,
|
value: elem.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return data
|
return data
|
||||||
})
|
})
|
||||||
|
|
||||||
const entries = computed(() => {
|
|
||||||
const len = size(tableData.value)
|
|
||||||
return `${len} / ${Math.max(len, props.length)}`
|
|
||||||
})
|
|
||||||
|
|
||||||
const onAddRow = () => {
|
const onAddRow = () => {
|
||||||
dialogStore.openAddFieldsDialog(props.name, props.db, props.keyPath, props.keyCode, types.STREAM)
|
dialogStore.openAddFieldsDialog(props.name, props.db, props.keyPath, props.keyCode, types.STREAM)
|
||||||
}
|
}
|
||||||
|
@ -184,28 +174,20 @@ const onUpdateFilter = (filters, sourceColumn) => {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
reset: () => {
|
|
||||||
clearFilter()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="content-wrapper flex-box-v">
|
<div class="content-wrapper flex-box-v">
|
||||||
<content-toolbar
|
<content-toolbar
|
||||||
:db="props.db"
|
:db="props.db"
|
||||||
|
:decode="props.decode"
|
||||||
:key-code="props.keyCode"
|
:key-code="props.keyCode"
|
||||||
:key-path="props.keyPath"
|
:key-path="props.keyPath"
|
||||||
:key-type="keyType"
|
:key-type="keyType"
|
||||||
:loading="props.loading"
|
|
||||||
:server="props.name"
|
:server="props.name"
|
||||||
:ttl="ttl"
|
:ttl="ttl"
|
||||||
class="value-item-part"
|
:view-as="props.viewAs"
|
||||||
@delete="emit('delete')"
|
class="value-item-part" />
|
||||||
@reload="emit('reload')"
|
|
||||||
@rename="emit('rename')" />
|
|
||||||
<div class="tb2 value-item-part flex-box-h">
|
<div class="tb2 value-item-part flex-box-h">
|
||||||
<div class="flex-box-h">
|
<div class="flex-box-h">
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
|
@ -224,22 +206,6 @@ defineExpose({
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-item-expand"></div>
|
<div class="flex-item-expand"></div>
|
||||||
<n-button-group>
|
|
||||||
<icon-button
|
|
||||||
:disabled="props.end || props.loading"
|
|
||||||
:icon="LoadList"
|
|
||||||
border
|
|
||||||
size="18"
|
|
||||||
t-tooltip="interface.load_more_entries"
|
|
||||||
@click="emit('loadmore')" />
|
|
||||||
<icon-button
|
|
||||||
:disabled="props.end || props.loading"
|
|
||||||
:icon="LoadAll"
|
|
||||||
border
|
|
||||||
size="18"
|
|
||||||
t-tooltip="interface.load_all_entries"
|
|
||||||
@click="emit('loadall')" />
|
|
||||||
</n-button-group>
|
|
||||||
<n-button :focusable="false" plain @click="onAddRow">
|
<n-button :focusable="false" plain @click="onAddRow">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon :component="AddLink" size="18" />
|
<n-icon :component="AddLink" size="18" />
|
||||||
|
@ -247,18 +213,17 @@ defineExpose({
|
||||||
{{ $t('interface.add_row') }}
|
{{ $t('interface.add_row') }}
|
||||||
</n-button>
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="value-wrapper value-item-part flex-box-v flex-item-expand">
|
<div class="value-wrapper value-item-part fill-height flex-box-h">
|
||||||
<n-data-table
|
<n-data-table
|
||||||
:key="(row) => row.id"
|
:key="(row) => row.id"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
:bottom-bordered="false"
|
:bottom-bordered="false"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:loading="props.loading"
|
|
||||||
:single-column="true"
|
:single-column="true"
|
||||||
:single-line="false"
|
:single-line="false"
|
||||||
class="flex-item-expand"
|
|
||||||
flex-height
|
flex-height
|
||||||
|
max-height="100%"
|
||||||
size="small"
|
size="small"
|
||||||
striped
|
striped
|
||||||
virtual-scroll
|
virtual-scroll
|
||||||
|
@ -266,7 +231,7 @@ defineExpose({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="value-footer flex-box-h">
|
<div class="value-footer flex-box-h">
|
||||||
<n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ entries }}</n-text>
|
<n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ props.length }}</n-text>
|
||||||
<n-divider v-if="!isNaN(props.length)" vertical />
|
<n-divider v-if="!isNaN(props.length)" vertical />
|
||||||
<n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text>
|
<n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text>
|
||||||
<div class="flex-item-expand"></div>
|
<div class="flex-item-expand"></div>
|
||||||
|
|
|
@ -43,11 +43,8 @@ const props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: decodeTypes.NONE,
|
default: decodeTypes.NONE,
|
||||||
},
|
},
|
||||||
loading: Boolean,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['reload', 'rename', 'delete'])
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {ComputedRef<string|number[]>}
|
* @type {ComputedRef<string|number[]>}
|
||||||
|
@ -56,6 +53,16 @@ const keyName = computed(() => {
|
||||||
return !isEmpty(props.keyCode) ? props.keyCode : props.keyPath
|
return !isEmpty(props.keyCode) ? props.keyCode : props.keyPath
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// const viewOption = computed(() =>
|
||||||
|
// map(types, (t) => {
|
||||||
|
// return {
|
||||||
|
// value: t,
|
||||||
|
// label: t,
|
||||||
|
// key: t,
|
||||||
|
// }
|
||||||
|
// }),
|
||||||
|
// )
|
||||||
|
|
||||||
const keyType = redisTypes.STRING
|
const keyType = redisTypes.STRING
|
||||||
const viewLanguage = computed(() => {
|
const viewLanguage = computed(() => {
|
||||||
switch (props.viewAs) {
|
switch (props.viewAs) {
|
||||||
|
@ -67,23 +74,11 @@ const viewLanguage = computed(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const onViewTypeUpdate = (viewType) => {
|
const onViewTypeUpdate = (viewType) => {
|
||||||
browserStore.loadKeyDetail({
|
browserStore.loadKeyValue(props.name, props.db, keyName.value, viewType, props.decode)
|
||||||
server: props.name,
|
|
||||||
db: props.db,
|
|
||||||
key: keyName.value,
|
|
||||||
viewType,
|
|
||||||
decodeType: props.decode,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDecodeTypeUpdate = (decodeType) => {
|
const onDecodeTypeUpdate = (decodeType) => {
|
||||||
browserStore.loadKeyDetail({
|
browserStore.loadKeyValue(props.name, props.db, keyName.value, props.viewAs, decodeType)
|
||||||
server: props.name,
|
|
||||||
db: props.db,
|
|
||||||
key: keyName.value,
|
|
||||||
viewType: props.viewAs,
|
|
||||||
decodeType,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -131,7 +126,7 @@ const onSaveValue = async () => {
|
||||||
props.decode,
|
props.decode,
|
||||||
)
|
)
|
||||||
if (success) {
|
if (success) {
|
||||||
await browserStore.loadKeyDetail({ server: props.name, db: props.db, key: keyName.value })
|
await browserStore.loadKeyValue(props.name, props.db, keyName.value)
|
||||||
$message.success(i18n.t('dialogue.save_value_succ'))
|
$message.success(i18n.t('dialogue.save_value_succ'))
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
|
@ -149,16 +144,14 @@ const onSaveValue = async () => {
|
||||||
<div class="content-wrapper flex-box-v">
|
<div class="content-wrapper flex-box-v">
|
||||||
<content-toolbar
|
<content-toolbar
|
||||||
:db="props.db"
|
:db="props.db"
|
||||||
|
:decode="props.decode"
|
||||||
:key-code="keyCode"
|
:key-code="keyCode"
|
||||||
:key-path="keyPath"
|
:key-path="keyPath"
|
||||||
:key-type="keyType"
|
:key-type="keyType"
|
||||||
:loading="loading"
|
|
||||||
:server="props.name"
|
:server="props.name"
|
||||||
:ttl="ttl"
|
:ttl="ttl"
|
||||||
class="value-item-part"
|
:view-as="props.viewAs"
|
||||||
@delete="emit('delete')"
|
class="value-item-part" />
|
||||||
@reload="emit('reload')"
|
|
||||||
@rename="emit('rename')" />
|
|
||||||
<div class="tb2 value-item-part flex-box-h">
|
<div class="tb2 value-item-part flex-box-h">
|
||||||
<div class="flex-item-expand"></div>
|
<div class="flex-item-expand"></div>
|
||||||
<n-button-group v-if="!inEdit">
|
<n-button-group v-if="!inEdit">
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
||||||
import { types as redisTypes } from '@/consts/support_redis_type.js'
|
import { types as redisTypes } from '@/consts/support_redis_type.js'
|
||||||
import ContentValueString from '@/components/content_value/ContentValueString.vue'
|
import ContentValueString from '@/components/content_value/ContentValueString.vue'
|
||||||
import ContentValueHash from '@/components/content_value/ContentValueHash.vue'
|
import ContentValueHash from '@/components/content_value/ContentValueHash.vue'
|
||||||
|
@ -8,46 +9,35 @@ import ContentValueZset from '@/components/content_value/ContentValueZSet.vue'
|
||||||
import ContentValueStream from '@/components/content_value/ContentValueStream.vue'
|
import ContentValueStream from '@/components/content_value/ContentValueStream.vue'
|
||||||
import { useThemeVars } from 'naive-ui'
|
import { useThemeVars } from 'naive-ui'
|
||||||
import useBrowserStore from 'stores/browser.js'
|
import useBrowserStore from 'stores/browser.js'
|
||||||
import { computed, onMounted, ref, watch } from 'vue'
|
|
||||||
import { isEmpty } from 'lodash'
|
|
||||||
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
|
||||||
import useDialogStore from 'stores/dialog.js'
|
|
||||||
|
|
||||||
const themeVars = useThemeVars()
|
const themeVars = useThemeVars()
|
||||||
const browserStore = useBrowserStore()
|
const browserStore = useBrowserStore()
|
||||||
const dialogStore = useDialogStore()
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
blank: Boolean,
|
blank: Boolean,
|
||||||
content: {
|
type: String,
|
||||||
type: Object,
|
name: String,
|
||||||
default: {},
|
db: Number,
|
||||||
|
keyPath: String,
|
||||||
|
keyCode: {
|
||||||
|
type: Array,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
ttl: {
|
||||||
|
type: Number,
|
||||||
|
default: -1,
|
||||||
|
},
|
||||||
|
value: [String, Object],
|
||||||
|
size: Number,
|
||||||
|
length: Number,
|
||||||
|
viewAs: {
|
||||||
|
type: String,
|
||||||
|
default: formatTypes.PLAIN_TEXT,
|
||||||
|
},
|
||||||
|
decode: {
|
||||||
|
type: String,
|
||||||
|
default: decodeTypes.NONE,
|
||||||
},
|
},
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {ComputedRef<{
|
|
||||||
* type:
|
|
||||||
* String, name: String,
|
|
||||||
* db: Number,
|
|
||||||
* keyPath: String,
|
|
||||||
* keyCode: Array,
|
|
||||||
* ttl: Number,
|
|
||||||
* value: [String, Object],
|
|
||||||
* size: Number,
|
|
||||||
* length: Number,
|
|
||||||
* viewAs: String,
|
|
||||||
* decode: String,
|
|
||||||
* end: Boolean
|
|
||||||
* }>}
|
|
||||||
*/
|
|
||||||
const data = computed(() => {
|
|
||||||
return props.content
|
|
||||||
})
|
|
||||||
|
|
||||||
const binaryKey = computed(() => {
|
|
||||||
return !!data.value.keyCode
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const valueComponents = {
|
const valueComponents = {
|
||||||
|
@ -59,108 +49,34 @@ const valueComponents = {
|
||||||
[redisTypes.STREAM]: ContentValueStream,
|
[redisTypes.STREAM]: ContentValueStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
const keyName = computed(() => {
|
/**
|
||||||
return !isEmpty(data.value.keyCode) ? data.value.keyCode : data.value.keyPath
|
* reload current selection key
|
||||||
})
|
* @returns {Promise<null>}
|
||||||
|
*/
|
||||||
const loadData = async (reset, full) => {
|
const onReloadKey = async () => {
|
||||||
try {
|
await browserStore.loadKeyValue(props.name, props.db, props.key, props.viewAs)
|
||||||
const { name, db, view, decodeType, matchPattern } = data.value
|
|
||||||
await browserStore.loadKeyDetail({
|
|
||||||
server: name,
|
|
||||||
db: db,
|
|
||||||
key: keyName.value,
|
|
||||||
viewType: view,
|
|
||||||
decodeType: decodeType,
|
|
||||||
matchPattern: matchPattern,
|
|
||||||
reset: reset === true,
|
|
||||||
full: full === true,
|
|
||||||
})
|
|
||||||
} finally {
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const onReload = async () => {
|
|
||||||
try {
|
|
||||||
const { name, db, keyCode, keyPath } = data.value
|
|
||||||
await browserStore.reloadKey({ server: name, db, key: keyCode || keyPath })
|
|
||||||
} finally {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onRename = () => {
|
|
||||||
const { name, db, keyPath } = data.value
|
|
||||||
if (binaryKey.value) {
|
|
||||||
$message.error(i18n.t('dialogue.rename_binary_key_fail'))
|
|
||||||
} else {
|
|
||||||
dialogStore.openRenameKeyDialog(name, db, keyPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onDelete = () => {
|
|
||||||
$dialog.warning(i18n.t('dialogue.remove_tip', { name: props.keyPath }), () => {
|
|
||||||
const { name, db } = data.value
|
|
||||||
browserStore.deleteKey(name, db, keyName.value).then((success) => {
|
|
||||||
if (success) {
|
|
||||||
$message.success(i18n.t('dialogue.delete_key_succ', { key: props.keyPath }))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const onLoadMore = () => {
|
|
||||||
loadData(false, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onLoadAll = () => {
|
|
||||||
loadData(false, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// onReload()
|
|
||||||
loadData(false, false)
|
|
||||||
})
|
|
||||||
|
|
||||||
const contentRef = ref(null)
|
|
||||||
watch(
|
|
||||||
() => data.value?.keyPath,
|
|
||||||
() => {
|
|
||||||
// onReload()
|
|
||||||
if (contentRef.value?.reset != null) {
|
|
||||||
contentRef.value?.reset()
|
|
||||||
}
|
|
||||||
loadData(false, false)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-empty v-if="props.blank" :description="$t('interface.nonexist_tab_content')" class="empty-content">
|
<n-empty v-if="props.blank" :description="$t('interface.nonexist_tab_content')" class="empty-content">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<n-button :focusable="false" @click="onReload">{{ $t('interface.reload') }}</n-button>
|
<n-button :focusable="false" @click="onReloadKey">{{ $t('interface.reload') }}</n-button>
|
||||||
</template>
|
</template>
|
||||||
</n-empty>
|
</n-empty>
|
||||||
<keep-alive v-else>
|
<keep-alive v-else>
|
||||||
<component
|
<component
|
||||||
:is="valueComponents[data.type]"
|
:is="valueComponents[props.type]"
|
||||||
ref="contentRef"
|
:db="props.db"
|
||||||
:db="data.db"
|
:decode="props.decode"
|
||||||
:decode="data.decode || decodeTypes.NONE"
|
:key-code="props.keyCode"
|
||||||
:end="data.end"
|
:key-path="props.keyPath"
|
||||||
:key-code="data.keyCode"
|
:length="props.length"
|
||||||
:key-path="data.keyPath"
|
:name="props.name"
|
||||||
:length="data.length"
|
:size="props.size"
|
||||||
:loading="data.loading === true"
|
:ttl="props.ttl"
|
||||||
:name="data.name"
|
:value="props.value"
|
||||||
:size="data.size"
|
:view-as="props.viewAs" />
|
||||||
:ttl="data.ttl"
|
|
||||||
:value="data.value"
|
|
||||||
:view-as="data.viewAs || formatTypes.PLAIN_TEXT"
|
|
||||||
@delete="onDelete"
|
|
||||||
@loadall="onLoadAll"
|
|
||||||
@loadmore="onLoadMore"
|
|
||||||
@reload="onReload"
|
|
||||||
@rename="onRename" />
|
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,11 @@ import AddLink from '@/components/icons/AddLink.vue'
|
||||||
import { NButton, NCode, NIcon, NInput, NInputNumber, useThemeVars } from 'naive-ui'
|
import { NButton, NCode, NIcon, NInput, NInputNumber, useThemeVars } from 'naive-ui'
|
||||||
import { types, types as redisTypes } from '@/consts/support_redis_type.js'
|
import { types, types as redisTypes } from '@/consts/support_redis_type.js'
|
||||||
import EditableTableColumn from '@/components/common/EditableTableColumn.vue'
|
import EditableTableColumn from '@/components/common/EditableTableColumn.vue'
|
||||||
import { isEmpty, size } from 'lodash'
|
import { isEmpty } from 'lodash'
|
||||||
import useDialogStore from 'stores/dialog.js'
|
import useDialogStore from 'stores/dialog.js'
|
||||||
import bytes from 'bytes'
|
import bytes from 'bytes'
|
||||||
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
|
||||||
import useBrowserStore from 'stores/browser.js'
|
import useBrowserStore from 'stores/browser.js'
|
||||||
import LoadList from '@/components/icons/LoadList.vue'
|
|
||||||
import LoadAll from '@/components/icons/LoadAll.vue'
|
|
||||||
import IconButton from '@/components/common/IconButton.vue'
|
|
||||||
|
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
const themeVars = useThemeVars()
|
const themeVars = useThemeVars()
|
||||||
|
@ -41,12 +38,8 @@ const props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: decodeTypes.NONE,
|
default: decodeTypes.NONE,
|
||||||
},
|
},
|
||||||
end: Boolean,
|
|
||||||
loading: Boolean,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['loadmore', 'loadall', 'reload', 'rename', 'delete'])
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {ComputedRef<string|number[]>}
|
* @type {ComputedRef<string|number[]>}
|
||||||
|
@ -185,6 +178,7 @@ const actionColumn = {
|
||||||
row.value,
|
row.value,
|
||||||
)
|
)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
browserStore.loadKeyValue(props.name, props.db, keyName.value).then((r) => {})
|
||||||
$message.success(i18n.t('dialogue.delete_key_succ', { key: row.value }))
|
$message.success(i18n.t('dialogue.delete_key_succ', { key: row.value }))
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
|
@ -209,6 +203,7 @@ const actionColumn = {
|
||||||
currentEditRow.value.score,
|
currentEditRow.value.score,
|
||||||
)
|
)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
browserStore.loadKeyValue(props.name, props.db, keyName.value).then((r) => {})
|
||||||
$message.success(i18n.t('dialogue.save_value_succ'))
|
$message.success(i18n.t('dialogue.save_value_succ'))
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
|
@ -240,7 +235,6 @@ const columns = reactive([
|
||||||
|
|
||||||
const tableData = computed(() => {
|
const tableData = computed(() => {
|
||||||
const data = []
|
const data = []
|
||||||
if (!isEmpty(props.value)) {
|
|
||||||
let index = 0
|
let index = 0
|
||||||
for (const elem of props.value) {
|
for (const elem of props.value) {
|
||||||
data.push({
|
data.push({
|
||||||
|
@ -249,15 +243,9 @@ const tableData = computed(() => {
|
||||||
score: elem.score,
|
score: elem.score,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return data
|
return data
|
||||||
})
|
})
|
||||||
|
|
||||||
const entries = computed(() => {
|
|
||||||
const len = size(tableData.value)
|
|
||||||
return `${len} / ${Math.max(len, props.length)}`
|
|
||||||
})
|
|
||||||
|
|
||||||
const onAddRow = () => {
|
const onAddRow = () => {
|
||||||
dialogStore.openAddFieldsDialog(props.name, props.db, props.keyPath, props.keyCode, types.ZSET)
|
dialogStore.openAddFieldsDialog(props.name, props.db, props.keyPath, props.keyCode, types.ZSET)
|
||||||
}
|
}
|
||||||
|
@ -299,28 +287,20 @@ const onUpdateFilter = (filters, sourceColumn) => {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
reset: () => {
|
|
||||||
clearFilter()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="content-wrapper flex-box-v">
|
<div class="content-wrapper flex-box-v">
|
||||||
<content-toolbar
|
<content-toolbar
|
||||||
:db="props.db"
|
:db="props.db"
|
||||||
|
:decode="props.decode"
|
||||||
:key-code="props.keyCode"
|
:key-code="props.keyCode"
|
||||||
:key-path="props.keyPath"
|
:key-path="props.keyPath"
|
||||||
:key-type="keyType"
|
:key-type="keyType"
|
||||||
:loading="props.loading"
|
|
||||||
:server="props.name"
|
:server="props.name"
|
||||||
:ttl="ttl"
|
:ttl="ttl"
|
||||||
class="value-item-part"
|
:view-as="props.viewAs"
|
||||||
@delete="emit('delete')"
|
class="value-item-part" />
|
||||||
@reload="emit('reload')"
|
|
||||||
@rename="emit('rename')" />
|
|
||||||
<div class="tb2 value-item-part flex-box-h">
|
<div class="tb2 value-item-part flex-box-h">
|
||||||
<div class="flex-box-h">
|
<div class="flex-box-h">
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
|
@ -344,22 +324,6 @@ defineExpose({
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-item-expand"></div>
|
<div class="flex-item-expand"></div>
|
||||||
<n-button-group>
|
|
||||||
<icon-button
|
|
||||||
:disabled="props.end || props.loading"
|
|
||||||
:icon="LoadList"
|
|
||||||
border
|
|
||||||
size="18"
|
|
||||||
t-tooltip="interface.load_more_entries"
|
|
||||||
@click="emit('loadmore')" />
|
|
||||||
<icon-button
|
|
||||||
:disabled="props.end || props.loading"
|
|
||||||
:icon="LoadAll"
|
|
||||||
border
|
|
||||||
size="18"
|
|
||||||
t-tooltip="interface.load_all_entries"
|
|
||||||
@click="emit('loadall')" />
|
|
||||||
</n-button-group>
|
|
||||||
<n-button :focusable="false" plain @click="onAddRow">
|
<n-button :focusable="false" plain @click="onAddRow">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon :component="AddLink" size="18" />
|
<n-icon :component="AddLink" size="18" />
|
||||||
|
@ -367,25 +331,24 @@ defineExpose({
|
||||||
{{ $t('interface.add_row') }}
|
{{ $t('interface.add_row') }}
|
||||||
</n-button>
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="value-wrapper value-item-part flex-box-v flex-item-expand">
|
<div class="value-wrapper value-item-part fill-height flex-box-h">
|
||||||
<n-data-table
|
<n-data-table
|
||||||
:key="(row) => row.no"
|
:key="(row) => row.no"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
:bottom-bordered="false"
|
:bottom-bordered="false"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:loading="props.loading"
|
|
||||||
:single-column="true"
|
:single-column="true"
|
||||||
:single-line="false"
|
:single-line="false"
|
||||||
class="flex-item-expand"
|
|
||||||
flex-height
|
flex-height
|
||||||
|
max-height="100%"
|
||||||
size="small"
|
size="small"
|
||||||
striped
|
striped
|
||||||
virtual-scroll
|
virtual-scroll
|
||||||
@update:filters="onUpdateFilter" />
|
@update:filters="onUpdateFilter" />
|
||||||
</div>
|
</div>
|
||||||
<div class="value-footer flex-box-h">
|
<div class="value-footer flex-box-h">
|
||||||
<n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ entries }}</n-text>
|
<n-text v-if="!isNaN(props.length)">{{ $t('interface.entries') }}: {{ props.length }}</n-text>
|
||||||
<n-divider v-if="!isNaN(props.length)" vertical />
|
<n-divider v-if="!isNaN(props.length)" vertical />
|
||||||
<n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text>
|
<n-text v-if="!isNaN(props.size)">{{ $t('interface.memory_usage') }}: {{ bytes(props.size) }}</n-text>
|
||||||
<div class="flex-item-expand"></div>
|
<div class="flex-item-expand"></div>
|
||||||
|
|
|
@ -11,7 +11,6 @@ import AddZSetValue from '@/components/new_value/AddZSetValue.vue'
|
||||||
import NewStreamValue from '@/components/new_value/NewStreamValue.vue'
|
import NewStreamValue from '@/components/new_value/NewStreamValue.vue'
|
||||||
import { isEmpty, size, slice } from 'lodash'
|
import { isEmpty, size, slice } from 'lodash'
|
||||||
import useBrowserStore from 'stores/browser.js'
|
import useBrowserStore from 'stores/browser.js'
|
||||||
import useTabStore from 'stores/tab.js'
|
|
||||||
|
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
const newForm = reactive({
|
const newForm = reactive({
|
||||||
|
@ -80,7 +79,6 @@ watch(
|
||||||
)
|
)
|
||||||
|
|
||||||
const browserStore = useBrowserStore()
|
const browserStore = useBrowserStore()
|
||||||
const tab = useTabStore()
|
|
||||||
const onAdd = async () => {
|
const onAdd = async () => {
|
||||||
try {
|
try {
|
||||||
const { server, db, key, keyCode, type } = newForm
|
const { server, db, key, keyCode, type } = newForm
|
||||||
|
@ -89,7 +87,6 @@ const onAdd = async () => {
|
||||||
value = defaultValue[type]
|
value = defaultValue[type]
|
||||||
}
|
}
|
||||||
const keyName = isEmpty(keyCode) ? key : keyCode
|
const keyName = isEmpty(keyCode) ? key : keyCode
|
||||||
let updated = false
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case types.LIST:
|
case types.LIST:
|
||||||
{
|
{
|
||||||
|
@ -101,7 +98,9 @@ const onAdd = async () => {
|
||||||
}
|
}
|
||||||
const { success, msg } = data
|
const { success, msg } = data
|
||||||
if (success) {
|
if (success) {
|
||||||
updated = true
|
if (newForm.reload) {
|
||||||
|
browserStore.loadKeyValue(server, db, keyName).then(() => {})
|
||||||
|
}
|
||||||
$message.success(i18n.t('dialogue.handle_succ'))
|
$message.success(i18n.t('dialogue.handle_succ'))
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
|
@ -113,7 +112,9 @@ const onAdd = async () => {
|
||||||
{
|
{
|
||||||
const { success, msg } = await browserStore.addHashField(server, db, keyName, newForm.opType, value)
|
const { success, msg } = await browserStore.addHashField(server, db, keyName, newForm.opType, value)
|
||||||
if (success) {
|
if (success) {
|
||||||
updated = true
|
if (newForm.reload) {
|
||||||
|
browserStore.loadKeyValue(server, db, keyName).then(() => {})
|
||||||
|
}
|
||||||
$message.success(i18n.t('dialogue.handle_succ'))
|
$message.success(i18n.t('dialogue.handle_succ'))
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
|
@ -125,7 +126,9 @@ const onAdd = async () => {
|
||||||
{
|
{
|
||||||
const { success, msg } = await browserStore.addSetItem(server, db, keyName, value)
|
const { success, msg } = await browserStore.addSetItem(server, db, keyName, value)
|
||||||
if (success) {
|
if (success) {
|
||||||
updated = true
|
if (newForm.reload) {
|
||||||
|
browserStore.loadKeyValue(server, db, keyName).then(() => {})
|
||||||
|
}
|
||||||
$message.success(i18n.t('dialogue.handle_succ'))
|
$message.success(i18n.t('dialogue.handle_succ'))
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
|
@ -137,7 +140,9 @@ const onAdd = async () => {
|
||||||
{
|
{
|
||||||
const { success, msg } = await browserStore.addZSetItem(server, db, keyName, newForm.opType, value)
|
const { success, msg } = await browserStore.addZSetItem(server, db, keyName, newForm.opType, value)
|
||||||
if (success) {
|
if (success) {
|
||||||
updated = true
|
if (newForm.reload) {
|
||||||
|
browserStore.loadKeyValue(server, db, keyName).then(() => {})
|
||||||
|
}
|
||||||
$message.success(i18n.t('dialogue.handle_succ'))
|
$message.success(i18n.t('dialogue.handle_succ'))
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
|
@ -156,7 +161,9 @@ const onAdd = async () => {
|
||||||
slice(value, 1),
|
slice(value, 1),
|
||||||
)
|
)
|
||||||
if (success) {
|
if (success) {
|
||||||
updated = true
|
if (newForm.reload) {
|
||||||
|
browserStore.loadKeyValue(server, db, keyName).then(() => {})
|
||||||
|
}
|
||||||
$message.success(i18n.t('dialogue.handle_succ'))
|
$message.success(i18n.t('dialogue.handle_succ'))
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
|
@ -165,12 +172,6 @@ const onAdd = async () => {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updated) {
|
|
||||||
if (newForm.reload) {
|
|
||||||
browserStore.reloadKey({ server, db, key: keyName })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dialogStore.closeAddFieldsDialog()
|
dialogStore.closeAddFieldsDialog()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$message.error(e.message)
|
$message.error(e.message)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, ref, watch } from 'vue'
|
import { reactive, watch } from 'vue'
|
||||||
import useDialog from 'stores/dialog'
|
import useDialog from 'stores/dialog'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { isEmpty, size } from 'lodash'
|
import { isEmpty, size } from 'lodash'
|
||||||
|
@ -29,22 +29,18 @@ watch(
|
||||||
deleteForm.loadingAffected = false
|
deleteForm.loadingAffected = false
|
||||||
deleteForm.affectedKeys = []
|
deleteForm.affectedKeys = []
|
||||||
deleteForm.async = true
|
deleteForm.async = true
|
||||||
loading.value = false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
const loading = ref(false)
|
|
||||||
const scanAffectedKey = async () => {
|
const scanAffectedKey = async () => {
|
||||||
try {
|
try {
|
||||||
loading.value = true
|
|
||||||
deleteForm.loadingAffected = true
|
deleteForm.loadingAffected = true
|
||||||
const { keys = [] } = await browserStore.scanKeys(deleteForm.server, deleteForm.db, deleteForm.key)
|
const { keys = [] } = await browserStore.scanKeys(deleteForm.server, deleteForm.db, deleteForm.key)
|
||||||
deleteForm.affectedKeys = keys || []
|
deleteForm.affectedKeys = keys || []
|
||||||
deleteForm.showAffected = true
|
deleteForm.showAffected = true
|
||||||
} finally {
|
} finally {
|
||||||
deleteForm.loadingAffected = false
|
deleteForm.loadingAffected = false
|
||||||
loading.value = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +52,6 @@ const resetAffected = () => {
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
const onConfirmDelete = async () => {
|
const onConfirmDelete = async () => {
|
||||||
try {
|
try {
|
||||||
loading.value = true
|
|
||||||
const { server, db, key, async } = deleteForm
|
const { server, db, key, async } = deleteForm
|
||||||
const success = await browserStore.deleteKeyPrefix(server, db, key, async)
|
const success = await browserStore.deleteKeyPrefix(server, db, key, async)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -64,9 +59,6 @@ const onConfirmDelete = async () => {
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$message.error(e.message)
|
$message.error(e.message)
|
||||||
return
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
}
|
||||||
dialogStore.closeDeleteKeyDialog()
|
dialogStore.closeDeleteKeyDialog()
|
||||||
}
|
}
|
||||||
|
@ -86,7 +78,6 @@ const onClose = () => {
|
||||||
:title="$t('interface.batch_delete_key')"
|
:title="$t('interface.batch_delete_key')"
|
||||||
preset="dialog"
|
preset="dialog"
|
||||||
transform-origin="center">
|
transform-origin="center">
|
||||||
<n-spin :show="loading">
|
|
||||||
<n-form :model="deleteForm" :show-require-mark="false" label-placement="top">
|
<n-form :model="deleteForm" :show-require-mark="false" label-placement="top">
|
||||||
<n-form-item :label="$t('dialogue.key.server')">
|
<n-form-item :label="$t('dialogue.key.server')">
|
||||||
<n-input :value="deleteForm.server" readonly />
|
<n-input :value="deleteForm.server" readonly />
|
||||||
|
@ -98,14 +89,9 @@ const onClose = () => {
|
||||||
<n-input v-model:value="deleteForm.key" placeholder="" @input="resetAffected" />
|
<n-input v-model:value="deleteForm.key" placeholder="" @input="resetAffected" />
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-form-item :label="$t('dialogue.key.async_delete')" required>
|
<n-form-item :label="$t('dialogue.key.async_delete')" required>
|
||||||
<n-checkbox v-model:checked="deleteForm.async">
|
<n-checkbox v-model:checked="deleteForm.async">{{ $t('dialogue.key.async_delete_title') }}</n-checkbox>
|
||||||
{{ $t('dialogue.key.async_delete_title') }}
|
|
||||||
</n-checkbox>
|
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-card
|
<n-card v-if="deleteForm.showAffected" :title="$t('dialogue.key.affected_key')" size="small">
|
||||||
v-if="deleteForm.showAffected"
|
|
||||||
:title="$t('dialogue.key.affected_key') + `(${size(deleteForm.affectedKeys)})`"
|
|
||||||
size="small">
|
|
||||||
<n-skeleton v-if="deleteForm.loadingAffected" :repeat="10" text />
|
<n-skeleton v-if="deleteForm.loadingAffected" :repeat="10" text />
|
||||||
<n-log
|
<n-log
|
||||||
v-else
|
v-else
|
||||||
|
@ -115,24 +101,17 @@ const onClose = () => {
|
||||||
style="user-select: text; cursor: text" />
|
style="user-select: text; cursor: text" />
|
||||||
</n-card>
|
</n-card>
|
||||||
</n-form>
|
</n-form>
|
||||||
</n-spin>
|
|
||||||
|
|
||||||
<template #action>
|
<template #action>
|
||||||
<div class="flex-item n-dialog__action">
|
<div class="flex-item n-dialog__action">
|
||||||
<n-button :disabled="loading" :focusable="false" @click="onClose">{{ $t('common.cancel') }}</n-button>
|
<n-button :focusable="false" @click="onClose">{{ $t('common.cancel') }}</n-button>
|
||||||
<n-button
|
<n-button v-if="!deleteForm.showAffected" :focusable="false" type="primary" @click="scanAffectedKey">
|
||||||
v-if="!deleteForm.showAffected"
|
|
||||||
:focusable="false"
|
|
||||||
:loading="loading"
|
|
||||||
type="primary"
|
|
||||||
@click="scanAffectedKey">
|
|
||||||
{{ $t('dialogue.key.show_affected_key') }}
|
{{ $t('dialogue.key.show_affected_key') }}
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button
|
<n-button
|
||||||
v-else
|
v-else
|
||||||
:disabled="isEmpty(deleteForm.affectedKeys)"
|
:disabled="isEmpty(deleteForm.affectedKeys)"
|
||||||
:focusable="false"
|
:focusable="false"
|
||||||
:loading="loading"
|
|
||||||
type="error"
|
type="error"
|
||||||
@click="onConfirmDelete">
|
@click="onConfirmDelete">
|
||||||
{{ $t('dialogue.key.confirm_delete_key', { num: size(deleteForm.affectedKeys) }) }}
|
{{ $t('dialogue.key.confirm_delete_key', { num: size(deleteForm.affectedKeys) }) }}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, ref, watch } from 'vue'
|
import { reactive, watch } from 'vue'
|
||||||
import useDialog from 'stores/dialog'
|
import useDialog from 'stores/dialog'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import useBrowserStore from 'stores/browser.js'
|
import useBrowserStore from 'stores/browser.js'
|
||||||
|
@ -23,16 +23,13 @@ watch(
|
||||||
flushForm.db = db
|
flushForm.db = db
|
||||||
flushForm.async = true
|
flushForm.async = true
|
||||||
flushForm.confirm = false
|
flushForm.confirm = false
|
||||||
loading.value = false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
const loading = ref(false)
|
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
const onConfirmFlush = async () => {
|
const onConfirmFlush = async () => {
|
||||||
try {
|
try {
|
||||||
loading.value = true
|
|
||||||
const { server, db, async } = flushForm
|
const { server, db, async } = flushForm
|
||||||
const success = await browserStore.flushDatabase(server, db, async)
|
const success = await browserStore.flushDatabase(server, db, async)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -40,9 +37,6 @@ const onConfirmFlush = async () => {
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$message.error(e.message)
|
$message.error(e.message)
|
||||||
return
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
}
|
||||||
dialogStore.closeFlushDBDialog()
|
dialogStore.closeFlushDBDialog()
|
||||||
}
|
}
|
||||||
|
@ -62,7 +56,6 @@ const onClose = () => {
|
||||||
:title="$t('interface.flush_db')"
|
:title="$t('interface.flush_db')"
|
||||||
preset="dialog"
|
preset="dialog"
|
||||||
transform-origin="center">
|
transform-origin="center">
|
||||||
<n-spin :show="loading">
|
|
||||||
<n-form :model="flushForm" :show-require-mark="false" label-placement="top">
|
<n-form :model="flushForm" :show-require-mark="false" label-placement="top">
|
||||||
<n-form-item :label="$t('dialogue.key.server')">
|
<n-form-item :label="$t('dialogue.key.server')">
|
||||||
<n-input :value="flushForm.server" readonly />
|
<n-input :value="flushForm.server" readonly />
|
||||||
|
@ -71,9 +64,7 @@ const onClose = () => {
|
||||||
<n-input :value="flushForm.db.toString()" readonly />
|
<n-input :value="flushForm.db.toString()" readonly />
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-form-item :label="$t('dialogue.key.async_delete')" required>
|
<n-form-item :label="$t('dialogue.key.async_delete')" required>
|
||||||
<n-checkbox v-model:checked="flushForm.async">
|
<n-checkbox v-model:checked="flushForm.async">{{ $t('dialogue.key.async_delete_title') }}</n-checkbox>
|
||||||
{{ $t('dialogue.key.async_delete_title') }}
|
|
||||||
</n-checkbox>
|
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-form-item :label="$t('common.warning')" required>
|
<n-form-item :label="$t('common.warning')" required>
|
||||||
<n-checkbox v-model:checked="flushForm.confirm">
|
<n-checkbox v-model:checked="flushForm.confirm">
|
||||||
|
@ -81,16 +72,10 @@ const onClose = () => {
|
||||||
</n-checkbox>
|
</n-checkbox>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
</n-form>
|
</n-form>
|
||||||
</n-spin>
|
|
||||||
|
|
||||||
<template #action>
|
<template #action>
|
||||||
<n-button :disabled="loading" :focusable="false" @click="onClose">{{ $t('common.cancel') }}</n-button>
|
<n-button :focusable="false" @click="onClose">{{ $t('common.cancel') }}</n-button>
|
||||||
<n-button
|
<n-button :disabled="!!!flushForm.confirm" :focusable="false" type="primary" @click="onConfirmFlush">
|
||||||
:disabled="!!!flushForm.confirm"
|
|
||||||
:focusable="false"
|
|
||||||
:loading="loading"
|
|
||||||
type="primary"
|
|
||||||
@click="onConfirmFlush">
|
|
||||||
{{ $t('dialogue.key.confirm_flush_db') }}
|
{{ $t('dialogue.key.confirm_flush_db') }}
|
||||||
</n-button>
|
</n-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -130,7 +130,7 @@ const onAdd = async () => {
|
||||||
if (success) {
|
if (success) {
|
||||||
// select current key
|
// select current key
|
||||||
tabStore.setSelectedKeys(server, nodeKey)
|
tabStore.setSelectedKeys(server, nodeKey)
|
||||||
browserStore.loadKeySummary({ server, db, key })
|
browserStore.loadKeyValue(server, db, key).then(() => {})
|
||||||
} else if (!isEmpty(msg)) {
|
} else if (!isEmpty(msg)) {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { reactive, watch } from 'vue'
|
||||||
import useDialog from 'stores/dialog'
|
import useDialog from 'stores/dialog'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import useBrowserStore from 'stores/browser.js'
|
import useBrowserStore from 'stores/browser.js'
|
||||||
import useTabStore from 'stores/tab.js'
|
|
||||||
|
|
||||||
const renameForm = reactive({
|
const renameForm = reactive({
|
||||||
server: '',
|
server: '',
|
||||||
|
@ -14,7 +13,6 @@ const renameForm = reactive({
|
||||||
|
|
||||||
const dialogStore = useDialog()
|
const dialogStore = useDialog()
|
||||||
const browserStore = useBrowserStore()
|
const browserStore = useBrowserStore()
|
||||||
const tab = useTabStore()
|
|
||||||
watch(
|
watch(
|
||||||
() => dialogStore.renameDialogVisible,
|
() => dialogStore.renameDialogVisible,
|
||||||
(visible) => {
|
(visible) => {
|
||||||
|
@ -32,10 +30,9 @@ const i18n = useI18n()
|
||||||
const onRename = async () => {
|
const onRename = async () => {
|
||||||
try {
|
try {
|
||||||
const { server, db, key, newKey } = renameForm
|
const { server, db, key, newKey } = renameForm
|
||||||
const { success, msg, nodeKey } = await browserStore.renameKey(server, db, key, newKey)
|
const { success, msg } = await browserStore.renameKey(server, db, key, newKey)
|
||||||
if (success) {
|
if (success) {
|
||||||
tab.setSelectedKeys(server, nodeKey)
|
await browserStore.loadKeyValue(server, db, newKey)
|
||||||
browserStore.loadKeySummary({ server, db, key: newKey })
|
|
||||||
$message.success(i18n.t('dialogue.handle_succ'))
|
$message.success(i18n.t('dialogue.handle_succ'))
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
|
|
|
@ -272,20 +272,11 @@ const handleSelectContextMenu = (key) => {
|
||||||
const { match: pattern, type } = browserStore.getKeyFilter(props.server, db)
|
const { match: pattern, type } = browserStore.getKeyFilter(props.server, db)
|
||||||
dialogStore.openKeyFilterDialog(props.server, db, pattern, type)
|
dialogStore.openKeyFilterDialog(props.server, db, pattern, type)
|
||||||
break
|
break
|
||||||
case 'key_reload':
|
// case 'key_reload':
|
||||||
if (node != null && !!!node.loading) {
|
// browserStore.loadKeys(props.server, db, redisKey)
|
||||||
node.loading = true
|
// break
|
||||||
browserStore.reloadLayer(props.server, db, redisKey).finally(() => {
|
|
||||||
delete node.loading
|
|
||||||
})
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case 'value_reload':
|
case 'value_reload':
|
||||||
browserStore.reloadKey({
|
browserStore.loadKeyValue(props.server, db, redisKey)
|
||||||
server: props.server,
|
|
||||||
db,
|
|
||||||
key: redisKey,
|
|
||||||
})
|
|
||||||
break
|
break
|
||||||
case 'key_remove':
|
case 'key_remove':
|
||||||
dialogStore.openDeleteKeyDialog(props.server, db, isEmpty(redisKey) ? '*' : redisKey + ':*')
|
dialogStore.openDeleteKeyDialog(props.server, db, isEmpty(redisKey) ? '*' : redisKey + ':*')
|
||||||
|
@ -387,18 +378,14 @@ const onUpdateSelectedKeys = (keys, options) => {
|
||||||
const { key, db } = node
|
const { key, db } = node
|
||||||
const redisKey = node.redisKeyCode || node.redisKey
|
const redisKey = node.redisKeyCode || node.redisKey
|
||||||
if (!includes(selectedKeys.value, key)) {
|
if (!includes(selectedKeys.value, key)) {
|
||||||
browserStore.loadKeySummary({
|
browserStore.loadKeyValue(props.server, db, redisKey)
|
||||||
server: props.server,
|
|
||||||
db,
|
|
||||||
key: redisKey,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// default is load blank key to display server status
|
// default is load blank key to display server status
|
||||||
tabStore.openBlank(props.server)
|
browserStore.loadKeyValue(props.server, 0)
|
||||||
} finally {
|
} finally {
|
||||||
tabStore.setSelectedKeys(props.server, keys)
|
tabStore.setSelectedKeys(props.server, keys)
|
||||||
}
|
}
|
||||||
|
@ -524,7 +511,7 @@ const renderIconMenu = (items) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const calcDBMenu = (opened, loading, end) => {
|
const getDatabaseMenu = (opened, loading, end) => {
|
||||||
const btns = []
|
const btns = []
|
||||||
if (opened) {
|
if (opened) {
|
||||||
btns.push(
|
btns.push(
|
||||||
|
@ -586,16 +573,14 @@ const calcDBMenu = (opened, loading, end) => {
|
||||||
return btns
|
return btns
|
||||||
}
|
}
|
||||||
|
|
||||||
const calcLayerMenu = (loading, end) => {
|
const getLayerMenu = () => {
|
||||||
return [
|
return [
|
||||||
// reload layer enable only full loaded
|
// disable reload by layer, due to conflict with partial loading keys
|
||||||
h(IconButton, {
|
// h(IconButton, {
|
||||||
tTooltip: end === true ? 'interface.reload' : 'interface.reload',
|
// tTooltip: 'interface.reload',
|
||||||
icon: Refresh,
|
// icon: Refresh,
|
||||||
loading: loading === true,
|
// onClick: () => handleSelectContextMenu('key_reload'),
|
||||||
disabled: end !== true,
|
// }),
|
||||||
onClick: () => handleSelectContextMenu('key_reload'),
|
|
||||||
}),
|
|
||||||
h(IconButton, {
|
h(IconButton, {
|
||||||
tTooltip: 'interface.new_key',
|
tTooltip: 'interface.new_key',
|
||||||
icon: Add,
|
icon: Add,
|
||||||
|
@ -609,7 +594,7 @@ const calcLayerMenu = (loading, end) => {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
const calcValueMenu = () => {
|
const getValueMenu = () => {
|
||||||
return [
|
return [
|
||||||
h(IconButton, {
|
h(IconButton, {
|
||||||
tTooltip: 'interface.remove_key',
|
tTooltip: 'interface.remove_key',
|
||||||
|
@ -624,12 +609,11 @@ const renderSuffix = ({ option }) => {
|
||||||
if ((option.type === ConnectionType.RedisDB && option.opened) || includes(selectedKeys.value, option.key)) {
|
if ((option.type === ConnectionType.RedisDB && option.opened) || includes(selectedKeys.value, option.key)) {
|
||||||
switch (option.type) {
|
switch (option.type) {
|
||||||
case ConnectionType.RedisDB:
|
case ConnectionType.RedisDB:
|
||||||
return renderIconMenu(calcDBMenu(option.opened, option.loading, option.fullLoaded))
|
return renderIconMenu(getDatabaseMenu(option.opened, option.loading, option.fullLoaded))
|
||||||
case ConnectionType.RedisKey:
|
case ConnectionType.RedisKey:
|
||||||
const fullLoaded = browserStore.isFullLoaded(props.server, option.db)
|
return renderIconMenu(getLayerMenu())
|
||||||
return renderIconMenu(calcLayerMenu(option.loading, fullLoaded))
|
|
||||||
case ConnectionType.RedisValue:
|
case ConnectionType.RedisValue:
|
||||||
return renderIconMenu(calcValueMenu())
|
return renderIconMenu(getValueMenu())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
|
@ -656,7 +640,7 @@ const nodeProps = ({ option }) => {
|
||||||
contextMenuParam.x = e.clientX
|
contextMenuParam.x = e.clientX
|
||||||
contextMenuParam.y = e.clientY
|
contextMenuParam.y = e.clientY
|
||||||
contextMenuParam.show = true
|
contextMenuParam.show = true
|
||||||
onUpdateSelectedKeys([option.key], [option])
|
tabStore.setSelectedKeys(props.server, option.key)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// onMouseover() {
|
// onMouseover() {
|
||||||
|
|
|
@ -90,8 +90,6 @@
|
||||||
"new_key": "Add Key",
|
"new_key": "Add Key",
|
||||||
"load_more": "Load More Keys",
|
"load_more": "Load More Keys",
|
||||||
"load_all": "Load All Left Keys",
|
"load_all": "Load All Left Keys",
|
||||||
"load_more_entries": "Load More",
|
|
||||||
"load_all_entries": "Load All",
|
|
||||||
"more_action": "More Action",
|
"more_action": "More Action",
|
||||||
"nonexist_tab_content": "Selected key does not exist or no key is selected. Please retry",
|
"nonexist_tab_content": "Selected key does not exist or no key is selected. Please retry",
|
||||||
"empty_server_content": "Select and open a connection from the left",
|
"empty_server_content": "Select and open a connection from the left",
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import en from './en-us'
|
import en from './en-us'
|
||||||
import pt from './pt-br'
|
|
||||||
import zh from './zh-cn'
|
import zh from './zh-cn'
|
||||||
|
|
||||||
export const lang = {
|
export const lang = {
|
||||||
en,
|
en,
|
||||||
pt,
|
|
||||||
zh,
|
zh,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,308 +0,0 @@
|
||||||
{
|
|
||||||
"name": "Português",
|
|
||||||
"common": {
|
|
||||||
"confirm": "Confirmar",
|
|
||||||
"cancel": "Cancelar",
|
|
||||||
"success": "Sucesso",
|
|
||||||
"warning": "Aviso",
|
|
||||||
"error": "Erro",
|
|
||||||
"save": "Salvar",
|
|
||||||
"none": "Nenhum",
|
|
||||||
"second": "Segundo(s)",
|
|
||||||
"unit_day": "D",
|
|
||||||
"unit_hour": "H",
|
|
||||||
"unit_minute": "M",
|
|
||||||
"all": "Tudo",
|
|
||||||
"key": "Chave",
|
|
||||||
"value": "Valor",
|
|
||||||
"field": "Campo"
|
|
||||||
},
|
|
||||||
"preferences": {
|
|
||||||
"name": "Preferências",
|
|
||||||
"restore_defaults": "Restaurar Padrões",
|
|
||||||
"general": {
|
|
||||||
"name": "Geral",
|
|
||||||
"theme": "Tema",
|
|
||||||
"theme_light": "Claro",
|
|
||||||
"theme_dark": "Escuro",
|
|
||||||
"theme_auto": "Automático",
|
|
||||||
"language": "Idioma",
|
|
||||||
"system_lang": "Usar Idioma do Sistema",
|
|
||||||
"default": "Padrão",
|
|
||||||
"font": "Fonte",
|
|
||||||
"font_size": "Tamanho da Fonte",
|
|
||||||
"scan_size": "Tamanho Padrão para Comando SCAN",
|
|
||||||
"proxy": "Proxy",
|
|
||||||
"use_system_proxy": "Usar proxy do sistema",
|
|
||||||
"use_system_proxy_http": "Usar proxy do sistema apenas para solicitações HTTP(S)",
|
|
||||||
"update": "Atualizar",
|
|
||||||
"auto_check_update": "Verificar atualizações automaticamente"
|
|
||||||
},
|
|
||||||
"editor": {
|
|
||||||
"name": "Editor"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"interface": {
|
|
||||||
"new_conn": "Adicionar Nova Conexão",
|
|
||||||
"new_group": "Adicionar Novo Grupo",
|
|
||||||
"disconnect_all": "Desconectar tudo",
|
|
||||||
"status": "Status",
|
|
||||||
"filter": "Filtro",
|
|
||||||
"sort_conn": "Ordenar Conexões",
|
|
||||||
"new_conn_title": "Nova Conexão",
|
|
||||||
"open_db": "Abrir Banco de Dados",
|
|
||||||
"close_db": "Fechar Banco de Dados",
|
|
||||||
"filter_key": "Filtrar Chave",
|
|
||||||
"disconnect": "Desconectar",
|
|
||||||
"dup_conn": "Duplicar Conexão",
|
|
||||||
"remove_conn": "Excluir Conexão",
|
|
||||||
"edit_conn": "Editar Configuração da Conexão",
|
|
||||||
"edit_conn_group": "Editar Grupo de Conexão",
|
|
||||||
"rename_conn_group": "Renomear Grupo de Conexão",
|
|
||||||
"remove_conn_group": "Excluir Grupo de Conexão",
|
|
||||||
"ttl": "TTL",
|
|
||||||
"forever": "Para Sempre",
|
|
||||||
"rename_key": "Renomear Chave",
|
|
||||||
"delete_key": "Excluir Chave",
|
|
||||||
"batch_delete_key": "Excluir Lotes de Chaves",
|
|
||||||
"flush_db": "Limpar Banco de Dados",
|
|
||||||
"copy_value": "Copiar Valor",
|
|
||||||
"edit_value": "Editar Valor",
|
|
||||||
"save_update": "Salvar Atualização",
|
|
||||||
"score_filter_tip": "Lista de operadores suportados abaixo:\n= igual\n!= diferente\n> maior que\n>= maior ou igual a\n< menor que\n<= menor ou igual a\nPor exemplo, se você deseja filtrar resultados maiores que 3, insira: >3",
|
|
||||||
"add_row": "Adicionar Linha",
|
|
||||||
"edit_row": "Editar Linha",
|
|
||||||
"delete_row": "Excluir Linha",
|
|
||||||
"search": "Buscar",
|
|
||||||
"filter_field": "Filtrar Campo",
|
|
||||||
"filter_value": "Filtrar Valor",
|
|
||||||
"length": "Tamanho",
|
|
||||||
"entries": "Entradas",
|
|
||||||
"memory_usage": "Uso de Memória",
|
|
||||||
"view_as": "Visualizar Como",
|
|
||||||
"decode_with": "Decodificar / Descompressão",
|
|
||||||
"reload": "Recarregar",
|
|
||||||
"open_connection": "Abrir Conexão",
|
|
||||||
"copy_path": "Copiar Caminho",
|
|
||||||
"copy_key": "Copiar Chave",
|
|
||||||
"binary_key": "Nome da Chave Binária",
|
|
||||||
"remove_key": "Remover Chave",
|
|
||||||
"new_key": "Adicionar Chave",
|
|
||||||
"load_more": "Carregar Mais Chaves",
|
|
||||||
"load_all": "Carregar Todas as Chaves Restantes",
|
|
||||||
"more_action": "Mais Ação",
|
|
||||||
"nonexist_tab_content": "A chave selecionada não existe ou nenhuma chave está selecionada. Por favor, tente novamente",
|
|
||||||
"empty_server_content": "Selecione e abra uma conexão à esquerda",
|
|
||||||
"empty_server_list": "Nenhum servidor Redis",
|
|
||||||
"action": "Ação",
|
|
||||||
"type": "Tipo",
|
|
||||||
"score": "Pontuação",
|
|
||||||
"cli_welcome": "Bem-vindo ao Console Redis Tiny RDM",
|
|
||||||
"sub_tab": {
|
|
||||||
"status": "Status",
|
|
||||||
"key_detail": "Detalhes da Chave",
|
|
||||||
"cli": "Console",
|
|
||||||
"slow_log": "Log Lento",
|
|
||||||
"cmd_monitor": "Monitorar Comandos",
|
|
||||||
"pub_message": "Pub/Sub"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ribbon": {
|
|
||||||
"server": "Servidor",
|
|
||||||
"browser": "Navegador de Dados",
|
|
||||||
"log": "Log"
|
|
||||||
},
|
|
||||||
"dialogue": {
|
|
||||||
"close_confirm": "Confirmar o fechamento desta guia e conexão ({name})",
|
|
||||||
"edit_close_confirm": "Por favor, feche as conexões relevantes antes de editar. Deseja continuar?",
|
|
||||||
"opening_connection": "Abrindo Conexão...",
|
|
||||||
"interrupt_connection": "Cancelar",
|
|
||||||
"remove_tip": "{type} \"{name}\" será excluído",
|
|
||||||
"remove_group_tip": "O grupo \"{name}\" e todas as conexões nele serão excluídos",
|
|
||||||
"delete_key_succ": "\"{key}\" foi excluída",
|
|
||||||
"save_value_succ": "Valor Salvo!",
|
|
||||||
"copy_succ": "Valor Copiado!",
|
|
||||||
"rename_binary_key_fail": "Renomear nome de chave binária não é suportado",
|
|
||||||
"handle_succ": "Sucesso!",
|
|
||||||
"reload_succ": "Recarregado!",
|
|
||||||
"field_required": "Este item não deve ficar em branco",
|
|
||||||
"spec_field_required": "\"{key}\" não deve ficar em branco",
|
|
||||||
"illegal_characters": "Inclui caracteres ilegais",
|
|
||||||
"connection": {
|
|
||||||
"new_title": "Nova Conexão",
|
|
||||||
"edit_title": "Editar Conexão",
|
|
||||||
"general": "Geral",
|
|
||||||
"no_group": "Sem Grupo",
|
|
||||||
"group": "Grupo",
|
|
||||||
"conn_name": "Nome",
|
|
||||||
"addr": "Endereço",
|
|
||||||
"usr": "Nome de Usuário",
|
|
||||||
"pwd": "Senha",
|
|
||||||
"name_tip": "Nome da Conexão",
|
|
||||||
"addr_tip": "Host do servidor Redis",
|
|
||||||
"usr_tip": "(Opcional) Nome de usuário para autenticação",
|
|
||||||
"pwd_tip": "(Opcional) Senha de autenticação (Redis > 6.0)",
|
|
||||||
"test": "Testar Conexão",
|
|
||||||
"test_succ": "Conexão bem-sucedida ao servidor Redis",
|
|
||||||
"test_fail": "Falha na Conexão",
|
|
||||||
"advn": {
|
|
||||||
"title": "Avançado",
|
|
||||||
"filter": "Padrão de Filtro de Chave Padrão",
|
|
||||||
"filter_tip": "Padrão que define as chaves carregadas do servidor Redis",
|
|
||||||
"separator": "Separador de Chave",
|
|
||||||
"separator_tip": "Separador para item do caminho da chave",
|
|
||||||
"conn_timeout": "Tempo Limite de Conexão",
|
|
||||||
"exec_timeout": "Tempo Limite de Execução",
|
|
||||||
"dbfilter_type": "Filtro de Banco de Dados",
|
|
||||||
"dbfilter_all": "Mostrar Todos",
|
|
||||||
"dbfilter_show": "Mostrar Selecionados",
|
|
||||||
"dbfilter_hide": "Ocultar Selecionados",
|
|
||||||
"dbfilter_show_title": "Selecione os Bancos de Dados para Mostrar",
|
|
||||||
"dbfilter_hide_title": "Selecione os Bancos de Dados para Ocultar",
|
|
||||||
"dbfilter_input": "Índice do Banco de Dados de Entrada",
|
|
||||||
"dbfilter_input_tip": "Pressione Enter para confirmar",
|
|
||||||
"key_view": "Visualização Padrão de Chave",
|
|
||||||
"key_view_tree": "Visualização em Árvore",
|
|
||||||
"key_view_list": "Visualização em Lista",
|
|
||||||
"load_size": "Tamanho das Chaves por Carga",
|
|
||||||
"mark_color": "Cor de Marcação"
|
|
||||||
},
|
|
||||||
"ssl": {
|
|
||||||
"title": "SSL/TLS",
|
|
||||||
"enable": "Habilitar SSL/TLS",
|
|
||||||
"cert_file": "Chave Pública",
|
|
||||||
"key_file": "Chave Privada",
|
|
||||||
"ca_file": "Autoridade",
|
|
||||||
"cert_file_tip": "Arquivo de Chave Pública no formato PEM (Cert)",
|
|
||||||
"key_file_tip": "Arquivo de Chave Privada no formato PEM (Chave)",
|
|
||||||
"ca_file_tip": "Arquivo de Autoridade de Certificação no formato PEM (CA)"
|
|
||||||
},
|
|
||||||
"ssh": {
|
|
||||||
"title": "Túnel SSH",
|
|
||||||
"enable": "Habilitar Túnel SSH",
|
|
||||||
"login_type": "Tipo de Login",
|
|
||||||
"pkfile": "Arquivo de Chave Privada",
|
|
||||||
"passphrase": "Frase de Senha",
|
|
||||||
"addr_tip": "Host do Servidor SSH",
|
|
||||||
"usr_tip": "Nome de Usuário SSH",
|
|
||||||
"pwd_tip": "Senha SSH",
|
|
||||||
"pkfile_tip": "Caminho do Arquivo de Chave Privada SSH",
|
|
||||||
"passphrase_tip": "(Opcional) Frase de Senha para Chave Privada"
|
|
||||||
},
|
|
||||||
"sentinel": {
|
|
||||||
"title": "Sentinela",
|
|
||||||
"enable": "Atuar como Nó Sentinela",
|
|
||||||
"master": "Nome do Grupo Master",
|
|
||||||
"auto_discover": "Auto Descoberta",
|
|
||||||
"password": "Senha para Nó Master",
|
|
||||||
"username": "Nome de Usuário para Nó Master",
|
|
||||||
"pwd_tip": "(Opcional) Nome de usuário para autenticação no nó master",
|
|
||||||
"usr_tip": "(Opcional) Senha de autenticação no nó master (Redis > 6.0)"
|
|
||||||
},
|
|
||||||
"cluster": {
|
|
||||||
"title": "Cluster",
|
|
||||||
"enable": "Atuar como Nó Cluster",
|
|
||||||
"readonly": "Habilitar comandos somente leitura em nós escravos"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"group": {
|
|
||||||
"name": "Nome do Grupo",
|
|
||||||
"rename": "Renomear Grupo",
|
|
||||||
"new": "Novo Grupo"
|
|
||||||
},
|
|
||||||
"key": {
|
|
||||||
"new": "Nova Chave",
|
|
||||||
"new_name": "Novo Nome da Chave",
|
|
||||||
"persist_key": "Persistir Chave",
|
|
||||||
"server": "Conexão",
|
|
||||||
"db_index": "Índice do Banco de Dados",
|
|
||||||
"key_expression": "Expressão da Chave",
|
|
||||||
"affected_key": "Chaves Afetadas",
|
|
||||||
"show_affected_key": "Mostrar Chaves Afetadas",
|
|
||||||
"confirm_delete_key": "Confirmar Exclusão de {num} Chave(s)",
|
|
||||||
"async_delete": "Executar de Forma Assíncrona",
|
|
||||||
"async_delete_title": "Não esperar pelo resultado da operação",
|
|
||||||
"confirm_flush": "Eu sei o que estou fazendo!",
|
|
||||||
"confirm_flush_db": "Confirmar Limpar Banco de Dados"
|
|
||||||
},
|
|
||||||
"field": {
|
|
||||||
"new": "Adicionar Novo Campo",
|
|
||||||
"new_item": "Adicionar Novo Item",
|
|
||||||
"overwrite_field": "Sobrescrever Campo Existente",
|
|
||||||
"ignore_field": "Ignorar Campo Existente",
|
|
||||||
"insert_type": "Inserir",
|
|
||||||
"append_item": "Anexar",
|
|
||||||
"prepend_item": "Inserir no Início",
|
|
||||||
"enter_key": "Digite a Chave",
|
|
||||||
"enter_value": "Digite o Valor",
|
|
||||||
"enter_field": "Digite o Nome do Campo",
|
|
||||||
"enter_elem": "Digite o Elemento",
|
|
||||||
"enter_member": "Digite o Membro",
|
|
||||||
"enter_score": "Digite a Pontuação",
|
|
||||||
"element": "Elemento",
|
|
||||||
"reload_when_succ": "Recarregar imediatamente após o sucesso"
|
|
||||||
},
|
|
||||||
"filter": {
|
|
||||||
"set_key_filter": "Definir Filtro de Chave",
|
|
||||||
"filter_pattern": "Padrão",
|
|
||||||
"filter_pattern_tip": "prefixo_*: Corresponde a nomes de chaves que começam com \"prefixo_\".\n*_sufixo: Corresponde a nomes de chaves que terminam com \"_sufixo\".\n*padrão*: Corresponde a nomes de chaves que contêm \"padrão\".\nprefixo_??: Corresponde a nomes de chaves que começam com \"prefixo_\" seguido por dois caracteres.\n*abc*: Corresponde a nomes de chaves que contêm \"abc\" em qualquer posição."
|
|
||||||
},
|
|
||||||
"ttl": {
|
|
||||||
"title": "Definir TTL da Chave"
|
|
||||||
},
|
|
||||||
"upgrade": {
|
|
||||||
"title": "Nova Versão Disponível",
|
|
||||||
"new_version_tip": "Uma nova versão ({ver}) está disponível. Baixar agora?",
|
|
||||||
"no_update": "Você está atualizado",
|
|
||||||
"download_now": "Baixar",
|
|
||||||
"later": "Mais Tarde",
|
|
||||||
"skip": "Pular Esta Atualização"
|
|
||||||
},
|
|
||||||
"about": {
|
|
||||||
"source": "Código Fonte",
|
|
||||||
"website": "Site Oficial"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"menu": {
|
|
||||||
"minimise": "Minimizar",
|
|
||||||
"maximise": "Maximizar",
|
|
||||||
"restore": "Restaurar",
|
|
||||||
"close": "Fechar",
|
|
||||||
"preferences": "Preferências",
|
|
||||||
"help": "Ajuda",
|
|
||||||
"check_update": "Verificar Atualizações...",
|
|
||||||
"about": "Sobre"
|
|
||||||
},
|
|
||||||
"log": {
|
|
||||||
"title": "Registro de Inicialização",
|
|
||||||
"filter_server": "Filtrar Servidor",
|
|
||||||
"filter_keyword": "Filtrar Palavra-chave",
|
|
||||||
"clean_log": "Limpar Registro de Inicialização",
|
|
||||||
"confirm_clean_log": "Confirmar limpar registro de inicialização",
|
|
||||||
"exec_time": "Tempo de Execução",
|
|
||||||
"server": "Servidor",
|
|
||||||
"cmd": "Comando",
|
|
||||||
"cost_time": "Custo",
|
|
||||||
"refresh": "Atualizar"
|
|
||||||
},
|
|
||||||
"status": {
|
|
||||||
"uptime": "Tempo de Atividade",
|
|
||||||
"connected_clients": "Clientes Conectados",
|
|
||||||
"total_keys": "Chaves Totais",
|
|
||||||
"memory_used": "Memória Usada",
|
|
||||||
"all_info": "Informações",
|
|
||||||
"refresh": "Atualizar",
|
|
||||||
"auto_refresh": "Atualização Automática"
|
|
||||||
},
|
|
||||||
"slog": {
|
|
||||||
"title": "Registro de Operações Lentas",
|
|
||||||
"limit": "Limite",
|
|
||||||
"filter": "Filtrar",
|
|
||||||
"exec_time": "Tempo",
|
|
||||||
"client": "Cliente",
|
|
||||||
"cmd": "Comando",
|
|
||||||
"cost_time": "Custo",
|
|
||||||
"refresh": "Atualizar Agora",
|
|
||||||
"auto_refresh": "Atualização Automática"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -90,8 +90,6 @@
|
||||||
"new_key": "添加新键",
|
"new_key": "添加新键",
|
||||||
"load_more": "加载更多键",
|
"load_more": "加载更多键",
|
||||||
"load_all": "加载剩余所有键",
|
"load_all": "加载剩余所有键",
|
||||||
"load_more_entries": "加载更多",
|
|
||||||
"load_all_entries": "加载全部",
|
|
||||||
"more_action": "更多操作",
|
"more_action": "更多操作",
|
||||||
"nonexist_tab_content": "所选键不存在或未选中任何键,请尝试刷新重试",
|
"nonexist_tab_content": "所选键不存在或未选中任何键,请尝试刷新重试",
|
||||||
"empty_server_content": "可以从左边选择并打开连接",
|
"empty_server_content": "可以从左边选择并打开连接",
|
||||||
|
|
|
@ -5,7 +5,6 @@ import {
|
||||||
get,
|
get,
|
||||||
isEmpty,
|
isEmpty,
|
||||||
join,
|
join,
|
||||||
last,
|
|
||||||
remove,
|
remove,
|
||||||
set,
|
set,
|
||||||
size,
|
size,
|
||||||
|
@ -25,8 +24,7 @@ import {
|
||||||
DeleteKey,
|
DeleteKey,
|
||||||
FlushDB,
|
FlushDB,
|
||||||
GetCmdHistory,
|
GetCmdHistory,
|
||||||
GetKeyDetail,
|
GetKeyValue,
|
||||||
GetKeySummary,
|
|
||||||
GetSlowLogs,
|
GetSlowLogs,
|
||||||
LoadAllKeys,
|
LoadAllKeys,
|
||||||
LoadNextKeys,
|
LoadNextKeys,
|
||||||
|
@ -60,7 +58,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
* @property {number} type
|
* @property {number} type
|
||||||
* @property {number} [db] - database index, type == ConnectionType.RedisDB only
|
* @property {number} [db] - database index, type == ConnectionType.RedisDB only
|
||||||
* @property {string} [redisKey] - redis key, type == ConnectionType.RedisKey || type == ConnectionType.RedisValue only
|
* @property {string} [redisKey] - redis key, type == ConnectionType.RedisKey || type == ConnectionType.RedisValue only
|
||||||
* @property {number[]} [redisKeyCode] - redis key char code array, optional for redis key which contains binary data
|
* @property {string} [redisKeyCode] - redis key char code array, optional for redis key which contains binary data
|
||||||
* @property {number} [keys] - children key count
|
* @property {number} [keys] - children key count
|
||||||
* @property {number} [maxKeys] - max key count for database
|
* @property {number} [maxKeys] - max key count for database
|
||||||
* @property {boolean} [isLeaf]
|
* @property {boolean} [isLeaf]
|
||||||
|
@ -139,7 +137,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
* get database by server name and index
|
* get database by server name and index
|
||||||
* @param {string} connName
|
* @param {string} connName
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @return {DatabaseItem|null}
|
* @return {{}|null}
|
||||||
*/
|
*/
|
||||||
getDatabase(connName, db) {
|
getDatabase(connName, db) {
|
||||||
const dbs = this.databases[connName]
|
const dbs = this.databases[connName]
|
||||||
|
@ -152,20 +150,6 @@ const useBrowserStore = defineStore('browser', {
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* get full loaded status of database
|
|
||||||
* @param connName
|
|
||||||
* @param db
|
|
||||||
* @return {boolean}
|
|
||||||
*/
|
|
||||||
isFullLoaded(connName, db) {
|
|
||||||
const selDB = this.getDatabase(connName, db)
|
|
||||||
if (selDB != null) {
|
|
||||||
return selDB.fullLoaded === true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* switch key view
|
* switch key view
|
||||||
* @param {string} connName
|
* @param {string} connName
|
||||||
|
@ -360,23 +344,20 @@ const useBrowserStore = defineStore('browser', {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* load key summary info
|
* load redis key
|
||||||
* @param {string} server
|
* @param {string} server
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string|number[]} [key] null or blank indicate that update tab to display normal content (blank content or server status)
|
* @param {string|number[]} [key] when key is null or blank, update tab to display normal content (blank content or server status)
|
||||||
* @return {Promise<void>}
|
* @param {string} [viewType]
|
||||||
|
* @param {string} [decodeType]
|
||||||
*/
|
*/
|
||||||
async loadKeySummary({ server, db, key }) {
|
async loadKeyValue(server, db, key, viewType, decodeType) {
|
||||||
try {
|
try {
|
||||||
const tab = useTabStore()
|
const tab = useTabStore()
|
||||||
if (!isEmpty(key)) {
|
if (!isEmpty(key)) {
|
||||||
const { data, success, msg } = await GetKeySummary({
|
const { data, success, msg } = await GetKeyValue(server, db, key, viewType, decodeType)
|
||||||
server,
|
|
||||||
db,
|
|
||||||
key,
|
|
||||||
})
|
|
||||||
if (success) {
|
if (success) {
|
||||||
const { type, ttl, size, length } = data
|
const { type, ttl, value, size, length, viewAs, decode } = data
|
||||||
const k = decodeRedisKey(key)
|
const k = decodeRedisKey(key)
|
||||||
const binaryKey = k !== key
|
const binaryKey = k !== key
|
||||||
tab.upsertTab({
|
tab.upsertTab({
|
||||||
|
@ -387,13 +368,16 @@ const useBrowserStore = defineStore('browser', {
|
||||||
ttl,
|
ttl,
|
||||||
keyCode: binaryKey ? key : undefined,
|
keyCode: binaryKey ? key : undefined,
|
||||||
key: k,
|
key: k,
|
||||||
|
value,
|
||||||
size,
|
size,
|
||||||
length,
|
length,
|
||||||
|
viewAs,
|
||||||
|
decode,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
if (!isEmpty(msg)) {
|
if (!isEmpty(msg)) {
|
||||||
$message.error('load key summary fail: ' + msg)
|
$message.error('load key fail: ' + msg)
|
||||||
}
|
}
|
||||||
// its danger to delete "non-exists" key, just remove from tree view
|
// its danger to delete "non-exists" key, just remove from tree view
|
||||||
await this.deleteKey(server, db, key, true)
|
await this.deleteKey(server, db, key, true)
|
||||||
|
@ -413,83 +397,18 @@ const useBrowserStore = defineStore('browser', {
|
||||||
size: 0,
|
size: 0,
|
||||||
length: 0,
|
length: 0,
|
||||||
})
|
})
|
||||||
} catch (e) {
|
|
||||||
$message.error('')
|
|
||||||
} finally {
|
} finally {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* reload key
|
|
||||||
* @param server
|
|
||||||
* @param db
|
|
||||||
* @param key
|
|
||||||
* @return {Promise<void>}
|
|
||||||
*/
|
|
||||||
async reloadKey({ server, db, key }) {
|
|
||||||
const tab = useTabStore()
|
|
||||||
try {
|
|
||||||
tab.updateLoading({ server, db, loading: true })
|
|
||||||
await this.loadKeySummary({ server, db, key })
|
|
||||||
await this.loadKeyDetail({ server, db, key, reset: true })
|
|
||||||
} finally {
|
|
||||||
tab.updateLoading({ server, db, loading: false })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* load key content
|
|
||||||
* @param {string} server
|
|
||||||
* @param {number} db
|
|
||||||
* @param {string|number[]} key
|
|
||||||
* @param {string} [viewType]
|
|
||||||
* @param {string} [decodeType]
|
|
||||||
* @param {string} [matchPattern]
|
|
||||||
* @param {boolean} [reset]
|
|
||||||
* @param {boolean} [full]
|
|
||||||
* @return {Promise<void>}
|
|
||||||
*/
|
|
||||||
async loadKeyDetail({ server, db, key, viewType, decodeType, matchPattern, reset, full }) {
|
|
||||||
const tab = useTabStore()
|
|
||||||
try {
|
|
||||||
tab.updateLoading({ server, db, loading: true })
|
|
||||||
const { data, success, msg } = await GetKeyDetail({
|
|
||||||
server,
|
|
||||||
db,
|
|
||||||
key,
|
|
||||||
viewAs: viewType,
|
|
||||||
decodeType,
|
|
||||||
matchPattern,
|
|
||||||
full: full === true,
|
|
||||||
reset,
|
|
||||||
lite: true,
|
|
||||||
})
|
|
||||||
if (success) {
|
|
||||||
const { value, viewAs, decodeType: decode, end } = data
|
|
||||||
tab.updateValue({
|
|
||||||
server,
|
|
||||||
db,
|
|
||||||
key: decodeRedisKey(key),
|
|
||||||
value,
|
|
||||||
viewAs,
|
|
||||||
decode,
|
|
||||||
reset: reset || full === true,
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
tab.updateLoading({ server, db, loading: false })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* scan keys with prefix
|
* scan keys with prefix
|
||||||
* @param {string} connName
|
* @param {string} connName
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string} match
|
* @param {string} match
|
||||||
* @param {string} [matchType]
|
* @param {string} matchType
|
||||||
* @param {boolean} [full]
|
* @param {boolean} [full]
|
||||||
* @returns {Promise<{keys: string[], maxKeys: number, end: boolean}>}
|
* @returns {Promise<{keys: string[], end: boolean}>}
|
||||||
*/
|
*/
|
||||||
async scanKeys(connName, db, match, matchType, full) {
|
async scanKeys(connName, db, match, matchType, full) {
|
||||||
let resp
|
let resp
|
||||||
|
@ -502,8 +421,8 @@ const useBrowserStore = defineStore('browser', {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
throw new Error(msg)
|
throw new Error(msg)
|
||||||
}
|
}
|
||||||
const { keys = [], maxKeys, end } = data
|
const { keys = [], end } = data
|
||||||
return { keys, end, maxKeys, success }
|
return { keys, end, success }
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -513,7 +432,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
* @param {string|null} prefix
|
* @param {string|null} prefix
|
||||||
* @param {string|null} matchType
|
* @param {string|null} matchType
|
||||||
* @param {boolean} [all]
|
* @param {boolean} [all]
|
||||||
* @return {Promise<{keys: Array<string|number[]>, maxKeys: number, end: boolean}>}
|
* @return {Promise<{keys: Array<string|number[]>, end: boolean}>}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
async _loadKeys(connName, db, prefix, matchType, all) {
|
async _loadKeys(connName, db, prefix, matchType, all) {
|
||||||
|
@ -537,8 +456,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
*/
|
*/
|
||||||
async loadMoreKeys(connName, db) {
|
async loadMoreKeys(connName, db) {
|
||||||
const { match, type: keyType } = this.getKeyFilter(connName, db)
|
const { match, type: keyType } = this.getKeyFilter(connName, db)
|
||||||
const { keys, maxKeys, end } = await this._loadKeys(connName, db, match, keyType, false)
|
const { keys, end } = await this._loadKeys(connName, db, match, keyType, false)
|
||||||
this._setDBMaxKeys(connName, db, maxKeys)
|
|
||||||
// remove current keys below prefix
|
// remove current keys below prefix
|
||||||
this._addKeyNodes(connName, db, keys)
|
this._addKeyNodes(connName, db, keys)
|
||||||
this._tidyNode(connName, db, '')
|
this._tidyNode(connName, db, '')
|
||||||
|
@ -553,44 +471,11 @@ const useBrowserStore = defineStore('browser', {
|
||||||
*/
|
*/
|
||||||
async loadAllKeys(connName, db) {
|
async loadAllKeys(connName, db) {
|
||||||
const { match, type: keyType } = this.getKeyFilter(connName, db)
|
const { match, type: keyType } = this.getKeyFilter(connName, db)
|
||||||
const { keys, maxKeys } = await this._loadKeys(connName, db, match, keyType, true)
|
const { keys } = await this._loadKeys(connName, db, match, keyType, true)
|
||||||
this._setDBMaxKeys(connName, db, maxKeys)
|
|
||||||
this._addKeyNodes(connName, db, keys)
|
this._addKeyNodes(connName, db, keys)
|
||||||
this._tidyNode(connName, db, '')
|
this._tidyNode(connName, db, '')
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* reload keys under layer
|
|
||||||
* @param {string} connName
|
|
||||||
* @param {number} db
|
|
||||||
* @param {string} prefix
|
|
||||||
* @return {Promise<void>}
|
|
||||||
*/
|
|
||||||
async reloadLayer(connName, db, prefix) {
|
|
||||||
if (isEmpty(prefix)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let match = prefix
|
|
||||||
const separator = this._getSeparator(connName)
|
|
||||||
if (!endsWith(match, separator)) {
|
|
||||||
match += separator + '*'
|
|
||||||
} else {
|
|
||||||
match += '*'
|
|
||||||
}
|
|
||||||
// FIXME: ignore original match pattern due to redis not support combination matching
|
|
||||||
const { match: originMatch, type: keyType } = this.getKeyFilter(connName, db)
|
|
||||||
const { keys, maxKeys, success } = await this._loadKeys(connName, db, match, keyType, true)
|
|
||||||
if (!success) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this._setDBMaxKeys(connName, db, maxKeys)
|
|
||||||
// remove current keys below prefix
|
|
||||||
this._deleteKeyNode(connName, db, prefix, true)
|
|
||||||
this._addKeyNodes(connName, db, keys)
|
|
||||||
this._tidyNode(connName, db, prefix)
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get custom separator of connection
|
* get custom separator of connection
|
||||||
* @param server
|
* @param server
|
||||||
|
@ -864,16 +749,13 @@ const useBrowserStore = defineStore('browser', {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update max key by increase/decrease value
|
* update max key by value
|
||||||
* @param {string} connName
|
* @param {string} connName
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {number} [updateValue]
|
* @param {number} updateValue
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_updateDBMaxKeys(connName, db, updateValue) {
|
_updateDBMaxKeys(connName, db, updateValue) {
|
||||||
if (updateValue === undefined) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const database = this.getDatabase(connName, db)
|
const database = this.getDatabase(connName, db)
|
||||||
if (database != null) {
|
if (database != null) {
|
||||||
const maxKeys = get(database, 'maxKeys', 0)
|
const maxKeys = get(database, 'maxKeys', 0)
|
||||||
|
@ -882,16 +764,15 @@ const useBrowserStore = defineStore('browser', {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set db max keys value
|
* set db max keys to 0
|
||||||
* @param {string} connName
|
* @param connName
|
||||||
* @param {number} db
|
* @param db
|
||||||
* @param {number} maxKeys
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_setDBMaxKeys(connName, db, maxKeys) {
|
_emptyDBMaxKeys(connName, db) {
|
||||||
const database = this.getDatabase(connName, db)
|
const database = this.getDatabase(connName, db)
|
||||||
if (database != null) {
|
if (database != null) {
|
||||||
set(database, 'maxKeys', maxKeys)
|
set(database, 'maxKeys', 0)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -976,14 +857,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
try {
|
try {
|
||||||
const { data, success, msg } = await SetHashValue(connName, db, key, field, newField || '', value || '')
|
const { data, success, msg } = await SetHashValue(connName, db, key, field, newField || '', value || '')
|
||||||
if (success) {
|
if (success) {
|
||||||
const { updated = {}, removed = [], replaced = {} } = data
|
const { updated = {} } = data
|
||||||
const tab = useTabStore()
|
|
||||||
if (!isEmpty(removed)) {
|
|
||||||
tab.removeValueEntries({ server: connName, db, key, type: 'hash', entries: removed })
|
|
||||||
}
|
|
||||||
if (!isEmpty(updated)) {
|
|
||||||
tab.upsertValueEntries({ server: connName, db, key, type: 'hash', entries: updated })
|
|
||||||
}
|
|
||||||
return { success, updated }
|
return { success, updated }
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
|
@ -1007,8 +881,6 @@ const useBrowserStore = defineStore('browser', {
|
||||||
const { data, success, msg } = await AddHashField(connName, db, key, action, fieldItems)
|
const { data, success, msg } = await AddHashField(connName, db, key, action, fieldItems)
|
||||||
if (success) {
|
if (success) {
|
||||||
const { updated = {} } = data
|
const { updated = {} } = data
|
||||||
const tab = useTabStore()
|
|
||||||
tab.upsertValueEntries({ server: connName, db, key, type: 'hash', entries: updated })
|
|
||||||
return { success, updated }
|
return { success, updated }
|
||||||
} else {
|
} else {
|
||||||
return { success: false, msg }
|
return { success: false, msg }
|
||||||
|
@ -1031,10 +903,6 @@ const useBrowserStore = defineStore('browser', {
|
||||||
const { data, success, msg } = await SetHashValue(connName, db, key, field, '', '')
|
const { data, success, msg } = await SetHashValue(connName, db, key, field, '', '')
|
||||||
if (success) {
|
if (success) {
|
||||||
const { removed = [] } = data
|
const { removed = [] } = data
|
||||||
if (!isEmpty(removed)) {
|
|
||||||
const tab = useTabStore()
|
|
||||||
tab.removeValueEntries({ server: connName, db, key, type: 'hash', entries: removed })
|
|
||||||
}
|
|
||||||
return { success, removed }
|
return { success, removed }
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
|
@ -1067,24 +935,13 @@ const useBrowserStore = defineStore('browser', {
|
||||||
* @param db
|
* @param db
|
||||||
* @param key
|
* @param key
|
||||||
* @param values
|
* @param values
|
||||||
* @returns {Promise<{[msg]: string, success: boolean, [item]: []}>}
|
* @returns {Promise<[msg]: string, success: boolean, [item]: []>}
|
||||||
*/
|
*/
|
||||||
async prependListItem(connName, db, key, values) {
|
async prependListItem(connName, db, key, values) {
|
||||||
try {
|
try {
|
||||||
const { data, success, msg } = await AddListItem(connName, db, key, 0, values)
|
const { data, success, msg } = await AddListItem(connName, db, key, 0, values)
|
||||||
if (success) {
|
if (success) {
|
||||||
const { left = [] } = data
|
const { left = [] } = data
|
||||||
if (!isEmpty(left)) {
|
|
||||||
const tab = useTabStore()
|
|
||||||
tab.upsertValueEntries({
|
|
||||||
server: connName,
|
|
||||||
db,
|
|
||||||
key,
|
|
||||||
type: 'list',
|
|
||||||
entries: right,
|
|
||||||
prepend: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return { success, item: left }
|
return { success, item: left }
|
||||||
} else {
|
} else {
|
||||||
return { success: false, msg }
|
return { success: false, msg }
|
||||||
|
@ -1100,24 +957,13 @@ const useBrowserStore = defineStore('browser', {
|
||||||
* @param db
|
* @param db
|
||||||
* @param key
|
* @param key
|
||||||
* @param values
|
* @param values
|
||||||
* @returns {Promise<{[msg]: string, success: boolean, [item]: any[]}>}
|
* @returns {Promise<[msg]: string, success: boolean, [item]: any[]>}
|
||||||
*/
|
*/
|
||||||
async appendListItem(connName, db, key, values) {
|
async appendListItem(connName, db, key, values) {
|
||||||
try {
|
try {
|
||||||
const { data, success, msg } = await AddListItem(connName, db, key, 1, values)
|
const { data, success, msg } = await AddListItem(connName, db, key, 1, values)
|
||||||
if (success) {
|
if (success) {
|
||||||
const { right = [] } = data
|
const { right = [] } = data
|
||||||
if (!isEmpty(right)) {
|
|
||||||
const tab = useTabStore()
|
|
||||||
tab.upsertValueEntries({
|
|
||||||
server: connName,
|
|
||||||
db,
|
|
||||||
key,
|
|
||||||
type: 'list',
|
|
||||||
entries: right,
|
|
||||||
prepend: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return { success, item: right }
|
return { success, item: right }
|
||||||
} else {
|
} else {
|
||||||
return { success: false, msg }
|
return { success: false, msg }
|
||||||
|
@ -1141,16 +987,6 @@ const useBrowserStore = defineStore('browser', {
|
||||||
const { data, success, msg } = await SetListItem(connName, db, key, index, value)
|
const { data, success, msg } = await SetListItem(connName, db, key, index, value)
|
||||||
if (success) {
|
if (success) {
|
||||||
const { updated = {} } = data
|
const { updated = {} } = data
|
||||||
if (!isEmpty(updated)) {
|
|
||||||
const tab = useTabStore()
|
|
||||||
tab.upsertValueEntries({
|
|
||||||
server: connName,
|
|
||||||
db,
|
|
||||||
key,
|
|
||||||
type: 'list',
|
|
||||||
entries: updated,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return { success, updated }
|
return { success, updated }
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
|
@ -1173,16 +1009,6 @@ const useBrowserStore = defineStore('browser', {
|
||||||
const { data, success, msg } = await SetListItem(connName, db, key, index, '')
|
const { data, success, msg } = await SetListItem(connName, db, key, index, '')
|
||||||
if (success) {
|
if (success) {
|
||||||
const { removed = [] } = data
|
const { removed = [] } = data
|
||||||
if (!isEmpty(removed)) {
|
|
||||||
const tab = useTabStore()
|
|
||||||
tab.removeValueEntries({
|
|
||||||
server: connName,
|
|
||||||
db,
|
|
||||||
key,
|
|
||||||
type: 'list',
|
|
||||||
entries: removed,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return { success, removed }
|
return { success, removed }
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
|
@ -1197,18 +1023,13 @@ const useBrowserStore = defineStore('browser', {
|
||||||
* @param {string} connName
|
* @param {string} connName
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string|number} key
|
* @param {string|number} key
|
||||||
* @param {string|string[]} value
|
* @param {string} value
|
||||||
* @returns {Promise<{[msg]: string, success: boolean}>}
|
* @returns {Promise<{[msg]: string, success: boolean}>}
|
||||||
*/
|
*/
|
||||||
async addSetItem(connName, db, key, value) {
|
async addSetItem(connName, db, key, value) {
|
||||||
try {
|
try {
|
||||||
if (!value instanceof Array) {
|
const { success, msg } = await SetSetItem(connName, db, key, false, [value])
|
||||||
value = [value]
|
|
||||||
}
|
|
||||||
const { data, success, msg } = await SetSetItem(connName, db, key, false, value)
|
|
||||||
if (success) {
|
if (success) {
|
||||||
const tab = useTabStore()
|
|
||||||
tab.upsertValueEntries({ server: connName, db, key, type: 'set', entries: value })
|
|
||||||
return { success }
|
return { success }
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
|
@ -1231,8 +1052,6 @@ const useBrowserStore = defineStore('browser', {
|
||||||
try {
|
try {
|
||||||
const { success, msg } = await UpdateSetItem(connName, db, key, value, newValue)
|
const { success, msg } = await UpdateSetItem(connName, db, key, value, newValue)
|
||||||
if (success) {
|
if (success) {
|
||||||
const tab = useTabStore()
|
|
||||||
tab.upsertValueEntries({ server: connName, db, key, type: 'set', entries: { [value]: newValue } })
|
|
||||||
return { success: true }
|
return { success: true }
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
|
@ -1254,8 +1073,6 @@ const useBrowserStore = defineStore('browser', {
|
||||||
try {
|
try {
|
||||||
const { success, msg } = await SetSetItem(connName, db, key, true, [value])
|
const { success, msg } = await SetSetItem(connName, db, key, true, [value])
|
||||||
if (success) {
|
if (success) {
|
||||||
const tab = useTabStore()
|
|
||||||
tab.removeValueEntries({ server: connName, db, key, type: 'set', entries: [value] })
|
|
||||||
return { success }
|
return { success }
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
|
@ -1277,8 +1094,6 @@ const useBrowserStore = defineStore('browser', {
|
||||||
async addZSetItem(connName, db, key, action, vs) {
|
async addZSetItem(connName, db, key, action, vs) {
|
||||||
try {
|
try {
|
||||||
const { success, msg } = await AddZSetValue(connName, db, key, action, vs)
|
const { success, msg } = await AddZSetValue(connName, db, key, action, vs)
|
||||||
const tab = useTabStore()
|
|
||||||
tab.upsertValueEntries({ server: connName, db, key, type: 'zset', entries: vs })
|
|
||||||
if (success) {
|
if (success) {
|
||||||
return { success }
|
return { success }
|
||||||
} else {
|
} else {
|
||||||
|
@ -1304,13 +1119,6 @@ const useBrowserStore = defineStore('browser', {
|
||||||
const { data, success, msg } = await UpdateZSetValue(connName, db, key, value, newValue, score)
|
const { data, success, msg } = await UpdateZSetValue(connName, db, key, value, newValue, score)
|
||||||
if (success) {
|
if (success) {
|
||||||
const { updated, removed } = data
|
const { updated, removed } = data
|
||||||
const tab = useTabStore()
|
|
||||||
if (!isEmpty(updated)) {
|
|
||||||
tab.upsertValueEntries({ server: connName, db, key, type: 'zset', entries: updated })
|
|
||||||
}
|
|
||||||
if (!isEmpty(removed)) {
|
|
||||||
tab.removeValueEntries({ server: connName, db, key, type: 'zset', entries: removed })
|
|
||||||
}
|
|
||||||
return { success, updated, removed }
|
return { success, updated, removed }
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
|
@ -1333,11 +1141,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
const { data, success, msg } = await UpdateZSetValue(connName, db, key, value, '', 0)
|
const { data, success, msg } = await UpdateZSetValue(connName, db, key, value, '', 0)
|
||||||
if (success) {
|
if (success) {
|
||||||
const { removed } = data
|
const { removed } = data
|
||||||
if (!isEmpty(removed)) {
|
return { success, removed }
|
||||||
const tab = useTabStore()
|
|
||||||
tab.removeValueEntries({ server: connName, db, key, type: 'zset', entries: removed })
|
|
||||||
}
|
|
||||||
return { success }
|
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
}
|
}
|
||||||
|
@ -1353,22 +1157,14 @@ const useBrowserStore = defineStore('browser', {
|
||||||
* @param {string|number[]} key
|
* @param {string|number[]} key
|
||||||
* @param {string} id
|
* @param {string} id
|
||||||
* @param {string[]} values field1, value1, filed2, value2...
|
* @param {string[]} values field1, value1, filed2, value2...
|
||||||
* @returns {Promise<{[msg]: string, success: boolean}>}
|
* @returns {Promise<{[msg]: string, success: boolean, [updated]: {}}>}
|
||||||
*/
|
*/
|
||||||
async addStreamValue(connName, db, key, id, values) {
|
async addStreamValue(connName, db, key, id, values) {
|
||||||
try {
|
try {
|
||||||
const { data = {}, success, msg } = await AddStreamValue(connName, db, key, id, values)
|
const { data = {}, success, msg } = await AddStreamValue(connName, db, key, id, values)
|
||||||
if (success) {
|
if (success) {
|
||||||
const { updateID } = data
|
const { updated = {} } = data
|
||||||
const tab = useTabStore()
|
return { success, updated }
|
||||||
tab.upsertValueEntries({
|
|
||||||
server: connName,
|
|
||||||
db,
|
|
||||||
key,
|
|
||||||
type: 'stream',
|
|
||||||
entries: [{ id: updateID, value: values }],
|
|
||||||
})
|
|
||||||
return { success }
|
|
||||||
} else {
|
} else {
|
||||||
return { success: false, msg }
|
return { success: false, msg }
|
||||||
}
|
}
|
||||||
|
@ -1383,7 +1179,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string|number[]} key
|
* @param {string|number[]} key
|
||||||
* @param {string[]|string} ids
|
* @param {string[]|string} ids
|
||||||
* @returns {Promise<{[msg]: {}, success: boolean}>}
|
* @returns {Promise<{[msg]: {}, success: boolean, [removed]: string[]}>}
|
||||||
*/
|
*/
|
||||||
async removeStreamValues(connName, db, key, ids) {
|
async removeStreamValues(connName, db, key, ids) {
|
||||||
if (typeof ids === 'string') {
|
if (typeof ids === 'string') {
|
||||||
|
@ -1392,9 +1188,8 @@ const useBrowserStore = defineStore('browser', {
|
||||||
try {
|
try {
|
||||||
const { data = {}, success, msg } = await RemoveStreamValues(connName, db, key, ids)
|
const { data = {}, success, msg } = await RemoveStreamValues(connName, db, key, ids)
|
||||||
if (success) {
|
if (success) {
|
||||||
const tab = useTabStore()
|
const { removed = [] } = data
|
||||||
tab.removeValueEntries({ server: connName, db, key, type: 'stream', entries: ids })
|
return { success, removed }
|
||||||
return { success }
|
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
}
|
}
|
||||||
|
@ -1420,34 +1215,6 @@ const useBrowserStore = defineStore('browser', {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {string} connName
|
|
||||||
* @param {number} db
|
|
||||||
* @param {string} key
|
|
||||||
* @param {string} newKey
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_renameKeyNode(connName, db, key, newKey) {
|
|
||||||
const nodeMap = this._getNodeMap(connName, db)
|
|
||||||
const nodeKey = `${ConnectionType.RedisValue}/${key}`
|
|
||||||
const newNodeKey = `${ConnectionType.RedisValue}/${newKey}`
|
|
||||||
const node = nodeMap.get(nodeKey)
|
|
||||||
if (node != null) {
|
|
||||||
// replace node map item
|
|
||||||
const separator = this._getSeparator(connName)
|
|
||||||
node.label = last(split(newKey, separator))
|
|
||||||
node.key = `${connName}/db${db}#${newNodeKey}`
|
|
||||||
node.redisKey = newKey
|
|
||||||
nodeMap[newNodeKey] = node
|
|
||||||
nodeMap.delete(nodeKey)
|
|
||||||
// replace key set item
|
|
||||||
const keySet = this._getKeySet(connName, db)
|
|
||||||
keySet.delete(key)
|
|
||||||
keySet.add(newKey)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} connName
|
* @param {string} connName
|
||||||
|
@ -1640,7 +1407,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
if (success === true) {
|
if (success === true) {
|
||||||
// update tree view data
|
// update tree view data
|
||||||
this._deleteKeyNode(connName, db)
|
this._deleteKeyNode(connName, db)
|
||||||
this._setDBMaxKeys(connName, db, 0)
|
this._emptyDBMaxKeys(connName, db)
|
||||||
// set tab content empty
|
// set tab content empty
|
||||||
const tab = useTabStore()
|
const tab = useTabStore()
|
||||||
tab.emptyTab(connName)
|
tab.emptyTab(connName)
|
||||||
|
@ -1657,14 +1424,15 @@ const useBrowserStore = defineStore('browser', {
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
* @param {string} newKey
|
* @param {string} newKey
|
||||||
* @returns {Promise<{[msg]: string, success: boolean, [nodeKey]: string}>}
|
* @returns {Promise<{[msg]: string, success: boolean}>}
|
||||||
*/
|
*/
|
||||||
async renameKey(connName, db, key, newKey) {
|
async renameKey(connName, db, key, newKey) {
|
||||||
const { success = false, msg } = await RenameKey(connName, db, key, newKey)
|
const { success = false, msg } = await RenameKey(connName, db, key, newKey)
|
||||||
if (success) {
|
if (success) {
|
||||||
// delete old key and add new key struct
|
// delete old key and add new key struct
|
||||||
this._renameKeyNode(connName, db, key, newKey)
|
this._deleteKeyNode(connName, db, key)
|
||||||
return { success: true, nodeKey: `${connName}/db${db}#${ConnectionType.RedisValue}/${newKey}` }
|
this._addKeyNodes(connName, db, [newKey])
|
||||||
|
return { success: true }
|
||||||
} else {
|
} else {
|
||||||
return { success: false, msg }
|
return { success: false, msg }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { assign, find, findIndex, get, indexOf, isEmpty, pullAt, remove, set, size } from 'lodash'
|
import { find, findIndex, get, isEmpty, set, size } from 'lodash'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
const useTabStore = defineStore('tab', {
|
const useTabStore = defineStore('tab', {
|
||||||
|
@ -11,18 +11,12 @@ const useTabStore = defineStore('tab', {
|
||||||
* @property {string} [icon] tab icon
|
* @property {string} [icon] tab icon
|
||||||
* @property {string[]} selectedKeys
|
* @property {string[]} selectedKeys
|
||||||
* @property {string} [type] key type
|
* @property {string} [type] key type
|
||||||
* @property {*} [value] key value
|
* @property {Object|Array} [value] key value
|
||||||
* @property {string} [server] server name
|
* @property {string} [server] server name
|
||||||
* @property {int} [db] database index
|
* @property {int} [db] database index
|
||||||
* @property {string} [key] current key name
|
* @property {string} [key] current key name
|
||||||
* @property {number[]|null|undefined} [keyCode] current key name as char array
|
* @property {number[]|null|undefined} [keyCode] current key name as char array
|
||||||
* @param {number} [size] memory usage
|
|
||||||
* @param {number} [length] length of content or entries
|
|
||||||
* @property {int} [ttl] ttl of current key
|
* @property {int} [ttl] ttl of current key
|
||||||
* @param {string} [viewAs]
|
|
||||||
* @param {string} [decode]
|
|
||||||
* @param {boolean} [end]
|
|
||||||
* @param {boolean} [loading]
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,10 +82,6 @@ const useTabStore = defineStore('tab', {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
openBlank(server) {
|
|
||||||
this.upsertTab({ server, db: 0 })
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update or insert a new tab if not exists with the same name
|
* update or insert a new tab if not exists with the same name
|
||||||
* @param {string} subTab
|
* @param {string} subTab
|
||||||
|
@ -104,8 +94,10 @@ const useTabStore = defineStore('tab', {
|
||||||
* @param {number} [size]
|
* @param {number} [size]
|
||||||
* @param {number} [length]
|
* @param {number} [length]
|
||||||
* @param {*} [value]
|
* @param {*} [value]
|
||||||
|
* @param {string} [viewAs]
|
||||||
|
* @param {string} [decode]
|
||||||
*/
|
*/
|
||||||
upsertTab({ subTab, server, db, type, ttl, key, keyCode, size, length }) {
|
upsertTab({ subTab, server, db, type, ttl, key, keyCode, size, length, value, viewAs, decode }) {
|
||||||
let tabIndex = findIndex(this.tabList, { name: server })
|
let tabIndex = findIndex(this.tabList, { name: server })
|
||||||
if (tabIndex === -1) {
|
if (tabIndex === -1) {
|
||||||
this.tabList.push({
|
this.tabList.push({
|
||||||
|
@ -120,7 +112,9 @@ const useTabStore = defineStore('tab', {
|
||||||
keyCode,
|
keyCode,
|
||||||
size,
|
size,
|
||||||
length,
|
length,
|
||||||
value: undefined,
|
value,
|
||||||
|
viewAs,
|
||||||
|
decode,
|
||||||
})
|
})
|
||||||
tabIndex = this.tabList.length - 1
|
tabIndex = this.tabList.length - 1
|
||||||
} else {
|
} else {
|
||||||
|
@ -137,239 +131,16 @@ const useTabStore = defineStore('tab', {
|
||||||
tab.keyCode = keyCode
|
tab.keyCode = keyCode
|
||||||
tab.size = size
|
tab.size = size
|
||||||
tab.length = length
|
tab.length = length
|
||||||
tab.value = undefined
|
tab.value = value
|
||||||
|
tab.viewAs = viewAs
|
||||||
|
tab.decode = decode
|
||||||
}
|
}
|
||||||
this._setActivatedIndex(tabIndex, true, subTab)
|
this._setActivatedIndex(tabIndex, true, subTab)
|
||||||
// this.activatedTab = tab.name
|
// this.activatedTab = tab.name
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* keep update value in tab
|
* update ttl by tag
|
||||||
* @param {string} server
|
|
||||||
* @param {number} db
|
|
||||||
* @param {string} key
|
|
||||||
* @param {*} value
|
|
||||||
* @param {string} [viewAs]
|
|
||||||
* @param {string] [decode]
|
|
||||||
* @param {boolean} reset
|
|
||||||
* @param {boolean} [end] keep end status if not set
|
|
||||||
*/
|
|
||||||
updateValue({ server, db, key, value, viewAs, decode, reset, end }) {
|
|
||||||
const tab = find(this.tabList, { name: server, db, key })
|
|
||||||
if (tab == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tab.viewAs = viewAs || tab.viewAs
|
|
||||||
tab.decode = decode || tab.decode
|
|
||||||
if (typeof end === 'boolean') {
|
|
||||||
tab.end = end
|
|
||||||
}
|
|
||||||
if (!reset && typeof value === 'object') {
|
|
||||||
if (value instanceof Array) {
|
|
||||||
tab.value = tab.value || []
|
|
||||||
tab.value.push(...value)
|
|
||||||
} else {
|
|
||||||
tab.value = assign(value, tab.value || {})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tab.value = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* update or insert value entries
|
|
||||||
* @param {string} server
|
|
||||||
* @param {number} db
|
|
||||||
* @param {string} key
|
|
||||||
* @param {string} type
|
|
||||||
* @param {string[]|Object.<string, number>|Object.<number, string>} entries
|
|
||||||
* @param {boolean} [prepend] for list only
|
|
||||||
* @param {boolean} [reset]
|
|
||||||
* @param {boolean} [nocheck] ignore conflict checking for hash/set/zset
|
|
||||||
*/
|
|
||||||
upsertValueEntries({ server, db, key, type, entries, prepend, reset, nocheck }) {
|
|
||||||
const tab = find(this.tabList, { name: server, db, key })
|
|
||||||
if (tab == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type.toLowerCase()) {
|
|
||||||
case 'list': // string[] | Object.<number, string>
|
|
||||||
if (entries instanceof Array) {
|
|
||||||
// append or prepend items
|
|
||||||
if (reset === true) {
|
|
||||||
tab.value = entries
|
|
||||||
} else {
|
|
||||||
tab.value = tab.value || []
|
|
||||||
if (prepend === true) {
|
|
||||||
tab.value = [...entries, ...tab.value]
|
|
||||||
} else {
|
|
||||||
tab.value.push(...entries)
|
|
||||||
}
|
|
||||||
tab.length += size(entries)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// replace by index
|
|
||||||
tab.value = tab.value || []
|
|
||||||
for (const idx in entries) {
|
|
||||||
set(tab.value, idx, entries[idx])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'hash': // Object.<string, string>
|
|
||||||
if (reset === true) {
|
|
||||||
tab.value = {}
|
|
||||||
tab.length = 0
|
|
||||||
} else {
|
|
||||||
tab.value = tab.value || {}
|
|
||||||
}
|
|
||||||
for (const k in entries) {
|
|
||||||
if (nocheck !== true && !tab.value.hasOwnProperty(k)) {
|
|
||||||
tab.length += 1
|
|
||||||
}
|
|
||||||
tab.value[k] = entries[k]
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'set': // string[] | Object.{string, string}
|
|
||||||
if (reset === true) {
|
|
||||||
tab.value = entries
|
|
||||||
} else {
|
|
||||||
tab.value = tab.value || []
|
|
||||||
if (entries instanceof Array) {
|
|
||||||
// add items
|
|
||||||
for (const elem of entries) {
|
|
||||||
if (nocheck !== true && indexOf(tab.value, elem) === -1) {
|
|
||||||
tab.value.push(elem)
|
|
||||||
tab.length += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// replace items
|
|
||||||
for (const k in entries) {
|
|
||||||
const idx = indexOf(tab.value, k)
|
|
||||||
if (idx !== -1) {
|
|
||||||
tab.value[idx] = entries[k]
|
|
||||||
} else {
|
|
||||||
tab.value.push(entries[k])
|
|
||||||
tab.length += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'zset': // {value: string, score: number}
|
|
||||||
if (reset === true) {
|
|
||||||
tab.value = Object.entries(entries).map(([value, score]) => ({ value, score }))
|
|
||||||
} else {
|
|
||||||
tab.value = tab.value || []
|
|
||||||
for (const val in entries) {
|
|
||||||
if (nocheck !== true) {
|
|
||||||
const ent = find(tab.value, (e) => e.value === val)
|
|
||||||
if (ent != null) {
|
|
||||||
ent.score = entries[val]
|
|
||||||
} else {
|
|
||||||
tab.value.push({ value: val, score: entries[val] })
|
|
||||||
tab.length += 1
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tab.value.push({ value: val, score: entries[val] })
|
|
||||||
tab.length += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'stream': // [{id: string, value: []any}]
|
|
||||||
if (reset === true) {
|
|
||||||
tab.value = entries
|
|
||||||
} else {
|
|
||||||
tab.value = tab.value || []
|
|
||||||
tab.value = [...entries, ...tab.value]
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* remove value entries
|
|
||||||
* @param {string} server
|
|
||||||
* @param {number} db
|
|
||||||
* @param {string} key
|
|
||||||
* @param {string} type
|
|
||||||
* @param {string[] | number[]} entries
|
|
||||||
*/
|
|
||||||
removeValueEntries({ server, db, key, type, entries }) {
|
|
||||||
const tab = find(this.tabList, { name: server, db, key })
|
|
||||||
if (tab == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type.toLowerCase()) {
|
|
||||||
case 'list': // string[] | number[]
|
|
||||||
tab.value = tab.value || []
|
|
||||||
if (typeof entries[0] === 'number') {
|
|
||||||
// remove by index、
|
|
||||||
entries.sort((a, b) => b - a)
|
|
||||||
const removed = pullAt(tab.value, ...entries)
|
|
||||||
tab.length -= size(removed)
|
|
||||||
} else {
|
|
||||||
// append or prepend items
|
|
||||||
for (const elem of entries) {
|
|
||||||
if (!isEmpty(remove(tab.value, elem))) {
|
|
||||||
tab.length -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'hash': // string[]
|
|
||||||
tab.value = tab.value || {}
|
|
||||||
for (const k of entries) {
|
|
||||||
if (tab.value.hasOwnProperty(k)) {
|
|
||||||
delete tab.value[k]
|
|
||||||
tab.length -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'set': // []string
|
|
||||||
tab.value = tab.value || []
|
|
||||||
tab.length -= size(remove(tab.value, (v) => entries.indexOf(v) >= 0))
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'zset': // string[]
|
|
||||||
tab.value = tab.value || []
|
|
||||||
tab.length -= size(remove(tab.value, (v) => entries.indexOf(v.value) >= 0))
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'stream': // string[]
|
|
||||||
tab.value = tab.value || []
|
|
||||||
tab.length -= size(remove(tab.value, (v) => entries.indexOf(v.id) >= 0))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* update loading status of content in tab
|
|
||||||
* @param {string} server
|
|
||||||
* @param {number} db
|
|
||||||
* @param {boolean} loading
|
|
||||||
*/
|
|
||||||
updateLoading({ server, db, loading }) {
|
|
||||||
const tab = find(this.tabList, { name: server, db })
|
|
||||||
if (tab == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tab.loading = loading
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* update ttl in tab
|
|
||||||
* @param {string} server
|
* @param {string} server
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string|number[]} key
|
* @param {string|number[]} key
|
||||||
|
|
|
@ -92,8 +92,7 @@ body {
|
||||||
.value-wrapper {
|
.value-wrapper {
|
||||||
//border-top: v-bind('themeVars.borderColor') 1px solid;
|
//border-top: v-bind('themeVars.borderColor') 1px solid;
|
||||||
user-select: text;
|
user-select: text;
|
||||||
//height: 100%;
|
height: 100%;
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.value-item-part {
|
.value-item-part {
|
||||||
|
@ -137,7 +136,3 @@ body {
|
||||||
.n-modal-mask {
|
.n-modal-mask {
|
||||||
--wails-draggable: drag;
|
--wails-draggable: drag;
|
||||||
}
|
}
|
||||||
|
|
||||||
.n-tabs .n-tabs-nav {
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -5,9 +5,9 @@ go 1.21
|
||||||
require (
|
require (
|
||||||
github.com/adrg/sysfont v0.1.2
|
github.com/adrg/sysfont v0.1.2
|
||||||
github.com/andybalholm/brotli v1.0.6
|
github.com/andybalholm/brotli v1.0.6
|
||||||
github.com/google/uuid v1.4.0
|
github.com/google/uuid v1.3.1
|
||||||
github.com/klauspost/compress v1.17.2
|
github.com/klauspost/compress v1.17.2
|
||||||
github.com/redis/go-redis/v9 v9.3.0
|
github.com/redis/go-redis/v9 v9.2.1
|
||||||
github.com/vrischmann/userdir v0.0.0-20151206171402-20f291cebd68
|
github.com/vrischmann/userdir v0.0.0-20151206171402-20f291cebd68
|
||||||
github.com/wailsapp/wails/v2 v2.6.0
|
github.com/wailsapp/wails/v2 v2.6.0
|
||||||
golang.org/x/crypto v0.14.0
|
golang.org/x/crypto v0.14.0
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -23,8 +23,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
|
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
|
||||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
|
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
|
||||||
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
||||||
|
@ -62,8 +62,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/redis/go-redis/v9 v9.3.0 h1:RiVDjmig62jIWp7Kk4XVLs0hzV6pI3PyTnnL0cnn0u0=
|
github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg=
|
||||||
github.com/redis/go-redis/v9 v9.3.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
|
Loading…
Reference in New Issue