Compare commits

..

No commits in common. "5d2080aafbf8f4ff4bf053bc8871c386f7bc2634" and "cefc5a5078e1f6b62f3e7ce41cd1eef28ff0df7f" have entirely different histories.

42 changed files with 353 additions and 414 deletions

View File

@ -1189,7 +1189,7 @@ func (b *browserService) SetKeyValue(param types.SetKeyParam) (resp types.JSResp
score, _ := strconv.ParseFloat(strs[i+1].(string), 64) score, _ := strconv.ParseFloat(strs[i+1].(string), 64)
members = append(members, redis.Z{ members = append(members, redis.Z{
Score: score, Score: score,
Member: strs[i], Member: strs[i].(string),
}) })
} }
err = client.ZAdd(ctx, key, members...).Err() err = client.ZAdd(ctx, key, members...).Err()

View File

@ -107,11 +107,14 @@ func (c *connectionService) buildOption(config types.ConnectionConfig) (*redis.O
caCertPool.AppendCertsFromPEM(ca) caCertPool.AppendCertsFromPEM(ca)
} }
if len(certs) <= 0 {
return nil, errors.New("tls config error")
}
tlsConfig = &tls.Config{ tlsConfig = &tls.Config{
RootCAs: caCertPool, RootCAs: caCertPool,
InsecureSkipVerify: config.SSL.AllowInsecure, InsecureSkipVerify: false,
Certificates: certs, Certificates: certs,
ServerName: strings.TrimSpace(config.SSL.SNI),
} }
} }

View File

@ -46,8 +46,6 @@ type ConnectionSSL struct {
KeyFile string `json:"keyFile,omitempty" yaml:"keyFile,omitempty"` KeyFile string `json:"keyFile,omitempty" yaml:"keyFile,omitempty"`
CertFile string `json:"certFile,omitempty" yaml:"certFile,omitempty"` CertFile string `json:"certFile,omitempty" yaml:"certFile,omitempty"`
CAFile string `json:"caFile,omitempty" yaml:"caFile,omitempty"` CAFile string `json:"caFile,omitempty" yaml:"caFile,omitempty"`
AllowInsecure bool `json:"allowInsecure,omitempty" yaml:"allowInsecure,omitempty"`
SNI string `json:"sni,omitempty" yaml:"sni,omitempty"`
} }
type ConnectionSSH struct { type ConnectionSSH struct {

View File

@ -14,17 +14,17 @@
"monaco-editor": "^0.45.0", "monaco-editor": "^0.45.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"sass": "^1.69.7", "sass": "^1.69.7",
"vue": "^3.4.7", "vue": "^3.4.5",
"vue-i18n": "^9.9.0", "vue-i18n": "^9.9.0",
"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": "^5.0.2", "@vitejs/plugin-vue": "^5.0.2",
"naive-ui": "^2.37.3", "naive-ui": "^2.36.0",
"prettier": "^3.1.1", "prettier": "^3.1.1",
"unplugin-auto-import": "^0.17.3", "unplugin-auto-import": "^0.17.3",
"unplugin-icons": "^0.18.2", "unplugin-icons": "^0.18.1",
"unplugin-vue-components": "^0.26.0", "unplugin-vue-components": "^0.26.0",
"vite": "^5.0.11" "vite": "^5.0.11"
} }
@ -877,36 +877,36 @@
} }
}, },
"node_modules/@vue/compiler-core": { "node_modules/@vue/compiler-core": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.5.tgz",
"integrity": "sha512-hhCaE3pTMrlIJK7M/o3Xf7HV8+JoNTGOQ/coWS+V+pH6QFFyqtoXqQzpqsNp7UK17xYKua/MBiKj4e1vgZOBYw==", "integrity": "sha512-Daka7P1z2AgKjzuueWXhwzIsKu0NkLB6vGbNVEV2iJ8GJTrzraZo/Sk4GWCMRtd/qVi3zwnk+Owbd/xSZbwHtQ==",
"dependencies": { "dependencies": {
"@babel/parser": "^7.23.6", "@babel/parser": "^7.23.6",
"@vue/shared": "3.4.7", "@vue/shared": "3.4.5",
"entities": "^4.5.0", "entities": "^4.5.0",
"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.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.5.tgz",
"integrity": "sha512-qDKBAIurCTub4n/6jDYkXwgsFuriqqmmLrIq1N2QDfYJA/mwiwvxi09OGn28g+uDdERX9NaKDLji0oTjE3sScg==", "integrity": "sha512-J8YlxknJVd90SXFJ4HwGANSAXsx5I0lK30sO/zvYV7s5gXf7gZR7r/1BmZ2ju7RGH1lnc6bpBc6nL61yW+PsAQ==",
"dependencies": { "dependencies": {
"@vue/compiler-core": "3.4.7", "@vue/compiler-core": "3.4.5",
"@vue/shared": "3.4.7" "@vue/shared": "3.4.5"
} }
}, },
"node_modules/@vue/compiler-sfc": { "node_modules/@vue/compiler-sfc": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.5.tgz",
"integrity": "sha512-Gec6CLkReVswDYjQFq79O5rktri4R7TsD/VPCiUoJw40JhNNxaNJJa8mrQrWoJluW4ETy6QN0NUyC/JO77OCOw==", "integrity": "sha512-jauvkDuSSUbP0ebhfNqljhShA90YEfX/0wZ+w40oZF43IjGyWYjqYaJbvMJwGOd+9+vODW6eSvnk28f0SGV7OQ==",
"dependencies": { "dependencies": {
"@babel/parser": "^7.23.6", "@babel/parser": "^7.23.6",
"@vue/compiler-core": "3.4.7", "@vue/compiler-core": "3.4.5",
"@vue/compiler-dom": "3.4.7", "@vue/compiler-dom": "3.4.5",
"@vue/compiler-ssr": "3.4.7", "@vue/compiler-ssr": "3.4.5",
"@vue/shared": "3.4.7", "@vue/shared": "3.4.5",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
"magic-string": "^0.30.5", "magic-string": "^0.30.5",
"postcss": "^8.4.32", "postcss": "^8.4.32",
@ -914,12 +914,12 @@
} }
}, },
"node_modules/@vue/compiler-ssr": { "node_modules/@vue/compiler-ssr": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.5.tgz",
"integrity": "sha512-PvYeSOvnCkST5mGS0TLwEn5w+4GavtEn6adcq8AspbHaIr+mId5hp7cG3ASy3iy8b+LuXEG2/QaV/nj5BQ/Aww==", "integrity": "sha512-DDdEcDzj2lWTMfUMMtEpLDhURai9LhM0zSZ219jCt7b2Vyl0/jy3keFgCPMitG0V1S1YG4Cmws3lWHWdxHQOpg==",
"dependencies": { "dependencies": {
"@vue/compiler-dom": "3.4.7", "@vue/compiler-dom": "3.4.5",
"@vue/shared": "3.4.7" "@vue/shared": "3.4.5"
} }
}, },
"node_modules/@vue/devtools-api": { "node_modules/@vue/devtools-api": {
@ -928,29 +928,29 @@
"integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==" "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
}, },
"node_modules/@vue/reactivity": { "node_modules/@vue/reactivity": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.5.tgz",
"integrity": "sha512-F539DO0ogH0+L8F9Pnw7cjqibcmSOh5UTk16u5f4MKQ8fraqepI9zdh+sozPX6VmEHOcjo8qw3Or9ZcFFw4SZA==", "integrity": "sha512-BcWkKvjdvqJwb7BhhFkXPLDCecX4d4a6GATvCduJQDLv21PkPowAE5GKuIE5p6RC07/Lp9FMkkq4AYCTVF5KlQ==",
"dependencies": { "dependencies": {
"@vue/shared": "3.4.7" "@vue/shared": "3.4.5"
} }
}, },
"node_modules/@vue/runtime-core": { "node_modules/@vue/runtime-core": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.5.tgz",
"integrity": "sha512-QMMsWRQaD3BpGyjjChthpl4Mji4Fjx1qfdufsXlDkKU3HV+hWNor2z+29F+E1MmVcP0ZfRZUfqYgtsQoL7IGwQ==", "integrity": "sha512-wh9ELIOQKeWT9SaUPdLrsxRkZv14jp+SJm9aiQGWio+/MWNM3Lib0wE6CoKEqQ9+SCYyGjDBhTOTtO47kCgbkg==",
"dependencies": { "dependencies": {
"@vue/reactivity": "3.4.7", "@vue/reactivity": "3.4.5",
"@vue/shared": "3.4.7" "@vue/shared": "3.4.5"
} }
}, },
"node_modules/@vue/runtime-dom": { "node_modules/@vue/runtime-dom": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.5.tgz",
"integrity": "sha512-XwegyUY1rw8zxsX1Z36vwYcqo+uOgih5ti7y9vx+pPFhNdSQmN4LqK2RmSeAJG1oKV8NqSUmjpv92f/x6h0SeQ==", "integrity": "sha512-n5ewvOjyG3IEpqGBahdPXODFSpVlSz3H4LF76Sx0XAqpIOqyJ5bIb2PrdYuH2ogBMAQPh+o5tnoH4nJpBr8U0Q==",
"dependencies": { "dependencies": {
"@vue/runtime-core": "3.4.7", "@vue/runtime-core": "3.4.5",
"@vue/shared": "3.4.7", "@vue/shared": "3.4.5",
"csstype": "^3.1.3" "csstype": "^3.1.3"
} }
}, },
@ -960,21 +960,21 @@
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
}, },
"node_modules/@vue/server-renderer": { "node_modules/@vue/server-renderer": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.5.tgz",
"integrity": "sha512-3bWnYLEkLLhkDWqvNk7IvbQD4UcxvFKxELBiOO2iG3m6AniFIsBWfHOO5tLVQnjdWkODu4rq0GipmfEenVAK5Q==", "integrity": "sha512-jOFc/VE87yvifQpNju12VcqimH8pBLxdcT+t3xMeiED1K6DfH9SORyhFEoZlW5TG2Vwfn3Ul5KE+1aC99xnSBg==",
"dependencies": { "dependencies": {
"@vue/compiler-ssr": "3.4.7", "@vue/compiler-ssr": "3.4.5",
"@vue/shared": "3.4.7" "@vue/shared": "3.4.5"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "3.4.7" "vue": "3.4.5"
} }
}, },
"node_modules/@vue/shared": { "node_modules/@vue/shared": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.5.tgz",
"integrity": "sha512-G+i4glX1dMJk88sbJEcQEGWRQnVm9eIY7CcQbO5dpdsD9SF8jka3Mr5OqZYGjczGN1+D6EUwdu6phcmcx9iuPA==" "integrity": "sha512-6XptuzlMvN4l4cDnDw36pdGEV+9njYkQ1ZE0Q6iZLwrKefKaOJyiFmcP3/KBDHbt72cJZGtllAc1GaHe6XGAyg=="
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.11.2", "version": "8.11.2",
@ -1545,9 +1545,9 @@
"dev": true "dev": true
}, },
"node_modules/naive-ui": { "node_modules/naive-ui": {
"version": "2.37.3", "version": "2.36.0",
"resolved": "https://registry.npmjs.org/naive-ui/-/naive-ui-2.37.3.tgz", "resolved": "https://registry.npmjs.org/naive-ui/-/naive-ui-2.36.0.tgz",
"integrity": "sha512-aUkHFXVIluSi8Me+npbcsdv1NYhVMj5t9YaruoCESlqmfqspj+R2QHEVXkTtUI1kQwVrABMCtAGq/wountqjZA==", "integrity": "sha512-r1ydtEm1Ryf/aWpbLCf32mQAGK99jd1eXgpkCtIomcBRZeAtusfy6zCtIpCppoCuIKM3BW5DMafhVxilubk/lQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@css-render/plugin-bem": "^0.15.12", "@css-render/plugin-bem": "^0.15.12",
@ -1557,7 +1557,6 @@
"@types/lodash-es": "^4.17.9", "@types/lodash-es": "^4.17.9",
"async-validator": "^4.2.5", "async-validator": "^4.2.5",
"css-render": "^0.15.12", "css-render": "^0.15.12",
"csstype": "^3.1.3",
"date-fns": "^2.30.0", "date-fns": "^2.30.0",
"date-fns-tz": "^2.0.0", "date-fns-tz": "^2.0.0",
"evtd": "^0.2.4", "evtd": "^0.2.4",
@ -1568,18 +1567,12 @@
"treemate": "^0.3.11", "treemate": "^0.3.11",
"vdirs": "^0.1.8", "vdirs": "^0.1.8",
"vooks": "^0.2.12", "vooks": "^0.2.12",
"vueuc": "^0.4.58" "vueuc": "^0.4.54"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "^3.0.0" "vue": "^3.0.0"
} }
}, },
"node_modules/naive-ui/node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true
},
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.7", "version": "3.3.7",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz", "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz",
@ -2091,9 +2084,9 @@
} }
}, },
"node_modules/unplugin-icons": { "node_modules/unplugin-icons": {
"version": "0.18.2", "version": "0.18.1",
"resolved": "https://registry.npmjs.org/unplugin-icons/-/unplugin-icons-0.18.2.tgz", "resolved": "https://registry.npmmirror.com/unplugin-icons/-/unplugin-icons-0.18.1.tgz",
"integrity": "sha512-OgZoIJHGubeJmc3KePMOy62ovtxPEJfNMlr5tU+1ZqHGpSXubg3fnqq28VPvLL0D5vKj2PRCJF9tVGbQ7vBXJQ==", "integrity": "sha512-WzKu/eoq74YC7vyEAGsFebkRzsZrRkR4FUzLU6gbpfa7WRaVVpQS2n7LSxE1iRUN0scKL5b9bq+i0wucR+ttFQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@antfu/install-pkg": "^0.3.0", "@antfu/install-pkg": "^0.3.0",
@ -2104,9 +2097,6 @@
"local-pkg": "^0.5.0", "local-pkg": "^0.5.0",
"unplugin": "^1.5.1" "unplugin": "^1.5.1"
}, },
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": { "peerDependencies": {
"@svgr/core": ">=7.0.0", "@svgr/core": ">=7.0.0",
"@svgx/core": "^1.0.1", "@svgx/core": "^1.0.1",
@ -2259,15 +2249,15 @@
} }
}, },
"node_modules/vue": { "node_modules/vue": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.7.tgz", "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.5.tgz",
"integrity": "sha512-4urmkWpudekq0CPNMO7p6mBGa9qmTXwJMO2r6CT4EzIJVG7WoSReiysiNb7OSi/WI113oX0Srn9Rz1k/DCXKFQ==", "integrity": "sha512-VH6nHFhLPjgu2oh5vEBXoNZxsGHuZNr3qf4PHClwJWw6IDqw6B3x+4J+ABdoZ0aJuT8Zi0zf3GpGlLQCrGWHrw==",
"dependencies": { "dependencies": {
"@vue/compiler-dom": "3.4.7", "@vue/compiler-dom": "3.4.5",
"@vue/compiler-sfc": "3.4.7", "@vue/compiler-sfc": "3.4.5",
"@vue/runtime-dom": "3.4.7", "@vue/runtime-dom": "3.4.5",
"@vue/server-renderer": "3.4.7", "@vue/server-renderer": "3.4.5",
"@vue/shared": "3.4.7" "@vue/shared": "3.4.5"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": "*" "typescript": "*"
@ -2865,36 +2855,36 @@
"requires": {} "requires": {}
}, },
"@vue/compiler-core": { "@vue/compiler-core": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.5.tgz",
"integrity": "sha512-hhCaE3pTMrlIJK7M/o3Xf7HV8+JoNTGOQ/coWS+V+pH6QFFyqtoXqQzpqsNp7UK17xYKua/MBiKj4e1vgZOBYw==", "integrity": "sha512-Daka7P1z2AgKjzuueWXhwzIsKu0NkLB6vGbNVEV2iJ8GJTrzraZo/Sk4GWCMRtd/qVi3zwnk+Owbd/xSZbwHtQ==",
"requires": { "requires": {
"@babel/parser": "^7.23.6", "@babel/parser": "^7.23.6",
"@vue/shared": "3.4.7", "@vue/shared": "3.4.5",
"entities": "^4.5.0", "entities": "^4.5.0",
"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.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.5.tgz",
"integrity": "sha512-qDKBAIurCTub4n/6jDYkXwgsFuriqqmmLrIq1N2QDfYJA/mwiwvxi09OGn28g+uDdERX9NaKDLji0oTjE3sScg==", "integrity": "sha512-J8YlxknJVd90SXFJ4HwGANSAXsx5I0lK30sO/zvYV7s5gXf7gZR7r/1BmZ2ju7RGH1lnc6bpBc6nL61yW+PsAQ==",
"requires": { "requires": {
"@vue/compiler-core": "3.4.7", "@vue/compiler-core": "3.4.5",
"@vue/shared": "3.4.7" "@vue/shared": "3.4.5"
} }
}, },
"@vue/compiler-sfc": { "@vue/compiler-sfc": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.5.tgz",
"integrity": "sha512-Gec6CLkReVswDYjQFq79O5rktri4R7TsD/VPCiUoJw40JhNNxaNJJa8mrQrWoJluW4ETy6QN0NUyC/JO77OCOw==", "integrity": "sha512-jauvkDuSSUbP0ebhfNqljhShA90YEfX/0wZ+w40oZF43IjGyWYjqYaJbvMJwGOd+9+vODW6eSvnk28f0SGV7OQ==",
"requires": { "requires": {
"@babel/parser": "^7.23.6", "@babel/parser": "^7.23.6",
"@vue/compiler-core": "3.4.7", "@vue/compiler-core": "3.4.5",
"@vue/compiler-dom": "3.4.7", "@vue/compiler-dom": "3.4.5",
"@vue/compiler-ssr": "3.4.7", "@vue/compiler-ssr": "3.4.5",
"@vue/shared": "3.4.7", "@vue/shared": "3.4.5",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
"magic-string": "^0.30.5", "magic-string": "^0.30.5",
"postcss": "^8.4.32", "postcss": "^8.4.32",
@ -2902,12 +2892,12 @@
} }
}, },
"@vue/compiler-ssr": { "@vue/compiler-ssr": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.5.tgz",
"integrity": "sha512-PvYeSOvnCkST5mGS0TLwEn5w+4GavtEn6adcq8AspbHaIr+mId5hp7cG3ASy3iy8b+LuXEG2/QaV/nj5BQ/Aww==", "integrity": "sha512-DDdEcDzj2lWTMfUMMtEpLDhURai9LhM0zSZ219jCt7b2Vyl0/jy3keFgCPMitG0V1S1YG4Cmws3lWHWdxHQOpg==",
"requires": { "requires": {
"@vue/compiler-dom": "3.4.7", "@vue/compiler-dom": "3.4.5",
"@vue/shared": "3.4.7" "@vue/shared": "3.4.5"
} }
}, },
"@vue/devtools-api": { "@vue/devtools-api": {
@ -2916,29 +2906,29 @@
"integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==" "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
}, },
"@vue/reactivity": { "@vue/reactivity": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.5.tgz",
"integrity": "sha512-F539DO0ogH0+L8F9Pnw7cjqibcmSOh5UTk16u5f4MKQ8fraqepI9zdh+sozPX6VmEHOcjo8qw3Or9ZcFFw4SZA==", "integrity": "sha512-BcWkKvjdvqJwb7BhhFkXPLDCecX4d4a6GATvCduJQDLv21PkPowAE5GKuIE5p6RC07/Lp9FMkkq4AYCTVF5KlQ==",
"requires": { "requires": {
"@vue/shared": "3.4.7" "@vue/shared": "3.4.5"
} }
}, },
"@vue/runtime-core": { "@vue/runtime-core": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.5.tgz",
"integrity": "sha512-QMMsWRQaD3BpGyjjChthpl4Mji4Fjx1qfdufsXlDkKU3HV+hWNor2z+29F+E1MmVcP0ZfRZUfqYgtsQoL7IGwQ==", "integrity": "sha512-wh9ELIOQKeWT9SaUPdLrsxRkZv14jp+SJm9aiQGWio+/MWNM3Lib0wE6CoKEqQ9+SCYyGjDBhTOTtO47kCgbkg==",
"requires": { "requires": {
"@vue/reactivity": "3.4.7", "@vue/reactivity": "3.4.5",
"@vue/shared": "3.4.7" "@vue/shared": "3.4.5"
} }
}, },
"@vue/runtime-dom": { "@vue/runtime-dom": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.5.tgz",
"integrity": "sha512-XwegyUY1rw8zxsX1Z36vwYcqo+uOgih5ti7y9vx+pPFhNdSQmN4LqK2RmSeAJG1oKV8NqSUmjpv92f/x6h0SeQ==", "integrity": "sha512-n5ewvOjyG3IEpqGBahdPXODFSpVlSz3H4LF76Sx0XAqpIOqyJ5bIb2PrdYuH2ogBMAQPh+o5tnoH4nJpBr8U0Q==",
"requires": { "requires": {
"@vue/runtime-core": "3.4.7", "@vue/runtime-core": "3.4.5",
"@vue/shared": "3.4.7", "@vue/shared": "3.4.5",
"csstype": "^3.1.3" "csstype": "^3.1.3"
}, },
"dependencies": { "dependencies": {
@ -2950,18 +2940,18 @@
} }
}, },
"@vue/server-renderer": { "@vue/server-renderer": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.5.tgz",
"integrity": "sha512-3bWnYLEkLLhkDWqvNk7IvbQD4UcxvFKxELBiOO2iG3m6AniFIsBWfHOO5tLVQnjdWkODu4rq0GipmfEenVAK5Q==", "integrity": "sha512-jOFc/VE87yvifQpNju12VcqimH8pBLxdcT+t3xMeiED1K6DfH9SORyhFEoZlW5TG2Vwfn3Ul5KE+1aC99xnSBg==",
"requires": { "requires": {
"@vue/compiler-ssr": "3.4.7", "@vue/compiler-ssr": "3.4.5",
"@vue/shared": "3.4.7" "@vue/shared": "3.4.5"
} }
}, },
"@vue/shared": { "@vue/shared": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.7.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.5.tgz",
"integrity": "sha512-G+i4glX1dMJk88sbJEcQEGWRQnVm9eIY7CcQbO5dpdsD9SF8jka3Mr5OqZYGjczGN1+D6EUwdu6phcmcx9iuPA==" "integrity": "sha512-6XptuzlMvN4l4cDnDw36pdGEV+9njYkQ1ZE0Q6iZLwrKefKaOJyiFmcP3/KBDHbt72cJZGtllAc1GaHe6XGAyg=="
}, },
"acorn": { "acorn": {
"version": "8.11.2", "version": "8.11.2",
@ -3404,9 +3394,9 @@
"dev": true "dev": true
}, },
"naive-ui": { "naive-ui": {
"version": "2.37.3", "version": "2.36.0",
"resolved": "https://registry.npmjs.org/naive-ui/-/naive-ui-2.37.3.tgz", "resolved": "https://registry.npmjs.org/naive-ui/-/naive-ui-2.36.0.tgz",
"integrity": "sha512-aUkHFXVIluSi8Me+npbcsdv1NYhVMj5t9YaruoCESlqmfqspj+R2QHEVXkTtUI1kQwVrABMCtAGq/wountqjZA==", "integrity": "sha512-r1ydtEm1Ryf/aWpbLCf32mQAGK99jd1eXgpkCtIomcBRZeAtusfy6zCtIpCppoCuIKM3BW5DMafhVxilubk/lQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@css-render/plugin-bem": "^0.15.12", "@css-render/plugin-bem": "^0.15.12",
@ -3416,7 +3406,6 @@
"@types/lodash-es": "^4.17.9", "@types/lodash-es": "^4.17.9",
"async-validator": "^4.2.5", "async-validator": "^4.2.5",
"css-render": "^0.15.12", "css-render": "^0.15.12",
"csstype": "^3.1.3",
"date-fns": "^2.30.0", "date-fns": "^2.30.0",
"date-fns-tz": "^2.0.0", "date-fns-tz": "^2.0.0",
"evtd": "^0.2.4", "evtd": "^0.2.4",
@ -3427,15 +3416,7 @@
"treemate": "^0.3.11", "treemate": "^0.3.11",
"vdirs": "^0.1.8", "vdirs": "^0.1.8",
"vooks": "^0.2.12", "vooks": "^0.2.12",
"vueuc": "^0.4.58" "vueuc": "^0.4.54"
},
"dependencies": {
"csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true
}
} }
}, },
"nanoid": { "nanoid": {
@ -3809,9 +3790,9 @@
} }
}, },
"unplugin-icons": { "unplugin-icons": {
"version": "0.18.2", "version": "0.18.1",
"resolved": "https://registry.npmjs.org/unplugin-icons/-/unplugin-icons-0.18.2.tgz", "resolved": "https://registry.npmmirror.com/unplugin-icons/-/unplugin-icons-0.18.1.tgz",
"integrity": "sha512-OgZoIJHGubeJmc3KePMOy62ovtxPEJfNMlr5tU+1ZqHGpSXubg3fnqq28VPvLL0D5vKj2PRCJF9tVGbQ7vBXJQ==", "integrity": "sha512-WzKu/eoq74YC7vyEAGsFebkRzsZrRkR4FUzLU6gbpfa7WRaVVpQS2n7LSxE1iRUN0scKL5b9bq+i0wucR+ttFQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@antfu/install-pkg": "^0.3.0", "@antfu/install-pkg": "^0.3.0",
@ -3884,15 +3865,15 @@
} }
}, },
"vue": { "vue": {
"version": "3.4.7", "version": "3.4.5",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.7.tgz", "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.5.tgz",
"integrity": "sha512-4urmkWpudekq0CPNMO7p6mBGa9qmTXwJMO2r6CT4EzIJVG7WoSReiysiNb7OSi/WI113oX0Srn9Rz1k/DCXKFQ==", "integrity": "sha512-VH6nHFhLPjgu2oh5vEBXoNZxsGHuZNr3qf4PHClwJWw6IDqw6B3x+4J+ABdoZ0aJuT8Zi0zf3GpGlLQCrGWHrw==",
"requires": { "requires": {
"@vue/compiler-dom": "3.4.7", "@vue/compiler-dom": "3.4.5",
"@vue/compiler-sfc": "3.4.7", "@vue/compiler-sfc": "3.4.5",
"@vue/runtime-dom": "3.4.7", "@vue/runtime-dom": "3.4.5",
"@vue/server-renderer": "3.4.7", "@vue/server-renderer": "3.4.5",
"@vue/shared": "3.4.7" "@vue/shared": "3.4.5"
} }
}, },
"vue-i18n": { "vue-i18n": {

View File

@ -15,17 +15,17 @@
"monaco-editor": "^0.45.0", "monaco-editor": "^0.45.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"sass": "^1.69.7", "sass": "^1.69.7",
"vue": "^3.4.7", "vue": "^3.4.5",
"vue-i18n": "^9.9.0", "vue-i18n": "^9.9.0",
"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": "^5.0.2", "@vitejs/plugin-vue": "^5.0.2",
"naive-ui": "^2.37.3", "naive-ui": "^2.36.0",
"prettier": "^3.1.1", "prettier": "^3.1.1",
"unplugin-auto-import": "^0.17.3", "unplugin-auto-import": "^0.17.3",
"unplugin-icons": "^0.18.2", "unplugin-icons": "^0.18.1",
"unplugin-vue-components": "^0.26.0", "unplugin-vue-components": "^0.26.0",
"vite": "^5.0.11" "vite": "^5.0.11"
} }

View File

@ -1 +1 @@
af8db32947008da00ca6dfaef778b59f 41f065f6e9d8aa8ad43c4d2d8065d48a

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

View File

@ -2,7 +2,6 @@
import { computed, h, ref } from 'vue' import { computed, h, ref } from 'vue'
import { get, map } from 'lodash' import { get, map } from 'lodash'
import { NIcon, NText } from 'naive-ui' import { NIcon, NText } from 'naive-ui'
import { useRender } from '@/utils/render.js'
const props = defineProps({ const props = defineProps({
value: { value: {
@ -22,12 +21,15 @@ const props = defineProps({
}) })
const emit = defineEmits(['update:value']) const emit = defineEmits(['update:value'])
const render = useRender()
const renderHeader = () => { const renderHeader = () => {
return h('div', { class: 'type-selector-header' }, [h(NText, null, () => props.tooltip)]) return h('div', { class: 'type-selector-header' }, [h(NText, null, () => props.tooltip)])
} }
const renderLabel = (option) => {
return h('div', { class: 'type-selector-item' }, option.label)
}
const dropdownOption = computed(() => { const dropdownOption = computed(() => {
const options = [ const options = [
{ {
@ -69,7 +71,7 @@ const onDropdownShow = (show) => {
<n-dropdown <n-dropdown
:disabled="props.disabled" :disabled="props.disabled"
:options="dropdownOption" :options="dropdownOption"
:render-label="({ label }) => render.renderLabel(label, { class: 'type-selector-item' })" :render-label="renderLabel"
:show-arrow="true" :show-arrow="true"
:title="props.tooltip" :title="props.tooltip"
:value="props.value" :value="props.value"

View File

@ -25,7 +25,7 @@ const handleSelectFile = async () => {
const path = get(data, 'path', '') const path = get(data, 'path', '')
emit('update:value', path) emit('update:value', path)
} else { } else {
// emit('update:value', '') emit('update:value', '')
} }
} }
</script> </script>

View File

@ -7,10 +7,6 @@ const emit = defineEmits(['click'])
const props = defineProps({ const props = defineProps({
tooltip: String, tooltip: String,
tTooltip: String, tTooltip: String,
tooltipDelay: {
type: Number,
default: 1000,
},
type: String, type: String,
icon: [String, Object], icon: [String, Object],
size: { size: {
@ -39,7 +35,7 @@ const hasTooltip = computed(() => {
</script> </script>
<template> <template>
<n-tooltip v-if="hasTooltip" :delay="tooltipDelay" :show-arrow="false"> <n-tooltip v-if="hasTooltip" :show-arrow="false">
<template #trigger> <template #trigger>
<n-button <n-button
:class="props.buttonClass" :class="props.buttonClass"

View File

@ -1,4 +1,5 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n'
import { computed } from 'vue' import { computed } from 'vue'
const props = defineProps({ const props = defineProps({
@ -14,24 +15,22 @@ const props = defineProps({
const emit = defineEmits(['update:value', 'update:unit']) const emit = defineEmits(['update:value', 'update:unit'])
const unit = [ const i18n = useI18n()
{ const unit = computed(() => [
value: 1, { value: 1, label: i18n.t('common.second') },
label: 'common.second',
},
{ {
value: 60, value: 60,
label: 'common.minute', label: i18n.t('common.minute'),
}, },
{ {
value: 3600, value: 3600,
label: 'common.hour', label: i18n.t('common.hour'),
}, },
{ {
value: 86400, value: 86400,
label: 'common.day', label: i18n.t('common.day'),
}, },
] ])
const unitValue = computed(() => { const unitValue = computed(() => {
switch (props.unit) { switch (props.unit) {
@ -58,7 +57,6 @@ const unitValue = computed(() => {
@update:value="(val) => emit('update:value', val)" /> @update:value="(val) => emit('update:value', val)" />
<n-select <n-select
:options="unit" :options="unit"
:render-label="({ label }) => $t(label)"
:value="unitValue" :value="unitValue"
style="max-width: 150px" style="max-width: 150px"
@update:value="(val) => emit('update:unit', val)" /> @update:value="(val) => emit('update:unit', val)" />

View File

@ -26,7 +26,7 @@ const filterServerOption = computed(() => {
value: server, value: server,
})) }))
options.splice(0, 0, { options.splice(0, 0, {
label: 'common.all', label: i18n.t('common.all'),
value: '', value: '',
}) })
return options return options
@ -36,7 +36,7 @@ const tableRef = ref(null)
const columns = computed(() => [ const columns = computed(() => [
{ {
title: () => i18n.t('log.exec_time'), title: i18n.t('log.exec_time'),
key: 'timestamp', key: 'timestamp',
defaultSortOrder: 'ascend', defaultSortOrder: 'ascend',
sorter: 'default', sorter: 'default',
@ -48,7 +48,7 @@ const columns = computed(() => [
}, },
}, },
{ {
title: () => i18n.t('log.server'), title: i18n.t('log.server'),
key: 'server', key: 'server',
filterOptionValue: data.server, filterOptionValue: data.server,
filter: (value, row) => { filter: (value, row) => {
@ -62,7 +62,7 @@ const columns = computed(() => [
}, },
}, },
{ {
title: () => i18n.t('log.cmd'), title: i18n.t('log.cmd'),
key: 'cmd', key: 'cmd',
titleAlign: 'center', titleAlign: 'center',
filterOptionValue: data.keyword, filterOptionValue: data.keyword,
@ -83,7 +83,7 @@ const columns = computed(() => [
}, },
}, },
{ {
title: () => i18n.t('log.cost_time'), title: i18n.t('log.cost_time'),
key: 'cost', key: 'cost',
width: 100, width: 100,
align: 'center', align: 'center',
@ -141,7 +141,6 @@ defineExpose({
v-model:value="data.server" v-model:value="data.server"
:consistent-menu-width="false" :consistent-menu-width="false"
:options="filterServerOption" :options="filterServerOption"
:render-label="({ label, value }) => (value === '' ? $t(label) : label)"
style="min-width: 100px" /> style="min-width: 100px" />
</n-form-item> </n-form-item>
<n-form-item :label="$t('log.filter_keyword')"> <n-form-item :label="$t('log.filter_keyword')">

View File

@ -35,7 +35,7 @@ const tableRef = ref(null)
const columns = computed(() => [ const columns = computed(() => [
{ {
title: () => i18n.t('slog.exec_time'), title: i18n.t('slog.exec_time'),
key: 'timestamp', key: 'timestamp',
sortOrder: data.sortOrder, sortOrder: data.sortOrder,
sorter: 'default', sorter: 'default',
@ -47,7 +47,7 @@ const columns = computed(() => [
}, },
}, },
{ {
title: () => i18n.t('slog.client'), title: i18n.t('slog.client'),
key: 'client', key: 'client',
filterOptionValue: data.client, filterOptionValue: data.client,
resizable: true, resizable: true,
@ -81,7 +81,7 @@ const columns = computed(() => [
}, },
}, },
{ {
title: () => i18n.t('slog.cmd'), title: i18n.t('slog.cmd'),
key: 'cmd', key: 'cmd',
titleAlign: 'center', titleAlign: 'center',
filterOptionValue: data.keyword, filterOptionValue: data.keyword,
@ -102,7 +102,7 @@ const columns = computed(() => [
}, },
}, },
{ {
title: () => i18n.t('slog.cost_time'), title: i18n.t('slog.cost_time'),
key: 'cost', key: 'cost',
width: 100, width: 100,
align: 'center', align: 'center',

View File

@ -62,7 +62,7 @@ const ttlString = computed(() => {
const seconds = Math.floor(props.ttl % 60) const seconds = Math.floor(props.ttl % 60)
s += padStart(seconds + '', 2, '0') s += padStart(seconds + '', 2, '0')
} else if (props.ttl < 0) { } else if (props.ttl < 0) {
s = '-1' s = i18n.t('interface.forever')
} else { } else {
s = '00:00:00' s = '00:00:00'
} }
@ -190,7 +190,7 @@ const onTTL = () => {
<template #icon> <template #icon>
<n-icon :component="Timer" size="18" /> <n-icon :component="Timer" size="18" />
</template> </template>
{{ ttlString === '-1' ? $t('interface.forever') : ttlString }} {{ ttlString }}
</n-button> </n-button>
</template> </template>
TTL{{ `${ttl > 0 ? ': ' + ttl + $t('common.second') : ''}` }} TTL{{ `${ttl > 0 ? ': ' + ttl + $t('common.second') : ''}` }}

View File

@ -83,7 +83,7 @@ const tableRef = ref(null)
const fieldFilterOption = ref(null) const fieldFilterOption = ref(null)
const fieldColumn = computed(() => ({ const fieldColumn = computed(() => ({
key: 'key', key: 'key',
title: () => i18n.t('common.field'), title: i18n.t('common.field'),
align: 'center', align: 'center',
titleAlign: 'center', titleAlign: 'center',
resizable: true, resizable: true,
@ -113,7 +113,7 @@ const displayCode = computed(() => {
// const valueFilterOption = ref(null) // const valueFilterOption = ref(null)
const valueColumn = computed(() => ({ const valueColumn = computed(() => ({
key: 'value', key: 'value',
title: () => i18n.t('common.value'), title: i18n.t('common.value'),
align: displayCode.value ? 'left' : 'center', align: displayCode.value ? 'left' : 'center',
titleAlign: 'center', titleAlign: 'center',
resizable: true, resizable: true,
@ -195,7 +195,7 @@ const resetEdit = () => {
const actionColumn = { const actionColumn = {
key: 'action', key: 'action',
title: () => i18n.t('interface.action'), title: i18n.t('interface.action'),
width: 120, width: 120,
align: 'center', align: 'center',
titleAlign: 'center', titleAlign: 'center',

View File

@ -83,7 +83,7 @@ const displayCode = computed(() => {
const valueFilterOption = ref(null) const valueFilterOption = ref(null)
const valueColumn = computed(() => ({ const valueColumn = computed(() => ({
key: 'value', key: 'value',
title: () => i18n.t('common.value'), title: i18n.t('common.value'),
align: displayCode.value ? 'left' : 'center', align: displayCode.value ? 'left' : 'center',
titleAlign: 'center', titleAlign: 'center',
ellipsis: displayCode.value ellipsis: displayCode.value
@ -164,7 +164,7 @@ const resetEdit = () => {
const actionColumn = { const actionColumn = {
key: 'action', key: 'action',
title: () => i18n.t('interface.action'), title: i18n.t('interface.action'),
width: 120, width: 120,
align: 'center', align: 'center',
titleAlign: 'center', titleAlign: 'center',

View File

@ -82,7 +82,7 @@ const displayCode = computed(() => {
const valueFilterOption = ref(null) const valueFilterOption = ref(null)
const valueColumn = computed(() => ({ const valueColumn = computed(() => ({
key: 'value', key: 'value',
title: () => i18n.t('common.value'), title: i18n.t('common.value'),
align: displayCode.value ? 'left' : 'center', align: displayCode.value ? 'left' : 'center',
titleAlign: 'center', titleAlign: 'center',
ellipsis: displayCode.value ellipsis: displayCode.value
@ -161,7 +161,7 @@ const resetEdit = () => {
const actionColumn = { const actionColumn = {
key: 'action', key: 'action',
title: () => i18n.t('interface.action'), title: i18n.t('interface.action'),
width: 120, width: 120,
align: 'center', align: 'center',
titleAlign: 'center', titleAlign: 'center',

View File

@ -74,7 +74,7 @@ const idColumn = computed(() => ({
const valueFilterOption = ref(null) const valueFilterOption = ref(null)
const valueColumn = computed(() => ({ const valueColumn = computed(() => ({
key: 'value', key: 'value',
title: () => i18n.t('common.value'), title: i18n.t('common.value'),
align: 'left', align: 'left',
titleAlign: 'center', titleAlign: 'center',
resizable: true, resizable: true,
@ -98,7 +98,7 @@ const valueColumn = computed(() => ({
})) }))
const actionColumn = { const actionColumn = {
key: 'action', key: 'action',
title: () => i18n.t('interface.action'), title: i18n.t('interface.action'),
width: 80, width: 80,
align: 'center', align: 'center',
titleAlign: 'center', titleAlign: 'center',

View File

@ -81,7 +81,7 @@ const fullEdit = ref(false)
// const scoreFilterOption = ref(null) // const scoreFilterOption = ref(null)
const scoreColumn = computed(() => ({ const scoreColumn = computed(() => ({
key: 'score', key: 'score',
title: () => i18n.t('common.score'), title: i18n.t('common.score'),
align: 'center', align: 'center',
titleAlign: 'center', titleAlign: 'center',
resizable: true, resizable: true,
@ -130,7 +130,7 @@ const displayCode = computed(() => {
const valueFilterOption = ref(null) const valueFilterOption = ref(null)
const valueColumn = computed(() => ({ const valueColumn = computed(() => ({
key: 'value', key: 'value',
title: () => i18n.t('common.value'), title: i18n.t('common.value'),
align: displayCode.value ? 'left' : 'center', align: displayCode.value ? 'left' : 'center',
titleAlign: 'center', titleAlign: 'center',
resizable: true, resizable: true,
@ -210,7 +210,7 @@ const resetEdit = () => {
const actionColumn = { const actionColumn = {
key: 'action', key: 'action',
title: () => i18n.t('interface.action'), title: i18n.t('interface.action'),
width: 120, width: 120,
align: 'center', align: 'center',
titleAlign: 'center', titleAlign: 'center',

View File

@ -49,15 +49,15 @@ const defaultValue = {
const title = computed(() => { const title = computed(() => {
switch (newForm.type) { switch (newForm.type) {
case types.LIST: case types.LIST:
return 'dialogue.field.new_item' return i18n.t('dialogue.field.new_item')
case types.HASH: case types.HASH:
return 'dialogue.field.new' return i18n.t('dialogue.field.new')
case types.SET: case types.SET:
return 'dialogue.field.new' return i18n.t('dialogue.field.new')
case types.ZSET: case types.ZSET:
return 'dialogue.field.new' return i18n.t('dialogue.field.new')
case types.STREAM: case types.STREAM:
return 'dialogue.field.new' return i18n.t('dialogue.field.new')
} }
return '' return ''
}) })
@ -204,7 +204,7 @@ const onClose = () => {
:positive-button-props="{ size: 'medium' }" :positive-button-props="{ size: 'medium' }"
:positive-text="$t('common.confirm')" :positive-text="$t('common.confirm')"
:show-icon="false" :show-icon="false"
:title="title ? $t(title) : ''" :title="title"
preset="dialog" preset="dialog"
style="width: 600px" style="width: 600px"
transform-origin="center" transform-origin="center"

View File

@ -56,7 +56,7 @@ const groupOptions = computed(() => {
value: group, value: group,
})) }))
options.splice(0, 0, { options.splice(0, 0, {
label: 'dialogue.connection.no_group', label: i18n.t('dialogue.connection.no_group'),
value: '', value: '',
}) })
return options return options
@ -278,10 +278,7 @@ const onClose = () => {
:label="$t('dialogue.connection.group')" :label="$t('dialogue.connection.group')"
:span="24" :span="24"
required> required>
<n-select <n-select v-model:value="generalForm.group" :options="groupOptions" />
v-model:value="generalForm.group"
:options="groupOptions"
:render-label="({ label, value }) => (value === '' ? $t(label) : label)" />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :label="$t('dialogue.connection.addr')" :span="24" path="addr" required> <n-form-item-gi :label="$t('dialogue.connection.addr')" :span="24" path="addr" required>
<n-input <n-input
@ -464,16 +461,6 @@ const onClose = () => {
:disabled="!generalForm.ssl.enable" :disabled="!generalForm.ssl.enable"
:placeholder="$t('dialogue.connection.ssl.ca_file_tip')" /> :placeholder="$t('dialogue.connection.ssl.ca_file_tip')" />
</n-form-item> </n-form-item>
<n-form-item>
<n-checkbox v-model:checked="generalForm.ssl.allowInsecure" size="medium">
{{ $t('dialogue.connection.ssl.allow_insecure') }}
</n-checkbox>
</n-form-item>
<n-form-item :label="$t('dialogue.connection.ssl.sni')">
<n-input
v-model:value="generalForm.ssl.sni"
:placeholder="$t('dialogue.connection.ssl.sni')" />
</n-form-item>
</n-form> </n-form>
</n-tab-pane> </n-tab-pane>
@ -556,10 +543,7 @@ const onClose = () => {
:options="masterNameOptions" :options="masterNameOptions"
filterable filterable
tag /> tag />
<n-button <n-button :loading="loadingSentinelMaster" @click="onLoadSentinelMasters">
:disabled="!generalForm.sentinel.enable"
:loading="loadingSentinelMaster"
@click="onLoadSentinelMasters">
{{ $t('dialogue.connection.sentinel.auto_discover') }} {{ $t('dialogue.connection.sentinel.auto_discover') }}
</n-button> </n-button>
</n-input-group> </n-input-group>

View File

@ -9,7 +9,6 @@ import { every, get, includes, isEmpty } from 'lodash'
* Dialog for create or rename group * Dialog for create or rename group
*/ */
const i18n = useI18n()
const editGroup = ref('') const editGroup = ref('')
const groupForm = reactive({ const groupForm = reactive({
name: '', name: '',
@ -43,6 +42,7 @@ watchEffect(() => {
} }
}) })
const i18n = useI18n()
const onConfirm = async () => { const onConfirm = async () => {
try { try {
await groupFormRef.value?.validate((errs) => { await groupFormRef.value?.validate((errs) => {

View File

@ -39,31 +39,31 @@ watchEffect(() => {
}) })
const i18n = useI18n() const i18n = useI18n()
const conflictOption = [ const conflictOption = computed(() => [
{ {
value: 0, value: 0,
label: 'dialogue.import.conflict_overwrite', label: i18n.t('dialogue.import.conflict_overwrite'),
}, },
{ {
value: 1, value: 1,
label: 'dialogue.import.conflict_ignore', label: i18n.t('dialogue.import.conflict_ignore'),
}, },
] ])
const ttlOption = [ const ttlOption = computed(() => [
{ {
value: 0, value: 0,
label: 'dialogue.import.ttl_include', label: i18n.t('dialogue.import.ttl_include'),
}, },
{ {
value: 1, value: 1,
label: 'dialogue.import.ttl_ignore', label: i18n.t('dialogue.import.ttl_ignore'),
}, },
{ {
value: 2, value: 2,
label: 'dialogue.import.ttl_custom', label: i18n.t('dialogue.import.ttl_custom'),
}, },
] ])
const importEnable = computed(() => { const importEnable = computed(() => {
return !isEmpty(importKeyForm.file) return !isEmpty(importKeyForm.file)
@ -130,18 +130,14 @@ const onClose = () => {
<n-radio-button <n-radio-button
v-for="(op, i) in conflictOption" v-for="(op, i) in conflictOption"
:key="i" :key="i"
:label="$t(op.label)" :label="op.label"
:value="op.value" /> :value="op.value" />
</n-radio-group> </n-radio-group>
</n-form-item> </n-form-item>
<n-form-item :label="$t('dialogue.import.import_expire_title')"> <n-form-item :label="$t('dialogue.import.import_expire_title')">
<n-space :wrap-item="false"> <n-space :wrap-item="false">
<n-radio-group v-model:value="importKeyForm.ttlType"> <n-radio-group v-model:value="importKeyForm.ttlType">
<n-radio-button <n-radio-button v-for="(op, i) in ttlOption" :key="i" :label="op.label" :value="op.value" />
v-for="(op, i) in ttlOption"
:key="i"
:label="$t(op.label)"
:value="op.value" />
</n-radio-group> </n-radio-group>
<ttl-input <ttl-input
v-if="importKeyForm.ttlType === 2" v-if="importKeyForm.ttlType === 2"

View File

@ -1,9 +1,11 @@
<script setup> <script setup>
import { computed, reactive, ref, watchEffect } from 'vue' import { computed, reactive, ref, watchEffect } from 'vue'
import useDialog from 'stores/dialog' import useDialog from 'stores/dialog'
import { useI18n } from 'vue-i18n'
import { types } from '@/consts/support_redis_type.js' import { types } from '@/consts/support_redis_type.js'
import useBrowserStore from 'stores/browser.js' import useBrowserStore from 'stores/browser.js'
const i18n = useI18n()
const filterForm = reactive({ const filterForm = reactive({
server: '', server: '',
db: 0, db: 0,
@ -18,7 +20,7 @@ const typeOptions = computed(() => {
})) }))
options.splice(0, 0, { options.splice(0, 0, {
value: '', value: '',
label: 'common.all', label: i18n.t('common.all'),
}) })
return options return options
}) })
@ -73,10 +75,7 @@ const onClose = () => {
<n-input :value="filterForm.db + ''" readonly></n-input> <n-input :value="filterForm.db + ''" readonly></n-input>
</n-form-item> </n-form-item>
<n-form-item :label="$t('interface.type')" path="type" required> <n-form-item :label="$t('interface.type')" path="type" required>
<n-select <n-select v-model:value="filterForm.type" :options="typeOptions" />
v-model:value="filterForm.type"
:options="typeOptions"
:render-label="({ label }) => $t(label)" />
</n-form-item> </n-form-item>
<n-form-item :label="$t('dialogue.filter.filter_pattern')" required> <n-form-item :label="$t('dialogue.filter.filter_pattern')" required>
<n-input-group> <n-input-group>

View File

@ -37,7 +37,7 @@ watchEffect(() => {
const keyOptions = computed(() => { const keyOptions = computed(() => {
const opts = map(typesIconStyle, (v) => ({ const opts = map(typesIconStyle, (v) => ({
value: v, value: v,
label: 'preferences.general.key_icon_style' + v, label: i18n.t('preferences.general.key_icon_style' + v),
})) }))
return sortBy(opts, (o) => o.value) return sortBy(opts, (o) => o.value)
}) })
@ -81,7 +81,7 @@ const onClose = () => {
v-for="opt in prefStore.themeOption" v-for="opt in prefStore.themeOption"
:key="opt.value" :key="opt.value"
:value="opt.value"> :value="opt.value">
{{ $t(opt.label) }} {{ opt.label }}
</n-radio-button> </n-radio-button>
</n-radio-group> </n-radio-group>
</n-form-item-gi> </n-form-item-gi>
@ -89,14 +89,12 @@ const onClose = () => {
<n-select <n-select
v-model:value="prefStore.general.language" v-model:value="prefStore.general.language"
:options="prefStore.langOption" :options="prefStore.langOption"
:render-label="({ label, value }) => (value === 'auto' ? $t(label) : label)"
filterable /> filterable />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :label="$t('preferences.general.font')" :span="12" required> <n-form-item-gi :label="$t('preferences.general.font')" :span="12" required>
<n-select <n-select
v-model:value="prefStore.general.font" v-model:value="prefStore.general.font"
:options="prefStore.fontOption" :options="prefStore.fontOption"
:render-label="({ label, value }) => (value === '' ? $t(label) : label)"
filterable /> filterable />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :label="$t('preferences.general.font_size')" :span="12"> <n-form-item-gi :label="$t('preferences.general.font_size')" :span="12">
@ -110,10 +108,7 @@ const onClose = () => {
style="width: 100%" /> style="width: 100%" />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :label="$t('preferences.general.key_icon_style')" :span="12"> <n-form-item-gi :label="$t('preferences.general.key_icon_style')" :span="12">
<n-select <n-select v-model:value="prefStore.general.keyIconStyle" :options="keyOptions" />
v-model:value="prefStore.general.keyIconStyle"
:options="keyOptions"
:render-label="({ label }) => $t(label)" />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :label="$t('preferences.general.proxy')" :span="24"> <n-form-item-gi :label="$t('preferences.general.proxy')" :span="24">
<n-space> <n-space>
@ -141,18 +136,17 @@ const onClose = () => {
<n-select <n-select
v-model:value="prefStore.editor.font" v-model:value="prefStore.editor.font"
:options="prefStore.fontOption" :options="prefStore.fontOption"
:render-label="({ label, value }) => value || $t(label)"
filterable /> filterable />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :label="$t('preferences.general.font_size')" :span="12"> <n-form-item-gi :label="$t('preferences.general.font_size')" :show-feedback="false" :span="12">
<n-input-number v-model:value="prefStore.editor.fontSize" :max="65535" :min="1" /> <n-input-number v-model:value="prefStore.editor.fontSize" :max="65535" :min="1" />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :show-feedback="false" :show-label="false" :span="24"> <n-form-item-gi :show-feedback="false" :span="24">
<n-checkbox v-model:checked="prefStore.editor.showLineNum"> <n-checkbox v-model:checked="prefStore.editor.showLineNum">
{{ $t('preferences.editor.show_linenum') }} {{ $t('preferences.editor.show_linenum') }}
</n-checkbox> </n-checkbox>
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :show-feedback="false" :show-label="false" :span="24"> <n-form-item-gi :show-feedback="false" :span="24">
<n-checkbox v-model:checked="prefStore.editor.showFolding"> <n-checkbox v-model:checked="prefStore.editor.showFolding">
{{ $t('preferences.editor.show_folding') }} {{ $t('preferences.editor.show_folding') }}
</n-checkbox> </n-checkbox>

View File

@ -44,20 +44,20 @@ const isBatchAction = computed(() => {
const title = computed(() => { const title = computed(() => {
if (isBatchAction.value) { if (isBatchAction.value) {
return () => i18n.t('dialogue.ttl.title_batch', { count: size(ttlForm.keys) }) return i18n.t('dialogue.ttl.title_batch', { count: size(ttlForm.keys) })
} else { } else {
return () => i18n.t('dialogue.ttl.title') return i18n.t('dialogue.ttl.title')
} }
}) })
const i18n = useI18n() const i18n = useI18n()
const quickOption = [ const quickOption = computed(() => [
{ value: -1, unit: 1, label: 'interface.forever' }, { value: -1, unit: 1, label: i18n.t('interface.forever') },
{ value: 10, unit: 1, label: 'common.second' }, { value: 10, unit: 1, label: `10 ${i18n.t('common.second')}` },
{ value: 1, unit: 60, label: 'common.minute' }, { value: 1, unit: 60, label: `1 ${i18n.t('common.minute')}` },
{ value: 1, unit: 3600, label: 'common.hour' }, { value: 1, unit: 3600, label: `1 ${i18n.t('common.hour')}` },
{ value: 1, unit: 86400, label: 'common.day' }, { value: 1, unit: 86400, label: `1 ${i18n.t('common.day')}` },
] ])
const onQuickSet = (opt) => { const onQuickSet = (opt) => {
ttlForm.ttl = opt.value ttlForm.ttl = opt.value
@ -121,7 +121,7 @@ const onConfirm = async () => {
secondary secondary
size="small" size="small"
@click="onQuickSet(opt)"> @click="onQuickSet(opt)">
{{ (opt.value > 0 ? opt.value + ' ' : '') + $t(opt.label) }} {{ opt.label }}
</n-button> </n-button>
</n-space> </n-space>
</n-form-item> </n-form-item>

View File

@ -4,6 +4,7 @@ import { flatMap, reject } from 'lodash'
import Add from '@/components/icons/Add.vue' import Add from '@/components/icons/Add.vue'
import Delete from '@/components/icons/Delete.vue' import Delete from '@/components/icons/Delete.vue'
import IconButton from '@/components/common/IconButton.vue' import IconButton from '@/components/common/IconButton.vue'
import { useI18n } from 'vue-i18n'
const props = defineProps({ const props = defineProps({
type: Number, type: Number,
@ -11,14 +12,15 @@ const props = defineProps({
}) })
const emit = defineEmits(['update:value', 'update:type']) const emit = defineEmits(['update:value', 'update:type'])
const i18n = useI18n()
const updateOption = [ const updateOption = [
{ {
value: 0, value: 0,
label: 'dialogue.field.overwrite_field', label: i18n.t('dialogue.field.overwrite_field'),
}, },
{ {
value: 1, value: 1,
label: 'dialogue.field.ignore_field', label: i18n.t('dialogue.field.ignore_field'),
}, },
] ]
@ -45,7 +47,7 @@ const onUpdate = (val) => {
<template> <template>
<n-form-item :label="$t('dialogue.field.conflict_handle')"> <n-form-item :label="$t('dialogue.field.conflict_handle')">
<n-radio-group :value="props.type" @update:value="(val) => emit('update:type', val)"> <n-radio-group :value="props.type" @update:value="(val) => emit('update:type', val)">
<n-radio-button v-for="(op, i) in updateOption" :key="i" :label="op.label" :value="$t(op.value)" /> <n-radio-button v-for="(op, i) in updateOption" :key="i" :label="op.label" :value="op.value" />
</n-radio-group> </n-radio-group>
</n-form-item> </n-form-item>
<n-form-item <n-form-item

View File

@ -4,6 +4,7 @@ import { compact } from 'lodash'
import Add from '@/components/icons/Add.vue' import Add from '@/components/icons/Add.vue'
import Delete from '@/components/icons/Delete.vue' import Delete from '@/components/icons/Delete.vue'
import IconButton from '@/components/common/IconButton.vue' import IconButton from '@/components/common/IconButton.vue'
import { useI18n } from 'vue-i18n'
const props = defineProps({ const props = defineProps({
type: Number, type: Number,
@ -11,14 +12,15 @@ const props = defineProps({
}) })
const emit = defineEmits(['update:value', 'update:type']) const emit = defineEmits(['update:value', 'update:type'])
const i18n = useI18n()
const insertOption = [ const insertOption = [
{ {
value: 0, value: 0,
label: 'dialogue.field.append_item', label: i18n.t('dialogue.field.append_item'),
}, },
{ {
value: 1, value: 1,
label: 'dialogue.field.prepend_item', label: i18n.t('dialogue.field.prepend_item'),
}, },
] ]
@ -32,7 +34,7 @@ const onUpdate = (val) => {
<template> <template>
<n-form-item :label="$t('interface.type')"> <n-form-item :label="$t('interface.type')">
<n-radio-group :value="props.type" @update:value="(val) => emit('update:type', val)"> <n-radio-group :value="props.type" @update:value="(val) => emit('update:type', val)">
<n-radio-button v-for="(op, i) in insertOption" :key="i" :label="op.label" :value="$t(op.value)" /> <n-radio-button v-for="(op, i) in insertOption" :key="i" :label="op.label" :value="op.value" />
</n-radio-group> </n-radio-group>
</n-form-item> </n-form-item>
<n-form-item :label="$t('dialogue.field.element')" required> <n-form-item :label="$t('dialogue.field.element')" required>

View File

@ -4,6 +4,7 @@ import { isEmpty, reject } from 'lodash'
import Add from '@/components/icons/Add.vue' import Add from '@/components/icons/Add.vue'
import Delete from '@/components/icons/Delete.vue' import Delete from '@/components/icons/Delete.vue'
import IconButton from '@/components/common/IconButton.vue' import IconButton from '@/components/common/IconButton.vue'
import { useI18n } from 'vue-i18n'
const props = defineProps({ const props = defineProps({
type: Number, type: Number,
@ -14,14 +15,15 @@ defineOptions({
}) })
const emit = defineEmits(['update:value', 'update:type']) const emit = defineEmits(['update:value', 'update:type'])
const i18n = useI18n()
const updateOption = [ const updateOption = [
{ {
value: 0, value: 0,
label: 'dialogue.field.overwrite_field', label: i18n.t('dialogue.field.overwrite_field'),
}, },
{ {
value: 1, value: 1,
label: 'dialogue.field.ignore_field', label: i18n.t('dialogue.field.ignore_field'),
}, },
] ]
@ -53,7 +55,7 @@ const onUpdate = () => {
<template> <template>
<n-form-item :label="$t('interface.type')"> <n-form-item :label="$t('interface.type')">
<n-radio-group :value="props.type" @update:value="(val) => emit('update:type', val)"> <n-radio-group :value="props.type" @update:value="(val) => emit('update:type', val)">
<n-radio-button v-for="(op, i) in updateOption" :key="i" :label="op.label" :value="$t(op.value)" /> <n-radio-button v-for="(op, i) in updateOption" :key="i" :label="op.label" :value="op.value" />
</n-radio-group> </n-radio-group>
</n-form-item> </n-form-item>
<n-form-item <n-form-item

View File

@ -64,12 +64,16 @@ const dbSelectOptions = computed(() => {
}) })
}) })
const moreOptions = [ const moreOptions = computed(() => [
{ key: 'import', label: 'interface.import_key', icon: Import }, { key: 'import', label: i18n.t('interface.import_key'), icon: render.renderIcon(Import, { strokeWidth: 3.5 }) },
{ key: 'flush', label: 'interface.flush_db', icon: Delete }, { key: 'flush', label: i18n.t('interface.flush_db'), icon: render.renderIcon(Delete, { strokeWidth: 3.5 }) },
{ key: 'divider', type: 'divider' }, { key: 'divider', type: 'divider' },
{ key: 'disconnect', label: 'interface.disconnect', icon: Unlink }, {
] key: 'disconnect',
label: i18n.t('interface.disconnect'),
icon: render.renderIcon(Unlink, { strokeWidth: 3.5 }),
},
])
const loadProgress = computed(() => { const loadProgress = computed(() => {
const db = browserStore.getDatabase(props.server, props.db) const db = browserStore.getDatabase(props.server, props.db)
@ -352,8 +356,6 @@ watch(
@click="inCheckState = true" /> @click="inCheckState = true" />
<n-dropdown <n-dropdown
:options="moreOptions" :options="moreOptions"
:render-icon="({ icon }) => render.renderIcon(icon, { strokeWidth: 3.5 })"
:render-label="({ label }) => $t(label)"
placement="top-end" placement="top-end"
style="min-width: 130px" style="min-width: 130px"
@select="onSelectOptions"> @select="onSelectOptions">

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { computed, h, markRaw, nextTick, reactive, ref, watchEffect } from 'vue' import { computed, h, nextTick, reactive, ref, watchEffect } from 'vue'
import { ConnectionType } from '@/consts/connection_type.js' import { ConnectionType } from '@/consts/connection_type.js'
import { NIcon, NSpace, NText, useThemeVars } from 'naive-ui' import { NIcon, NSpace, NText, useThemeVars } from 'naive-ui'
import Key from '@/components/icons/Key.vue' import Key from '@/components/icons/Key.vue'
@ -15,6 +15,7 @@ import Delete from '@/components/icons/Delete.vue'
import useDialogStore from 'stores/dialog.js' import useDialogStore from 'stores/dialog.js'
import { ClipboardSetText } from 'wailsjs/runtime/runtime.js' import { ClipboardSetText } from 'wailsjs/runtime/runtime.js'
import useConnectionStore from 'stores/connections.js' import useConnectionStore from 'stores/connections.js'
import Filter from '@/components/icons/Filter.vue'
import useTabStore from 'stores/tab.js' import useTabStore from 'stores/tab.js'
import IconButton from '@/components/common/IconButton.vue' import IconButton from '@/components/common/IconButton.vue'
import { parseHexColor } from '@/utils/rgb.js' import { parseHexColor } from '@/utils/rgb.js'
@ -103,21 +104,42 @@ const contextMenuParam = reactive({
}) })
const menuOptions = { const menuOptions = {
[ConnectionType.RedisKey]: [ [ConnectionType.RedisDB]: ({ opened }) => {
if (opened) {
return [
{
key: 'db_filter',
label: i18n.t('interface.filter_key'),
icon: render.renderIcon(Filter),
},
{
type: 'divider',
key: 'd1',
},
{
type: 'divider',
key: 'd2',
},
]
} else {
return []
}
},
[ConnectionType.RedisKey]: () => [
// { // {
// key: 'key_reload', // key: 'key_reload',
// label: 'interface.reload'), // label: i18n.t('interface.reload'),
// icon: Refresh, // icon: render.renderIcon(Refresh),
// }, // },
{ {
key: 'key_newkey', key: 'key_newkey',
label: 'interface.new_key', label: i18n.t('interface.new_key'),
icon: Add, icon: render.renderIcon(Add),
}, },
{ {
key: 'key_copy', key: 'key_copy',
label: 'interface.copy_path', label: i18n.t('interface.copy_path'),
icon: CopyLink, icon: render.renderIcon(CopyLink),
}, },
{ {
type: 'divider', type: 'divider',
@ -125,20 +147,20 @@ const menuOptions = {
}, },
{ {
key: 'key_remove', key: 'key_remove',
label: 'interface.batch_delete_key', label: i18n.t('interface.batch_delete_key'),
icon: Delete, icon: render.renderIcon(Delete),
}, },
], ],
[ConnectionType.RedisValue]: [ [ConnectionType.RedisValue]: () => [
{ {
key: 'value_reload', key: 'value_reload',
label: 'interface.reload', label: i18n.t('interface.reload'),
icon: Refresh, icon: render.renderIcon(Refresh),
}, },
{ {
key: 'value_copy', key: 'value_copy',
label: 'interface.copy_key', label: i18n.t('interface.copy_key'),
icon: CopyLink, icon: render.renderIcon(CopyLink),
}, },
{ {
type: 'divider', type: 'divider',
@ -146,12 +168,16 @@ const menuOptions = {
}, },
{ {
key: 'value_remove', key: 'value_remove',
label: 'interface.remove_key', label: i18n.t('interface.remove_key'),
icon: Delete, icon: render.renderIcon(Delete),
}, },
], ],
} }
const renderContextLabel = (option) => {
return h('div', { class: 'context-menu-item' }, option.label)
}
const handleSelectContextMenu = (key) => { const handleSelectContextMenu = (key) => {
contextMenuParam.show = false contextMenuParam.show = false
const selectedKey = get(selectedKeys.value, 0) const selectedKey = get(selectedKeys.value, 0)
@ -500,7 +526,7 @@ const nodeProps = ({ option }) => {
return return
} }
contextMenuParam.show = false contextMenuParam.show = false
contextMenuParam.options = markRaw(menuOptions[option.type] || []) contextMenuParam.options = menuOptions[option.type](option)
nextTick().then(() => { nextTick().then(() => {
contextMenuParam.x = e.clientX contextMenuParam.x = e.clientX
contextMenuParam.y = e.clientY contextMenuParam.y = e.clientY
@ -601,12 +627,9 @@ defineExpose({
@update:selected-keys="onUpdateSelectedKeys" @update:selected-keys="onUpdateSelectedKeys"
@update:expanded-keys="onUpdateExpanded" @update:expanded-keys="onUpdateExpanded"
@update:checked-keys="onUpdateCheckedKeys" /> @update:checked-keys="onUpdateCheckedKeys" />
<!-- context menu -->
<n-dropdown <n-dropdown
:options="contextMenuParam.options" :options="contextMenuParam.options"
:render-icon="({ icon }) => render.renderIcon(icon)" :render-label="renderContextLabel"
:render-label="({ label }) => render.renderLabel($t(label), { class: 'context-menu-item' })"
:show="contextMenuParam.show" :show="contextMenuParam.show"
:x="contextMenuParam.x" :x="contextMenuParam.x"
:y="contextMenuParam.y" :y="contextMenuParam.y"

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import useDialogStore from 'stores/dialog.js' import useDialogStore from 'stores/dialog.js'
import { h, markRaw, nextTick, reactive, ref } from 'vue' import { h, nextTick, reactive, ref } from 'vue'
import useConnectionStore from 'stores/connections.js' import useConnectionStore from 'stores/connections.js'
import { NIcon, NSpace, NText, useThemeVars } from 'naive-ui' import { NIcon, NSpace, NText, useThemeVars } from 'naive-ui'
import { ConnectionType } from '@/consts/connection_type.js' import { ConnectionType } from '@/consts/connection_type.js'
@ -53,13 +53,13 @@ const menuOptions = {
[ConnectionType.Group]: ({ opened }) => [ [ConnectionType.Group]: ({ opened }) => [
{ {
key: 'group_rename', key: 'group_rename',
label: 'interface.rename_conn_group', label: i18n.t('interface.rename_conn_group'),
icon: Edit, icon: render.renderIcon(Edit),
}, },
{ {
key: 'group_delete', key: 'group_delete',
label: 'interface.remove_conn_group', label: i18n.t('interface.remove_conn_group'),
icon: Delete, icon: render.renderIcon(Delete),
}, },
], ],
[ConnectionType.Server]: ({ name }) => { [ConnectionType.Server]: ({ name }) => {
@ -68,18 +68,18 @@ const menuOptions = {
return [ return [
{ {
key: 'server_close', key: 'server_close',
label: 'interface.disconnect', label: i18n.t('interface.disconnect'),
icon: Unlink, icon: render.renderIcon(Unlink),
}, },
{ {
key: 'server_edit', key: 'server_edit',
label: 'interface.edit_conn', label: i18n.t('interface.edit_conn'),
icon: Config, icon: render.renderIcon(Config),
}, },
{ {
key: 'server_dup', key: 'server_dup',
label: 'interface.dup_conn', label: i18n.t('interface.dup_conn'),
icon: CopyLink, icon: render.renderIcon(CopyLink),
}, },
{ {
type: 'divider', type: 'divider',
@ -87,26 +87,26 @@ const menuOptions = {
}, },
{ {
key: 'server_remove', key: 'server_remove',
label: 'interface.remove_conn', label: i18n.t('interface.remove_conn'),
icon: Delete, icon: render.renderIcon(Delete),
}, },
] ]
} else { } else {
return [ return [
{ {
key: 'server_open', key: 'server_open',
label: 'interface.open_connection', label: i18n.t('interface.open_connection'),
icon: Connect, icon: render.renderIcon(Connect),
}, },
{ {
key: 'server_edit', key: 'server_edit',
label: 'interface.edit_conn', label: i18n.t('interface.edit_conn'),
icon: Config, icon: render.renderIcon(Config),
}, },
{ {
key: 'server_dup', key: 'server_dup',
label: 'interface.dup_conn', label: i18n.t('interface.dup_conn'),
icon: CopyLink, icon: render.renderIcon(CopyLink),
}, },
{ {
type: 'divider', type: 'divider',
@ -114,8 +114,8 @@ const menuOptions = {
}, },
{ {
key: 'server_remove', key: 'server_remove',
label: 'interface.remove_conn', label: i18n.t('interface.remove_conn'),
icon: Delete, icon: render.renderIcon(Delete),
}, },
] ]
} }
@ -355,7 +355,7 @@ const nodeProps = ({ option }) => {
} }
contextMenuParam.show = false contextMenuParam.show = false
nextTick().then(() => { nextTick().then(() => {
contextMenuParam.options = markRaw(mop(option)) contextMenuParam.options = mop(option)
contextMenuParam.currentNode = option contextMenuParam.currentNode = option
contextMenuParam.x = e.clientX contextMenuParam.x = e.clientX
contextMenuParam.y = e.clientY contextMenuParam.y = e.clientY
@ -366,6 +366,10 @@ const nodeProps = ({ option }) => {
} }
} }
const renderContextLabel = (option) => {
return h('div', { class: 'context-menu-item' }, option.label)
}
const handleSelectContextMenu = (key) => { const handleSelectContextMenu = (key) => {
contextMenuParam.show = false contextMenuParam.show = false
const selectedKey = get(selectedKeys.value, 0) const selectedKey = get(selectedKeys.value, 0)
@ -529,8 +533,7 @@ const onCancelOpen = () => {
<n-dropdown <n-dropdown
:keyboard="true" :keyboard="true"
:options="contextMenuParam.options" :options="contextMenuParam.options"
:render-icon="({ icon }) => render.renderIcon(icon)" :render-label="renderContextLabel"
:render-label="({ label }) => render.renderLabel($t(label), { class: 'context-menu-item' })"
:show="contextMenuParam.show" :show="contextMenuParam.show"
:x="contextMenuParam.x" :x="contextMenuParam.x"
:y="contextMenuParam.y" :y="contextMenuParam.y"

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { computed, ref } from 'vue' import { computed, h } from 'vue'
import { NIcon, useThemeVars } from 'naive-ui' import { NIcon, useThemeVars } from 'naive-ui'
import Database from '@/components/icons/Database.vue' import Database from '@/components/icons/Database.vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
@ -14,7 +14,6 @@ import Record from '@/components/icons/Record.vue'
import { extraTheme } from '@/utils/extra_theme.js' import { extraTheme } from '@/utils/extra_theme.js'
import useBrowserStore from 'stores/browser.js' import useBrowserStore from 'stores/browser.js'
import { useRender } from '@/utils/render.js' import { useRender } from '@/utils/render.js'
import wechatUrl from '@/assets/images/wechat_official.png'
const themeVars = useThemeVars() const themeVars = useThemeVars()
const render = useRender() const render = useRender()
@ -36,22 +35,21 @@ const iconSize = computed(() => Math.floor(props.width * 0.45))
const browserStore = useBrowserStore() const browserStore = useBrowserStore()
const i18n = useI18n() const i18n = useI18n()
const showWechat = ref(false)
const menuOptions = computed(() => { const menuOptions = computed(() => {
return [ return [
{ {
label: 'ribbon.browser', label: i18n.t('ribbon.browser'),
key: 'browser', key: 'browser',
icon: Database, icon: Database,
show: browserStore.anyConnectionOpened, show: browserStore.anyConnectionOpened,
}, },
{ {
label: 'ribbon.server', label: i18n.t('ribbon.server'),
key: 'server', key: 'server',
icon: Server, icon: Server,
}, },
{ {
label: 'ribbon.log', label: i18n.t('ribbon.log'),
key: 'log', key: 'log',
icon: Record, icon: Record,
}, },
@ -61,21 +59,21 @@ const menuOptions = computed(() => {
const preferencesOptions = computed(() => { const preferencesOptions = computed(() => {
return [ return [
{ {
label: 'menu.preferences', label: i18n.t('menu.preferences'),
key: 'preferences', key: 'preferences',
icon: Config, icon: render.renderIcon(Config, { strokeWidth: 3 }),
}, },
// { // {
// label: 'menu.help', // label: i18n.t('menu.help'),
// key: 'help', // key: 'help',
// icon: Help, // icon: render.renderIcon(Help, { strokeWidth: 3 }),
// }, // },
{ {
label: 'menu.report_bug', label: i18n.t('menu.report_bug'),
key: 'report', key: 'report',
}, },
{ {
label: 'menu.check_update', label: i18n.t('menu.check_update'),
key: 'update', key: 'update',
}, },
{ {
@ -83,16 +81,16 @@ const preferencesOptions = computed(() => {
key: 'd1', key: 'd1',
}, },
{ {
label: 'menu.wechat_official', label: i18n.t('menu.about'),
key: 'wechat_official',
},
{
label: 'menu.about',
key: 'about', key: 'about',
}, },
] ]
}) })
const renderContextLabel = (option) => {
return h('div', { class: 'context-menu-item' }, option.label)
}
const dialogStore = useDialogStore() const dialogStore = useDialogStore()
const prefStore = usePreferencesStore() const prefStore = usePreferencesStore()
const onSelectPreferenceMenu = (key) => { const onSelectPreferenceMenu = (key) => {
@ -106,9 +104,6 @@ const onSelectPreferenceMenu = (key) => {
case 'report': case 'report':
BrowserOpenURL('https://github.com/tiny-craft/tiny-rdm/issues') BrowserOpenURL('https://github.com/tiny-craft/tiny-rdm/issues')
break break
case 'wechat_official':
showWechat.value = true
break
case 'about': case 'about':
dialogStore.openAboutDialog() dialogStore.openAboutDialog()
break break
@ -145,35 +140,20 @@ const exThemeVars = computed(() => {
</n-icon> </n-icon>
</div> </div>
</template> </template>
{{ $t(m.label) }} {{ m.label }}
</n-tooltip> </n-tooltip>
</div> </div>
<div class="flex-item-expand"></div> <div class="flex-item-expand"></div>
<div class="nav-menu-item flex-box-v"> <div class="nav-menu-item flex-box-v">
<n-dropdown <n-dropdown
:options="preferencesOptions" :options="preferencesOptions"
:render-icon="({ icon }) => render.renderIcon(icon)" :render-label="renderContextLabel"
:render-label="({ label }) => render.renderLabel($t(label), { class: 'context-menu-item' })"
trigger="click" trigger="click"
@select="onSelectPreferenceMenu"> @select="onSelectPreferenceMenu">
<icon-button :icon="Config" :size="iconSize" :stroke-width="3" class="nav-menu-button" /> <icon-button :icon="Config" :size="iconSize" :stroke-width="3" class="nav-menu-button" />
</n-dropdown> </n-dropdown>
<icon-button <icon-button :icon="Github" :size="iconSize" class="nav-menu-button" @click="openGithub" />
:icon="Github"
:size="iconSize"
:tooltip="$t('ribbon.github')"
class="nav-menu-button"
@click="openGithub" />
</div> </div>
<!-- wechat official modal -->
<n-modal
:show="showWechat"
transform-origin="center"
@close="showWechat = false"
@mask-click="showWechat = false">
<n-image :src="wechatUrl" :width="400" preview-disabled />
</n-modal>
</div> </div>
</template> </template>
@ -247,7 +227,7 @@ const exThemeVars = computed(() => {
.nav-menu-item { .nav-menu-item {
align-items: center; align-items: center;
padding: 10px 0; padding: 10px 0;
gap: 18px; gap: 15px;
--wails-draggable: none; --wails-draggable: none;
.nav-menu-button { .nav-menu-button {

View File

@ -70,7 +70,7 @@
"disconnect": "Disconnect", "disconnect": "Disconnect",
"dup_conn": "Duplicate Connection", "dup_conn": "Duplicate Connection",
"remove_conn": "Delete Connection", "remove_conn": "Delete Connection",
"edit_conn": "Edit Connection", "edit_conn": "Edit Connection Config",
"edit_conn_group": "Edit Group", "edit_conn_group": "Edit Group",
"rename_conn_group": "Rename Group", "rename_conn_group": "Rename Group",
"remove_conn_group": "Delete Group", "remove_conn_group": "Delete Group",
@ -142,8 +142,7 @@
"ribbon": { "ribbon": {
"server": "Server", "server": "Server",
"browser": "Data Browser", "browser": "Data Browser",
"log": "Log", "log": "Log"
"github": "Github"
}, },
"dialogue": { "dialogue": {
"close_confirm": "Confirm close this tab and connection ({name})", "close_confirm": "Confirm close this tab and connection ({name})",
@ -201,9 +200,6 @@
"ssl": { "ssl": {
"title": "SSL/TLS", "title": "SSL/TLS",
"enable": "Enable SSL/TLS", "enable": "Enable SSL/TLS",
"allow_insecure": "Allow Insecure Connection",
"sni": "Server Name(SNI)",
"sni_tip": "(Optional) Server Name",
"cert_file": "Public Key", "cert_file": "Public Key",
"key_file": "Private Key", "key_file": "Private Key",
"ca_file": "Authority", "ca_file": "Authority",
@ -339,7 +335,6 @@
"help": "Help", "help": "Help",
"check_update": "Check for Updates...", "check_update": "Check for Updates...",
"report_bug": "Report a Bug", "report_bug": "Report a Bug",
"wechat_official": "Wechat Official Account",
"about": "About" "about": "About"
}, },
"log": { "log": {

View File

@ -114,8 +114,7 @@
"ribbon": { "ribbon": {
"server": "Servidor", "server": "Servidor",
"browser": "Navegador de Dados", "browser": "Navegador de Dados",
"log": "Log", "log": "Log"
"github": "Github"
}, },
"dialogue": { "dialogue": {
"close_confirm": "Confirmar o fechamento desta guia e conexão ({name})", "close_confirm": "Confirmar o fechamento desta guia e conexão ({name})",

View File

@ -142,8 +142,7 @@
"ribbon": { "ribbon": {
"server": "服务器", "server": "服务器",
"browser": "数据浏览", "browser": "数据浏览",
"log": "日志", "log": "日志"
"github": "Github"
}, },
"dialogue": { "dialogue": {
"close_confirm": "是否关闭此连接({name}", "close_confirm": "是否关闭此连接({name}",
@ -201,9 +200,6 @@
"ssl": { "ssl": {
"title": "SSL/TLS", "title": "SSL/TLS",
"enable": "启用SSL", "enable": "启用SSL",
"allow_insecure": "允许不安全连接",
"sni": "服务器名(SNI)",
"sni_tip": "(可选)服务器名",
"cert_file": "公钥文件", "cert_file": "公钥文件",
"key_file": "私钥文件", "key_file": "私钥文件",
"ca_file": "授权文件", "ca_file": "授权文件",
@ -339,7 +335,6 @@
"help": "帮助", "help": "帮助",
"check_update": "检查更新...", "check_update": "检查更新...",
"report_bug": "报告错误", "report_bug": "报告错误",
"wechat_official": "微信公众号",
"about": "关于" "about": "关于"
}, },
"log": { "log": {

View File

@ -159,8 +159,6 @@ const useConnectionStore = defineStore('connections', {
markColor: '', markColor: '',
ssl: { ssl: {
enable: false, enable: false,
allowInsecure: true,
sni: '',
certFile: '', certFile: '',
keyFile: '', keyFile: '',
caFile: '', caFile: '',

View File

@ -69,15 +69,15 @@ const usePreferencesStore = defineStore('preferences', {
return [ return [
{ {
value: 'light', value: 'light',
label: 'preferences.general.theme_light', label: i18nGlobal.t('preferences.general.theme_light'),
}, },
{ {
value: 'dark', value: 'dark',
label: 'preferences.general.theme_dark', label: i18nGlobal.t('preferences.general.theme_dark'),
}, },
{ {
value: 'auto', value: 'auto',
label: 'preferences.general.theme_auto', label: i18nGlobal.t('preferences.general.theme_auto'),
}, },
] ]
}, },
@ -93,7 +93,7 @@ const usePreferencesStore = defineStore('preferences', {
})) }))
options.splice(0, 0, { options.splice(0, 0, {
value: 'auto', value: 'auto',
label: 'preferences.general.system_lang', label: i18nGlobal.t('preferences.general.system_lang'),
}) })
return options return options
}, },
@ -110,7 +110,7 @@ const usePreferencesStore = defineStore('preferences', {
})) }))
option.splice(0, 0, { option.splice(0, 0, {
value: '', value: '',
label: 'preferences.general.default', label: i18nGlobal.t('preferences.general.default'),
path: '', path: '',
}) })
return option return option

View File

@ -7,25 +7,14 @@ export function useRender() {
* *
* @param {string|Object} icon * @param {string|Object} icon
* @param {{}} [props] * @param {{}} [props]
* @return {VNode} * @return {*}
*/ */
renderIcon: (icon, props = {}) => { renderIcon: (icon, props = {}) => {
if (icon == null) { return () => {
return undefined
}
return h(NIcon, null, { return h(NIcon, null, {
default: () => h(icon, props), default: () => h(icon, props),
}) })
}, }
/**
*
* @param {string} label
* @param {{}} [props]
* @return {VNode}
*/
renderLabel: (label, props = {}) => {
return h('div', props, label)
}, },
} }
} }

View File

@ -69,7 +69,6 @@ export const themeOverrides = {
padding: '6px 2px', padding: '6px 2px',
optionColorHover: '#D33A31', optionColorHover: '#D33A31',
optionTextColorHover: '#FFF', optionTextColorHover: '#FFF',
optionHeightMedium: '28px',
}, },
} }

6
go.mod
View File

@ -7,10 +7,10 @@ require (
github.com/andybalholm/brotli v1.0.6 github.com/andybalholm/brotli v1.0.6
github.com/google/uuid v1.5.0 github.com/google/uuid v1.5.0
github.com/klauspost/compress v1.17.4 github.com/klauspost/compress v1.17.4
github.com/redis/go-redis/v9 v9.4.0 github.com/redis/go-redis/v9 v9.3.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.7.1 github.com/wailsapp/wails/v2 v2.7.1
golang.org/x/crypto v0.18.0 golang.org/x/crypto v0.17.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
@ -44,7 +44,7 @@ require (
github.com/wailsapp/mimetype v1.4.1 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect
golang.org/x/net v0.19.0 // indirect golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.16.0 // indirect golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
) )

16
go.sum
View File

@ -68,8 +68,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.4.0 h1:Yzoz33UZw9I/mFhx4MNrB6Fk+XHO1VukNcCa1+lwyKk= github.com/redis/go-redis/v9 v9.3.1 h1:KqdY8U+3X6z+iACvumCNxnoluToB+9Me+TvyFa21Mds=
github.com/redis/go-redis/v9 v9.4.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/redis/go-redis/v9 v9.3.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=
@ -100,8 +100,8 @@ github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhw
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
github.com/wailsapp/wails/v2 v2.7.1 h1:HAzp2c5ODOzsLC6ZMDVtNOB72ozM7/SJecJPB2Ur+UU= github.com/wailsapp/wails/v2 v2.7.1 h1:HAzp2c5ODOzsLC6ZMDVtNOB72ozM7/SJecJPB2Ur+UU=
github.com/wailsapp/wails/v2 v2.7.1/go.mod h1:oIJVwwso5fdOgprBYWXBBqtx6PaSvxg8/KTQHNGkadc= github.com/wailsapp/wails/v2 v2.7.1/go.mod h1:oIJVwwso5fdOgprBYWXBBqtx6PaSvxg8/KTQHNGkadc=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8= golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8=
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@ -115,11 +115,11 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=