This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -28,3 +28,4 @@ go.work.sum
|
|||||||
/.idea
|
/.idea
|
||||||
config.toml
|
config.toml
|
||||||
/*.txt
|
/*.txt
|
||||||
|
/tmp/
|
||||||
@@ -1,20 +1,19 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"dypid-client/config"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func uploadDataToServer(httpClient *http.Client, data string) error {
|
func UploadDataToServer(httpClient *http.Client, data string) error {
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
params.Set("token", viper.GetString("token"))
|
params.Set("token", config.APPConfig.Token)
|
||||||
params.Set("data", data)
|
params.Set("data", data)
|
||||||
|
|
||||||
resp, err := httpClient.Post(viper.GetString("url")+"/api/data?"+params.Encode(), "application/x-www-form-urlencoded", strings.NewReader(""))
|
resp, err := httpClient.Post(config.APPConfig.Url+"/api/data?"+params.Encode(), "application/x-www-form-urlencoded", strings.NewReader(""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
63
config/config.go
Normal file
63
config/config.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/fsnotify/fsnotify"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Url string `mapstructure:"url"`
|
||||||
|
Token string `mapstructure:"token"`
|
||||||
|
ThreadCount int `mapstructure:"thread-count"`
|
||||||
|
IsRunOnStart bool `mapstructure:"is-run-on-start"`
|
||||||
|
LookingPath string `mapstructure:"looking-path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var APPConfig Config
|
||||||
|
|
||||||
|
func InitConfig() {
|
||||||
|
// 设置默认配置
|
||||||
|
defaultConfig := Config{
|
||||||
|
Url: "http://127.0.0.1:8080",
|
||||||
|
Token: "",
|
||||||
|
ThreadCount: 10,
|
||||||
|
IsRunOnStart: false,
|
||||||
|
LookingPath: "",
|
||||||
|
}
|
||||||
|
viper.SetDefault("url", defaultConfig.Url)
|
||||||
|
viper.SetDefault("token", defaultConfig.Token)
|
||||||
|
viper.SetDefault("thread-count", defaultConfig.ThreadCount)
|
||||||
|
viper.SetDefault("is-run-on-start", defaultConfig.IsRunOnStart)
|
||||||
|
viper.SetDefault("looking-path", defaultConfig.LookingPath)
|
||||||
|
|
||||||
|
//设置配置文件名和路径 ./config.toml
|
||||||
|
viper.AddConfigPath(".")
|
||||||
|
viper.SetConfigName("config")
|
||||||
|
viper.SetConfigType("toml")
|
||||||
|
viper.SafeWriteConfig() //安全写入默认配置
|
||||||
|
|
||||||
|
//读取配置文件
|
||||||
|
if err := viper.ReadInConfig(); err != nil {
|
||||||
|
fmt.Errorf("无法读取配置文件: %w", err)
|
||||||
|
}
|
||||||
|
if err := viper.Unmarshal(&APPConfig); err != nil {
|
||||||
|
fmt.Errorf("无法解析配置: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
viper.WatchConfig()
|
||||||
|
viper.OnConfigChange(func(e fsnotify.Event) {
|
||||||
|
if err := viper.ReadInConfig(); err != nil {
|
||||||
|
fmt.Errorf("无法读取配置文件: %w", err)
|
||||||
|
}
|
||||||
|
if err := viper.Unmarshal(&APPConfig); err != nil {
|
||||||
|
fmt.Errorf("无法解析配置: %w", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteConfig(key string, value any) {
|
||||||
|
viper.Set(key, value)
|
||||||
|
viper.WriteConfig()
|
||||||
|
}
|
||||||
31
go.mod
31
go.mod
@@ -3,21 +3,50 @@ module dypid-client
|
|||||||
go 1.25.1
|
go 1.25.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
fyne.io/fyne/v2 v2.6.3
|
||||||
github.com/fsnotify/fsnotify v1.9.0
|
github.com/fsnotify/fsnotify v1.9.0
|
||||||
github.com/spf13/viper v1.21.0
|
github.com/spf13/viper v1.21.0
|
||||||
golang.org/x/sync v0.17.0
|
golang.org/x/sync v0.17.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
fyne.io/systray v1.11.0 // indirect
|
||||||
|
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/fredbi/uri v1.1.0 // indirect
|
||||||
|
github.com/fyne-io/gl-js v0.2.0 // indirect
|
||||||
|
github.com/fyne-io/glfw-js v0.3.0 // indirect
|
||||||
|
github.com/fyne-io/image v0.1.1 // indirect
|
||||||
|
github.com/fyne-io/oksvg v0.1.0 // indirect
|
||||||
|
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect
|
||||||
|
github.com/go-text/render v0.2.0 // indirect
|
||||||
|
github.com/go-text/typesetting v0.2.1 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||||
|
github.com/hack-pad/go-indexeddb v0.3.2 // indirect
|
||||||
|
github.com/hack-pad/safejs v0.1.0 // indirect
|
||||||
|
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect
|
||||||
|
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||||
|
github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/rymdport/portal v0.4.1 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||||
github.com/spf13/afero v1.15.0 // indirect
|
github.com/spf13/afero v1.15.0 // indirect
|
||||||
github.com/spf13/cast v1.10.0 // indirect
|
github.com/spf13/cast v1.10.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.10 // indirect
|
github.com/spf13/pflag v1.0.10 // indirect
|
||||||
|
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect
|
||||||
|
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect
|
||||||
|
github.com/stretchr/testify v1.11.1 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
|
github.com/yuin/goldmark v1.7.8 // indirect
|
||||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||||
golang.org/x/sys v0.29.0 // indirect
|
golang.org/x/image v0.24.0 // indirect
|
||||||
|
golang.org/x/net v0.35.0 // indirect
|
||||||
|
golang.org/x/sys v0.30.0 // indirect
|
||||||
golang.org/x/text v0.28.0 // indirect
|
golang.org/x/text v0.28.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
68
go.sum
68
go.sum
@@ -1,23 +1,73 @@
|
|||||||
|
fyne.io/fyne/v2 v2.6.3 h1:cvtM2KHeRuH+WhtHiA63z5wJVBkQ9+Ay0UMl9PxFHyA=
|
||||||
|
fyne.io/fyne/v2 v2.6.3/go.mod h1:NGSurpRElVoI1G3h+ab2df3O5KLGh1CGbsMMcX0bPIs=
|
||||||
|
fyne.io/systray v1.11.0 h1:D9HISlxSkx+jHSniMBR6fCFOUjk1x/OOOJLa9lJYAKg=
|
||||||
|
fyne.io/systray v1.11.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs=
|
||||||
|
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||||
|
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
|
||||||
|
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
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/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
|
github.com/fredbi/uri v1.1.0 h1:OqLpTXtyRg9ABReqvDGdJPqZUxs8cyBDOMXBbskCaB8=
|
||||||
|
github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4=
|
||||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
|
github.com/fyne-io/gl-js v0.2.0 h1:+EXMLVEa18EfkXBVKhifYB6OGs3HwKO3lUElA0LlAjs=
|
||||||
|
github.com/fyne-io/gl-js v0.2.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI=
|
||||||
|
github.com/fyne-io/glfw-js v0.3.0 h1:d8k2+Y7l+zy2pc7wlGRyPfTgZoqDf3AI4G+2zOWhWUk=
|
||||||
|
github.com/fyne-io/glfw-js v0.3.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk=
|
||||||
|
github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA=
|
||||||
|
github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM=
|
||||||
|
github.com/fyne-io/oksvg v0.1.0 h1:7EUKk3HV3Y2E+qypp3nWqMXD7mum0hCw2KEGhI1fnBw=
|
||||||
|
github.com/fyne-io/oksvg v0.1.0/go.mod h1:dJ9oEkPiWhnTFNCmRgEze+YNprJF7YRbpjgpWS4kzoI=
|
||||||
|
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA=
|
||||||
|
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc=
|
||||||
|
github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU=
|
||||||
|
github.com/go-text/typesetting v0.2.1 h1:x0jMOGyO3d1qFAPI0j4GSsh7M0Q3Ypjzr4+CEVg82V8=
|
||||||
|
github.com/go-text/typesetting v0.2.1/go.mod h1:mTOxEwasOFpAMBjEQDhdWRckoLLeI/+qrQeBCTGEt6M=
|
||||||
|
github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066 h1:qCuYC+94v2xrb1PoS4NIDe7DGYtLnU2wWiQe9a1B1c0=
|
||||||
|
github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
|
||||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
|
||||||
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||||
|
github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A=
|
||||||
|
github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0=
|
||||||
|
github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8=
|
||||||
|
github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
|
||||||
|
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE=
|
||||||
|
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
|
||||||
|
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M=
|
||||||
|
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
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 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
|
github.com/nicksnyder/go-i18n/v2 v2.5.1 h1:IxtPxYsR9Gp60cGXjfuR/llTqV8aYMsC472zD0D1vHk=
|
||||||
|
github.com/nicksnyder/go-i18n/v2 v2.5.1/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
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.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||||
|
github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
|
||||||
|
github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
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/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
|
github.com/rymdport/portal v0.4.1 h1:2dnZhjf5uEaeDjeF/yBIeeRo6pNI2QAKm7kq1w/kbnA=
|
||||||
|
github.com/rymdport/portal v0.4.1/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
|
||||||
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||||
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
||||||
@@ -30,20 +80,30 @@ github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
|||||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
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 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||||
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||||
|
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE=
|
||||||
|
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q=
|
||||||
|
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
|
||||||
|
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
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/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 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||||
|
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||||
|
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
|
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
|
||||||
|
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
|
||||||
|
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||||
|
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
235
main.go
235
main.go
@@ -3,21 +3,164 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
|
"dypid-client/api"
|
||||||
|
"dypid-client/config"
|
||||||
|
"dypid-client/utils/folder"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"fyne.io/fyne/v2"
|
||||||
"github.com/spf13/viper"
|
"fyne.io/fyne/v2/app"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/layout"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var isRun = false
|
||||||
|
var logText = widget.NewMultiLineEntry()
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
config.InitConfig()
|
||||||
|
|
||||||
|
myApp := app.New()
|
||||||
|
myWindow := myApp.NewWindow("抖音数据上传工具")
|
||||||
|
myWindow.Resize(fyne.NewSize(900, 550))
|
||||||
|
|
||||||
|
logText.Scroll = container.ScrollVerticalOnly
|
||||||
|
|
||||||
|
// 创建界面组件
|
||||||
|
urlEntry := widget.NewEntry()
|
||||||
|
urlEntry.SetPlaceHolder("http://127.0.0.1:8080")
|
||||||
|
urlEntry.Text = config.APPConfig.Url
|
||||||
|
urlEntry.OnChanged = func(s string) {
|
||||||
|
config.WriteConfig("url", urlEntry.Text)
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenEntry := widget.NewEntry()
|
||||||
|
tokenEntry.SetPlaceHolder("请输入Token")
|
||||||
|
tokenEntry.Text = config.APPConfig.Token
|
||||||
|
tokenEntry.OnChanged = func(s string) {
|
||||||
|
config.WriteConfig("token", tokenEntry.Text)
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedDirLabel := widget.NewEntry()
|
||||||
|
selectedDirLabel.SetPlaceHolder("未选择目录(默认为程序运行目录)")
|
||||||
|
selectedDirLabel.Text = config.APPConfig.LookingPath
|
||||||
|
selectedDirLabel.OnChanged = func(s string) {
|
||||||
|
config.WriteConfig("looking-path", selectedDirLabel.Text)
|
||||||
|
}
|
||||||
|
|
||||||
|
threadCountLabel := widget.NewEntry()
|
||||||
|
threadCountLabel.SetPlaceHolder("10")
|
||||||
|
threadCountLabel.Text = strconv.Itoa(config.APPConfig.ThreadCount)
|
||||||
|
threadCountLabel.OnChanged = func(s string) {
|
||||||
|
i, err := strconv.Atoi(threadCountLabel.Text)
|
||||||
|
if err != nil {
|
||||||
|
AddLog("输入上传线程错误")
|
||||||
|
}
|
||||||
|
config.WriteConfig("thread-count", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
isRunOnStartWidget := widget.NewCheck("启动程序时启动上传程序", func(b bool) {
|
||||||
|
config.WriteConfig("is-run-on-start", b)
|
||||||
|
})
|
||||||
|
isRunOnStartWidget.Checked = config.APPConfig.IsRunOnStart
|
||||||
|
|
||||||
|
// 使用Windows原生目录选择按钮
|
||||||
|
selectDirBtn := widget.NewButton("选择检测目录", func() {
|
||||||
|
// 调用CGO实现的Windows原生对话框
|
||||||
|
selectedPath := folder.OpenFolderDialog()
|
||||||
|
if selectedPath == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
selectedDirLabel.SetText(selectedPath)
|
||||||
|
config.WriteConfig("looking-path", selectedPath)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 开始运行按钮
|
||||||
|
startBtn := widget.NewButton("开始运行", func() {
|
||||||
|
if strings.TrimSpace(tokenEntry.Text) == "" {
|
||||||
|
AddLog("错误:请输入Token")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
AddLog(fmt.Sprintf("Token:%s", tokenEntry.Text))
|
||||||
|
AddLog(fmt.Sprintf("检测目录:%s", selectedDirLabel.Text))
|
||||||
|
AddLog("===============================")
|
||||||
|
|
||||||
|
isRun = true
|
||||||
|
go StartLooking(selectedDirLabel.Text)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 清除日志按钮
|
||||||
|
clearLogBtn := widget.NewButton("清除日志", func() {
|
||||||
|
logText.SetText("")
|
||||||
|
AddLog("日志已清除")
|
||||||
|
})
|
||||||
|
|
||||||
|
// 组装左侧面板
|
||||||
|
leftPanel := container.NewBorder(
|
||||||
|
nil,
|
||||||
|
// 底部 - 放置按钮
|
||||||
|
container.NewVBox(
|
||||||
|
isRunOnStartWidget,
|
||||||
|
startBtn,
|
||||||
|
clearLogBtn,
|
||||||
|
),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
// 中间内容
|
||||||
|
container.NewVBox(
|
||||||
|
widget.NewLabelWithStyle("服务器地址:", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
|
||||||
|
urlEntry,
|
||||||
|
widget.NewSeparator(),
|
||||||
|
widget.NewLabelWithStyle("Token:", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
|
||||||
|
tokenEntry,
|
||||||
|
widget.NewSeparator(),
|
||||||
|
widget.NewLabelWithStyle("检测目录:", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
|
||||||
|
selectedDirLabel,
|
||||||
|
selectDirBtn,
|
||||||
|
widget.NewSeparator(),
|
||||||
|
container.NewHBox(
|
||||||
|
widget.NewLabelWithStyle("单文件上传线程:", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
|
||||||
|
threadCountLabel,
|
||||||
|
),
|
||||||
|
widget.NewSeparator(),
|
||||||
|
layout.NewSpacer(), // 添加一个弹性空间,将内容向上推
|
||||||
|
),
|
||||||
|
)
|
||||||
|
// 组装右侧面板(日志显示)
|
||||||
|
rightPanel := container.NewBorder(
|
||||||
|
widget.NewLabelWithStyle("运行日志", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
|
||||||
|
nil, nil, nil,
|
||||||
|
container.NewScroll(logText),
|
||||||
|
)
|
||||||
|
|
||||||
|
// 使用HSplit容器创建可调整大小的左右分割布局
|
||||||
|
splitContainer := container.NewHSplit(leftPanel, rightPanel)
|
||||||
|
splitContainer.SetOffset(0.35) // 左侧占35%宽度
|
||||||
|
|
||||||
|
myWindow.SetContent(splitContainer)
|
||||||
|
myWindow.ShowAndRun()
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddLog(message string) {
|
||||||
|
fyne.Do(func() {
|
||||||
|
logText.Append(message + "\n")
|
||||||
|
// 自动滚动到底部
|
||||||
|
logText.CursorRow = len(logText.Text)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传数据代码
|
||||||
|
|
||||||
var httpClient = &http.Client{
|
var httpClient = &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
MaxIdleConns: 200,
|
MaxIdleConns: 200,
|
||||||
@@ -32,26 +175,28 @@ type Task struct {
|
|||||||
FileLines int
|
FileLines int
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func StartLooking(lookingPath string) {
|
||||||
initConfig()
|
//检测./
|
||||||
|
AddLog("程序启动成功,正在检测txt文件")
|
||||||
//检测./upload
|
|
||||||
fmt.Println("程序启动成功,正在检测txt文件")
|
|
||||||
for {
|
for {
|
||||||
files, err := getTxtFiles("./")
|
var path = "./"
|
||||||
|
if lookingPath != "" {
|
||||||
|
path = lookingPath
|
||||||
|
}
|
||||||
|
files, err := getTxtFiles(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
AddLog(err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if files != nil {
|
if files != nil {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
fileLines := make(map[string]int)
|
fileLines := make(map[string]int)
|
||||||
fmt.Println("正在统计", len(files), "个文件行数")
|
AddLog(fmt.Sprintf("正在统计 %v 个文件行数", len(files)))
|
||||||
for _, filePath := range files {
|
for _, filePath := range files {
|
||||||
file, err := os.Open(filePath)
|
file, err := os.Open(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("打开文件失败:", err)
|
AddLog("打开文件失败:" + err.Error())
|
||||||
}
|
}
|
||||||
// 使用 bufio.Scanner 逐行读取
|
// 使用 bufio.Scanner 逐行读取
|
||||||
scanner := bufio.NewScanner(file)
|
scanner := bufio.NewScanner(file)
|
||||||
@@ -64,7 +209,7 @@ func main() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fileLines[filepath.Base(filePath)] = lineCount
|
fileLines[filepath.Base(filePath)] = lineCount
|
||||||
fmt.Println(filepath.Base(filePath), "文件行数:", lineCount)
|
AddLog(fmt.Sprintf("%s 文件行数:%v", filepath.Base(filePath), lineCount))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,11 +229,11 @@ func main() {
|
|||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
default:
|
default:
|
||||||
fmt.Println("正在上传文件:", filepath.Base(task.FilePath))
|
AddLog("正在上传文件:" + filepath.Base(task.FilePath))
|
||||||
processFile(task.FilePath, task.FileLines)
|
processFile(task.FilePath, task.FileLines)
|
||||||
err := os.Truncate(task.FilePath, 0)
|
err := os.Truncate(task.FilePath, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("清空文件失败:", err)
|
AddLog("清空文件失败:" + err.Error())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -97,52 +242,16 @@ func main() {
|
|||||||
|
|
||||||
// 等待所有任务完成
|
// 等待所有任务完成
|
||||||
if err := g.Wait(); err != nil {
|
if err := g.Wait(); err != nil {
|
||||||
fmt.Printf("任务执行出错: %v\n", err)
|
AddLog(fmt.Sprintf("任务执行出错: %v", err))
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("所有任务执行完成!")
|
AddLog("所有任务执行完成!")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("上传完成,耗时:%s\n", time.Since(start))
|
AddLog(fmt.Sprintf("上传完成,耗时:%s\n", time.Since(start)))
|
||||||
}
|
}
|
||||||
time.Sleep(time.Minute)
|
time.Sleep(time.Minute)
|
||||||
}
|
}
|
||||||
}
|
AddLog("上传程序已退出")
|
||||||
|
|
||||||
func initConfig() {
|
|
||||||
//程序配置
|
|
||||||
viper.SetDefault("url", "http://localhost:8080")
|
|
||||||
viper.SetDefault("token", "")
|
|
||||||
viper.SetDefault("thread-count", 10)
|
|
||||||
//设置配置文件名和路径 ./config.toml
|
|
||||||
viper.AddConfigPath(".")
|
|
||||||
viper.SetConfigName("config")
|
|
||||||
viper.SetConfigType("toml")
|
|
||||||
viper.SafeWriteConfig() //安全写入默认配置
|
|
||||||
//读取配置文件
|
|
||||||
if err := viper.ReadInConfig(); err != nil {
|
|
||||||
fmt.Errorf("无法读取配置文件: %w", err)
|
|
||||||
}
|
|
||||||
viper.WatchConfig()
|
|
||||||
viper.OnConfigChange(func(e fsnotify.Event) {
|
|
||||||
if err := viper.ReadInConfig(); err != nil {
|
|
||||||
fmt.Errorf("无法读取配置文件: %w", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func uploadDataToServer(data string) error {
|
|
||||||
params := url.Values{}
|
|
||||||
params.Set("token", viper.GetString("token"))
|
|
||||||
params.Set("data", data)
|
|
||||||
|
|
||||||
resp, err := httpClient.Post(viper.GetString("url")+"/api/data?"+params.Encode(), "application/x-www-form-urlencoded", strings.NewReader(""))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if resp != nil {
|
|
||||||
_, _ = io.Copy(io.Discard, resp.Body)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取目录中的所有txt文件
|
// 获取目录中的所有txt文件
|
||||||
@@ -173,7 +282,7 @@ func processFile(filePath string, fileLines int) {
|
|||||||
// 打开文件
|
// 打开文件
|
||||||
file, err := os.Open(filePath)
|
file, err := os.Open(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("无法打开文件 %s: %v\n", filePath, err)
|
AddLog(fmt.Sprintf("无法打开文件 %s: %v\n", filePath, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
@@ -182,7 +291,7 @@ func processFile(filePath string, fileLines int) {
|
|||||||
lines := make(chan string, 100)
|
lines := make(chan string, 100)
|
||||||
|
|
||||||
// 创建10个worker处理文件上传
|
// 创建10个worker处理文件上传
|
||||||
for i := 0; i < viper.GetInt("thread-count"); i++ {
|
for i := 0; i < config.APPConfig.ThreadCount; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(workerID int) {
|
go func(workerID int) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
@@ -197,7 +306,7 @@ func processFile(filePath string, fileLines int) {
|
|||||||
lines <- scanner.Text()
|
lines <- scanner.Text()
|
||||||
lineCount++
|
lineCount++
|
||||||
if lineCount%10000 == 0 {
|
if lineCount%10000 == 0 {
|
||||||
fmt.Printf("文件【%s】处理进度:%.2f%%\n", filePath, float64(lineCount)/float64(fileLines)*100)
|
AddLog(fmt.Sprintf("文件【%s】处理进度:%.2f%%\n", filePath, float64(lineCount)/float64(fileLines)*100))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,11 +314,11 @@ func processFile(filePath string, fileLines int) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
fmt.Printf("读取文件 %s 错误: %v\n", filePath, err)
|
AddLog(fmt.Sprintf("读取文件 %s 错误: %v\n", filePath, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("文件【%s】处理完成,共处理 %d 行数据\n", filePath, lineCount)
|
AddLog(fmt.Sprintf("文件【%s】处理完成,共处理 %d 行数据\n", filePath, lineCount))
|
||||||
}
|
}
|
||||||
|
|
||||||
func processLines(lines <-chan string, workerID int, filePath string) {
|
func processLines(lines <-chan string, workerID int, filePath string) {
|
||||||
@@ -219,8 +328,8 @@ func processLines(lines <-chan string, workerID int, filePath string) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 上传数据
|
// 上传数据
|
||||||
if err := uploadDataToServer(line); err != nil {
|
if err := api.UploadDataToServer(httpClient, line); err != nil {
|
||||||
fmt.Printf("Worker %d (文件 %s): 上传失败: %v\n", workerID, filePath, err)
|
AddLog(fmt.Sprintf("Worker %d (文件 %s): 上传失败: %v\n", workerID, filePath, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
185
uploader/uploader.go
Normal file
185
uploader/uploader.go
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
package uploader
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"dypid-client/api"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
var httpClient = &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
MaxIdleConns: 200,
|
||||||
|
MaxIdleConnsPerHost: 100,
|
||||||
|
IdleConnTimeout: 30 * time.Second,
|
||||||
|
},
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Task struct {
|
||||||
|
FilePath string
|
||||||
|
FileLines int
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartLooking(lookingPath string) {
|
||||||
|
//检测./
|
||||||
|
fmt.Println("程序启动成功,正在检测txt文件")
|
||||||
|
for {
|
||||||
|
files, err := getTxtFiles("./")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if files != nil {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
fileLines := make(map[string]int)
|
||||||
|
fmt.Println("正在统计", len(files), "个文件行数")
|
||||||
|
for _, filePath := range files {
|
||||||
|
file, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("打开文件失败:", err)
|
||||||
|
}
|
||||||
|
// 使用 bufio.Scanner 逐行读取
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
lineCount := 0
|
||||||
|
for scanner.Scan() {
|
||||||
|
lineCount++
|
||||||
|
}
|
||||||
|
file.Close()
|
||||||
|
if lineCount == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fileLines[filepath.Base(filePath)] = lineCount
|
||||||
|
fmt.Println(filepath.Base(filePath), "文件行数:", lineCount)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var tasks []Task
|
||||||
|
for k, v := range fileLines {
|
||||||
|
tasks = append(tasks, Task{FilePath: k, FileLines: v})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用errgroup控制并发
|
||||||
|
g, ctx := errgroup.WithContext(context.Background())
|
||||||
|
g.SetLimit(50) // 设置最大并发数为50
|
||||||
|
// 执行所有任务
|
||||||
|
for _, task := range tasks {
|
||||||
|
task := task // 创建局部变量
|
||||||
|
g.Go(func() error {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
default:
|
||||||
|
fmt.Println("正在上传文件:", filepath.Base(task.FilePath))
|
||||||
|
processFile(task.FilePath, task.FileLines)
|
||||||
|
err := os.Truncate(task.FilePath, 0)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("清空文件失败:", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待所有任务完成
|
||||||
|
if err := g.Wait(); err != nil {
|
||||||
|
fmt.Printf("任务执行出错: %v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Println("所有任务执行完成!")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("上传完成,耗时:%s\n", time.Since(start))
|
||||||
|
}
|
||||||
|
time.Sleep(time.Minute)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取目录中的所有txt文件
|
||||||
|
func getTxtFiles(dir string) (txtFiles []string, err error) {
|
||||||
|
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只处理普通文件,跳过目录
|
||||||
|
if !info.Mode().IsRegular() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查文件扩展名是否为.txt
|
||||||
|
if strings.ToLower(filepath.Ext(path)) == ".txt" {
|
||||||
|
txtFiles = append(txtFiles, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return txtFiles, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func processFile(filePath string, fileLines int) {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
// 打开文件
|
||||||
|
file, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("无法打开文件 %s: %v\n", filePath, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// 创建行通道
|
||||||
|
lines := make(chan string, 100)
|
||||||
|
|
||||||
|
// 创建10个worker处理文件上传
|
||||||
|
for i := 0; i < viper.GetInt("thread-count"); i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(workerID int) {
|
||||||
|
defer wg.Done()
|
||||||
|
processLines(lines, workerID, filePath)
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取文件并发送到通道
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
lineCount := 0
|
||||||
|
for scanner.Scan() {
|
||||||
|
lines <- scanner.Text()
|
||||||
|
lineCount++
|
||||||
|
if lineCount%10000 == 0 {
|
||||||
|
fmt.Printf("文件【%s】处理进度:%.2f%%\n", filePath, float64(lineCount)/float64(fileLines)*100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(lines)
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
fmt.Printf("读取文件 %s 错误: %v\n", filePath, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("文件【%s】处理完成,共处理 %d 行数据\n", filePath, lineCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processLines(lines <-chan string, workerID int, filePath string) {
|
||||||
|
for line := range lines {
|
||||||
|
// 跳过空行
|
||||||
|
if strings.TrimSpace(line) == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 上传数据
|
||||||
|
if err := api.UploadDataToServer(httpClient, line); err != nil {
|
||||||
|
fmt.Printf("Worker %d (文件 %s): 上传失败: %v\n", workerID, filePath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
utils/folder/folder.go
Normal file
20
utils/folder/folder.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package folder
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo windows LDFLAGS: -lole32 -luuid
|
||||||
|
|
||||||
|
#include "windows_dialog.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
// OpenFolderDialog 调用Windows原生文件夹选择对话框
|
||||||
|
// 返回选择的文件夹路径,如果用户取消选择则返回空字符串
|
||||||
|
func OpenFolderDialog() string {
|
||||||
|
cPath := C.OpenFolderDialog()
|
||||||
|
if cPath == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer C.FreeMemory(cPath)
|
||||||
|
|
||||||
|
return C.GoString(cPath)
|
||||||
|
}
|
||||||
56
utils/folder/windows_dialog.c
Normal file
56
utils/folder/windows_dialog.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#include "windows_dialog.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
char* OpenFolderDialog(void) {
|
||||||
|
IFileOpenDialog *pFileOpen = NULL;
|
||||||
|
IShellItem *pItem = NULL;
|
||||||
|
PWSTR pszFilePath = NULL;
|
||||||
|
char* result = NULL;
|
||||||
|
|
||||||
|
// 初始化COM库
|
||||||
|
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建FileOpenDialog对象
|
||||||
|
hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_ALL, &IID_IFileOpenDialog, (void**)&pFileOpen);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
// 设置为选择文件夹模式
|
||||||
|
DWORD options;
|
||||||
|
pFileOpen->lpVtbl->GetOptions(pFileOpen, &options);
|
||||||
|
pFileOpen->lpVtbl->SetOptions(pFileOpen, options | FOS_PICKFOLDERS);
|
||||||
|
|
||||||
|
// 显示对话框
|
||||||
|
hr = pFileOpen->lpVtbl->Show(pFileOpen, NULL);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
// 获取结果
|
||||||
|
hr = pFileOpen->lpVtbl->GetResult(pFileOpen, &pItem);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
// 获取文件夹路径
|
||||||
|
hr = pItem->lpVtbl->GetDisplayName(pItem, SIGDN_FILESYSPATH, &pszFilePath);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
// 计算所需缓冲区大小并转换宽字符串到多字节字符串
|
||||||
|
int size_needed = WideCharToMultiByte(CP_UTF8, 0, pszFilePath, -1, NULL, 0, NULL, NULL);
|
||||||
|
result = (char*)malloc(size_needed);
|
||||||
|
if (result) {
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, pszFilePath, -1, result, size_needed, NULL, NULL);
|
||||||
|
}
|
||||||
|
CoTaskMemFree(pszFilePath);
|
||||||
|
}
|
||||||
|
pItem->lpVtbl->Release(pItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pFileOpen->lpVtbl->Release(pFileOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoUninitialize();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeMemory(char* ptr) {
|
||||||
|
if (ptr) {
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
utils/folder/windows_dialog.h
Normal file
11
utils/folder/windows_dialog.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef WINDOWS_DIALOG_H
|
||||||
|
#define WINDOWS_DIALOG_H
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <shobjidl.h>
|
||||||
|
|
||||||
|
// 导出函数声明
|
||||||
|
char* OpenFolderDialog(void);
|
||||||
|
void FreeMemory(char* ptr);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user