refactor: 对齐后端样例工程规范
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
# PostgreSQL 为首期唯一必需的真实依赖;请仅在本地环境文件中填写真实连接串。
|
||||
DATABASE_URL=postgres://postgres:change-me@localhost:5432/agent_dev?sslmode=disable
|
||||
PORT=8080
|
||||
|
||||
# 其它外部能力在首期使用 Mock;不要在仓库提交真实 Redis、支付或 IoT 凭证。
|
||||
REDIS_URL=redis://default:change-me@127.0.0.1:6379/0
|
||||
APP_ENV=development
|
||||
@@ -1,11 +1,12 @@
|
||||
# 平台核心后端
|
||||
# 后端服务仓
|
||||
|
||||
首期实现 M0 + M1 的平台总后台 API:组织、服务人员、用户、安全事件和仪表盘。PostgreSQL 保存业务事实;支付、地图、IoT、短信和 Redis 在本阶段均通过 Mock 边界预留,不连接生产外部服务。
|
||||
本目录严格采用 [sample/server](../../sample/server) 的 BSM-SDK Core 分层:每个 Go 进程均使用 `cmd`、`internal/config`、`internal/impl`、`internal/logic`、`internal/models`、`internal/routers`、`etc`、`scripts`、`test` 和 `Makefile` 约定。
|
||||
|
||||
## 运行
|
||||
| 目录 | 进程与职责 |
|
||||
| --- | --- |
|
||||
| `api` | Gin HTTP API / BFF、同步事务、JWT 鉴权与统一响应 |
|
||||
| `worker` | Redis Streams 消费、Outbox 投递、超时扫描与 Mock 外部适配 |
|
||||
| `iot` | MQTT 协议适配边界、遥测/命令契约校验与 Mock 设备接入 |
|
||||
| `migrations` | PostgreSQL 迁移、中文注释、回滚说明和初始化数据 |
|
||||
|
||||
1. 将 `.env.example` 复制为本地环境文件,设置 `DATABASE_URL`。
|
||||
2. 在 PowerShell 设置 `DATABASE_URL` 后执行 `go run ./cmd/api`。
|
||||
3. 服务启动时自动执行幂等迁移和演示数据初始化。
|
||||
|
||||
接口前缀为 `/api/v1`,例如:`GET /api/v1/dashboard/overview`。
|
||||
`sample/server` 的工程机制被直接沿用;但由于项目规范强制要求 `identity` 为 UUID V7 主键,领域模型使用自定义 `models.Entity`,不使用样例中含自增 `ID` 的 `types.Std_IICUDS`。
|
||||
|
||||
21
backend/api/Makefile
Normal file
21
backend/api/Makefile
Normal file
@@ -0,0 +1,21 @@
|
||||
.PHONY: build run cli migrate lint tidy
|
||||
|
||||
build:
|
||||
go build -o build/platform-api ./cmd/main/main.go
|
||||
go build -o build/platform-cli ./cmd/cli/main.go
|
||||
|
||||
run:
|
||||
go run ./cmd/main/main.go
|
||||
|
||||
cli:
|
||||
go run ./cmd/cli/main.go $(ARGS)
|
||||
|
||||
migrate:
|
||||
go run ./cmd/cli/main.go migrate
|
||||
|
||||
lint:
|
||||
go vet ./...
|
||||
go fmt ./...
|
||||
|
||||
tidy:
|
||||
go mod tidy
|
||||
12
backend/api/README.md
Normal file
12
backend/api/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Platform API
|
||||
|
||||
严格沿用 `sample/server` 的 BSM-SDK Core 分层和运行方式。运行前设置:
|
||||
|
||||
```powershell
|
||||
$env:BSM_RuntimeMode="dev"
|
||||
$env:BSM_Prefix="$(Get-Location)/etc"
|
||||
$env:BSM_JwtSecretKey="仅本地使用的随机密钥"
|
||||
go run ./cmd/main/main.go
|
||||
```
|
||||
|
||||
`cmd/cli` 提供 `version` 与 `migrate`;受保护接口使用 `middleware.JwtAuth(true)`。UUID V7 主键及完整中文注释以 `../migrations` 为准。
|
||||
31
backend/api/cmd/cli/main.go
Normal file
31
backend/api/cmd/cli/main.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// 平台 API 的数据库迁移与版本命令行工具。
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/config"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
_ "git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
)
|
||||
|
||||
const serviceKey = "Platform"
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Println("usage: platform-cli <version|migrate>")
|
||||
return
|
||||
}
|
||||
switch os.Args[1] {
|
||||
case "version":
|
||||
fmt.Println("platform-cli 0.1.0")
|
||||
case "migrate":
|
||||
config.New(serviceKey)
|
||||
impl.NewImpl()
|
||||
fmt.Println("platform database auto migrate completed")
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "unknown command: %s\n", os.Args[1])
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
49
backend/api/cmd/main/main.go
Normal file
49
backend/api/cmd/main/main.go
Normal file
@@ -0,0 +1,49 @@
|
||||
// 平台 HTTP API 进程入口,沿用 sample/server 的 BSM 启动规范。
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/middleware"
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/config"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/routers"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const serviceKey = "Platform"
|
||||
|
||||
func main() {
|
||||
config.New(serviceKey)
|
||||
impl.NewImpl()
|
||||
|
||||
app := gin.Default()
|
||||
middleware.Mode(app)
|
||||
app.Use(middleware.Cors())
|
||||
app.Use(gin.Recovery())
|
||||
app.HEAD("/", infra.Health)
|
||||
routers.Register(serviceKey, app)
|
||||
|
||||
server := &http.Server{Addr: fmt.Sprintf(":%s", config.Spec.Port), Handler: app}
|
||||
go func() {
|
||||
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
printer.Success("[BSM - %s] Service Started At: %s", serviceKey, server.Addr)
|
||||
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-quit
|
||||
shutdownContext, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
_ = server.Shutdown(shutdownContext)
|
||||
}
|
||||
4
backend/api/etc/platform.env.example
Normal file
4
backend/api/etc/platform.env.example
Normal file
@@ -0,0 +1,4 @@
|
||||
BSM_Workspace=default
|
||||
BSM_RuntimeMode=dev
|
||||
BSM_Prefix=./etc
|
||||
BSM_JwtSecretKey=change-me-to-a-random-string
|
||||
12
backend/api/etc/platform_dev.yaml
Normal file
12
backend/api/etc/platform_dev.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
Service: platform
|
||||
Port: 12426
|
||||
|
||||
Databases:
|
||||
Driver: postgres
|
||||
Source:
|
||||
- host=127.0.0.1 user=postgres password=change-me dbname=agent_dev port=5432 sslmode=disable TimeZone=Asia/Shanghai
|
||||
|
||||
# Redis 仅用于缓存、会话、限流和 Streams;首期外部事件适配使用 Mock。
|
||||
Cache: redis://default:change-me@127.0.0.1:6379/0
|
||||
OnMicroService: false
|
||||
SecretKey: change-me-to-a-random-string
|
||||
75
backend/api/go.mod
Normal file
75
backend/api/go.mod
Normal file
@@ -0,0 +1,75 @@
|
||||
module git.apinb.com/heqiapp/platforms/backend/api
|
||||
|
||||
go 1.26.1
|
||||
|
||||
require (
|
||||
git.apinb.com/bsm-sdk/core v0.2.0
|
||||
github.com/gin-gonic/gin v1.12.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
gorm.io/gorm v1.31.1
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||
github.com/bytedance/sonic v1.15.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.5.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
||||
github.com/gin-contrib/cors v1.7.7 // indirect
|
||||
github.com/gin-contrib/sse v1.1.0 // 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.30.1 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/pgx/v5 v5.6.0 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/oklog/ulid/v2 v2.1.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/quic-go/quic-go v0.59.0 // indirect
|
||||
github.com/redis/go-redis/v9 v9.19.0 // indirect
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.6.11 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.11 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.6.11 // indirect
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/arch v0.23.0 // indirect
|
||||
golang.org/x/crypto v0.49.0 // indirect
|
||||
golang.org/x/net v0.52.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.44.0 // indirect
|
||||
golang.org/x/text v0.36.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect
|
||||
google.golang.org/grpc v1.81.1 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/driver/mysql v1.6.0 // indirect
|
||||
gorm.io/driver/postgres v1.6.0 // indirect
|
||||
)
|
||||
225
backend/api/go.sum
Normal file
225
backend/api/go.sum
Normal file
@@ -0,0 +1,225 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
git.apinb.com/bsm-sdk/core v0.2.0 h1:/e9yqpsbKBrRgMiGpS3KX2O4qDLxo5V5GpPSLNGxEKw=
|
||||
git.apinb.com/bsm-sdk/core v0.2.0/go.mod h1:E9T6Eboo/0Zb36BjkKbIgvFzq4fQ2Q8P/7y5zmYTI6Y=
|
||||
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/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
|
||||
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
|
||||
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
|
||||
github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE=
|
||||
github.com/bytedance/sonic/loader v0.5.0/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.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
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/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
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.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||
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-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
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.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w=
|
||||
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
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/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
|
||||
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
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/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/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
|
||||
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
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/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
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/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/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
|
||||
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
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.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
github.com/redis/go-redis/v9 v9.19.0 h1:XPVaaPSnG6RhYf7p+rmSa9zZfeVAnWsH5h3lxthOm/k=
|
||||
github.com/redis/go-redis/v9 v9.19.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||
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.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/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.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
||||
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
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.etcd.io/etcd/api/v3 v3.6.11 h1:XFGTgrJ8nak3kB4NgMG8t7NT+lEeuuvKQAqUHKVgkWQ=
|
||||
go.etcd.io/etcd/api/v3 v3.6.11/go.mod h1:HYfTh0jyh+uFgp6gMbxJteIDYY97yMuYz85Rnw6Gy9o=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.11 h1:e41mp315Yn3QMGPmEzCyLsMINgJXTY/dX8kM++1csxU=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.11/go.mod h1:DysuMe/inqRyC/1tjRR6hReH/VV9Lufs27YKSKBWWJg=
|
||||
go.etcd.io/etcd/client/v3 v3.6.11 h1:LAByD96VmmeuairkvdAcE0RZnrmGz/q3ceeWePo9bwc=
|
||||
go.etcd.io/etcd/client/v3 v3.6.11/go.mod h1:vOTDMCo+fGPEClJqcFEFSqZ+8e7WKV7AyqJjX//HR2w=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
|
||||
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
|
||||
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||
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/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/arch v0.23.0 h1:lKF64A2jF6Zd8L0knGltUnegD62JMFBiCPBmQpToHhg=
|
||||
golang.org/x/arch v0.23.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
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/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
|
||||
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/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=
|
||||
gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
|
||||
gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
|
||||
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
|
||||
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
||||
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
|
||||
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
|
||||
29
backend/api/internal/config/config.go
Normal file
29
backend/api/internal/config/config.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Package config 沿用 sample/server 的 BSM 配置加载与校验方式。
|
||||
package config
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/conf"
|
||||
)
|
||||
|
||||
// Spec 是 Platform API 的运行配置。
|
||||
var Spec SrvConfig
|
||||
|
||||
// SrvConfig 与 sample/server 配置结构保持一致。
|
||||
type SrvConfig struct {
|
||||
conf.Base `yaml:",inline"`
|
||||
Databases *conf.DBConf `yaml:"Databases"`
|
||||
Rpc map[string]conf.RpcConf `yaml:"Rpc"`
|
||||
Apm *conf.ApmConf `yaml:"APM"`
|
||||
}
|
||||
|
||||
// New 初始化 BSM 配置并校验服务监听地址。
|
||||
func New(srvKey string) {
|
||||
conf.New(srvKey, &Spec)
|
||||
Spec.Port = conf.CheckPort(Spec.Port)
|
||||
Spec.BindIP = conf.CheckIP(Spec.BindIP)
|
||||
Spec.Addr = net.JoinHostPort(Spec.BindIP, Spec.Port)
|
||||
conf.NotNil(Spec.Service, Spec.Cache)
|
||||
conf.PrintInfo(Spec.Addr)
|
||||
}
|
||||
25
backend/api/internal/impl/new.go
Normal file
25
backend/api/internal/impl/new.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// Package impl 统一创建数据库、Redis、内存缓存与日志基础设施。
|
||||
package impl
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/cache/redis"
|
||||
"git.apinb.com/bsm-sdk/core/logger"
|
||||
"git.apinb.com/bsm-sdk/core/with"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/config"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
RedisService *redis.RedisClient
|
||||
DBService *gorm.DB
|
||||
MemoryService *cache.Cache
|
||||
)
|
||||
|
||||
// NewImpl 与 sample/server 保持一致,所有进程通过此处创建共享基础设施。
|
||||
func NewImpl() {
|
||||
MemoryService = with.Memory(nil)
|
||||
RedisService = with.RedisCache(config.Spec.Cache)
|
||||
DBService = with.Databases(config.Spec.Databases, nil)
|
||||
logger.New(nil)
|
||||
}
|
||||
18
backend/api/internal/logic/dashboard/dashboard.go
Normal file
18
backend/api/internal/logic/dashboard/dashboard.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Package dashboard 提供平台总后台聚合指标。
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Overview 返回组织与安全运营的首期概览数据。
|
||||
func Overview(ctx *gin.Context) {
|
||||
overview, err := models.GetDashboardOverview()
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, overview)
|
||||
}
|
||||
54
backend/api/internal/logic/idn_account/idn_account.go
Normal file
54
backend/api/internal/logic/idn_account/idn_account.go
Normal file
@@ -0,0 +1,54 @@
|
||||
// Package idn_account 提供用户账户最小必要查询逻辑。
|
||||
package idn_account
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// AccountView 是 idn_account 的最小必要输出,手机号始终脱敏。
|
||||
type AccountView struct {
|
||||
Identity string `json:"identity"` // 用户主键
|
||||
PhoneMasked string `json:"phone_masked"` // 脱敏手机号
|
||||
AccountType string `json:"account_type"` // 账户类型
|
||||
Status string `json:"status"` // 账户状态
|
||||
ServiceArea string `json:"service_area"` // 服务区域
|
||||
}
|
||||
|
||||
// ListReply 是 idn_account 的标准分页响应。
|
||||
type ListReply struct {
|
||||
Total int64 `json:"total"`
|
||||
List []AccountView `json:"list"`
|
||||
}
|
||||
|
||||
// List 查询普通用户账户列表。
|
||||
func List(ctx *gin.Context) {
|
||||
page := utils.String2Int(ctx.DefaultQuery("page", "1"))
|
||||
size := utils.String2Int(ctx.DefaultQuery("size", "20"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
list, total, err := models.ListIdnAccount(page, size)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
views := make([]AccountView, 0, len(list))
|
||||
for _, item := range list {
|
||||
views = append(views, AccountView{Identity: item.Identity.String(), PhoneMasked: maskPhone(item.Phone), AccountType: item.AccountType, Status: item.Status, ServiceArea: item.ServiceArea})
|
||||
}
|
||||
infra.Response.Success(ctx, ListReply{Total: total, List: views})
|
||||
}
|
||||
|
||||
// maskPhone 遵循敏感数据最小展示原则。
|
||||
func maskPhone(phone string) string {
|
||||
if len(phone) < 7 {
|
||||
return "***"
|
||||
}
|
||||
return phone[:3] + "****" + phone[len(phone)-4:]
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Package org_delivery_point 提供配送点管理查询逻辑。
|
||||
package org_delivery_point
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ListReply 是 org_delivery_point 的标准分页响应。
|
||||
type ListReply struct {
|
||||
Total int64 `json:"total"`
|
||||
List []models.OrgDeliveryPoint `json:"list"`
|
||||
}
|
||||
|
||||
// List 查询配送点分页列表。
|
||||
func List(ctx *gin.Context) {
|
||||
page, size := pageSize(ctx)
|
||||
list, total, err := models.ListOrgDeliveryPoint(page, size)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, ListReply{Total: total, List: list})
|
||||
}
|
||||
|
||||
func pageSize(ctx *gin.Context) (int, int) {
|
||||
page := utils.String2Int(ctx.DefaultQuery("page", "1"))
|
||||
size := utils.String2Int(ctx.DefaultQuery("size", "20"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
return page, size
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Package org_gas_station 提供气站管理的 HTTP 业务逻辑。
|
||||
package org_gas_station
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// CreateRequest 是创建 org_gas_station 的请求体。
|
||||
type CreateRequest struct {
|
||||
StationCode string `json:"station_code" binding:"required,max=32"`
|
||||
Name string `json:"name" binding:"required,max=128"`
|
||||
Principal string `json:"principal" binding:"required,max=64"`
|
||||
ServiceArea string `json:"service_area" binding:"required,max=128"`
|
||||
}
|
||||
|
||||
// ListReply 是标准分页响应。
|
||||
type ListReply struct {
|
||||
Total int64 `json:"total"`
|
||||
List []models.OrgGasStation `json:"list"`
|
||||
}
|
||||
|
||||
// Create 创建待审核气站并由数据库层保证唯一编码。
|
||||
func Create(ctx *gin.Context) {
|
||||
var request CreateRequest
|
||||
if err := ctx.ShouldBindJSON(&request); err != nil {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
data := models.OrgGasStation{StationCode: request.StationCode, Name: request.Name, Principal: request.Principal, ServiceArea: request.ServiceArea}
|
||||
data.Identity = models.NewIdentity()
|
||||
data.Status = "draft"
|
||||
data.Version = 1
|
||||
if err := models.CreateOrgGasStation(&data); err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, data)
|
||||
}
|
||||
|
||||
// List 查询气站分页列表。
|
||||
func List(ctx *gin.Context) {
|
||||
page := utils.String2Int(ctx.DefaultQuery("page", "1"))
|
||||
size := utils.String2Int(ctx.DefaultQuery("size", "20"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
list, total, err := models.ListOrgGasStation(page, size)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, ListReply{Total: total, List: list})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Package org_service_person 提供服务人员管理查询逻辑。
|
||||
package org_service_person
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ListReply 是 org_service_person 的标准分页响应。
|
||||
type ListReply struct {
|
||||
Total int64 `json:"total"`
|
||||
List []models.OrgServicePerson `json:"list"`
|
||||
}
|
||||
|
||||
// List 查询服务人员分页列表。
|
||||
func List(ctx *gin.Context) {
|
||||
page := utils.String2Int(ctx.DefaultQuery("page", "1"))
|
||||
size := utils.String2Int(ctx.DefaultQuery("size", "20"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
list, total, err := models.ListOrgServicePerson(page, size)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, ListReply{Total: total, List: list})
|
||||
}
|
||||
12
backend/api/internal/logic/ping/hello.go
Normal file
12
backend/api/internal/logic/ping/hello.go
Normal file
@@ -0,0 +1,12 @@
|
||||
// Package ping 提供匿名健康检查接口。
|
||||
package ping
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Hello 返回 API 进程健康状态。
|
||||
func Hello(ctx *gin.Context) {
|
||||
infra.Response.Success(ctx, gin.H{"service": "platform-api", "status": "ok"})
|
||||
}
|
||||
33
backend/api/internal/logic/saf_event/saf_event.go
Normal file
33
backend/api/internal/logic/saf_event/saf_event.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Package saf_event 提供安全事件查询逻辑。
|
||||
package saf_event
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ListReply 是 saf_event 的标准分页响应。
|
||||
type ListReply struct {
|
||||
Total int64 `json:"total"`
|
||||
List []models.SafEvent `json:"list"`
|
||||
}
|
||||
|
||||
// List 查询安全事件列表。
|
||||
func List(ctx *gin.Context) {
|
||||
page := utils.String2Int(ctx.DefaultQuery("page", "1"))
|
||||
size := utils.String2Int(ctx.DefaultQuery("size", "20"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
list, total, err := models.ListSafEvent(page, size)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, ListReply{Total: total, List: list})
|
||||
}
|
||||
28
backend/api/internal/models/entity.go
Normal file
28
backend/api/internal/models/entity.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Package models 定义与数据库表同名的领域模型和数据访问方法。
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Entity 是所有主表共享字段;identity 必须由应用生成 UUID V7,禁止自增主键。
|
||||
type Entity struct {
|
||||
Identity uuid.UUID `gorm:"column:identity;type:uuid;primaryKey" json:"identity"` // 主键,UUID V7
|
||||
CreatedAt time.Time `gorm:"column:created_at;type:timestamptz;not null" json:"created_at"` // 创建时间
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamptz;not null" json:"updated_at"` // 更新时间
|
||||
CreatedByIdentity *uuid.UUID `gorm:"column:created_by_identity;type:uuid" json:"created_by_identity,omitempty"` // 创建人主键
|
||||
UpdatedByIdentity *uuid.UUID `gorm:"column:updated_by_identity;type:uuid" json:"updated_by_identity,omitempty"` // 更新人主键
|
||||
Status string `gorm:"column:status;type:varchar(32);not null;default:'draft'" json:"status"` // 业务状态
|
||||
Version int `gorm:"column:version;not null;default:1" json:"version"` // 乐观锁版本
|
||||
}
|
||||
|
||||
// NewIdentity 生成时间有序 UUID V7,生成失败属于不可恢复的运行时错误。
|
||||
func NewIdentity() uuid.UUID {
|
||||
identity, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return identity
|
||||
}
|
||||
16
backend/api/internal/models/idn_account.go
Normal file
16
backend/api/internal/models/idn_account.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package models
|
||||
|
||||
import "git.apinb.com/bsm-sdk/core/database"
|
||||
|
||||
// IdnAccount 对应 idn_account,表示用户或服务人员身份账户。
|
||||
type IdnAccount struct {
|
||||
Entity
|
||||
Phone string `gorm:"column:phone;type:varchar(32);uniqueIndex;not null" json:"phone"` // 手机号,响应时需脱敏
|
||||
AccountType string `gorm:"column:account_type;type:varchar(32);not null" json:"account_type"` // 账户类型
|
||||
ServiceArea string `gorm:"column:service_area;type:varchar(128);not null" json:"service_area"` // 服务区域
|
||||
}
|
||||
|
||||
func init() { database.AppendMigrate(&IdnAccount{}) }
|
||||
|
||||
// TableName 返回与模型、文件名一致的单数数据表名。
|
||||
func (table *IdnAccount) TableName() string { return "idn_account" }
|
||||
17
backend/api/internal/models/org_delivery_point.go
Normal file
17
backend/api/internal/models/org_delivery_point.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package models
|
||||
|
||||
import "git.apinb.com/bsm-sdk/core/database"
|
||||
|
||||
// OrgDeliveryPoint 对应 org_delivery_point,表示末端配送组织单元。
|
||||
type OrgDeliveryPoint struct {
|
||||
Entity
|
||||
DeliveryCode string `gorm:"column:delivery_code;type:varchar(32);uniqueIndex;not null" json:"delivery_code"` // 配送点编码
|
||||
GasStationIdentity string `gorm:"column:gas_station_identity;type:uuid" json:"gas_station_identity"` // 归属气站主键
|
||||
Name string `gorm:"column:name;type:varchar(128);not null" json:"name"` // 配送点名称
|
||||
ServiceArea string `gorm:"column:service_area;type:varchar(128);not null" json:"service_area"` // 服务区域
|
||||
}
|
||||
|
||||
func init() { database.AppendMigrate(&OrgDeliveryPoint{}) }
|
||||
|
||||
// TableName 返回与模型、文件名一致的单数数据表名。
|
||||
func (table *OrgDeliveryPoint) TableName() string { return "org_delivery_point" }
|
||||
60
backend/api/internal/models/org_gas_station.go
Normal file
60
backend/api/internal/models/org_gas_station.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/database"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// OrgGasStation 对应 org_gas_station,表示可燃气体站经营主体。
|
||||
type OrgGasStation struct {
|
||||
Entity
|
||||
StationCode string `gorm:"column:station_code;type:varchar(32);uniqueIndex;not null" json:"station_code"` // 气站编码
|
||||
Name string `gorm:"column:name;type:varchar(128);not null" json:"name"` // 气站名称
|
||||
Principal string `gorm:"column:principal;type:varchar(64);not null" json:"principal"` // 负责人
|
||||
ServiceArea string `gorm:"column:service_area;type:varchar(128);not null" json:"service_area"` // 服务区域
|
||||
}
|
||||
|
||||
func init() {
|
||||
database.AppendMigrate(&OrgGasStation{})
|
||||
}
|
||||
|
||||
// TableName 返回与模型、文件名一致的单数数据表名。
|
||||
func (table *OrgGasStation) TableName() string { return "org_gas_station" }
|
||||
|
||||
// CreateOrgGasStation 创建待审核气站。
|
||||
func CreateOrgGasStation(data *OrgGasStation) error {
|
||||
if err := impl.DBService.Create(data).Error; err != nil {
|
||||
return errcode.ErrDB
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListOrgGasStation 按创建时间倒序查询气站。
|
||||
func ListOrgGasStation(page, size int) ([]OrgGasStation, int64, error) {
|
||||
var list []OrgGasStation
|
||||
var total int64
|
||||
databaseQuery := impl.DBService.Model(&OrgGasStation{})
|
||||
if err := databaseQuery.Count(&total).Error; err != nil {
|
||||
return nil, 0, errcode.ErrDB
|
||||
}
|
||||
if err := databaseQuery.Order("created_at desc").Offset((page - 1) * size).Limit(size).Find(&list).Error; err != nil {
|
||||
return nil, 0, errcode.ErrDB
|
||||
}
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
// GetOrgGasStationByIdentity 查询单个气站。
|
||||
func GetOrgGasStationByIdentity(identity string) (*OrgGasStation, error) {
|
||||
var data OrgGasStation
|
||||
if err := impl.DBService.Where("identity = ?", identity).First(&data).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errcode.ErrRecordNotFound
|
||||
}
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
return &data, nil
|
||||
}
|
||||
20
backend/api/internal/models/org_service_person.go
Normal file
20
backend/api/internal/models/org_service_person.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package models
|
||||
|
||||
import "git.apinb.com/bsm-sdk/core/database"
|
||||
|
||||
// OrgServicePerson 对应 org_service_person,表示安装维修、安检或配送服务人员。
|
||||
type OrgServicePerson struct {
|
||||
Entity
|
||||
AccountIdentity string `gorm:"column:account_identity;type:uuid;uniqueIndex" json:"account_identity"` // 关联 idn_account 主键
|
||||
GasStationIdentity string `gorm:"column:gas_station_identity;type:uuid" json:"gas_station_identity"` // 归属气站主键
|
||||
DeliveryPointIdentity string `gorm:"column:delivery_point_identity;type:uuid" json:"delivery_point_identity"` // 主归属配送点主键
|
||||
Name string `gorm:"column:name;type:varchar(64);not null" json:"name"` // 服务人员姓名
|
||||
Roles string `gorm:"column:roles;type:varchar(128);not null" json:"roles"` // 可执行角色集合
|
||||
WorkStatus string `gorm:"column:work_status;type:varchar(32);not null" json:"work_status"` // 上班与接单状态
|
||||
CredentialStatus string `gorm:"column:credential_status;type:varchar(32);not null" json:"credential_status"` // 资质状态
|
||||
}
|
||||
|
||||
func init() { database.AppendMigrate(&OrgServicePerson{}) }
|
||||
|
||||
// TableName 返回与模型、文件名一致的单数数据表名。
|
||||
func (table *OrgServicePerson) TableName() string { return "org_service_person" }
|
||||
89
backend/api/internal/models/query.go
Normal file
89
backend/api/internal/models/query.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package models
|
||||
|
||||
import "git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
|
||||
// DashboardOverview 是平台总后台的安全与组织聚合指标。
|
||||
type DashboardOverview struct {
|
||||
GasStationCount int64 `json:"gas_station_count"` // 启用气站数量
|
||||
DeliveryPointCount int64 `json:"delivery_point_count"` // 启用配送点数量
|
||||
ServicePersonCount int64 `json:"service_person_count"` // 在岗服务人员数量
|
||||
UserCount int64 `json:"user_count"` // 启用普通用户数量
|
||||
PendingSafetyCount int64 `json:"pending_safety_count"` // 待处理安全事件数量
|
||||
}
|
||||
|
||||
// GetDashboardOverview 通过独立查询返回首期仪表盘指标。
|
||||
func GetDashboardOverview() (DashboardOverview, error) {
|
||||
var overview DashboardOverview
|
||||
if err := impl.DBService.Model(&OrgGasStation{}).Where("status = ?", "enabled").Count(&overview.GasStationCount).Error; err != nil {
|
||||
return DashboardOverview{}, err
|
||||
}
|
||||
if err := impl.DBService.Model(&OrgDeliveryPoint{}).Where("status = ?", "enabled").Count(&overview.DeliveryPointCount).Error; err != nil {
|
||||
return DashboardOverview{}, err
|
||||
}
|
||||
if err := impl.DBService.Model(&OrgServicePerson{}).Where("work_status = ?", "on_duty").Count(&overview.ServicePersonCount).Error; err != nil {
|
||||
return DashboardOverview{}, err
|
||||
}
|
||||
if err := impl.DBService.Model(&IdnAccount{}).Where("account_type = ? AND status = ?", "user", "enabled").Count(&overview.UserCount).Error; err != nil {
|
||||
return DashboardOverview{}, err
|
||||
}
|
||||
if err := impl.DBService.Model(&SafEvent{}).Where("status = ?", "pending").Count(&overview.PendingSafetyCount).Error; err != nil {
|
||||
return DashboardOverview{}, err
|
||||
}
|
||||
return overview, nil
|
||||
}
|
||||
|
||||
// ListOrgDeliveryPoint 返回配送点分页列表。
|
||||
func ListOrgDeliveryPoint(page, size int) ([]OrgDeliveryPoint, int64, error) {
|
||||
var list []OrgDeliveryPoint
|
||||
var total int64
|
||||
databaseQuery := impl.DBService.Model(&OrgDeliveryPoint{})
|
||||
if err := databaseQuery.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := databaseQuery.Order("created_at desc").Offset((page - 1) * size).Limit(size).Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
// ListOrgServicePerson 返回服务人员分页列表。
|
||||
func ListOrgServicePerson(page, size int) ([]OrgServicePerson, int64, error) {
|
||||
var list []OrgServicePerson
|
||||
var total int64
|
||||
databaseQuery := impl.DBService.Model(&OrgServicePerson{})
|
||||
if err := databaseQuery.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := databaseQuery.Order("created_at desc").Offset((page - 1) * size).Limit(size).Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
// ListIdnAccount 返回普通用户分页列表,手机号脱敏由前端展示层处理。
|
||||
func ListIdnAccount(page, size int) ([]IdnAccount, int64, error) {
|
||||
var list []IdnAccount
|
||||
var total int64
|
||||
databaseQuery := impl.DBService.Model(&IdnAccount{}).Where("account_type = ?", "user")
|
||||
if err := databaseQuery.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := databaseQuery.Order("created_at desc").Offset((page - 1) * size).Limit(size).Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
// ListSafEvent 返回安全事件分页列表。
|
||||
func ListSafEvent(page, size int) ([]SafEvent, int64, error) {
|
||||
var list []SafEvent
|
||||
var total int64
|
||||
databaseQuery := impl.DBService.Model(&SafEvent{})
|
||||
if err := databaseQuery.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := databaseQuery.Order("level asc, created_at desc").Offset((page - 1) * size).Limit(size).Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return list, total, nil
|
||||
}
|
||||
18
backend/api/internal/models/saf_event.go
Normal file
18
backend/api/internal/models/saf_event.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package models
|
||||
|
||||
import "git.apinb.com/bsm-sdk/core/database"
|
||||
|
||||
// SafEvent 对应 saf_event,表示需要平台跟踪处置的安全事件。
|
||||
type SafEvent struct {
|
||||
Entity
|
||||
EventCode string `gorm:"column:event_code;type:varchar(32);uniqueIndex;not null" json:"event_code"` // 安全事件编码
|
||||
Level int `gorm:"column:level;type:integer;not null" json:"level"` // 风险等级,1 至 3 级
|
||||
Title string `gorm:"column:title;type:varchar(256);not null" json:"title"` // 事件说明
|
||||
}
|
||||
|
||||
func init() {
|
||||
database.AppendMigrate(&SafEvent{})
|
||||
}
|
||||
|
||||
// TableName 返回与模型、文件名一致的单数数据表名。
|
||||
func (table *SafEvent) TableName() string { return "saf_event" }
|
||||
36
backend/api/internal/routers/register.go
Normal file
36
backend/api/internal/routers/register.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Package routers 注册与 sample/server 一致的匿名和 JWT 受保护路由组。
|
||||
package routers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/middleware"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/dashboard"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/idn_account"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/org_delivery_point"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/org_gas_station"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/org_service_person"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/ping"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/saf_event"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Register 注册路由,请求地址格式: /{serviceKey}/v1/{domain}/{resource}。
|
||||
func Register(srvKey string, engine *gin.Engine) {
|
||||
v1Key := fmt.Sprintf("/%s/%s", srvKey, "v1")
|
||||
anonymous := engine.Group(v1Key)
|
||||
anonymous.GET("/ping/hello", ping.Hello)
|
||||
|
||||
protected := engine.Group(v1Key)
|
||||
protected.Use(middleware.JwtAuth(true))
|
||||
{
|
||||
protected.GET("/dashboard/overview", dashboard.Overview)
|
||||
gasStationGroup := protected.Group("/organization/org_gas_station")
|
||||
gasStationGroup.POST("", org_gas_station.Create)
|
||||
gasStationGroup.GET("", org_gas_station.List)
|
||||
protected.GET("/organization/org_delivery_point", org_delivery_point.List)
|
||||
protected.GET("/organization/org_service_person", org_service_person.List)
|
||||
protected.GET("/identity/idn_account", idn_account.List)
|
||||
protected.GET("/safety/saf_event", saf_event.List)
|
||||
}
|
||||
}
|
||||
5
backend/api/scripts/build.sh
Normal file
5
backend/api/scripts/build.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
mkdir -p build
|
||||
GOARCH=amd64 GOOS=linux go build -o ./build/platform-api ./cmd/main/main.go
|
||||
GOARCH=amd64 GOOS=linux go build -o ./build/platform-cli ./cmd/cli/main.go
|
||||
4
backend/api/scripts/lint.sh
Normal file
4
backend/api/scripts/lint.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
go vet ./...
|
||||
go fmt ./...
|
||||
2
backend/api/test/ping/hello.http
Normal file
2
backend/api/test/ping/hello.http
Normal file
@@ -0,0 +1,2 @@
|
||||
### 匿名健康检查
|
||||
GET http://127.0.0.1:12426/Platform/v1/ping/hello
|
||||
@@ -1,58 +0,0 @@
|
||||
// 平台核心 API 的启动入口。
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"git.apinb.com/heqiapp/platforms/backend/internal/config"
|
||||
"git.apinb.com/heqiapp/platforms/backend/internal/database"
|
||||
platformhttp "git.apinb.com/heqiapp/platforms/backend/internal/http"
|
||||
)
|
||||
|
||||
func main() {
|
||||
appConfig := config.Load()
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
|
||||
pool, err := database.Connect(context.Background(), appConfig.DatabaseURL)
|
||||
if err != nil {
|
||||
logger.Error("连接 PostgreSQL 失败", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer pool.Close()
|
||||
|
||||
if err := database.MigrateAndSeed(context.Background(), pool); err != nil {
|
||||
logger.Error("初始化数据库失败", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
server := &http.Server{
|
||||
Addr: ":" + appConfig.Port,
|
||||
Handler: platformhttp.NewRouter(pool, logger),
|
||||
ReadHeaderTimeout: 5 * time.Second,
|
||||
}
|
||||
|
||||
go func() {
|
||||
logger.Info("平台核心 API 已启动", "address", server.Addr)
|
||||
if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
logger.Error("HTTP 服务异常退出", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
stop := make(chan os.Signal, 1)
|
||||
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-stop
|
||||
|
||||
shutdownContext, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
if err := server.Shutdown(shutdownContext); err != nil {
|
||||
logger.Error("HTTP 服务停止失败", "error", err)
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
module git.apinb.com/heqiapp/platforms/backend
|
||||
|
||||
go 1.26.1
|
||||
|
||||
require (
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jackc/pgx/v5 v5.10.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
golang.org/x/text v0.29.0 // indirect
|
||||
)
|
||||
@@ -1,28 +0,0 @@
|
||||
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/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/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.10.0 h1:VhSvgU2jSli8o3AqIEOTJr7rZwAEUVo4E4XhR94Zfr0=
|
||||
github.com/jackc/pgx/v5 v5.10.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
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/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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
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=
|
||||
7
backend/go.work
Normal file
7
backend/go.work
Normal file
@@ -0,0 +1,7 @@
|
||||
go 1.26.1
|
||||
|
||||
use (
|
||||
./api
|
||||
./worker
|
||||
./iot
|
||||
)
|
||||
108
backend/go.work.sum
Normal file
108
backend/go.work.sum
Normal file
@@ -0,0 +1,108 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
git.apinb.com/bsm-sdk/core v0.2.0 h1:/e9yqpsbKBrRgMiGpS3KX2O4qDLxo5V5GpPSLNGxEKw=
|
||||
git.apinb.com/bsm-sdk/core v0.2.0/go.mod h1:E9T6Eboo/0Zb36BjkKbIgvFzq4fQ2Q8P/7y5zmYTI6Y=
|
||||
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/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
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.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||
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/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.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w=
|
||||
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
|
||||
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
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/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
|
||||
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
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/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/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
|
||||
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
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/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.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
github.com/redis/go-redis/v9 v9.19.0 h1:XPVaaPSnG6RhYf7p+rmSa9zZfeVAnWsH5h3lxthOm/k=
|
||||
github.com/redis/go-redis/v9 v9.19.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
||||
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
go.etcd.io/etcd/api/v3 v3.6.11 h1:XFGTgrJ8nak3kB4NgMG8t7NT+lEeuuvKQAqUHKVgkWQ=
|
||||
go.etcd.io/etcd/api/v3 v3.6.11/go.mod h1:HYfTh0jyh+uFgp6gMbxJteIDYY97yMuYz85Rnw6Gy9o=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.11 h1:e41mp315Yn3QMGPmEzCyLsMINgJXTY/dX8kM++1csxU=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.11/go.mod h1:DysuMe/inqRyC/1tjRR6hReH/VV9Lufs27YKSKBWWJg=
|
||||
go.etcd.io/etcd/client/v3 v3.6.11 h1:LAByD96VmmeuairkvdAcE0RZnrmGz/q3ceeWePo9bwc=
|
||||
go.etcd.io/etcd/client/v3 v3.6.11/go.mod h1:vOTDMCo+fGPEClJqcFEFSqZ+8e7WKV7AyqJjX//HR2w=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.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/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
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/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
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.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
|
||||
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
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/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
|
||||
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
||||
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
|
||||
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
|
||||
@@ -1,19 +0,0 @@
|
||||
// Package config 提供运行配置,不在代码或仓库中保存真实密钥。
|
||||
package config
|
||||
|
||||
import "os"
|
||||
|
||||
// Config 是 API 进程的最小运行配置。
|
||||
type Config struct {
|
||||
DatabaseURL string
|
||||
Port string
|
||||
}
|
||||
|
||||
// Load 读取环境变量并提供适用于本地开发的端口默认值。
|
||||
func Load() Config {
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
port = "8080"
|
||||
}
|
||||
return Config{DatabaseURL: os.Getenv("DATABASE_URL"), Port: port}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// Package database 负责 PostgreSQL 连接、迁移和演示数据初始化。
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
// Connect 建立 PostgreSQL 连接池;数据库地址必须通过环境变量提供。
|
||||
func Connect(ctx context.Context, databaseURL string) (*pgxpool.Pool, error) {
|
||||
if databaseURL == "" {
|
||||
return nil, errors.New("缺少 DATABASE_URL 环境变量")
|
||||
}
|
||||
return pgxpool.New(ctx, databaseURL)
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
// MigrateAndSeed 执行幂等结构迁移,并只在空库时创建演示数据。
|
||||
func MigrateAndSeed(ctx context.Context, pool *pgxpool.Pool) error {
|
||||
statements := []string{
|
||||
`CREATE TABLE IF NOT EXISTS idn_account (
|
||||
identity uuid PRIMARY KEY, phone varchar(32) NOT NULL UNIQUE, account_type varchar(32) NOT NULL,
|
||||
status varchar(32) NOT NULL, service_area varchar(128) NOT NULL, created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL, version integer NOT NULL DEFAULT 1
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS org_gas_station (
|
||||
identity uuid PRIMARY KEY, station_code varchar(32) NOT NULL UNIQUE, name varchar(128) NOT NULL,
|
||||
principal varchar(64) NOT NULL, service_area varchar(128) NOT NULL, status varchar(32) NOT NULL,
|
||||
created_at timestamptz NOT NULL, updated_at timestamptz NOT NULL, version integer NOT NULL DEFAULT 1
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS org_delivery_point (
|
||||
identity uuid PRIMARY KEY, delivery_code varchar(32) NOT NULL UNIQUE, gas_station_identity uuid REFERENCES org_gas_station(identity),
|
||||
name varchar(128) NOT NULL, service_area varchar(128) NOT NULL, status varchar(32) NOT NULL,
|
||||
created_at timestamptz NOT NULL, updated_at timestamptz NOT NULL, version integer NOT NULL DEFAULT 1
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS org_service_person (
|
||||
identity uuid PRIMARY KEY, account_identity uuid UNIQUE REFERENCES idn_account(identity), gas_station_identity uuid REFERENCES org_gas_station(identity),
|
||||
delivery_point_identity uuid REFERENCES org_delivery_point(identity), name varchar(64) NOT NULL, roles varchar(128) NOT NULL,
|
||||
work_status varchar(32) NOT NULL, credential_status varchar(32) NOT NULL, created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL, version integer NOT NULL DEFAULT 1
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS org_user_service_relation (
|
||||
identity uuid PRIMARY KEY, account_identity uuid NOT NULL REFERENCES idn_account(identity), gas_station_identity uuid REFERENCES org_gas_station(identity),
|
||||
delivery_point_identity uuid REFERENCES org_delivery_point(identity), source varchar(32) NOT NULL, status varchar(32) NOT NULL,
|
||||
created_at timestamptz NOT NULL, updated_at timestamptz NOT NULL, version integer NOT NULL DEFAULT 1
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS dev_device (
|
||||
identity uuid PRIMARY KEY, device_code varchar(64) NOT NULL UNIQUE, account_identity uuid REFERENCES idn_account(identity),
|
||||
online_status varchar(32) NOT NULL, valve_status varchar(32) NOT NULL, created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL, version integer NOT NULL DEFAULT 1
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS saf_event (
|
||||
identity uuid PRIMARY KEY, event_code varchar(32) NOT NULL UNIQUE, device_identity uuid REFERENCES dev_device(identity),
|
||||
level integer NOT NULL CHECK (level BETWEEN 1 AND 3), title varchar(256) NOT NULL, status varchar(32) NOT NULL,
|
||||
created_at timestamptz NOT NULL, updated_at timestamptz NOT NULL, version integer NOT NULL DEFAULT 1
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS aud_operation_log (
|
||||
identity uuid PRIMARY KEY, operator_identity uuid, action varchar(64) NOT NULL, object_type varchar(64) NOT NULL,
|
||||
object_identity uuid, detail jsonb NOT NULL DEFAULT '{}'::jsonb, created_at timestamptz NOT NULL
|
||||
)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_org_delivery_point_gas_station_identity ON org_delivery_point(gas_station_identity)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_org_service_person_gas_station_identity ON org_service_person(gas_station_identity)`,
|
||||
`CREATE INDEX IF NOT EXISTS idx_saf_event_status_level ON saf_event(status, level)`,
|
||||
`COMMENT ON TABLE idn_account IS '身份账户主表'`,
|
||||
`COMMENT ON COLUMN idn_account.identity IS '主键,应用生成的 UUID V7'`,
|
||||
`COMMENT ON TABLE org_gas_station IS '可燃气体站主表'`,
|
||||
`COMMENT ON COLUMN org_gas_station.identity IS '主键,应用生成的 UUID V7'`,
|
||||
`COMMENT ON TABLE org_delivery_point IS '配送点主表'`,
|
||||
`COMMENT ON COLUMN org_delivery_point.identity IS '主键,应用生成的 UUID V7'`,
|
||||
`COMMENT ON TABLE org_service_person IS '服务人员主表'`,
|
||||
`COMMENT ON COLUMN org_service_person.identity IS '主键,应用生成的 UUID V7'`,
|
||||
`COMMENT ON TABLE org_user_service_relation IS '用户服务关系表'`,
|
||||
`COMMENT ON COLUMN org_user_service_relation.identity IS '主键,应用生成的 UUID V7'`,
|
||||
`COMMENT ON TABLE dev_device IS '智能瓶阀设备主表'`,
|
||||
`COMMENT ON COLUMN dev_device.identity IS '主键,应用生成的 UUID V7'`,
|
||||
`COMMENT ON TABLE saf_event IS '安全事件主表'`,
|
||||
`COMMENT ON COLUMN saf_event.identity IS '主键,应用生成的 UUID V7'`,
|
||||
`COMMENT ON TABLE aud_operation_log IS '不可变操作审计日志表'`,
|
||||
`COMMENT ON COLUMN aud_operation_log.identity IS '主键,应用生成的 UUID V7'`,
|
||||
}
|
||||
|
||||
for _, statement := range statements {
|
||||
if _, err := pool.Exec(ctx, statement); err != nil {
|
||||
return fmt.Errorf("执行数据库迁移失败: %w", err)
|
||||
}
|
||||
}
|
||||
return seed(ctx, pool)
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
// seed 仅为空数据库提供可用于平台总后台演示的初始数据。
|
||||
func seed(ctx context.Context, pool *pgxpool.Pool) error {
|
||||
var count int
|
||||
if err := pool.QueryRow(ctx, `SELECT count(*) FROM org_gas_station`).Scan(&count); err != nil {
|
||||
return err
|
||||
}
|
||||
if count > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
tx, err := pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = tx.Rollback(ctx) }()
|
||||
|
||||
now := time.Now().UTC()
|
||||
stationID := newIdentity()
|
||||
deliveryID := newIdentity()
|
||||
userID := newIdentity()
|
||||
personAccountID := newIdentity()
|
||||
personID := newIdentity()
|
||||
deviceID := newIdentity()
|
||||
eventID := newIdentity()
|
||||
|
||||
queries := []struct {
|
||||
sql string
|
||||
args []any
|
||||
}{
|
||||
{`INSERT INTO org_gas_station (identity, station_code, name, principal, service_area, status, created_at, updated_at) VALUES ($1,$2,$3,$4,$5,$6,$7,$7)`, []any{stationID, "GS-1001", "浦东可燃气体站", "张敏", "浦东新区", "enabled", now}},
|
||||
{`INSERT INTO org_delivery_point (identity, delivery_code, gas_station_identity, name, service_area, status, created_at, updated_at) VALUES ($1,$2,$3,$4,$5,$6,$7,$7)`, []any{deliveryID, "DP-2001", stationID, "陆家嘴配送点", "陆家嘴片区", "enabled", now}},
|
||||
{`INSERT INTO idn_account (identity, phone, account_type, status, service_area, created_at, updated_at) VALUES ($1,$2,$3,$4,$5,$6,$6)`, []any{userID, "13800000001", "user", "enabled", "浦东新区", now}},
|
||||
{`INSERT INTO idn_account (identity, phone, account_type, status, service_area, created_at, updated_at) VALUES ($1,$2,$3,$4,$5,$6,$6)`, []any{personAccountID, "13900000001", "service_person", "enabled", "陆家嘴片区", now}},
|
||||
{`INSERT INTO org_service_person (identity, account_identity, gas_station_identity, delivery_point_identity, name, roles, work_status, credential_status, created_at, updated_at) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$9)`, []any{personID, personAccountID, stationID, deliveryID, "李强", "delivery", "on_duty", "valid", now}},
|
||||
{`INSERT INTO org_user_service_relation (identity, account_identity, gas_station_identity, delivery_point_identity, source, status, created_at, updated_at) VALUES ($1,$2,$3,$4,$5,$6,$7,$7)`, []any{newIdentity(), userID, stationID, deliveryID, "seed", "active", now}},
|
||||
{`INSERT INTO dev_device (identity, device_code, account_identity, online_status, valve_status, created_at, updated_at) VALUES ($1,$2,$3,$4,$5,$6,$6)`, []any{deviceID, "DEV-1001", userID, "online", "closed", now}},
|
||||
{`INSERT INTO saf_event (identity, event_code, device_identity, level, title, status, created_at, updated_at) VALUES ($1,$2,$3,$4,$5,$6,$7,$7)`, []any{eventID, "SAF-3001", deviceID, 1, "设备压力异常待处置", "pending", now}},
|
||||
{`INSERT INTO aud_operation_log (identity, action, object_type, object_identity, detail, created_at) VALUES ($1,$2,$3,$4,$5,$6)`, []any{newIdentity(), "seed", "org_gas_station", stationID, `{"source":"development"}`, now}},
|
||||
}
|
||||
for _, query := range queries {
|
||||
if _, err := tx.Exec(ctx, query.sql, query.args...); err != nil {
|
||||
return fmt.Errorf("写入演示数据失败: %w", err)
|
||||
}
|
||||
}
|
||||
return tx.Commit(ctx)
|
||||
}
|
||||
|
||||
// newIdentity 生成符合全局命名规范的时间有序 UUID V7 主键。
|
||||
func newIdentity() uuid.UUID {
|
||||
identity, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return identity
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
// Package http 提供平台总后台的 HTTP 路由和统一响应。
|
||||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.apinb.com/heqiapp/platforms/backend/internal/platform"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
// NewRouter 注册首期平台总后台所需的只读列表、仪表盘与气站创建接口。
|
||||
func NewRouter(pool *pgxpool.Pool, logger *slog.Logger) http.Handler {
|
||||
repository := platform.NewRepository(pool)
|
||||
mux := http.NewServeMux()
|
||||
|
||||
mux.HandleFunc("GET /healthz", func(writer http.ResponseWriter, request *http.Request) {
|
||||
writeJSON(writer, http.StatusOK, map[string]any{"status": "ok"})
|
||||
})
|
||||
mux.HandleFunc("GET /api/v1/dashboard/overview", func(writer http.ResponseWriter, request *http.Request) {
|
||||
respondRepository(writer, request, logger, func() (any, error) { return repository.DashboardOverview(request.Context()) })
|
||||
})
|
||||
mux.HandleFunc("GET /api/v1/org/gas-station", func(writer http.ResponseWriter, request *http.Request) {
|
||||
respondRepository(writer, request, logger, func() (any, error) { return repository.ListOrgGasStation(request.Context()) })
|
||||
})
|
||||
mux.HandleFunc("POST /api/v1/org/gas-station", func(writer http.ResponseWriter, request *http.Request) {
|
||||
var body struct {
|
||||
StationCode string `json:"stationCode"`
|
||||
Name string `json:"name"`
|
||||
Principal string `json:"principal"`
|
||||
ServiceArea string `json:"serviceArea"`
|
||||
}
|
||||
if err := json.NewDecoder(request.Body).Decode(&body); err != nil || body.StationCode == "" || body.Name == "" || body.Principal == "" || body.ServiceArea == "" {
|
||||
writeError(writer, http.StatusBadRequest, "参数不完整:站点编码、名称、负责人和服务区域均为必填")
|
||||
return
|
||||
}
|
||||
respondRepositoryWithStatus(writer, request, logger, http.StatusCreated, func() (any, error) {
|
||||
return repository.CreateOrgGasStation(request.Context(), body.StationCode, body.Name, body.Principal, body.ServiceArea)
|
||||
})
|
||||
})
|
||||
mux.HandleFunc("GET /api/v1/org/delivery-point", func(writer http.ResponseWriter, request *http.Request) {
|
||||
respondRepository(writer, request, logger, func() (any, error) { return repository.ListOrgDeliveryPoint(request.Context()) })
|
||||
})
|
||||
mux.HandleFunc("GET /api/v1/org/service-person", func(writer http.ResponseWriter, request *http.Request) {
|
||||
respondRepository(writer, request, logger, func() (any, error) { return repository.ListOrgServicePerson(request.Context()) })
|
||||
})
|
||||
mux.HandleFunc("GET /api/v1/idn/account", func(writer http.ResponseWriter, request *http.Request) {
|
||||
respondRepository(writer, request, logger, func() (any, error) { return repository.ListIdnAccount(request.Context()) })
|
||||
})
|
||||
mux.HandleFunc("GET /api/v1/saf/event", func(writer http.ResponseWriter, request *http.Request) {
|
||||
respondRepository(writer, request, logger, func() (any, error) { return repository.ListSafEvent(request.Context()) })
|
||||
})
|
||||
|
||||
return requestLogger(cors(mux), logger)
|
||||
}
|
||||
|
||||
func respondRepository(writer http.ResponseWriter, request *http.Request, logger *slog.Logger, query func() (any, error)) {
|
||||
respondRepositoryWithStatus(writer, request, logger, http.StatusOK, query)
|
||||
}
|
||||
|
||||
func respondRepositoryWithStatus(writer http.ResponseWriter, request *http.Request, logger *slog.Logger, status int, query func() (any, error)) {
|
||||
result, err := query()
|
||||
if err != nil {
|
||||
logger.Error("处理平台 API 请求失败", "method", request.Method, "path", request.URL.Path, "error", err)
|
||||
writeError(writer, http.StatusInternalServerError, "服务暂不可用,请稍后重试")
|
||||
return
|
||||
}
|
||||
writeJSON(writer, status, map[string]any{"data": result})
|
||||
}
|
||||
|
||||
func writeJSON(writer http.ResponseWriter, status int, data any) {
|
||||
writer.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
writer.WriteHeader(status)
|
||||
_ = json.NewEncoder(writer).Encode(data)
|
||||
}
|
||||
|
||||
func writeError(writer http.ResponseWriter, status int, message string) {
|
||||
writeJSON(writer, status, map[string]any{"error": message})
|
||||
}
|
||||
|
||||
func cors(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
||||
writer.Header().Set("Access-Control-Allow-Origin", "http://localhost:5173")
|
||||
writer.Header().Set("Access-Control-Allow-Methods", "GET,POST,OPTIONS")
|
||||
writer.Header().Set("Access-Control-Allow-Headers", "Content-Type,Idempotency-Key")
|
||||
if request.Method == http.MethodOptions {
|
||||
writer.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(writer, request)
|
||||
})
|
||||
}
|
||||
|
||||
func requestLogger(next http.Handler, logger *slog.Logger) http.Handler {
|
||||
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
||||
requestID, err := uuid.NewV7()
|
||||
if err == nil {
|
||||
writer.Header().Set("X-Request-Id", requestID.String())
|
||||
}
|
||||
startedAt := time.Now()
|
||||
next.ServeHTTP(writer, request)
|
||||
logger.Info("平台 API 请求完成", "method", request.Method, "path", request.URL.Path, "duration", time.Since(startedAt).String())
|
||||
})
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package platform
|
||||
|
||||
// IdnAccount 对应 idn_account,表示平台用户的最小账户视图。
|
||||
type IdnAccount struct {
|
||||
Identity string `json:"identity"`
|
||||
PhoneMasked string `json:"phoneMasked"`
|
||||
AccountType string `json:"accountType"`
|
||||
Status string `json:"status"`
|
||||
ServiceArea string `json:"serviceArea"`
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package platform
|
||||
|
||||
// OrgDeliveryPoint 对应 org_delivery_point,表示末端配送组织单元。
|
||||
type OrgDeliveryPoint struct {
|
||||
Identity string `json:"identity"`
|
||||
DeliveryCode string `json:"deliveryCode"`
|
||||
Name string `json:"name"`
|
||||
GasStationName string `json:"gasStationName"`
|
||||
ServiceArea string `json:"serviceArea"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// Package platform 包含平台总后台的领域模型和数据访问。
|
||||
package platform
|
||||
|
||||
import "time"
|
||||
|
||||
// OrgGasStation 对应 org_gas_station,表示可燃气体站经营主体。
|
||||
type OrgGasStation struct {
|
||||
Identity string `json:"identity"`
|
||||
StationCode string `json:"stationCode"`
|
||||
Name string `json:"name"`
|
||||
Principal string `json:"principal"`
|
||||
ServiceArea string `json:"serviceArea"`
|
||||
Status string `json:"status"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package platform
|
||||
|
||||
// OrgServicePerson 对应 org_service_person,表示具备一个或多个服务角色的人员。
|
||||
type OrgServicePerson struct {
|
||||
Identity string `json:"identity"`
|
||||
Name string `json:"name"`
|
||||
PhoneMasked string `json:"phoneMasked"`
|
||||
Roles string `json:"roles"`
|
||||
WorkStatus string `json:"workStatus"`
|
||||
Credential string `json:"credentialStatus"`
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
package platform
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
// Repository 封装平台总后台首期需要的 PostgreSQL 查询。
|
||||
type Repository struct {
|
||||
pool *pgxpool.Pool
|
||||
}
|
||||
|
||||
// NewRepository 创建平台领域数据访问实例。
|
||||
func NewRepository(pool *pgxpool.Pool) *Repository {
|
||||
return &Repository{pool: pool}
|
||||
}
|
||||
|
||||
// DashboardOverview 返回平台总后台首页所需的聚合指标。
|
||||
func (repository *Repository) DashboardOverview(ctx context.Context) (map[string]int, error) {
|
||||
queries := map[string]string{
|
||||
"gasStationCount": `SELECT count(*) FROM org_gas_station WHERE status = 'enabled'`,
|
||||
"deliveryPointCount": `SELECT count(*) FROM org_delivery_point WHERE status = 'enabled'`,
|
||||
"servicePersonCount": `SELECT count(*) FROM org_service_person WHERE work_status = 'on_duty'`,
|
||||
"userCount": `SELECT count(*) FROM idn_account WHERE account_type = 'user' AND status = 'enabled'`,
|
||||
"pendingSafetyCount": `SELECT count(*) FROM saf_event WHERE status = 'pending'`,
|
||||
}
|
||||
result := make(map[string]int, len(queries))
|
||||
for key, query := range queries {
|
||||
var count int
|
||||
if err := repository.pool.QueryRow(ctx, query).Scan(&count); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[key] = count
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ListOrgGasStation 查询可燃气体站列表。
|
||||
func (repository *Repository) ListOrgGasStation(ctx context.Context) ([]OrgGasStation, error) {
|
||||
rows, err := repository.pool.Query(ctx, `SELECT identity, station_code, name, principal, service_area, status, created_at FROM org_gas_station ORDER BY created_at DESC`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
items := make([]OrgGasStation, 0)
|
||||
for rows.Next() {
|
||||
var item OrgGasStation
|
||||
if err := rows.Scan(&item.Identity, &item.StationCode, &item.Name, &item.Principal, &item.ServiceArea, &item.Status, &item.CreatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
return items, rows.Err()
|
||||
}
|
||||
|
||||
// CreateOrgGasStation 创建可燃气体站并写入不可变审计记录。
|
||||
func (repository *Repository) CreateOrgGasStation(ctx context.Context, stationCode, name, principal, serviceArea string) (OrgGasStation, error) {
|
||||
identity, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
return OrgGasStation{}, err
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
item := OrgGasStation{Identity: identity.String(), StationCode: stationCode, Name: name, Principal: principal, ServiceArea: serviceArea, Status: "draft", CreatedAt: now}
|
||||
|
||||
tx, err := repository.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return OrgGasStation{}, err
|
||||
}
|
||||
defer func() { _ = tx.Rollback(ctx) }()
|
||||
|
||||
_, err = tx.Exec(ctx, `INSERT INTO org_gas_station (identity, station_code, name, principal, service_area, status, created_at, updated_at) VALUES ($1,$2,$3,$4,$5,$6,$7,$7)`, identity, stationCode, name, principal, serviceArea, item.Status, now)
|
||||
if err != nil {
|
||||
return OrgGasStation{}, fmt.Errorf("创建气站失败: %w", err)
|
||||
}
|
||||
_, err = tx.Exec(ctx, `INSERT INTO aud_operation_log (identity, action, object_type, object_identity, detail, created_at) VALUES ($1,$2,$3,$4,$5,$6)`, newIdentity(), "create", "org_gas_station", identity, `{"channel":"platform_admin"}`, now)
|
||||
if err != nil {
|
||||
return OrgGasStation{}, err
|
||||
}
|
||||
if err = tx.Commit(ctx); err != nil {
|
||||
return OrgGasStation{}, err
|
||||
}
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// ListOrgDeliveryPoint 查询配送点及其气站归属。
|
||||
func (repository *Repository) ListOrgDeliveryPoint(ctx context.Context) ([]OrgDeliveryPoint, error) {
|
||||
rows, err := repository.pool.Query(ctx, `SELECT d.identity, d.delivery_code, d.name, COALESCE(g.name, ''), d.service_area, d.status FROM org_delivery_point d LEFT JOIN org_gas_station g ON d.gas_station_identity = g.identity ORDER BY d.created_at DESC`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := make([]OrgDeliveryPoint, 0)
|
||||
for rows.Next() {
|
||||
var item OrgDeliveryPoint
|
||||
if err := rows.Scan(&item.Identity, &item.DeliveryCode, &item.Name, &item.GasStationName, &item.ServiceArea, &item.Status); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
return items, rows.Err()
|
||||
}
|
||||
|
||||
// ListOrgServicePerson 查询服务人员并在 API 层完成手机号脱敏。
|
||||
func (repository *Repository) ListOrgServicePerson(ctx context.Context) ([]OrgServicePerson, error) {
|
||||
rows, err := repository.pool.Query(ctx, `SELECT p.identity, p.name, a.phone, p.roles, p.work_status, p.credential_status FROM org_service_person p JOIN idn_account a ON p.account_identity = a.identity ORDER BY p.created_at DESC`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := make([]OrgServicePerson, 0)
|
||||
for rows.Next() {
|
||||
var item OrgServicePerson
|
||||
var phone string
|
||||
if err := rows.Scan(&item.Identity, &item.Name, &phone, &item.Roles, &item.WorkStatus, &item.Credential); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item.PhoneMasked = maskPhone(phone)
|
||||
items = append(items, item)
|
||||
}
|
||||
return items, rows.Err()
|
||||
}
|
||||
|
||||
// ListIdnAccount 查询用户最小必要视图,不返回完整手机号。
|
||||
func (repository *Repository) ListIdnAccount(ctx context.Context) ([]IdnAccount, error) {
|
||||
rows, err := repository.pool.Query(ctx, `SELECT identity, phone, account_type, status, service_area FROM idn_account WHERE account_type = 'user' ORDER BY created_at DESC`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := make([]IdnAccount, 0)
|
||||
for rows.Next() {
|
||||
var item IdnAccount
|
||||
var phone string
|
||||
if err := rows.Scan(&item.Identity, &phone, &item.AccountType, &item.Status, &item.ServiceArea); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item.PhoneMasked = maskPhone(phone)
|
||||
items = append(items, item)
|
||||
}
|
||||
return items, rows.Err()
|
||||
}
|
||||
|
||||
// ListSafEvent 查询安全事件列表,供平台安全运营中心使用。
|
||||
func (repository *Repository) ListSafEvent(ctx context.Context) ([]SafEvent, error) {
|
||||
rows, err := repository.pool.Query(ctx, `SELECT identity, event_code, level, title, status, created_at FROM saf_event ORDER BY level ASC, created_at DESC`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := make([]SafEvent, 0)
|
||||
for rows.Next() {
|
||||
var item SafEvent
|
||||
if err := rows.Scan(&item.Identity, &item.EventCode, &item.Level, &item.Title, &item.Status, &item.CreatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
return items, rows.Err()
|
||||
}
|
||||
|
||||
// maskPhone 按最小必要原则返回脱敏手机号。
|
||||
func maskPhone(phone string) string {
|
||||
if len(phone) < 7 {
|
||||
return "***"
|
||||
}
|
||||
return phone[:3] + "****" + phone[len(phone)-4:]
|
||||
}
|
||||
|
||||
// newIdentity 生成审计记录使用的 UUID V7。
|
||||
func newIdentity() uuid.UUID {
|
||||
identity, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return identity
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package platform
|
||||
|
||||
import "time"
|
||||
|
||||
// SafEvent 对应 saf_event,表示需要跟踪处置的安全事件。
|
||||
type SafEvent struct {
|
||||
Identity string `json:"identity"`
|
||||
EventCode string `json:"eventCode"`
|
||||
Level int `json:"level"`
|
||||
Title string `json:"title"`
|
||||
Status string `json:"status"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
3
backend/iot/README.md
Normal file
3
backend/iot/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Platform IoT
|
||||
|
||||
独立 IoT 进程预留 MQTT TLS 会话、协议适配、遥测校验与命令回执边界。首期使用 Mock 适配,不连接真实设备或 MQTT Broker。
|
||||
21
backend/iot/cmd/main/main.go
Normal file
21
backend/iot/cmd/main/main.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// IoT 进程入口;真实 MQTT TLS 适配将在设备协议和证书契约确认后接入。
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/heqiapp/platforms/backend/iot/internal/config"
|
||||
"git.apinb.com/heqiapp/platforms/backend/iot/internal/impl"
|
||||
)
|
||||
|
||||
func main() {
|
||||
config.New("PlatformIot")
|
||||
impl.NewImpl()
|
||||
printer.Info("[BSM - PlatformIot] Mock IoT adapter started; MQTT broker is not connected")
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-quit
|
||||
}
|
||||
9
backend/iot/etc/platform_iot_dev.yaml
Normal file
9
backend/iot/etc/platform_iot_dev.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
Service: platform-iot
|
||||
Port: 12428
|
||||
Databases:
|
||||
Driver: postgres
|
||||
Source:
|
||||
- host=127.0.0.1 user=postgres password=change-me dbname=agent_dev port=5432 sslmode=disable TimeZone=Asia/Shanghai
|
||||
Cache: redis://default:change-me@127.0.0.1:6379/0
|
||||
OnMicroService: false
|
||||
SecretKey: change-me-to-a-random-string
|
||||
48
backend/iot/go.mod
Normal file
48
backend/iot/go.mod
Normal file
@@ -0,0 +1,48 @@
|
||||
module git.apinb.com/heqiapp/platforms/backend/iot
|
||||
|
||||
go 1.26.1
|
||||
|
||||
require (
|
||||
git.apinb.com/bsm-sdk/core v0.2.0
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
gorm.io/gorm v1.31.1
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/pgx/v5 v5.6.0 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/oklog/ulid/v2 v2.1.1 // indirect
|
||||
github.com/redis/go-redis/v9 v9.19.0 // indirect
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.6.11 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.11 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.6.11 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.49.0 // indirect
|
||||
golang.org/x/net v0.52.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.44.0 // indirect
|
||||
golang.org/x/text v0.36.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect
|
||||
google.golang.org/grpc v1.81.1 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/driver/mysql v1.6.0 // indirect
|
||||
gorm.io/driver/postgres v1.6.0 // indirect
|
||||
)
|
||||
159
backend/iot/go.sum
Normal file
159
backend/iot/go.sum
Normal file
@@ -0,0 +1,159 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
git.apinb.com/bsm-sdk/core v0.2.0 h1:/e9yqpsbKBrRgMiGpS3KX2O4qDLxo5V5GpPSLNGxEKw=
|
||||
git.apinb.com/bsm-sdk/core v0.2.0/go.mod h1:E9T6Eboo/0Zb36BjkKbIgvFzq4fQ2Q8P/7y5zmYTI6Y=
|
||||
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/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
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/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
|
||||
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
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/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
|
||||
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||
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.19.0 h1:XPVaaPSnG6RhYf7p+rmSa9zZfeVAnWsH5h3lxthOm/k=
|
||||
github.com/redis/go-redis/v9 v9.19.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||
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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
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/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
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.etcd.io/etcd/api/v3 v3.6.11 h1:XFGTgrJ8nak3kB4NgMG8t7NT+lEeuuvKQAqUHKVgkWQ=
|
||||
go.etcd.io/etcd/api/v3 v3.6.11/go.mod h1:HYfTh0jyh+uFgp6gMbxJteIDYY97yMuYz85Rnw6Gy9o=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.11 h1:e41mp315Yn3QMGPmEzCyLsMINgJXTY/dX8kM++1csxU=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.11/go.mod h1:DysuMe/inqRyC/1tjRR6hReH/VV9Lufs27YKSKBWWJg=
|
||||
go.etcd.io/etcd/client/v3 v3.6.11 h1:LAByD96VmmeuairkvdAcE0RZnrmGz/q3ceeWePo9bwc=
|
||||
go.etcd.io/etcd/client/v3 v3.6.11/go.mod h1:vOTDMCo+fGPEClJqcFEFSqZ+8e7WKV7AyqJjX//HR2w=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
|
||||
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
|
||||
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||
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/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
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/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
|
||||
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/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=
|
||||
gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
|
||||
gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
|
||||
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
|
||||
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
||||
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
|
||||
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
|
||||
29
backend/iot/internal/config/config.go
Normal file
29
backend/iot/internal/config/config.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Package config 沿用 sample/server 的 BSM 运行配置与地址校验。
|
||||
package config
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/conf"
|
||||
)
|
||||
|
||||
// Spec 是 IoT 进程运行配置。
|
||||
var Spec SrvConfig
|
||||
|
||||
// SrvConfig 保持与 API 进程相同的 BSM 配置结构。
|
||||
type SrvConfig struct {
|
||||
conf.Base `yaml:",inline"`
|
||||
Databases *conf.DBConf `yaml:"Databases"`
|
||||
Rpc map[string]conf.RpcConf `yaml:"Rpc"`
|
||||
Apm *conf.ApmConf `yaml:"APM"`
|
||||
}
|
||||
|
||||
// New 初始化 IoT 进程配置。
|
||||
func New(srvKey string) {
|
||||
conf.New(srvKey, &Spec)
|
||||
Spec.Port = conf.CheckPort(Spec.Port)
|
||||
Spec.BindIP = conf.CheckIP(Spec.BindIP)
|
||||
Spec.Addr = net.JoinHostPort(Spec.BindIP, Spec.Port)
|
||||
conf.NotNil(Spec.Service, Spec.Cache)
|
||||
conf.PrintInfo(Spec.Addr)
|
||||
}
|
||||
25
backend/iot/internal/impl/new.go
Normal file
25
backend/iot/internal/impl/new.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// Package impl 沿用 sample/server 创建 IoT 进程所需的基础设施实例。
|
||||
package impl
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/cache/redis"
|
||||
"git.apinb.com/bsm-sdk/core/logger"
|
||||
"git.apinb.com/bsm-sdk/core/with"
|
||||
"git.apinb.com/heqiapp/platforms/backend/iot/internal/config"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
RedisService *redis.RedisClient
|
||||
DBService *gorm.DB
|
||||
MemoryService *cache.Cache
|
||||
)
|
||||
|
||||
// NewImpl 初始化 MQTT Mock 进程共用的数据库、缓存、Redis 与日志。
|
||||
func NewImpl() {
|
||||
MemoryService = with.Memory(nil)
|
||||
RedisService = with.RedisCache(config.Spec.Cache)
|
||||
DBService = with.Databases(config.Spec.Databases, nil)
|
||||
logger.New(nil)
|
||||
}
|
||||
27
backend/migrations/0001_create_org_gas_station.sql
Normal file
27
backend/migrations/0001_create_org_gas_station.sql
Normal file
@@ -0,0 +1,27 @@
|
||||
-- org_gas_station:可燃气体站主表。identity 由应用生成 UUID V7,禁止自增主键。
|
||||
CREATE TABLE IF NOT EXISTS org_gas_station (
|
||||
identity uuid PRIMARY KEY,
|
||||
station_code varchar(32) NOT NULL UNIQUE,
|
||||
name varchar(128) NOT NULL,
|
||||
principal varchar(64) NOT NULL,
|
||||
service_area varchar(128) NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
created_by_identity uuid,
|
||||
updated_by_identity uuid,
|
||||
status varchar(32) NOT NULL DEFAULT 'draft',
|
||||
version integer NOT NULL DEFAULT 1
|
||||
);
|
||||
|
||||
COMMENT ON TABLE org_gas_station IS '可燃气体站主表';
|
||||
COMMENT ON COLUMN org_gas_station.identity IS '主键,应用生成的 UUID V7';
|
||||
COMMENT ON COLUMN org_gas_station.station_code IS '气站全局唯一业务编码';
|
||||
COMMENT ON COLUMN org_gas_station.name IS '气站名称';
|
||||
COMMENT ON COLUMN org_gas_station.principal IS '气站负责人姓名';
|
||||
COMMENT ON COLUMN org_gas_station.service_area IS '气站授权服务区域';
|
||||
COMMENT ON COLUMN org_gas_station.created_at IS '记录创建时间,UTC';
|
||||
COMMENT ON COLUMN org_gas_station.updated_at IS '记录更新时间,UTC';
|
||||
COMMENT ON COLUMN org_gas_station.created_by_identity IS '创建人 identity';
|
||||
COMMENT ON COLUMN org_gas_station.updated_by_identity IS '更新人 identity';
|
||||
COMMENT ON COLUMN org_gas_station.status IS '状态:draft、enabled、frozen、archived';
|
||||
COMMENT ON COLUMN org_gas_station.version IS '乐观锁版本';
|
||||
28
backend/migrations/0002_create_saf_event.sql
Normal file
28
backend/migrations/0002_create_saf_event.sql
Normal file
@@ -0,0 +1,28 @@
|
||||
-- saf_event:安全事件主表。事件和审计记录不允许物理删除。
|
||||
CREATE TABLE IF NOT EXISTS saf_event (
|
||||
identity uuid PRIMARY KEY,
|
||||
event_code varchar(32) NOT NULL UNIQUE,
|
||||
device_identity uuid,
|
||||
level integer NOT NULL CHECK (level BETWEEN 1 AND 3),
|
||||
title varchar(256) NOT NULL,
|
||||
created_at timestamptz NOT NULL,
|
||||
updated_at timestamptz NOT NULL,
|
||||
created_by_identity uuid,
|
||||
updated_by_identity uuid,
|
||||
status varchar(32) NOT NULL DEFAULT 'pending',
|
||||
version integer NOT NULL DEFAULT 1
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_saf_event_status_level ON saf_event(status, level);
|
||||
COMMENT ON TABLE saf_event IS '安全事件主表';
|
||||
COMMENT ON COLUMN saf_event.identity IS '主键,应用生成的 UUID V7';
|
||||
COMMENT ON COLUMN saf_event.event_code IS '安全事件全局唯一业务编码';
|
||||
COMMENT ON COLUMN saf_event.device_identity IS '关联 dev_device 的 identity';
|
||||
COMMENT ON COLUMN saf_event.level IS '风险等级:1 高风险、2 中风险、3 低风险';
|
||||
COMMENT ON COLUMN saf_event.title IS '安全事件说明';
|
||||
COMMENT ON COLUMN saf_event.created_at IS '记录创建时间,UTC';
|
||||
COMMENT ON COLUMN saf_event.updated_at IS '记录更新时间,UTC';
|
||||
COMMENT ON COLUMN saf_event.created_by_identity IS '创建人 identity';
|
||||
COMMENT ON COLUMN saf_event.updated_by_identity IS '更新人 identity';
|
||||
COMMENT ON COLUMN saf_event.status IS '状态:pending、processing、closed、overdue';
|
||||
COMMENT ON COLUMN saf_event.version IS '乐观锁版本';
|
||||
@@ -0,0 +1,39 @@
|
||||
-- 首期平台组织与身份主表。所有 identity 均为应用生成的 UUID V7。
|
||||
CREATE TABLE IF NOT EXISTS idn_account (
|
||||
identity uuid PRIMARY KEY, phone varchar(32) NOT NULL UNIQUE, account_type varchar(32) NOT NULL,
|
||||
service_area varchar(128) NOT NULL, created_at timestamptz NOT NULL, updated_at timestamptz NOT NULL,
|
||||
created_by_identity uuid, updated_by_identity uuid, status varchar(32) NOT NULL DEFAULT 'enabled', version integer NOT NULL DEFAULT 1
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS org_delivery_point (
|
||||
identity uuid PRIMARY KEY, delivery_code varchar(32) NOT NULL UNIQUE, gas_station_identity uuid,
|
||||
name varchar(128) NOT NULL, service_area varchar(128) NOT NULL, created_at timestamptz NOT NULL, updated_at timestamptz NOT NULL,
|
||||
created_by_identity uuid, updated_by_identity uuid, status varchar(32) NOT NULL DEFAULT 'draft', version integer NOT NULL DEFAULT 1
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS org_service_person (
|
||||
identity uuid PRIMARY KEY, account_identity uuid UNIQUE, gas_station_identity uuid, delivery_point_identity uuid,
|
||||
name varchar(64) NOT NULL, roles varchar(128) NOT NULL, work_status varchar(32) NOT NULL, credential_status varchar(32) NOT NULL,
|
||||
created_at timestamptz NOT NULL, updated_at timestamptz NOT NULL, created_by_identity uuid, updated_by_identity uuid,
|
||||
status varchar(32) NOT NULL DEFAULT 'draft', version integer NOT NULL DEFAULT 1
|
||||
);
|
||||
COMMENT ON TABLE idn_account IS '身份账户主表';
|
||||
COMMENT ON COLUMN idn_account.identity IS '主键,应用生成的 UUID V7';
|
||||
COMMENT ON COLUMN idn_account.phone IS '手机号,敏感字段,展示时脱敏';
|
||||
COMMENT ON COLUMN idn_account.account_type IS '账户类型:user、service_person、admin';
|
||||
COMMENT ON COLUMN idn_account.service_area IS '授权服务区域';
|
||||
COMMENT ON COLUMN idn_account.status IS '状态:enabled、frozen、archived';
|
||||
COMMENT ON TABLE org_delivery_point IS '配送点主表';
|
||||
COMMENT ON COLUMN org_delivery_point.identity IS '主键,应用生成的 UUID V7';
|
||||
COMMENT ON COLUMN org_delivery_point.delivery_code IS '配送点全局唯一业务编码';
|
||||
COMMENT ON COLUMN org_delivery_point.gas_station_identity IS '归属 org_gas_station 的 identity';
|
||||
COMMENT ON COLUMN org_delivery_point.name IS '配送点名称';
|
||||
COMMENT ON COLUMN org_delivery_point.service_area IS '配送服务区域';
|
||||
COMMENT ON COLUMN org_delivery_point.status IS '状态:draft、enabled、frozen、archived';
|
||||
COMMENT ON TABLE org_service_person IS '服务人员主表';
|
||||
COMMENT ON COLUMN org_service_person.identity IS '主键,应用生成的 UUID V7';
|
||||
COMMENT ON COLUMN org_service_person.account_identity IS '关联 idn_account 的 identity';
|
||||
COMMENT ON COLUMN org_service_person.gas_station_identity IS '归属 org_gas_station 的 identity';
|
||||
COMMENT ON COLUMN org_service_person.delivery_point_identity IS '主归属 org_delivery_point 的 identity';
|
||||
COMMENT ON COLUMN org_service_person.roles IS '可执行角色集合';
|
||||
COMMENT ON COLUMN org_service_person.work_status IS '上班与接单状态';
|
||||
COMMENT ON COLUMN org_service_person.credential_status IS '资质状态';
|
||||
COMMENT ON COLUMN org_service_person.status IS '状态:draft、enabled、frozen、archived';
|
||||
5
backend/migrations/README.md
Normal file
5
backend/migrations/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# PostgreSQL 迁移
|
||||
|
||||
迁移文件名遵循 `<序号>_create_<模块前缀_单数实体>.sql`。每个主表必须以应用生成的 UUID V7 `identity` 为主键,并对表、字段、索引、约束和枚举补充中文注释。
|
||||
|
||||
当前 API 的 GORM 自动迁移用于本地开发;生产发布必须先评审并执行本目录的显式 SQL 迁移,再部署新版本服务。
|
||||
3
backend/worker/README.md
Normal file
3
backend/worker/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Platform Worker
|
||||
|
||||
独立 Worker 进程沿用 `sample/server` 的 BSM 配置与基础设施创建方式。首期只提供 Mock 事件循环,真实 Redis Streams 消费将在 Outbox、死信、幂等消费与积压监控契约确定后接入。
|
||||
21
backend/worker/cmd/main/main.go
Normal file
21
backend/worker/cmd/main/main.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// Worker 进程入口;保留独立扩缩和 Redis Streams 消费边界。
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/heqiapp/platforms/backend/worker/internal/config"
|
||||
"git.apinb.com/heqiapp/platforms/backend/worker/internal/impl"
|
||||
)
|
||||
|
||||
func main() {
|
||||
config.New("PlatformWorker")
|
||||
impl.NewImpl()
|
||||
printer.Info("[BSM - PlatformWorker] Mock worker started; Redis Streams consumer is not enabled")
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-quit
|
||||
}
|
||||
9
backend/worker/etc/platform_worker_dev.yaml
Normal file
9
backend/worker/etc/platform_worker_dev.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
Service: platform-worker
|
||||
Port: 12427
|
||||
Databases:
|
||||
Driver: postgres
|
||||
Source:
|
||||
- host=127.0.0.1 user=postgres password=change-me dbname=agent_dev port=5432 sslmode=disable TimeZone=Asia/Shanghai
|
||||
Cache: redis://default:change-me@127.0.0.1:6379/0
|
||||
OnMicroService: false
|
||||
SecretKey: change-me-to-a-random-string
|
||||
48
backend/worker/go.mod
Normal file
48
backend/worker/go.mod
Normal file
@@ -0,0 +1,48 @@
|
||||
module git.apinb.com/heqiapp/platforms/backend/worker
|
||||
|
||||
go 1.26.1
|
||||
|
||||
require (
|
||||
git.apinb.com/bsm-sdk/core v0.2.0
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
gorm.io/gorm v1.31.1
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/pgx/v5 v5.6.0 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/oklog/ulid/v2 v2.1.1 // indirect
|
||||
github.com/redis/go-redis/v9 v9.19.0 // indirect
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.6.11 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.11 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.6.11 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.49.0 // indirect
|
||||
golang.org/x/net v0.52.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.44.0 // indirect
|
||||
golang.org/x/text v0.36.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect
|
||||
google.golang.org/grpc v1.81.1 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/driver/mysql v1.6.0 // indirect
|
||||
gorm.io/driver/postgres v1.6.0 // indirect
|
||||
)
|
||||
159
backend/worker/go.sum
Normal file
159
backend/worker/go.sum
Normal file
@@ -0,0 +1,159 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
git.apinb.com/bsm-sdk/core v0.2.0 h1:/e9yqpsbKBrRgMiGpS3KX2O4qDLxo5V5GpPSLNGxEKw=
|
||||
git.apinb.com/bsm-sdk/core v0.2.0/go.mod h1:E9T6Eboo/0Zb36BjkKbIgvFzq4fQ2Q8P/7y5zmYTI6Y=
|
||||
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/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
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/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
|
||||
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
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/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
|
||||
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||
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.19.0 h1:XPVaaPSnG6RhYf7p+rmSa9zZfeVAnWsH5h3lxthOm/k=
|
||||
github.com/redis/go-redis/v9 v9.19.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||
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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
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/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
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.etcd.io/etcd/api/v3 v3.6.11 h1:XFGTgrJ8nak3kB4NgMG8t7NT+lEeuuvKQAqUHKVgkWQ=
|
||||
go.etcd.io/etcd/api/v3 v3.6.11/go.mod h1:HYfTh0jyh+uFgp6gMbxJteIDYY97yMuYz85Rnw6Gy9o=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.11 h1:e41mp315Yn3QMGPmEzCyLsMINgJXTY/dX8kM++1csxU=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.6.11/go.mod h1:DysuMe/inqRyC/1tjRR6hReH/VV9Lufs27YKSKBWWJg=
|
||||
go.etcd.io/etcd/client/v3 v3.6.11 h1:LAByD96VmmeuairkvdAcE0RZnrmGz/q3ceeWePo9bwc=
|
||||
go.etcd.io/etcd/client/v3 v3.6.11/go.mod h1:vOTDMCo+fGPEClJqcFEFSqZ+8e7WKV7AyqJjX//HR2w=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
|
||||
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
|
||||
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||
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/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
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/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
|
||||
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/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=
|
||||
gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
|
||||
gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
|
||||
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
|
||||
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
||||
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
|
||||
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
|
||||
29
backend/worker/internal/config/config.go
Normal file
29
backend/worker/internal/config/config.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Package config 沿用 sample/server 的 BSM 运行配置与地址校验。
|
||||
package config
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/conf"
|
||||
)
|
||||
|
||||
// Spec 是 Worker 运行配置。
|
||||
var Spec SrvConfig
|
||||
|
||||
// SrvConfig 保持与 API 进程相同的 BSM 配置结构。
|
||||
type SrvConfig struct {
|
||||
conf.Base `yaml:",inline"`
|
||||
Databases *conf.DBConf `yaml:"Databases"`
|
||||
Rpc map[string]conf.RpcConf `yaml:"Rpc"`
|
||||
Apm *conf.ApmConf `yaml:"APM"`
|
||||
}
|
||||
|
||||
// New 初始化 Worker 配置。
|
||||
func New(srvKey string) {
|
||||
conf.New(srvKey, &Spec)
|
||||
Spec.Port = conf.CheckPort(Spec.Port)
|
||||
Spec.BindIP = conf.CheckIP(Spec.BindIP)
|
||||
Spec.Addr = net.JoinHostPort(Spec.BindIP, Spec.Port)
|
||||
conf.NotNil(Spec.Service, Spec.Cache)
|
||||
conf.PrintInfo(Spec.Addr)
|
||||
}
|
||||
25
backend/worker/internal/impl/new.go
Normal file
25
backend/worker/internal/impl/new.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// Package impl 沿用 sample/server 创建 Worker 需要的基础设施实例。
|
||||
package impl
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/cache/redis"
|
||||
"git.apinb.com/bsm-sdk/core/logger"
|
||||
"git.apinb.com/bsm-sdk/core/with"
|
||||
"git.apinb.com/heqiapp/platforms/backend/worker/internal/config"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
RedisService *redis.RedisClient
|
||||
DBService *gorm.DB
|
||||
MemoryService *cache.Cache
|
||||
)
|
||||
|
||||
// NewImpl 初始化 Outbox 和 Mock 事件消费共用的数据库、缓存、Redis 与日志。
|
||||
func NewImpl() {
|
||||
MemoryService = with.Memory(nil)
|
||||
RedisService = with.RedisCache(config.Spec.Cache)
|
||||
DBService = with.Databases(config.Spec.Databases, nil)
|
||||
logger.New(nil)
|
||||
}
|
||||
Reference in New Issue
Block a user