├── .github
└── workflows
│ └── releases_build.yaml
├── .gitignore
├── LICENSE
├── README.md
├── aa_test.go
├── app.go
├── backup
└── commadn.txt
├── build
├── README.md
├── appicon.png
├── darwin
│ └── Info.plist
└── windows
│ ├── icon.ico
│ ├── info.json
│ ├── installer
│ ├── project.nsi
│ └── wails_tools.nsh
│ └── wails.exe.manifest
├── common
├── consts
│ └── appConfig.go
└── structs
│ ├── BaseInfo.go
│ └── redis.go
├── frontend
├── .gitignore
├── favicon.ico
├── index.html
├── package.json
├── src
│ ├── App.vue
│ ├── Aside.vue
│ ├── Header.vue
│ ├── Welcome.vue
│ ├── assets
│ │ ├── css
│ │ │ ├── font.css
│ │ │ └── reset.css
│ │ ├── fonts
│ │ │ ├── JetBrainsMono-Bold.woff2
│ │ │ ├── JetBrainsMono-BoldItalic.woff2
│ │ │ ├── JetBrainsMono-ExtraBold.woff2
│ │ │ ├── JetBrainsMono-ExtraBoldItalic.woff2
│ │ │ ├── JetBrainsMono-ExtraLight.woff2
│ │ │ ├── JetBrainsMono-ExtraLightItalic.woff2
│ │ │ ├── JetBrainsMono-Italic.woff2
│ │ │ ├── JetBrainsMono-Light.woff2
│ │ │ ├── JetBrainsMono-LightItalic.woff2
│ │ │ ├── JetBrainsMono-Medium.woff2
│ │ │ ├── JetBrainsMono-MediumItalic.woff2
│ │ │ ├── JetBrainsMono-Regular.woff2
│ │ │ ├── JetBrainsMono-SemiBold.woff2
│ │ │ ├── JetBrainsMono-SemiBoldItalic.woff2
│ │ │ ├── JetBrainsMono-Thin.woff2
│ │ │ ├── JetBrainsMono-ThinItalic.woff2
│ │ │ ├── OFL.txt
│ │ │ └── nunito-v16-latin-regular.woff2
│ │ ├── images
│ │ │ ├── comeon.gif
│ │ │ ├── logo-universal.png
│ │ │ └── quick
│ │ │ │ ├── about.png
│ │ │ │ ├── conn.png
│ │ │ │ ├── export.png
│ │ │ │ ├── import.png
│ │ │ │ ├── select.png
│ │ │ │ └── table.png
│ │ ├── line.png
│ │ ├── logo.png
│ │ └── logos
│ │ │ └── logo.png
│ ├── i18n
│ │ ├── index.js
│ │ └── messages
│ │ │ ├── en.json
│ │ │ ├── fr.json
│ │ │ └── zh-Hans.json
│ ├── index.html
│ ├── main.css
│ ├── main.js
│ ├── public
│ │ ├── favicon.ico
│ │ ├── info
│ │ │ ├── close.png
│ │ │ └── key.png
│ │ ├── leftNavigation
│ │ │ └── redis.png
│ │ └── status
│ │ │ ├── history.png
│ │ │ ├── kv.png
│ │ │ ├── memory.png
│ │ │ └── service.png
│ ├── router
│ │ └── index.js
│ ├── views
│ │ ├── pop
│ │ │ ├── AddListValue.vue
│ │ │ └── NewConnection.vue
│ │ └── redis
│ │ │ ├── Content_hash_info.vue
│ │ │ ├── Content_list_info.vue
│ │ │ ├── Content_set_info.vue
│ │ │ ├── Content_status.vue
│ │ │ ├── Content_stream_info.vue
│ │ │ ├── Content_string_info.vue
│ │ │ └── Content_zset_info.vue
│ └── wailsjs
│ │ ├── go
│ │ ├── bindings.d.ts
│ │ ├── bindings.js
│ │ ├── models.ts
│ │ └── package.json
│ │ └── runtime
│ │ ├── ipcdev.js
│ │ ├── package.json
│ │ ├── runtime.d.ts
│ │ ├── runtime.js
│ │ └── runtimedev.js
├── vite.config.js
└── wailsjs
│ └── runtime
│ ├── ipcdev.js
│ ├── package.json
│ ├── runtime.d.ts
│ ├── runtime.js
│ └── runtimedev.js
├── go.mod
├── go.sum
├── jb_beam.png
├── kit
├── dialog.go
├── os
│ ├── file.go
│ └── os_test.go
├── redis
│ ├── redis.go
│ └── redis_test.go
├── response.go
├── strKit.go
└── update.go
├── main.go
├── menu
├── macOSMenu.go
├── menu.go
└── winMenu.go
├── scripts
├── build-macos-arm.sh
├── build-macos-intel.sh
├── build-macos.sh
├── build-windows.sh
├── build.sh
└── install-wails-cli.sh
├── service
├── general.go
└── redis.go
├── todb.png
└── wails.json
/.github/workflows/releases_build.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | tags:
4 | - "v*"
5 | jobs:
6 | package:
7 | strategy:
8 | matrix:
9 | go-version: [1.17]
10 | os: [macos-11, windows-latest]
11 | runs-on: ${{ matrix.os }}
12 | steps:
13 | - name: Install Go
14 | uses: actions/setup-go@v2
15 | with:
16 | go-version: ${{ matrix.go-version }}
17 | - name: Checkout code
18 | uses: actions/checkout@v2
19 | - name: Set Version
20 | run: echo "VERSION=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
21 | # - name: Get Wails dependencies
22 | # run: sudo apt update && sudo apt install -y libgtk-3-dev libwebkit2gtk-4.0-dev
23 | # if: matrix.os == 'ubuntu-latest'
24 | - name: Get Wails
25 | run: go install github.com/wailsapp/wails/v2/cmd/wails@v2.0.0-beta.34
26 |
27 | # - name: Import Code-Signing Certificates
28 | # uses: Apple-Actions/import-codesign-certs@v1
29 | # with:
30 | # # The certificates in a PKCS12 file encoded as a base64 string
31 | # p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}
32 | # # The password used to import the PKCS12 file.
33 | # p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }}
34 | if: matrix.os == 'macos-11'
35 |
36 | - name: Install gon via HomeBrew for code signing and app notarization
37 | run: |
38 | brew tap mitchellh/gon
39 | brew install mitchellh/gon/gon
40 | if: matrix.os == 'macos-11'
41 |
42 | - name: Build and Sign MacOS Binaries
43 | # env:
44 | # AC_USERNAME: ${{ secrets.AC_USERNAME }}
45 | # AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
46 | run: |
47 | ./build-macos.sh
48 | if: matrix.os == 'macos-11'
49 | # - name: Build package linux
50 | # run: |
51 | # export PATH=$PATH:$(go env GOPATH)/bin
52 | # echo "building on ${{ matrix.os }}"
53 | # echo ${{ env.GITHUB_REF }}
54 | # echo ${{ env.GITHUB_HEAD_REF }}
55 | # mkdir -p ~/.wails
56 | # cp wails.json ~/.wails/
57 | # export LOG_LEVEL=debug
58 | # export GODEBUG=1
59 | # wails build
60 | # tar -czvf riftshare.tar.gz ./build/riftshare
61 | # # wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
62 | # # chmod +x linuxdeploy*.AppImage
63 | # # ls ./
64 | # # ./linuxdeploy*.AppImage --appdir AppDir --executable ./build/riftshare --desktop-file=riftshare.AppImage.desktop --icon-file=appicon--512.png --output appimage
65 | # if: matrix.os == 'ubuntu-latest'
66 | - name: Build package windows
67 | run: |
68 | $GP = (go env GOPATH)
69 | $env:path = "$env:path;$GP\bin"
70 | echo "building on ${{ matrix.os }}"
71 | choco install mingw
72 | wails build -platform windows/amd64 -clean
73 | Compress-Archive -Path .\build\bin\ToDb.exe -DestinationPath .\ToDb-windows-amd64.zip
74 | if: matrix.os == 'windows-latest'
75 | - name: upload artifacts macOS-AMD64
76 | uses: actions/upload-artifact@v2
77 | with:
78 | name: todb-macOS
79 | path: ToDb-*.zip
80 | if: matrix.os == 'macos-11'
81 | # - name: upload artifact linux
82 | # uses: actions/upload-artifact@v2-preview
83 | # with:
84 | # name: riftshare-linux
85 | # path: riftshare.tar.gz
86 | # if: matrix.os == 'ubuntu-latest'
87 | # - name: upload artifact linux appimage
88 | # uses: actions/upload-artifact@v2-preview
89 | # with:
90 | # name: riftshare-linux-appimage
91 | # path: riftshare-${{ env.VERSION }}-x86_64.AppImage
92 | # if: matrix.os == 'ubuntu-latest'
93 | - name: upload artifact windows
94 | uses: actions/upload-artifact@v2
95 | with:
96 | name: todb-windows
97 | path: ToDb-windows-amd64.zip
98 | if: matrix.os == 'windows-latest'
99 |
100 | release:
101 | runs-on: ubuntu-latest
102 | needs: package
103 | steps:
104 | - name: Download Windows Package
105 | uses: actions/download-artifact@v2
106 | with:
107 | name: todb-windows
108 | - name: Download macOS packages
109 | uses: actions/download-artifact@v2
110 | with:
111 | name: todb-macOS
112 | - name: Create Release
113 | id: create_release
114 | uses: "marvinpinto/action-automatic-releases@latest"
115 | with:
116 | repo_token: "${{ secrets.GITHUB_TOKEN }}"
117 | prerelease: false
118 | files: ToDb*.zip
119 | # - name: Download linux package
120 | # uses: actions/download-artifact@v1
121 | # with:
122 | # name: riftshare-linux
123 | # - name: Upload Linux package to release
124 | # id: upload-linux-release-asset
125 | # uses: actions/upload-release-asset@v1
126 | # env:
127 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
128 | # with:
129 | # upload_url: ${{ steps.create_release.outputs.upload_url }}
130 | # asset_path: ./riftshare-linux/riftshare.tar.gz
131 | # asset_name: riftshare_${{ github.ref }}_linux_x86_64.tar.gz
132 | # asset_content_type: application/octet-stream
133 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/ToDb.iml
2 | .vscode/settings.json
3 | build/bin/ToDb.app/Contents/Info.plist
4 | build/bin/ToDb.app/Contents/MacOS/ToDb
5 | build/bin/ToDb.app/Contents/Resources/iconfile.icns
6 | .idea/ToDb.iml
7 | .idea/
8 | .history/
9 | node_modules/
10 | build/bin/
11 | .gitignore
12 | /frontend/package-lock.json
13 | /frontend/package.json.md5
14 | backup/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | 木兰宽松许可证, 第2版
2 |
3 | 木兰宽松许可证, 第2版
4 | 2020年1月 http://license.coscl.org.cn/MulanPSL2
5 |
6 |
7 | 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束:
8 |
9 | 0. 定义
10 |
11 | “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。
12 |
13 | “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。
14 |
15 | “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。
16 |
17 | “法人实体”是指提交贡献的机构及其“关联实体”。
18 |
19 | “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。
20 |
21 | 1. 授予版权许可
22 |
23 | 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。
24 |
25 | 2. 授予专利许可
26 |
27 | 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。
28 |
29 | 3. 无商标许可
30 |
31 | “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。
32 |
33 | 4. 分发限制
34 |
35 | 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。
36 |
37 | 5. 免责声明与责任限制
38 |
39 | “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。
40 |
41 | 6. 语言
42 | “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。
43 |
44 | 条款结束
45 |
46 | 如何将木兰宽松许可证,第2版,应用到您的软件
47 |
48 | 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步:
49 |
50 | 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字;
51 |
52 | 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中;
53 |
54 | 3, 请将如下声明文本放入每个源文件的头部注释中。
55 |
56 | Copyright (c) [Year] [name of copyright holder]
57 | [Software Name] is licensed under Mulan PSL v2.
58 | You can use this software according to the terms and conditions of the Mulan PSL v2.
59 | You may obtain a copy of Mulan PSL v2 at:
60 | http://license.coscl.org.cn/MulanPSL2
61 | THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
62 | See the Mulan PSL v2 for more details.
63 |
64 |
65 | Mulan Permissive Software License,Version 2
66 |
67 | Mulan Permissive Software License,Version 2 (Mulan PSL v2)
68 | January 2020 http://license.coscl.org.cn/MulanPSL2
69 |
70 | Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions:
71 |
72 | 0. Definition
73 |
74 | Software means the program and related documents which are licensed under this License and comprise all Contribution(s).
75 |
76 | Contribution means the copyrightable work licensed by a particular Contributor under this License.
77 |
78 | Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License.
79 |
80 | Legal Entity means the entity making a Contribution and all its Affiliates.
81 |
82 | Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity.
83 |
84 | 1. Grant of Copyright License
85 |
86 | Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not.
87 |
88 | 2. Grant of Patent License
89 |
90 | Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken.
91 |
92 | 3. No Trademark License
93 |
94 | No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4.
95 |
96 | 4. Distribution Restriction
97 |
98 | You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software.
99 |
100 | 5. Disclaimer of Warranty and Limitation of Liability
101 |
102 | THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
103 |
104 | 6. Language
105 |
106 | THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL.
107 |
108 | END OF THE TERMS AND CONDITIONS
109 |
110 | How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software
111 |
112 | To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps:
113 |
114 | i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner;
115 |
116 | ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package;
117 |
118 | iii Attach the statement to the appropriate annotated syntax at the beginning of each source file.
119 |
120 |
121 | Copyright (c) [Year] [name of copyright holder]
122 | [Software Name] is licensed under Mulan PSL v2.
123 | You can use this software according to the terms and conditions of the Mulan PSL v2.
124 | You may obtain a copy of Mulan PSL v2 at:
125 | http://license.coscl.org.cn/MulanPSL2
126 | THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
127 | See the Mulan PSL v2 for more details.
128 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # `ToDb`
6 |
7 | `ToDb`一款连接数据库的工具
8 |
9 | ## 特点
10 |
11 | - 支持多种数据库
12 | - 全平台
13 | - 配置可视化
14 |
15 | ## 准备处理的数据库
16 |
17 | - [x] `Redis`
18 | - [ ] `MySQL`
19 | - [ ] ......
20 |
21 | ## 预览
22 |
23 | 
24 |
25 | 
26 |
27 | ## 常见问题
28 |
29 | - 它是什么?
30 |
31 | 这是一款数据库连接工具,可以连接`Redis`、`MySQL`等数据库,可视化处理
32 |
33 | - 这个项目针对的是哪些人?
34 |
35 | 这个项目针对的是程序员,但是也有非程序员的使用者,比如`DBA`、管理员等
36 |
37 | ## 贡献者
38 |
39 | ---
40 |
41 |
42 |
43 |
44 | ## 特别提及
45 |
46 | 如果没有以下成员,此项目或许就该胎死腹中了:
47 |
48 | - [reciment](https://gitee.com/recimentPackage)
49 | - [ProudMuBai](https://gitee.com/proudmubai)
50 |
51 | ## 特别感谢
52 |
53 | A special thank you to JetBrains for donating licenses to us!
54 | Please click the logo to let them know your appreciation!
55 |
56 |
57 |
--------------------------------------------------------------------------------
/aa_test.go:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: symbol
3 | * @Date: 2022-05-04 10:22:52
4 | * @LastEditors: symbol
5 | * @LastEditTime: 2022-05-19 17:15:31
6 | * @FilePath: /todb/aa_test.go
7 | * @Description:
8 | *
9 | * Copyright (c) 2022 by symbol, All Rights Reserved.
10 | */
11 | package main
12 |
13 | import (
14 | "ToDb/kit"
15 | "ToDb/service"
16 | "context"
17 | "fmt"
18 | "testing"
19 | )
20 |
21 | func TestTt(t *testing.T) {
22 | aa := `{"alias":"11","hostURL":"11","port":"11","username":"11","password":"11","savePassword":true}`
23 | service.Redis().Ok(context.Background(), aa)
24 | }
25 |
26 | func TestReadFile(t *testing.T) {
27 | //communication.LoadingBaseHistoryInfo()
28 | service.Redis().LoadingHistoryInfo("这是2")
29 | }
30 |
31 | func TestGetHistoryInfo(t *testing.T) {
32 | fmt.Println(service.Redis().LoadingHistoryInfo("这是2"))
33 | }
34 |
35 | func TestFilePath(t *testing.T) {
36 | fmt.Println(service.Redis().LoadingBaseHistoryInfo(context.Background()))
37 | }
38 |
39 | func TestTest(t *testing.T) {
40 | //redis返回数据: [1:2:3, 1:2:4, 1111, 12312]
41 | //sl := []string{"1:2:3:9:5", "1:2:4:6", "1111", "12312:333"}
42 | sl := []string{"234234", "1:2:4", "1:2:3", "1111:33333", "12312", "1:2:5", "1111:2222"}
43 | v := kit.StrKit().PackageTree(sl)
44 | fmt.Printf("%s\n", v)
45 | }
46 |
47 | func TestMP(t *testing.T) {
48 | //v := []int{0, 2, 2, 0, 0}
49 | sl := []string{"234234", "1:2:4", "1:2:3", "1111:33333", "12312", "1:2:5", "1111:2222"}
50 | fmt.Println(kit.StrKit().BubbleDescSort(sl))
51 | }
52 |
53 | func TestApp_GetNodeData(t *testing.T) {
54 | fmt.Println(service.Redis().GetNodeData(context.Background(), "redis", "localhost", "13"))
55 | }
56 |
--------------------------------------------------------------------------------
/app.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "ToDb/kit"
5 | "ToDb/menu"
6 | communication "ToDb/service"
7 | "context"
8 | "encoding/json"
9 | "errors"
10 | "net/http"
11 | "strings"
12 |
13 | "github.com/tidwall/gjson"
14 |
15 | "github.com/wailsapp/wails/v2/pkg/runtime"
16 | )
17 |
18 | // App struct
19 | type App struct {
20 | ctx context.Context
21 | }
22 |
23 | // NewApp creates a new App application struct
24 | // NewApp 创建一个新的 App 应用程序
25 | func NewApp() *App {
26 | return &App{}
27 | }
28 |
29 | // startup is called at application startup
30 | // startup 在应用程序启动时调用
31 | func (a *App) startup(ctx context.Context) {
32 | // Perform your setup here
33 | // 在这里执行初始化设置
34 | a.ctx = ctx
35 | menu.InitMenu(ctx, icon)
36 | }
37 |
38 | // domReady is called after the front-end dom has been loaded
39 | // domReady 在前端Dom加载完毕后调用
40 | func (a *App) domReady(ctx context.Context) {
41 | // Add your action here
42 | // 在这里添加你的操作
43 | }
44 |
45 | // beforeClose is called when the application is about to quit,
46 | // either by clicking the window close button or calling runtime.Quit.
47 | // Returning true will cause the application to continue,
48 | // false will continue shutdown as normal.
49 | // beforeClose在单击窗口关闭按钮或调用runtime.Quit即将退出应用程序时被调用.
50 | // 返回 true 将导致应用程序继续,false 将继续正常关闭。
51 | func (a *App) beforeClose(ctx context.Context) (prevent bool) {
52 | return false
53 | }
54 |
55 | // shutdown is called at application termination
56 | // 在应用程序终止时被调用
57 | func (a *App) shutdown(ctx context.Context) {
58 | // Perform your teardown here
59 | // 在此处做一些资源释放的操作
60 | }
61 |
62 | // ImportConn 导入
63 | func (a *App) ImportConn() {
64 | err := communication.General().ImportConn(a.ctx)
65 | if err != nil {
66 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", err.Error(), icon)
67 | return
68 | }
69 | kit.DiaLogKit().DefaultDialog(a.ctx, "成功", "导入成功", icon)
70 | // 导入成功后窗口重载
71 | runtime.WindowReload(a.ctx)
72 | }
73 |
74 | // ExportConn 导出
75 | func (a *App) ExportConn() {
76 | communication.General().ExportConn(a.ctx)
77 | }
78 |
79 | // TestConnection 测试连接
80 | func (a *App) TestConnection(connectionInfo string) {
81 | //var responseJson lib.JsonResponse
82 | code, message := communication.Redis().RedisPing(connectionInfo)
83 | if code != http.StatusOK {
84 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", message, icon)
85 | } else {
86 | kit.DiaLogKit().DefaultDialog(a.ctx, "成功", message, icon)
87 | }
88 | }
89 |
90 | // Ok 确定按钮进行的操作
91 | func (a App) Ok(connectionInfo string) string {
92 | var responseJson kit.JsonResponse
93 | code, message := communication.Redis().Ok(a.ctx, connectionInfo)
94 | responseJson = kit.JsonResponse{
95 | Code: code,
96 | Message: message,
97 | }
98 | if code != http.StatusOK {
99 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", message, icon)
100 | }
101 | runtime.WindowReload(a.ctx)
102 | return responseJson.String()
103 | }
104 |
105 | // LoadingConnKey 加载已保存的连接信息
106 | func (a *App) LoadingConnKey() string {
107 | return communication.Redis().LoadingBaseHistoryInfo(a.ctx)
108 | }
109 |
110 | // LoadingConnInfo 获取链接信息详情
111 | func (a *App) LoadingConnInfo(dbType, fileName string) string {
112 | var code int
113 | var message string
114 | switch dbType {
115 | case "redis":
116 | code, message = communication.Redis().LoadingHistoryInfo(fileName)
117 | default:
118 | code = http.StatusNotFound
119 | message = "暂不支持的数据库类型"
120 | }
121 | if code != http.StatusOK {
122 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", message, icon)
123 | return ""
124 | }
125 | return message
126 | }
127 |
128 | // LoadingDbResource 加载数据库资源消耗信息
129 | func (a *App) LoadingDbResource(key string) string {
130 | return communication.Redis().LoadingDbResource(a.ctx, key)
131 | }
132 |
133 | // ChangeRightWindowStyle 改变右侧窗口样式
134 | func (a *App) ChangeRightWindowStyle(parentNode, nextParentNode, node string) string {
135 | // 连接类型
136 | connType := gjson.Get(parentNode, "connType").String()
137 | // 文件名
138 | fileName := gjson.Get(parentNode, "title").String()
139 | switch connType {
140 | case "redis":
141 | default:
142 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", "暂不支持的数据库类型", icon)
143 | return ""
144 | }
145 | // 获取db信息
146 | dbId := gjson.Get(nextParentNode, "key").String()
147 | // 获取指定的节点key
148 | fullKey := gjson.Get(node, "fullStr").String()
149 | // 指定的key数据类型
150 | dataType, err := communication.Redis().GetValueType(a.ctx, fileName, dbId, fullKey)
151 | if err != nil {
152 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", err.Error(), icon)
153 | }
154 | return strings.ToLower(dataType)
155 | }
156 |
157 | // GetNodeData 获取节点数据
158 | func (a *App) GetNodeData(connType, connName, nodeIdStr string) string {
159 | strs := ""
160 | var err error
161 | switch connType {
162 | case "redis":
163 | // 获取redis节点数据
164 | strs, err = communication.Redis().GetNodeData(a.ctx, connType, connName, nodeIdStr)
165 | default:
166 | err = errors.New("暂不支持此连接类型")
167 | }
168 | if err != nil {
169 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", err.Error(), icon)
170 | }
171 | if strs == "null" {
172 | strs = ""
173 | }
174 | return strs
175 | }
176 |
177 | // RedisGetData 从redis获取数据
178 | func (a *App) RedisGetData(connType, connName, nodeIdStr, key string) string {
179 | v := ""
180 | switch connType {
181 | case "redis":
182 | // 获取redis节点数据
183 | getValue, err := communication.Redis().RedisGetData(a.ctx, connType, connName, nodeIdStr, key)
184 | if err != nil {
185 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", err.Error(), icon)
186 | return ""
187 | }
188 | _v, _ := json.Marshal(getValue)
189 | v = string(_v)
190 | default:
191 | v = "暂不支持"
192 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", v, icon)
193 | return v
194 | }
195 | return v
196 | }
197 |
198 | // RedisReName redis key重命名
199 | func (a *App) RedisReName(connType, connName, nodeIdStr, oldKey, newKey string) {
200 | v := ""
201 | switch connType {
202 | case "redis":
203 | v = communication.Redis().RedisReName(a.ctx, connType, connName,
204 | nodeIdStr, oldKey, newKey)
205 | default:
206 | v = "暂不支持"
207 | }
208 | if v != "success" {
209 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", v, icon)
210 | } else {
211 | kit.DiaLogKit().DefaultDialog(a.ctx, "成功", "修改成功", icon)
212 | }
213 | }
214 |
215 | // RedisUpTtl 更新redis剩余时间
216 | func (a *App) RedisUpTtl(connType, connName, nodeIdStr, key, ttlStr string) {
217 | v := ""
218 | switch connType {
219 | case "redis":
220 | v = communication.Redis().RedisUpTtl(a.ctx, connType, connName, nodeIdStr, key, ttlStr)
221 | default:
222 | v = "暂不支持"
223 | }
224 | if v != "success" {
225 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", v, icon)
226 | } else {
227 | kit.DiaLogKit().DefaultDialog(a.ctx, "成功", "修改成功", icon)
228 | }
229 | }
230 |
231 | // RedisDelKey 删除键
232 | func (a *App) RedisDelKey(connType, connName, nodeIdStr, key string) {
233 | selection, _ := runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
234 | Type: runtime.InfoDialog,
235 | Title: "删除",
236 | Message: "确定删除该key吗?",
237 | Buttons: []string{"Cancel", "Ok"},
238 | })
239 | if selection != "Ok" {
240 | return
241 | }
242 | v := communication.Redis().RedisDel(a.ctx, connType, connName, nodeIdStr, key)
243 |
244 | if v != "success" {
245 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", v, icon)
246 | } else {
247 | kit.DiaLogKit().DefaultDialog(a.ctx, "成功", "删除成功", icon)
248 | }
249 | }
250 |
251 | // RedisSaveStringValue 更新redis值
252 | func (a *App) RedisSaveStringValue(connType, connName, nodeIdStr, key, value, ttl string) {
253 | var err error
254 | switch connType {
255 | case "redis":
256 | err = communication.Redis().RedisUpdateStringValue(a.ctx, connType, connName,
257 | nodeIdStr, key, value, ttl)
258 | default:
259 | err = errors.New("暂不支持")
260 | }
261 | if err != nil {
262 | kit.DiaLogKit().DefaultDialog(a.ctx, "错误", err.Error(), icon)
263 | } else {
264 | kit.DiaLogKit().DefaultDialog(a.ctx, "成功", "修改成功", icon)
265 | }
266 | }
267 |
--------------------------------------------------------------------------------
/backup/commadn.txt:
--------------------------------------------------------------------------------
1 | string
2 | SET "1:2:34" "你好啊😂"
3 |
4 | hash
5 | HMSET "1:2:hash" "New field" "New value" "123" "321"
6 |
7 | list
8 | RPUSH "1:2:list" "New member" "12312213"
9 |
10 | set
11 | SADD "1:2:set" "New member" "sdfsdf"
12 |
13 | stream
14 | XADD "1:2:stream" 1650445322163-0 "New key" "New value"
15 | XADD "1:2:stream" 21312312312312-0 "New key" "New value"
16 |
17 | zset
18 | ZADD "1:2:zset" 12 "321" 0 "New member"
--------------------------------------------------------------------------------
/build/README.md:
--------------------------------------------------------------------------------
1 | # Build Directory
2 |
3 | The build directory is used to house all the build files and assets for your application.
4 |
5 | The structure is:
6 |
7 | * bin - Output directory
8 | * dialog - Icons for dialogs
9 | * tray - Icons for the system tray
10 | * mac - MacOS specific files
11 | * linux - Linux specific files
12 | * windows - Windows specific files
13 |
14 | ## Dialog Icons
15 |
16 | Place any PNG file in this directory to be able to use them in message dialogs.
17 | The files should have names in the following format: `name[-(light|dark)][2x].png`
18 |
19 | Examples:
20 |
21 | * `mypic.png` - Standard definition icon with ID `mypic`
22 | * `mypic-light.png` - Standard definition icon with ID `mypic`, used when system theme is light
23 | * `mypic-dark.png` - Standard definition icon with ID `mypic`, used when system theme is dark
24 | * `mypic2x.png` - High definition icon with ID `mypic`
25 | * `mypic-light2x.png` - High definition icon with ID `mypic`, used when system theme is light
26 | * `mypic-dark2x.png` - High definition icon with ID `mypic`, used when system theme is dark
27 |
28 | ### Order of preference
29 |
30 | Icons are selected with the following order of preference:
31 |
32 | For High Definition displays:
33 | * name-(theme)2x.png
34 | * name2x.png
35 | * name-(theme).png
36 | * name.png
37 |
38 | For Standard Definition displays:
39 | * name-(theme).png
40 | * name.png
41 |
42 | ## Tray
43 |
44 | Place any PNG file in this directory to be able to use them as tray icons.
45 | The name of the filename will be the ID to reference the image.
46 |
47 | Example:
48 |
49 | * `mypic.png` - May be referenced using `runtime.Tray.SetIcon("mypic")`
50 |
51 | ## Mac
52 |
53 | The `darwin` directory holds files specific to Mac builds, such as `Info.plist`.
54 | These may be customised and used as part of the build. To return these files to the default state, simply delete them and
55 | build with the `-package` flag.
56 |
57 | ## Windows
58 |
59 | The `windows` directory contains the manifest and rc files used when building with the `-package` flag.
60 | These may be customised for your application. To return these files to the default state, simply delete them and
61 | build with the `-package` flag.
--------------------------------------------------------------------------------
/build/appicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/build/appicon.png
--------------------------------------------------------------------------------
/build/darwin/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 | CFBundlePackageType APPL
4 | CFBundleName {{.Info.ProductName}}
5 | CFBundleExecutable {{.Name}}
6 | CFBundleIdentifier com.wails.{{.Name}}
7 | CFBundleVersion {{.Info.ProductVersion}}
8 | CFBundleGetInfoString {{.Info.Comments}}
9 | CFBundleShortVersionString {{.Info.ProductVersion}}
10 | CFBundleIconFile iconfile
11 | LSMinimumSystemVersion 10.13.0
12 | NSHighResolutionCapable true
13 | NSHumanReadableCopyright {{.Info.Copyright}}
14 |
--------------------------------------------------------------------------------
/build/windows/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/build/windows/icon.ico
--------------------------------------------------------------------------------
/build/windows/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "fixed": {
3 | "file_version": "{{.Info.ProductVersion}}"
4 | },
5 | "info": {
6 | "0000": {
7 | "ProductVersion": "{{.Info.ProductVersion}}",
8 | "CompanyName": "{{.Info.CompanyName}}",
9 | "FileDescription": "{{.Info.ProductName}}",
10 | "LegalCopyright": "{{.Info.Copyright}}",
11 | "ProductName": "{{.Info.ProductName}}",
12 | "Comments": "{{.Info.Comments}}"
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/build/windows/installer/project.nsi:
--------------------------------------------------------------------------------
1 | Unicode true
2 |
3 | ####
4 | ## Please note: Template replacements don't work in this file. They are provided with default defines like
5 | ## mentioned underneath.
6 | ## If the keyword is not defined, "wails_tools.nsh" will populate them with the values from ProjectInfo.
7 | ## If they are defined here, "wails_tools.nsh" will not touch them. This allows to use this project.nsi manually
8 | ## from outside of Wails for debugging and development of the installer.
9 | ##
10 | ## For development first make a wails nsis build to populate the "wails_tools.nsh":
11 | ## > wails build --target windows/amd64 --nsis
12 | ## Then you can call makensis on this file with specifying the path to your binary:
13 | ## For a AMD64 only installer:
14 | ## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe
15 | ## For a ARM64 only installer:
16 | ## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe
17 | ## For a installer with both architectures:
18 | ## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe
19 | ####
20 | ## The following information is taken from the ProjectInfo file, but they can be overwritten here.
21 | ####
22 | ## !define INFO_PROJECTNAME "MyProject" # Default "{{.Name}}"
23 | ## !define INFO_COMPANYNAME "MyCompany" # Default "{{.Info.CompanyName}}"
24 | ## !define INFO_PRODUCTNAME "MyProduct" # Default "{{.Info.ProductName}}"
25 | ## !define INFO_PRODUCTVERSION "1.0.0" # Default "{{.Info.ProductVersion}}"
26 | ## !define INFO_COPYRIGHT "Copyright" # Default "{{.Info.Copyright}}"
27 | ###
28 | ## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe"
29 | ## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
30 | ####
31 | ## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html
32 | ####
33 | ## Include the wails tools
34 | ####
35 | !include "wails_tools.nsh"
36 |
37 | # The version information for this two must consist of 4 parts
38 | VIProductVersion "${INFO_PRODUCTVERSION}.0"
39 | VIFileVersion "${INFO_PRODUCTVERSION}.0"
40 |
41 | VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}"
42 | VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer"
43 | VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}"
44 | VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}"
45 | VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}"
46 | VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
47 |
48 | !include "MUI.nsh"
49 |
50 | !define MUI_ICON "..\icon.ico"
51 | !define MUI_UNICON "..\icon.ico"
52 | # !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314
53 | !define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps
54 | !define MUI_ABORTWARNING # This will warn the user if they exit from the installer.
55 |
56 | !insertmacro MUI_PAGE_WELCOME # Welcome to the installer page.
57 | # !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer
58 | !insertmacro MUI_PAGE_DIRECTORY # In which folder install page.
59 | !insertmacro MUI_PAGE_INSTFILES # Installing page.
60 | !insertmacro MUI_PAGE_FINISH # Finished installation page.
61 |
62 | !insertmacro MUI_UNPAGE_INSTFILES # Uinstalling page
63 |
64 | !insertmacro MUI_LANGUAGE "English" # Set the Language of the installer
65 |
66 | ## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1
67 | #!uninstfinalize 'signtool --file "%1"'
68 | #!finalize 'signtool --file "%1"'
69 |
70 | Name "${INFO_PRODUCTNAME}"
71 | OutFile "..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file.
72 | InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder).
73 | ShowInstDetails show # This will always show the installation details.
74 |
75 | Function .onInit
76 | !insertmacro wails.checkArchitecture
77 | FunctionEnd
78 |
79 | Section
80 | !insertmacro wails.webview2runtime
81 |
82 | SetOutPath $INSTDIR
83 |
84 | !insertmacro wails.files
85 |
86 | CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
87 | CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
88 |
89 | !insertmacro wails.writeUninstaller
90 | SectionEnd
91 |
92 | Section "uninstall"
93 | RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath
94 |
95 | RMDir /r $INSTDIR
96 |
97 | Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk"
98 | Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk"
99 |
100 | !insertmacro wails.deleteUninstaller
101 | SectionEnd
102 |
--------------------------------------------------------------------------------
/build/windows/installer/wails_tools.nsh:
--------------------------------------------------------------------------------
1 | # DO NOT EDIT - Generated automatically by `wails build`
2 |
3 | !include "x64.nsh"
4 | !include "WinVer.nsh"
5 | !include "FileFunc.nsh"
6 |
7 | !ifndef INFO_PROJECTNAME
8 | !define INFO_PROJECTNAME "{{.Name}}"
9 | !endif
10 | !ifndef INFO_COMPANYNAME
11 | !define INFO_COMPANYNAME "{{.Info.CompanyName}}"
12 | !endif
13 | !ifndef INFO_PRODUCTNAME
14 | !define INFO_PRODUCTNAME "{{.Info.ProductName}}"
15 | !endif
16 | !ifndef INFO_PRODUCTVERSION
17 | !define INFO_PRODUCTVERSION "{{.Info.ProductVersion}}"
18 | !endif
19 | !ifndef INFO_COPYRIGHT
20 | !define INFO_COPYRIGHT "{{.Info.Copyright}}"
21 | !endif
22 | !ifndef PRODUCT_EXECUTABLE
23 | !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe"
24 | !endif
25 | !ifndef UNINST_KEY_NAME
26 | !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
27 | !endif
28 | !define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}"
29 |
30 | !ifndef REQUEST_EXECUTION_LEVEL
31 | !define REQUEST_EXECUTION_LEVEL "admin"
32 | !endif
33 |
34 | RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
35 |
36 | !ifdef ARG_WAILS_AMD64_BINARY
37 | !define SUPPORTS_AMD64
38 | !endif
39 |
40 | !ifdef ARG_WAILS_ARM64_BINARY
41 | !define SUPPORTS_ARM64
42 | !endif
43 |
44 | !ifdef SUPPORTS_AMD64
45 | !ifdef SUPPORTS_ARM64
46 | !define ARCH "amd64_arm64"
47 | !else
48 | !define ARCH "amd64"
49 | !endif
50 | !else
51 | !ifdef SUPPORTS_ARM64
52 | !define ARCH "arm64"
53 | !else
54 | !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY"
55 | !endif
56 | !endif
57 |
58 | !macro wails.checkArchitecture
59 | !ifndef WAILS_WIN10_REQUIRED
60 | !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later."
61 | !endif
62 |
63 | !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED
64 | !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}"
65 | !endif
66 |
67 | ${If} ${AtLeastWin10}
68 | !ifdef SUPPORTS_AMD64
69 | ${if} ${IsNativeAMD64}
70 | Goto ok
71 | ${EndIf}
72 | !endif
73 |
74 | !ifdef SUPPORTS_ARM64
75 | ${if} ${IsNativeARM64}
76 | Goto ok
77 | ${EndIf}
78 | !endif
79 |
80 | IfSilent silentArch notSilentArch
81 | silentArch:
82 | SetErrorLevel 65
83 | Abort
84 | notSilentArch:
85 | MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}"
86 | Quit
87 | ${else}
88 | IfSilent silentWin notSilentWin
89 | silentWin:
90 | SetErrorLevel 64
91 | Abort
92 | notSilentWin:
93 | MessageBox MB_OK "${WAILS_WIN10_REQUIRED}"
94 | Quit
95 | ${EndIf}
96 |
97 | ok:
98 | !macroend
99 |
100 | !macro wails.files
101 | !ifdef SUPPORTS_AMD64
102 | ${if} ${IsNativeAMD64}
103 | File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}"
104 | ${EndIf}
105 | !endif
106 |
107 | !ifdef SUPPORTS_ARM64
108 | ${if} ${IsNativeARM64}
109 | File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}"
110 | ${EndIf}
111 | !endif
112 | !macroend
113 |
114 | !macro wails.writeUninstaller
115 | WriteUninstaller "$INSTDIR\uninstall.exe"
116 |
117 | SetRegView 64
118 | WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}"
119 | WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}"
120 | WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}"
121 | WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}"
122 | WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
123 | WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
124 |
125 | ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
126 | IntFmt $0 "0x%08X" $0
127 | WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0"
128 | !macroend
129 |
130 | !macro wails.deleteUninstaller
131 | Delete "$INSTDIR\uninstall.exe"
132 |
133 | SetRegView 64
134 | DeleteRegKey HKLM "${UNINST_KEY}"
135 | !macroend
136 |
137 | # Install webview2 by launching the bootstrapper
138 | # See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment
139 | !macro wails.webview2runtime
140 | !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT
141 | !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime"
142 | !endif
143 |
144 | SetRegView 64
145 | # If the admin key exists and is not empty then webview2 is already installed
146 | ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
147 | ${If} $0 != ""
148 | Goto ok
149 | ${EndIf}
150 |
151 | ${If} ${REQUEST_EXECUTION_LEVEL} == "user"
152 | # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed
153 | ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
154 | ${If} $0 != ""
155 | Goto ok
156 | ${EndIf}
157 | ${EndIf}
158 |
159 | SetDetailsPrint both
160 | DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}"
161 | SetDetailsPrint listonly
162 |
163 | InitPluginsDir
164 | CreateDirectory "$pluginsdir\webview2bootstrapper"
165 | SetOutPath "$pluginsdir\webview2bootstrapper"
166 | File "tmp\MicrosoftEdgeWebview2Setup.exe"
167 | ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install'
168 |
169 | SetDetailsPrint both
170 | ok:
171 | !macroend
--------------------------------------------------------------------------------
/build/windows/wails.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | true/pm
12 | permonitorv2,permonitor
13 |
14 |
15 |
--------------------------------------------------------------------------------
/common/consts/appConfig.go:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: symbol
3 | * @Date: 2022-05-23 14:41:57
4 | * @LastEditors: symbol
5 | * @LastEditTime: 2022-05-23 22:12:12
6 | * @FilePath: \ToDb\common\consts\appConfig.go
7 | * @Description: 应用配置
8 | *
9 | * Copyright (c) 2022 by symbol, All Rights Reserved.
10 | */
11 |
12 | package consts
13 |
14 | // 应用
15 | const (
16 | AppName = "ToDb"
17 | Version = "0.1.0"
18 | Description = "又一个装模作样的数据库连接工具🙄️"
19 | BtnConfirmText = "确定"
20 | BtnCancelText = "取消"
21 | )
22 |
--------------------------------------------------------------------------------
/common/structs/BaseInfo.go:
--------------------------------------------------------------------------------
1 | // package structs
2 | // @Author: easymbol
3 | // @Date: 2022/5/3
4 | // @LastEditors: easymbol
5 | // @LastEditTime: 2022/5/3 22:39
6 | // @FilePath:
7 | // @Description: 对象结构体
8 |
9 | // Copyright (c) 2022 by easymbol, All Rights Reserved.
10 |
11 | package structs
12 |
13 | // ConnectionType 基础连接信息
14 | type ConnectionType struct {
15 | Type string `tag:"类型" json:"type"` //类型
16 | Alias string `tag:"连接名" json:"alias"` //别名
17 | HostURL string `tag:"连接地址" json:"hostURL"` //连接地址
18 | Port string `tag:"端口号" json:"port"` //端口号
19 | Username string `tag:"用户名" json:"username"` //用户名
20 | Password string `tag:"密码" json:"password"` //密码
21 | }
22 |
23 | // BaseTreeInfo 基础连接信息
24 | type BaseTreeInfo struct {
25 | Label string `json:"label"` //适配tree
26 | Title string `json:"title"` //别名
27 | ConnType string `json:"connType"` //类型
28 | IconPath string `json:"iconPath"` //图标路径
29 | ConnFileAddr string `json:"ConnFileAddr"` //连接信息文件存放地址
30 | //Children string `json:"children"` //子节点
31 | }
32 |
33 | // DbTreeInfo 数据库内部信息
34 | type DbTreeInfo struct {
35 | Label string `json:"label"` //名称
36 | Title string `json:"title"` //别名
37 | Key string `json:"key"` //键
38 | IsLeaf bool `json:"isLeaf"` //是否是叶子节点
39 | Children string `json:"children"` //子节点
40 | }
41 |
--------------------------------------------------------------------------------
/common/structs/redis.go:
--------------------------------------------------------------------------------
1 | package structs
2 |
3 | // @Author: symbol
4 | // @Date: 2022-04-28 10:57:39
5 | // @LastEditors: symbol
6 | // @LastEditTime: 2022-04-30 17:02:36
7 | // @FilePath: /todb/model/redis.go
8 | // @Description: redis返回信息结构体
9 |
10 | // Copyright (c) 2022 by symbol, All Rights Reserved.
11 |
12 | // GetValue redis的详情页面返回结构体
13 | type GetValue struct {
14 | Type string `json:"type"` // value类型
15 | Key string `json:"key"` // key键
16 | Ttl string `json:"ttl"` // ttl剩余时间
17 | Value interface{} `json:"value"` // value值
18 | Size int `json:"size"` // value大小
19 | CommandStr string `json:"commandStr"` // redis命令
20 | }
21 |
22 | // RedisList redis List数据
23 | type RedisList struct {
24 | Id int `json:"id"`
25 | Value string `json:"value"`
26 | }
27 |
28 | // RedisHash redis hash数据
29 | type RedisHash struct {
30 | Id int `json:"id"`
31 | Key string `json:"key"`
32 | Value string `json:"value"`
33 | }
34 |
--------------------------------------------------------------------------------
/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | /dist/
3 |
--------------------------------------------------------------------------------
/frontend/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/favicon.ico
--------------------------------------------------------------------------------
/frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | ToDb
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ToDb",
3 | "version": "0.1.0",
4 | "author": "easymbol",
5 | "private": true,
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "@ant-design/icons-vue": "^6.1.0",
13 | "@soerenmartius/vue3-clipboard": "^0.1.2",
14 | "ant-design-vue": "^3.2.3",
15 | "element-plus": "^2.1.11",
16 | "timers": "^0.1.1",
17 | "vue": "^3.2.31",
18 | "vue-i18n": "^9.1.9",
19 | "vue-router": "^4.0.12"
20 | },
21 | "devDependencies": {
22 | "@vicons/antd": "^0.12.0",
23 | "@vicons/carbon": "^0.12.0",
24 | "@vicons/fa": "^0.12.0",
25 | "@vicons/fluent": "^0.12.0",
26 | "@vicons/ionicons4": "^0.12.0",
27 | "@vicons/ionicons5": "^0.12.0",
28 | "@vicons/material": "^0.12.0",
29 | "@vicons/tabler": "^0.12.0",
30 | "@vitejs/plugin-vue": "^2.3.1",
31 | "sass": "^1.49.9",
32 | "vite": "^2.9.7",
33 | "vite-plugin-html": "^3.2.0",
34 | "vue-tsc": "^0.3.0"
35 | }
36 | }
--------------------------------------------------------------------------------
/frontend/src/App.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
59 |
65 |
89 |
--------------------------------------------------------------------------------
/frontend/src/Aside.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
223 |
224 |
229 |
--------------------------------------------------------------------------------
/frontend/src/Header.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
13 |
14 |
连接
15 |
16 |
17 |
18 |
19 | Redis
22 | MySQL
28 | Other
31 |
32 |
33 |
34 |
35 |
36 |
37 |
42 |
43 |
44 |
45 |
表
46 |
47 |
48 |
49 |
50 |
51 |
52 |
57 |
58 |
59 |
60 |
查询
61 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
74 |
75 |
76 |
导入
77 |
78 |
79 |
80 |
81 |
82 |
83 |
89 |
90 |
91 |
92 |
导出
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
107 |
108 |
109 |
147 |
148 |
171 |
--------------------------------------------------------------------------------
/frontend/src/Welcome.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
18 |
19 |
20 |
21 |
22 | ToDB .app
23 |
24 | Version 0.1.0
25 | Powered by
27 | wails
32 | and
33 | Icons8
36 |
37 |
38 |
39 |
40 |
41 |
46 |
47 |
66 |
--------------------------------------------------------------------------------
/frontend/src/assets/css/font.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "JetBrainsMono";
3 | src: url("../fonts/JetBrainsMono-Medium.woff2");
4 | }
5 |
--------------------------------------------------------------------------------
/frontend/src/assets/css/reset.css:
--------------------------------------------------------------------------------
1 | html,
2 | body,
3 | div,
4 | span,
5 | applet,
6 | object,
7 | iframe,
8 | h1,
9 | h2,
10 | h3,
11 | h4,
12 | h5,
13 | h6,
14 | p,
15 | blockquote,
16 | pre,
17 | a,
18 | abbr,
19 | acronym,
20 | address,
21 | big,
22 | cite,
23 | code,
24 | del,
25 | dfn,
26 | em,
27 | img,
28 | ins,
29 | kbd,
30 | q,
31 | s,
32 | samp,
33 | small,
34 | strike,
35 | strong,
36 | sub,
37 | sup,
38 | tt,
39 | var,
40 | b,
41 | u,
42 | i,
43 | center,
44 | dl,
45 | dt,
46 | dd,
47 | ol,
48 | ul,
49 | li,
50 | fieldset,
51 | form,
52 | label,
53 | legend,
54 | table,
55 | caption,
56 | tbody,
57 | tfoot,
58 | thead,
59 | tr,
60 | th,
61 | td,
62 | article,
63 | aside,
64 | canvas,
65 | details,
66 | embed,
67 | figure,
68 | figcaption,
69 | footer,
70 | header,
71 | hgroup,
72 | menu,
73 | nav,
74 | output,
75 | ruby,
76 | section,
77 | summary,
78 | time,
79 | mark,
80 | audio,
81 | video {
82 | margin: 0;
83 | padding: 0;
84 | border: 0;
85 | font-size: 100%;
86 | font: inherit;
87 | vertical-align: baseline;
88 | }
89 | /* HTML5 display-role reset for older browsers */
90 | article,
91 | aside,
92 | details,
93 | figcaption,
94 | figure,
95 | footer,
96 | header,
97 | hgroup,
98 | menu,
99 | nav,
100 | section {
101 | display: block;
102 | }
103 | body {
104 | line-height: 1;
105 | }
106 | ol,
107 | ul {
108 | list-style: none;
109 | }
110 | blockquote,
111 | q {
112 | quotes: none;
113 | }
114 | blockquote:before,
115 | blockquote:after,
116 | q:before,
117 | q:after {
118 | content: "";
119 | content: none;
120 | }
121 | table {
122 | border-collapse: collapse;
123 | border-spacing: 0;
124 | }
125 |
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-Bold.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-BoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-BoldItalic.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-ExtraBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-ExtraBold.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-ExtraBoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-ExtraBoldItalic.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-ExtraLight.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-ExtraLight.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-ExtraLightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-ExtraLightItalic.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-Italic.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-Light.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-LightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-LightItalic.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-Medium.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-MediumItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-MediumItalic.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-Regular.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-SemiBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-SemiBold.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-SemiBoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-SemiBoldItalic.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-Thin.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-Thin.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/JetBrainsMono-ThinItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/JetBrainsMono-ThinItalic.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/OFL.txt:
--------------------------------------------------------------------------------
1 | Copyright 2016 The Nunito Project Authors (contact@sansoxygen.com),
2 |
3 | This Font Software is licensed under the SIL Open Font License, Version 1.1.
4 | This license is copied below, and is also available with a FAQ at:
5 | http://scripts.sil.org/OFL
6 |
7 |
8 | -----------------------------------------------------------
9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10 | -----------------------------------------------------------
11 |
12 | PREAMBLE
13 | The goals of the Open Font License (OFL) are to stimulate worldwide
14 | development of collaborative font projects, to support the font creation
15 | efforts of academic and linguistic communities, and to provide a free and
16 | open framework in which fonts may be shared and improved in partnership
17 | with others.
18 |
19 | The OFL allows the licensed fonts to be used, studied, modified and
20 | redistributed freely as long as they are not sold by themselves. The
21 | fonts, including any derivative works, can be bundled, embedded,
22 | redistributed and/or sold with any software provided that any reserved
23 | names are not used by derivative works. The fonts and derivatives,
24 | however, cannot be released under any other type of license. The
25 | requirement for fonts to remain under this license does not apply
26 | to any document created using the fonts or their derivatives.
27 |
28 | DEFINITIONS
29 | "Font Software" refers to the set of files released by the Copyright
30 | Holder(s) under this license and clearly marked as such. This may
31 | include source files, build scripts and documentation.
32 |
33 | "Reserved Font Name" refers to any names specified as such after the
34 | copyright statement(s).
35 |
36 | "Original Version" refers to the collection of Font Software components as
37 | distributed by the Copyright Holder(s).
38 |
39 | "Modified Version" refers to any derivative made by adding to, deleting,
40 | or substituting -- in part or in whole -- any of the components of the
41 | Original Version, by changing formats or by porting the Font Software to a
42 | new environment.
43 |
44 | "Author" refers to any designer, engineer, programmer, technical
45 | writer or other person who contributed to the Font Software.
46 |
47 | PERMISSION & CONDITIONS
48 | Permission is hereby granted, free of charge, to any person obtaining
49 | a copy of the Font Software, to use, study, copy, merge, embed, modify,
50 | redistribute, and sell modified and unmodified copies of the Font
51 | Software, subject to the following conditions:
52 |
53 | 1) Neither the Font Software nor any of its individual components,
54 | in Original or Modified Versions, may be sold by itself.
55 |
56 | 2) Original or Modified Versions of the Font Software may be bundled,
57 | redistributed and/or sold with any software, provided that each copy
58 | contains the above copyright notice and this license. These can be
59 | included either as stand-alone text files, human-readable headers or
60 | in the appropriate machine-readable metadata fields within text or
61 | binary files as long as those fields can be easily viewed by the user.
62 |
63 | 3) No Modified Version of the Font Software may use the Reserved Font
64 | Name(s) unless explicit written permission is granted by the corresponding
65 | Copyright Holder. This restriction only applies to the primary font name as
66 | presented to the users.
67 |
68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69 | Software shall not be used to promote, endorse or advertise any
70 | Modified Version, except to acknowledge the contribution(s) of the
71 | Copyright Holder(s) and the Author(s) or with their explicit written
72 | permission.
73 |
74 | 5) The Font Software, modified or unmodified, in part or in whole,
75 | must be distributed entirely under this license, and must not be
76 | distributed under any other license. The requirement for fonts to
77 | remain under this license does not apply to any document created
78 | using the Font Software.
79 |
80 | TERMINATION
81 | This license becomes null and void if any of the above conditions are
82 | not met.
83 |
84 | DISCLAIMER
85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93 | OTHER DEALINGS IN THE FONT SOFTWARE.
94 |
--------------------------------------------------------------------------------
/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2
--------------------------------------------------------------------------------
/frontend/src/assets/images/comeon.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/images/comeon.gif
--------------------------------------------------------------------------------
/frontend/src/assets/images/logo-universal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/images/logo-universal.png
--------------------------------------------------------------------------------
/frontend/src/assets/images/quick/about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/images/quick/about.png
--------------------------------------------------------------------------------
/frontend/src/assets/images/quick/conn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/images/quick/conn.png
--------------------------------------------------------------------------------
/frontend/src/assets/images/quick/export.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/images/quick/export.png
--------------------------------------------------------------------------------
/frontend/src/assets/images/quick/import.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/images/quick/import.png
--------------------------------------------------------------------------------
/frontend/src/assets/images/quick/select.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/images/quick/select.png
--------------------------------------------------------------------------------
/frontend/src/assets/images/quick/table.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/images/quick/table.png
--------------------------------------------------------------------------------
/frontend/src/assets/line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/line.png
--------------------------------------------------------------------------------
/frontend/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/logo.png
--------------------------------------------------------------------------------
/frontend/src/assets/logos/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/assets/logos/logo.png
--------------------------------------------------------------------------------
/frontend/src/i18n/index.js:
--------------------------------------------------------------------------------
1 | import { createI18n } from "vue-i18n";
2 |
3 | import zhHans from "./messages/zh-Hans.json";
4 | import en from "./messages/en.json";
5 | import fr from "./messages/fr.json";
6 |
7 | const i18n = createI18n({
8 | locale: "en",
9 | fallbackLocale: "en",
10 | messages: {
11 | "zh-Hans": zhHans,
12 | en: en,
13 | fr: fr,
14 | },
15 | });
16 |
17 | export default i18n;
18 |
--------------------------------------------------------------------------------
/frontend/src/i18n/messages/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "nav": {
3 | "home": "Home",
4 | "about": "About"
5 | },
6 | "languages": {
7 | "en": "English",
8 | "zh-Hans": "简体中文",
9 | "fr": "Français"
10 | },
11 | "topbar": {
12 | "minimise": "Minimise",
13 | "quit": "Quit"
14 | },
15 | "homepage": {
16 | "welcome": "Welcome to use Wails program developed based on Vue",
17 | "getting-started": "Getting Started",
18 | "star-me": "Star Me"
19 | },
20 | "aboutpage": {
21 | "title": "Wails Template Vue",
22 | "project-repository": "Project Repository",
23 | "author": "Author",
24 | "misitebao": "Misitebao",
25 | "wails-repository": "Wails Repository",
26 | "thanks": "Thank you all for your support🙏!"
27 | },
28 | "global": {
29 | "not-supported": "Because it is a beta version, it can't be done for the time being, it will be completed later.",
30 | "click-link": "The currently clicked link is: "
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/frontend/src/i18n/messages/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "nav": {
3 | "home": "Page d'accueil",
4 | "about": "À propos"
5 | },
6 | "languages": {
7 | "en": "English",
8 | "zh-Hans": "简体中文",
9 | "fr": "Français"
10 | },
11 | "topbar": {
12 | "minimise": "Minimiser",
13 | "quit": "Quitter"
14 | },
15 | "homepage": {
16 | "welcome": "Bienvenue à utiliser le programme Wails développé sur la base de Vue",
17 | "getting-started": "Commencer",
18 | "star-me": "Étoile moi"
19 | },
20 | "aboutpage": {
21 | "title": "Wails Template Vue",
22 | "project-repository": "Référentiel de projets",
23 | "author": "Auteur",
24 | "misitebao": "Misitebao",
25 | "wails-repository": "Wails Dépôt",
26 | "thanks": "Merci à tous pour votre soutien🙏!"
27 | },
28 | "global": {
29 | "not-supported": "Parce qu'il s'agit d'une version bêta, cela ne peut pas être fait pour le moment, il sera complété plus tard.",
30 | "click-link": "Le lien actuellement cliqué est: "
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/frontend/src/i18n/messages/zh-Hans.json:
--------------------------------------------------------------------------------
1 | {
2 | "nav": {
3 | "home": "主页",
4 | "about": "关于"
5 | },
6 | "languages": {
7 | "en": "English",
8 | "zh-Hans": "简体中文",
9 | "fr": "Français"
10 | },
11 | "topbar": {
12 | "minimise": "最小化",
13 | "quit": "退出"
14 | },
15 | "homepage": {
16 | "welcome": "欢迎使用基于Vue开发的Wails程序",
17 | "getting-started": "新手入门",
18 | "star-me": "给我点星"
19 | },
20 | "aboutpage": {
21 | "title": "Wails Template Vue",
22 | "project-repository": "项目仓库",
23 | "author": "作者",
24 | "misitebao": "米司特包",
25 | "wails-repository": "Wails 仓库",
26 | "thanks": "感谢各位大佬的支持🙏!"
27 | },
28 | "global": {
29 | "not-supported": "由于是测试版,所以暂时做不了,后续会完成它。",
30 | "click-link": "当前点击的链接是: "
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/frontend/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | test
7 |
8 |
9 |
10 |
11 |
12 |
13 |
Please enter your name below 👇
14 |
15 |
16 | Greet
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/frontend/src/main.css:
--------------------------------------------------------------------------------
1 | html {
2 | background-color: rgba(27, 38, 54, 1);
3 | text-align: center;
4 | color: white;
5 | }
6 |
7 | body {
8 | margin: 0;
9 | color: white;
10 | font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
11 | "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
12 | sans-serif;
13 | }
14 |
15 | @font-face {
16 | font-family: "Nunito";
17 | font-style: normal;
18 | font-weight: 400;
19 | src: local(""),
20 | url("assets/fonts/nunito-v16-latin-regular.woff2") format("woff2");
21 | }
22 |
23 | #app {
24 | height: 100vh;
25 | text-align: center;
26 | }
27 |
28 | .logo {
29 | display: block;
30 | width: 50%;
31 | height: 50%;
32 | margin: auto;
33 | padding: 10% 0 0;
34 | background-position: center;
35 | background-repeat: no-repeat;
36 | background-image: url("./assets/images/logo-universal.png");
37 | background-size: 100% 100%;
38 | background-origin: content-box;
39 | }
40 | .result {
41 | height: 20px;
42 | line-height: 20px;
43 | margin: 1.5rem auto;
44 | }
45 | .input-box .btn {
46 | width: 60px;
47 | height: 30px;
48 | line-height: 30px;
49 | border-radius: 3px;
50 | border: none;
51 | margin: 0 0 0 20px;
52 | padding: 0 8px;
53 | cursor: pointer;
54 | }
55 | .input-box .btn:hover {
56 | background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);
57 | color: #333333;
58 | }
59 |
60 | .input-box .input {
61 | border: none;
62 | border-radius: 3px;
63 | outline: none;
64 | height: 30px;
65 | line-height: 30px;
66 | padding: 0 10px;
67 | background-color: rgba(240, 240, 240, 1);
68 | -webkit-font-smoothing: antialiased;
69 | }
70 |
71 | .input-box .input:hover {
72 | border: none;
73 | background-color: rgba(255, 255, 255, 1);
74 | }
75 |
76 | .input-box .input:focus {
77 | border: none;
78 | background-color: rgba(255, 255, 255, 1);
79 | }
80 |
--------------------------------------------------------------------------------
/frontend/src/main.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: symbol
3 | * @Date: 2022-04-30 11:18:03
4 | * @LastEditors: symbol
5 | * @LastEditTime: 2022-05-20 16:09:11
6 | * @FilePath: /todb/frontend/src/main.js
7 | * @Description:
8 | *
9 | * Copyright (c) 2022 by symbol, All Rights Reserved.
10 | */
11 | import { createApp } from "vue";
12 | import App from "./App.vue";
13 | import router from "./router";
14 | import i18n from "./i18n";
15 | import ElementPlus from "element-plus";
16 | import "element-plus/dist/index.css";
17 | import { VueClipboard } from "@soerenmartius/vue3-clipboard";
18 |
19 | createApp(App)
20 | .use(router)
21 | .use(i18n)
22 | .use(ElementPlus)
23 | .use(VueClipboard)
24 | .mount("#app");
25 |
--------------------------------------------------------------------------------
/frontend/src/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/public/favicon.ico
--------------------------------------------------------------------------------
/frontend/src/public/info/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/public/info/close.png
--------------------------------------------------------------------------------
/frontend/src/public/info/key.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/public/info/key.png
--------------------------------------------------------------------------------
/frontend/src/public/leftNavigation/redis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/public/leftNavigation/redis.png
--------------------------------------------------------------------------------
/frontend/src/public/status/history.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/public/status/history.png
--------------------------------------------------------------------------------
/frontend/src/public/status/kv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/public/status/kv.png
--------------------------------------------------------------------------------
/frontend/src/public/status/memory.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/public/status/memory.png
--------------------------------------------------------------------------------
/frontend/src/public/status/service.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/frontend/src/public/status/service.png
--------------------------------------------------------------------------------
/frontend/src/router/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: symbol
3 | * @Date: 2022-04-30 11:18:03
4 | * @LastEditors: symbol
5 | * @LastEditTime: 2022-05-28 17:16:50
6 | * @FilePath: \ToDb\frontend\src\router\index.js
7 | * @Description:路由
8 | *
9 | * Copyright (c) 2022 by symbol, All Rights Reserved.
10 | */
11 | import Default from "../Welcome.vue";
12 | import NewConnect from "../views/pop/NewConnection.vue";
13 | import Status from "../views/redis/Content_status.vue";
14 | import StringInfo from "../views/redis/Content_string_info.vue";
15 | import ListInfo from "../views/redis/Content_list_info.vue";
16 | import HashInfo from "../views/redis/Content_hash_info.vue";
17 | import SetInfo from "../views/redis/Content_set_info.vue";
18 | import ZSetInfo from "../views/redis/Content_zset_info.vue";
19 | import StreamInfo from "../views/redis/Content_stream_info.vue";
20 | import { createRouter, createWebHashHistory } from "vue-router";
21 |
22 | const routes = [
23 | {
24 | // 新建连接
25 | path: "/newConnection",
26 | name: "newConnection",
27 | component: NewConnect,
28 | },
29 | {
30 | // 右侧默认页面
31 | path: "/rightContent/default",
32 | name: "default",
33 | component: Default,
34 | },
35 | {
36 | // 右侧状态页面
37 | path: "/rightContent/status",
38 | name: "status",
39 | component: Status,
40 | },
41 | {
42 | // 右侧详情页面string类型
43 | path: "/rightContent/value_string",
44 | name: "stringInfo",
45 | component: StringInfo,
46 | },
47 | {
48 | // 右侧详情页面list类型
49 | path: "/rightContent/value_list",
50 | name: "listInfo",
51 | component: ListInfo,
52 | },
53 | {
54 | // 右侧详情页面hash类型
55 | path: "/rightContent/value_hash",
56 | name: "hashInfo",
57 | component: HashInfo,
58 | },
59 | {
60 | // 右侧详情页面set类型
61 | path: "/rightContent/value_set",
62 | name: "setInfo",
63 | component: SetInfo,
64 | },
65 | {
66 | // 右侧详情页面stream类型
67 | path: "/rightContent/value_stream",
68 | name: "streamInfo",
69 | component: StreamInfo,
70 | },
71 | {
72 | // 右侧详情页面zset类型
73 | path: "/rightContent/value_zset",
74 | name: "zsetInfo",
75 | component: ZSetInfo,
76 | },
77 | ];
78 |
79 | const router = createRouter({
80 | history: createWebHashHistory(),
81 | routes,
82 | });
83 |
84 | export default router;
85 |
--------------------------------------------------------------------------------
/frontend/src/views/pop/AddListValue.vue:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/frontend/src/views/pop/NewConnection.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | 连接名:
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | 主 机:
28 |
29 |
30 |
31 |
32 |
33 | 端 口:
34 |
35 |
36 |
37 |
38 |
39 |
40 | 用户名:
41 |
42 |
43 |
44 |
45 |
46 | 密 码:
47 |
48 |
54 |
55 |
56 |
57 |
58 |
59 | 保存密码
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | 测试连接
68 |
69 |
70 | 确定
71 |
72 |
73 | 取消
74 |
75 |
76 |
77 |
78 |
79 |
154 |
155 |
164 |
--------------------------------------------------------------------------------
/frontend/src/views/redis/Content_hash_info.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 | {{ nowKey }}
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | {{ allValue.data.type }}
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | TTL
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | 添加新行
92 |
93 |
94 |
95 |
96 |
97 |
98 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
254 |
255 |
260 |
--------------------------------------------------------------------------------
/frontend/src/views/redis/Content_list_info.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 | {{ nowKey }}
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | {{ allValue.data.type }}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | TTL
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | 添加新行
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | 键值
103 |
104 |
105 |
106 |
107 |
113 |
114 |
115 |
116 |
117 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
277 |
278 |
283 |
--------------------------------------------------------------------------------
/frontend/src/views/redis/Content_set_info.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 | {{ nowKey }}
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | {{ allValue.data.type }}
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | TTL
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | 添加新行
91 |
92 |
93 |
94 |
95 |
96 |
97 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
252 |
253 |
258 |
--------------------------------------------------------------------------------
/frontend/src/views/redis/Content_status.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | 自动刷新
11 |
12 |
13 | {{ autoRefresh }}
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
36 | 服务器
37 |
38 |
39 |
40 | Redis版本:
41 | {{
42 | serviceInfo.data.version
43 | }}
44 |
45 |
46 |
47 |
48 | OS:
49 | {{ serviceInfo.data.os }}
50 |
51 |
52 |
53 |
54 | 进程ID:
55 | {{
56 | serviceInfo.data.process
57 | }}
58 |
59 |
60 |
61 |
62 |
63 |
64 |
69 | 内存
70 |
71 |
72 |
73 | 已用内存:
74 | {{
75 | memoryInfo.data.usedMemory
76 | }}
77 |
78 |
79 |
80 |
81 | 内存占用峰值:
82 | {{
83 | memoryInfo.data.usedBigMemory
84 | }}
85 |
86 |
87 |
88 |
89 | Lua占用内存:
90 | {{
91 | memoryInfo.data.luaMemory
92 | }}
93 |
94 |
95 |
96 |
97 |
98 |
103 | 历史
104 |
105 |
106 |
107 | 客户端连接数:
108 | {{
109 | historyInfo.data.connectCount
110 | }}
111 |
112 |
113 |
114 |
115 | 历史连接数:
116 | {{
117 | historyInfo.data.historyCount
118 | }}
119 |
120 |
121 |
122 |
123 | 历史命令数:
124 | {{
125 | historyInfo.data.historyInstructions
126 | }}
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
142 | 键值统计
143 |
144 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
289 |
290 |
313 |
--------------------------------------------------------------------------------
/frontend/src/views/redis/Content_stream_info.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 | {{ nowKey }}
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | {{ allValue.data.type }}
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | TTL
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | 添加新行
92 |
93 |
94 |
95 |
96 |
97 |
98 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
255 |
256 |
261 |
--------------------------------------------------------------------------------
/frontend/src/views/redis/Content_string_info.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 | {{ nowKey }}
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | {{ allValue.data.type }}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | TTL
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
100 |
101 |
102 |
103 |
104 | Size:{{ contentSize }}B
105 |
106 |
107 |
108 |
109 |
114 |
115 |
116 |
117 | 复制
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 | 保存
130 |
131 |
132 |
133 |
134 |
299 |
300 |
308 |
--------------------------------------------------------------------------------
/frontend/src/views/redis/Content_zset_info.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 | {{ nowKey }}
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | {{ allValue.data.type }}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | TTL
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | 添加新行
94 |
95 |
96 |
97 |
98 |
99 |
100 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
261 |
262 |
267 |
--------------------------------------------------------------------------------
/frontend/src/wailsjs/go/bindings.d.ts:
--------------------------------------------------------------------------------
1 | import * as models from './models';
2 |
3 | export interface go {
4 | "main": {
5 | "App": {
6 | ChangeRightWindowStyle(arg1:string,arg2:string,arg3:string):Promise
7 | ExportConn():Promise
8 | GetNodeData(arg1:string,arg2:string,arg3:string):Promise
9 | ImportConn():Promise
10 | LoadingConnInfo(arg1:string,arg2:string):Promise
11 | LoadingConnKey():Promise
12 | LoadingDbResource(arg1:string):Promise
13 | Ok(arg1:string):Promise
14 | RedisDelKey(arg1:string,arg2:string,arg3:string,arg4:string):Promise
15 | RedisGetData(arg1:string,arg2:string,arg3:string,arg4:string):Promise
16 | RedisReName(arg1:string,arg2:string,arg3:string,arg4:string,arg5:string):Promise
17 | RedisSaveStringValue(arg1:string,arg2:string,arg3:string,arg4:string,arg5:string,arg6:string):Promise
18 | RedisUpTtl(arg1:string,arg2:string,arg3:string,arg4:string,arg5:string):Promise
19 | TestConnection(arg1:string):Promise
20 | },
21 | }
22 |
23 | }
24 |
25 | declare global {
26 | interface Window {
27 | go: go;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/frontend/src/wailsjs/go/bindings.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
3 | // This file is automatically generated. DO NOT EDIT
4 | const go = {
5 | "main": {
6 | "App": {
7 | /**
8 | * ChangeRightWindowStyle
9 | * @param {string} arg1 - Go Type: string
10 | * @param {string} arg2 - Go Type: string
11 | * @param {string} arg3 - Go Type: string
12 | * @returns {Promise} - Go Type: string
13 | */
14 | "ChangeRightWindowStyle": (arg1, arg2, arg3) => {
15 | return window.go.main.App.ChangeRightWindowStyle(arg1, arg2, arg3);
16 | },
17 | /**
18 | * ExportConn
19 | * @returns {Promise}
20 | */
21 | "ExportConn": () => {
22 | return window.go.main.App.ExportConn();
23 | },
24 | /**
25 | * GetNodeData
26 | * @param {string} arg1 - Go Type: string
27 | * @param {string} arg2 - Go Type: string
28 | * @param {string} arg3 - Go Type: string
29 | * @returns {Promise} - Go Type: string
30 | */
31 | "GetNodeData": (arg1, arg2, arg3) => {
32 | return window.go.main.App.GetNodeData(arg1, arg2, arg3);
33 | },
34 | /**
35 | * ImportConn
36 | * @returns {Promise}
37 | */
38 | "ImportConn": () => {
39 | return window.go.main.App.ImportConn();
40 | },
41 | /**
42 | * LoadingConnInfo
43 | * @param {string} arg1 - Go Type: string
44 | * @param {string} arg2 - Go Type: string
45 | * @returns {Promise} - Go Type: string
46 | */
47 | "LoadingConnInfo": (arg1, arg2) => {
48 | return window.go.main.App.LoadingConnInfo(arg1, arg2);
49 | },
50 | /**
51 | * LoadingConnKey
52 | * @returns {Promise} - Go Type: string
53 | */
54 | "LoadingConnKey": () => {
55 | return window.go.main.App.LoadingConnKey();
56 | },
57 | /**
58 | * LoadingDbResource
59 | * @param {string} arg1 - Go Type: string
60 | * @returns {Promise} - Go Type: string
61 | */
62 | "LoadingDbResource": (arg1) => {
63 | return window.go.main.App.LoadingDbResource(arg1);
64 | },
65 | /**
66 | * Ok
67 | * @param {string} arg1 - Go Type: string
68 | * @returns {Promise} - Go Type: string
69 | */
70 | "Ok": (arg1) => {
71 | return window.go.main.App.Ok(arg1);
72 | },
73 | /**
74 | * RedisDelKey
75 | * @param {string} arg1 - Go Type: string
76 | * @param {string} arg2 - Go Type: string
77 | * @param {string} arg3 - Go Type: string
78 | * @param {string} arg4 - Go Type: string
79 | * @returns {Promise}
80 | */
81 | "RedisDelKey": (arg1, arg2, arg3, arg4) => {
82 | return window.go.main.App.RedisDelKey(arg1, arg2, arg3, arg4);
83 | },
84 | /**
85 | * RedisGetData
86 | * @param {string} arg1 - Go Type: string
87 | * @param {string} arg2 - Go Type: string
88 | * @param {string} arg3 - Go Type: string
89 | * @param {string} arg4 - Go Type: string
90 | * @returns {Promise} - Go Type: string
91 | */
92 | "RedisGetData": (arg1, arg2, arg3, arg4) => {
93 | return window.go.main.App.RedisGetData(arg1, arg2, arg3, arg4);
94 | },
95 | /**
96 | * RedisReName
97 | * @param {string} arg1 - Go Type: string
98 | * @param {string} arg2 - Go Type: string
99 | * @param {string} arg3 - Go Type: string
100 | * @param {string} arg4 - Go Type: string
101 | * @param {string} arg5 - Go Type: string
102 | * @returns {Promise}
103 | */
104 | "RedisReName": (arg1, arg2, arg3, arg4, arg5) => {
105 | return window.go.main.App.RedisReName(arg1, arg2, arg3, arg4, arg5);
106 | },
107 | /**
108 | * RedisSaveStringValue
109 | * @param {string} arg1 - Go Type: string
110 | * @param {string} arg2 - Go Type: string
111 | * @param {string} arg3 - Go Type: string
112 | * @param {string} arg4 - Go Type: string
113 | * @param {string} arg5 - Go Type: string
114 | * @param {string} arg6 - Go Type: string
115 | * @returns {Promise}
116 | */
117 | "RedisSaveStringValue": (arg1, arg2, arg3, arg4, arg5, arg6) => {
118 | return window.go.main.App.RedisSaveStringValue(arg1, arg2, arg3, arg4, arg5, arg6);
119 | },
120 | /**
121 | * RedisUpTtl
122 | * @param {string} arg1 - Go Type: string
123 | * @param {string} arg2 - Go Type: string
124 | * @param {string} arg3 - Go Type: string
125 | * @param {string} arg4 - Go Type: string
126 | * @param {string} arg5 - Go Type: string
127 | * @returns {Promise}
128 | */
129 | "RedisUpTtl": (arg1, arg2, arg3, arg4, arg5) => {
130 | return window.go.main.App.RedisUpTtl(arg1, arg2, arg3, arg4, arg5);
131 | },
132 | /**
133 | * TestConnection
134 | * @param {string} arg1 - Go Type: string
135 | * @returns {Promise}
136 | */
137 | "TestConnection": (arg1) => {
138 | return window.go.main.App.TestConnection(arg1);
139 | },
140 | },
141 | },
142 |
143 | };
144 | export default go;
145 |
--------------------------------------------------------------------------------
/frontend/src/wailsjs/go/models.ts:
--------------------------------------------------------------------------------
1 | /* Do not change, this code is generated from Golang structs */
2 |
3 | export {};
4 |
--------------------------------------------------------------------------------
/frontend/src/wailsjs/go/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "go",
3 | "version": "1.0.0",
4 | "description": "Package to wrap your bound go methods",
5 | "main": "bindings.js",
6 | "types": "bindings.d.ts",
7 | "scripts": {},
8 | "author": "",
9 | "license": "ISC"
10 | }
--------------------------------------------------------------------------------
/frontend/src/wailsjs/runtime/ipcdev.js:
--------------------------------------------------------------------------------
1 | (()=>{(function(){let n=function(e){for(var s=window[e.shift()];s&&e.length;)s=s[e.shift()];return s},o=n(["chrome","webview","postMessage"]),t=n(["webkit","messageHandlers","external","postMessage"]);if(!o&&!t){console.error("Unsupported Platform");return}o&&(window.WailsInvoke=e=>window.chrome.webview.postMessage(e)),t&&(window.WailsInvoke=e=>window.webkit.messageHandlers.external.postMessage(e))})();})();
2 |
--------------------------------------------------------------------------------
/frontend/src/wailsjs/runtime/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@wailsapp/runtime",
3 | "version": "2.0.0",
4 | "description": "Wails Javascript runtime library",
5 | "main": "runtime.js",
6 | "types": "runtime.d.ts",
7 | "scripts": {
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/wailsapp/wails.git"
12 | },
13 | "keywords": [
14 | "Wails",
15 | "Javascript",
16 | "Go"
17 | ],
18 | "author": "Lea Anthony ",
19 | "license": "MIT",
20 | "bugs": {
21 | "url": "https://github.com/wailsapp/wails/issues"
22 | },
23 | "homepage": "https://github.com/wailsapp/wails#readme"
24 | }
25 |
--------------------------------------------------------------------------------
/frontend/src/wailsjs/runtime/runtime.d.ts:
--------------------------------------------------------------------------------
1 | export interface Position {
2 | x: number;
3 | y: number;
4 | }
5 |
6 | export interface Size {
7 | w: number;
8 | h: number;
9 | }
10 |
11 | export interface runtime {
12 | EventsEmit(eventName: string, data?: any): void;
13 |
14 | EventsOn(eventName: string, callback: (data?: any) => void): void;
15 |
16 | EventsOnMultiple(eventName: string, callback: (data?: any) => void, maxCallbacks: number): void;
17 |
18 | EventsOnce(eventName: string, callback: (data?: any) => void): void;
19 |
20 | LogTrace(message: string): void;
21 |
22 | LogDebug(message: string): void;
23 |
24 | LogError(message: string): void;
25 |
26 | LogFatal(message: string): void;
27 |
28 | LogInfo(message: string): void;
29 |
30 | LogWarning(message: string): void;
31 |
32 | WindowReload(): void;
33 |
34 | WindowCenter(): void;
35 |
36 | WindowSetTitle(title: string): void;
37 |
38 | WindowFullscreen(): void;
39 |
40 | WindowUnfullscreen(): void;
41 |
42 | WindowSetSize(width: number, height: number): Promise;
43 |
44 | WindowGetSize(): Promise;
45 |
46 | WindowSetMaxSize(width: number, height: number): void;
47 |
48 | WindowSetMinSize(width: number, height: number): void;
49 |
50 | WindowSetPosition(x: number, y: number): void;
51 |
52 | WindowGetPosition(): Promise;
53 |
54 | WindowHide(): void;
55 |
56 | WindowShow(): void;
57 |
58 | WindowMaximise(): void;
59 |
60 | WindowToggleMaximise(): void;
61 |
62 | WindowUnmaximise(): void;
63 |
64 | WindowMinimise(): void;
65 |
66 | WindowUnminimise(): void;
67 |
68 | WindowSetRGBA(R: number, G: number, B: number, A: number): void;
69 |
70 | BrowserOpenURL(url: string): void;
71 |
72 | Quit(): void;
73 | }
74 |
75 | declare global {
76 | interface Window {
77 | runtime: runtime;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/frontend/src/wailsjs/runtime/runtime.js:
--------------------------------------------------------------------------------
1 | (()=>{var d=Object.defineProperty;var m=n=>d(n,"__esModule",{value:!0});var e=(n,i)=>{m(n);for(var o in i)d(n,o,{get:i[o],enumerable:!0})};var t={};e(t,{LogDebug:()=>W,LogError:()=>x,LogFatal:()=>s,LogInfo:()=>c,LogTrace:()=>p,LogWarning:()=>f});function p(n){window.runtime.LogTrace(n)}function W(n){window.runtime.LogDebug(n)}function c(n){window.runtime.LogInfo(n)}function f(n){window.runtime.LogWarning(n)}function x(n){window.runtime.LogError(n)}function s(n){window.runtime.LogFatal(n)}var w={};e(w,{EventsEmit:()=>S,EventsOn:()=>a,EventsOnMultiple:()=>l,EventsOnce:()=>g});function l(n,i,o){window.runtime.EventsOnMultiple(n,i,o)}function a(n,i){OnMultiple(n,i,-1)}function g(n,i){OnMultiple(n,i,1)}function S(n){let i=[n].slice.call(arguments);return window.runtime.EventsEmit.apply(null,i)}var r={};e(r,{WindowCenter:()=>M,WindowFullscreen:()=>v,WindowGetPosition:()=>B,WindowGetSize:()=>O,WindowHide:()=>F,WindowMaximise:()=>b,WindowMinimise:()=>C,WindowReload:()=>L,WindowSetMaxSize:()=>G,WindowSetMinSize:()=>R,WindowSetPosition:()=>T,WindowSetRGBA:()=>H,WindowSetSize:()=>U,WindowSetTitle:()=>E,WindowShow:()=>P,WindowToggleMaximise:()=>h,WindowUnfullscreen:()=>z,WindowUnmaximise:()=>A,WindowUnminimise:()=>D});function L(){window.runtime.WindowReload()}function M(){window.runtime.WindowCenter()}function E(n){window.runtime.WindowSetTitle(n)}function v(){window.runtime.WindowFullscreen()}function z(){window.runtime.WindowUnfullscreen()}function O(){window.runtime.WindowGetSize()}function U(n,i){window.runtime.WindowSetSize(n,i)}function G(n,i){window.runtime.WindowSetMaxSize(n,i)}function R(n,i){window.runtime.WindowSetMinSize(n,i)}function T(n,i){window.runtime.WindowSetPosition(n,i)}function B(){window.runtime.WindowGetPosition()}function F(){window.runtime.WindowHide()}function P(){window.runtime.WindowShow()}function b(){window.runtime.WindowMaximise()}function h(){window.runtime.WindowToggleMaximise()}function A(){window.runtime.WindowUnmaximise()}function C(){window.runtime.WindowMinimise()}function D(){window.runtime.WindowUnminimise()}function H(n){window.runtime.WindowSetRGBA(n)}var u={};e(u,{BrowserOpenURL:()=>I});function I(n){window.runtime.BrowserOpenURL(n)}function Q(){window.runtime.Quit()}var j={...t,...w,...r,...u,Quit:Q};})();
2 |
--------------------------------------------------------------------------------
/frontend/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import vue from "@vitejs/plugin-vue";
3 | import path from "path";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [vue()],
8 | resolve: {
9 | alias: {
10 | "@": path.resolve(__dirname, "src"),
11 | },
12 | },
13 | build: {
14 | outDir: "dist",
15 | rollupOptions: {
16 | output: {
17 | entryFileNames: `src/assets/[name].js`,
18 | chunkFileNames: `src/assets/[name].js`,
19 | assetFileNames: `src/assets/[name].[ext]`,
20 | },
21 | },
22 | },
23 | });
24 |
--------------------------------------------------------------------------------
/frontend/wailsjs/runtime/ipcdev.js:
--------------------------------------------------------------------------------
1 | (()=>{(function(){let n=function(e){for(var s=window[e.shift()];s&&e.length;)s=s[e.shift()];return s},o=n(["chrome","webview","postMessage"]),t=n(["webkit","messageHandlers","external","postMessage"]);if(!o&&!t){console.error("Unsupported Platform");return}o&&(window.WailsInvoke=e=>window.chrome.webview.postMessage(e)),t&&(window.WailsInvoke=e=>window.webkit.messageHandlers.external.postMessage(e))})();})();
2 |
--------------------------------------------------------------------------------
/frontend/wailsjs/runtime/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@wailsapp/runtime",
3 | "version": "2.0.0",
4 | "description": "Wails Javascript runtime library",
5 | "main": "runtime.js",
6 | "types": "runtime.d.ts",
7 | "scripts": {
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/wailsapp/wails.git"
12 | },
13 | "keywords": [
14 | "Wails",
15 | "Javascript",
16 | "Go"
17 | ],
18 | "author": "Lea Anthony ",
19 | "license": "MIT",
20 | "bugs": {
21 | "url": "https://github.com/wailsapp/wails/issues"
22 | },
23 | "homepage": "https://github.com/wailsapp/wails#readme"
24 | }
25 |
--------------------------------------------------------------------------------
/frontend/wailsjs/runtime/runtime.d.ts:
--------------------------------------------------------------------------------
1 | export interface Position {
2 | x: number;
3 | y: number;
4 | }
5 |
6 | export interface Size {
7 | w: number;
8 | h: number;
9 | }
10 |
11 | export interface runtime {
12 | EventsEmit(eventName: string, data?: any): void;
13 |
14 | EventsOn(eventName: string, callback: (data?: any) => void): void;
15 |
16 | EventsOnMultiple(eventName: string, callback: (data?: any) => void, maxCallbacks: number): void;
17 |
18 | EventsOnce(eventName: string, callback: (data?: any) => void): void;
19 |
20 | LogTrace(message: string): void;
21 |
22 | LogDebug(message: string): void;
23 |
24 | LogError(message: string): void;
25 |
26 | LogFatal(message: string): void;
27 |
28 | LogInfo(message: string): void;
29 |
30 | LogWarning(message: string): void;
31 |
32 | WindowReload(): void;
33 |
34 | WindowCenter(): void;
35 |
36 | WindowSetTitle(title: string): void;
37 |
38 | WindowFullscreen(): void;
39 |
40 | WindowUnfullscreen(): void;
41 |
42 | WindowSetSize(width: number, height: number): Promise;
43 |
44 | WindowGetSize(): Promise;
45 |
46 | WindowSetMaxSize(width: number, height: number): void;
47 |
48 | WindowSetMinSize(width: number, height: number): void;
49 |
50 | WindowSetPosition(x: number, y: number): void;
51 |
52 | WindowGetPosition(): Promise;
53 |
54 | WindowHide(): void;
55 |
56 | WindowShow(): void;
57 |
58 | WindowMaximise(): void;
59 |
60 | WindowToggleMaximise(): void;
61 |
62 | WindowUnmaximise(): void;
63 |
64 | WindowMinimise(): void;
65 |
66 | WindowUnminimise(): void;
67 |
68 | WindowSetRGBA(R: number, G: number, B: number, A: number): void;
69 |
70 | BrowserOpenURL(url: string): void;
71 |
72 | Quit(): void;
73 | }
74 |
75 | declare global {
76 | interface Window {
77 | runtime: runtime;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/frontend/wailsjs/runtime/runtime.js:
--------------------------------------------------------------------------------
1 | (()=>{var d=Object.defineProperty;var m=n=>d(n,"__esModule",{value:!0});var e=(n,i)=>{m(n);for(var o in i)d(n,o,{get:i[o],enumerable:!0})};var t={};e(t,{LogDebug:()=>W,LogError:()=>x,LogFatal:()=>s,LogInfo:()=>c,LogTrace:()=>p,LogWarning:()=>f});function p(n){window.runtime.LogTrace(n)}function W(n){window.runtime.LogDebug(n)}function c(n){window.runtime.LogInfo(n)}function f(n){window.runtime.LogWarning(n)}function x(n){window.runtime.LogError(n)}function s(n){window.runtime.LogFatal(n)}var w={};e(w,{EventsEmit:()=>S,EventsOn:()=>a,EventsOnMultiple:()=>l,EventsOnce:()=>g});function l(n,i,o){window.runtime.EventsOnMultiple(n,i,o)}function a(n,i){OnMultiple(n,i,-1)}function g(n,i){OnMultiple(n,i,1)}function S(n){let i=[n].slice.call(arguments);return window.runtime.EventsEmit.apply(null,i)}var r={};e(r,{WindowCenter:()=>M,WindowFullscreen:()=>v,WindowGetPosition:()=>B,WindowGetSize:()=>O,WindowHide:()=>F,WindowMaximise:()=>b,WindowMinimise:()=>C,WindowReload:()=>L,WindowSetMaxSize:()=>G,WindowSetMinSize:()=>R,WindowSetPosition:()=>T,WindowSetRGBA:()=>H,WindowSetSize:()=>U,WindowSetTitle:()=>E,WindowShow:()=>P,WindowToggleMaximise:()=>h,WindowUnfullscreen:()=>z,WindowUnmaximise:()=>A,WindowUnminimise:()=>D});function L(){window.runtime.WindowReload()}function M(){window.runtime.WindowCenter()}function E(n){window.runtime.WindowSetTitle(n)}function v(){window.runtime.WindowFullscreen()}function z(){window.runtime.WindowUnfullscreen()}function O(){window.runtime.WindowGetSize()}function U(n,i){window.runtime.WindowSetSize(n,i)}function G(n,i){window.runtime.WindowSetMaxSize(n,i)}function R(n,i){window.runtime.WindowSetMinSize(n,i)}function T(n,i){window.runtime.WindowSetPosition(n,i)}function B(){window.runtime.WindowGetPosition()}function F(){window.runtime.WindowHide()}function P(){window.runtime.WindowShow()}function b(){window.runtime.WindowMaximise()}function h(){window.runtime.WindowToggleMaximise()}function A(){window.runtime.WindowUnmaximise()}function C(){window.runtime.WindowMinimise()}function D(){window.runtime.WindowUnminimise()}function H(n){window.runtime.WindowSetRGBA(n)}var u={};e(u,{BrowserOpenURL:()=>I});function I(n){window.runtime.BrowserOpenURL(n)}function Q(){window.runtime.Quit()}var j={...t,...w,...r,...u,Quit:Q};})();
2 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module ToDb
2 |
3 | go 1.17
4 |
5 | require (
6 | github.com/go-redis/redis/v8 v8.11.5
7 | github.com/tidwall/gjson v1.8.0
8 | github.com/wailsapp/wails/v2 v2.0.0-beta.34
9 | )
10 |
11 | require (
12 | github.com/andybalholm/brotli v1.0.2 // indirect
13 | github.com/cespare/xxhash/v2 v2.1.2 // indirect
14 | github.com/davecgh/go-spew v1.1.1 // indirect
15 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
16 | github.com/fasthttp/websocket v0.0.0-20200320073529-1554a54587ab // indirect
17 | github.com/gabriel-vasile/mimetype v1.3.1 // indirect
18 | github.com/go-ole/go-ole v1.2.6 // indirect
19 | github.com/gofiber/fiber/v2 v2.17.0 // indirect
20 | github.com/gofiber/websocket/v2 v2.0.8 // indirect
21 | github.com/google/uuid v1.1.2 // indirect
22 | github.com/imdario/mergo v0.3.12 // indirect
23 | github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
24 | github.com/klauspost/compress v1.12.2 // indirect
25 | github.com/leaanthony/go-ansi-parser v1.0.1 // indirect
26 | github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
27 | github.com/leaanthony/go-webview2 v1.0.3-0.20220314105146-f44268990abe // indirect
28 | github.com/leaanthony/gosod v1.0.3 // indirect
29 | github.com/leaanthony/slicer v1.5.0 // indirect
30 | github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
31 | github.com/leaanthony/winc v0.0.0-20220208061147-37b059b9dc3b // indirect
32 | github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
33 | github.com/pkg/errors v0.9.1 // indirect
34 | github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f // indirect
35 | github.com/tidwall/match v1.0.3 // indirect
36 | github.com/tidwall/pretty v1.1.0 // indirect
37 | github.com/tkrajina/go-reflector v0.5.5 // indirect
38 | github.com/valyala/bytebufferpool v1.0.0 // indirect
39 | github.com/valyala/fasthttp v1.28.0 // indirect
40 | github.com/valyala/tcplisten v1.0.0 // indirect
41 | golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
42 | golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
43 | )
44 |
45 | // replace github.com/wailsapp/wails/v2 v2.0.0-beta.34 => /Users/symbol/go/pkg/mod/github.com/wailsapp/wails/v2@v2.0.0-beta.34
46 |
--------------------------------------------------------------------------------
/jb_beam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/jb_beam.png
--------------------------------------------------------------------------------
/kit/dialog.go:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: symbol
3 | * @Date: 2022-05-22 11:21:34
4 | * @LastEditors: symbol
5 | * @LastEditTime: 2022-05-28 17:00:39
6 | * @FilePath: \ToDb\kit\dialog.go
7 | * @Description: 对话框控制工具
8 | *
9 | * Copyright (c) 2022 by symbol, All Rights Reserved.
10 | */
11 |
12 | package kit
13 |
14 | import (
15 | "ToDb/common/consts"
16 | "context"
17 |
18 | "github.com/wailsapp/wails/v2/pkg/runtime"
19 | )
20 |
21 | var (
22 | insDiaLogKit = sDiaLogKit{}
23 | )
24 |
25 | type sDiaLogKit struct {
26 | ctx context.Context
27 | }
28 |
29 | func DiaLogKit() *sDiaLogKit {
30 | return &insDiaLogKit
31 | }
32 |
33 | // DefaultDialog 显示默认的对话框
34 | func (d *sDiaLogKit) DefaultDialog(ctx context.Context, title, message string, icon []byte) {
35 | runtime.MessageDialog(ctx, runtime.MessageDialogOptions{
36 | Type: func(title string) runtime.DialogType {
37 | if title == "错误" {
38 | return runtime.ErrorDialog
39 | }
40 | return runtime.InfoDialog
41 | }(title),
42 | Icon: icon,
43 | Title: title,
44 | Message: message,
45 | Buttons: []string{"确定"},
46 | DefaultButton: "确定",
47 | })
48 | }
49 |
50 | // AboutDialog 关于对话框
51 | func (d *sDiaLogKit) About(ctx context.Context, icon []byte) {
52 | runtime.MessageDialog(ctx, runtime.MessageDialogOptions{
53 | Type: runtime.InfoDialog,
54 | Title: consts.AppName,
55 | Message: consts.Description,
56 | Icon: icon,
57 | DefaultButton: consts.BtnConfirmText,
58 | Buttons: []string{consts.BtnConfirmText},
59 | })
60 | }
61 |
--------------------------------------------------------------------------------
/kit/os/file.go:
--------------------------------------------------------------------------------
1 | // package os
2 | // @Author: symbol
3 | // @Date: 2022-05-03
4 | // @LastEditors: symbol
5 | // @LastEditTime: 2022-05-03 18:06:31
6 | // @FilePath: \ToDb\lib\os\file.go
7 | // @Description: 针对操作系统文件/文件夹进行封装
8 |
9 | // Copyright (c) 2022 by symbol, All Rights Reserved.
10 |
11 | package os
12 |
13 | import (
14 | "context"
15 | "io/fs"
16 | "io/ioutil"
17 | "os"
18 | "os/user"
19 | "strings"
20 | )
21 |
22 | var (
23 | insFile = sFile{}
24 | lastPath = ".ToDb"
25 | )
26 |
27 | type sFile struct {
28 | ctx context.Context
29 | }
30 |
31 | func File() *sFile {
32 | return &insFile
33 | }
34 |
35 | // FormatOsPath
36 | // 基于系统替换路径中的分隔符
37 | // @param {[type]} ctx context.Context
38 | // @return string,error
39 | func (s *sFile) FormatOsPath(ctx context.Context, path string) string {
40 | return strings.ReplaceAll(path, "/", string(os.PathSeparator))
41 | }
42 |
43 | // HomeDir
44 | // 获取系统当前使用的用户名
45 | // @param {[type]} ctx context.Context
46 | // @return string,error
47 | func (o *sFile) HomeDir(ctx context.Context) (string, error) {
48 | user, err := user.Current()
49 | if err != nil {
50 | return "", err
51 | }
52 | path := user.HomeDir + string(os.PathSeparator) + lastPath + string(os.PathSeparator)
53 | return path, nil
54 | }
55 |
56 | // CreateFile 创建文件夹或文件
57 | // @param {[type]} ctx context.Context [description]
58 | // @param {string} fileName 文件名 如果文件名不存在则创建文件夹
59 | // @return error
60 | func (o *sFile) CreateFile(ctx context.Context, fileName string) error {
61 | // 文件夹路径
62 | folderPath, err := o.HomeDir(ctx)
63 | if err != nil {
64 | return err
65 | }
66 | // 判断文件夹是否存在
67 | if !o.Exists(ctx, folderPath) {
68 | // 文件夹不存在,创建文件夹,并且对文件夹设置隐藏属性
69 | err = os.MkdirAll(folderPath, os.ModePerm)
70 | if err != nil {
71 | return err
72 | }
73 | }
74 | if fileName != "" {
75 | // 文件名如果存在,就创建文件
76 | filePath := folderPath + fileName + ".json"
77 | if !o.Exists(ctx, filePath) {
78 | // 创建文件
79 | file, err := os.Create(filePath)
80 | if err != nil {
81 | return err
82 | }
83 | defer file.Close()
84 | }
85 | }
86 | return nil
87 | }
88 |
89 | // Exists 文件或文件夹是否存在
90 | // @param {[type]} ctx context.Context [description]
91 | // @param {string} path 文件夹路径
92 | // @return bool true 存在 false 不存在
93 | func (o *sFile) Exists(ctx context.Context, path string) bool {
94 | _, err := os.Stat(path)
95 | if os.IsNotExist(err) {
96 | return false
97 | }
98 | return true
99 | }
100 |
101 | // SaveFile 保存信息到文件
102 | // @param {[type]} ctx context.Context [description]
103 | // @param {string} fileName 文件名
104 | // @param {string} content 文件内容
105 | // @return error
106 | func (o *sFile) SaveFile(ctx context.Context, fileName, content string) error {
107 | // 文件夹路径
108 | folderPath, err := o.HomeDir(ctx)
109 | if err != nil {
110 | return err
111 | }
112 | folderPath = folderPath + fileName + ".json"
113 | f, err := os.OpenFile(folderPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666)
114 | if err != nil {
115 | return err
116 | }
117 | f.WriteString(content)
118 | defer f.Close()
119 | return nil
120 | }
121 |
122 | // ReadFiles 读取文件夹中的文件
123 | // @param {[type]} ctx context.Context [description]
124 | // @return []fs.FileInfo,error
125 | func (o *sFile) ReadFiles(ctx context.Context) ([]fs.FileInfo, error) {
126 | // 文件夹路径
127 | folderPath, err := o.HomeDir(ctx)
128 | if err != nil {
129 | return nil, err
130 | }
131 | f, err := ioutil.ReadDir(folderPath)
132 | if err != nil {
133 | return nil, err
134 | }
135 | for i, v := range f {
136 | // macOS下会存在这个隐藏文件,所以需要过滤掉
137 | if v.Name() == ".DS_Store" {
138 | f = append(f[:i], f[i+1:]...)
139 | }
140 | }
141 | return f, nil
142 | }
143 |
144 | // InputFile 导入文件
145 | // @param {[type]} ctx context.Context [description]
146 | // @return error
147 | func (o *sFile) InputFile(ctx context.Context) error {
148 | return nil
149 | }
150 |
--------------------------------------------------------------------------------
/kit/os/os_test.go:
--------------------------------------------------------------------------------
1 | // package os
2 | // @Author: easymbol
3 | // @Date: 2022/5/3
4 | // @LastEditors: easymbol
5 | // @LastEditTime: 2022/5/3 22:23
6 | // @FilePath:
7 | // @Description: TODO
8 |
9 | // Copyright (c) 2022 by easymbol, All Rights Reserved.
10 |
11 | package os
12 |
13 | import (
14 | "context"
15 | "fmt"
16 | "testing"
17 | )
18 |
19 | func TestCreateFile(t *testing.T) {
20 | File().CreateFile(context.Background(), "test.txt")
21 | }
22 |
23 | func TestReadFiles(t *testing.T) {
24 | files, err := File().ReadFiles(context.Background())
25 | if err != nil {
26 | t.Error(err)
27 | }
28 | fmt.Println(files)
29 | }
30 |
--------------------------------------------------------------------------------
/kit/redis/redis_test.go:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: symbol
3 | * @Date: 2022-05-04 10:22:53
4 | * @LastEditors: symbol
5 | * @LastEditTime: 2022-05-20 17:54:11
6 | * @FilePath: /todb/kit/redis/redis_test.go
7 | * @Description:
8 | *
9 | * Copyright (c) 2022 by symbol, All Rights Reserved.
10 | */
11 | package redisKit
12 |
13 | import (
14 | "ToDb/kit"
15 | "context"
16 | "fmt"
17 | "testing"
18 | )
19 |
20 | func TestConnect(t *testing.T) {
21 | Addr = "127.0.0.1"
22 | Port = "6379"
23 | Password = "123456"
24 | InitDb()
25 | fmt.Println(Redis().GetMainViewInfo(context.Background()))
26 | }
27 |
28 | func TestInfo(t *testing.T) {
29 | Addr = "127.0.0.1"
30 | Port = "6379"
31 | Password = "123456"
32 | InitDb()
33 | Redis().ChangeDb(context.Background(), 13)
34 | //fmt.Println(GetBaseAllInfo(context.Background()))
35 | v, _ := Redis().GetDbKeys(context.Background(), 0)
36 | fmt.Println(v)
37 | _v := kit.StrKit().PackageTree(v)
38 | fmt.Println(_v)
39 | }
40 |
41 | func TestDel(t *testing.T) {
42 | Addr = "127.0.0.1"
43 | Port = "6379"
44 | Password = "123456"
45 | InitDb()
46 | Redis().ChangeDb(context.Background(), 13)
47 | Redis().Del(context.Background(), "1111")
48 | }
49 |
50 | func TestStream(t *testing.T) {
51 | Addr = "127.0.0.1"
52 | Port = "6379"
53 | Password = "123456"
54 | InitDb()
55 | Redis().ChangeDb(context.Background(), 13)
56 | Redis().GetStreamValue(context.Background(), "1:2:stream")
57 | }
58 |
59 | func TestZSet(t *testing.T) {
60 | Addr = "127.0.0.1"
61 | Port = "6379"
62 | Password = "123456"
63 | InitDb()
64 | Redis().ChangeDb(context.Background(), 13)
65 | Redis().GetZSetCount(context.Background(), "1:2:zset")
66 | }
67 |
--------------------------------------------------------------------------------
/kit/response.go:
--------------------------------------------------------------------------------
1 | package kit
2 |
3 | import "encoding/json"
4 |
5 | type JsonResponse struct {
6 | Code int `json:"code"` //错误码
7 | Message string `json:"message"` //提示信息
8 | Data interface{} `json:"data"` //返回数据
9 | }
10 |
11 | func (jr *JsonResponse) String() string {
12 | val, _ := json.Marshal(jr)
13 | return string(val)
14 | }
15 |
--------------------------------------------------------------------------------
/kit/strKit.go:
--------------------------------------------------------------------------------
1 | package kit
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "strings"
7 | )
8 |
9 | var (
10 | insStrKit = sStrKit{}
11 | )
12 |
13 | type sStrKit struct {
14 | ctx context.Context
15 | }
16 |
17 | func StrKit() *sStrKit {
18 | return &insStrKit
19 | }
20 |
21 | type Node struct {
22 | Label string `json:"label"`
23 | Key string `json:"key"`
24 | FullStr string `json:"fullStr"`
25 | Count int `json:"count"`
26 | Children []*Node `json:"children,omitempty"`
27 | }
28 |
29 | func (s *sStrKit) PackageTree(v []string) string {
30 | // 根据数组中的中的冒号数量进行排序,最多的冒号数量的元素放在最前面
31 | v = s.BubbleDescSort(v)
32 |
33 | // 声明切片存放树形数据
34 | var treeNode []Node
35 | for _, val := range v {
36 | var node Node
37 | sl := strings.SplitN(val, ":", 2)
38 | // 查找treeNode切片中是否已经存在当前key
39 | for _, v := range treeNode {
40 | var sb strings.Builder
41 | sb.WriteString(sl[0])
42 | sb.WriteString(":*")
43 | if v.Key == sb.String() {
44 | node = v
45 | }
46 | }
47 | flag := node.Key == ""
48 | if flag {
49 | node.Label = sl[0]
50 | var sb strings.Builder
51 | sb.WriteString(sl[0])
52 | sb.WriteString(":*")
53 | node.Key = sb.String()
54 | node.FullStr = val
55 | node.Count = 0
56 | }
57 | if len(sl) > 1 {
58 | s.GetChildren(sl[1], val, &node)
59 | if !flag {
60 | for i, v := range treeNode {
61 | if v.Key == node.Key {
62 | treeNode[i] = node
63 | }
64 | }
65 | }
66 | }
67 | if flag {
68 | treeNode = append(treeNode, node)
69 | }
70 | }
71 | res, err := json.Marshal(treeNode)
72 | if err != nil {
73 | panic(err)
74 | }
75 | return string(res)
76 | }
77 |
78 | func (s *sStrKit) GetChildren(nodeStr, fullStr string, parentNode *Node) {
79 | node := &Node{}
80 | sl := strings.SplitN(nodeStr, ":", 2)
81 | for _, v := range parentNode.Children {
82 | var sb strings.Builder
83 | sb.WriteString(sl[0])
84 | sb.WriteString(":*")
85 | if len(sl) > 1 && v.Key == sb.String() {
86 | node = v
87 | }
88 | }
89 | flag := node.Key == ""
90 | if flag {
91 | node.Label = sl[0]
92 | var sb strings.Builder
93 | sb.WriteString(sl[0])
94 | sb.WriteString(":*")
95 | node.Key = sb.String()
96 | node.FullStr = fullStr
97 | node.Count = 0
98 | }
99 |
100 | if len(sl) > 1 {
101 | s.GetChildren(sl[1], fullStr, node)
102 | } else {
103 | // 如果没有子节点说明是最终节点
104 | node.Key = fullStr
105 | }
106 | if flag {
107 | parentNode.Children = append(parentNode.Children, node)
108 | parentNode.Count = len(parentNode.Children)
109 | }
110 | }
111 |
112 | // BubbleDescSort 冒泡排序 倒序
113 | func (s *sStrKit) BubbleDescSort(values []string) []string {
114 | for i := 0; i < len(values)-1; i++ {
115 | for j := i + 1; j < len(values); j++ {
116 | if strings.Count(values[i], ":") < strings.Count(values[j], ":") {
117 | values[i], values[j] = values[j], values[i]
118 | }
119 | }
120 | }
121 | return values
122 | }
123 |
124 | // BubbleAscSort 冒泡排序 正序
125 | func (s *sStrKit) BubbleAscSort(values []string) []string {
126 | for i := 0; i < len(values)-1; i++ {
127 | for j := i + 1; j < len(values); j++ {
128 | if strings.Count(values[i], ":") > strings.Count(values[j], ":") {
129 | values[i], values[j] = values[j], values[i]
130 | }
131 | }
132 | }
133 | return values
134 | }
135 |
136 | // FirstUpper 字符串首字母大写
137 | func (s *sStrKit) FirstUpper(str string) string {
138 | if str == "" {
139 | return ""
140 | }
141 | return strings.ToUpper(str[:1]) + str[1:]
142 | }
143 |
144 | // FirstLower 字符串首字母小写
145 | func (s *sStrKit) FirstLower(str string) string {
146 | if str == "" {
147 | return ""
148 | }
149 | return strings.ToLower(str[:1]) + str[1:]
150 | }
151 |
--------------------------------------------------------------------------------
/kit/update.go:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: symbol
3 | * @Date: 2022-05-28 23:13:40
4 | * @LastEditors: symbol
5 | * @LastEditTime: 2022-05-28 23:48:38
6 | * @FilePath: \ToDb\kit\update.go
7 | * @Description:
8 | *
9 | * Copyright (c) 2022 by symbol, All Rights Reserved.
10 | */
11 | package kit
12 |
13 | import (
14 | "context"
15 | "fmt"
16 | )
17 |
18 | var (
19 | insUpdate = sUpdate{}
20 | )
21 |
22 | type sUpdate struct {
23 | ctx context.Context
24 | }
25 |
26 | func Update() *sUpdate {
27 | return &insUpdate
28 | }
29 |
30 | const (
31 | githubUrl = "https://api.github.com/repos/xingcxb/todb/releases/latest"
32 | )
33 |
34 | // 检查是否存在更新
35 | func (u *sUpdate) CheckUpdate() {
36 | //TODO 未发布版本暂缓实现
37 | fmt.Println(githubUrl)
38 | }
39 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: symbol
3 | * @Date: 2022-05-08 08:49:54
4 | * @LastEditors: symbol
5 | * @LastEditTime: 2022-05-23 22:44:39
6 | * @FilePath: \ToDb\main.go
7 | * @Description:
8 | *
9 | * Copyright (c) 2022 by symbol, All Rights Reserved.
10 | */
11 | package main
12 |
13 | import (
14 | "ToDb/common/consts"
15 | "embed"
16 | "log"
17 | goruntime "runtime"
18 |
19 | "github.com/wailsapp/wails/v2"
20 | "github.com/wailsapp/wails/v2/pkg/options"
21 | )
22 |
23 | //go:embed frontend/dist
24 | var assets embed.FS
25 |
26 | //go:embed build/appicon.png
27 | var icon []byte
28 |
29 | func main() {
30 | // 判断系统如果是win需要增高窗口大小
31 | windowsHeight := 728
32 | osInfo := goruntime.GOOS
33 | if osInfo == "windows" {
34 | windowsHeight = 770
35 | }
36 | // Create an instance of the app structure
37 | // 创建一个App结构体实例
38 | app := NewApp()
39 |
40 | // Create application with options
41 | // 使用选项创建应用
42 | err := wails.Run(&options.App{
43 | Title: consts.AppName,
44 | Width: 1342,
45 | Height: windowsHeight,
46 | DisableResize: true,
47 | Assets: assets,
48 | OnStartup: app.startup,
49 | OnDomReady: app.domReady,
50 | OnBeforeClose: app.beforeClose,
51 | OnShutdown: app.shutdown,
52 | WindowStartState: options.Normal,
53 | Bind: []interface{}{
54 | app,
55 | },
56 | })
57 |
58 | if err != nil {
59 | log.Fatal(err)
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/menu/macOSMenu.go:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: symbol
3 | * @Date: 2022-05-22 11:21:34
4 | * @LastEditors: symbol
5 | * @LastEditTime: 2022-05-28 23:12:52
6 | * @FilePath: \ToDb\menu\macOSMenu.go
7 | * @Description:
8 | *
9 | * Copyright (c) 2022 by symbol, All Rights Reserved.
10 | */
11 | package menu
12 |
13 | import (
14 | "ToDb/kit"
15 | "context"
16 |
17 | "github.com/wailsapp/wails/v2/pkg/menu"
18 | "github.com/wailsapp/wails/v2/pkg/menu/keys"
19 | "github.com/wailsapp/wails/v2/pkg/runtime"
20 | )
21 |
22 | var (
23 | insMacOSMenu = sMacOSMenu{}
24 | )
25 |
26 | type sMacOSMenu struct {
27 | ctx context.Context
28 | }
29 |
30 | func MacOSMenu() *sMacOSMenu {
31 | return &insMacOSMenu
32 | }
33 |
34 | // About macOS菜单关于
35 | func (s *sMacOSMenu) About(ctx context.Context, icon []byte) *menu.MenuItem {
36 | //todo 由于目前不可变暂时使用默认
37 | //看了别人的的代码,可以考虑使用自定义的对话框来实现
38 | return menu.SubMenu("关于",
39 | menu.NewMenuFromItems(
40 | menu.Text("关于ToDb", nil, func(cd *menu.CallbackData) {
41 | kit.DiaLogKit().About(ctx, icon)
42 | }),
43 | menu.Separator(),
44 | menu.Text("退出", keys.CmdOrCtrl("Q"), func(cd *menu.CallbackData) {
45 | runtime.Quit(ctx)
46 | }),
47 | ),
48 | )
49 | }
50 |
51 | // File macOs文件
52 | func (s *sMacOSMenu) File(ctx context.Context) *menu.MenuItem {
53 | return menu.SubMenu("文件",
54 | menu.NewMenuFromItems(
55 | menu.SubMenu("新建连接",
56 | menu.NewMenuFromItems(
57 | menu.Text("Redis...", keys.CmdOrCtrl("N"), func(data *menu.CallbackData) {
58 | runtime.EventsEmit(ctx, "createConn", "redis")
59 | }),
60 | // menu.Text("MySQL...", nil, func(data *menu.CallbackData) {
61 | // runtime.EventsEmit(ctx, "createConn", "mysql")
62 | // }),
63 | ),
64 | ),
65 | menu.Text("新建查询", nil, nil),
66 | menu.Separator(),
67 | menu.Text("导入连接...", keys.CmdOrCtrl("I"), func(data *menu.CallbackData) {
68 | runtime.EventsEmit(ctx, "importConn")
69 | }),
70 | menu.Text("导出连接...", nil, func(data *menu.CallbackData) {
71 | runtime.EventsEmit(ctx, "exportConn")
72 | }),
73 | ),
74 | )
75 | }
76 |
--------------------------------------------------------------------------------
/menu/menu.go:
--------------------------------------------------------------------------------
1 | package menu
2 |
3 | import (
4 | "ToDb/kit"
5 | "context"
6 | goruntime "runtime"
7 |
8 | "github.com/wailsapp/wails/v2/pkg/menu"
9 | "github.com/wailsapp/wails/v2/pkg/menu/keys"
10 | "github.com/wailsapp/wails/v2/pkg/runtime"
11 | )
12 |
13 | var (
14 | osInfo = ""
15 | insMenu = sMenu{}
16 | )
17 |
18 | type sMenu struct {
19 | ctx context.Context
20 | }
21 |
22 | func Menu() *sMenu {
23 | return &insMenu
24 | }
25 |
26 | // InitMenu 初始化菜单目录
27 | func InitMenu(ctx context.Context, icon []byte) {
28 | var appMenu *menu.Menu
29 | // 判断系统类型
30 | osInfo = goruntime.GOOS
31 | switch osInfo {
32 | case "windows":
33 | //Windows目录
34 | appMenu = windows(ctx, icon)
35 | case "darwin":
36 | //macos
37 | appMenu = macOs(ctx, icon)
38 | default:
39 | //linux
40 | kit.DiaLogKit().DefaultDialog(ctx, "错误", "暂不支持该系统", nil)
41 | }
42 | runtime.MenuSetApplicationMenu(ctx, appMenu)
43 | }
44 |
45 | // macOS菜单
46 | func macOs(ctx context.Context, icon []byte) *menu.Menu {
47 | return menu.NewMenuFromItems(
48 | MacOSMenu().About(ctx, icon),
49 | MacOSMenu().File(ctx),
50 | Menu().Edit(ctx),
51 | Menu().Find(ctx),
52 | Menu().Tools(ctx),
53 | Menu().Help(ctx, icon),
54 | )
55 | }
56 |
57 | // windows菜单
58 | func windows(ctx context.Context, icon []byte) *menu.Menu {
59 | return menu.NewMenuFromItems(
60 | WinMenu().File(ctx),
61 | Menu().Edit(ctx),
62 | Menu().Find(ctx),
63 | Menu().Tools(ctx),
64 | Menu().Help(ctx, icon),
65 | )
66 | }
67 |
68 | // Edit 编辑
69 | func (s *sMenu) Edit(ctx context.Context) *menu.MenuItem {
70 | return menu.SubMenu("编辑",
71 | menu.NewMenuFromItems(
72 | menu.Text("撤销", keys.CmdOrCtrl("Z"), nil),
73 | menu.Separator(),
74 | menu.Text("剪切", keys.CmdOrCtrl("X"), nil),
75 | menu.Text("复制", keys.CmdOrCtrl("C"), nil),
76 | menu.Text("粘贴", keys.CmdOrCtrl("V"), nil),
77 | ),
78 | )
79 | }
80 |
81 | // Find 查找
82 | func (s *sMenu) Find(ctx context.Context) *menu.MenuItem {
83 | return menu.SubMenu("查找",
84 | menu.NewMenuFromItems(
85 | menu.Text("运行", nil, nil),
86 | menu.Text("停止", nil, nil),
87 | ),
88 | )
89 | }
90 |
91 | // Tools 工具
92 | func (s *sMenu) Tools(ctx context.Context) *menu.MenuItem {
93 | return menu.SubMenu("工具",
94 | menu.NewMenuFromItems(
95 | menu.Text("历史日志", nil, nil),
96 | menu.Text("刷新", keys.CmdOrCtrl("R"), func(data *menu.CallbackData) {
97 | runtime.WindowReload(ctx)
98 | }),
99 | ),
100 | )
101 | }
102 |
103 | // Help 帮助
104 | func (s *sMenu) Help(ctx context.Context, icon []byte) *menu.MenuItem {
105 | return menu.SubMenu("帮助",
106 | menu.NewMenuFromItems(
107 | menu.Text("帮助中心", nil, nil),
108 | menu.SubMenu("在线文档",
109 | menu.NewMenuFromItems(
110 | menu.Text("Redis", nil, func(_ *menu.CallbackData) {
111 | runtime.BrowserOpenURL(ctx, "http://doc.redisfans.com/")
112 | }),
113 | menu.Text("MySQL", nil, func(_ *menu.CallbackData) {
114 | runtime.BrowserOpenURL(ctx, "https://dev.mysql.com/doc/refman/8.0/en/")
115 | }),
116 | ),
117 | ),
118 | menu.Text("意见反馈", nil, nil),
119 | menu.Separator(),
120 | menu.Text("检查更新", nil, func(_ *menu.CallbackData) {
121 | kit.Update().CheckUpdate()
122 | }),
123 | menu.Separator(),
124 | menu.Text("关于", nil, func(cd *menu.CallbackData) {
125 | kit.DiaLogKit().About(ctx, icon)
126 | }),
127 | ),
128 | )
129 | }
130 |
--------------------------------------------------------------------------------
/menu/winMenu.go:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: symbol
3 | * @Date: 2022-05-22 11:21:34
4 | * @LastEditors: symbol
5 | * @LastEditTime: 2022-05-23 11:57:23
6 | * @FilePath: /todb/menu/winMenu.go
7 | * @Description:
8 | *
9 | * Copyright (c) 2022 by symbol, All Rights Reserved.
10 | */
11 | package menu
12 |
13 | import (
14 | "context"
15 |
16 | "github.com/wailsapp/wails/v2/pkg/menu"
17 | "github.com/wailsapp/wails/v2/pkg/menu/keys"
18 | "github.com/wailsapp/wails/v2/pkg/runtime"
19 | )
20 |
21 | var (
22 | insWinMenu = sWinMenu{}
23 | )
24 |
25 | type sWinMenu struct {
26 | ctx context.Context
27 | }
28 |
29 | func WinMenu() *sWinMenu {
30 | return &insWinMenu
31 | }
32 |
33 | // File win文件
34 | func (s *sWinMenu) File(ctx context.Context) *menu.MenuItem {
35 | return menu.SubMenu("文件",
36 | menu.NewMenuFromItems(
37 | menu.SubMenu("新建连接",
38 | menu.NewMenuFromItems(
39 | menu.Text("Redis...", keys.CmdOrCtrl("N"), func(data *menu.CallbackData) {
40 | runtime.EventsEmit(ctx, "createConn", "redis")
41 | }),
42 | // menu.Text("MySQL...", nil, func(data *menu.CallbackData) {
43 | // runtime.EventsEmit(ctx, "createConn", "mysql")
44 | // }),
45 | ),
46 | ),
47 | menu.Text("新建查询", nil, nil),
48 | menu.Separator(),
49 | menu.Text("导入连接...", keys.CmdOrCtrl("I"), func(data *menu.CallbackData) {
50 | runtime.EventsEmit(ctx, "importConn")
51 | }),
52 | menu.Text("导出连接...", nil, func(data *menu.CallbackData) {
53 | runtime.EventsEmit(ctx, "exportConn")
54 | }),
55 | menu.Separator(),
56 | menu.Text("退出", keys.CmdOrCtrl("Q"), func(cd *menu.CallbackData) {
57 | runtime.Quit(ctx)
58 | }),
59 | ),
60 | )
61 | }
62 |
--------------------------------------------------------------------------------
/scripts/build-macos-arm.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | echo -e "Start running the script..."
4 | cd ../
5 |
6 | echo -e "Start building the app for macos platform..."
7 | wails build --clean --platform darwin/arm64
8 |
9 | echo -e "End running the script!"
10 |
--------------------------------------------------------------------------------
/scripts/build-macos-intel.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | echo -e "Start running the script..."
4 | cd ../
5 |
6 | echo -e "Start building the app for macos platform..."
7 | wails build --clean --platform darwin
8 |
9 | echo -e "End running the script!"
10 |
--------------------------------------------------------------------------------
/scripts/build-macos.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | echo -e "Start running the script..."
4 | cd ../
5 |
6 | echo -e "Start building the app for macos platform..."
7 | wails build --clean --platform darwin/universal
8 |
9 | echo -e "End running the script!"
10 |
--------------------------------------------------------------------------------
/scripts/build-windows.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | echo -e "Start running the script..."
4 | cd ../
5 |
6 | echo -e "Start building the app for windows platform..."
7 | wails build --clean --platform windows/amd64
8 |
9 | echo -e "End running the script!"
10 |
--------------------------------------------------------------------------------
/scripts/build.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | echo -e "Start running the script..."
4 | cd ../
5 |
6 | echo -e "Start building the app..."
7 | wails build --clean
8 |
9 | echo -e "End running the script!"
10 |
--------------------------------------------------------------------------------
/scripts/install-wails-cli.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | echo -e "Start running the script..."
4 | cd ../
5 |
6 | echo -e "Current Go version: \c"
7 | go version
8 |
9 | echo -e "Install the Wails command line tool..."
10 | go install github.com/wailsapp/wails/v2/cmd/wails@latest
11 |
12 | echo -e "Successful installation!"
13 |
14 | echo -e "End running the script!"
15 |
--------------------------------------------------------------------------------
/service/general.go:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: symbol
3 | * @Date: 2022-05-21 19:59:46
4 | * @LastEditors: symbol
5 | * @LastEditTime: 2022-05-28 14:53:21
6 | * @FilePath: \ToDb\service\general.go
7 | * @Description:
8 | *
9 | * Copyright (c) 2022 by symbol, All Rights Reserved.
10 | */
11 | // package service
12 | // @Author: symbol
13 | // @Date: 2022-05-04
14 | // @LastEditors: symbol
15 | // @LastEditTime: 2022-05-04 18:06:31
16 | // @FilePath: \ToDb\service\general.go
17 | // @Description: 通用的通信模块
18 |
19 | // Copyright (c) 2022 by symbol, All Rights Reserved.
20 |
21 | package service
22 |
23 | import (
24 | "ToDb/kit/os"
25 | "context"
26 | "io/ioutil"
27 | sysOs "os"
28 | "os/exec"
29 | "os/user"
30 | sysRuntime "runtime"
31 |
32 | "github.com/tidwall/gjson"
33 | "github.com/wailsapp/wails/v2/pkg/runtime"
34 | )
35 |
36 | var (
37 | insGeneral = sGeneral{}
38 | )
39 |
40 | type sGeneral struct {
41 | ctx context.Context
42 | }
43 |
44 | func General() *sGeneral {
45 | return &insGeneral
46 | }
47 |
48 | // ImportConn 导入连接
49 | // @param {[type]} ctx context.Context [description]
50 | // @return error
51 | func (s *sGeneral) ImportConn(ctx context.Context) error {
52 | user, err := user.Current()
53 | if err != nil {
54 | return err
55 | }
56 | defaultPath := user.HomeDir + string(sysOs.PathSeparator) + "Downloads"
57 | // 获取到文件的路径和错误信息
58 | selection, err := runtime.OpenFileDialog(ctx, runtime.OpenDialogOptions{
59 | // 默认对话框打开时显示的目录
60 | DefaultDirectory: defaultPath,
61 | // 对话框标题
62 | Title: "选择导入文件",
63 | // 默认文件名
64 | DefaultFilename: "localhost.json",
65 | // 文件过滤器列表
66 | Filters: []runtime.FileFilter{
67 | {
68 | DisplayName: "File (*.json)",
69 | Pattern: "*.json",
70 | },
71 | },
72 | })
73 | if err != nil {
74 | return err
75 | }
76 | // 读取文件
77 | bData, err := ioutil.ReadFile(selection)
78 | if err != nil {
79 | return err
80 | }
81 | alias := gjson.Get(string(bData), "alias").String()
82 | return os.File().SaveFile(ctx, alias, string(bData))
83 | }
84 |
85 | // ExportConn 导出连接[由于需要第二个窗口,基础框架未实现故暂时未实现]
86 | // @param {[type]} ctx context.Context [description]
87 | // @return error
88 | func (s *sGeneral) ExportConn(ctx context.Context) error {
89 | homeDir, err := os.File().HomeDir(ctx)
90 | if err != nil {
91 | return err
92 | }
93 | // 打开文件资源管理器
94 | osName := sysRuntime.GOOS
95 |
96 | switch osName {
97 | case "windows":
98 | exec.Command("explorer", homeDir).Start()
99 | case "linux":
100 | exec.Command("xdg-open", homeDir).Start()
101 | case "darwin":
102 | exec.Command("open", homeDir).Start()
103 | }
104 | return nil
105 | }
106 |
--------------------------------------------------------------------------------
/service/redis.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "ToDb/common/structs"
5 | "ToDb/kit"
6 | "ToDb/kit/os"
7 | redisKit "ToDb/kit/redis"
8 | "context"
9 | "encoding/json"
10 | "errors"
11 | "fmt"
12 | "io/ioutil"
13 | "net/http"
14 | "reflect"
15 | "strconv"
16 | "strings"
17 |
18 | "github.com/go-redis/redis/v8"
19 |
20 | "github.com/tidwall/gjson"
21 | )
22 |
23 | var (
24 | insRedis = sRedis{}
25 | )
26 |
27 | type sRedis struct {
28 | ctx context.Context
29 | }
30 |
31 | func Redis() *sRedis {
32 | return &insRedis
33 | }
34 |
35 | // 检查参数
36 | func (s *sRedis) checkParameter(parameter map[string]gjson.Result) (int, string, bool) {
37 | //返回连接信息
38 | message := "连接成功"
39 | //状态码
40 | code := http.StatusOK
41 | //用于标记是否要继续匹配
42 | fail := false
43 | for k, v := range parameter {
44 | if k == "savePassword" || k == "username" {
45 | continue
46 | }
47 | if v.String() == "" {
48 | code = http.StatusBadRequest
49 | fieldV, _ := reflect.TypeOf(structs.ConnectionType{}).FieldByName(k)
50 | tag := fieldV.Tag.Get("tag")
51 | message = tag + "不能为空"
52 | fail = true
53 | break
54 | }
55 | }
56 | return code, message, fail
57 | }
58 |
59 | // RedisPing redis测试连接
60 | func (s *sRedis) RedisPing(connectionInfo string) (int, string) {
61 | //返回连接信息
62 | message := "连接成功"
63 | //状态码
64 | code := http.StatusOK
65 | //用于标记是否要继续匹配
66 | fail := false
67 | parameter := gjson.Parse(connectionInfo).Map()
68 | code, message, fail = s.checkParameter(parameter)
69 |
70 | info := structs.ConnectionType{
71 | Alias: parameter["alias"].String(),
72 | HostURL: parameter["hostURL"].String(),
73 | Port: parameter["port"].String(),
74 | Username: parameter["username"].String(),
75 | Password: parameter["password"].String(),
76 | }
77 |
78 | if !fail {
79 | redisKit.Addr = info.HostURL
80 | redisKit.Port = info.Port
81 | redisKit.Username = info.Username
82 | redisKit.Password = info.Password
83 | redisKit.InitDb()
84 | err := redisKit.Redis().Ping(context.Background())
85 | if err != nil {
86 | code = http.StatusBadRequest
87 | message = err.Error()
88 | } else {
89 | code = http.StatusOK
90 | message = "连接成功"
91 | }
92 | }
93 | return code, message
94 | }
95 |
96 | // Ok 确定按钮
97 | func (s *sRedis) Ok(ctx context.Context, connectionInfo string) (int, string) {
98 | //返回连接信息
99 | message := "连接成功"
100 | //状态码
101 | code := http.StatusOK
102 | parameter := gjson.Parse(connectionInfo).Map()
103 | code, message, _ = s.checkParameter(parameter)
104 | connType := parameter["connType"].String()
105 | connType = strings.ToLower(connType)
106 | info := structs.ConnectionType{
107 | Type: connType,
108 | Alias: parameter["alias"].String(),
109 | HostURL: parameter["hostURL"].String(),
110 | Port: parameter["port"].String(),
111 | Username: parameter["username"].String(),
112 | Password: parameter["password"].String(),
113 | }
114 | if parameter["savePassword"].Bool() {
115 | // 创建文件或文件夹
116 | err := os.File().CreateFile(ctx, info.Alias)
117 | if err != nil {
118 | return code, message
119 | }
120 | value, _ := json.MarshalIndent(info, "", " ")
121 | err = os.File().SaveFile(ctx, info.Alias, string(value))
122 | if err != nil {
123 | return 0, "保存失败"
124 | }
125 | }
126 | return code, message
127 | }
128 |
129 | // LoadingBaseHistoryInfo 加载已经存储的连接别名
130 | func (s *sRedis) LoadingBaseHistoryInfo(ctx context.Context) string {
131 | // 读取所有的文件
132 | files, _ := os.File().ReadFiles(ctx)
133 | datas := make([]structs.BaseTreeInfo, 0, 1)
134 | // 获取程序设定的基础路径
135 | homeDir, _ := os.File().HomeDir(ctx)
136 | // 循环组装数据,用于前端tree的显示
137 | for _, f := range files {
138 | fileName := f.Name()
139 | var filePath strings.Builder
140 | filePath.WriteString(homeDir)
141 | filePath.WriteString(fileName)
142 | // 读取文件内容
143 | valueByte, _ := ioutil.ReadFile(filePath.String())
144 | // 提取类型
145 | t := gjson.Get(string(valueByte), "type").String()
146 | // 提取别名
147 | alias := gjson.Get(string(valueByte), "alias").String()
148 | bci := structs.BaseTreeInfo{
149 | Title: alias,
150 | Label: alias,
151 | ConnType: t,
152 | IconPath: "",
153 | ConnFileAddr: filePath.String(),
154 | }
155 | datas = append(datas, bci)
156 | }
157 | jb, _ := json.Marshal(datas)
158 | return string(jb)
159 | }
160 |
161 | // LoadingHistoryInfo 加载已经存储的连接信息
162 | func (s *sRedis) LoadingHistoryInfo(fileName string) (int, string) {
163 | s.initRedis(fileName)
164 | err := redisKit.Redis().Ping(context.Background())
165 | if err != nil {
166 | return http.StatusBadRequest, err.Error()
167 | }
168 | var data []structs.DbTreeInfo
169 | //redis则直接显示15个库
170 | for i := 0; i < 16; i++ {
171 | var dbName strings.Builder
172 | dbName.WriteString("db")
173 | dbName.WriteString(strconv.Itoa(i))
174 | dbName.WriteString("(")
175 | dbName.WriteString(strconv.Itoa(redisKit.Redis().GetDbCount(context.Background(), i)))
176 | dbName.WriteString(")")
177 | data = append(data, structs.DbTreeInfo{
178 | Label: dbName.String(),
179 | Title: dbName.String(),
180 | Key: strconv.Itoa(i),
181 | })
182 | }
183 |
184 | vb, _ := json.Marshal(data)
185 | return http.StatusOK, string(vb)
186 | }
187 |
188 | // 连接redis
189 | func (s *sRedis) initRedis(fileName string) []byte {
190 | // 获取所有连接文件的路径
191 | homeDir, _ := os.File().HomeDir(context.Background())
192 | var filePath strings.Builder
193 | filePath.WriteString(homeDir)
194 | filePath.WriteString(fileName)
195 | filePath.WriteString(".json")
196 | valueByte, _ := ioutil.ReadFile(filePath.String())
197 |
198 | //优先初始化redis链接
199 | redisKit.Port = gjson.Get(string(valueByte), "port").String()
200 | redisKit.Username = gjson.Get(string(valueByte), "username").String()
201 | redisKit.Password = gjson.Get(string(valueByte), "password").String()
202 | redisKit.Addr = gjson.Get(string(valueByte), "hostURL").String()
203 | redisKit.InitDb()
204 | return valueByte
205 | }
206 |
207 | // LoadingDbResource 加载数据库资源消耗信息
208 | func (s *sRedis) LoadingDbResource(ctx context.Context, key string) string {
209 | s.initRedis(key)
210 | return redisKit.Redis().GetMainViewInfo(ctx)
211 | }
212 |
213 | // GetNodeData 获取节点数据
214 | func (s *sRedis) GetNodeData(ctx context.Context, connType, connName, nodeIdStr string) (string, error) {
215 | var value string
216 | if connType == "" ||
217 | connName == "" {
218 | return value, errors.New("parameter is missing")
219 | }
220 | s.initRedis(connName)
221 | nodeId, _ := strconv.Atoi(nodeIdStr)
222 | redisKit.Redis().ChangeDb(ctx, nodeId)
223 | arr, err := redisKit.Redis().GetDbKeys(ctx, 0)
224 | if err != nil {
225 | return "", err
226 | }
227 | value = kit.StrKit().PackageTree(arr)
228 | return value, nil
229 | }
230 |
231 | // RedisGetData 通过key获取连接信息
232 | func (s *sRedis) RedisGetData(ctx context.Context, connType, connName, nodeIdStr, key string) (structs.GetValue, error) {
233 | var getValue structs.GetValue
234 | if connType == "" ||
235 | connName == "" {
236 | return getValue, errors.New("parameter is missing")
237 | }
238 | s.initRedis(connName)
239 | nodeId, _ := strconv.Atoi(nodeIdStr)
240 | redisKit.Redis().ChangeDb(ctx, nodeId)
241 | // 获取数据类型
242 | valueType := redisKit.Redis().GetType(ctx, key)
243 | valueType = strings.ToLower(valueType)
244 | switch valueType {
245 | case "string":
246 | // 获取类型为string的数据
247 | v := redisKit.Redis().GetStrValue(ctx, key)
248 | getValue.Type = "string"
249 | getValue.Key = key
250 | getValue.Ttl = redisKit.Redis().GetTTL(ctx, key)
251 | getValue.Value = v
252 | getValue.Size = len(v)
253 | command := s.BuildCommand(key, "string", v)
254 | getValue.CommandStr = command
255 | return getValue, nil
256 | case "list":
257 | // 获取类型为list的数据
258 | v := redisKit.Redis().GetListValue(ctx, key)
259 | getValue.Type = "list"
260 | getValue.Key = key
261 | getValue.Ttl = redisKit.Redis().GetTTL(ctx, key)
262 | var listValues []structs.RedisList
263 | for i, vv := range v {
264 | listValues = append(listValues, structs.RedisList{
265 | Id: i + 1,
266 | Value: vv,
267 | })
268 | }
269 | getValue.Value = listValues
270 | command := s.BuildCommand(key, "list", v)
271 | getValue.CommandStr = command
272 | return getValue, nil
273 | case "set":
274 | // 获取类型为set的数据
275 | v := redisKit.Redis().GetSetValue(ctx, key)
276 | getValue.Type = "set"
277 | getValue.Key = key
278 | getValue.Ttl = redisKit.Redis().GetTTL(ctx, key)
279 | var setValues []structs.RedisList
280 | for i, vv := range v {
281 | setValues = append(setValues, structs.RedisList{
282 | Id: i + 1,
283 | Value: vv,
284 | })
285 | }
286 | getValue.Value = setValues
287 | command := s.BuildCommand(key, "set", v)
288 | getValue.CommandStr = command
289 | return getValue, nil
290 | case "hash":
291 | // 获取类型为hash的数据
292 | v := redisKit.Redis().GetHashValue(ctx, key)
293 | getValue.Type = "hash"
294 | getValue.Key = key
295 | getValue.Ttl = redisKit.Redis().GetTTL(ctx, key)
296 | var hashValues []structs.RedisHash
297 | var i = 1
298 | for k, vv := range v {
299 | hashValues = append(hashValues, structs.RedisHash{
300 | Id: i,
301 | Key: k,
302 | Value: vv,
303 | })
304 | i++
305 | }
306 | getValue.Value = hashValues
307 | command := s.BuildCommand(key, "hash", v)
308 | getValue.CommandStr = command
309 | return getValue, nil
310 | case "stream":
311 | // 获取类型为stream的数据
312 | v := redisKit.Redis().GetStreamValue(ctx, key)
313 | getValue.Type = "stream"
314 | getValue.Key = key
315 | getValue.Ttl = redisKit.Redis().GetTTL(ctx, key)
316 | var streamValues []structs.RedisHash
317 | for i, vv := range v {
318 | _data, _ := json.Marshal(vv.Values)
319 | streamValues = append(streamValues, structs.RedisHash{
320 | Id: i,
321 | Key: vv.ID,
322 | Value: string(_data),
323 | })
324 | // streamValues = append(streamValues, vv)
325 | }
326 | getValue.Value = streamValues
327 | command := s.BuildCommand(key, "stream", v)
328 | getValue.CommandStr = command
329 | return getValue, nil
330 | case "zset":
331 | // 获取类型为zset的数据
332 | v := redisKit.Redis().GetZSetValue(ctx, key)
333 | getValue.Type = "zset"
334 | getValue.Key = key
335 | getValue.Ttl = redisKit.Redis().GetTTL(ctx, key)
336 | var zsetValues []structs.RedisHash
337 | var i = 1
338 | for mk, mv := range v {
339 | zsetValues = append(zsetValues, structs.RedisHash{
340 | Id: i,
341 | Key: mk,
342 | Value: mv,
343 | })
344 | i++
345 | }
346 | getValue.Value = zsetValues
347 | command := s.BuildCommand(key, "zset", v)
348 | getValue.CommandStr = command
349 | return getValue, nil
350 | default:
351 | return getValue, errors.New("unknown error")
352 | }
353 | }
354 |
355 | // GetValueType 获取指定key的数据类型
356 | func (s *sRedis) GetValueType(ctx context.Context, connName, nodeIdStr, key string) (string, error) {
357 | if connName == "" {
358 | return "", errors.New("parameter is missing")
359 | }
360 | s.initRedis(connName)
361 | s.initRedis(connName)
362 | nodeId, _ := strconv.Atoi(nodeIdStr)
363 | redisKit.Redis().ChangeDb(ctx, nodeId)
364 | // 获取数据类型
365 | valueType := redisKit.Redis().GetType(ctx, key)
366 | return valueType, nil
367 | }
368 |
369 | // RedisReName 重命名key
370 | func (s *sRedis) RedisReName(ctx context.Context, connType, connName, nodeIdStr, oldKey, newKey string) string {
371 | if connType == "" ||
372 | connName == "" {
373 | return "parameter is missing"
374 | }
375 | s.initRedis(connName)
376 | nodeId, _ := strconv.Atoi(nodeIdStr)
377 | redisKit.Redis().ChangeDb(ctx, nodeId)
378 | // 通过键获取值
379 | v := redisKit.Redis().RenName(ctx, oldKey, newKey)
380 | if v != nil {
381 | return v.Error()
382 | }
383 | return "success"
384 | }
385 |
386 | // RedisUpTtl 更新redis剩余时间
387 | func (s *sRedis) RedisUpTtl(ctx context.Context, connType, connName, nodeIdStr, key string, ttlStr string) string {
388 | //todo 当ttl=-1时会出现数据直接丢失的情况
389 | ttl, err := strconv.Atoi(ttlStr)
390 | if err != nil {
391 | return "ttl is not number"
392 | }
393 | if connType == "" ||
394 | connName == "" {
395 | return "parameter is missing"
396 | }
397 | s.initRedis(connName)
398 | nodeId, _ := strconv.Atoi(nodeIdStr)
399 | redisKit.Redis().ChangeDb(ctx, nodeId)
400 | // 通过键获取值
401 | var v error
402 | if ttl == -1 {
403 | // 表示需要永久存储
404 | v = redisKit.Redis().UpPermanent(ctx, key)
405 | } else {
406 | v = redisKit.Redis().UpTtl(ctx, key, ttl)
407 | }
408 | if v != nil {
409 | return v.Error()
410 | }
411 | return "success"
412 | }
413 |
414 | // RedisDel 删除redis数据
415 | func (s *sRedis) RedisDel(ctx context.Context, connType, connName, nodeIdStr, key string) string {
416 | if connType == "" ||
417 | connName == "" {
418 | return "parameter is missing"
419 | }
420 | s.initRedis(connName)
421 | nodeId, _ := strconv.Atoi(nodeIdStr)
422 | redisKit.Redis().ChangeDb(ctx, nodeId)
423 | // 通过键获取值
424 | v := redisKit.Redis().Del(ctx, key)
425 | if v == 0 {
426 | return "del error"
427 | }
428 | return "success"
429 | }
430 |
431 | // RedisUpdateStringValue 更新redis数据
432 | func (s *sRedis) RedisUpdateStringValue(ctx context.Context, connType, connName, nodeIdStr, key, value, ttlStr string) error {
433 | if connType == "" ||
434 | connName == "" {
435 | return errors.New("parameter is missing")
436 | }
437 | s.initRedis(connName)
438 | nodeId, _ := strconv.Atoi(nodeIdStr)
439 | redisKit.Redis().ChangeDb(ctx, nodeId)
440 | // 通过键获取值
441 | ttl, _ := strconv.Atoi(ttlStr)
442 | err := redisKit.Redis().AddData(ctx, key, value, ttl)
443 | if err != nil {
444 | return err
445 | }
446 | return nil
447 | }
448 |
449 | // BuildCommand 构建命令
450 | func (s *sRedis) BuildCommand(key, keyType string, value interface{}) string {
451 | lowerCaseKeyType := strings.ToLower(keyType)
452 | var command strings.Builder
453 | switch lowerCaseKeyType {
454 | case "string":
455 | // 构建set命令
456 | // SET "1:2:34" "你好啊😂"
457 | command.WriteString("SET ")
458 | command.WriteString("\"")
459 | command.WriteString(key)
460 | command.WriteString("\" \"")
461 | command.WriteString(value.(string))
462 | command.WriteString("\"")
463 | case "hash":
464 | // 构建hash命令
465 | //HMSET "1:2:hash" "New field" "New value" "123" "321"
466 | command.WriteString("HMSET ")
467 | command.WriteString("\"")
468 | command.WriteString(key)
469 | arr := value.(map[string]string)
470 | for k, v := range arr {
471 | command.WriteString("\" \"")
472 | command.WriteString(k)
473 | command.WriteString("\" \"")
474 | command.WriteString(v)
475 | }
476 | command.WriteString("\"")
477 | case "list":
478 | // 构建list命令
479 | // RPUSH "1:2:list" "New member" "12312213" "1231" "测试"
480 | // return "RPUSH " + key + " " + value
481 | command.WriteString("RPUSH ")
482 | command.WriteString("\"")
483 | command.WriteString(key)
484 | command.WriteString("\"")
485 | arr := value.([]string)
486 | for _, v := range arr {
487 | command.WriteString(" \"")
488 | command.WriteString(v)
489 | command.WriteString("\"")
490 | }
491 | case "set":
492 | // 构建set命令
493 | // SADD "1:2:set" "New member" "sdfsdf"
494 | // return "SADD " + key + " " + value
495 | command.WriteString("SADD ")
496 | command.WriteString("\"")
497 | command.WriteString(key)
498 | command.WriteString("\"")
499 | arr := value.([]string)
500 | for _, v := range arr {
501 | command.WriteString(" \"")
502 | command.WriteString(v)
503 | command.WriteString("\"")
504 | }
505 | case "zset":
506 | // 构建zset命令
507 | //ZADD "1:2:zset" 12 "321" 0 "New member"
508 | // return "ZADD " + key + " " + value
509 | command.WriteString("ZADD ")
510 | command.WriteString("\"")
511 | command.WriteString(key)
512 | command.WriteString("\" ")
513 | arr := value.(map[string]string)
514 | fmt.Println("=====>", arr)
515 | for k, v := range arr {
516 | command.WriteString(k)
517 | command.WriteString(" \"")
518 | command.WriteString(v)
519 | command.WriteString("\" ")
520 | }
521 | case "stream":
522 | // 构建stream命令
523 | // return "XADD " + key + " " + value
524 | command.WriteString("XADD ")
525 | command.WriteString("\"")
526 | command.WriteString(key)
527 | command.WriteString("\"")
528 | arr := value.([]redis.XMessage)
529 | for _, v := range arr {
530 | command.WriteString(v.ID)
531 | _val := v.Values
532 | for mk, mv := range _val {
533 | command.WriteString(" \"")
534 | command.WriteString(mk)
535 | command.WriteString("\" \"")
536 | command.WriteString(mv.(string))
537 | command.WriteString("\"")
538 | }
539 | }
540 | default:
541 | return ""
542 | }
543 | return command.String()
544 | }
545 |
--------------------------------------------------------------------------------
/todb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xingcxb/ToDb/e039f594c6d84c56122e5d4ee4bb0e67e403f56c/todb.png
--------------------------------------------------------------------------------
/wails.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ToDb",
3 | "assetdir": "frontend/dist",
4 | "frontend:build": "npm run build",
5 | "frontend:install": "npm install",
6 | "frontend:dev": "",
7 | "wailsjsdir": "frontend/src",
8 | "version": "2",
9 | "Path": "",
10 | "BuildDir": "",
11 | "outputfilename": "wails_note.exe",
12 | "OutputType": "",
13 | "Platform": "",
14 | "Author": {
15 | "name": "Symbol",
16 | "email": "xingcxb@hotmail.com"
17 | },
18 | "Info": {
19 | "companyName": "Symbol",
20 | "productName": "ToDb",
21 | "productVersion": "0.1.0",
22 | "copyright": "Copyright©️ 2022- Symbol. All Rights Reserved.",
23 | "comments": "又一个装模作样的数据库连接工具🙄️"
24 | },
25 | "debounceMS": 100,
26 | "devserverurl": "http://localhost:34115",
27 | "appargs": ""
28 | }
--------------------------------------------------------------------------------