Compare commits

...
11 Commits
Author SHA1 Message Date
ygxbnet 0602f1d21d feat(settings): 添加版本信息显示功能
部署开发环境 / deploy-dev (push) Successful in 2m3s
- 在 API 模块中添加获取版本信息的接口方法
- 在设置页面组件中引入 API 并调用版本获取方法
- 使用 onMounted 钩子在组件挂载时获取版本数据
- 将获取到的版本信息绑定到模板中显示
- 完成设置页面的初始功能实现
2026-08-23 00:17:11 +08:00
ygxbnet 54a05c27ab chore(deps): 更新项目依赖版本
部署开发环境 / deploy-dev (push) Successful in 1m32s
- 将 Element Plus 相关导入语句注释掉
- 更新 axios 从 1.16.1 到 1.19.0 版本
- 更新 element-plus 从 2.14.1 到 2.14.4 版本
- 更新 vue 从 3.5.35 到 3.5.41 版本
- 更新 vue-router 从 5.1.0 到 5.2.0 版本
- 更新 @tailwindcss/vite 和 tailwindcss 至 4.3.3 版本
- 更新 pinia 从 3.0.4 到 4.0.3 版本
- 更新 devDependencies 中多个开发工具包版本
- 在类型声明文件中添加 oxlint 和 oxfmt 的忽略注释
2026-08-22 23:57:33 +08:00
ygxbnet bce8d30108 chore(deps): 更新项目依赖版本
部署开发环境 / deploy-dev (push) Successful in 4m0s
- 将 Go 版本从 1.26 升级到 1.27
- 更新 gin 框架从 v1.10.1 到 v1.12.0
- 更新 redis 客户端从 v9.12.1 到 v9.22.0
- 更新 viper 库从 v1.20.1 到 v1.21.0
- 更新多个间接依赖包到最新版本
- 添加了新的依赖包包括 go.mongodb.org/mongo-driver/v2 和相关工具库
2026-08-20 22:31:20 +08:00
ygxbnet 8dae755df2 refactor(token): 简化循环中的条件判断逻辑
部署开发环境 / deploy-dev (push) Successful in 1m13s
- 使用 min 函数替代 if-else 条件判断
- 减少代码行数提高可读性
- 保持原有功能不变
2026-07-27 00:44:25 +08:00
ygxbnet 9105cba067 chore(build): 更新自动导入配置以优化类型定义文件位置
部署开发环境 / deploy-dev (push) Successful in 3m0s
- 将 auto-imports.d.ts 和 components.d.ts 移至 src/types/import 目录
- 修改 tsconfig.app.json 配置以排除旧的类型定义文件路径
- 在 vite.config.ts 中更新类型定义文件输出路径配置
- 重新生成组件和自动导入的类型声明文件
2026-07-17 23:48:37 +08:00
ygxbnet fe16e8b2f9 fix(token): 修复去重选项标签显示问题
部署开发环境 / deploy-dev (push) Successful in 1m53s
- 将'不用去重'修改为'不去重'以保持表述一致性
2026-07-09 00:35:02 +08:00
ygxbnet bc15b19474 feat(data): 添加数据不去重功能
部署开发环境 / deploy-dev (push) Successful in 2m6s
- 在数据控制器中引入去重对象逻辑
- 根据去重对象配置决定是否执行去重操作
- 当去重对象为 false 时不进行去重直接写入数据库
- 在管理界面令牌管理页面添加不去重选项
- 表格中显示去重对象时将 false 显示为不去重中文描述
2026-07-09 00:21:04 +08:00
ygxbnet ac72b80505 feat(admin): 添加数据格式选项自定义功能
部署开发环境 / deploy-dev (push) Successful in 1m46s
- 在TokenManageView中增加自定义数据格式选项功能
- 实现添加数据格式按钮和输入框界面
- 添加确认和取消操作按钮
- 支持动态添加新的数据格式选项到下拉列表
- 整理数据格式选项顺序保持一致性
- 添加输入验证确保选项名称不为空
2026-07-07 23:55:01 +08:00
ygxbnet 080d62621e refactor(ui): 重构UI组件样式和对话框功能
部署开发环境 / deploy-dev (push) Successful in 1m54s
- 将 AddDataDialog 组件的布局改为 flex 布局并移除自定义 CSS 类
- 更新 TokenDetailView 的整体布局结构,使用 Tailwind CSS 类替换原生样式
- 优化 TokenManageView 的表单和表格界面,调整响应式设计
- 移除 Element Plus ElContainer 组件的引用
- 合并多个编辑对话框为统一的数据编辑对话框
- 优化进度条和标签的显示样式
- 调整按钮和表单项的间距和对齐方式
2026-07-07 23:38:23 +08:00
ygxbnet 7c9bb58806 更新 web/src/views/admin/TokenManageView.vue
部署开发环境 / deploy-dev (push) Successful in 1m36s
2026-07-06 04:58:06 +00:00
ygxbnet d21a1adfb2 更新 web/src/views/admin/TokenManageView.vue
部署开发环境 / deploy-dev (push) Failing after 2m38s
2026-07-06 04:51:46 +00:00
16 changed files with 1341 additions and 1426 deletions
+36 -34
View File
@@ -1,50 +1,52 @@
module dypid
go 1.26
go 1.27
require (
github.com/gin-contrib/cors v1.7.6
github.com/gin-gonic/gin v1.10.1
github.com/redis/go-redis/v9 v9.12.1
github.com/spf13/viper v1.20.1
github.com/gin-contrib/cors v1.7.7
github.com/gin-gonic/gin v1.12.0
github.com/redis/go-redis/v9 v9.22.0
github.com/spf13/viper v1.21.0
)
require (
github.com/bytedance/sonic v1.13.3 // indirect
github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/bytedance/gopkg v0.1.4 // indirect
github.com/bytedance/sonic v1.15.2 // indirect
github.com/bytedance/sonic/loader v0.5.2 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
github.com/gin-contrib/sse v1.1.0 // indirect
github.com/cloudwego/base64x v0.1.7 // indirect
github.com/fsnotify/fsnotify v1.10.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.15 // indirect
github.com/gin-contrib/sse v1.1.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.26.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/go-playground/validator/v10 v10.30.3 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/goccy/go-json v0.10.6 // indirect
github.com/goccy/go-yaml v1.19.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/klauspost/cpuid/v2 v2.4.0 // indirect
github.com/leodido/go-urn v1.5.0 // indirect
github.com/mattn/go-isatty v0.0.24 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.12.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/pelletier/go-toml/v2 v2.4.3 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.61.0 // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.18.0 // indirect
golang.org/x/crypto v0.39.0 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/sys v0.35.0 // indirect
golang.org/x/text v0.26.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
github.com/ugorji/go/codec v1.3.2 // indirect
go.mongodb.org/mongo-driver/v2 v2.8.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.yaml.in/yaml/v3 v3.0.5 // indirect
golang.org/x/arch v0.30.0 // indirect
golang.org/x/crypto v0.55.0 // indirect
golang.org/x/net v0.58.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/text v0.41.0 // indirect
google.golang.org/protobuf v1.36.12 // indirect
)
+82 -77
View File
@@ -2,124 +2,129 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/bytedance/sonic v1.13.3 h1:MS8gmaH16Gtirygw7jV91pDCN33NyMrPbN7qiYhEsF0=
github.com/bytedance/sonic v1.13.3/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM=
github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4=
github.com/bytedance/sonic v1.15.2 h1:90H+rcF/FwLXwfB1cudOLq/je83n683Utf4Cbp0xHCo=
github.com/bytedance/sonic v1.15.2/go.mod h1:mT2NbXunuaEbnZ+mRIX/vYqKISmgEuHFDI4UzmKx2SA=
github.com/bytedance/sonic/loader v0.5.2 h1:0QtP1gevc1OZ6/H8Lb9BRZiCXd1Ftjd3OKuj1T1lBIo=
github.com/bytedance/sonic/loader v0.5.2/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/cloudwego/base64x v0.1.7 h1:NppS+Fgzg5ovhn4NkUXaDT3x9jldgH5ToMCqzBSi2zI=
github.com/cloudwego/base64x v0.1.7/go.mod h1:Cu1PV9zfrSf7ET2tIbWbbEy7jO7HHJ13q4X2SQ8aWYg=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
github.com/gin-contrib/cors v1.7.6 h1:3gQ8GMzs1Ylpf70y8bMw4fVpycXIeX1ZemuSQIsnQQY=
github.com/gin-contrib/cors v1.7.6/go.mod h1:Ulcl+xN4jel9t1Ry8vqph23a60FwH9xVLd+3ykmTjOk=
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
github.com/gabriel-vasile/mimetype v1.4.15 h1:05iP/CYtZ/w455R/KZM6rZ5ieAdh99UPtd+d3YzLmaI=
github.com/gabriel-vasile/mimetype v1.4.15/go.mod h1:azpTcoLcDZRNgFou5j+APrqQx9HqVPWa6ijYQIIVswQ=
github.com/gin-contrib/cors v1.7.7 h1:Oh9joP463x7Mw72vhvJ61YQm8ODh9b04YR7vsOErD0Q=
github.com/gin-contrib/cors v1.7.7/go.mod h1:K5tW0RkzJtWSiOdikXloy8VEZlgdVNpHNw8FpjUPNrE=
github.com/gin-contrib/sse v1.1.1 h1:uGYpNwTacv5R68bSGMapo62iLTRa9l5zxGCps4hK6ko=
github.com/gin-contrib/sse v1.1.1/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s=
github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8=
github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/go-playground/validator/v10 v10.30.3 h1:4MU6YkEwx7GbcPJOZxrtbu+QfF3pJLJuaYTeAH0DYy8=
github.com/go-playground/validator/v10 v10.30.3/go.mod h1:4Axh7oCNGcoGkqLoE4YWt6n20mcEIsPRlB7vPk3lpyc=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/goccy/go-json v0.10.6 h1:p8HrPJzOakx/mn/bQtjgNjdTcN+/S6FcG2CTtQOrHVU=
github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw=
github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/leodido/go-urn v1.5.0 h1:pLqT2kq1zpHW/1D18QMjMpdtX7cekxqtJJjg5ANyWw0=
github.com/leodido/go-urn v1.5.0/go.mod h1:9BORnCDhdPBJNDEX+w1bJisa8yOKYi116VeO96s4ifE=
github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pelletier/go-toml/v2 v2.4.3 h1:GTRvJQutkOSftxIFD5xw9aepkYNuPWmVJpffdDPYVpY=
github.com/pelletier/go-toml/v2 v2.4.3/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.12.1 h1:k5iquqv27aBtnTm2tIkROUDp8JBXhXZIVu1InSgvovg=
github.com/redis/go-redis/v9 v9.12.1/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/quic-go/go-ossfuzz-seeds v0.1.0 h1:APacT+iIaNF6fd8AGEiN3bT/Jtkd2jz4v4TzM7MFjy0=
github.com/quic-go/go-ossfuzz-seeds v0.1.0/go.mod h1:3IOHRbJIc+L6YKMwfDtJAM9Vj9k0YY4muhuyUYk5tbk=
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
github.com/quic-go/quic-go v0.61.0 h1:ui88A53s8MSVYLC56en0KQ17HARk+9986Dn0SBfKNvA=
github.com/quic-go/quic-go v0.61.0/go.mod h1:9So2anK4Tp22URSQq00k+Vo2PNkle96ycDPDHL4s9vs=
github.com/redis/go-redis/v9 v9.22.0 h1:laDvpYXTJtZLloinw1fA5Kqd6HAEH2XKxOkG/PDq2F0=
github.com/redis/go-redis/v9 v9.22.0/go.mod h1:y2g0Wj8rQvuK0ELM+oxSudcLtC09JScs98I/X9gRWY4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
golang.org/x/arch v0.18.0 h1:WN9poc33zL4AzGxqf8VtpKUnGvMi8O9lhNyBMF/85qc=
golang.org/x/arch v0.18.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
github.com/ugorji/go/codec v1.3.2 h1:zkEASHHyEClGeURfgNT9PJZVfAbs9oEX9QXggwWNJbc=
github.com/ugorji/go/codec v1.3.2/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s=
go.mongodb.org/mongo-driver/v2 v2.8.0 h1:CxWDGQYY8QQwNjAl/aq2sfWakdnWZynnqJ9F4DhHbP8=
go.mongodb.org/mongo-driver/v2 v2.8.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
golang.org/x/arch v0.30.0 h1:sB9h+1gRGa2+LauFSV0tm8bK1J2yo1bx6/Uyi/P6DTU=
golang.org/x/arch v0.30.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8=
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
+16 -1
View File
@@ -3,6 +3,7 @@ package controller
import (
"dypid/internal/db"
"dypid/internal/global"
"dypid/internal/model"
"fmt"
"net/http"
"strings"
@@ -41,12 +42,26 @@ func WriteDataHandler(c *gin.Context) {
return
}
//数据获取
//获取去重对象
dedupObject, err := db.GetDedupObject(input.Token)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
//判断数据是否需要去重
//如果数据不需要去重则直接写入数据库
if dedupObject == "false" {
global.RDB.LPush(global.RCtx, fmt.Sprintf("list:%s", input.Token), input.Data)
c.JSON(http.StatusOK, model.APIResponse{
Code: 200,
Message: "数据写入成功",
})
return
}
//数据要去重,下面函数会执行
//获取数据索引
dataIndex, err := getDataIndex(input.Token)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+9 -16
View File
@@ -180,12 +180,13 @@ func GetTokenInfoHandler(c *gin.Context) {
DataFormat string `json:"data_format"`
DedupItemsNumber int64 `json:"dedup_items_number"`
CacheListNumber int64 `json:"cache_list_number"`
}{}
output.Token = input.Token
output.DedupObject = dedupObject
output.DataFormat = dataFormat
output.DedupItemsNumber = global.RDB.CFInfo(global.RCtx, "dedup:"+input.Token+":"+dedupObject).Val().NumItemsInserted
output.CacheListNumber = global.RDB.LLen(global.RCtx, "list:"+input.Token).Val()
}{
Token: input.Token,
DedupObject: dedupObject,
DataFormat: dataFormat,
DedupItemsNumber: global.RDB.CFInfo(global.RCtx, "dedup:"+input.Token+":"+dedupObject).Val().NumItemsInserted,
CacheListNumber: global.RDB.LLen(global.RCtx, "list:"+input.Token).Val(),
}
c.JSON(http.StatusOK, model.APIResponse{
Code: 200,
@@ -248,11 +249,7 @@ func DeleteTokenInfoHandler(c *gin.Context) {
for i := num; i > 0; i -= 20_0000 {
a := 0
if i > 20_0000 {
a = 20_0000
} else {
a = i
}
a = min(i, 20_0000)
//获得要删的值(列表)
result := global.RDB.LRange(global.RCtx, "delete-list:"+input.Token, int64(-a), -1).Val()
@@ -310,11 +307,7 @@ func DeleteTokenInfoHandler(c *gin.Context) {
for i := num; i > 0; i -= 20_0000 {
a := 0
if i > 20_0000 {
a = 20_0000
} else {
a = i
}
a = min(i, 20_0000)
result := global.RDB.LRange(global.RCtx, "delete-list:"+input.Token, int64(-a), -1).Val()
_, err = global.RDB.TxPipelined(global.RCtx, func(pipe redis.Pipeliner) error {
+15 -15
View File
@@ -12,27 +12,27 @@
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.2",
"@tailwindcss/vite": "^4.3.0",
"axios": "^1.16.1",
"element-plus": "^2.14.1",
"pinia": "^3.0.4",
"@tailwindcss/vite": "^4.3.3",
"axios": "^1.19.0",
"element-plus": "^2.14.5",
"pinia": "^4.0.3",
"pinia-plugin-persistedstate": "^4.7.1",
"tailwindcss": "^4.3.0",
"vue": "^3.5.35",
"vue-router": "^5.1.0"
"tailwindcss": "^4.3.3",
"vue": "^3.5.41",
"vue-router": "^5.2.0"
},
"devDependencies": {
"@tsconfig/node24": "^24.0.4",
"@types/node": "^24.12.4",
"@vitejs/plugin-vue": "^6.0.7",
"@tsconfig/node24": "^24.0.5",
"@types/node": "^24.13.3",
"@vitejs/plugin-vue": "^6.0.8",
"@vue/tsconfig": "^0.9.1",
"npm-run-all2": "^8.0.4",
"npm-run-all2": "^9.0.3",
"typescript": "~6.0.3",
"unplugin-auto-import": "^21.0.0",
"unplugin-auto-import": "^21.1.0",
"unplugin-vue-components": "^32.1.0",
"vite": "^8.0.16",
"vite-plugin-vue-devtools": "^8.1.2",
"vue-tsc": "^3.3.3"
"vite": "^8.2.2",
"vite-plugin-vue-devtools": "^8.2.1",
"vue-tsc": "^3.3.11"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
+775 -580
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -5,6 +5,9 @@ const axiosInstance = axios.create({
})
export default {
getVersion:() =>
axiosInstance.get('/api/version'),
getTokenList: () =>
axiosInstance.get('/api/token'),
+6 -35
View File
@@ -70,7 +70,7 @@ const handleUpload = async () => {
<el-tag type="primary" effect="plain">{{ props.token }}</el-tag>
</template>
<div class="add-data-dialog">
<div class="flex flex-col gap-4">
<el-input
v-model="inputData"
type="textarea"
@@ -80,13 +80,14 @@ const handleUpload = async () => {
class="textarea-input"
/>
<div class="footer">
<div class="progress">
<div class="flex justify-between items-center gap-4">
<div class="flex-1 flex items-center gap-3">
<el-progress
:percentage="totalCount > 0 ? Math.round((uploadedCount / totalCount) * 100) : 0"
:show-text="false"
class="flex-1"
/>
<span class="progress-text">已上传 {{ uploadedCount }}/{{ totalCount }} </span>
<span class="text-sm text-[var(--el-text-color-secondary)] whitespace-nowrap">已上传 {{ uploadedCount }}/{{ totalCount }} </span>
</div>
<el-button
@@ -105,39 +106,9 @@ const handleUpload = async () => {
</template>
<style scoped>
.add-data-dialog {
display: flex;
flex-direction: column;
gap: 16px;
}
.textarea-input :deep(.el-textarea__inner) {
overflow-x: auto;
white-space: pre;
word-break: keep-all;
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
gap: 16px;
}
.progress {
flex: 1;
display: flex;
align-items: center;
gap: 12px;
}
.progress-text {
font-size: 14px;
color: var(--el-text-color-secondary);
white-space: nowrap;
}
.footer .el-progress {
flex: 1;
}
</style>
</style>
+3 -3
View File
@@ -3,8 +3,8 @@ import {createPinia} from 'pinia'
import persistedState from 'pinia-plugin-persistedstate';
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// import ElementPlus from 'element-plus'
// import 'element-plus/dist/index.css'
import './assets/main.css'
const pinia = createPinia()
@@ -13,7 +13,7 @@ pinia.use(persistedState)
const app = createApp(App)
app.use(pinia)
app.use(router)
app.use(ElementPlus)
// app.use(ElementPlus)
app.mount('#app')
@@ -1,5 +1,7 @@
/* eslint-disable */
/* prettier-ignore */
/* oxlint-disable */
/* oxfmt-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
@@ -11,12 +11,11 @@ export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
AddDataDialog: typeof import('./src/components/AddDataDialog.vue')['default']
AddDataDialog: typeof import('./../../components/AddDataDialog.vue')['default']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCollapse: typeof import('element-plus/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
ElContainer: typeof import('element-plus/es')['ElContainer']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDivider: typeof import('element-plus/es')['ElDivider']
ElDropdown: typeof import('element-plus/es')['ElDropdown']
+10 -1
View File
@@ -1,7 +1,16 @@
<script setup lang="ts">
import api from "@/api.ts";
const version = ref('')
onMounted(() => {
api.getVersion().then((response) => {
version.value = response.data
})
})
</script>
<template>
TODO
{{ version }}
</template>
+143 -322
View File
@@ -142,354 +142,175 @@ const statCards = [
</script>
<template>
<div class="token-detail">
<div class="mx-auto w-full">
<!-- 管理页面 -->
<div class="detail-page">
<div class="content-card">
<div class="page-title">Token 详情</div>
<div class="bg-white rounded-lg p-6 shadow-[0_2px_12px_rgba(0,0,0,0.08)]">
<div class="text-xl font-semibold text-(--el-text-color-primary) mb-5 pb-3 border-b border-(--el-border-color)">
Token 详情
</div>
<!-- 选择 Token -->
<div class="token-select">
<el-select v-model="value" placeholder="选择 Token" clearable style="width: 100%; max-width: 300px">
<el-option v-for="item in options" :key="item" :value="item" :label="item"/>
</el-select>
<el-button type="primary" @click="refresh" :loading="loading">
<el-icon>
<Refresh/>
</el-icon>
刷新
</el-button>
<span v-if="lastUpdate" class="update-time">上次更新: {{ lastUpdate }}</span>
<!-- 选择 Token -->
<div class="flex items-center gap-3 mb-6 flex-wrap max-md:flex-col max-md:items-stretch">
<el-select v-model="value" placeholder="选择 Token" clearable style="width: 100%; max-width: 300px">
<el-option v-for="item in options" :key="item" :value="item" :label="item"/>
</el-select>
<el-button type="primary" @click="refresh" :loading="loading">
<el-icon>
<Refresh/>
</el-icon>
刷新
</el-button>
<span v-if="lastUpdate" class="text-xs text-(--el-text-color-secondary)">上次更新: {{ lastUpdate }}</span>
</div>
<!-- Token 信息 -->
<div v-if="result && value" class="animate-fade-in">
<div class="text-base font-semibold text-(--el-text-color-primary) mt-5 mb-4">Token 信息</div>
<div class="grid grid-cols-4 gap-4 mb-8 max-xl:grid-cols-2 max-md:grid-cols-1">
<div v-for="card in statCards" :key="card.key"
class="flex items-center gap-4 p-5 bg-(--bg-page) rounded-xl transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_4px_16px_rgba(0,0,0,0.1)]">
<div class="w-14 h-14 rounded-xl flex items-center justify-center shrink-0"
:style="{ background: card.color + '20', color: card.color }">
<el-icon size="24">
<component :is="card.icon"/>
</el-icon>
</div>
<div class="flex-1 min-w-0">
<div class="text-xs text-(--el-text-color-secondary) mb-1">{{ card.label }}</div>
<div class="text-lg font-semibold text-(--el-text-color-primary)">{{ result[card.key] || '-' }}</div>
</div>
</div>
</div>
<!-- Token 信息 -->
<div v-if="result && value" class="info-section">
<div class="section-title">Token 信息</div>
<!-- 管理操作 -->
<div class="mt-8">
<div class="text-base font-semibold text-(--el-text-color-primary) mt-5 mb-4">数据管理</div>
<div class="stat-cards">
<div v-for="card in statCards" :key="card.key" class="stat-card">
<div class="stat-icon" :style="{ background: card.color + '20', color: card.color }">
<el-icon size="24">
<component :is="card.icon"/>
<div class="grid grid-cols-3 gap-4 max-xl:grid-cols-2 max-md:grid-cols-1">
<div
class="flex items-center gap-4 p-5 bg-(--bg-page) rounded-xl transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_4px_16px_rgba(0,0,0,0.1)] max-md:flex-col max-md:text-center">
<div
class="w-14 h-14 rounded-xl flex items-center justify-center shrink-0 bg-(--el-color-primary) text-white">
<el-icon size="28">
<Delete/>
</el-icon>
</div>
<div class="stat-content">
<div class="stat-label">{{ card.label }}</div>
<div class="stat-value">{{ result[card.key] || '-' }}</div>
<div class="flex-1 min-w-0">
<div class="text-base font-semibold text-(--el-text-color-primary) mb-1">删除全部去重参考值</div>
<div class="text-xs text-(--el-text-color-secondary)">清除该 Token 的所有去重布隆过滤器</div>
</div>
<el-button type="danger" @click="deleteDedup">执行</el-button>
</div>
<div
class="flex items-center gap-4 p-5 bg-(--bg-page) rounded-xl transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_4px_16px_rgba(0,0,0,0.1)] max-md:flex-col max-md:text-center">
<div
class="w-14 h-14 rounded-xl flex items-center justify-center shrink-0 bg-(--el-color-primary) text-white">
<el-icon size="28">
<Delete/>
</el-icon>
</div>
<div class="flex-1 min-w-0">
<div class="text-base font-semibold text-(--el-text-color-primary) mb-1">删除全部原始数据</div>
<div class="text-xs text-(--el-text-color-secondary)">清除该 Token 的所有原始缓存数据</div>
</div>
<el-button type="danger" @click="deleteRedis">执行</el-button>
</div>
</div>
<!-- 管理操作 -->
<div class="manage-section">
<div class="section-title">数据管理</div>
<div class="text-sm font-semibold text-(--el-text-color-secondary) mt-6 mb-4">按数量删除</div>
<div class="action-grid">
<div class="action-card danger">
<div class="action-icon">
<el-icon size="28">
<Delete/>
</el-icon>
</div>
<div class="action-info">
<div class="action-label">删除全部去重参考值</div>
<div class="action-desc">清除该 Token 的所有去重布隆过滤器</div>
</div>
<el-button type="danger" @click="deleteDedup">执行</el-button>
<div class="grid grid-cols-3 gap-4 max-xl:grid-cols-2 max-md:grid-cols-1">
<div
class="flex items-center gap-4 p-5 bg-(--bg-page) rounded-xl transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_4px_16px_rgba(0,0,0,0.1)] max-md:flex-col max-md:text-center">
<div
class="w-14 h-14 rounded-xl flex items-center justify-center shrink-0 bg-(--el-color-warning) text-white">
<el-icon size="28">
<Search/>
</el-icon>
</div>
<div class="action-card danger">
<div class="action-icon">
<el-icon size="28">
<Delete/>
</el-icon>
</div>
<div class="action-info">
<div class="action-label">删除全部原始数据</div>
<div class="action-desc">清除该 Token 的所有原始缓存数据</div>
</div>
<el-button type="danger" @click="deleteRedis">执行</el-button>
<div class="flex-1 min-w-0">
<div class="text-base font-semibold text-(--el-text-color-primary) mb-1">删除指定数量去重参考值</div>
<div class="text-xs text-(--el-text-color-secondary)">指定要删除的去重参考值数量</div>
</div>
<el-button type="warning" @click="deleteSpecifyDedupVisible = true">指定</el-button>
</div>
<div class="section-subtitle">按数量删除</div>
<div class="action-grid">
<div class="action-card">
<div class="action-icon warning">
<el-icon size="28">
<Search/>
</el-icon>
</div>
<div class="action-info">
<div class="action-label">删除指定数量去重参考值</div>
<div class="action-desc">指定要删除的去重参考值数量</div>
</div>
<el-button type="warning" @click="deleteSpecifyDedupVisible = true">指定</el-button>
<div
class="flex items-center gap-4 p-5 bg-(--bg-page) rounded-xl transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_4px_16px_rgba(0,0,0,0.1)] max-md:flex-col max-md:text-center">
<div
class="w-14 h-14 rounded-xl flex items-center justify-center shrink-0 bg-(--el-color-warning) text-white">
<el-icon size="28">
<Search/>
</el-icon>
</div>
<div class="action-card">
<div class="action-icon warning">
<el-icon size="28">
<Search/>
</el-icon>
</div>
<div class="action-info">
<div class="action-label">删除指定数量原始数据</div>
<div class="action-desc">指定要删除的原始数据数量</div>
</div>
<el-button type="warning" @click="deleteSpecifyRawVisible = true">指定</el-button>
<div class="flex-1 min-w-0">
<div class="text-base font-semibold text-(--el-text-color-primary) mb-1">删除指定数量原始数据</div>
<div class="text-xs text-(--el-text-color-secondary)">指定要删除的原始数据数量</div>
</div>
<el-button type="warning" @click="deleteSpecifyRawVisible = true">指定</el-button>
</div>
<div class="action-card">
<div class="action-icon warning">
<el-icon size="28">
<Search/>
</el-icon>
</div>
<div class="action-info">
<div class="action-label">删除指定数量数据</div>
<div class="action-desc">同时删除去重参考值和原始数据</div>
</div>
<el-button type="warning" @click="deleteSpecifyDataVisible = true">指定</el-button>
<div
class="flex items-center gap-4 p-5 bg-(--bg-page) rounded-xl transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_4px_16px_rgba(0,0,0,0.1)] max-md:flex-col max-md:text-center">
<div
class="w-14 h-14 rounded-xl flex items-center justify-center shrink-0 bg-(--el-color-warning) text-white">
<el-icon size="28">
<Search/>
</el-icon>
</div>
<div class="flex-1 min-w-0">
<div class="text-base font-semibold text-(--el-text-color-primary) mb-1">删除指定数量数据</div>
<div class="text-xs text-(--el-text-color-secondary)">同时删除去重参考值和原始数据</div>
</div>
<el-button type="warning" @click="deleteSpecifyDataVisible = true">指定</el-button>
</div>
</div>
</div>
<!-- 空状态 -->
<div v-else-if="value" class="empty-state">
<el-icon size="64" color="#dcdfe6">
<InfoFilled/>
</el-icon>
<div class="empty-text">暂无数据</div>
</div>
<!-- 未选择 -->
<div v-else class="empty-state">
<el-icon size="64" color="#dcdfe6">
<Key/>
</el-icon>
<div class="empty-text">请选择 Token 查看详情</div>
</div>
</div>
<!-- 删除确认对话框 -->
<el-dialog v-model="deleteSpecifyDedupVisible" title="删除指定数量去重参考值" width="400">
<el-input v-model="inputSpecifyDedup" placeholder="请输入删除数量" type="number"/>
<!-- 空状态 -->
<div v-else-if="value" class="flex flex-col items-center p-16 text-(--el-text-color-secondary)">
<el-icon size="64" color="#dcdfe6">
<InfoFilled/>
</el-icon>
<div class="mt-4 text-[15px]">暂无数据</div>
</div>
<template #footer>
<el-button @click="deleteSpecifyDedupVisible = false">取消</el-button>
<el-button type="primary" @click="deleteSpecifyDedup" :loading="isLoading">确定</el-button>
</template>
</el-dialog>
<el-dialog v-model="deleteSpecifyRawVisible" title="删除指定数量原始数据" width="400">
<el-input v-model="inputSpecifyRaw" placeholder="请输入删除数量" type="number"/>
<template #footer>
<el-button @click="deleteSpecifyRawVisible = false">取消</el-button>
<el-button type="primary" @click="deleteSpecifyRaw" :loading="isLoading">确定</el-button>
</template>
</el-dialog>
<el-dialog v-model="deleteSpecifyDataVisible" title="删除指定数量数据" width="400">
<el-input v-model="inputSpecifyData" placeholder="请输入删除数量" type="number"/>
<template #footer>
<el-button @click="deleteSpecifyDataVisible = false">取消</el-button>
<el-button type="primary" @click="deleteSpecifyData" :loading="isLoading">确定</el-button>
</template>
</el-dialog>
<!-- 未选择 -->
<div v-else class="flex flex-col items-center p-16 text-(--el-text-color-secondary)">
<el-icon size="64" color="#dcdfe6">
<Key/>
</el-icon>
<div class="mt-4 text-[15px]">请选择 Token 查看详情</div>
</div>
</div>
<!-- 删除确认对话框 -->
<el-dialog v-model="deleteSpecifyDedupVisible" title="删除指定数量去重参考值" width="400">
<el-input v-model="inputSpecifyDedup" placeholder="请输入删除数量" type="number"/>
<template #footer>
<el-button @click="deleteSpecifyDedupVisible = false">取消</el-button>
<el-button type="primary" @click="deleteSpecifyDedup" :loading="isLoading">确定</el-button>
</template>
</el-dialog>
<el-dialog v-model="deleteSpecifyRawVisible" title="删除指定数量原始数据" width="400">
<el-input v-model="inputSpecifyRaw" placeholder="请输入删除数量" type="number"/>
<template #footer>
<el-button @click="deleteSpecifyRawVisible = false">取消</el-button>
<el-button type="primary" @click="deleteSpecifyRaw" :loading="isLoading">确定</el-button>
</template>
</el-dialog>
<el-dialog v-model="deleteSpecifyDataVisible" title="删除指定数量数据" width="400">
<el-input v-model="inputSpecifyData" placeholder="请输入删除数量" type="number"/>
<template #footer>
<el-button @click="deleteSpecifyDataVisible = false">取消</el-button>
<el-button type="primary" @click="deleteSpecifyData" :loading="isLoading">确定</el-button>
</template>
</el-dialog>
</div>
</template>
<style scoped>
.token-detail {
margin: 0 auto;
width: 100%;
padding: 0;
}
/* Token 选择 */
.token-select {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 24px;
flex-wrap: wrap;
}
.update-time {
font-size: 13px;
color: var(--el-text-color-secondary);
}
/* 信息卡片 */
.info-section {
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.stat-cards {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
margin-bottom: 32px;
}
.stat-card {
display: flex;
align-items: center;
gap: 16px;
padding: 20px;
background: var(--bg-page);
border-radius: 12px;
transition: transform 0.2s, box-shadow 0.2s;
}
.stat-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}
.stat-icon {
width: 56px;
height: 56px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
}
.stat-label {
font-size: 13px;
color: var(--el-text-color-secondary);
margin-bottom: 4px;
}
.stat-value {
font-size: 18px;
font-weight: 600;
color: var(--el-text-color-primary);
word-break: break-all;
}
/* 管理操作 */
.manage-section {
margin-top: 32px;
}
.section-subtitle {
font-size: 14px;
font-weight: 600;
color: var(--el-text-color-secondary);
margin: 24px 0 16px;
}
.action-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.action-card {
display: flex;
align-items: center;
gap: 16px;
padding: 20px;
background: var(--bg-page);
border-radius: 12px;
transition: transform 0.2s, box-shadow 0.2s;
}
.action-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}
.action-icon {
width: 56px;
height: 56px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
background: var(--el-color-primary);
color: #fff;
}
.action-icon.warning {
background: var(--el-color-warning);
}
.action-info {
flex: 1;
min-width: 0;
}
.action-label {
font-size: 15px;
font-weight: 600;
color: var(--el-text-color-primary);
margin-bottom: 4px;
}
.action-desc {
font-size: 13px;
color: var(--el-text-color-secondary);
}
/* 空状态 */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
padding: 64px;
color: var(--el-text-color-secondary);
}
.empty-text {
margin-top: 16px;
font-size: 15px;
}
@media (max-width: 1200px) {
.stat-cards {
grid-template-columns: repeat(2, 1fr);
}
.action-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 768px) {
.token-select {
flex-direction: column;
align-items: stretch;
}
.stat-cards {
grid-template-columns: 1fr;
}
.action-grid {
grid-template-columns: 1fr;
}
.action-card {
flex-direction: column;
text-align: center;
}
}
</style>
+238 -338
View File
@@ -9,27 +9,52 @@ const router = useRouter()
const tableData = ref<any[]>([])
const loading = ref(false)
const input = ref('')
const value = ref('')
const dataFormat = ref('')
const inputDedupObject = ref('')
const inputDataFormat = ref('')
const inputNotes = ref('')
const activeNames = ref(['1'])
const rowOut = ref<any>(null)
const addDataDialogVisible = ref(false)
const dedupObjectVisible = ref(false)
const dataFormatVisible = ref(false)
const inputNotesVisible = ref(false)
const dataDialogVisible = ref(false)
const isAdding = ref(false)
const optionName = ref('')
const onAddOption = () => {
isAdding.value = true
}
const onConfirm = () => {
if (optionName.value) {
dataFormatOptions.push({
label: optionName.value,
value: optionName.value,
})
clear()
}
}
const clear = () => {
optionName.value = ''
isAdding.value = false
}
const options = [
{value: 'false', label: '不去重'},
{value: 'uid', label: 'uid'},
{value: 'secid', label: 'secid'},
{value: 'pid', label: 'pid'},
{value: 'comment_id', label: 'comment_id'},
{value: 'dyid', label: 'dyid'}
{value: 'dyid', label: 'dyid'},
{value: "弹幕ID", label: "弹幕ID"}
]
const dataFormatOptions = [
{value: 'uid----secid----pid----comment_id', label: 'uid----secid----pid----comment_id'},
{value: "uid----pid----弹幕ID", label: "uid----pid----弹幕ID"},
{value: 'uid----secid', label: 'uid----secid'},
{value: 'dyid', label: 'dyid'}
]
@@ -44,32 +69,26 @@ const fetchTokens = async () => {
}
}
onMounted(() => {
if (store.isAdmin) {
fetchTokens()
}
})
const addToken = async () => {
if (!input.value || !value.value || !dataFormat.value) {
if (!input.value || !inputDedupObject.value || !inputDataFormat.value) {
ElMessage.warning('请填写完整信息')
return
}
try {
await api.createToken({
token: input.value,
dedup_object: value.value,
data_format: dataFormat.value,
dedup_object: inputDedupObject.value,
data_format: inputDataFormat.value,
notes: inputNotes.value,
})
ElMessage({message: '添加成功', type: 'success'})
input.value = ''
value.value = ''
dataFormat.value = ''
inputDedupObject.value = ''
inputDataFormat.value = ''
inputNotes.value = ''
fetchTokens()
} catch (error: any) {
ElMessage.error(error.response?.data?.error || '添加失败')
ElMessage.error('添加失败' + error.response?.data?.error)
}
}
@@ -78,75 +97,38 @@ const viewDetails = (row: any) => {
router.push({name: "TokenDetail"})
}
const dialogDedupObjectVisible = (row: any) => {
rowOut.value = row
value.value = row.dedup_object
dedupObjectVisible.value = true
}
const dialogDataFormatVisible = (row: any) => {
rowOut.value = row
dataFormat.value = row.data_format
dataFormatVisible.value = true
}
const dialogNotesVisible = (row: any) => {
rowOut.value = row
inputNotes.value = row.notes
inputNotesVisible.value = true
}
const dialogDataADDVisible = (row: any) => {
rowOut.value = row
addDataDialogVisible.value = true
}
const updateDedupObject = async () => {
try {
await api.updateToken({
token: rowOut.value.token,
dedup_object: value.value,
data_format: rowOut.value.data_format,
notes: rowOut.value.notes,
})
ElMessage({message: '更新成功', type: 'success'})
dedupObjectVisible.value = false
fetchTokens()
} catch (error: any) {
ElMessage.error(error.response?.data?.error || '更新失败')
}
const displayDataVisible = (row: any) => {
rowOut.value = row
inputDedupObject.value = row.dedup_object
inputDataFormat.value = row.data_format
inputNotes.value = row.notes
dataDialogVisible.value = true
}
const updateDataFormat = async () => {
const updateData = async () => {
try {
await api.updateToken({
token: rowOut.value.token,
dedup_object: rowOut.value.dedup_object,
data_format: dataFormat.value,
notes: rowOut.value.notes,
})
ElMessage({message: '更新成功', type: 'success'})
dataFormatVisible.value = false
fetchTokens()
} catch (error: any) {
ElMessage.error(error.response?.data?.error || '更新失败')
}
}
const updateNotes = async () => {
try {
await api.updateToken({
token: rowOut.value.token,
dedup_object: rowOut.value.dedup_object,
data_format: rowOut.value.data_format,
dedup_object: inputDedupObject.value,
data_format: inputDataFormat.value,
notes: inputNotes.value,
})
ElMessage({message: '更新成功', type: 'success'})
inputNotesVisible.value = false
fetchTokens()
} catch (error: any) {
ElMessage.error(error.response?.data?.error || '更新失败')
ElMessage.error('更新失败' + error.response?.data?.error)
dataDialogVisible.value = false
return
}
ElMessage({message: '更新成功', type: 'success'})
fetchTokens()
dataDialogVisible.value = false
}
const deleteToken = async (row: any) => {
@@ -155,282 +137,200 @@ const deleteToken = async (row: any) => {
ElMessage({message: '删除成功', type: 'success'})
fetchTokens()
} catch (error: any) {
ElMessage.error(error.response?.data?.error || '删除失败')
ElMessage.error('删除失败' + error.response?.data?.error)
}
}
onMounted(() => {
if (store.isAdmin) {
fetchTokens()
}
})
</script>
<template>
<div class="token-manage">
<div class="mx-auto w-full bg-white">
<!-- 管理页面 -->
<div class="manage-page">
<div class="content-card">
<div class="page-title">Token 管理</div>
<!-- 添加表单 -->
<el-collapse class="add-form" v-model="activeNames">
<el-collapse-item title="添加新 Token" name="1">
<div class="form-grid">
<el-input v-model="input" placeholder="Token 名称" clearable>
<template #prefix>
<el-icon>
<Key/>
</el-icon>
</template>
</el-input>
<el-select v-model="value" placeholder="去重对象" clearable>
<el-option v-for="item in options" :key="item.value" :value="item.value" :label="item.label"/>
</el-select>
<el-select v-model="dataFormat" placeholder="数据格式" clearable>
<el-option v-for="item in dataFormatOptions" :key="item.value" :value="item.value"
:label="item.label"/>
</el-select>
<el-input v-model="inputNotes" placeholder="备注(可选)" clearable>
<template #prefix>
<el-icon>
<Memo/>
</el-icon>
</template>
</el-input>
<el-button type="primary" @click="addToken">
<el-icon>
<Plus/>
</el-icon>
添加
</el-button>
</div>
</el-collapse-item>
</el-collapse>
<!-- Token 列表 -->
<div class="table-section">
<div class="section-header">
<span class="section-title">Token 列表</span>
<span class="table-count"> {{ tableData.length }} </span>
</div>
<el-table empty-text="没有数据" stripe style="width: 100%"
:data="tableData" v-loading="loading">
<el-table-column prop="token" label="Token" min-width="100" show-overflow-tooltip>
<template #default="{ row }">
<div class="token-cell">
<el-icon>
<Key/>
</el-icon>
<span>{{ row.token }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="dedup_object" label="去重对象" width="150">
<template #default="{ row }">
<el-tag type="primary" effect="plain">{{ row.dedup_object }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="data_format" label="数据格式" min-width="200" show-overflow-tooltip>
<template #default="{ row }">
<div class="format-cell">{{ row.data_format }}</div>
</template>
</el-table-column>
<el-table-column prop="notes" label="备注" min-width="150" show-overflow-tooltip>
<template #default="{ row }">
<span class="notes-text">{{ row.notes || '-' }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="500" fixed="right">
<template #default="{ row }">
<div class="action-buttons">
<el-button type="primary" size="small" text @click="viewDetails(row)">
<el-icon>
<View/>
</el-icon>
详情
</el-button>
<el-button size="small" text @click="dialogDataADDVisible(row)">
<el-icon>
<Plus/>
</el-icon>
数据
</el-button>
<el-button size="small" text @click="dialogDedupObjectVisible(row)">
<el-icon>
<Edit/>
</el-icon>
去重对象
</el-button>
<el-button size="small" text @click="dialogDataFormatVisible(row)">
<el-icon>
<Edit/>
</el-icon>
数据格式
</el-button>
<el-button size="small" text @click="dialogNotesVisible(row)">
<el-icon>
<Edit/>
</el-icon>
备注
</el-button>
<el-popconfirm
title="确认删除此 Token 吗?"
confirm-button-text="确认"
cancel-button-text="取消"
@confirm="deleteToken(row)"
>
<template #reference>
<el-button type="danger" size="small" text>
<el-icon>
<Delete/>
</el-icon>
删除
</el-button>
</template>
</el-popconfirm>
</div>
</template>
</el-table-column>
</el-table>
</div>
<div class="rounded-lg p-6 shadow-[0_2px_12px_rgba(0,0,0,0.08)]">
<div class="text-xl font-semibold text-(--el-text-color-primary) pb-3 border-b border-(--el-border-color)">
Token 管理
</div>
<!-- 编辑对话框 -->
<el-dialog v-model="dedupObjectVisible" title="更改去重对象" width="400">
<el-select v-model="value" placeholder="选择去重对象" style="width: 100%">
<el-option v-for="item in options" :key="item.value" :value="item.value" :label="item.label"/>
</el-select>
<template #footer>
<el-button @click="dedupObjectVisible = false">取消</el-button>
<el-button type="primary" @click="updateDedupObject">确定</el-button>
</template>
</el-dialog>
<!-- 添加表单 -->
<el-collapse
class="rounded-xl"
v-model="activeNames"
>
<el-collapse-item title="添加新 Token" name="1"
class="flex flex-wrap gap-3 items-center max-md:flex-col max-md:items-stretch"
>
<el-input v-model="input" placeholder="Token 名称" clearable class="w-55 max-md:w-full">
<template #prefix>
<el-icon>
<Key/>
</el-icon>
</template>
</el-input>
<el-dialog v-model="dataFormatVisible" title="更改数据格式" width="400">
<el-select v-model="dataFormat" placeholder="选择数据格式" style="width: 100%">
<el-option v-for="item in dataFormatOptions" :key="item.value" :value="item.value" :label="item.label"/>
</el-select>
<template #footer>
<el-button @click="dataFormatVisible = false">取消</el-button>
<el-button type="primary" @click="updateDataFormat">确定</el-button>
</template>
</el-dialog>
<el-select v-model="inputDedupObject" placeholder="去重对象" clearable class="w-70 max-md:w-full">
<el-option v-for="item in options" :key="item.value" :value="item.value" :label="item.label"/>
</el-select>
<el-dialog v-model="inputNotesVisible" title="更改备注" width="400">
<el-input v-model="inputNotes" placeholder="请输入备注"/>
<template #footer>
<el-button @click="inputNotesVisible = false">取消</el-button>
<el-button type="primary" @click="updateNotes">确定</el-button>
</template>
</el-dialog>
<el-select v-model="inputDataFormat" placeholder="数据格式" clearable class="w-70 max-md:w-full">
<template #footer>
<el-button v-if="!isAdding" text bg size="small" @click="onAddOption">
添加数据格式
</el-button>
<template v-else>
<el-input
v-model="optionName"
placeholder="输入数据格式(以----分割)"
size="small"
/>
<el-button type="primary" size="small" @click="onConfirm">添加</el-button>
<el-button size="small" @click="clear">取消</el-button>
</template>
</template>
<el-option v-for="item in dataFormatOptions" :key="item.value" :value="item.value"
:label="item.label"
/>
</el-select>
<AddDataDialog
v-model="addDataDialogVisible"
:token="rowOut?.token"
/>
<el-input v-model="inputNotes" placeholder="备注(可选)" clearable class="w-55 max-md:w-full">
<template #prefix>
<el-icon>
<Memo/>
</el-icon>
</template>
</el-input>
<el-button type="primary" @click="addToken" class="max-md:w-full">
<el-icon>
<Plus/>
</el-icon>
添加
</el-button>
</el-collapse-item>
</el-collapse>
<!-- Token 列表 -->
<div>
<div class="flex justify-between items-center">
<span class="text-base font-semibold text-(--el-text-color-primary) mt-5 mb-4">Token 列表</span>
<span class="text-xs text-(--el-text-color-secondary)"> {{ tableData.length }} </span>
</div>
<el-table empty-text="没有数据" stripe style="width: 100%"
:data="tableData" v-loading="loading">
<el-table-column prop="token" label="Token" min-width="100" show-overflow-tooltip>
<template #default="{ row }">
<div class="flex items-center gap-2">
<el-icon>
<Key/>
</el-icon>
<span>{{ row.token }}</span>
</div>
</template>
</el-table-column>
<el-table-column prop="dedup_object" label="去重对象" width="200">
<template #default="{ row }">
<el-tag type="primary" effect="plain">
{{ row.dedup_object == "false" ? "不去重" : row.dedup_object }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="data_format" label="数据格式" min-width="200" show-overflow-tooltip>
<template #default="{ row }">
<div class="text-xs break-all">{{ row.data_format }}</div>
</template>
</el-table-column>
<el-table-column prop="notes" label="备注" min-width="150" show-overflow-tooltip>
<template #default="{ row }">
<span class="text-(--el-text-color-secondary) overflow-hidden text-ellipsis whitespace-nowrap">
{{ row.notes || '-' }}
</span>
</template>
</el-table-column>
<el-table-column label="操作" width="380" fixed="right">
<template #default="{ row }">
<div class="flex gap-1 flex-wrap max-md:flex-col">
<el-button size="small" text @click="viewDetails(row)">
<el-icon>
<View/>
</el-icon>
详情
</el-button>
<el-button size="small" text @click="dialogDataADDVisible(row)">
<el-icon>
<Plus/>
</el-icon>
数据
</el-button>
<el-button type="primary" size="small" text @click="displayDataVisible(row)">
<el-icon>
<Edit/>
</el-icon>
编辑
</el-button>
<el-popconfirm
title="确认删除此 Token 吗?"
confirm-button-text="确认"
cancel-button-text="取消"
@confirm="deleteToken(row)"
>
<template #reference>
<el-button type="danger" size="small" text>
<el-icon>
<Delete/>
</el-icon>
删除
</el-button>
</template>
</el-popconfirm>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
<!-- 编辑对话框 -->
<el-dialog width="400"
v-model="dataDialogVisible"
>
<template #header>
编辑Token
<el-tag type="primary" effect="plain">{{ rowOut?.token }}</el-tag>
</template>
<div class="flex flex-col gap-3">
<el-text class="mr-auto">去重对象</el-text>
<el-select v-model="inputDedupObject" placeholder="选择去重对象">
<el-option v-for="item in options" :key="item.value" :value="item.value" :label="item.label"/>
</el-select>
<el-text class="mr-auto">数据格式</el-text>
<el-select v-model="inputDataFormat" placeholder="选择数据格式">
<el-option v-for="item in dataFormatOptions" :key="item.value" :value="item.value" :label="item.label"/>
</el-select>
<el-text class="mr-auto">备注</el-text>
<el-input v-model="inputNotes" placeholder="请输入备注"/>
</div>
<template #footer>
<el-button @click="dataDialogVisible = false">取消</el-button>
<el-button type="primary" @click="updateData">确定</el-button>
</template>
</el-dialog>
<AddDataDialog
v-model="addDataDialogVisible"
:token="rowOut?.token"
/>
</template>
<style scoped>
.token-manage {
margin: 0 auto;
width: 100%;
padding: 0;
}
/* 管理页面 */
.add-form {
margin-bottom: 32px;
padding: 24px;
background: var(--bg-page);
border-radius: 12px;
}
.form-title {
font-size: 15px;
font-weight: 600;
color: var(--el-text-color-primary);
margin-bottom: 16px;
}
.form-grid {
display: flex;
flex-wrap: wrap;
gap: 12px;
align-items: center;
}
.form-grid .el-input {
width: 220px;
}
.form-grid .el-select {
width: 280px;
}
/* 表格 */
.table-section {
margin-top: 8px;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.table-count {
font-size: 13px;
color: var(--el-text-color-secondary);
}
.token-cell {
display: flex;
align-items: center;
gap: 8px;
}
.format-cell {
font-size: 12px;
word-break: break-all;
}
.notes-text {
color: var(--el-text-color-secondary);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.action-buttons {
display: flex;
gap: 4px;
flex-wrap: wrap;
}
@media (max-width: 768px) {
.form-grid {
flex-direction: column;
align-items: stretch;
}
.form-grid .el-input,
.form-grid .el-select {
width: 100%;
}
.form-grid .el-button {
width: 100%;
}
.action-buttons {
flex-direction: column;
}
}
</style>
-2
View File
@@ -4,8 +4,6 @@
"env.d.ts",
"src/**/*",
"src/**/*.vue",
"auto-imports.d.ts",
"components.d.ts"
],
"exclude": [
"src/**/__tests__/*"
+2
View File
@@ -20,9 +20,11 @@ export default defineConfig({
'vue-router',
],
resolvers: [ElementPlusResolver()],
dts: 'src/types/import/auto-imports.d.ts',
}),
Components({
resolvers: [ElementPlusResolver()],
dts: 'src/types/import/components.d.ts',
}),
],
resolve: {