This commit is contained in:
renzhiyuan 2026-04-13 03:03:34 +08:00
parent a06ae5c8cf
commit ef2d3f68b9
27 changed files with 772 additions and 46 deletions

1
a.md Normal file

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,6 @@ package main
import (
"fmt"
"geo/internal/config"
"github.com/gofiber/fiber/v2/log"
)

9
go.mod
View File

@ -1,8 +1,9 @@
module geo
go 1.26.1
go 1.25.4
require (
gitea.cdlsxd.cn/self-tools/l_request v1.0.8
github.com/go-kratos/kratos/v2 v2.9.2
github.com/go-playground/validator/v10 v10.30.2
github.com/go-rod/rod v0.116.2
@ -11,6 +12,7 @@ require (
github.com/google/uuid v1.6.0
github.com/google/wire v0.7.0
github.com/redis/go-redis/v9 v9.18.0
github.com/volcengine/volcengine-go-sdk v1.2.24
gorm.io/driver/mysql v1.6.0
gorm.io/gorm v1.31.1
xorm.io/builder v0.3.13
@ -18,7 +20,6 @@ require (
require (
filippo.io/edwards25519 v1.1.0 // indirect
gitea.cdlsxd.cn/self-tools/l_request v1.0.8 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
@ -28,6 +29,7 @@ require (
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
@ -38,6 +40,7 @@ require (
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.51.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
github.com/volcengine/volc-sdk-golang v1.0.23 // indirect
github.com/ysmood/fetchup v0.2.3 // indirect
github.com/ysmood/goob v0.4.0 // indirect
github.com/ysmood/got v0.40.0 // indirect
@ -47,4 +50,6 @@ require (
golang.org/x/crypto v0.49.0 // indirect
golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v2 v2.2.8 // indirect
)

98
go.sum
View File

@ -1,22 +1,29 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
gitea.cdlsxd.cn/self-tools/l_request v1.0.8 h1:FaKRql9mCVcSoaGqPeBOAruZ52slzRngQ6VRTYKNSsA=
gitea.cdlsxd.cn/self-tools/l_request v1.0.8/go.mod h1:Qf4hVXm2Eu5vOvwXk8D7U0q/aekMCkZ4Fg9wnRKlasQ=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
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/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/go-kratos/kratos/v2 v2.9.2 h1:px8GJQBeLpquDKQWQ9zohEWiLA8n4D/pv7aH3asvUvo=
@ -37,6 +44,27 @@ github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPE
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gofiber/fiber/v2 v2.52.12 h1:0LdToKclcPOj8PktUdIKo9BUohjjwfnQl42Dhw8/WUw=
github.com/gofiber/fiber/v2 v2.52.12/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4=
@ -45,10 +73,20 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
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-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
@ -58,15 +96,20 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/redis/go-redis/v9 v9.18.0 h1:pMkxYPkEbMPwRdenAzUNyFNrDgHx9U+DrBabWNfSRQs=
github.com/redis/go-redis/v9 v9.18.0/go.mod h1:k3ufPphLU5YXwNTUcCRXGxUoF1fqxnhFQmscfkCoDA0=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
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/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
@ -75,6 +118,10 @@ github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1S
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/volcengine/volc-sdk-golang v1.0.23 h1:anOslb2Qp6ywnsbyq9jqR0ljuO63kg9PY+4OehIk5R8=
github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU=
github.com/volcengine/volcengine-go-sdk v1.2.24 h1:TK5yfSmLgeWZ0ufO2tBzIS6KdSu1b/A8D/soTXAuRhg=
github.com/volcengine/volcengine-go-sdk v1.2.24/go.mod h1:oxoVo+A17kvkwPkIeIHPVLjSw7EQAm+l/Vau1YGHN+A=
github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ=
github.com/ysmood/fetchup v0.2.3/go.mod h1:xhibcRKziSvol0H1/pj33dnKrYyI2ebIvz5cOOkYGns=
github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=
@ -93,21 +140,72 @@ github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
xorm.io/builder v0.3.13/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=

180
internal/ai/hsyq.go Normal file
View File

@ -0,0 +1,180 @@
package third_party
import (
"context"
"sync"
"time"
"github.com/gofiber/fiber/v2/log"
"github.com/volcengine/volcengine-go-sdk/service/arkruntime"
"github.com/volcengine/volcengine-go-sdk/service/arkruntime/model"
"github.com/volcengine/volcengine-go-sdk/service/arkruntime/model/responses"
"github.com/volcengine/volcengine-go-sdk/volcengine"
)
type Hsyq struct {
mapClient map[string]*arkruntime.Client
}
var (
HsyqClient *Hsyq
once sync.Once
)
func NewHsyq() *Hsyq {
once.Do(func() {
HsyqClient = &Hsyq{
mapClient: make(map[string]*arkruntime.Client),
}
})
return HsyqClient
}
func (h *Hsyq) getClient(key string) *arkruntime.Client {
var client *arkruntime.Client
if _, ok := h.mapClient[key]; ok {
client = h.mapClient[key]
} else {
client = arkruntime.NewClientWithApiKey(
key,
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
arkruntime.WithRegion("cn-beijing"),
arkruntime.WithTimeout(2*time.Minute),
arkruntime.WithRetryTimes(2),
)
h.mapClient[key] = client
}
return client
}
// 火山引擎
func (h *Hsyq) Chat(ctx context.Context, key string, modelName string, prompt []*model.ChatCompletionMessage) (model.ChatCompletionResponse, error) {
req := model.CreateChatCompletionRequest{
Model: modelName,
Messages: prompt,
Stream: new(bool),
Thinking: &model.Thinking{Type: model.ThinkingTypeDisabled},
}
resp, err := h.getClient(key).CreateChatCompletion(ctx, req)
if err != nil {
return model.ChatCompletionResponse{ID: ""}, err
}
log.Info("token用量", resp.Usage.TotalTokens, "输入:", resp.Usage.PromptTokens, "输出:", resp.Usage.CompletionTokens)
return resp, err
}
// 火山引擎
func (h *Hsyq) ChatWithRequest(ctx context.Context, key string, request model.ContextChatCompletionRequest) (model.ChatCompletionResponse, error) {
resp, err := h.getClient(key).CreateContextChatCompletion(ctx, request)
if err != nil {
return model.ChatCompletionResponse{ID: ""}, err
}
log.Info("token用量", resp.Usage.TotalTokens, "输入:", resp.Usage.PromptTokens, "输出:", resp.Usage.CompletionTokens)
return resp, err
}
func (h *Hsyq) CreateContextCache(ctx context.Context, key string, modelName string, prompt []*model.ChatCompletionMessage) (string, error) {
req := model.CreateContextRequest{
Model: modelName,
Messages: prompt,
TTL: volcengine.Int(3600),
Mode: model.ContextModeSession,
TruncationStrategy: &model.TruncationStrategy{Type: model.TruncationStrategyTypeRollingTokens},
}
resp, err := h.getClient(key).CreateContext(ctx, req)
if err != nil {
return "", err
}
log.Info("token用量", resp.Usage.TotalTokens, "输入:", resp.Usage.PromptTokens, "输出:", resp.Usage.CompletionTokens)
return resp.ID, err
}
func (h *Hsyq) CreateResponse(ctx context.Context, key string, modelName string, prompt []*responses.InputItem, id string, isRegis bool) (*responses.ResponseObject, error) {
req := &responses.ResponsesRequest{
Model: modelName,
Input: &responses.ResponsesInput{
Union: &responses.ResponsesInput_ListValue{
ListValue: &responses.InputItemList{ListValue: prompt},
},
},
Stream: new(bool),
Thinking: &responses.ResponsesThinking{Type: responses.ThinkingType_disabled.Enum()},
}
if isRegis {
prefix := true
req.Caching = &responses.ResponsesCaching{Type: responses.CacheType_enabled.Enum(), Prefix: &prefix}
req.ExpireAt = volcengine.Int64(time.Now().Unix() + 3600)
}
if len(id) != 0 {
req.PreviousResponseId = &id
//req.Text = &responses.ResponsesText{
// Format: &responses.TextFormat{
// Type: responses.TextType_json_object,
// Schema:
// }
//}
}
resp, err := h.getClient(key).CreateResponses(ctx, req)
if err != nil {
return nil, err
}
log.Info("token用量", resp.Usage.TotalTokens, "输入:", resp.Usage.InputTokens, "输出:", resp.Usage.OutputTokens)
return resp, err
}
func (h *Hsyq) RequestHsyqJson(ctx context.Context, key string, modelName string, prompt []*responses.InputItem) (*responses.ResponseObject, error) {
req := responses.ResponsesRequest{
Model: modelName,
Input: &responses.ResponsesInput{
Union: &responses.ResponsesInput_ListValue{
ListValue: &responses.InputItemList{ListValue: prompt},
},
},
Stream: new(bool),
Thinking: &responses.ResponsesThinking{Type: responses.ThinkingType_disabled.Enum()},
Text: &responses.ResponsesText{Format: &responses.TextFormat{Type: responses.TextType_json_object}},
}
resp, err := h.getClient(key).CreateResponses(ctx, &req)
if err != nil {
return resp, err
}
log.Info("token用量", resp.Usage.TotalTokens)
return resp, err
}
// []*model.ChatCompletionMessage{
// {
// Role: model.ChatMessageRoleSystem,
// Content: &model.ChatCompletionMessageContent{
// StringValue: volcengine.String("你是豆包,是由字节跳动开发的 AI 人工智能助手"),
// },
// },
// {
// Role: model.ChatMessageRoleUser,
// Content: &model.ChatCompletionMessageContent{
// StringValue: volcengine.String("常见的十字花科植物有哪些?"),
// },
// },
// },
func (h *Hsyq) RequestHsyqBot(ctx context.Context, key string, botId string, message []*model.ChatCompletionMessage) ([]byte, error) {
req := model.BotChatCompletionRequest{
BotId: botId,
Messages: message,
Stream: false,
Thinking: &model.Thinking{Type: model.ThinkingTypeDisabled},
ResponseFormat: &model.ResponseFormat{Type: model.ResponseFormatJsonObject},
}
resp, err := h.mapClient[key].CreateBotChatCompletion(ctx, req)
if err != nil {
return nil, err
}
log.Info("token用量", resp.Usage.TotalTokens)
return resp.Choices[0].Message.Content.MarshalJSON()
}

4
internal/biz/ai.go Normal file
View File

@ -0,0 +1,4 @@
package biz
type Ai struct {
}

75
internal/biz/auth.go Normal file
View File

@ -0,0 +1,75 @@
package biz
import (
"context"
"geo/internal/config"
"geo/internal/data/impl"
"geo/internal/data/model"
"geo/tmpl/errcode"
"xorm.io/builder"
)
type AuthBiz struct {
cfg *config.Config
userImpl *impl.UserImpl
tokenImpl *impl.TokenImpl
}
func NewAuthBiz(
cfg *config.Config,
tokenImpl *impl.TokenImpl,
userImpl *impl.UserImpl,
) *AuthBiz {
return &AuthBiz{
cfg: cfg,
tokenImpl: tokenImpl,
userImpl: userImpl,
}
}
func (a *AuthBiz) ValidateAccessToken(ctx context.Context, accessToken string) (*model.Token, error) {
cond := builder.NewCond().
And(builder.Eq{"access_token": accessToken}).
And(builder.Eq{"status": 1})
tokenInfo := &model.Token{}
err := a.tokenImpl.GetOneBySearchStruct(ctx, &cond, tokenInfo)
if err != nil {
return nil, errcode.Forbidden("密钥无效或已禁用")
}
if tokenInfo.ID == 0 {
return nil, errcode.Forbidden("密钥无效或已禁用")
}
return tokenInfo, nil
}
func (a *AuthBiz) UserValid(ctx context.Context, userIndex string, tokenId int32) (*model.User, error) {
cond := builder.NewCond().
And(builder.Eq{"user_index": userIndex}).
And(builder.Eq{"status": 1})
if tokenId != 0 {
cond.And(builder.Eq{"tokenId": tokenId})
}
userInfo := &model.User{}
err := a.userImpl.GetOneBySearchStruct(ctx, &cond, userInfo)
if err != nil {
return nil, errcode.Forbidden("未找到用户")
}
if userInfo.ID == 0 {
return nil, errcode.Forbidden("未找到用户")
}
return userInfo, nil
}
func (a *AuthBiz) UserAndTokenValid(ctx context.Context, accessToken, userIndex string) (*model.User, *model.Token, error) {
tokenInfo, err := a.ValidateAccessToken(ctx, accessToken)
if err != nil {
return nil, nil, err
}
userInfo, err := a.UserValid(ctx, userIndex, tokenInfo.ID)
if err != nil {
return nil, nil, err
}
return userInfo, tokenInfo, err
}

View File

@ -6,4 +6,5 @@ import (
var ProviderSetBiz = wire.NewSet(
NewPublishBiz,
NewAuthBiz,
)

View File

@ -12,8 +12,6 @@ import (
"geo/internal/config"
"geo/internal/data/impl"
"geo/internal/data/model"
"geo/tmpl/errcode"
"xorm.io/builder"
)
@ -45,21 +43,6 @@ func NewPublishBiz(
}
}
func (b *PublishBiz) ValidateAccessToken(ctx context.Context, accessToken string) (*model.Token, error) {
cond := builder.NewCond().
And(builder.Eq{"access_token": accessToken}).
And(builder.Eq{"status": 1})
tokenInfo := &model.Token{}
err := b.tokenImpl.GetOneBySearchStruct(ctx, &cond, tokenInfo)
if err != nil {
return nil, errcode.Forbidden("密钥无效或已禁用")
}
if tokenInfo.ID == 0 {
return nil, errcode.Forbidden("密钥无效或已禁用")
}
return tokenInfo, nil
}
func (b *PublishBiz) BatchInsertPublish(ctx context.Context, list []*model.Publish) error {
return b.publishImpl.Add(ctx, list)

View File

@ -56,7 +56,7 @@ func LoadConfig() (*Config, error) {
Source: "root:lansexiongdi6,@tcp(47.97.27.195:3306)/geo?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai",
},
Sys: Sys{
AutoPublishWorkers: 3,
AutoPublishWorkers: 5,
MaxConcurrent: 1,
TaskTimeout: 200,
SessionTimeout: 300,

View File

@ -0,0 +1 @@
package constant

View File

@ -0,0 +1 @@
package constant

View File

@ -0,0 +1,27 @@
package impl
import (
"geo/internal/data/model"
"geo/tmpl/dataTemp"
"geo/utils"
)
type ProductImpl struct {
dataTemp.DataTemp
db *utils.Db
}
func NewProductImpl(db *utils.Db) *UserImpl {
return &UserImpl{
DataTemp: *dataTemp.NewDataTemp(db, new(model.Product)),
db: db,
}
}
func (m *ProductImpl) PrimaryKey() string {
return "id"
}
func (m *ProductImpl) GetTemp() *dataTemp.DataTemp {
return &m.DataTemp
}

View File

@ -10,4 +10,5 @@ var ProviderImpl = wire.NewSet(
NewUserImpl,
NewTokenImpl,
NewPublishImpl,
NewProductImpl,
)

View File

@ -0,0 +1,36 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package model
import (
"gorm.io/gorm"
"time"
)
const TableNameProduct = "product"
type Product struct {
ID int32 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
UserIndex string `gorm:"column:user_index;not null" json:"user_index"`
Name string `gorm:"column:name;not null;default:''" json:"name"`
Industry string `gorm:"column:industry;not null" json:"industry"`
Type string `gorm:"column:type;not null;default:''" json:"type"`
Advantages string `gorm:"column:advantages;type:text" json:"advantages"`
Problem string `gorm:"column:problem;type:text" json:"problem"`
Background string `gorm:"column:background;type:text" json:"background"`
Case string `gorm:"column:case;type:text" json:"case"`
Other string `gorm:"column:other;type:text" json:"other"`
ServiceCope string `gorm:"column:service_cope;size:100" json:"service_cope"`
TargetAudience string `gorm:"column:target_audience;size:255" json:"target_audience"`
CreateAt *time.Time `gorm:"column:create_at" json:"create_at"`
UpdateAt *time.Time `gorm:"column:update_at" json:"update_at"`
DeleteAt gorm.DeletedAt `gorm:"column:delete_at;index" json:"delete_at"`
Status int8 `gorm:"column:status;default:1" json:"status"`
}
// TableName LoginRelation's table name
func (*Product) TableName() string {
return TableNameProduct
}

View File

@ -86,4 +86,63 @@ type (
UserIndex string `json:"user_index" validate:"required" zh:"用户索引"`
PlatIndex string `json:"plat_index" validate:"required" zh:"平台索引"`
}
CreateProductRequest struct {
AccessToken string `json:"access_token" validate:"required" zh:"access_token"`
UserIndex string `json:"user_index" validate:"required" zh:"用户索引"`
Name string `json:"name" validate:"required" zh:"产品名称"`
Industry string `json:"industry" validate:"required" zh:"所属行业"`
Type string `json:"type" validate:"required" zh:"产品类型"`
Advantages string `json:"advantages" zh:"核心优势"`
Story string `json:"story" zh:"发展故事"`
Problem string `json:"problem" zh:"解决痛点"`
Background string `json:"background" zh:"信任背书"`
Case string `json:"case" zh:"品牌案例"`
Other string `json:"other" zh:"其他信息"`
ServiceCope string `json:"service_cope" zh:"服务范围"`
TargetAudience string `json:"target_audience" zh:"目标客户群体"`
}
ProductListRequest struct {
AccessToken string `json:"access_token" validate:"required" zh:"access_token"`
UserIndex string `json:"user_index" validate:"required" zh:"用户索引"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}
ProductUpdateRequest struct {
AccessToken string `json:"access_token" validate:"required" zh:"access_token"`
UserIndex string `json:"user_index" validate:"required" zh:"用户索引"`
PlatIndex string `json:"plat_index" validate:"required" zh:"平台索引"`
}
ProductDelRequest struct {
AccessToken string `json:"access_token" validate:"required" zh:"access_token"`
UserIndex string `json:"user_index" validate:"required" zh:"用户索引"`
PlatIndex string `json:"plat_index" validate:"required" zh:"平台索引"`
}
ProductSourceCreateRequest struct {
AccessToken string `json:"access_token" validate:"required" zh:"access_token"`
UserIndex string `json:"user_index" validate:"required" zh:"用户索引"`
PlatIndex string `json:"plat_index" validate:"required" zh:"平台索引"`
}
ProductSourceListRequest struct {
AccessToken string `json:"access_token" validate:"required" zh:"access_token"`
UserIndex string `json:"user_index" validate:"required" zh:"用户索引"`
PlatIndex string `json:"plat_index" validate:"required" zh:"平台索引"`
}
ProductSourceUploadRequest struct {
AccessToken string `json:"access_token" validate:"required" zh:"access_token"`
UserIndex string `json:"user_index" validate:"required" zh:"用户索引"`
PlatIndex string `json:"plat_index" validate:"required" zh:"平台索引"`
}
ProductSourceDelRequest struct {
AccessToken string `json:"access_token" validate:"required" zh:"access_token"`
UserIndex string `json:"user_index" validate:"required" zh:"用户索引"`
PlatIndex string `json:"plat_index" validate:"required" zh:"平台索引"`
}
)

View File

@ -4,15 +4,16 @@ import (
"geo/internal/config"
"geo/internal/entitys"
"geo/internal/service"
"github.com/gofiber/fiber/v2"
)
type AppModule struct {
cfg *config.Config
appService *service.AppService
loginService *service.LoginService
publishService *service.PublishService
cfg *config.Config
appService *service.AppService
loginService *service.LoginService
publishService *service.PublishService
productService *service.ProductService
productSourceService *service.ProductSourceService
}
func NewAppModule(
@ -20,12 +21,16 @@ func NewAppModule(
appService *service.AppService,
loginService *service.LoginService,
publishService *service.PublishService,
productService *service.ProductService,
productSourceService *service.ProductSourceService,
) *AppModule {
return &AppModule{
cfg: cfg,
appService: appService,
loginService: loginService,
publishService: publishService,
cfg: cfg,
appService: appService,
loginService: loginService,
publishService: publishService,
productService: productService,
productSourceService: productSourceService,
}
}
@ -39,10 +44,19 @@ func (m *AppModule) Register(router fiber.Router) {
router.Post("/publish_on", vali(m.publishService.PublishOn, &entitys.PublishOnRequest{}))
router.Post("/publish_off", vali(m.publishService.PublishOff, &entitys.PublishOffRequest{}))
router.Post("/publish_status", vali(m.publishService.PublishStatus, &entitys.PublishStatusRequest{}))
//router.Post("/publish_execute_once", vali(m.publishService.PublishExecuteOnce, &entitys.PublishExecuteOnceRequest{}))
router.Post("/publish_execute_retry", vali(m.publishService.PublishExecuteRetry, &entitys.PublishExecuteRetryRequest{}))
router.Post("/get_publish_list", vali(m.publishService.GetPublishList, &entitys.GetPublishListRequest{}))
router.Post("/login_platform", vali(m.loginService.LoginPlatform, &entitys.LoginPlatformRequest{}))
router.Post("/logout_platform", vali(m.loginService.LogoutPlatform, &entitys.LogoutPlatformRequest{}))
router.Get("/logs/:request_id", m.loginService.Log)
router.Get("/product/add", vali(m.productService.Add, &entitys.ProductAddRequest{}))
router.Get("/product/list", vali(m.productService.List, &entitys.ProductListRequest{}))
router.Get("/product/update", vali(m.productService.Update, &entitys.ProductUpdateRequest{}))
router.Get("/product/del", vali(m.productService.Del, &entitys.ProductDelRequest{}))
router.Get("/product/word/create", vali(m.productSourceService.Create, &entitys.ProductSourceCreateRequest{}))
router.Get("/product/word/list", vali(m.productSourceService.List, &entitys.ProductSourceListRequest{}))
router.Get("/product/word/upload", vali(m.productSourceService.Upload, &entitys.ProductSourceUploadRequest{}))
router.Get("/product/word/del", vali(m.productSourceService.Del, &entitys.ProductSourceDelRequest{}))
}

View File

@ -23,6 +23,7 @@ type AppService struct {
platImpl *impl.PlatImpl
loginRelationImpl *impl.LoginRelationImpl
publishBiz *biz.PublishBiz
authBiz *biz.AuthBiz
}
func NewAppService(
@ -32,6 +33,7 @@ func NewAppService(
userImpl *impl.UserImpl,
platImpl *impl.PlatImpl,
publishBiz *biz.PublishBiz,
authBiz *biz.AuthBiz,
loginRelationImpl *impl.LoginRelationImpl,
) *AppService {
return &AppService{
@ -41,6 +43,7 @@ func NewAppService(
userImpl: userImpl,
platImpl: platImpl,
publishBiz: publishBiz,
authBiz: authBiz,
}
}
@ -77,7 +80,7 @@ func (a *AppService) LoginApp(c *fiber.Ctx, req *entitys.LoginAppRequest) error
}
func (a *AppService) GetUserAndAutoStatus(c *fiber.Ctx, req *entitys.GetUserAndAutoStatusRequest) error {
tokenInfo, err := a.publishBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
tokenInfo, err := a.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
if err != nil {
return err
}
@ -102,7 +105,7 @@ func (a *AppService) GetUserAndAutoStatus(c *fiber.Ctx, req *entitys.GetUserAndA
}
func (a *AppService) AddUser(c *fiber.Ctx, req *entitys.AddUserRequest) error {
tokenInfo, err := a.publishBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
tokenInfo, err := a.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
if err != nil {
return err
}
@ -159,7 +162,7 @@ func (a *AppService) AddUser(c *fiber.Ctx, req *entitys.AddUserRequest) error {
func (a *AppService) DelUser(c *fiber.Ctx, req *entitys.DelUserRequest) error {
// 需要从请求中获取 access_token
_, err := a.publishBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
_, err := a.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
if err != nil {
return err
}
@ -172,7 +175,7 @@ func (a *AppService) DelUser(c *fiber.Ctx, req *entitys.DelUserRequest) error {
}
func (a *AppService) GetApp(c *fiber.Ctx, req *entitys.GetAppRequest) error {
_, err := a.publishBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
_, err := a.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
if err != nil {
return err
}

View File

@ -18,21 +18,23 @@ import (
type LoginService struct {
cfg *config.Config
publishBiz *biz.PublishBiz
authBiz *biz.AuthBiz
}
func NewLoginService(
cfg *config.Config,
publishBiz *biz.PublishBiz,
authBiz *biz.AuthBiz,
) *LoginService {
return &LoginService{
cfg: cfg,
publishBiz: publishBiz,
authBiz: authBiz,
}
}
func (s *LoginService) LoginPlatform(c *fiber.Ctx, req *entitys.LoginPlatformRequest) error {
_, err := s.publishBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
_, err := s.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
if err != nil {
return err
}
@ -74,7 +76,7 @@ func (s *LoginService) LoginPlatform(c *fiber.Ctx, req *entitys.LoginPlatformReq
}
func (s *LoginService) LogoutPlatform(c *fiber.Ctx, req *entitys.LogoutPlatformRequest) error {
_, err := s.publishBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
_, err := s.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
if err != nil {
return err
}

View File

@ -0,0 +1,92 @@
package service
import (
"geo/internal/biz"
"geo/internal/config"
"geo/internal/data/impl"
"geo/internal/data/model"
"geo/internal/entitys"
"geo/pkg"
"geo/tmpl/dataTemp"
"github.com/gofiber/fiber/v2"
)
type ProductService struct {
cfg *config.Config
productImpl *impl.ProductImpl
authBiz *biz.AuthBiz
}
func NewProductService(cfg *config.Config, ProductImpl *impl.ProductImpl, authBiz *biz.AuthBiz) *ProductService {
return &ProductService{
cfg: cfg,
productImpl: ProductImpl,
authBiz: authBiz,
}
}
func (p *ProductService) Add(c *fiber.Ctx, req *entitys.CreateProductRequest) error {
userInfo, _, err := p.authBiz.UserAndTokenValid(c.UserContext(), req.UserIndex, req.AccessToken)
if err != nil {
return err
}
add := &model.Product{
UserIndex: userInfo.UserIndex,
Name: req.Name,
Industry: req.Industry,
Type: req.Type,
Advantages: req.Advantages,
Problem: req.Problem,
Background: req.Background,
Case: req.Case,
Other: req.Other,
ServiceCope: req.ServiceCope,
TargetAudience: req.TargetAudience,
}
err = p.productImpl.Add(c.UserContext(), add)
if err != nil {
return err
}
return nil
}
func (p *ProductService) List(c *fiber.Ctx, req *entitys.ProductListRequest) error {
_, _, err := p.authBiz.UserAndTokenValid(c.UserContext(), req.UserIndex, req.AccessToken)
if err != nil {
return err
}
page := req.Page
if page < 1 {
page = 1
}
pageSize := req.PageSize
if pageSize < 1 {
pageSize = 20
}
if pageSize > 100 {
pageSize = 100
}
var list []*model.Product
total, err := p.productImpl.GetListToStruct(c.UserContext(), nil, &dataTemp.ReqPageBo{Page: page, Limit: pageSize}, list, "")
if err != nil {
return err
}
return pkg.SuccessWithPageMsg(c, list, total.Total, page, pageSize)
}
func (p *ProductService) Update(c *fiber.Ctx, req *entitys.ProductUpdateRequest) error {
userInfo, _, err := p.authBiz.UserAndTokenValid(c.UserContext(), req.UserIndex, req.AccessToken)
if err != nil {
return err
}
return nil
}
func (p *ProductService) Del(c *fiber.Ctx, req *entitys.ProductDelRequest) error {
userInfo, _, err := p.authBiz.UserAndTokenValid(c.UserContext(), req.UserIndex, req.AccessToken)
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,63 @@
package service
import (
"geo/internal/biz"
"geo/internal/config"
"geo/internal/data/impl"
"geo/internal/entitys"
"github.com/gofiber/fiber/v2"
)
type ProductSourceService struct {
cfg *config.Config
productImpl *impl.ProductImpl
authBiz *biz.AuthBiz
}
func NewProductSourceService(cfg *config.Config, ProductImpl *impl.ProductImpl, authBiz *biz.AuthBiz) *ProductSourceService {
return &ProductSourceService{
cfg: cfg,
productImpl: ProductImpl,
authBiz: authBiz,
}
}
func (p *ProductSourceService) Create(c *fiber.Ctx, req *entitys.ProductSourceCreateRequest) error {
// 验证token
userInfo, _, err := p.authBiz.UserAndTokenValid(c.UserContext(), req.UserIndex, req.AccessToken)
if err != nil {
return err
}
return nil
}
func (p *ProductSourceService) List(c *fiber.Ctx, req *entitys.ProductSourceListRequest) error {
// 验证token
userInfo, _, err := p.authBiz.UserAndTokenValid(c.UserContext(), req.UserIndex, req.AccessToken)
if err != nil {
return err
}
return nil
}
func (p *ProductSourceService) Upload(c *fiber.Ctx, req *entitys.ProductSourceUploadRequest) error {
// 验证token
userInfo, _, err := p.authBiz.UserAndTokenValid(c.UserContext(), req.UserIndex, req.AccessToken)
if err != nil {
return err
}
return nil
}
func (p *ProductSourceService) Del(c *fiber.Ctx, req *entitys.ProductSourceDelRequest) error {
// 验证token
userInfo, _, err := p.authBiz.UserAndTokenValid(c.UserContext(), req.UserIndex, req.AccessToken)
if err != nil {
return err
}
return nil
}

View File

@ -8,4 +8,6 @@ var ProviderSetAppService = wire.NewSet(
NewAppService,
NewPublishService,
NewLoginService,
NewProductService,
NewProductSourceService,
)

View File

@ -24,23 +24,26 @@ type PublishService struct {
cfg *config.Config
publishBiz *biz.PublishBiz
db *utils.Db
authBiz *biz.AuthBiz
}
func NewPublishService(
cfg *config.Config,
publishBiz *biz.PublishBiz,
authBiz *biz.AuthBiz,
db *utils.Db,
) *PublishService {
return &PublishService{
cfg: cfg,
publishBiz: publishBiz,
db: db,
authBiz: authBiz,
}
}
func (s *PublishService) PublishRecords(c *fiber.Ctx, req *entitys.PublishRecordsRequest) error {
// 验证token
tokenInfo, err := s.publishBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
tokenInfo, err := s.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
if err != nil {
return err
}
@ -79,7 +82,7 @@ func (s *PublishService) PublishRecords(c *fiber.Ctx, req *entitys.PublishRecord
}
func (s *PublishService) PublishOn(c *fiber.Ctx, req *entitys.PublishOnRequest) error {
tokenInfo, err := s.publishBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
tokenInfo, err := s.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
if err != nil {
return err
}
@ -97,7 +100,7 @@ func (s *PublishService) PublishOn(c *fiber.Ctx, req *entitys.PublishOnRequest)
}
func (s *PublishService) PublishOff(c *fiber.Ctx, req *entitys.PublishOffRequest) error {
_, err := s.publishBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
_, err := s.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
if err != nil {
return err
}
@ -113,7 +116,7 @@ func (s *PublishService) PublishOff(c *fiber.Ctx, req *entitys.PublishOffRequest
}
func (s *PublishService) PublishStatus(c *fiber.Ctx, req *entitys.PublishStatusRequest) error {
_, err := s.publishBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
_, err := s.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
if err != nil {
return err
}
@ -147,7 +150,7 @@ func (s *PublishService) PublishStatus(c *fiber.Ctx, req *entitys.PublishStatusR
//}
func (s *PublishService) PublishExecuteRetry(c *fiber.Ctx, req *entitys.PublishExecuteRetryRequest) error {
tokenInfo, err := s.publishBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
tokenInfo, err := s.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
if err != nil {
return err
}
@ -162,7 +165,7 @@ func (s *PublishService) PublishExecuteRetry(c *fiber.Ctx, req *entitys.PublishE
}
func (s *PublishService) GetPublishList(c *fiber.Ctx, req *entitys.GetPublishListRequest) error {
tokenInfo, err := s.publishBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
tokenInfo, err := s.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken)
if err != nil {
return err
}

View File

@ -6,6 +6,7 @@ import (
"os"
"os/exec"
"path/filepath"
"strings"
)
// ExtractWordContent 从docx文件提取内容
@ -104,3 +105,76 @@ func CopyImageToDoc(docPath, imgPath string) error {
return nil
}
// Md2wordFix 将 Markdown 文件转换为 Word 文档,并支持插入图片
// 参数:
// - mdFile: Markdown 文件路径
// - outputDir: 输出目录路径
// - img: 图片路径列表(按顺序插入到 ## 标题之间,跳过第一个)
//
// 返回:
// - error: 错误信息,成功返回
func Md2wordFix(mdFile, outPutDIr string, img []string) error {
baseDir, err := os.Getwd()
if err != nil {
return fmt.Errorf("获取工作目录失败: %w", err)
}
exePath := filepath.Join(baseDir, "plugins", "md2word_fix.exe")
// 3. 检查 exe 是否存在
if _, err = os.Stat(exePath); os.IsNotExist(err) {
return fmt.Errorf("exe不存在: %s", exePath)
}
// 4. 检查 Markdown 文件是否存在
if _, err = os.Stat(mdFile); os.IsNotExist(err) {
return fmt.Errorf("Markdown文件不存在: %s", mdFile)
}
// 5. 确保输出目录存在
if err = os.MkdirAll(outPutDIr, 0755); err != nil {
return fmt.Errorf("创建输出目录失败: %w", err)
}
//7. 构建命令行参数
args := []string{"-i", mdFile, "-o", outPutDIr}
// 如果有图片,添加图片参数
if len(img) > 0 {
// 过滤空图片路径
validImages := make([]string, 0)
for _, img := range img {
if strings.TrimSpace(img) != "" {
validImages = append(validImages, img)
}
}
if len(validImages) > 0 {
imagesArg := strings.Join(validImages, ",")
args = append(args, "--images", imagesArg)
}
}
cmd := exec.Command(exePath, args...)
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("执行失败: %v", err)
}
var result struct {
Success bool `json:"success"`
Content string `json:"content"`
Error string `json:"error"`
}
if err = json.Unmarshal(output, &result); err != nil {
return fmt.Errorf("解析结果失败: %v, 输出: %s", err, string(output))
}
if !result.Success {
return fmt.Errorf("插入图片失败: %s", result.Error)
}
return nil
}

BIN
plugins/md2word_fix.exe Normal file

Binary file not shown.

View File

@ -14,6 +14,7 @@ type Db struct {
func NewGormDb(c *config.Config) (*Db, func()) {
transDBClient, mf := utils_gorm.DBConn(&c.DB)
//directDBClient, df := directDB(c, hLog)
cleanup := func() {
mf()
//df()

View File

@ -6,6 +6,7 @@ import (
"geo/internal/config"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"time"
)
@ -14,11 +15,11 @@ func DBConn(c *config.DB) (*gorm.DB, func()) {
gormDB, err := gorm.Open(
mysql.New(mysql.Config{Conn: mysqlConn}),
)
gormDB.Logger = NewCustomLogger(gormDB)
gormDB.Logger = gormDB.Logger.LogMode(logger.Silent)
if err != nil {
panic("failed to connect database")
}
sqlDB, err := gormDB.DB()
// SetMaxIdleConns sets the maximum number of connections in the idle connection pool.