first commit

This commit is contained in:
Daniel 2025-06-19 10:33:58 +08:00
commit 3e8f494cb9
224 changed files with 42083 additions and 0 deletions

5
.devcontainer/.env Normal file
View File

@ -0,0 +1,5 @@
POSTGRES_DB=ginadmin
POSTGRES_USER=postgres
POSTGRES_PASSWORD=123456
DATABASE_URL=postgres://postgres:123456@db:5432/ginadmin

13
.devcontainer/Dockerfile Normal file
View File

@ -0,0 +1,13 @@
FROM mcr.microsoft.com/devcontainers/go:1.22-bookworm
ARG APP=haibei
# Set CGO_CFLAGS to enable large file support
ENV CGO_CFLAGS "-D_LARGEFILE64_SOURCE"
RUN go install github.com/google/wire/cmd/wire@latest \
&& go install github.com/swaggo/swag/cmd/swag@latest \
&& go install github.com/gin-admin/gin-admin-cli/v10@latest \
&& chown -R vscode /go

View File

@ -0,0 +1,9 @@
{
"name": "ginadmin",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
"forwardPorts": [
8040
]
}

View File

@ -0,0 +1,42 @@
version: "3"
services:
app:
build:
context: .
dockerfile: Dockerfile
command: sleep infinity
networks:
- db
- redis
volumes:
- ../..:/workspaces:cached
env_file:
- .env
db:
image: postgres:15.3-alpine
restart: unless-stopped
ports:
- 5432:5432
networks:
- db
volumes:
- postgres-data:/var/lib/postgresql/data
env_file:
- .env
redis:
image: redis:latest
restart: unless-stopped
ports:
- 6379:6379
networks:
- redis
volumes:
postgres-data:
networks:
db:
redis:

32
.gitignore vendored Normal file
View File

@ -0,0 +1,32 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
*.DS_Store
/haibei
/haibei_linux_amd64
/haibei.lock
/release
/data
/internal/test/data
tmp
/vendor
/configs/gen_rbac_policy.csv
/configs/gen_rbac_policy.csv.bak
/configs/rbac_policy.csv.bak
/test/data
/internal/swagger/v3/.openapi-generator
/internal/swagger/v3/.openapi-generator-ignore
# IDE configs
.idea
.vscode

28
Dockerfile Normal file
View File

@ -0,0 +1,28 @@
FROM golang:alpine as builder
ARG APP=haibei
ARG VERSION=v1.0.0
ARG RELEASE_TAG=$(VERSION)
# Install the required packages
RUN apk add --no-cache gcc musl-dev sqlite-dev
# Set CGO_CFLAGS to enable large file support
ENV CGO_CFLAGS "-D_LARGEFILE64_SOURCE"
ENV GOPROXY="https://goproxy.cn"
WORKDIR /go/src/${APP}
COPY . .
# Build the application
RUN go build -ldflags "-w -s -X main.VERSION=${RELEASE_TAG}" -o ./${APP} .
FROM alpine
ARG APP=haibei
WORKDIR /go/src/${APP}
COPY --from=builder /go/src/${APP}/${APP} /usr/bin/
# COPY --from=builder /go/src/${APP}/configs /usr/bin/configs
# COPY --from=builder /go/src/${APP}/dist /usr/bin/dist
ENTRYPOINT ["haibei", "start", "-d", "/usr/bin/configs", "-c", "prod", "-s", "/usr/bin/dist"]
EXPOSE 8040

51
Makefile Normal file
View File

@ -0,0 +1,51 @@
.PHONY: start build
NOW = $(shell date -u '+%Y%m%d%I%M%S')
RELEASE_VERSION = v1.0.0
APP = haibei
SERVER_BIN = ${APP}
GIT_COUNT = $(shell git rev-list --all --count)
GIT_HASH = $(shell git rev-parse --short HEAD)
RELEASE_TAG = $(RELEASE_VERSION).$(GIT_COUNT).$(GIT_HASH)
CONFIG_DIR = ./configs
CONFIG_FILES = dev
STATIC_DIR = ./build/dist
START_ARGS = -d $(CONFIG_DIR) -c $(CONFIG_FILES) -s $(STATIC_DIR)
all: start
start:
@go run -ldflags "-X main.VERSION=$(RELEASE_TAG)" main.go start $(START_ARGS)
build:
@go build -ldflags "-w -s -X main.VERSION=$(RELEASE_TAG)" -o $(SERVER_BIN)
build-linux:
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC="zig cc -target x86_64-linux-musl" CXX="zig c++ -target x86_64-linux-musl" CGO_CFLAGS="-D_LARGEFILE64_SOURCE" go build -ldflags "-w -s -X main.VERSION=$(RELEASE_TAG)" -o $(SERVER_BIN)_linux_amd64
# go install github.com/google/wire/cmd/wire@latest
wire:
@wire gen ./internal/wirex
# go install github.com/swaggo/swag/cmd/swag@latest
swagger:
@swag init --parseDependency --generalInfo ./main.go --output ./internal/swagger
# https://github.com/OpenAPITools/openapi-generator
openapi:
docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate -i /local/internal/swagger/swagger.yaml -g openapi -o /local/internal/swagger/v3
clean:
rm -rf data $(SERVER_BIN)
serve: build
./$(SERVER_BIN) start $(START_ARGS)
serve-d: build
./$(SERVER_BIN) start $(START_ARGS) -d
stop:
./$(SERVER_BIN) stop

28
README.md Normal file
View File

@ -0,0 +1,28 @@
# haibei
> 中海小程序
## Quick Start
```bash
make start
```
## Build
```bash
make build
```
## Generate wire inject files
```bash
make wire
```
## Generate swagger documents
```bash
make swagger
```

250
README_EN.md Normal file
View File

@ -0,0 +1,250 @@
# [Gin](https://github.com/gin-gonic/gin)-Admin
> A lightweight, flexible, elegant and full-featured RBAC scaffolding based on Golang + Gin + GORM 2.0 + Casbin 2.0 + Wire DI.
English | [中文](README.md)
[![LICENSE](https://img.shields.io/github/license/LyricTian/gin-admin.svg)](https://github.com/LyricTian/gin-admin/blob/main/LICENSE)
[![Language](https://img.shields.io/badge/Language-Go-blue.svg)](https://golang.org/)
[![Go Report Card](https://goreportcard.com/badge/github.com/LyricTian/gin-admin)](https://goreportcard.com/report/github.com/LyricTian/gin-admin)
[![GitHub release](https://img.shields.io/github/tag/LyricTian/gin-admin.svg?label=release)](https://github.com/LyricTian/gin-admin/releases)
[![GitHub release date](https://img.shields.io/github/release-date/LyricTian/gin-admin.svg)](https://github.com/LyricTian/gin-admin/releases)
[![GoDoc](https://img.shields.io/badge/Godoc-reference-blue.svg)](https://godoc.org/github.com/LyricTian/gin-admin)
## Features
- :scroll: Elegant implementation of `RESTful API`, using interface-based programming paradigm to make your API design more professional and standardized
- :house: Adopts clear and concise modular architecture, making code structure clear at a glance, maintenance and upgrades more effortless
- :rocket: Based on high-performance `GIN` framework, integrating rich and practical middleware (authentication, CORS, logging, rate limiting, tracing, permission control, fault tolerance, compression, etc.), helping you quickly build enterprise-level applications
- :closed_lock_with_key: Integrates industry-leading `Casbin` permission framework, flexible and precise RBAC permission control makes security protection rock solid
- :page_facing_up: Based on powerful `GORM 2.0` ORM framework, elegantly handles database operations, greatly improving development efficiency
- :electric_plug: Innovatively adopts `WIRE` dependency injection, revolutionarily simplifies module dependency relationships, making code more elegant and decoupled
- :memo: Based on high-performance `Zap` logging framework, coupled with Context tracing, making system running status clear and transparent, problem troubleshooting nowhere to hide
- :key: Integrates time-tested `JWT` authentication mechanism, making user identity verification more secure and reliable
- :microscope: Automatically integrates `Swagger` API documentation, real-time API documentation updates, making development and debugging easier - [Online Demo](https://demo.ginadmin.top/swagger/index.html)
- :wrench: Complete unit testing system, based on `testify` framework to ensure system quality, leaving no place for bugs to hide
- :100: Adopts stateless design, supports horizontal scaling, paired with Redis to implement dynamic permission management, letting your system easily handle high concurrency
- :hammer: Developer's blessing! Powerful scaffolding tool [gin-admin-cli](https://github.com/gin-admin/gin-admin-cli), making your development work twice as efficient
![demo](./demo.png)
![swagger](./swagger.png)
## Frontend Projects
- [Frontend project based on Ant Design React](https://github.com/gin-admin/gin-admin-frontend)
- [Frontend project based on Vue.js](https://github.com/gin-admin/gin-admin-vue)
## Install Dependencies
- [Go](https://golang.org/) 1.19+
- [Wire](github.com/google/wire) `go install github.com/google/wire/cmd/wire@latest`
- [Swag](github.com/swaggo/swag) `go install github.com/swaggo/swag/cmd/swag@latest`
- [GIN-ADMIN-CLI](https://github.com/gin-admin/gin-admin-cli) `go install github.com/gin-admin/gin-admin-cli/v10@latest`
## Quick Start
### Create a New Project
> You can view detailed command instructions via `gin-admin-cli help new`
```bash
gin-admin-cli new -d ~/go/src --name testapp --desc 'A test API service based on golang.' --pkg 'github.com/xxx/testapp' --git-url https://gitee.com/lyric/gin-admin.git
```
### Start the Service
> You can switch to Chinese menu by changing `MenuFile = "menu_cn.json"` in the `configs/dev/server.toml` configuration file
```bash
cd ~/go/src/testapp
make start
# or
go run main.go start
```
### Compile the Service
```bash
make build
# or
go build -ldflags "-w -s -X main.VERSION=v1.0.0" -o testapp
```
### Generate Docker Image
```bash
docker build -f ./Dockerfile -t testapp:v1.0.0 .
```
### Generate Codes
> You can view detailed command instructions via `gin-admin-cli help gen`
#### Prepare Configuration File `dictionary.yaml`
```yaml
- name: Dictionary
comment: Dictionary management
disable_pagination: true
fill_gorm_commit: true
fill_router_prefix: true
tpl_type: "tree"
fields:
- name: Code
type: string
comment: Code of dictionary (unique for same parent)
gorm_tag: "size:32;"
form:
binding_tag: "required,max=32"
- name: Name
type: string
comment: Display name of dictionary
gorm_tag: "size:128;index"
query:
name: LikeName
in_query: true
form_tag: name
op: LIKE
form:
binding_tag: "required,max=128"
- name: Description
type: string
comment: Details about dictionary
gorm_tag: "size:1024"
form: {}
- name: Sequence
type: int
comment: Sequence for sorting
gorm_tag: "index;"
order: DESC
form: {}
- name: Status
type: string
comment: Status of dictionary (disabled, enabled)
gorm_tag: "size:20;index"
query: {}
form:
binding_tag: "required,oneof=disabled enabled"
```
```bash
gin-admin-cli gen -d . -m SYS -c dictionary.yaml
```
### Delete Function Module
> You can view detailed command instructions via `gin-admin-cli help remove`
```bash
gin-admin-cli rm -d . -m CMS --structs Article
```
### Generate Swagger Documentation
> You can generate Swagger documentation automatically via [Swag](github.com/swaggo/swag)
```bash
make swagger
# or
swag init --parseDependency --generalInfo ./main.go --output ./internal/swagger
```
### Generate Dependency Injection Code
> Dependency injection itself is used to solve the initial process of layer dependency among various modules, and you can generate dependency injection code automatically via [Wire](github.com/google/wire) to simplify the dependency injection process.
```bash
make wire
# or
wire gen ./internal/wirex
```
## Project Structure Overview
```text
├── cmd (Command line definition directory)
│ ├── start.go (Start command)
│ ├── stop.go (Stop command)
│ └── version.go (Version command)
├── configs
│ ├── dev
│ │ ├── logging.toml (Logging configuration file)
│ │ ├── middleware.toml (Middleware configuration file)
│ │ └── server.toml (Service configuration file)
│ ├── menu.json (Initialization menu file)
│ └── rbac_model.conf (Casbin RBAC model configuration file)
├── internal
│ ├── bootstrap (Initialization directory)
│ │ ├── bootstrap.go (Initialization)
│ │ ├── http.go (HTTP service)
│ │ └── logger.go (Logging service)
│ ├── config (Configuration file directory)
│ │ ├── config.go (Configuration file initialization)
│ │ ├── consts.go (Constant definition)
│ │ ├── middleware.go (Middleware configuration)
│ │ └── parse.go (Configuration file parsing)
│ ├── mods
│ │ ├── rbac (RBAC module)
│ │ │ ├── api (API layer)
│ │ │ ├── biz (Business logic layer)
│ │ │ ├── dal (Data access layer)
│ │ │ ├── schema (Data model layer)
│ │ │ ├── casbin.go (Casbin initialization)
│ │ │ ├── main.go (RBAC module entry)
│ │ │ └── wire.go (RBAC dependency injection initialization)
│ │ └── mods.go
│ ├── utility
│ │ └── prom
│ │ └── prom.go (Prometheus monitoring, used for integration with prometheus)
│ └── wirex (Dependency injection directory, contains the definition and initialization of dependency groups)
│ ├── injector.go
│ ├── wire.go
│ └── wire_gen.go
├── pkg (Public package directory)
│ ├── cachex (Cache package)
│ ├── crypto (Encryption package)
│ │ ├── aes (AES encryption)
│ │ ├── hash (Hash encryption)
│ │ └── rand (Random number)
│ ├── encoding (Encoding package)
│ │ ├── json (JSON encoding)
│ │ ├── toml (TOML encoding)
│ │ └── yaml (YAML encoding)
│ ├── errors (Error handling package)
│ ├── gormx (Gorm extension package)
│ ├── jwtx (JWT package)
│ ├── logging (Logging package)
│ ├── mail (Mail package)
│ ├── middleware (Middleware package)
│ ├── oss (Object storage package)
│ ├── promx (Prometheus package)
│ └── util (Utility package)
├── test (Unit test directory)
│ ├── menu_test.go
│ ├── role_test.go
│ ├── test.go
│ └── user_test.go
├── Dockerfile
├── Makefile
├── README.md
├── go.mod
├── go.sum
└── main.go (Entry file)
```
## License
Copyright (c) 2023 Lyric
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

105
cmd/start.go Normal file
View File

@ -0,0 +1,105 @@
package cmd
import (
"context"
"fmt"
"github.guxuan/haibei/internal/config"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/urfave/cli/v2"
"github.guxuan/haibei/internal/bootstrap"
)
// The function defines a CLI command to start a server with various flags and options, including the
// ability to run as a daemon.
func StartCmd() *cli.Command {
return &cli.Command{
Name: "start",
Usage: "Start server",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "workdir",
Aliases: []string{"d"},
Usage: "Working directory",
DefaultText: "configs",
Value: "configs",
},
&cli.StringFlag{
Name: "config",
Aliases: []string{"c"},
Usage: "Runtime configuration files or directory (relative to workdir, multiple separated by commas)",
DefaultText: "dev",
Value: "dev",
},
&cli.StringFlag{
Name: "static",
Aliases: []string{"s"},
Usage: "Static files directory",
},
&cli.BoolFlag{
Name: "daemon",
Usage: "Run as a daemon",
},
},
Action: func(c *cli.Context) error {
workDir := c.String("workdir")
staticDir := c.String("static")
configs := c.String("config")
if c.Bool("daemon") {
bin, err := filepath.Abs(os.Args[0])
if err != nil {
fmt.Printf("failed to get absolute path for command: %s \n", err.Error())
return err
}
args := []string{"start"}
args = append(args, "-d", workDir)
args = append(args, "-c", configs)
args = append(args, "-s", staticDir)
fmt.Printf("execute command: %s %s \n", bin, strings.Join(args, " "))
command := exec.Command(bin, args...)
// Redirect stdout and stderr to log file
stdLogFile := fmt.Sprintf("%s.log", c.App.Name)
file, err := os.OpenFile(stdLogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
fmt.Printf("failed to open log file: %s \n", err.Error())
return err
}
defer file.Close()
command.Stdout = file
command.Stderr = file
err = command.Start()
if err != nil {
fmt.Printf("failed to start daemon thread: %s \n", err.Error())
return err
}
// Don't wait for the command to finish
// The main process will exit, allowing the daemon to run independently
fmt.Printf("Service %s daemon thread started successfully\n", config.C.General.AppName)
pid := command.Process.Pid
_ = os.WriteFile(fmt.Sprintf("%s.lock", c.App.Name), []byte(fmt.Sprintf("%d", pid)), 0666)
fmt.Printf("service %s daemon thread started with pid %d \n", config.C.General.AppName, pid)
os.Exit(0)
}
err := bootstrap.Run(context.Background(), bootstrap.RunConfig{
WorkDir: workDir,
Configs: configs,
StaticDir: staticDir,
})
if err != nil {
panic(err)
}
return nil
},
}
}

40
cmd/stop.go Normal file
View File

@ -0,0 +1,40 @@
package cmd
import (
"fmt"
"os"
"os/exec"
"github.com/urfave/cli/v2"
)
// The function defines a CLI command to stop a server by reading a lock file, killing the process with
// the corresponding PID, and removing the lock file.
func StopCmd() *cli.Command {
return &cli.Command{
Name: "stop",
Usage: "stop server",
Action: func(c *cli.Context) error {
appName := c.App.Name
lockFile := fmt.Sprintf("%s.lock", appName)
pid, err := os.ReadFile(lockFile)
if err != nil {
return err
}
command := exec.Command("kill", string(pid))
err = command.Start()
if err != nil {
return err
}
err = os.Remove(lockFile)
if err != nil {
return fmt.Errorf("can't remove %s.lock. %s", appName, err.Error())
}
fmt.Printf("service %s stopped \n", appName)
return nil
},
}
}

19
cmd/version.go Normal file
View File

@ -0,0 +1,19 @@
package cmd
import (
"fmt"
"github.com/urfave/cli/v2"
)
// This function creates a CLI command that prints the version number.
func VersionCmd(v string) *cli.Command {
return &cli.Command{
Name: "version",
Usage: "Show version",
Action: func(_ *cli.Context) error {
fmt.Println(v)
return nil
},
}
}

26
configs/dev/logging.toml Normal file
View File

@ -0,0 +1,26 @@
[Logger]
Debug = true
Level = "debug" # debug/info/warn/error/dpanic/panic/fatal
CallerSkip = 1
[Logger.File]
Enable = false
Path = "./haibei.log"
MaxBackups = 20 # Files
MaxSize = 64 # MB
[[Logger.Hooks]]
Enable = true
Level = "info"
Type = "gorm" # gorm
MaxBuffer = 1024
MaxThread = 2
[Logger.Hooks.Options]
Debug = "false"
DBType = "mysql" # sqlite3/mysql/postgres
DSN = "haibei:haibei@tcp(115.239.217.220:3306)/haibei?charset=utf8mb4&parseTime=True&loc=Local"
MaxOpenConns = "16"
MaxIdleConns = "4"
MaxLifetime = "86400"
MaxIdleTime = "7200"

View File

@ -0,0 +1,75 @@
[Middleware]
[Middleware.Recovery]
Skip = 3
[Middleware.CORS]
Enable = true
AllowOrigins = ["*"]
AllowMethods = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]
AllowHeaders = ["*"]
MaxAge = 86400
AllowWildcard = true
AllowWebSockets = true
AllowFiles = true
[Middleware.Trace]
RequestHeaderKey = "X-Request-Id"
ResponseTraceKey = "X-Trace-Id"
[Middleware.Logger]
MaxOutputRequestBodyLen = 4096 # bytes
MaxOutputResponseBodyLen = 4096 # bytes
[Middleware.CopyBody]
MaxContentLen = 134217728 # 128MB
[Middleware.Auth]
Disable = false
SkippedPathPrefixes = ["/api/v1/captcha/", "/api/v1/login","/api/v1/apps/login"]
SigningMethod = "HS512" # HS256/HS384/HS512
SigningKey = "XnEsT0S@" # Secret key
OldSigningKey = "" # Old secret key (For change secret key)
Expired = 86400 # seconds
[Middleware.Auth.Store]
Type = "badger" # memory/badger/redis
Delimiter = ":"
[Middleware.Auth.Store.Memory]
CleanupInterval = 60 # seconds
[Middleware.Auth.Store.Badger]
Path = "data/auth"
[Middleware.Auth.Store.Redis]
Addr = "115.239.217.220:6379" # If empty, then use the same configuration as Storage.Cache.Redis
Username = ""
Password = "123456"
DB = 2
[Middleware.RateLimiter]
Enable = false
Period = 10 # seconds
MaxRequestsPerIP = 1000
MaxRequestsPerUser = 500
[Middleware.RateLimiter.Store]
Type = "redis" # memory/redis
[Middleware.RateLimiter.Store.Memory]
Expiration = 3600
CleanupInterval = 60
[Middleware.RateLimiter.Store.Redis]
Addr = "115.239.217.220:6379" # If empty, then use the same configuration as Storage.Cache.Redis
Username = ""
Password = "123456"
DB = 10
[Middleware.Casbin]
Disable = true
SkippedPathPrefixes = ["/api/v1/captcha/", "/api/v1/login", "/api/v1/current/"]
LoadThread = 2
AutoLoadInterval = 3 # seconds
ModelFile = "rbac_model.conf"
GenPolicyFile = "gen_rbac_policy.csv"

85
configs/dev/server.toml Normal file
View File

@ -0,0 +1,85 @@
[General]
AppName = "haibei"
Version = "v10.1.0"
Debug = true
PprofAddr = "" # Pprof monitor address, "localhost:6060"
DisableSwagger = false
DisablePrintConfig = false
DefaultLoginPwd = "6351623c8cef86fefabfa7da046fc619" # MD5("abc-123")
MenuFile = "menu_cn.json" # Or use "menu_cn.json"
DenyOperateMenu = false
[General.HTTP]
Addr = ":8070"
ShutdownTimeout = 10
ReadTimeout = 60
WriteTimeout = 60
IdleTimeout = 10
CertFile = ""
KeyFile = ""
[General.Root] # Super Administrator Account
ID = "root"
Username = "admin"
Password = "6351623c8cef86fefabfa7da046fc619" # MD5("abc-123")
Name = "Admin"
[Storage]
[Storage.Cache]
Type = "redis" # memory/badger/redis
Delimiter = ":"
[Storage.Cache.Memory]
CleanupInterval = 60
[Storage.Cache.Badger]
Path = "data/cache"
[Storage.Cache.Redis]
Addr = "115.239.217.220:6379"
Username = ""
Password = "123456"
DB = 0
[Storage.DB]
Debug = true
Type = "mysql" # sqlite3/mysql/postgres
# SQLite3 DSN
#DSN = "data/haibei.db"
# MySQL DSN
DSN = "haibei:haibei@tcp(115.239.217.220:3306)/haibei?charset=utf8mb4&parseTime=True&loc=Local"
# PostgreSQL DSN
# DSN = "host=db user=postgres password=123456 dbname=haibei port=5432 sslmode=disable TimeZone=Asia/Shanghai"
MaxLifetime = 86400
MaxIdleTime = 3600
MaxOpenConns = 100
MaxIdleConns = 50
TablePrefix = ""
AutoMigrate = true
[Util]
[Util.Captcha]
Length = 4
Width = 400
Height = 160
CacheType = "memory" # memory/redis
[Util.Captcha.Redis]
Addr = "115.239.217.220:6379" # If empty, then use the same configuration as Storage.Cache.Redis
Username = ""
Password = "123456"
DB = 1
KeyPrefix = "captcha:"
[Util.Prometheus]
Enable = false
Port = 9100
BasicUsername = "admin"
BasicPassword = "admin"
LogApis = [] # Log APIs, e.g. ["/api/v1/users"]
LogMethods = [] # Log HTTP methods, e.g. ["GET"]
DefaultCollect = true
[Dictionary]
UserCacheExp = 4 # hours
[FileConfig]
UploadDir = "./uploads"
StaticPrefix = "/static"

240
configs/menu.json Normal file
View File

@ -0,0 +1,240 @@
[
{
"code": "home",
"name": "Home",
"sequence": 90,
"type": "page",
"path": "/home",
"status": "enabled"
},
{
"code": "system",
"name": "System",
"sequence": 10,
"type": "page",
"path": "/system",
"status": "enabled",
"children": [
{
"code": "menu",
"name": "Menu",
"sequence": 90,
"type": "page",
"path": "/system/menu",
"status": "enabled",
"children": [
{
"code": "add",
"name": "Add",
"sequence": 9,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "POST",
"path": "/api/v1/menus"
}
]
},
{
"code": "edit",
"name": "Edit",
"sequence": 8,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "PUT",
"path": "/api/v1/menus/{id}"
}
]
},
{
"code": "delete",
"name": "Delete",
"sequence": 7,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "DELETE",
"path": "/api/v1/menus/{id}"
}
]
},
{
"code": "search",
"name": "Search",
"sequence": 6,
"type": "button",
"status": "enabled"
}
],
"resources": [
{
"method": "GET",
"path": "/api/v1/menus"
},
{
"method": "GET",
"path": "/api/v1/menus/{id}"
}
]
},
{
"code": "role",
"name": "Role",
"sequence": 80,
"type": "page",
"path": "/system/role",
"status": "enabled",
"children": [
{
"code": "add",
"name": "Add",
"sequence": 9,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "POST",
"path": "/api/v1/roles"
}
]
},
{
"code": "edit",
"name": "Edit",
"sequence": 8,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "PUT",
"path": "/api/v1/roles/{id}"
}
]
},
{
"code": "delete",
"name": "Delete",
"sequence": 7,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "DELETE",
"path": "/api/v1/roles/{id}"
}
]
},
{
"code": "search",
"name": "Search",
"sequence": 6,
"type": "button",
"status": "enabled"
}
],
"resources": [
{
"method": "GET",
"path": "/api/v1/menus"
},
{
"method": "GET",
"path": "/api/v1/roles"
},
{
"method": "GET",
"path": "/api/v1/roles/{id}"
}
]
},
{
"code": "user",
"name": "User",
"sequence": 70,
"type": "page",
"path": "/system/user",
"status": "enabled",
"children": [
{
"code": "add",
"name": "Add",
"sequence": 9,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "POST",
"path": "/api/v1/users"
}
]
},
{
"code": "edit",
"name": "Edit",
"sequence": 8,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "PUT",
"path": "/api/v1/users/{id}"
}
]
},
{
"code": "delete",
"name": "Delete",
"sequence": 7,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "DELETE",
"path": "/api/v1/users/{id}"
}
]
},
{
"code": "search",
"name": "Search",
"sequence": 6,
"type": "button",
"status": "enabled"
}
],
"resources": [
{
"method": "GET",
"path": "/api/v1/roles"
},
{
"method": "GET",
"path": "/api/v1/users"
},
{
"method": "GET",
"path": "/api/v1/users/{id}"
}
]
},
{
"code": "logger",
"name": "Logger",
"sequence": 10,
"type": "page",
"path": "/system/logger",
"status": "enabled",
"resources": [
{
"method": "GET",
"path": "/api/v1/loggers"
}
]
}
]
}
]

240
configs/menu_cn.json Normal file
View File

@ -0,0 +1,240 @@
[
{
"code": "home",
"name": "首页",
"sequence": 90,
"type": "page",
"path": "/home",
"status": "enabled"
},
{
"code": "system",
"name": "系统管理",
"sequence": 10,
"type": "page",
"path": "/system",
"status": "enabled",
"children": [
{
"code": "menu",
"name": "菜单管理",
"sequence": 90,
"type": "page",
"path": "/system/menu",
"status": "enabled",
"children": [
{
"code": "add",
"name": "增加",
"sequence": 9,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "POST",
"path": "/api/v1/menus"
}
]
},
{
"code": "edit",
"name": "编辑",
"sequence": 8,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "PUT",
"path": "/api/v1/menus/{id}"
}
]
},
{
"code": "delete",
"name": "删除",
"sequence": 7,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "DELETE",
"path": "/api/v1/menus/{id}"
}
]
},
{
"code": "search",
"name": "查询",
"sequence": 6,
"type": "button",
"status": "enabled"
}
],
"resources": [
{
"method": "GET",
"path": "/api/v1/menus"
},
{
"method": "GET",
"path": "/api/v1/menus/{id}"
}
]
},
{
"code": "role",
"name": "角色管理",
"sequence": 80,
"type": "page",
"path": "/system/role",
"status": "enabled",
"children": [
{
"code": "add",
"name": "增加",
"sequence": 9,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "POST",
"path": "/api/v1/roles"
}
]
},
{
"code": "edit",
"name": "编辑",
"sequence": 8,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "PUT",
"path": "/api/v1/roles/{id}"
}
]
},
{
"code": "delete",
"name": "删除",
"sequence": 7,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "DELETE",
"path": "/api/v1/roles/{id}"
}
]
},
{
"code": "search",
"name": "查询",
"sequence": 6,
"type": "button",
"status": "enabled"
}
],
"resources": [
{
"method": "GET",
"path": "/api/v1/menus"
},
{
"method": "GET",
"path": "/api/v1/roles"
},
{
"method": "GET",
"path": "/api/v1/roles/{id}"
}
]
},
{
"code": "user",
"name": "用户管理",
"sequence": 70,
"type": "page",
"path": "/system/user",
"status": "enabled",
"children": [
{
"code": "add",
"name": "增加",
"sequence": 9,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "POST",
"path": "/api/v1/users"
}
]
},
{
"code": "edit",
"name": "编辑",
"sequence": 8,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "PUT",
"path": "/api/v1/users/{id}"
}
]
},
{
"code": "delete",
"name": "删除",
"sequence": 7,
"type": "button",
"status": "enabled",
"resources": [
{
"method": "DELETE",
"path": "/api/v1/users/{id}"
}
]
},
{
"code": "search",
"name": "查询",
"sequence": 6,
"type": "button",
"status": "enabled"
}
],
"resources": [
{
"method": "GET",
"path": "/api/v1/roles"
},
{
"method": "GET",
"path": "/api/v1/users"
},
{
"method": "GET",
"path": "/api/v1/users/{id}"
}
]
},
{
"code": "logger",
"name": "日志查询",
"sequence": 10,
"type": "page",
"path": "/system/logger",
"status": "enabled",
"resources": [
{
"method": "GET",
"path": "/api/v1/loggers"
}
]
}
]
}
]

14
configs/rbac_model.conf Normal file
View File

@ -0,0 +1,14 @@
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow)) # Passes auth if any of the policies allows
[role_definition]
g = _, _
[matchers]
m = g(r.sub, p.sub) && r.sub == p.sub && (keyMatch2(r.obj, p.obj) || keyMatch3(r.obj, p.obj)) && r.act == p.act

138
go.mod Normal file
View File

@ -0,0 +1,138 @@
module github.guxuan/haibei
go 1.19
require (
github.com/BurntSushi/toml v1.2.1
github.com/LyricTian/captcha v1.2.0
github.com/aws/aws-sdk-go v1.44.300
github.com/casbin/casbin/v2 v2.68.0
github.com/creasty/defaults v1.7.0
github.com/dgraph-io/badger/v3 v3.2103.5
github.com/gavv/httpexpect/v2 v2.15.0
github.com/gin-contrib/cors v1.4.0
github.com/gin-gonic/gin v1.9.0
github.com/go-playground/validator/v10 v10.12.0
github.com/go-redis/redis/v8 v8.11.5
github.com/go-redis/redis_rate/v9 v9.1.2
github.com/go-sql-driver/mysql v1.7.0
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.3.0
github.com/google/wire v0.5.0
github.com/json-iterator/go v1.1.12
github.com/minio/minio-go/v7 v7.0.51
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pelletier/go-toml v1.9.5
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.14.0
github.com/redis/go-redis/v9 v9.0.4
github.com/rs/xid v1.4.0
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/spf13/cast v1.5.1
github.com/stretchr/testify v1.8.4
github.com/swaggo/files v1.0.1
github.com/swaggo/gin-swagger v1.6.0
github.com/swaggo/swag v1.16.2
github.com/urfave/cli/v2 v2.25.1
go.uber.org/zap v1.24.0
golang.org/x/crypto v0.8.0
golang.org/x/time v0.3.0
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/mysql v1.4.7
gorm.io/driver/postgres v1.5.0
gorm.io/driver/sqlite v1.4.4
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11
gorm.io/plugin/dbresolver v1.4.1
gorm.io/plugin/soft_delete v1.2.1
)
require (
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/ajg/form v1.5.1 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bytedance/sonic v1.8.7 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/spec v0.20.8 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/glog v1.1.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/flatbuffers v23.3.3+incompatible // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/imkira/go-interpol v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.3.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.16.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/leodido/go-urn v1.2.3 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mattn/go-sqlite3 v1.14.16 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sanity-io/litter v1.5.5 // indirect
github.com/sergi/go-diff v1.0.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.34.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect
github.com/yudai/gojsondiff v1.0.0 // indirect
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
go.opencensus.io v0.24.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/tools v0.8.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
moul.io/http2curl/v2 v2.3.0 // indirect
)

603
go.sum Normal file
View File

@ -0,0 +1,603 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/LyricTian/captcha v1.2.0 h1:SXmXj9B1KHBTsVv9rXVVTsKdgNlHrSeb4Memlw+wks4=
github.com/LyricTian/captcha v1.2.0/go.mod h1:tpNDvMWf9XBnkfPB2Tyx7lxDWTgfZ9wA4o7Yl50FWs4=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-sdk-go v1.44.300 h1:Zn+3lqgYahIf9yfrwZ+g+hq/c3KzUBaQ8wqY/ZXiAbY=
github.com/aws/aws-sdk-go v1.44.300/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.8.7 h1:d3sry5vGgVq/OpgozRUNP6xBsSo0mtNdwliApw+SAMQ=
github.com/bytedance/sonic v1.8.7/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/casbin/casbin/v2 v2.68.0 h1:7L4kwNJJw/pzdSEhl4SkeHz+1JzYn8guO+Q422sxzLM=
github.com/casbin/casbin/v2 v2.68.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creasty/defaults v1.7.0 h1:eNdqZvc5B509z18lD8yc212CAqJNvfT1Jq6L8WowdBA=
github.com/creasty/defaults v1.7.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM=
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg=
github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw=
github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gavv/httpexpect/v2 v2.15.0 h1:CCnFk9of4l4ijUhnMxyoEpJsIIBKcuWIFLMwwGTZxNs=
github.com/gavv/httpexpect/v2 v2.15.0/go.mod h1:7myOP3A3VyS4+qnA4cm8DAad8zMN+7zxDB80W9f8yIc=
github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g=
github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs=
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/spec v0.20.8 h1:ubHmXNY3FCIOinT8RNrrPfGc9t7I1qhPtdOGoG2AxRU=
github.com/go-openapi/spec v0.20.8/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
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.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
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.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-playground/validator/v10 v10.12.0 h1:E4gtWgxWxp8YSxExrQFv5BpCahla0PVF2oTTEYaWQGI=
github.com/go-playground/validator/v10 v10.12.0/go.mod h1:hCAPuzYvKdP33pxWa+2+6AIKXEKqjIUyqsNCtbsSJrA=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-redis/redis_rate/v9 v9.1.2 h1:H0l5VzoAtOE6ydd38j8MCq3ABlGLnvvbA1xDSVVCHgQ=
github.com/go-redis/redis_rate/v9 v9.1.2/go.mod h1:oam2de2apSgRG8aJzwJddXbNu91Iyz1m8IKJE2vpvlQ=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
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 v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.1.1 h1:jxpi2eWoU84wbX9iIEyAeeoac3FLuifZpY9tcNUD9kw=
github.com/golang/glog v1.1.1/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/flatbuffers v23.3.3+incompatible h1:5PJI/WbJkaMTvpGxsHVKG/LurN/KnWXNyGpwSCDgen0=
github.com/google/flatbuffers v23.3.3+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
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-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU=
github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
github.com/jackc/puddle/v2 v2.2.0/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.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
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/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU=
github.com/klauspost/compress v1.16.4/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
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.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/leodido/go-urn v1.2.3 h1:6BE2vPT0lqoz3fmOesHZiaiFh7889ssCo2GMvLCfiuA=
github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.51 h1:eSewrwc23TqUDEH8aw8Bwp4f+JDdozRrPWcKR7DZhmY=
github.com/minio/minio-go/v7 v7.0.51/go.mod h1:IbbodHyjUAguneyucUaahv+VMNs/EOTV9du7A7/Z3HU=
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
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 v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us=
github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
github.com/redis/go-redis/v9 v9.0.4 h1:FC82T+CHJ/Q/PdyLW++GeCO+Ol59Y4T7R4jbgjvktgc=
github.com/redis/go-redis/v9 v9.0.4/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
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/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
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/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo=
github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04=
github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E=
github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
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 v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw=
github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4=
github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
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.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
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.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/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-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
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.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
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-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
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=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=
gorm.io/driver/mysql v1.4.7 h1:rY46lkCspzGHn7+IYsNpSfEv9tA+SU4SkkB+GFX125Y=
gorm.io/driver/mysql v1.4.7/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8oc=
gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
gorm.io/driver/sqlite v1.1.3/go.mod h1:AKDgRWk8lcSQSw+9kxCJnX/yySj8G3rdwYlU57cB45c=
gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc=
gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.23.0/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.24.3/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11 h1:9qNbmu21nNThCNnF5i2R3kw2aL27U8ZwbzccNjOmW0g=
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/plugin/dbresolver v1.4.1 h1:Ug4LcoPhrvqq71UhxtF346f+skTYoCa/nEsdjvHwEzk=
gorm.io/plugin/dbresolver v1.4.1/go.mod h1:CTbCtMWhsjXSiJqiW2R8POvJ2cq18RVOl4WGyT5nhNc=
gorm.io/plugin/soft_delete v1.2.1 h1:qx9D/c4Xu6w5KT8LviX8DgLcB9hkKl6JC9f44Tj7cGU=
gorm.io/plugin/soft_delete v1.2.1/go.mod h1:Zv7vQctOJTGOsJ/bWgrN1n3od0GBAZgnLjEx+cApLGk=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs=
moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -0,0 +1,106 @@
package bootstrap
import (
"context"
"fmt"
"net/http"
_ "net/http/pprof" //nolint:gosec
"os"
"strings"
"github.guxuan/haibei/internal/config"
_ "github.guxuan/haibei/internal/swagger"
"github.guxuan/haibei/internal/utility/prom"
"github.guxuan/haibei/internal/wirex"
"github.guxuan/haibei/pkg/logging"
"github.guxuan/haibei/pkg/util"
"go.uber.org/zap"
)
// RunConfig defines the config for run command.
type RunConfig struct {
WorkDir string // Working directory
Configs string // Directory or files (multiple separated by commas)
StaticDir string // Static files directory
}
// The Run function initializes and starts a service with configuration and logging, and handles
// cleanup upon exit.
func Run(ctx context.Context, runCfg RunConfig) error {
defer func() {
if err := zap.L().Sync(); err != nil {
fmt.Printf("failed to sync zap logger: %s \n", err.Error())
}
}()
// Load configuration.
workDir := runCfg.WorkDir
staticDir := runCfg.StaticDir
config.MustLoad(workDir, strings.Split(runCfg.Configs, ",")...)
config.C.General.WorkDir = workDir
config.C.Middleware.Static.Dir = staticDir
config.C.Print()
config.C.PreLoad()
// Initialize logger.
cleanLoggerFn, err := logging.InitWithConfig(ctx, &config.C.Logger, initLoggerHook)
if err != nil {
return err
}
ctx = logging.NewTag(ctx, logging.TagKeyMain)
logging.Context(ctx).Info("starting service ...",
zap.String("version", config.C.General.Version),
zap.Int("pid", os.Getpid()),
zap.String("workdir", workDir),
zap.String("config", runCfg.Configs),
zap.String("static", staticDir),
)
// Start pprof server.
if addr := config.C.General.PprofAddr; addr != "" {
logging.Context(ctx).Info("pprof server is listening on " + addr)
go func() {
err := http.ListenAndServe(addr, nil)
if err != nil {
logging.Context(ctx).Error("failed to listen pprof server", zap.Error(err))
}
}()
}
// Build injector.
injector, cleanInjectorFn, err := wirex.BuildInjector(ctx)
if err != nil {
return err
}
if err := injector.M.Init(ctx); err != nil {
return err
}
// Initialize global prometheus metrics.
prom.Init()
return util.Run(ctx, func(ctx context.Context) (func(), error) {
cleanHTTPServerFn, err := startHTTPServer(ctx, injector)
if err != nil {
return cleanInjectorFn, err
}
return func() {
if err := injector.M.Release(ctx); err != nil {
logging.Context(ctx).Error("failed to release injector", zap.Error(err))
}
if cleanHTTPServerFn != nil {
cleanHTTPServerFn()
}
if cleanInjectorFn != nil {
cleanInjectorFn()
}
if cleanLoggerFn != nil {
cleanLoggerFn()
}
}, nil
})
}

192
internal/bootstrap/http.go Normal file
View File

@ -0,0 +1,192 @@
package bootstrap
import (
"context"
"crypto/tls"
"fmt"
"net/http"
"path/filepath"
"time"
"github.com/casbin/casbin/v2"
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"github.guxuan/haibei/internal/config"
"github.guxuan/haibei/internal/utility/prom"
"github.guxuan/haibei/internal/wirex"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/logging"
"github.guxuan/haibei/pkg/middleware"
"github.guxuan/haibei/pkg/util"
"go.uber.org/zap"
)
func startHTTPServer(ctx context.Context, injector *wirex.Injector) (func(), error) {
if config.C.IsDebug() {
gin.SetMode(gin.DebugMode)
} else {
gin.SetMode(gin.ReleaseMode)
}
e := gin.New()
e.GET("/health", func(c *gin.Context) {
util.ResOK(c)
})
e.Use(middleware.RecoveryWithConfig(middleware.RecoveryConfig{
Skip: config.C.Middleware.Recovery.Skip,
}))
e.NoMethod(func(c *gin.Context) {
util.ResError(c, errors.MethodNotAllowed("", "Method Not Allowed"))
})
e.NoRoute(func(c *gin.Context) {
util.ResError(c, errors.NotFound("", "Not Found"))
})
allowedPrefixes := injector.M.RouterPrefixes()
// Register middlewares
if err := useHTTPMiddlewares(ctx, e, injector, allowedPrefixes); err != nil {
return nil, err
}
// Register routers
if err := injector.M.RegisterRouters(ctx, e); err != nil {
return nil, err
}
// Register swagger
if !config.C.General.DisableSwagger {
e.StaticFile("/openapi.json", filepath.Join(config.C.General.WorkDir, "openapi.json"))
e.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
}
if dir := config.C.Middleware.Static.Dir; dir != "" {
e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
Root: dir,
SkippedPathPrefixes: allowedPrefixes,
}))
}
addr := config.C.General.HTTP.Addr
logging.Context(ctx).Info(fmt.Sprintf("HTTP server is listening on %s", addr))
srv := &http.Server{
Addr: addr,
Handler: e,
ReadTimeout: time.Second * time.Duration(config.C.General.HTTP.ReadTimeout),
WriteTimeout: time.Second * time.Duration(config.C.General.HTTP.WriteTimeout),
IdleTimeout: time.Second * time.Duration(config.C.General.HTTP.IdleTimeout),
}
go func() {
var err error
if config.C.General.HTTP.CertFile != "" && config.C.General.HTTP.KeyFile != "" {
srv.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS12}
err = srv.ListenAndServeTLS(config.C.General.HTTP.CertFile, config.C.General.HTTP.KeyFile)
} else {
err = srv.ListenAndServe()
}
if err != nil && err != http.ErrServerClosed {
logging.Context(ctx).Error("Failed to listen http server", zap.Error(err))
}
}()
return func() {
ctx, cancel := context.WithTimeout(ctx, time.Second*time.Duration(config.C.General.HTTP.ShutdownTimeout))
defer cancel()
srv.SetKeepAlivesEnabled(false)
if err := srv.Shutdown(ctx); err != nil {
logging.Context(ctx).Error("Failed to shutdown http server", zap.Error(err))
}
}, nil
}
func useHTTPMiddlewares(_ context.Context, e *gin.Engine, injector *wirex.Injector, allowedPrefixes []string) error {
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
Enable: config.C.Middleware.CORS.Enable,
AllowAllOrigins: config.C.Middleware.CORS.AllowAllOrigins,
AllowOrigins: config.C.Middleware.CORS.AllowOrigins,
AllowMethods: config.C.Middleware.CORS.AllowMethods,
AllowHeaders: config.C.Middleware.CORS.AllowHeaders,
AllowCredentials: config.C.Middleware.CORS.AllowCredentials,
ExposeHeaders: config.C.Middleware.CORS.ExposeHeaders,
MaxAge: config.C.Middleware.CORS.MaxAge,
AllowWildcard: config.C.Middleware.CORS.AllowWildcard,
AllowBrowserExtensions: config.C.Middleware.CORS.AllowBrowserExtensions,
AllowWebSockets: config.C.Middleware.CORS.AllowWebSockets,
AllowFiles: config.C.Middleware.CORS.AllowFiles,
}))
e.Use(middleware.TraceWithConfig(middleware.TraceConfig{
AllowedPathPrefixes: allowedPrefixes,
SkippedPathPrefixes: config.C.Middleware.Trace.SkippedPathPrefixes,
RequestHeaderKey: config.C.Middleware.Trace.RequestHeaderKey,
ResponseTraceKey: config.C.Middleware.Trace.ResponseTraceKey,
}))
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
AllowedPathPrefixes: allowedPrefixes,
SkippedPathPrefixes: config.C.Middleware.Logger.SkippedPathPrefixes,
MaxOutputRequestBodyLen: config.C.Middleware.Logger.MaxOutputRequestBodyLen,
MaxOutputResponseBodyLen: config.C.Middleware.Logger.MaxOutputResponseBodyLen,
}))
e.Use(middleware.CopyBodyWithConfig(middleware.CopyBodyConfig{
AllowedPathPrefixes: allowedPrefixes,
SkippedPathPrefixes: config.C.Middleware.CopyBody.SkippedPathPrefixes,
MaxContentLen: config.C.Middleware.CopyBody.MaxContentLen,
}))
e.Use(middleware.AuthWithConfig(middleware.AuthConfig{
AllowedPathPrefixes: allowedPrefixes,
SkippedPathPrefixes: config.C.Middleware.Auth.SkippedPathPrefixes,
ParseUserID: injector.M.RBAC.LoginAPI.LoginBIZ.ParseUserID,
RootID: config.C.General.Root.ID,
}))
e.Use(middleware.RateLimiterWithConfig(middleware.RateLimiterConfig{
Enable: config.C.Middleware.RateLimiter.Enable,
AllowedPathPrefixes: allowedPrefixes,
SkippedPathPrefixes: config.C.Middleware.RateLimiter.SkippedPathPrefixes,
Period: config.C.Middleware.RateLimiter.Period,
MaxRequestsPerIP: config.C.Middleware.RateLimiter.MaxRequestsPerIP,
MaxRequestsPerUser: config.C.Middleware.RateLimiter.MaxRequestsPerUser,
StoreType: config.C.Middleware.RateLimiter.Store.Type,
MemoryStoreConfig: middleware.RateLimiterMemoryConfig{
Expiration: time.Second * time.Duration(config.C.Middleware.RateLimiter.Store.Memory.Expiration),
CleanupInterval: time.Second * time.Duration(config.C.Middleware.RateLimiter.Store.Memory.CleanupInterval),
},
RedisStoreConfig: middleware.RateLimiterRedisConfig{
Addr: config.C.Middleware.RateLimiter.Store.Redis.Addr,
Password: config.C.Middleware.RateLimiter.Store.Redis.Password,
DB: config.C.Middleware.RateLimiter.Store.Redis.DB,
Username: config.C.Middleware.RateLimiter.Store.Redis.Username,
},
}))
e.Use(middleware.CasbinWithConfig(middleware.CasbinConfig{
AllowedPathPrefixes: allowedPrefixes,
SkippedPathPrefixes: config.C.Middleware.Casbin.SkippedPathPrefixes,
Skipper: func(c *gin.Context) bool {
if config.C.Middleware.Casbin.Disable ||
util.FromIsRootUser(c.Request.Context()) {
return true
}
return false
},
GetEnforcer: func(c *gin.Context) *casbin.Enforcer {
return injector.M.RBAC.Casbinx.GetEnforcer()
},
GetSubjects: func(c *gin.Context) []string {
return util.FromUserCache(c.Request.Context()).RoleIDs
},
}))
if config.C.Util.Prometheus.Enable {
e.Use(prom.GinMiddleware)
}
return nil
}

View File

@ -0,0 +1,43 @@
package bootstrap
import (
"context"
"github.com/spf13/cast"
"github.guxuan/haibei/internal/config"
"github.guxuan/haibei/pkg/gormx"
"github.guxuan/haibei/pkg/logging"
)
func initLoggerHook(_ context.Context, cfg *logging.HookConfig) (*logging.Hook, error) {
extra := cfg.Extra
if extra == nil {
extra = make(map[string]string)
}
extra["appname"] = config.C.General.AppName
switch cfg.Type {
case "gorm":
db, err := gormx.New(gormx.Config{
Debug: cast.ToBool(cfg.Options["Debug"]),
DBType: cast.ToString(cfg.Options["DBType"]),
DSN: cast.ToString(cfg.Options["DSN"]),
MaxLifetime: cast.ToInt(cfg.Options["MaxLifetime"]),
MaxIdleTime: cast.ToInt(cfg.Options["MaxIdleTime"]),
MaxOpenConns: cast.ToInt(cfg.Options["MaxOpenConns"]),
MaxIdleConns: cast.ToInt(cfg.Options["MaxIdleConns"]),
TablePrefix: config.C.Storage.DB.TablePrefix,
})
if err != nil {
return nil, err
}
hook := logging.NewHook(logging.NewGormHook(db),
logging.SetHookExtra(cfg.Extra),
logging.SetHookMaxJobs(cfg.MaxBuffer),
logging.SetHookMaxWorkers(cfg.MaxThread))
return hook, nil
default:
return nil, nil
}
}

166
internal/config/config.go Normal file
View File

@ -0,0 +1,166 @@
package config
import (
"fmt"
"github.guxuan/haibei/pkg/encoding/json"
"github.guxuan/haibei/pkg/logging"
)
type Config struct {
Logger logging.LoggerConfig
General General
Storage Storage
Middleware Middleware
Util Util
Dictionary Dictionary
FileConfig FileConfig
}
type FileConfig struct {
UploadDir string
StaticPrefix string
}
type General struct {
AppName string `default:"haibei"`
Version string `default:"v1.0.0"`
Debug bool
PprofAddr string
DisableSwagger bool
DisablePrintConfig bool
DefaultLoginPwd string `default:"6351623c8cef86fefabfa7da046fc619"` // MD5(abc-123)
WorkDir string // From command arguments
MenuFile string // From schema.Menus (JSON/YAML)
DenyOperateMenu bool
HTTP struct {
Addr string `default:":8040"`
ShutdownTimeout int `default:"10"` // seconds
ReadTimeout int `default:"60"` // seconds
WriteTimeout int `default:"60"` // seconds
IdleTimeout int `default:"10"` // seconds
CertFile string
KeyFile string
}
Root struct {
ID string `default:"root"`
Username string `default:"admin"`
Password string
Name string `default:"Admin"`
}
}
type Storage struct {
Cache struct {
Type string `default:"memory"` // memory/badger/redis
Delimiter string `default:":"` // delimiter for key
Memory struct {
CleanupInterval int `default:"60"` // seconds
}
Badger struct {
Path string `default:"data/cache"`
}
Redis struct {
Addr string
Username string
Password string
DB int
}
}
DB struct {
Debug bool
Type string `default:"sqlite3"` // sqlite3/mysql/postgres
DSN string `default:"data/haibei.db"` // database source name
MaxLifetime int `default:"86400"` // seconds
MaxIdleTime int `default:"3600"` // seconds
MaxOpenConns int `default:"100"` // connections
MaxIdleConns int `default:"50"` // connections
TablePrefix string `default:""`
AutoMigrate bool
PrepareStmt bool
Resolver []struct {
DBType string // sqlite3/mysql/postgres
Sources []string // DSN
Replicas []string // DSN
Tables []string
}
}
}
type Util struct {
Captcha struct {
Length int `default:"4"`
Width int `default:"400"`
Height int `default:"160"`
CacheType string `default:"memory"` // memory/redis
Redis struct {
Addr string
Username string
Password string
DB int
KeyPrefix string `default:"captcha:"`
}
}
Prometheus struct {
Enable bool
Port int `default:"9100"`
BasicUsername string `default:"admin"`
BasicPassword string `default:"admin"`
LogApis []string
LogMethods []string
DefaultCollect bool
}
}
type Dictionary struct {
UserCacheExp int `default:"4"` // hours
}
func (c *Config) IsDebug() bool {
return c.General.Debug
}
func (c *Config) String() string {
b, err := json.MarshalIndent(c, "", " ")
if err != nil {
panic("Failed to marshal config: " + err.Error())
}
return string(b)
}
func (c *Config) PreLoad() {
if addr := c.Storage.Cache.Redis.Addr; addr != "" {
username := c.Storage.Cache.Redis.Username
password := c.Storage.Cache.Redis.Password
if c.Util.Captcha.CacheType == "redis" &&
c.Util.Captcha.Redis.Addr == "" {
c.Util.Captcha.Redis.Addr = addr
c.Util.Captcha.Redis.Username = username
c.Util.Captcha.Redis.Password = password
}
if c.Middleware.RateLimiter.Store.Type == "redis" &&
c.Middleware.RateLimiter.Store.Redis.Addr == "" {
c.Middleware.RateLimiter.Store.Redis.Addr = addr
c.Middleware.RateLimiter.Store.Redis.Username = username
c.Middleware.RateLimiter.Store.Redis.Password = password
}
if c.Middleware.Auth.Store.Type == "redis" &&
c.Middleware.Auth.Store.Redis.Addr == "" {
c.Middleware.Auth.Store.Redis.Addr = addr
c.Middleware.Auth.Store.Redis.Username = username
c.Middleware.Auth.Store.Redis.Password = password
}
}
}
func (c *Config) Print() {
if c.General.DisablePrintConfig {
return
}
fmt.Println("// ----------------------- Load configurations start ------------------------")
fmt.Println(c.String())
fmt.Println("// ----------------------- Load configurations end --------------------------")
}
func (c *Config) FormatTableName(name string) string {
return c.Storage.DB.TablePrefix + name
}

18
internal/config/consts.go Normal file
View File

@ -0,0 +1,18 @@
package config
const (
CacheNSForUser = "user"
CacheNSForCustomer = "customer"
CacheNSForRole = "role"
)
const (
CacheKeyForSyncToCasbin = "sync:casbin"
)
const (
ErrInvalidTokenID = "com.invalid.token"
ErrInvalidCaptchaID = "com.invalid.captcha"
ErrInvalidUsernameOrPassword = "com.invalid.username-or-password"
)

View File

@ -0,0 +1,90 @@
package config
type Middleware struct {
Recovery struct {
Skip int `default:"3"` // skip the first n stack frames
}
CORS struct {
Enable bool
AllowAllOrigins bool
AllowOrigins []string
AllowMethods []string
AllowHeaders []string
AllowCredentials bool
ExposeHeaders []string
MaxAge int
AllowWildcard bool
AllowBrowserExtensions bool
AllowWebSockets bool
AllowFiles bool
}
Trace struct {
SkippedPathPrefixes []string
RequestHeaderKey string `default:"X-Request-Id"`
ResponseTraceKey string `default:"X-Trace-Id"`
}
Logger struct {
SkippedPathPrefixes []string
MaxOutputRequestBodyLen int `default:"4096"`
MaxOutputResponseBodyLen int `default:"1024"`
}
CopyBody struct {
SkippedPathPrefixes []string
MaxContentLen int64 `default:"33554432"` // max content length (default 32MB)
}
Auth struct {
Disable bool
SkippedPathPrefixes []string
SigningMethod string `default:"HS512"` // HS256/HS384/HS512
SigningKey string `default:"XnEsT0S@"` // secret key
OldSigningKey string // old secret key (for migration)
Expired int `default:"86400"` // seconds
Store struct {
Type string `default:"memory"` // memory/badger/redis
Delimiter string `default:":"` // delimiter for key
Memory struct {
CleanupInterval int `default:"60"` // seconds
}
Badger struct {
Path string `default:"data/auth"`
}
Redis struct {
Addr string
Username string
Password string
DB int
}
}
}
RateLimiter struct {
Enable bool
SkippedPathPrefixes []string
Period int // seconds
MaxRequestsPerIP int
MaxRequestsPerUser int
Store struct {
Type string // memory/redis
Memory struct {
Expiration int `default:"3600"` // seconds
CleanupInterval int `default:"60"` // seconds
}
Redis struct {
Addr string
Username string
Password string
DB int
}
}
}
Casbin struct {
Disable bool
SkippedPathPrefixes []string
LoadThread int `default:"2"`
AutoLoadInterval int `default:"3"` // seconds
ModelFile string `default:"rbac_model.conf"`
GenPolicyFile string `default:"gen_rbac_policy.csv"`
}
Static struct {
Dir string // Static files directory (From command arguments)
}
}

84
internal/config/parse.go Normal file
View File

@ -0,0 +1,84 @@
package config
import (
"os"
"path/filepath"
"strings"
"sync"
"github.com/creasty/defaults"
"github.guxuan/haibei/pkg/encoding/json"
"github.guxuan/haibei/pkg/encoding/toml"
"github.guxuan/haibei/pkg/errors"
)
var (
once sync.Once
C = new(Config)
)
func MustLoad(dir string, names ...string) {
once.Do(func() {
if err := Load(dir, names...); err != nil {
panic(err)
}
})
}
// Loads configuration files in various formats from a directory and parses them into
// a struct.
func Load(dir string, names ...string) error {
// Set default values
if err := defaults.Set(C); err != nil {
return err
}
supportExts := []string{".json", ".toml"}
parseFile := func(name string) error {
ext := filepath.Ext(name)
if ext == "" || !strings.Contains(strings.Join(supportExts, ","), ext) {
return nil
}
buf, err := os.ReadFile(name)
if err != nil {
return errors.Wrapf(err, "failed to read config file %s", name)
}
switch ext {
case ".json":
err = json.Unmarshal(buf, C)
case ".toml":
err = toml.Unmarshal(buf, C)
}
return errors.Wrapf(err, "failed to unmarshal config %s", name)
}
for _, name := range names {
fullname := filepath.Join(dir, name)
info, err := os.Stat(fullname)
if err != nil {
return errors.Wrapf(err, "failed to get config file %s", name)
}
if info.IsDir() {
err := filepath.WalkDir(fullname, func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
} else if d.IsDir() {
return nil
}
return parseFile(path)
})
if err != nil {
return errors.Wrapf(err, "failed to walk config dir %s", name)
}
continue
}
if err := parseFile(fullname); err != nil {
return err
}
}
return nil
}

View File

@ -0,0 +1,145 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/activity/biz"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Activity` api.
type Activity struct {
ActivityBIZ *biz.Activity
}
// @Tags 活动模块
// @Security ApiKeyAuth
// @Summary Query activity list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.Activity}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/activities [get]
func (a *Activity) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.ActivityQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.ActivityBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags 活动模块
// @Security ApiKeyAuth
// @Summary Get activity record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.Activity}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/activities/{id} [get]
func (a *Activity) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.ActivityBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags 活动模块
// @Security ApiKeyAuth
// @Summary Create activity record
// @Param body body schema.ActivityForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.Activity}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/activities [post]
func (a *Activity) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.ActivityForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.ActivityBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags 活动模块
// @Security ApiKeyAuth
// @Summary Update activity record by ID
// @Param id path string true "unique id"
// @Param body body schema.ActivityForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/activities/{id} [put]
func (a *Activity) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.ActivityForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.ActivityBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags 活动模块
// @Security ApiKeyAuth
// @Summary Delete activity record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/activities/{id} [delete]
func (a *Activity) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.ActivityBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,145 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/activity/biz"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/util"
)
// Defining the `ActivityDetail` api.
type ActivityDetail struct {
ActivityDetailBIZ *biz.ActivityDetail
}
// @Tags ActivityDetailAPI
// @Security ApiKeyAuth
// @Summary Query activity detail list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.ActivityDetail}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/activity-details [get]
func (a *ActivityDetail) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.ActivityDetailQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.ActivityDetailBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags ActivityDetailAPI
// @Security ApiKeyAuth
// @Summary Get activity detail record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.ActivityDetail}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/activity-details/{id} [get]
func (a *ActivityDetail) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.ActivityDetailBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags ActivityDetailAPI
// @Security ApiKeyAuth
// @Summary Create activity detail record
// @Param body body schema.ActivityDetailForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.ActivityDetail}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/activity-details [post]
func (a *ActivityDetail) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.ActivityDetailForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.ActivityDetailBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags ActivityDetailAPI
// @Security ApiKeyAuth
// @Summary Update activity detail record by ID
// @Param id path string true "unique id"
// @Param body body schema.ActivityDetailForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/activity-details/{id} [put]
func (a *ActivityDetail) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.ActivityDetailForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.ActivityDetailBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags ActivityDetailAPI
// @Security ApiKeyAuth
// @Summary Delete activity detail record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/activity-details/{id} [delete]
func (a *ActivityDetail) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.ActivityDetailBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,144 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/activity/biz"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/util"
)
type House struct {
HouseBIZ *biz.House
}
// @Tags 房源模块
// @Security ApiKeyAuth
// @Summary Query house list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.House}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/houses [get]
func (a *House) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.HouseQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.HouseBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags 房源模块
// @Security ApiKeyAuth
// @Summary Get house record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.House}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/houses/{id} [get]
func (a *House) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.HouseBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags 房源模块
// @Security ApiKeyAuth
// @Summary Create house record
// @Param body body schema.HouseForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.House}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/houses [post]
func (a *House) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.HouseForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.HouseBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags 房源模块
// @Security ApiKeyAuth
// @Summary Update house record by ID
// @Param id path string true "unique id"
// @Param body body schema.HouseForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/houses/{id} [put]
func (a *House) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.HouseForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.HouseBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags 房源模块
// @Security ApiKeyAuth
// @Summary Delete house record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/houses/{id} [delete]
func (a *House) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.HouseBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,144 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/activity/biz"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/util"
)
type HouseArticle struct {
HouseArticleBIZ *biz.HouseArticle
}
// @Tags 房刊模块
// @Security ApiKeyAuth
// @Summary Query house list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.HouseArticle}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/house_articles [get]
func (a *HouseArticle) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.HouseArticleQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.HouseArticleBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags 房刊模块
// @Security ApiKeyAuth
// @Summary Get house record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.HouseArticle}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/house_articles/{id} [get]
func (a *HouseArticle) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.HouseArticleBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags 房刊模块
// @Security ApiKeyAuth
// @Summary Create house record
// @Param body body schema.HouseArticleForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.HouseArticle}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/house_articles [post]
func (a *HouseArticle) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.HouseArticleForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.HouseArticleBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags 房刊模块
// @Security ApiKeyAuth
// @Summary Update house record by ID
// @Param id path string true "unique id"
// @Param body body schema.HouseArticleForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/house_articles/{id} [put]
func (a *HouseArticle) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.HouseArticleForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.HouseArticleBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags 房刊模块
// @Security ApiKeyAuth
// @Summary Delete house record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/house_articles/{id} [delete]
func (a *HouseArticle) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.HouseArticleBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,145 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/activity/biz"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/util"
)
// Defining the `QeustionDetail` api.
type QeustionDetail struct {
QeustionDetailBIZ *biz.QeustionDetail
}
// @Tags QeustionDetailAPI
// @Security ApiKeyAuth
// @Summary Query qeustion detail list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.QeustionDetail}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/qeustion-details [get]
func (a *QeustionDetail) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.QeustionDetailQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.QeustionDetailBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags QeustionDetailAPI
// @Security ApiKeyAuth
// @Summary Get qeustion detail record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.QeustionDetail}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/qeustion-details/{id} [get]
func (a *QeustionDetail) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.QeustionDetailBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags QeustionDetailAPI
// @Security ApiKeyAuth
// @Summary Create qeustion detail record
// @Param body body schema.QeustionDetailForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.QeustionDetail}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/qeustion-details [post]
func (a *QeustionDetail) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.QeustionDetailForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.QeustionDetailBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags QeustionDetailAPI
// @Security ApiKeyAuth
// @Summary Update qeustion detail record by ID
// @Param id path string true "unique id"
// @Param body body schema.QeustionDetailForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/qeustion-details/{id} [put]
func (a *QeustionDetail) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.QeustionDetailForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.QeustionDetailBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags QeustionDetailAPI
// @Security ApiKeyAuth
// @Summary Delete qeustion detail record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/qeustion-details/{id} [delete]
func (a *QeustionDetail) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.QeustionDetailBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,145 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/activity/biz"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Questionnaire` api.
type Questionnaire struct {
QuestionnaireBIZ *biz.Questionnaire
}
// @Tags 问卷模块
// @Security ApiKeyAuth
// @Summary Query questionnaire list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.Questionnaire}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/questionnaires [get]
func (a *Questionnaire) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.QuestionnaireQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.QuestionnaireBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags 问卷模块
// @Security ApiKeyAuth
// @Summary Get questionnaire record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.Questionnaire}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/questionnaires/{id} [get]
func (a *Questionnaire) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.QuestionnaireBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags 问卷模块
// @Security ApiKeyAuth
// @Summary Create questionnaire record
// @Param body body schema.QuestionnaireForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.Questionnaire}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/questionnaires [post]
func (a *Questionnaire) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.QuestionnaireForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.QuestionnaireBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags 问卷模块
// @Security ApiKeyAuth
// @Summary Update questionnaire record by ID
// @Param id path string true "unique id"
// @Param body body schema.QuestionnaireForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/questionnaires/{id} [put]
func (a *Questionnaire) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.QuestionnaireForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.QuestionnaireBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags 问卷模块
// @Security ApiKeyAuth
// @Summary Delete questionnaire record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/questionnaires/{id} [delete]
func (a *Questionnaire) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.QuestionnaireBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,104 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/activity/dal"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Activity` business logic.
type Activity struct {
Trans *util.Trans
ActivityDAL *dal.Activity
}
// Query activities from the data access object based on the provided parameters and options.
func (a *Activity) Query(ctx context.Context, params schema.ActivityQueryParam) (*schema.ActivityQueryResult, error) {
params.Pagination = true
result, err := a.ActivityDAL.Query(ctx, params, schema.ActivityQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified activity from the data access object.
func (a *Activity) Get(ctx context.Context, id uint) (*schema.Activity, error) {
activity, err := a.ActivityDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if activity == nil {
return nil, errors.NotFound("", "Activity not found")
}
return activity, nil
}
// Create a new activity in the data access object.
func (a *Activity) Create(ctx context.Context, formItem *schema.ActivityForm) (*schema.Activity, error) {
activity := &schema.Activity{}
if err := formItem.FillTo(activity); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.ActivityDAL.Create(ctx, activity); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return activity, nil
}
// Update the specified activity in the data access object.
func (a *Activity) Update(ctx context.Context, id uint, formItem *schema.ActivityForm) error {
activity, err := a.ActivityDAL.Get(ctx, id)
if err != nil {
return err
} else if activity == nil {
return errors.NotFound("", "Activity not found")
}
if err := formItem.FillTo(activity); err != nil {
return err
}
activity.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.ActivityDAL.Update(ctx, activity); err != nil {
return err
}
return nil
})
}
// Delete the specified activity from the data access object.
func (a *Activity) Delete(ctx context.Context, id uint) error {
exists, err := a.ActivityDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Activity not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.ActivityDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,104 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/activity/dal"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
// Defining the `ActivityDetail` business logic.
type ActivityDetail struct {
Trans *util.Trans
ActivityDetailDAL *dal.ActivityDetail
}
// Query activity details from the data access object based on the provided parameters and options.
func (a *ActivityDetail) Query(ctx context.Context, params schema.ActivityDetailQueryParam) (*schema.ActivityDetailQueryResult, error) {
params.Pagination = true
result, err := a.ActivityDetailDAL.Query(ctx, params, schema.ActivityDetailQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified activity detail from the data access object.
func (a *ActivityDetail) Get(ctx context.Context, id uint) (*schema.ActivityDetail, error) {
activityDetail, err := a.ActivityDetailDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if activityDetail == nil {
return nil, errors.NotFound("", "Activity detail not found")
}
return activityDetail, nil
}
// Create a new activity detail in the data access object.
func (a *ActivityDetail) Create(ctx context.Context, formItem *schema.ActivityDetailForm) (*schema.ActivityDetail, error) {
activityDetail := &schema.ActivityDetail{}
if err := formItem.FillTo(activityDetail); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.ActivityDetailDAL.Create(ctx, activityDetail); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return activityDetail, nil
}
// Update the specified activity detail in the data access object.
func (a *ActivityDetail) Update(ctx context.Context, id uint, formItem *schema.ActivityDetailForm) error {
activityDetail, err := a.ActivityDetailDAL.Get(ctx, id)
if err != nil {
return err
} else if activityDetail == nil {
return errors.NotFound("", "Activity detail not found")
}
if err := formItem.FillTo(activityDetail); err != nil {
return err
}
activityDetail.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.ActivityDetailDAL.Update(ctx, activityDetail); err != nil {
return err
}
return nil
})
}
// Delete the specified activity detail from the data access object.
func (a *ActivityDetail) Delete(ctx context.Context, id uint) error {
exists, err := a.ActivityDetailDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Activity detail not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.ActivityDetailDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,98 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/activity/dal"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
type House struct {
Trans *util.Trans
HouseDAL *dal.House
}
func (a *House) Query(ctx context.Context, params schema.HouseQueryParam) (*schema.HouseQueryResult, error) {
params.Pagination = true
result, err := a.HouseDAL.Query(ctx, params, schema.HouseQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
func (a *House) Get(ctx context.Context, id uint) (*schema.House, error) {
item, err := a.HouseDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if item == nil {
return nil, errors.NotFound("", "house not found")
}
return item, nil
}
func (a *House) Create(ctx context.Context, formItem *schema.HouseForm) (*schema.House, error) {
item := &schema.House{}
if err := formItem.FillTo(item); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.HouseDAL.Create(ctx, item); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return item, nil
}
func (a *House) Update(ctx context.Context, id uint, formItem *schema.HouseForm) error {
item, err := a.HouseDAL.Get(ctx, id)
if err != nil {
return err
} else if item == nil {
return errors.NotFound("", "House not found")
}
if err := formItem.FillTo(item); err != nil {
return err
}
item.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.HouseDAL.Update(ctx, item); err != nil {
return err
}
return nil
})
}
func (a *House) Delete(ctx context.Context, id uint) error {
exists, err := a.HouseDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "HOUSE not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.HouseDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,98 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/activity/dal"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
type HouseArticle struct {
Trans *util.Trans
HouseArticleDAL *dal.HouseArticle
}
func (a *HouseArticle) Query(ctx context.Context, params schema.HouseArticleQueryParam) (*schema.HouseArticleQueryResult, error) {
params.Pagination = true
result, err := a.HouseArticleDAL.Query(ctx, params, schema.HouseArticleQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
func (a *HouseArticle) Get(ctx context.Context, id uint) (*schema.HouseArticle, error) {
item, err := a.HouseArticleDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if item == nil {
return nil, errors.NotFound("", "house not found")
}
return item, nil
}
func (a *HouseArticle) Create(ctx context.Context, formItem *schema.HouseArticleForm) (*schema.HouseArticle, error) {
item := &schema.HouseArticle{}
if err := formItem.FillTo(item); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.HouseArticleDAL.Create(ctx, item); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return item, nil
}
func (a *HouseArticle) Update(ctx context.Context, id uint, formItem *schema.HouseArticleForm) error {
item, err := a.HouseArticleDAL.Get(ctx, id)
if err != nil {
return err
} else if item == nil {
return errors.NotFound("", "House not found")
}
if err := formItem.FillTo(item); err != nil {
return err
}
item.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.HouseArticleDAL.Update(ctx, item); err != nil {
return err
}
return nil
})
}
func (a *HouseArticle) Delete(ctx context.Context, id uint) error {
exists, err := a.HouseArticleDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "HOUSE not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.HouseArticleDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,104 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/activity/dal"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
// Defining the `QeustionDetail` business logic.
type QeustionDetail struct {
Trans *util.Trans
QeustionDetailDAL *dal.QeustionDetail
}
// Query qeustion details from the data access object based on the provided parameters and options.
func (a *QeustionDetail) Query(ctx context.Context, params schema.QeustionDetailQueryParam) (*schema.QeustionDetailQueryResult, error) {
params.Pagination = true
result, err := a.QeustionDetailDAL.Query(ctx, params, schema.QeustionDetailQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified qeustion detail from the data access object.
func (a *QeustionDetail) Get(ctx context.Context, id uint) (*schema.QeustionDetail, error) {
qeustionDetail, err := a.QeustionDetailDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if qeustionDetail == nil {
return nil, errors.NotFound("", "Qeustion detail not found")
}
return qeustionDetail, nil
}
// Create a new qeustion detail in the data access object.
func (a *QeustionDetail) Create(ctx context.Context, formItem *schema.QeustionDetailForm) (*schema.QeustionDetail, error) {
qeustionDetail := &schema.QeustionDetail{}
if err := formItem.FillTo(qeustionDetail); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.QeustionDetailDAL.Create(ctx, qeustionDetail); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return qeustionDetail, nil
}
// Update the specified qeustion detail in the data access object.
func (a *QeustionDetail) Update(ctx context.Context, id uint, formItem *schema.QeustionDetailForm) error {
qeustionDetail, err := a.QeustionDetailDAL.Get(ctx, id)
if err != nil {
return err
} else if qeustionDetail == nil {
return errors.NotFound("", "Qeustion detail not found")
}
if err := formItem.FillTo(qeustionDetail); err != nil {
return err
}
qeustionDetail.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.QeustionDetailDAL.Update(ctx, qeustionDetail); err != nil {
return err
}
return nil
})
}
// Delete the specified qeustion detail from the data access object.
func (a *QeustionDetail) Delete(ctx context.Context, id uint) error {
exists, err := a.QeustionDetailDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Qeustion detail not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.QeustionDetailDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,104 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/activity/dal"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Questionnaire` business logic.
type Questionnaire struct {
Trans *util.Trans
QuestionnaireDAL *dal.Questionnaire
}
// Query questionnaires from the data access object based on the provided parameters and options.
func (a *Questionnaire) Query(ctx context.Context, params schema.QuestionnaireQueryParam) (*schema.QuestionnaireQueryResult, error) {
params.Pagination = true
result, err := a.QuestionnaireDAL.Query(ctx, params, schema.QuestionnaireQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified questionnaire from the data access object.
func (a *Questionnaire) Get(ctx context.Context, id uint) (*schema.Questionnaire, error) {
questionnaire, err := a.QuestionnaireDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if questionnaire == nil {
return nil, errors.NotFound("", "Questionnaire not found")
}
return questionnaire, nil
}
// Create a new questionnaire in the data access object.
func (a *Questionnaire) Create(ctx context.Context, formItem *schema.QuestionnaireForm) (*schema.Questionnaire, error) {
questionnaire := &schema.Questionnaire{}
if err := formItem.FillTo(questionnaire); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.QuestionnaireDAL.Create(ctx, questionnaire); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return questionnaire, nil
}
// Update the specified questionnaire in the data access object.
func (a *Questionnaire) Update(ctx context.Context, id uint, formItem *schema.QuestionnaireForm) error {
questionnaire, err := a.QuestionnaireDAL.Get(ctx, id)
if err != nil {
return err
} else if questionnaire == nil {
return errors.NotFound("", "Questionnaire not found")
}
if err := formItem.FillTo(questionnaire); err != nil {
return err
}
questionnaire.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.QuestionnaireDAL.Update(ctx, questionnaire); err != nil {
return err
}
return nil
})
}
// Delete the specified questionnaire from the data access object.
func (a *Questionnaire) Delete(ctx context.Context, id uint) error {
exists, err := a.QuestionnaireDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Questionnaire not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.QuestionnaireDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,83 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get activity storage instance
func GetActivityDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.Activity))
}
// Defining the `Activity` data access object.
type Activity struct {
DB *gorm.DB
}
// Query activities from the database based on the provided parameters and options.
func (a *Activity) Query(ctx context.Context, params schema.ActivityQueryParam, opts ...schema.ActivityQueryOptions) (*schema.ActivityQueryResult, error) {
var opt schema.ActivityQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetActivityDB(ctx, a.DB)
var list schema.Activities
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.ActivityQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified activity from the database.
func (a *Activity) Get(ctx context.Context, id uint, opts ...schema.ActivityQueryOptions) (*schema.Activity, error) {
var opt schema.ActivityQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.Activity)
ok, err := util.FindOne(ctx, GetActivityDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified activity exists in the database.
func (a *Activity) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetActivityDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new activity.
func (a *Activity) Create(ctx context.Context, item *schema.Activity) error {
result := GetActivityDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified activity in the database.
func (a *Activity) Update(ctx context.Context, item *schema.Activity) error {
result := GetActivityDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified activity from the database.
func (a *Activity) Delete(ctx context.Context, id uint) error {
result := GetActivityDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.Activity))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,96 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get activity detail storage instance
func GetActivityDetailDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.ActivityDetail))
}
// Defining the `ActivityDetail` data access object.
type ActivityDetail struct {
DB *gorm.DB
}
// Query activity details from the database based on the provided parameters and options.
func (a *ActivityDetail) Query(ctx context.Context, params schema.ActivityDetailQueryParam, opts ...schema.ActivityDetailQueryOptions) (*schema.ActivityDetailQueryResult, error) {
var opt schema.ActivityDetailQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetActivityDetailDB(ctx, a.DB)
var list schema.ActivityDetails
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.ActivityDetailQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified activity detail from the database.
func (a *ActivityDetail) Get(ctx context.Context, id uint, opts ...schema.ActivityDetailQueryOptions) (*schema.ActivityDetail, error) {
var opt schema.ActivityDetailQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.ActivityDetail)
ok, err := util.FindOne(ctx, GetActivityDetailDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
func (a *ActivityDetail) GetByCustomerIDAndActivityID(ctx context.Context, customerID, activityID uint) (*schema.ActivityDetail, error) {
var opt schema.ActivityDetailQueryOptions
item := new(schema.ActivityDetail)
ok, err := util.FindOne(ctx, GetActivityDetailDB(ctx, a.DB).Where("customer_id =? AND activity_id = ? ", customerID, activityID), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified activity detail exists in the database.
func (a *ActivityDetail) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetActivityDetailDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new activity detail.
func (a *ActivityDetail) Create(ctx context.Context, item *schema.ActivityDetail) error {
result := GetActivityDetailDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified activity detail in the database.
func (a *ActivityDetail) Update(ctx context.Context, item *schema.ActivityDetail) error {
result := GetActivityDetailDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified activity detail from the database.
func (a *ActivityDetail) Delete(ctx context.Context, id uint) error {
result := GetActivityDetailDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.ActivityDetail))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,76 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
func GetHouseDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.House))
}
type House struct {
DB *gorm.DB
}
// Query activities from the database based on the provided parameters and options.
func (a *House) Query(ctx context.Context, params schema.HouseQueryParam, opts ...schema.HouseQueryOptions) (*schema.HouseQueryResult, error) {
var opt schema.HouseQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetHouseDB(ctx, a.DB)
var list schema.Houses
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.HouseQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
func (a *House) Get(ctx context.Context, id uint, opts ...schema.HouseQueryOptions) (*schema.House, error) {
var opt schema.HouseQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.House)
ok, err := util.FindOne(ctx, GetHouseDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
func (a *House) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetHouseDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
func (a *House) Create(ctx context.Context, item *schema.House) error {
result := GetHouseDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
func (a *House) Update(ctx context.Context, item *schema.House) error {
result := GetHouseDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
func (a *House) Delete(ctx context.Context, id uint) error {
result := GetHouseDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.House))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,76 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
func GetHouseArticleDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.HouseArticle))
}
type HouseArticle struct {
DB *gorm.DB
}
// Query activities from the database based on the provided parameters and options.
func (a *HouseArticle) Query(ctx context.Context, params schema.HouseArticleQueryParam, opts ...schema.HouseArticleQueryOptions) (*schema.HouseArticleQueryResult, error) {
var opt schema.HouseArticleQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetHouseArticleDB(ctx, a.DB)
var list schema.HouseArticles
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.HouseArticleQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
func (a *HouseArticle) Get(ctx context.Context, id uint, opts ...schema.HouseArticleQueryOptions) (*schema.HouseArticle, error) {
var opt schema.HouseArticleQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.HouseArticle)
ok, err := util.FindOne(ctx, GetHouseArticleDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
func (a *HouseArticle) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetHouseArticleDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
func (a *HouseArticle) Create(ctx context.Context, item *schema.HouseArticle) error {
result := GetHouseArticleDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
func (a *HouseArticle) Update(ctx context.Context, item *schema.HouseArticle) error {
result := GetHouseArticleDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
func (a *HouseArticle) Delete(ctx context.Context, id uint) error {
result := GetHouseArticleDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.HouseArticle))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,96 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get qeustion detail storage instance
func GetQeustionDetailDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.QeustionDetail))
}
// Defining the `QeustionDetail` data access object.
type QeustionDetail struct {
DB *gorm.DB
}
// Query qeustion details from the database based on the provided parameters and options.
func (a *QeustionDetail) Query(ctx context.Context, params schema.QeustionDetailQueryParam, opts ...schema.QeustionDetailQueryOptions) (*schema.QeustionDetailQueryResult, error) {
var opt schema.QeustionDetailQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetQeustionDetailDB(ctx, a.DB)
var list schema.QeustionDetails
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.QeustionDetailQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified qeustion detail from the database.
func (a *QeustionDetail) Get(ctx context.Context, id uint, opts ...schema.QeustionDetailQueryOptions) (*schema.QeustionDetail, error) {
var opt schema.QeustionDetailQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.QeustionDetail)
ok, err := util.FindOne(ctx, GetQeustionDetailDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
func (a *QeustionDetail) GetByCustomerIDAndActivityID(ctx context.Context, customerID, questionID uint) (*schema.QeustionDetail, error) {
var opt schema.QeustionDetailQueryOptions
item := new(schema.QeustionDetail)
ok, err := util.FindOne(ctx, GetQeustionDetailDB(ctx, a.DB).Where("customer_id =? AND question_id = ? ", customerID, questionID), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified qeustion detail exists in the database.
func (a *QeustionDetail) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetQeustionDetailDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new qeustion detail.
func (a *QeustionDetail) Create(ctx context.Context, item *schema.QeustionDetail) error {
result := GetQeustionDetailDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified qeustion detail in the database.
func (a *QeustionDetail) Update(ctx context.Context, item *schema.QeustionDetail) error {
result := GetQeustionDetailDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified qeustion detail from the database.
func (a *QeustionDetail) Delete(ctx context.Context, id uint) error {
result := GetQeustionDetailDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.QeustionDetail))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,83 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/activity/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get questionnaire storage instance
func GetQuestionnaireDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.Questionnaire))
}
// Defining the `Questionnaire` data access object.
type Questionnaire struct {
DB *gorm.DB
}
// Query questionnaires from the database based on the provided parameters and options.
func (a *Questionnaire) Query(ctx context.Context, params schema.QuestionnaireQueryParam, opts ...schema.QuestionnaireQueryOptions) (*schema.QuestionnaireQueryResult, error) {
var opt schema.QuestionnaireQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetQuestionnaireDB(ctx, a.DB)
var list schema.Questionnaires
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.QuestionnaireQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified questionnaire from the database.
func (a *Questionnaire) Get(ctx context.Context, id uint, opts ...schema.QuestionnaireQueryOptions) (*schema.Questionnaire, error) {
var opt schema.QuestionnaireQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.Questionnaire)
ok, err := util.FindOne(ctx, GetQuestionnaireDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified questionnaire exists in the database.
func (a *Questionnaire) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetQuestionnaireDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new questionnaire.
func (a *Questionnaire) Create(ctx context.Context, item *schema.Questionnaire) error {
result := GetQuestionnaireDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified questionnaire in the database.
func (a *Questionnaire) Update(ctx context.Context, item *schema.Questionnaire) error {
result := GetQuestionnaireDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified questionnaire from the database.
func (a *Questionnaire) Delete(ctx context.Context, id uint) error {
result := GetQuestionnaireDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.Questionnaire))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,73 @@
package activity
import (
"context"
"github.guxuan/haibei/internal/config"
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/activity/api"
"github.guxuan/haibei/internal/mods/activity/schema"
"gorm.io/gorm"
)
type Activity struct {
DB *gorm.DB
ActivityAPI *api.Activity
QuestionnaireAPI *api.Questionnaire
ActivityDetailAPI *api.ActivityDetail
QeustionDetailAPI *api.QeustionDetail
}
func (a *Activity) AutoMigrate(ctx context.Context) error {
return a.DB.AutoMigrate(new(schema.Activity), new(schema.Questionnaire), new(schema.ActivityDetail), new(schema.QeustionDetail), new(schema.House), new(schema.HouseArticle))
}
func (a *Activity) Init(ctx context.Context) error {
if config.C.Storage.DB.AutoMigrate {
if err := a.AutoMigrate(ctx); err != nil {
return err
}
}
return nil
}
func (a *Activity) RegisterV1Routers(ctx context.Context, v1 *gin.RouterGroup) error {
activity := v1.Group("activities")
{
activity.GET("", a.ActivityAPI.Query)
activity.GET(":id", a.ActivityAPI.Get)
activity.POST("", a.ActivityAPI.Create)
activity.PUT(":id", a.ActivityAPI.Update)
activity.DELETE(":id", a.ActivityAPI.Delete)
}
questionnaire := v1.Group("questionnaires")
{
questionnaire.GET("", a.QuestionnaireAPI.Query)
questionnaire.GET(":id", a.QuestionnaireAPI.Get)
questionnaire.POST("", a.QuestionnaireAPI.Create)
questionnaire.PUT(":id", a.QuestionnaireAPI.Update)
questionnaire.DELETE(":id", a.QuestionnaireAPI.Delete)
}
activityDetail := v1.Group("activity-details")
{
activityDetail.GET("", a.ActivityDetailAPI.Query)
activityDetail.GET(":id", a.ActivityDetailAPI.Get)
activityDetail.POST("", a.ActivityDetailAPI.Create)
activityDetail.PUT(":id", a.ActivityDetailAPI.Update)
activityDetail.DELETE(":id", a.ActivityDetailAPI.Delete)
}
qeustionDetail := v1.Group("qeustion-details")
{
qeustionDetail.GET("", a.QeustionDetailAPI.Query)
qeustionDetail.GET(":id", a.QeustionDetailAPI.Get)
qeustionDetail.POST("", a.QeustionDetailAPI.Create)
qeustionDetail.PUT(":id", a.QeustionDetailAPI.Update)
qeustionDetail.DELETE(":id", a.QeustionDetailAPI.Delete)
}
return nil
}
func (a *Activity) Release(ctx context.Context) error {
return nil
}

View File

@ -0,0 +1,86 @@
package schema
import (
"github.guxuan/haibei/pkg/util"
"time"
)
// Defining the `Activity` struct.
type Activity struct {
util.BaseModel
Title string `json:"title" gorm:"size:128;not null;index;comment:标题"`
Cover string `json:"cover" gorm:"size:2048;not null;comment:封面"`
Images *[]string `json:"images" gorm:"serializer:json;comment:详图数组"`
StartAt *time.Time `json:"startAt" gorm:"not null;comment:开始时间"`
EndAt *time.Time `json:"endAt" gorm:"not null;comment:结束时间"`
EndSignupAt *time.Time `json:"endSignupAt" gorm:"not null;comment:最晚报名时间"`
MaxSignupNum int `json:"maxSignupNum" gorm:"not null;comment:最大报名人数"`
SignupNum int `json:"signupNum" gorm:"not null;default:0;comment:当前报名人数"`
Address string `json:"address" gorm:"size:1024;not null;comment:活动地址"`
Content string `json:"content" gorm:"type:text;not null;comment:活动详情"`
Point int `json:"point" gorm:"not null;default:0;comment:活动所需积分"`
AreaID uint `json:"areaId" gorm:"index;comment:城市id"`
Status string `json:"status" gorm:"size:20;index;comment:状态"`
}
// Defining the query parameters for the `Activity` struct.
type ActivityQueryParam struct {
util.PaginationParam
LikeTitle string `form:"title" `
Status string `form:"status" `
AreaID uint `form:"areaId"`
}
// Defining the query options for the `Activity` struct.
type ActivityQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `Activity` struct.
type ActivityQueryResult struct {
Data Activities
PageResult *util.PaginationResult
}
// Defining the slice of `Activity` struct.
type Activities []*Activity
// Defining the data structure for creating a `Activity` struct.
type ActivityForm struct {
Title string `json:"title" `
Cover string `json:"cover" `
Images *[]string `json:"images" `
StartAt *time.Time `json:"startAt" `
EndAt *time.Time `json:"endAt" `
EndSignupAt *time.Time `json:"endSignupAt" `
MaxSignupNum int `json:"maxSignupNum" `
SignupNum int `json:"signupNum"`
Address string `json:"address" `
Content string `json:"content"`
Point int `json:"point" `
Status string `json:"status" `
AreaID uint `json:"areaId" `
}
// A validation function for the `ActivityForm` struct.
func (a *ActivityForm) Validate() error {
return nil
}
// Convert `ActivityForm` to `Activity` object.
func (a *ActivityForm) FillTo(activity *Activity) error {
activity.Title = a.Title
activity.Cover = a.Cover
activity.Images = a.Images
activity.StartAt = a.StartAt
activity.EndAt = a.EndAt
activity.AreaID = a.AreaID
activity.EndSignupAt = a.EndSignupAt
activity.MaxSignupNum = a.MaxSignupNum
activity.SignupNum = a.SignupNum
activity.Address = a.Address
activity.Content = a.Content
activity.Point = a.Point
activity.Status = a.Status
return nil
}

View File

@ -0,0 +1,55 @@
package schema
import (
"github.guxuan/haibei/pkg/util"
)
// Defining the `ActivityDetail` struct.
type ActivityDetail struct {
util.BaseModel
ActivityID uint `json:"activityId" gorm:"index;"`
CustomerID uint `json:"customerId" gorm:"index;"`
Status string `json:"status" gorm:"size:20;index;comment:状态"`
}
// Defining the query parameters for the `ActivityDetail` struct.
type ActivityDetailQueryParam struct {
util.PaginationParam
ActivityID uint `form:"activityId" `
CustomerID uint `form:"customerId" `
Status string `form:"status" `
}
// Defining the query options for the `ActivityDetail` struct.
type ActivityDetailQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `ActivityDetail` struct.
type ActivityDetailQueryResult struct {
Data ActivityDetails
PageResult *util.PaginationResult
}
// Defining the slice of `ActivityDetail` struct.
type ActivityDetails []*ActivityDetail
// Defining the data structure for creating a `ActivityDetail` struct.
type ActivityDetailForm struct {
ActivityID uint `json:"activityId" `
CustomerID uint `json:"customerId" `
Status string `json:"status" `
}
// A validation function for the `ActivityDetailForm` struct.
func (a *ActivityDetailForm) Validate() error {
return nil
}
// Convert `ActivityDetailForm` to `ActivityDetail` object.
func (a *ActivityDetailForm) FillTo(activityDetail *ActivityDetail) error {
activityDetail.ActivityID = a.ActivityID
activityDetail.CustomerID = a.CustomerID
activityDetail.Status = a.Status
return nil
}

View File

@ -0,0 +1,163 @@
package schema
import (
"github.guxuan/haibei/pkg/util"
)
// Defining the `Activity` struct.
type House struct {
util.BaseModel
Name string `json:"name" gorm:"size:128;not null;index;comment:名字"`
Title string `json:"title" gorm:"size:128;not null;index;comment:标题"`
Cover string `json:"cover" gorm:"size:2048;not null;comment:封面"`
Price int64 `json:"price" gorm:"size:11;comment:价格"`
Labels *[]string `json:"labels" gorm:"serializer:json;comment:标签数组"`
Images *[]string `json:"images" gorm:"serializer:json;comment:详图数组"`
Videos *[]string `json:"videos" gorm:"serializer:json;comment:视频数组"`
WatchAvatars *[]string `json:"watchAvatars" gorm:"serializer:json;comment:围观人数头像"`
WatchNum int `json:"watchNum" gorm:"size:11;comment:围观人数"`
Area float64 `json:"area" gorm:"not null;comment:占地面积"`
OpenAt string `json:"openAt" gorm:"comment:开盘时间"`
MasterType string `json:"masterType" gorm:"comment:主力户型"`
Address string `json:"address" gorm:"size:1024;not null;comment:楼盘地址"`
Latitude float64 `json:"latitude" gorm:"comment:经度"`
Longitude float64 `json:"longitude" gorm:"comment:维度"`
LayOuts *[]LayOut `json:"layOuts" gorm:"serializer:json;comment:户型图数组"`
Advisers *[]Adviser `json:"advisers" gorm:"serializer:json;comment:顾问数组"`
AreaID uint `json:"areaId" gorm:"index;comment:城市id"`
Detail Detail `json:"detail" gorm:"serializer:json;comment:项目详情"`
Surroundings *Surroundings `json:"surroundings" gorm:"serializer:json;comment:周边设施"`
Status string `json:"status" gorm:"size:20;index;comment:状态"`
}
type Detail struct {
BasicInfo BasicInfo `json:"basicInfo"`
SalesInfo SalesInfo `json:"salesInfo"`
CommunityInfo CommunityInfo `json:"communityInfo"`
}
type BasicInfo struct {
Area string `json:"area"`
Address string `json:"address"`
Typer string `json:"type"`
UnitStruct string `json:"unitStruct"`
Status string `json:"status"`
MasterType string `json:"masterType"`
ShowAddress string `json:"showAddress"`
BuildingArea string `json:"buildingarea"`
}
type SalesInfo struct {
Status string `json:"status"`
Duration string `json:"duration"`
SalesType string `json:"salesType"`
SalesAddress string `json:"salesAddress"`
SalesPhone string `json:"salesPhone"`
}
type CommunityInfo struct {
PackingNum string `json:"packingNum"`
RoomNUM string `json:"roomNUM"`
GreeningRate string `json:"greeningRate"`
R19009Ratio string `json:"r19009Ratio"`
R19010Ratio string `json:"r19010Ratio"`
R19011Ratio string `json:"r19011Ratio"`
PropertyType string `json:"propertyType"`
PropertyName string `json:"propertyName"`
PropertyPrice string `json:"propertyPrice"`
}
type Surroundings struct {
BusNum int `json:"busNum"`
SchoolNum int `json:"schoolNum"`
HospitalNum int `json:"hospitalNum"`
LifeNum int `json:"lifeNum"`
MetroNum int `json:"metroNum"`
}
type LayOut struct {
Img string `json:"img"`
Title string `json:"title"`
Price string `json:"price"`
Labels *[]string `json:"labels"`
Area float64 `json:"area"`
Direction string `json:"direction"`
}
type Adviser struct {
Avatar string `json:"avatar"`
Name string `json:"name"`
Phone string `json:"phone"`
}
// Defining the query parameters for the `Activity` struct.
type HouseQueryParam struct {
util.PaginationParam
LikeName string `form:"name" `
LikeTitle string `form:"title" `
Status string `form:"status" `
AreaID uint `form:"areaId"`
}
// Defining the query options for the `Activity` struct.
type HouseQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `Activity` struct.
type HouseQueryResult struct {
Data Houses
PageResult *util.PaginationResult
}
// Defining the slice of `Activity` struct.
type Houses []*House
// Defining the data structure for creating a `Activity` struct.
type HouseForm struct {
Name string `json:"name" `
Title string `json:"title" `
Cover string `json:"cover" `
Price int64 `json:"price" `
Labels *[]string `json:"labels" `
Images *[]string `json:"images" `
Videos *[]string `json:"videos"`
WatchAvatars *[]string `json:"watchAvatars" `
WatchNum int `json:"watchNum" `
Area float64 `json:"area" `
OpenAt string `json:"openAt"`
MasterType string `json:"masterType" `
Address string `json:"address" `
Latitude float64 `json:"latitude" `
Longitude float64 `json:"longitude" `
LayOuts *[]LayOut `json:"layOuts" `
Advisers *[]Adviser `json:"advisers" `
AreaID uint `json:"areaId" `
Detail Detail `json:"detail" `
Surroundings *Surroundings `json:"surroundings"`
Status string `json:"status" `
}
// A validation function for the `ActivityForm` struct.
func (a *HouseForm) Validate() error {
return nil
}
// Convert `ActivityForm` to `Activity` object.
func (a *HouseForm) FillTo(house *House) error {
house.Name = a.Name
house.Title = a.Title
house.Cover = a.Cover
house.Price = a.Price
house.Labels = a.Labels
house.Images = a.Images
house.Videos = a.Videos
house.WatchAvatars = a.WatchAvatars
house.WatchNum = a.WatchNum
house.Area = a.Area
house.OpenAt = a.OpenAt
house.MasterType = a.MasterType
house.Address = a.Address
house.Latitude = a.Latitude
house.Longitude = a.Longitude
house.LayOuts = a.LayOuts
house.Advisers = a.Advisers
house.AreaID = a.AreaID
house.Detail = a.Detail
house.Status = a.Status
return nil
}

View File

@ -0,0 +1,67 @@
package schema
import (
"github.guxuan/haibei/pkg/util"
)
// Defining the `Activity` struct.
type HouseArticle struct {
util.BaseModel
HouseID uint `json:"houseId" gorm:"index;comment:房源id"`
Title string `json:"title" gorm:"size:128;not null;index;comment:标题"`
Cover string `json:"cover" gorm:"size:2048;not null;comment:封面"`
Name string `json:"name" gorm:"size:1024;comment:作者名字"`
PushAt string `json:"pushAt" gorm:"index;comment:发布时间"`
Content string `json:"content" gorm:"type:text;comment:内容详情"`
Status string `json:"status" gorm:"size:20;index;comment:状态"`
}
// Defining the query parameters for the `Activity` struct.
type HouseArticleQueryParam struct {
util.PaginationParam
LikeName string `form:"name" `
LikeTitle string `form:"title" `
Status string `form:"status" `
AreaID uint `form:"areaId"`
}
// Defining the query options for the `Activity` struct.
type HouseArticleQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `Activity` struct.
type HouseArticleQueryResult struct {
Data HouseArticles
PageResult *util.PaginationResult
}
// Defining the slice of `Activity` struct.
type HouseArticles []*HouseArticle
// Defining the data structure for creating a `Activity` struct.
type HouseArticleForm struct {
HouseID uint `json:"houseId"`
Title string `json:"title"`
Cover string `json:"cover"`
Name string `json:"name"`
PushAt string `json:"pushAt"`
Content string `json:"content"`
Status string `json:"status"`
}
// A validation function for the `ActivityForm` struct.
func (a *HouseArticleForm) Validate() error {
return nil
}
// Convert `ActivityForm` to `Activity` object.
func (a *HouseArticleForm) FillTo(houseArticle *HouseArticle) error {
houseArticle.Name = a.Name
houseArticle.Title = a.Title
houseArticle.Cover = a.Cover
houseArticle.PushAt = a.PushAt
houseArticle.Content = a.Content
houseArticle.Status = a.Status
return nil
}

View File

@ -0,0 +1,66 @@
package schema
import (
"github.guxuan/haibei/pkg/util"
)
// Defining the `QeustionDetail` struct.
type QeustionDetail struct {
util.BaseModel
QuestionID uint `json:"questionId" gorm:"index;"`
CustomerID uint `json:"customerId" gorm:"index;"`
Content *[]QuestionDetailTable `json:"content" gorm:"serializer:json;comment:问卷表单详情"`
Status string `json:"status" gorm:"size:20;index;comment:状态"`
}
type QuestionDetailTable struct {
Label string `json:"label"`
Typer string `json:"type"`
Required bool `json:"required"`
Options []string `json:"options"`
Answer string `json:"answer"`
}
// Defining the query parameters for the `QeustionDetail` struct.
type QeustionDetailQueryParam struct {
util.PaginationParam
QuestionID uint `form:"questionId" `
CustomerID uint `form:"customerId" `
Status string `form:"status" `
}
// Defining the query options for the `QeustionDetail` struct.
type QeustionDetailQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `QeustionDetail` struct.
type QeustionDetailQueryResult struct {
Data QeustionDetails
PageResult *util.PaginationResult
}
// Defining the slice of `QeustionDetail` struct.
type QeustionDetails []*QeustionDetail
// Defining the data structure for creating a `QeustionDetail` struct.
type QeustionDetailForm struct {
QuestionID uint `json:"questionId" `
CustomerID uint `json:"customerId" `
Content *[]QuestionDetailTable `json:"content" `
Status string `json:"status" `
}
// A validation function for the `QeustionDetailForm` struct.
func (a *QeustionDetailForm) Validate() error {
return nil
}
// Convert `QeustionDetailForm` to `QeustionDetail` object.
func (a *QeustionDetailForm) FillTo(qeustionDetail *QeustionDetail) error {
qeustionDetail.CustomerID = a.CustomerID
qeustionDetail.QuestionID = a.QuestionID
qeustionDetail.Content = a.Content
qeustionDetail.Status = a.Status
return nil
}

View File

@ -0,0 +1,78 @@
package schema
import (
"time"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Questionnaire` struct.
type Questionnaire struct {
util.BaseModel
Title string `json:"title" gorm:"size:128;not null;index;comment:标题"`
Cover string `json:"cover" gorm:"size:2048;not null;comment:封面"`
StartAt *time.Time `json:"startAt" gorm:"not null;comment:开始时间"`
EndAt *time.Time `json:"endAt" gorm:"not null;comment:结束时间"`
Content *[]QuestionnaireTable `json:"content" gorm:"serializer:json;comment:问卷表单详情"`
Point int `json:"point" gorm:"not null;default:0;comment:问卷获得积分积分"`
AreaID uint `json:"areaId" gorm:"index;comment:城市id"`
Status string `json:"status" gorm:"size:20;index;comment:状态"`
}
type QuestionnaireTable struct {
Label string `json:"label"`
Typer string `json:"type"`
Required bool `json:"required"`
Options []string `json:"options"`
}
// Defining the query parameters for the `Questionnaire` struct.
type QuestionnaireQueryParam struct {
util.PaginationParam
LikeTitle string `form:"title" `
Status string `form:"status"`
AreaID uint `form:"areaId"`
}
// Defining the query options for the `Questionnaire` struct.
type QuestionnaireQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `Questionnaire` struct.
type QuestionnaireQueryResult struct {
Data Questionnaires
PageResult *util.PaginationResult
}
// Defining the slice of `Questionnaire` struct.
type Questionnaires []*Questionnaire
// Defining the data structure for creating a `Questionnaire` struct.
type QuestionnaireForm struct {
Title string `json:"title" `
Cover string `json:"cover"`
StartAt *time.Time `json:"startAt"`
EndAt *time.Time `json:"endAt"`
AreaID uint `json:"areaId"`
Content *[]QuestionnaireTable `json:"content"`
Point int `json:"point" `
Status string `json:"status"`
}
// A validation function for the `QuestionnaireForm` struct.
func (a *QuestionnaireForm) Validate() error {
return nil
}
// Convert `QuestionnaireForm` to `Questionnaire` object.
func (a *QuestionnaireForm) FillTo(questionnaire *Questionnaire) error {
questionnaire.Title = a.Title
questionnaire.Cover = a.Cover
questionnaire.StartAt = a.StartAt
questionnaire.EndAt = a.EndAt
questionnaire.AreaID = a.AreaID
questionnaire.Content = a.Content
questionnaire.Point = a.Point
questionnaire.Status = a.Status
return nil
}

View File

@ -0,0 +1,24 @@
package activity
import (
"github.com/google/wire"
"github.guxuan/haibei/internal/mods/activity/api"
"github.guxuan/haibei/internal/mods/activity/biz"
"github.guxuan/haibei/internal/mods/activity/dal"
)
var Set = wire.NewSet(
wire.Struct(new(Activity), "*"),
wire.Struct(new(dal.Activity), "*"),
wire.Struct(new(biz.Activity), "*"),
wire.Struct(new(api.Activity), "*"),
wire.Struct(new(dal.Questionnaire), "*"),
wire.Struct(new(biz.Questionnaire), "*"),
wire.Struct(new(api.Questionnaire), "*"),
wire.Struct(new(dal.ActivityDetail), "*"),
wire.Struct(new(biz.ActivityDetail), "*"),
wire.Struct(new(api.ActivityDetail), "*"),
wire.Struct(new(dal.QeustionDetail), "*"),
wire.Struct(new(biz.QeustionDetail), "*"),
wire.Struct(new(api.QeustionDetail), "*"),
)

View File

@ -0,0 +1,136 @@
package api
import (
"github.com/gin-gonic/gin"
activityBiz "github.guxuan/haibei/internal/mods/activity/biz"
"github.guxuan/haibei/internal/mods/app/biz"
commonBiz "github.guxuan/haibei/internal/mods/common/biz"
commonSchema "github.guxuan/haibei/internal/mods/common/schema"
customerBiz "github.guxuan/haibei/internal/mods/customer/biz"
customerSchema "github.guxuan/haibei/internal/mods/customer/schema"
ProductBiz "github.guxuan/haibei/internal/mods/product/biz"
"github.guxuan/haibei/pkg/util"
)
// Defining the `App` api.
type App struct {
AppBIZ *biz.App
CustomerBIZ *customerBiz.Customer
BannerBIZ *commonBiz.Banner
ActivityBIZ *activityBiz.Activity
QuestionnaireBIZ *activityBiz.Questionnaire
ProductBIZ *ProductBiz.Product
}
// @Tags APP端
// @Security ApiKeyAuth
// @Summary 小程序登陆
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/apps/login [post]
func (a *App) Login(c *gin.Context) {
ctx := c.Request.Context()
item := new(customerSchema.CustomerLoginForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
}
data, err := a.CustomerBIZ.Login(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, data)
}
// @Tags APP端
// @Security ApiKeyAuth
// @Summary 发送验证码
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/apps/sms/{phone} [get]
func (a *App) SendSms(c *gin.Context) {
ctx := c.Request.Context()
phone := c.Param("phone")
data, err := a.CustomerBIZ.SendSms(ctx, phone)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, data)
}
// @Tags APP端
// @Security ApiKeyAuth
// @Summary 小程序绑定手机号
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/apps/bind [post]
func (a *App) BindPhone(c *gin.Context) {
ctx := c.Request.Context()
item := new(customerSchema.CustomerBindPhoneForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
}
data, err := a.CustomerBIZ.BindPhone(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, data)
}
// @Tags APP端
// @Security ApiKeyAuth
// @Summary 首页banner
// @Success 200 {object} util.ResponseResult{data=[]commonSchema.Banner}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/apps/banner [get]
func (a *App) GetBannerList(c *gin.Context) {
ctx := c.Request.Context()
item := new(commonSchema.BannerQueryParam)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
}
data, err := a.BannerBIZ.Query(ctx, *item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, data)
}
// @Tags APP端
// @Security ApiKeyAuth
// @Summary 首页接口
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/apps/home [post]
func (a *App) HomeDetails(c *gin.Context) {
ctx := c.Request.Context()
uid, err := a.AppBIZ.GetLoginUid(ctx)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, uid)
}
// @Tags APP端
// @Security ApiKeyAuth
// @Summary 首页接口
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/apps/mine [post]
func (a *App) MineDetails(c *gin.Context) {
//ctx := c.Request.Context()
}

View File

@ -0,0 +1,9 @@
package backResp
import "github.guxuan/haibei/internal/mods/common/schema"
type HomePage struct {
BannerList schema.Banners `json:"bannerList"`
NoticeList schema.Notices `json:"noticeList"`
ActivityList schema.Notices `json:"activityList"`
}

View File

@ -0,0 +1,209 @@
package biz
import (
"context"
"errors"
"fmt"
"gorm.io/gorm"
"strconv"
"time"
//"time"
"github.guxuan/haibei/internal/mods/app/dal"
//"github.guxuan/haibei/internal/mods/app/schema"
activityDal "github.guxuan/haibei/internal/mods/activity/dal"
activitySchema "github.guxuan/haibei/internal/mods/activity/schema"
commonDal "github.guxuan/haibei/internal/mods/common/dal"
commonSchema "github.guxuan/haibei/internal/mods/common/schema"
customerDal "github.guxuan/haibei/internal/mods/customer/dal"
customerSchema "github.guxuan/haibei/internal/mods/customer/schema"
productDal "github.guxuan/haibei/internal/mods/product/dal"
productSchema "github.guxuan/haibei/internal/mods/product/schema"
//"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
// Defining the `App` business logic.
type App struct {
DB *gorm.DB
Trans *util.Trans
AppDAL *dal.App
BannerDal *commonDal.Banner
NoticeDal *commonDal.Notice
ProductDal *productDal.Product
ProductCategoryDal *productDal.ProductCategory
ProductOrderDal *customerDal.ProductOrder
ActivityDal *activityDal.Activity
ActivityDetailDal *activityDal.ActivityDetail
QuestionnaireDal *activityDal.Questionnaire
QeustionDetailDal *activityDal.QeustionDetail
CustomerDal *customerDal.Customer
BalanceDal *customerDal.Balance
}
func (a *App) QueryBannerList(ctx context.Context, areaId uint) (*[]commonSchema.Banner, error) {
query := commonDal.GetBannerDB(ctx, a.DB)
if areaId > 0 {
query.Where("area_id = ?", areaId)
}
var list []commonSchema.Banner
query.Order("sequence DESC").Limit(3).Find(&list)
return &list, nil
}
func (a *App) QueryNoticeList(ctx context.Context, areaId uint) (*[]commonSchema.Notice, error) {
query := commonDal.GetNoticeDB(ctx, a.DB)
if areaId > 0 {
query.Where("area_id = ?", areaId)
}
var list []commonSchema.Notice
query.Order("sequence DESC").Limit(6).Find(&list)
return &list, nil
}
func (a *App) QueryHomeProductList(ctx context.Context, isHot bool, areaId uint) (*[]productSchema.Product, error) {
query := productDal.GetProductDB(ctx, a.DB).Preload("Category").Where("status = ?", "enabled")
query.Where("area_id = ?", areaId)
if isHot {
query.Where("is_hot = ?", 1)
}
var list []productSchema.Product
query.Order("createAt DESC").Find(&list)
return &list, nil
}
func (a *App) QueryProductDetails(ctx context.Context, id uint) (productSchema.Product, error) {
query := productDal.GetProductDB(ctx, a.DB).Preload("Category").Where("id = ?", id)
var info productSchema.Product
query.First(&info)
return info, nil
}
func (a *App) QueryHomeActivityList(ctx context.Context, areaId uint) (activitySchema.Activities, error) {
query := activityDal.GetActivityDB(ctx, a.DB).Where("status = ?", "enabled")
query.Where("area_id = ?", areaId)
var list activitySchema.Activities
query.Order("createAt DESC").Find(list)
return list, nil
}
func (a *App) QueryActivityDetails(ctx context.Context, customerId, id uint) (activitySchema.Activity, *activitySchema.ActivityDetail, error) {
query := activityDal.GetActivityDB(ctx, a.DB).Where("id = ?", id)
var info activitySchema.Activity
query.First(&info)
result, _ := a.ActivityDetailDal.GetByCustomerIDAndActivityID(ctx, customerId, id)
return info, result, nil
}
func (a *App) QueryHomeQuestionsList(ctx context.Context, areaId uint) (activitySchema.Questionnaires, error) {
query := activityDal.GetQuestionnaireDB(ctx, a.DB).Where("status = ?", "enabled")
query.Where("area_id = ?", areaId)
var list activitySchema.Questionnaires
query.Order("createAt DESC").Find(list)
return list, nil
}
func (a *App) QueryQuestionsDetails(ctx context.Context, customerId, id uint) (activitySchema.Questionnaire, *activitySchema.QeustionDetail, error) {
query := activityDal.GetQuestionnaireDB(ctx, a.DB).Where("id = ?", id)
var info activitySchema.Questionnaire
query.First(&info)
result, _ := a.QeustionDetailDal.GetByCustomerIDAndActivityID(ctx, customerId, id)
return info, result, nil
}
func (a *App) AddProductToCustomer(ctx context.Context, customerID, productID, num uint) error {
customer, err2 := a.CustomerDal.Get(ctx, customerID, customerSchema.CustomerQueryOptions{})
if err2 != nil {
return errors.New("用户未找到")
}
product, err := a.ProductDal.Get(ctx, productID, productSchema.ProductQueryOptions{})
if err != nil {
return errors.New("商品未找到")
}
if product.Stock < int(num) {
return errors.New("商品库存不足")
}
if product.Status != "enabled" {
return errors.New("商品状态不可用")
}
if product.ExpireAt.Before(time.Now()) {
return errors.New("商品已过期")
}
if customer.Balance < product.Price*int(num) {
return errors.New("积分不足")
}
info, err := a.ProductOrderDal.ExistsByCustomerID(ctx, customerID, productID)
if err != nil {
return errors.New("系统繁忙,请稍后再试!")
}
if info != nil && len(*info) >= product.MaxNum {
return errors.New("兑换数量已达到上限")
}
orderInfo := customerSchema.ProductOrder{
CustomerID: customerID,
ProductID: productID,
MentorID: customer.MentorID,
Status: "UNCHECK",
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
//创建商品订单
err = a.ProductOrderDal.Create(ctx, &orderInfo)
if err != nil {
return errors.New("系统繁忙,请稍后再试!")
}
//修改库存
product.Stock--
err = a.ProductDal.Update(ctx, product)
if err != nil {
return errors.New("系统繁忙,请稍后再试!")
}
//积分变动
oldBalance := customer.Balance
change := product.Price * int(num)
newBalance := oldBalance - change
customer.Balance = newBalance
err = a.CustomerDal.Update(ctx, customer)
if err != nil {
return errors.New("系统繁忙,请稍后再试!")
}
var record = customerSchema.Balance{
CustomerID: customerID,
Before: oldBalance,
After: newBalance,
Change: -change,
Reason: fmt.Sprintf("用户通过小程序兑换商品-%s", product.Name),
Typer: "兑换商品",
OperatorID: productID,
CreatorID: "",
}
err = a.BalanceDal.Create(ctx, &record)
if err != nil {
return errors.New("系统繁忙,请稍后再试!")
}
return nil
})
}
func (a *App) RegisterActivity(ctx context.Context, customerID, activityID uint) error {
return nil
}
func (a *App) RegisterQuestion(ctx context.Context, customerID, questionID uint, questionBody *[]activitySchema.QuestionDetailTable) error {
return nil
}
func (a *App) GetLoginUid(ctx context.Context) (uint, error) {
userID := util.FromUserID(ctx)
u64, err := strconv.ParseUint(fmt.Sprintf("%v", userID), 10, 64)
if err != nil {
fmt.Println("转换错误:", err)
return 0, errors.New("登录id获取失败")
}
return uint(u64), nil
}

View File

@ -0,0 +1,83 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/app/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get app storage instance
func GetAppDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.App))
}
// Defining the `App` data access object.
type App struct {
DB *gorm.DB
}
// Query apps from the database based on the provided parameters and options.
func (a *App) Query(ctx context.Context, params schema.AppQueryParam, opts ...schema.AppQueryOptions) (*schema.AppQueryResult, error) {
var opt schema.AppQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetAppDB(ctx, a.DB)
var list schema.Apps
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.AppQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified app from the database.
func (a *App) Get(ctx context.Context, id string, opts ...schema.AppQueryOptions) (*schema.App, error) {
var opt schema.AppQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.App)
ok, err := util.FindOne(ctx, GetAppDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified app exists in the database.
func (a *App) Exists(ctx context.Context, id string) (bool, error) {
ok, err := util.Exists(ctx, GetAppDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new app.
func (a *App) Create(ctx context.Context, item *schema.App) error {
result := GetAppDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified app in the database.
func (a *App) Update(ctx context.Context, item *schema.App) error {
result := GetAppDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified app from the database.
func (a *App) Delete(ctx context.Context, id string) error {
result := GetAppDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.App))
return errors.WithStack(result.Error)
}

44
internal/mods/app/main.go Normal file
View File

@ -0,0 +1,44 @@
package app
import (
"context"
"github.guxuan/haibei/internal/config"
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/app/api"
"github.guxuan/haibei/internal/mods/app/schema"
"gorm.io/gorm"
)
type App struct {
DB *gorm.DB
AppAPI *api.App
}
func (a *App) AutoMigrate(ctx context.Context) error {
return a.DB.AutoMigrate(new(schema.App))
}
func (a *App) Init(ctx context.Context) error {
if config.C.Storage.DB.AutoMigrate {
if err := a.AutoMigrate(ctx); err != nil {
return err
}
}
return nil
}
func (a *App) RegisterV1Routers(ctx context.Context, v1 *gin.RouterGroup) error {
app := v1.Group("apps")
{
app.POST("login", a.AppAPI.Login)
app.GET("sms/:phone", a.AppAPI.SendSms)
app.POST("bind", a.AppAPI.BindPhone)
}
return nil
}
func (a *App) Release(ctx context.Context) error {
return nil
}

View File

@ -0,0 +1,47 @@
package schema
import (
"time"
"github.guxuan/haibei/pkg/util"
)
// Defining the `App` struct.
type App struct {
ID string `json:"id" gorm:"size:20;primaryKey;"` // Unique ID
CreatedAt time.Time `json:"created_at" gorm:"index;"` // Create time
UpdatedAt time.Time `json:"updated_at" gorm:"index;"` // Update time
}
// Defining the query parameters for the `App` struct.
type AppQueryParam struct {
util.PaginationParam
}
// Defining the query options for the `App` struct.
type AppQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `App` struct.
type AppQueryResult struct {
Data Apps
PageResult *util.PaginationResult
}
// Defining the slice of `App` struct.
type Apps []*App
// Defining the data structure for creating a `App` struct.
type AppForm struct {
}
// A validation function for the `AppForm` struct.
func (a *AppForm) Validate() error {
return nil
}
// Convert `AppForm` to `App` object.
func (a *AppForm) FillTo(app *App) error {
return nil
}

15
internal/mods/app/wire.go Normal file
View File

@ -0,0 +1,15 @@
package app
import (
"github.com/google/wire"
"github.guxuan/haibei/internal/mods/app/api"
"github.guxuan/haibei/internal/mods/app/biz"
"github.guxuan/haibei/internal/mods/app/dal"
)
var Set = wire.NewSet(
wire.Struct(new(App), "*"),
wire.Struct(new(dal.App), "*"),
wire.Struct(new(biz.App), "*"),
wire.Struct(new(api.App), "*"),
)

View File

@ -0,0 +1,145 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/common/biz"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Area` api.
type Area struct {
AreaBIZ *biz.Area
}
// @Tags 区域模块
// @Security ApiKeyAuth
// @Summary Query area list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.Area}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/areas [get]
func (a *Area) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.AreaQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.AreaBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags 区域模块
// @Security ApiKeyAuth
// @Summary Get area record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.Area}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/areas/{id} [get]
func (a *Area) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.AreaBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags 区域模块
// @Security ApiKeyAuth
// @Summary Create area record
// @Param body body schema.AreaForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.Area}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/areas [post]
func (a *Area) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.AreaForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.AreaBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags 区域模块
// @Security ApiKeyAuth
// @Summary Update area record by ID
// @Param id path string true "unique id"
// @Param body body schema.AreaForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/areas/{id} [put]
func (a *Area) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.AreaForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.AreaBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags 区域模块
// @Security ApiKeyAuth
// @Summary Delete area record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/areas/{id} [delete]
func (a *Area) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.AreaBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,144 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/common/biz"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Banner` api.
type Banner struct {
BannerBIZ *biz.Banner
}
// @Tags 首页轮播图模块
// @Security ApiKeyAuth
// @Summary Query banner list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.Banner}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/banners [get]
func (a *Banner) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.BannerQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.BannerBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags 首页轮播图模块
// @Security ApiKeyAuth
// @Summary Get banner record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.Banner}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/banners/{id} [get]
func (a *Banner) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.BannerBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags 首页轮播图模块
// @Security ApiKeyAuth
// @Summary Create banner record
// @Param body body schema.BannerForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.Banner}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/banners [post]
func (a *Banner) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.BannerForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.BannerBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags 首页轮播图模块
// @Security ApiKeyAuth
// @Summary Update banner record by ID
// @Param id path string true "unique id"
// @Param body body schema.BannerForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/banners/{id} [put]
func (a *Banner) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.BannerForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.BannerBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags 首页轮播图模块
// @Security ApiKeyAuth
// @Summary Delete banner record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/banners/{id} [delete]
func (a *Banner) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.BannerBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,145 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/common/biz"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Common` api.
type Common struct {
CommonBIZ *biz.Common
}
// @Tags CommonAPI
// @Security ApiKeyAuth
// @Summary Query common list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.Common}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/commons [get]
func (a *Common) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.CommonQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.CommonBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags CommonAPI
// @Security ApiKeyAuth
// @Summary Get common record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.Common}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/commons/{id} [get]
func (a *Common) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.CommonBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags CommonAPI
// @Security ApiKeyAuth
// @Summary Create common record
// @Param body body schema.CommonForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.Common}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/commons [post]
func (a *Common) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.CommonForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.CommonBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags CommonAPI
// @Security ApiKeyAuth
// @Summary Update common record by ID
// @Param id path string true "unique id"
// @Param body body schema.CommonForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/commons/{id} [put]
func (a *Common) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.CommonForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.CommonBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags CommonAPI
// @Security ApiKeyAuth
// @Summary Delete common record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/commons/{id} [delete]
func (a *Common) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.CommonBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,145 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/common/biz"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Company` api.
type Company struct {
CompanyBIZ *biz.Company
}
// @Tags 项目模块
// @Security ApiKeyAuth
// @Summary Query company list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.Company}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/companies [get]
func (a *Company) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.CompanyQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.CompanyBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags 项目模块
// @Security ApiKeyAuth
// @Summary Get company record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.Company}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/companies/{id} [get]
func (a *Company) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.CompanyBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags 项目模块
// @Security ApiKeyAuth
// @Summary Create company record
// @Param body body schema.CompanyForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.Company}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/companies [post]
func (a *Company) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.CompanyForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.CompanyBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags 项目模块
// @Security ApiKeyAuth
// @Summary Update company record by ID
// @Param id path string true "unique id"
// @Param body body schema.CompanyForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/companies/{id} [put]
func (a *Company) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.CompanyForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.CompanyBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags 项目模块
// @Security ApiKeyAuth
// @Summary Delete company record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/companies/{id} [delete]
func (a *Company) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.CompanyBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,138 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/common/biz"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Notice` api.
type Notice struct {
NoticeBIZ *biz.Notice
}
// @Tags 公告模块
// @Security ApiKeyAuth
// @Summary Query notice list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.Notice}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/notices [get]
func (a *Notice) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.NoticeQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.NoticeBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags 公告模块
// @Security ApiKeyAuth
// @Summary Get notice record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.Notice}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/notices/{id} [get]
func (a *Notice) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.NoticeBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags 公告模块
// @Security ApiKeyAuth
// @Summary Create notice record
// @Param body body schema.NoticeForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.Notice}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/notices [post]
func (a *Notice) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.NoticeForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
}
result, err := a.NoticeBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags 公告模块
// @Security ApiKeyAuth
// @Summary Update notice record by ID
// @Param id path string true "unique id"
// @Param body body schema.NoticeForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/notices/{id} [put]
func (a *Notice) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.NoticeForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.NoticeBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags 公告模块
// @Security ApiKeyAuth
// @Summary Delete notice record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/notices/{id} [delete]
func (a *Notice) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.NoticeBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,198 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/common/biz"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Company` api.
type ReceptionCenter struct {
ReceptionCenterBIZ *biz.ReceptionCenter
}
// @Tags 楼盘模块
// @Security ApiKeyAuth
// @Summary Query ReceptionCenter list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.ReceptionCenter}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/reception_center [get]
func (a *ReceptionCenter) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.ReceptionCenterQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.ReceptionCenterBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags 楼盘模块
// @Security ApiKeyAuth
// @Summary Get ReceptionCenter record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.ReceptionCenter}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/reception_center/{id} [get]
func (a *ReceptionCenter) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.ReceptionCenterBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags 楼盘模块
// @Security ApiKeyAuth
// @Summary Create ReceptionCenter record
// @Param body body schema.ReceptionCenterForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.ReceptionCenter}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/reception_center [post]
func (a *ReceptionCenter) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.ReceptionCenterForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.ReceptionCenterBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags 楼盘模块
// @Security ApiKeyAuth
// @Summary Update ReceptionCenter record by ID
// @Param id path string true "unique id"
// @Param body body schema.ReceptionCenterForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/reception_center/{id} [put]
func (a *ReceptionCenter) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.ReceptionCenterForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.ReceptionCenterBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags 楼盘模块
// @Security ApiKeyAuth
// @Summary Delete ReceptionCenter record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/reception_center/{id} [delete]
func (a *ReceptionCenter) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.ReceptionCenterBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags 楼盘模块
// @Security ApiKeyAuth
// @Summary Get ReceptionCenter QrCode by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=[]byte}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/reception_center/qr_code/{id} [get]
func (a *ReceptionCenter) GetQrCode(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
qrcode, err := a.ReceptionCenterBIZ.GetQrCode(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, qrcode)
}
// @Tags 楼盘模块
// @Security ApiKeyAuth
// @Summary check QrCode
// @Param body body CheckQrCodeStruct true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/reception_center [post]
func (a *ReceptionCenter) CheckQrCode(c *gin.Context) {
ctx := c.Request.Context()
item := new(CheckQrCodeStruct)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
}
err := a.ReceptionCenterBIZ.CheckQrcode(ctx, item.CustomerID, item.ReceptionCenterID)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
type CheckQrCodeStruct struct {
CustomerID uint `json:"customer_id"`
ReceptionCenterID uint `json:"reception_center_id"`
}

View File

@ -0,0 +1,24 @@
package api
import (
"fmt"
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/config"
"github.guxuan/haibei/internal/mods/common/biz"
"github.guxuan/haibei/pkg/util"
)
type Upload struct {
UploadBIZ *biz.Upload
}
func (a *Upload) SaveFile(c *gin.Context) {
file, err := c.FormFile("file")
if err != nil {
util.ResError(c, err)
return
}
result, err := a.UploadBIZ.SaveFile(c, file)
fileURL := fmt.Sprintf("%s/%s", config.C.FileConfig.StaticPrefix, result)
util.ResSuccess(c, fileURL)
}

View File

@ -0,0 +1,104 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/common/dal"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Area` business logic.
type Area struct {
Trans *util.Trans
AreaDAL *dal.Area
}
// Query areas from the data access object based on the provided parameters and options.
func (a *Area) Query(ctx context.Context, params schema.AreaQueryParam) (*schema.AreaQueryResult, error) {
params.Pagination = true
result, err := a.AreaDAL.Query(ctx, params, schema.AreaQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified area from the data access object.
func (a *Area) Get(ctx context.Context, id uint) (*schema.Area, error) {
area, err := a.AreaDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if area == nil {
return nil, errors.NotFound("", "Area not found")
}
return area, nil
}
// Create a new area in the data access object.
func (a *Area) Create(ctx context.Context, formItem *schema.AreaForm) (*schema.Area, error) {
area := &schema.Area{}
if err := formItem.FillTo(area); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.AreaDAL.Create(ctx, area); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return area, nil
}
// Update the specified area in the data access object.
func (a *Area) Update(ctx context.Context, id uint, formItem *schema.AreaForm) error {
area, err := a.AreaDAL.Get(ctx, id)
if err != nil {
return err
} else if area == nil {
return errors.NotFound("", "Area not found")
}
if err := formItem.FillTo(area); err != nil {
return err
}
area.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.AreaDAL.Update(ctx, area); err != nil {
return err
}
return nil
})
}
// Delete the specified area from the data access object.
func (a *Area) Delete(ctx context.Context, id uint) error {
exists, err := a.AreaDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Area not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.AreaDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,104 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/common/dal"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Banner` business logic.
type Banner struct {
Trans *util.Trans
BannerDAL *dal.Banner
}
// Query banners from the data access object based on the provided parameters and options.
func (a *Banner) Query(ctx context.Context, params schema.BannerQueryParam) (*schema.BannerQueryResult, error) {
params.Pagination = true
result, err := a.BannerDAL.Query(ctx, params, schema.BannerQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified banner from the data access object.
func (a *Banner) Get(ctx context.Context, id uint) (*schema.Banner, error) {
banner, err := a.BannerDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if banner == nil {
return nil, errors.NotFound("", "Banner not found")
}
return banner, nil
}
// Create a new banner in the data access object.
func (a *Banner) Create(ctx context.Context, formItem *schema.BannerForm) (*schema.Banner, error) {
banner := &schema.Banner{}
if err := formItem.FillTo(banner); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.BannerDAL.Create(ctx, banner); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return banner, nil
}
// Update the specified banner in the data access object.
func (a *Banner) Update(ctx context.Context, id uint, formItem *schema.BannerForm) error {
banner, err := a.BannerDAL.Get(ctx, id)
if err != nil {
return err
} else if banner == nil {
return errors.NotFound("", "Banner not found")
}
if err := formItem.FillTo(banner); err != nil {
return err
}
banner.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.BannerDAL.Update(ctx, banner); err != nil {
return err
}
return nil
})
}
// Delete the specified banner from the data access object.
func (a *Banner) Delete(ctx context.Context, id uint) error {
exists, err := a.BannerDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Banner not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.BannerDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,107 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/common/dal"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Common` business logic.
type Common struct {
Trans *util.Trans
CommonDAL *dal.Common
}
// Query commons from the data access object based on the provided parameters and options.
func (a *Common) Query(ctx context.Context, params schema.CommonQueryParam) (*schema.CommonQueryResult, error) {
params.Pagination = true
result, err := a.CommonDAL.Query(ctx, params, schema.CommonQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified common from the data access object.
func (a *Common) Get(ctx context.Context, id uint) (*schema.Common, error) {
common, err := a.CommonDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if common == nil {
return nil, errors.NotFound("", "Common not found")
}
return common, nil
}
// Create a new common in the data access object.
func (a *Common) Create(ctx context.Context, formItem *schema.CommonForm) (*schema.Common, error) {
common := &schema.Common{
ID: util.NewXID(),
CreatedAt: time.Now(),
}
if err := formItem.FillTo(common); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.CommonDAL.Create(ctx, common); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return common, nil
}
// Update the specified common in the data access object.
func (a *Common) Update(ctx context.Context, id uint, formItem *schema.CommonForm) error {
common, err := a.CommonDAL.Get(ctx, id)
if err != nil {
return err
} else if common == nil {
return errors.NotFound("", "Common not found")
}
if err := formItem.FillTo(common); err != nil {
return err
}
common.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.CommonDAL.Update(ctx, common); err != nil {
return err
}
return nil
})
}
// Delete the specified common from the data access object.
func (a *Common) Delete(ctx context.Context, id uint) error {
exists, err := a.CommonDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Common not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.CommonDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,104 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/common/dal"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Company` business logic.
type Company struct {
Trans *util.Trans
CompanyDAL *dal.Company
}
// Query companies from the data access object based on the provided parameters and options.
func (a *Company) Query(ctx context.Context, params schema.CompanyQueryParam) (*schema.CompanyQueryResult, error) {
params.Pagination = true
result, err := a.CompanyDAL.Query(ctx, params, schema.CompanyQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified company from the data access object.
func (a *Company) Get(ctx context.Context, id uint) (*schema.Company, error) {
company, err := a.CompanyDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if company == nil {
return nil, errors.NotFound("", "Company not found")
}
return company, nil
}
// Create a new company in the data access object.
func (a *Company) Create(ctx context.Context, formItem *schema.CompanyForm) (*schema.Company, error) {
company := &schema.Company{}
if err := formItem.FillTo(company); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.CompanyDAL.Create(ctx, company); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return company, nil
}
// Update the specified company in the data access object.
func (a *Company) Update(ctx context.Context, id uint, formItem *schema.CompanyForm) error {
company, err := a.CompanyDAL.Get(ctx, id)
if err != nil {
return err
} else if company == nil {
return errors.NotFound("", "Company not found")
}
if err := formItem.FillTo(company); err != nil {
return err
}
company.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.CompanyDAL.Update(ctx, company); err != nil {
return err
}
return nil
})
}
// Delete the specified company from the data access object.
func (a *Company) Delete(ctx context.Context, id uint) error {
exists, err := a.CompanyDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Company not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.CompanyDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,104 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/common/dal"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Notice` business logic.
type Notice struct {
Trans *util.Trans
NoticeDAL *dal.Notice
}
// Query notices from the data access object based on the provided parameters and options.
func (a *Notice) Query(ctx context.Context, params schema.NoticeQueryParam) (*schema.NoticeQueryResult, error) {
params.Pagination = true
result, err := a.NoticeDAL.Query(ctx, params, schema.NoticeQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified notice from the data access object.
func (a *Notice) Get(ctx context.Context, id uint) (*schema.Notice, error) {
notice, err := a.NoticeDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if notice == nil {
return nil, errors.NotFound("", "Notice not found")
}
return notice, nil
}
// Create a new notice in the data access object.
func (a *Notice) Create(ctx context.Context, formItem *schema.NoticeForm) (*schema.Notice, error) {
notice := &schema.Notice{}
if err := formItem.FillTo(notice); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.NoticeDAL.Create(ctx, notice); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return notice, nil
}
// Update the specified notice in the data access object.
func (a *Notice) Update(ctx context.Context, id uint, formItem *schema.NoticeForm) error {
notice, err := a.NoticeDAL.Get(ctx, id)
if err != nil {
return err
} else if notice == nil {
return errors.NotFound("", "Notice not found")
}
if err := formItem.FillTo(notice); err != nil {
return err
}
notice.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.NoticeDAL.Update(ctx, notice); err != nil {
return err
}
return nil
})
}
// Delete the specified notice from the data access object.
func (a *Notice) Delete(ctx context.Context, id uint) error {
exists, err := a.NoticeDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Notice not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.NoticeDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,133 @@
package biz
import (
"context"
"fmt"
"github.com/skip2/go-qrcode"
"github.guxuan/haibei/internal/mods/common/dal"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"time"
)
type ReceptionCenter struct {
Trans *util.Trans
ReceptionCenterDAL *dal.ReceptionCenter
}
// Query companies from the data access object based on the provided parameters and options.
func (a *ReceptionCenter) Query(ctx context.Context, params schema.ReceptionCenterQueryParam) (*schema.ReceptionCenterQueryResult, error) {
params.Pagination = true
result, err := a.ReceptionCenterDAL.Query(ctx, params, schema.ReceptionCenterQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified company from the data access object.
func (a *ReceptionCenter) Get(ctx context.Context, id uint) (*schema.ReceptionCenter, error) {
company, err := a.ReceptionCenterDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if company == nil {
return nil, errors.NotFound("", "Company not found")
}
return company, nil
}
func GenerateStoreQR(recepId uint) ([]byte, error) {
// 格式checkin:store_id=123 (添加前缀防止恶意扫描)
content := fmt.Sprintf("checkin:reception_center_id=%d", recepId)
return qrcode.Encode(content, qrcode.Medium, 256)
}
func (a *ReceptionCenter) GetQrCode(ctx context.Context, id uint) ([]byte, error) {
recep, err := a.ReceptionCenterDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if recep == nil {
return nil, errors.NotFound("", "ReceptionCenter not found")
}
png, err := GenerateStoreQR(recep.ID)
if err != nil {
return nil, err
}
return png, nil
}
// Create a new company in the data access object.
func (a *ReceptionCenter) Create(ctx context.Context, formItem *schema.ReceptionCenterForm) (*schema.ReceptionCenter, error) {
recep := &schema.ReceptionCenter{}
if err := formItem.FillTo(recep); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.ReceptionCenterDAL.Create(ctx, recep); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return recep, nil
}
func (a *ReceptionCenter) CheckQrcode(ctx context.Context, receptionID, customerID uint) error {
recep, err := a.ReceptionCenterDAL.Get(ctx, receptionID)
if err != nil {
return err
} else if recep == nil {
return errors.NotFound("", "ReceptionCenter not found")
}
return nil
}
// Update the specified company in the data access object.
func (a *ReceptionCenter) Update(ctx context.Context, id uint, formItem *schema.ReceptionCenterForm) error {
recep, err := a.ReceptionCenterDAL.Get(ctx, id)
if err != nil {
return err
} else if recep == nil {
return errors.NotFound("", "recep not found")
}
if err := formItem.FillTo(recep); err != nil {
return err
}
recep.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.ReceptionCenterDAL.Update(ctx, recep); err != nil {
return err
}
return nil
})
}
// Delete the specified company from the data access object.
func (a *ReceptionCenter) Delete(ctx context.Context, id uint) error {
exists, err := a.ReceptionCenterDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "recep not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.ReceptionCenterDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,54 @@
package biz
import (
"context"
"fmt"
"github.guxuan/haibei/internal/config"
"github.guxuan/haibei/pkg/cachex"
"github.guxuan/haibei/pkg/util"
"io"
"mime/multipart"
"os"
"path/filepath"
"strings"
)
// Role management for RBAC
type Upload struct {
Cache cachex.Cacher
Trans *util.Trans
}
func (a *Upload) SaveFile(ctx context.Context, file *multipart.FileHeader) (string, error) {
ext := strings.ToLower(filepath.Ext(file.Filename))
// 简单过滤危险扩展名
blacklist := []string{".exe", ".bat", ".sh", ".php", ".js"}
for _, b := range blacklist {
if ext == b {
return "", fmt.Errorf("不支持的文件类型: %s", ext)
}
}
// 确保上传目录存在
if err := os.MkdirAll(config.C.FileConfig.UploadDir, os.ModePerm); err != nil {
return "", err
}
// 构造保存路径
dstPath := filepath.Join(config.C.FileConfig.UploadDir, file.Filename)
// 打开源文件
srcFile, err := file.Open()
if err != nil {
return "", err
}
defer srcFile.Close()
// 在目标位置创建文件
outFile, err := os.Create(dstPath)
if err != nil {
return "", err
}
defer outFile.Close()
// 复制内容
if _, err := io.Copy(outFile, srcFile); err != nil {
return "", err
}
return file.Filename, nil
}

View File

@ -0,0 +1,83 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get area storage instance
func GetAreaDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.Area))
}
// Defining the `Area` data access object.
type Area struct {
DB *gorm.DB
}
// Query areas from the database based on the provided parameters and options.
func (a *Area) Query(ctx context.Context, params schema.AreaQueryParam, opts ...schema.AreaQueryOptions) (*schema.AreaQueryResult, error) {
var opt schema.AreaQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetAreaDB(ctx, a.DB)
var list schema.Areas
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.AreaQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified area from the database.
func (a *Area) Get(ctx context.Context, id uint, opts ...schema.AreaQueryOptions) (*schema.Area, error) {
var opt schema.AreaQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.Area)
ok, err := util.FindOne(ctx, GetAreaDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified area exists in the database.
func (a *Area) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetAreaDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new area.
func (a *Area) Create(ctx context.Context, item *schema.Area) error {
result := GetAreaDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified area in the database.
func (a *Area) Update(ctx context.Context, item *schema.Area) error {
result := GetAreaDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified area from the database.
func (a *Area) Delete(ctx context.Context, id uint) error {
result := GetAreaDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.Area))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,83 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get banner storage instance
func GetBannerDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.Banner))
}
// Defining the `Banner` data access object.
type Banner struct {
DB *gorm.DB
}
// Query banners from the database based on the provided parameters and options.
func (a *Banner) Query(ctx context.Context, params schema.BannerQueryParam, opts ...schema.BannerQueryOptions) (*schema.BannerQueryResult, error) {
var opt schema.BannerQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetBannerDB(ctx, a.DB)
var list schema.Banners
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.BannerQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified banner from the database.
func (a *Banner) Get(ctx context.Context, id uint, opts ...schema.BannerQueryOptions) (*schema.Banner, error) {
var opt schema.BannerQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.Banner)
ok, err := util.FindOne(ctx, GetBannerDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified banner exists in the database.
func (a *Banner) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetBannerDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new banner.
func (a *Banner) Create(ctx context.Context, item *schema.Banner) error {
result := GetBannerDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified banner in the database.
func (a *Banner) Update(ctx context.Context, item *schema.Banner) error {
result := GetBannerDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified banner from the database.
func (a *Banner) Delete(ctx context.Context, id uint) error {
result := GetBannerDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.Banner))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,83 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get common storage instance
func GetCommonDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.Common))
}
// Defining the `Common` data access object.
type Common struct {
DB *gorm.DB
}
// Query commons from the database based on the provided parameters and options.
func (a *Common) Query(ctx context.Context, params schema.CommonQueryParam, opts ...schema.CommonQueryOptions) (*schema.CommonQueryResult, error) {
var opt schema.CommonQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetCommonDB(ctx, a.DB)
var list schema.Commons
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.CommonQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified common from the database.
func (a *Common) Get(ctx context.Context, id uint, opts ...schema.CommonQueryOptions) (*schema.Common, error) {
var opt schema.CommonQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.Common)
ok, err := util.FindOne(ctx, GetCommonDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified common exists in the database.
func (a *Common) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetCommonDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new common.
func (a *Common) Create(ctx context.Context, item *schema.Common) error {
result := GetCommonDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified common in the database.
func (a *Common) Update(ctx context.Context, item *schema.Common) error {
result := GetCommonDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified common from the database.
func (a *Common) Delete(ctx context.Context, id uint) error {
result := GetCommonDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.Common))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,83 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get company storage instance
func GetCompanyDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.Company))
}
// Defining the `Company` data access object.
type Company struct {
DB *gorm.DB
}
// Query companies from the database based on the provided parameters and options.
func (a *Company) Query(ctx context.Context, params schema.CompanyQueryParam, opts ...schema.CompanyQueryOptions) (*schema.CompanyQueryResult, error) {
var opt schema.CompanyQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetCompanyDB(ctx, a.DB)
var list schema.Companies
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.CompanyQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified company from the database.
func (a *Company) Get(ctx context.Context, id uint, opts ...schema.CompanyQueryOptions) (*schema.Company, error) {
var opt schema.CompanyQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.Company)
ok, err := util.FindOne(ctx, GetCompanyDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified company exists in the database.
func (a *Company) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetCompanyDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new company.
func (a *Company) Create(ctx context.Context, item *schema.Company) error {
result := GetCompanyDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified company in the database.
func (a *Company) Update(ctx context.Context, item *schema.Company) error {
result := GetCompanyDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified company from the database.
func (a *Company) Delete(ctx context.Context, id uint) error {
result := GetCompanyDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.Company))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,83 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get notice storage instance
func GetNoticeDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.Notice))
}
// Defining the `Notice` data access object.
type Notice struct {
DB *gorm.DB
}
// Query notices from the database based on the provided parameters and options.
func (a *Notice) Query(ctx context.Context, params schema.NoticeQueryParam, opts ...schema.NoticeQueryOptions) (*schema.NoticeQueryResult, error) {
var opt schema.NoticeQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetNoticeDB(ctx, a.DB)
var list schema.Notices
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.NoticeQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified notice from the database.
func (a *Notice) Get(ctx context.Context, id uint, opts ...schema.NoticeQueryOptions) (*schema.Notice, error) {
var opt schema.NoticeQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.Notice)
ok, err := util.FindOne(ctx, GetNoticeDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified notice exists in the database.
func (a *Notice) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetNoticeDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new notice.
func (a *Notice) Create(ctx context.Context, item *schema.Notice) error {
result := GetNoticeDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified notice in the database.
func (a *Notice) Update(ctx context.Context, item *schema.Notice) error {
result := GetNoticeDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified notice from the database.
func (a *Notice) Delete(ctx context.Context, id uint) error {
result := GetNoticeDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.Notice))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,83 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get company storage instance
func GetReceptionCenterDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.ReceptionCenter))
}
// Defining the `Company` data access object.
type ReceptionCenter struct {
DB *gorm.DB
}
// Query companies from the database based on the provided parameters and options.
func (a *ReceptionCenter) Query(ctx context.Context, params schema.ReceptionCenterQueryParam, opts ...schema.ReceptionCenterQueryOptions) (*schema.ReceptionCenterQueryResult, error) {
var opt schema.ReceptionCenterQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetReceptionCenterDB(ctx, a.DB)
var list schema.ReceptionCenters
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.ReceptionCenterQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified company from the database.
func (a *ReceptionCenter) Get(ctx context.Context, id uint, opts ...schema.ReceptionCenterQueryOptions) (*schema.ReceptionCenter, error) {
var opt schema.ReceptionCenterQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.ReceptionCenter)
ok, err := util.FindOne(ctx, GetReceptionCenterDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified company exists in the database.
func (a *ReceptionCenter) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetReceptionCenterDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new company.
func (a *ReceptionCenter) Create(ctx context.Context, item *schema.ReceptionCenter) error {
result := GetReceptionCenterDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified company in the database.
func (a *ReceptionCenter) Update(ctx context.Context, item *schema.ReceptionCenter) error {
result := GetReceptionCenterDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified company from the database.
func (a *ReceptionCenter) Delete(ctx context.Context, id uint) error {
result := GetReceptionCenterDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.ReceptionCenter))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,81 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/common/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
func GetSignInDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.SignIn))
}
type SignIn struct {
DB *gorm.DB
}
// Query notices from the database based on the provided parameters and options.
func (a *SignIn) Query(ctx context.Context, params schema.SignInQueryParam, opts ...schema.SignInQueryOptions) (*schema.SignInQueryResult, error) {
var opt schema.SignInQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetSignInDB(ctx, a.DB)
var list schema.SignIns
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.SignInQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified notice from the database.
func (a *SignIn) Get(ctx context.Context, id uint, opts ...schema.SignInQueryOptions) (*schema.SignIn, error) {
var opt schema.SignInQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.SignIn)
ok, err := util.FindOne(ctx, GetSignInDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified notice exists in the database.
func (a *SignIn) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetSignInDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new notice.
func (a *SignIn) Create(ctx context.Context, item *schema.SignIn) error {
result := GetSignInDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified notice in the database.
func (a *SignIn) Update(ctx context.Context, item *schema.SignIn) error {
result := GetSignInDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified notice from the database.
func (a *SignIn) Delete(ctx context.Context, id uint) error {
result := GetSignInDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.SignIn))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,99 @@
package common
import (
"context"
"github.guxuan/haibei/internal/config"
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/common/api"
"github.guxuan/haibei/internal/mods/common/schema"
"gorm.io/gorm"
)
type Common struct {
DB *gorm.DB
CommonAPI *api.Common
BannerAPI *api.Banner
NoticeAPI *api.Notice
CompanyAPI *api.Company
AreaAPI *api.Area
UploadAPI *api.Upload
ReceptionCenterAPI *api.ReceptionCenter
}
func (a *Common) AutoMigrate(ctx context.Context) error {
return a.DB.AutoMigrate(new(schema.Common), new(schema.Banner), new(schema.Notice), new(schema.Company), new(schema.Area), new(schema.ReceptionCenter), new(schema.SignIn))
}
func (a *Common) Init(ctx context.Context) error {
if config.C.Storage.DB.AutoMigrate {
if err := a.AutoMigrate(ctx); err != nil {
return err
}
}
return nil
}
func (a *Common) RegisterV1Routers(ctx context.Context, v1 *gin.RouterGroup) error {
common := v1.Group("commons")
{
common.GET("", a.CommonAPI.Query)
common.GET(":id", a.CommonAPI.Get)
common.POST("", a.CommonAPI.Create)
common.PUT(":id", a.CommonAPI.Update)
common.DELETE(":id", a.CommonAPI.Delete)
}
upload := v1.Group("upload")
{
upload.POST("", a.UploadAPI.SaveFile)
}
banner := v1.Group("banners")
{
banner.GET("", a.BannerAPI.Query)
banner.GET(":id", a.BannerAPI.Get)
banner.POST("", a.BannerAPI.Create)
banner.PUT(":id", a.BannerAPI.Update)
banner.DELETE(":id", a.BannerAPI.Delete)
}
notice := v1.Group("notices")
{
notice.GET("", a.NoticeAPI.Query)
notice.GET(":id", a.NoticeAPI.Get)
notice.POST("", a.NoticeAPI.Create)
notice.PUT(":id", a.NoticeAPI.Update)
notice.DELETE(":id", a.NoticeAPI.Delete)
}
company := v1.Group("companies")
{
company.GET("", a.CompanyAPI.Query)
company.GET(":id", a.CompanyAPI.Get)
company.POST("", a.CompanyAPI.Create)
company.PUT(":id", a.CompanyAPI.Update)
company.DELETE(":id", a.CompanyAPI.Delete)
}
area := v1.Group("areas")
{
area.GET("", a.AreaAPI.Query)
area.GET(":id", a.AreaAPI.Get)
area.POST("", a.AreaAPI.Create)
area.PUT(":id", a.AreaAPI.Update)
area.DELETE(":id", a.AreaAPI.Delete)
}
reception := v1.Group("reception_center")
{
reception.GET("", a.ReceptionCenterAPI.Query)
reception.GET(":id", a.ReceptionCenterAPI.Get)
reception.POST("", a.ReceptionCenterAPI.Create)
reception.GET("qr_code/:id", a.ReceptionCenterAPI.GetQrCode)
reception.POST("qr_code", a.ReceptionCenterAPI.CheckQrCode)
reception.PUT(":id", a.ReceptionCenterAPI.Update)
reception.DELETE(":id", a.ReceptionCenterAPI.Delete)
}
return nil
}
func (a *Common) Release(ctx context.Context) error {
return nil
}

View File

@ -0,0 +1,49 @@
package schema
import (
"github.guxuan/haibei/pkg/util"
)
// Defining the `Area` struct.
type Area struct {
util.BaseModel
Name string `json:"name" gorm:"size:128;not null;index"`
Status string `json:"status" gorm:"size:20;index"`
}
// Defining the query parameters for the `Area` struct.
type AreaQueryParam struct {
util.PaginationParam
}
// Defining the query options for the `Area` struct.
type AreaQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `Area` struct.
type AreaQueryResult struct {
Data Areas
PageResult *util.PaginationResult
}
// Defining the slice of `Area` struct.
type Areas []*Area
// Defining the data structure for creating a `Area` struct.
type AreaForm struct {
Name string `json:"name" `
Status string `json:"status"`
}
// A validation function for the `AreaForm` struct.
func (a *AreaForm) Validate() error {
return nil
}
// Convert `AreaForm` to `Area` object.
func (a *AreaForm) FillTo(area *Area) error {
area.Status = a.Status
area.Name = a.Name
return nil
}

View File

@ -0,0 +1,69 @@
package schema
import (
"github.guxuan/haibei/pkg/util"
)
// Defining the `Banner` struct.
type Banner struct {
util.BaseModel
Name string `json:"name" gorm:"size:128;not null;index"`
Img string `json:"img" gorm:"size:2048"`
Sequence int `json:"sequence" gorm:"index;default:0"`
Link string `json:"link" gorm:"size:2048;"`
AreaID uint `json:"areaId" gorm:"index;comment:城市id"`
Status string `json:"status" gorm:"size:20;index"`
}
// Defining the query parameters for the `Banner` struct.
type BannerQueryParam struct {
util.PaginationParam
Status string `form:"status"`
AreaID uint `form:"areaId" `
}
// Defining the query options for the `Banner` struct.
type BannerQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `Banner` struct.
type BannerQueryResult struct {
Data Banners
PageResult *util.PaginationResult
}
// Defining the slice of `Banner` struct.
type Banners []*Banner
// Defining the data structure for creating a `Banner` struct.
type BannerForm struct {
Name string `json:"name" `
Img string `json:"img"`
Sequence int `json:"sequence"`
Link string `json:"link"`
AreaID uint `json:"areaId" `
Status string `json:"status"`
}
// A validation function for the `BannerForm` struct.
func (a *BannerForm) Validate() error {
return nil
}
// Convert `BannerForm` to `Banner` object.
func (a *BannerForm) FillTo(banner *Banner) error {
banner.Name = a.Name
banner.Img = a.Img
banner.AreaID = a.AreaID
banner.Sequence = a.Sequence
banner.Link = a.Link
if a.Status != "" {
banner.Status = a.Status
} else {
banner.Status = "active"
}
return nil
}

View File

@ -0,0 +1,47 @@
package schema
import (
"time"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Common` struct.
type Common struct {
ID string `json:"id" gorm:"size:20;primaryKey;"` // Unique ID
CreatedAt time.Time `json:"created_at" gorm:"index;"` // Create time
UpdatedAt time.Time `json:"updated_at" gorm:"index;"` // Update time
}
// Defining the query parameters for the `Common` struct.
type CommonQueryParam struct {
util.PaginationParam
}
// Defining the query options for the `Common` struct.
type CommonQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `Common` struct.
type CommonQueryResult struct {
Data Commons
PageResult *util.PaginationResult
}
// Defining the slice of `Common` struct.
type Commons []*Common
// Defining the data structure for creating a `Common` struct.
type CommonForm struct {
}
// A validation function for the `CommonForm` struct.
func (a *CommonForm) Validate() error {
return nil
}
// Convert `CommonForm` to `Common` object.
func (a *CommonForm) FillTo(common *Common) error {
return nil
}

View File

@ -0,0 +1,57 @@
package schema
import (
"github.guxuan/haibei/pkg/util"
)
// Defining the `Company` struct.
type Company struct {
util.BaseModel
Name string `json:"name" gorm:"size:128;not null;index"`
Img string `json:"img" gorm:"size:2048"`
AreaID uint `json:"areaId" gorm:"index;comment:城市id"`
Status string `json:"status" gorm:"size:20;index"`
}
// Defining the query parameters for the `Company` struct.
type CompanyQueryParam struct {
util.PaginationParam
AreaID uint `form:"areaId"`
}
// Defining the query options for the `Company` struct.
type CompanyQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `Company` struct.
type CompanyQueryResult struct {
Data Companies
PageResult *util.PaginationResult
}
// Defining the slice of `Company` struct.
type Companies []*Company
// Defining the data structure for creating a `Company` struct.
type CompanyForm struct {
Name string `json:"name" `
Img string `json:"img" `
AreaID uint `json:"areaId" `
Status string `json:"status" `
}
// A validation function for the `CompanyForm` struct.
func (a *CompanyForm) Validate() error {
return nil
}
// Convert `CompanyForm` to `Company` object.
func (a *CompanyForm) FillTo(company *Company) error {
company.Name = a.Name
company.Img = a.Img
company.AreaID = a.AreaID
company.Status = a.Status
return nil
}

View File

@ -0,0 +1,60 @@
package schema
import (
"github.guxuan/haibei/pkg/util"
)
// Defining the `Notice` struct.
type Notice struct {
util.BaseModel
Title string `json:"title" gorm:"size:128;not null;index"`
Content string `json:"content" gorm:"size:2048;not null"`
Sequence int `json:"sequence" gorm:"index;default:0"`
AreaID uint `json:"areaId" gorm:"index;comment:城市id"`
Status string `json:"status" gorm:"size:20;index"`
}
// Defining the query parameters for the `Notice` struct.
type NoticeQueryParam struct {
util.PaginationParam
AreaID uint `form:"areaId"`
}
// Defining the query options for the `Notice` struct.
type NoticeQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `Notice` struct.
type NoticeQueryResult struct {
Data Notices
PageResult *util.PaginationResult
}
// Defining the slice of `Notice` struct.
type Notices []*Notice
// Defining the data structure for creating a `Notice` struct.
type NoticeForm struct {
Title string `json:"title" `
Content string `json:"content"`
Sequence int `json:"sequence" `
Status string `json:"status"`
AreaID uint `json:"areaId"`
}
// A validation function for the `NoticeForm` struct.
func (a *NoticeForm) Validate() error {
return nil
}
// Convert `NoticeForm` to `Notice` object.
func (a *NoticeForm) FillTo(notice *Notice) error {
notice.Title = a.Title
notice.Content = a.Content
notice.Sequence = a.Sequence
notice.Status = a.Status
notice.AreaID = a.AreaID
return nil
}

View File

@ -0,0 +1,56 @@
package schema
import (
"github.guxuan/haibei/pkg/util"
)
// Defining the `Company` struct.
type ReceptionCenter struct {
util.BaseModel
Name string `json:"name" gorm:"size:128;not null;index"`
Introduce string `json:"introduce" gorm:"size:1024;comment:介绍"`
AreaID uint `json:"areaId" gorm:"index;comment:城市id"`
Status string `json:"status" gorm:"size:20;index"`
}
// Defining the query parameters for the `Company` struct.
type ReceptionCenterQueryParam struct {
util.PaginationParam
AreaID uint `form:"areaId"`
}
// Defining the query options for the `Company` struct.
type ReceptionCenterQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `Company` struct.
type ReceptionCenterQueryResult struct {
Data ReceptionCenters
PageResult *util.PaginationResult
}
// Defining the slice of `Company` struct.
type ReceptionCenters []*ReceptionCenter
// Defining the data structure for creating a `Company` struct.
type ReceptionCenterForm struct {
Name string `json:"name" `
Introduce string `json:"introduce" `
AreaID uint `json:"areaId" `
Status string `json:"status" `
}
// A validation function for the `CompanyForm` struct.
func (a *ReceptionCenterForm) Validate() error {
return nil
}
// Convert `CompanyForm` to `Company` object.
func (a *ReceptionCenterForm) FillTo(receptionCenter *ReceptionCenter) error {
receptionCenter.Name = a.Name
receptionCenter.Introduce = a.Introduce
receptionCenter.AreaID = a.AreaID
receptionCenter.Status = a.Status
return nil
}

View File

@ -0,0 +1,50 @@
package schema
import (
"github.guxuan/haibei/pkg/util"
)
// Defining the `Notice` struct.
type SignIn struct {
util.BaseModel
CustomerID uint `json:"customerId" gorm:"not null;index"`
ReceptionID uint `json:"receptionId" gorm:"not null;index"`
}
// Defining the query parameters for the `Notice` struct.
type SignInQueryParam struct {
util.PaginationParam
}
// Defining the query options for the `Notice` struct.
type SignInQueryOptions struct {
util.QueryOptions
}
// Defining the query result for the `Notice` struct.
type SignInQueryResult struct {
Data SignIns
PageResult *util.PaginationResult
}
// Defining the slice of `Notice` struct.
type SignIns []*SignIn
// Defining the data structure for creating a `Notice` struct.
type SignInForm struct {
CustomerID uint `json:"customerId" `
ReceptionID uint `json:"receptionId"`
}
// A validation function for the `NoticeForm` struct.
func (a *SignInForm) Validate() error {
return nil
}
// Convert `NoticeForm` to `Notice` object.
func (a *SignInForm) FillTo(signIn *SignIn) error {
signIn.CustomerID = a.CustomerID
signIn.ReceptionID = a.ReceptionID
return nil
}

View File

@ -0,0 +1,31 @@
package common
import (
"github.com/google/wire"
"github.guxuan/haibei/internal/mods/common/api"
"github.guxuan/haibei/internal/mods/common/biz"
"github.guxuan/haibei/internal/mods/common/dal"
)
var Set = wire.NewSet(
wire.Struct(new(Common), "*"),
wire.Struct(new(dal.ReceptionCenter), "*"),
wire.Struct(new(biz.ReceptionCenter), "*"),
wire.Struct(new(api.ReceptionCenter), "*"),
wire.Struct(new(dal.SignIn), "*"),
wire.Struct(new(dal.Common), "*"),
wire.Struct(new(biz.Common), "*"),
wire.Struct(new(api.Common), "*"),
wire.Struct(new(dal.Banner), "*"),
wire.Struct(new(biz.Banner), "*"),
wire.Struct(new(api.Banner), "*"),
wire.Struct(new(dal.Notice), "*"),
wire.Struct(new(biz.Notice), "*"),
wire.Struct(new(api.Notice), "*"),
wire.Struct(new(dal.Company), "*"),
wire.Struct(new(biz.Company), "*"),
wire.Struct(new(api.Company), "*"),
wire.Struct(new(dal.Area), "*"),
wire.Struct(new(biz.Area), "*"),
wire.Struct(new(api.Area), "*"),
)

View File

@ -0,0 +1,146 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/customer/biz"
"github.guxuan/haibei/internal/mods/customer/schema"
"github.guxuan/haibei/pkg/util"
"strconv"
)
// Defining the `Balance` api.
type Balance struct {
BalanceBIZ *biz.Balance
}
// @Tags 积分模块
// @Security ApiKeyAuth
// @Summary Query balance list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.Balance}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/balances [get]
func (a *Balance) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.BalanceQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.BalanceBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags 积分模块
// @Security ApiKeyAuth
// @Summary Get balance record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.Balance}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/balances/{id} [get]
func (a *Balance) Get(c *gin.Context) {
ctx := c.Request.Context()
u64, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.BalanceBIZ.Get(ctx, uint(u64))
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags 积分模块
// @Security ApiKeyAuth
// @Summary Create balance record
// @Param body body schema.BalanceForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.Balance}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/balances [post]
func (a *Balance) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.BalanceForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.BalanceBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags 积分模块
// @Security ApiKeyAuth
// @Summary Update balance record by ID
// @Param id path string true "unique id"
// @Param body body schema.BalanceForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/balances/{id} [put]
func (a *Balance) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.BalanceForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
u64, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
util.ResError(c, err)
return
}
err = a.BalanceBIZ.Update(ctx, uint(u64), item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags 积分模块
// @Security ApiKeyAuth
// @Summary Delete balance record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/balances/{id} [delete]
func (a *Balance) Delete(c *gin.Context) {
ctx := c.Request.Context()
u64, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
util.ResError(c, err)
return
}
err = a.BalanceBIZ.Delete(ctx, uint(u64))
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,146 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/customer/biz"
"github.guxuan/haibei/internal/mods/customer/schema"
"github.guxuan/haibei/pkg/util"
"strconv"
)
// Defining the `Customer` api.
type Customer struct {
CustomerBIZ *biz.Customer
}
// @Tags 客户模块
// @Security ApiKeyAuth
// @Summary Query customer list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.Customer}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/customers [get]
func (a *Customer) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.CustomerQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.CustomerBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags 客户模块
// @Security ApiKeyAuth
// @Summary Get customer record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.Customer}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/customers/{id} [get]
func (a *Customer) Get(c *gin.Context) {
ctx := c.Request.Context()
u64, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.CustomerBIZ.Get(ctx, uint(u64))
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags 客户模块
// @Security ApiKeyAuth
// @Summary Create customer record
// @Param body body schema.CustomerForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.Customer}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/customers [post]
func (a *Customer) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.CustomerForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.CustomerBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags 客户模块
// @Security ApiKeyAuth
// @Summary Update customer record by ID
// @Param id path string true "unique id"
// @Param body body schema.CustomerForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/customers/{id} [put]
func (a *Customer) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.CustomerForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
u64, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
util.ResError(c, err)
return
}
err = a.CustomerBIZ.Update(ctx, uint(u64), item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags 客户模块
// @Security ApiKeyAuth
// @Summary Delete customer record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/customers/{id} [delete]
func (a *Customer) Delete(c *gin.Context) {
ctx := c.Request.Context()
u64, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
util.ResError(c, err)
return
}
err = a.CustomerBIZ.Delete(ctx, uint(u64))
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,145 @@
package api
import (
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/customer/biz"
"github.guxuan/haibei/internal/mods/customer/schema"
"github.guxuan/haibei/pkg/util"
)
// Defining the `ProductOrder` api.
type ProductOrder struct {
ProductOrderBIZ *biz.ProductOrder
}
// @Tags ProductOrderAPI
// @Security ApiKeyAuth
// @Summary Query product order list
// @Param current query int true "pagination index" default(1)
// @Param pageSize query int true "pagination size" default(10)
// @Success 200 {object} util.ResponseResult{data=[]schema.ProductOrder}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/product-orders [get]
func (a *ProductOrder) Query(c *gin.Context) {
ctx := c.Request.Context()
var params schema.ProductOrderQueryParam
if err := util.ParseQuery(c, &params); err != nil {
util.ResError(c, err)
return
}
result, err := a.ProductOrderBIZ.Query(ctx, params)
if err != nil {
util.ResError(c, err)
return
}
util.ResPage(c, result.Data, result.PageResult)
}
// @Tags ProductOrderAPI
// @Security ApiKeyAuth
// @Summary Get product order record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult{data=schema.ProductOrder}
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/product-orders/{id} [get]
func (a *ProductOrder) Get(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
item, err := a.ProductOrderBIZ.Get(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, item)
}
// @Tags ProductOrderAPI
// @Security ApiKeyAuth
// @Summary Create product order record
// @Param body body schema.ProductOrderForm true "Request body"
// @Success 200 {object} util.ResponseResult{data=schema.ProductOrder}
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/product-orders [post]
func (a *ProductOrder) Create(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.ProductOrderForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
result, err := a.ProductOrderBIZ.Create(ctx, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResSuccess(c, result)
}
// @Tags ProductOrderAPI
// @Security ApiKeyAuth
// @Summary Update product order record by ID
// @Param id path string true "unique id"
// @Param body body schema.ProductOrderForm true "Request body"
// @Success 200 {object} util.ResponseResult
// @Failure 400 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/product-orders/{id} [put]
func (a *ProductOrder) Update(c *gin.Context) {
ctx := c.Request.Context()
item := new(schema.ProductOrderForm)
if err := util.ParseJSON(c, item); err != nil {
util.ResError(c, err)
return
} else if err := item.Validate(); err != nil {
util.ResError(c, err)
return
}
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.ProductOrderBIZ.Update(ctx, id, item)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}
// @Tags ProductOrderAPI
// @Security ApiKeyAuth
// @Summary Delete product order record by ID
// @Param id path string true "unique id"
// @Success 200 {object} util.ResponseResult
// @Failure 401 {object} util.ResponseResult
// @Failure 500 {object} util.ResponseResult
// @Router /api/v1/product-orders/{id} [delete]
func (a *ProductOrder) Delete(c *gin.Context) {
ctx := c.Request.Context()
id, err := util.GetQueryID(c)
if err != nil {
util.ResError(c, err)
return
}
err = a.ProductOrderBIZ.Delete(ctx, id)
if err != nil {
util.ResError(c, err)
return
}
util.ResOK(c)
}

View File

@ -0,0 +1,104 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/customer/dal"
"github.guxuan/haibei/internal/mods/customer/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
// Defining the `Balance` business logic.
type Balance struct {
Trans *util.Trans
BalanceDAL *dal.Balance
}
// Query balances from the data access object based on the provided parameters and options.
func (a *Balance) Query(ctx context.Context, params schema.BalanceQueryParam) (*schema.BalanceQueryResult, error) {
params.Pagination = true
result, err := a.BalanceDAL.Query(ctx, params, schema.BalanceQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified balance from the data access object.
func (a *Balance) Get(ctx context.Context, id uint) (*schema.Balance, error) {
balance, err := a.BalanceDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if balance == nil {
return nil, errors.NotFound("", "Balance not found")
}
return balance, nil
}
// Create a new balance in the data access object.
func (a *Balance) Create(ctx context.Context, formItem *schema.BalanceForm) (*schema.Balance, error) {
balance := &schema.Balance{}
if err := formItem.FillTo(balance); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.BalanceDAL.Create(ctx, balance); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return balance, nil
}
// Update the specified balance in the data access object.
func (a *Balance) Update(ctx context.Context, id uint, formItem *schema.BalanceForm) error {
balance, err := a.BalanceDAL.Get(ctx, id)
if err != nil {
return err
} else if balance == nil {
return errors.NotFound("", "Balance not found")
}
if err := formItem.FillTo(balance); err != nil {
return err
}
balance.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.BalanceDAL.Update(ctx, balance); err != nil {
return err
}
return nil
})
}
// Delete the specified balance from the data access object.
func (a *Balance) Delete(ctx context.Context, id uint) error {
exists, err := a.BalanceDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Balance not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.BalanceDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,239 @@
package biz
import (
"context"
"encoding/json"
"fmt"
"github.guxuan/haibei/internal/config"
"github.guxuan/haibei/pkg/cachex"
"github.guxuan/haibei/pkg/jwtx"
"github.guxuan/haibei/pkg/logging"
"go.uber.org/zap"
"math/rand"
"strconv"
"time"
"github.guxuan/haibei/internal/mods/customer/dal"
"github.guxuan/haibei/internal/mods/customer/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
const (
REGISTER_SMS_CODE = "REGISTER_SMS_CODE"
CHECK_SMS_CODE = "CHECK_SMS_CODE"
)
// Defining the `Customer` business logic.
type Customer struct {
Cache cachex.Cacher
Trans *util.Trans
CustomerDAL *dal.Customer
Auth jwtx.Auther
}
func (a *Customer) Login(ctx context.Context, formItem *schema.CustomerLoginForm) (*schema.CustomerLoginToken, error) {
ctx = logging.NewTag(ctx, logging.TagKeyAppLogin)
// get user info
user, err := a.CustomerDAL.GetByWxSign(ctx, formItem.WxSign, schema.CustomerQueryOptions{})
if err != nil {
return nil, err
}
if user == nil {
customer := &schema.Customer{}
customer.WxSign = formItem.WxSign
err := a.CustomerDAL.Create(ctx, customer)
if err != nil {
return nil, err
}
user = customer
}
userID := fmt.Sprintf("%d", user.ID)
var subject jwtx.JwtSubject
subject.ID = userID
subject.Typer = "APP"
marshal, err := json.Marshal(subject)
if err != nil {
return nil, err
}
// generate token
ctx = logging.NewUserID(ctx, userID)
userCache := util.UserCache{RoleIDs: []string{}}
err = a.Cache.Set(ctx, config.CacheNSForUser, userID, userCache.String(),
time.Duration(config.C.Dictionary.UserCacheExp)*time.Hour)
if err != nil {
logging.Context(ctx).Error("Failed to set cache", zap.Error(err))
}
logging.Context(ctx).Info("Login success", zap.String("WxSign", formItem.WxSign))
reload, err := a.genCustomerToken(ctx, string(marshal))
reload.Phone = user.Phone
return reload, err
}
func (a *Customer) BindPhone(ctx context.Context, formItem *schema.CustomerBindPhoneForm) (bool, error) {
userID := util.FromUserID(ctx)
num, err := strconv.ParseUint(fmt.Sprintf("%s", userID), 10, 64)
if err != nil {
fmt.Println("转换错误:", err)
return false, err
}
userIDNum := uint(num)
code, b, err := a.Cache.Get(ctx, REGISTER_SMS_CODE, formItem.Phone)
if err != nil {
return false, err
}
if !b {
return false, errors.NotFound("", "验证码过期!")
}
if code != formItem.Code {
return false, errors.NotFound("", "验证码失败!")
}
get, err := a.CustomerDAL.Get(ctx, userIDNum, schema.CustomerQueryOptions{})
if err != nil || get == nil {
return false, err
}
get.Phone = formItem.Phone
get.Avatar = formItem.Avatar
err = a.CustomerDAL.Update(ctx, get)
if err != nil {
return false, err
}
return true, nil
}
func (a *Customer) SendSms(ctx context.Context, phone string) (string, error) {
code := generateVerificationCode()
exists, err := a.Cache.Exists(ctx, REGISTER_SMS_CODE, phone)
if err != nil {
return "", err
}
if exists {
return "", errors.NotFound("", "验证码不能重复获取 等待90秒")
}
err = sendVerificationCode(phone, code)
if err != nil {
return "", err
}
err = a.Cache.Set(ctx, REGISTER_SMS_CODE, phone, code, 90*time.Second)
if err != nil {
return "", err
}
return code, nil
}
func sendVerificationCode(phone, code string) error {
// 这里应该是调用短信服务商的API发送短信
// 这里只是模拟
fmt.Printf("向手机号 %s 发送验证码: %s\n", phone, code)
return nil
}
func generateVerificationCode() string {
rand.Seed(time.Now().UnixNano())
return fmt.Sprintf("%06d", rand.Intn(1000000))
}
func (a *Customer) genCustomerToken(ctx context.Context, suject string) (*schema.CustomerLoginToken, error) {
token, err := a.Auth.GenerateToken(ctx, suject)
if err != nil {
return nil, err
}
tokenBuf, err := token.EncodeToJSON()
if err != nil {
return nil, err
}
logging.Context(ctx).Info("Generate user token", zap.Any("token", string(tokenBuf)))
return &schema.CustomerLoginToken{
AccessToken: token.GetAccessToken(),
TokenType: token.GetTokenType(),
ExpiresAt: token.GetExpiresAt(),
}, nil
}
// Query customers from the data access object based on the provided parameters and options.
func (a *Customer) Query(ctx context.Context, params schema.CustomerQueryParam) (*schema.CustomerQueryResult, error) {
params.Pagination = true
result, err := a.CustomerDAL.Query(ctx, params, schema.CustomerQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified customer from the data access object.
func (a *Customer) Get(ctx context.Context, id uint) (*schema.Customer, error) {
customer, err := a.CustomerDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if customer == nil {
return nil, errors.NotFound("", "Customer not found")
}
return customer, nil
}
// Create a new customer in the data access object.
func (a *Customer) Create(ctx context.Context, formItem *schema.CustomerForm) (*schema.Customer, error) {
customer := &schema.Customer{}
if err := formItem.FillTo(customer); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.CustomerDAL.Create(ctx, customer); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return customer, nil
}
// Update the specified customer in the data access object.
func (a *Customer) Update(ctx context.Context, id uint, formItem *schema.CustomerForm) error {
customer, err := a.CustomerDAL.Get(ctx, id)
if err != nil {
return err
} else if customer == nil {
return errors.NotFound("", "Customer not found")
}
if err := formItem.FillTo(customer); err != nil {
return err
}
customer.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.CustomerDAL.Update(ctx, customer); err != nil {
return err
}
return nil
})
}
// Delete the specified customer from the data access object.
func (a *Customer) Delete(ctx context.Context, id uint) error {
exists, err := a.CustomerDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Customer not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.CustomerDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,104 @@
package biz
import (
"context"
"time"
"github.guxuan/haibei/internal/mods/customer/dal"
"github.guxuan/haibei/internal/mods/customer/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
)
// Defining the `ProductOrder` business logic.
type ProductOrder struct {
Trans *util.Trans
ProductOrderDAL *dal.ProductOrder
}
// Query product orders from the data access object based on the provided parameters and options.
func (a *ProductOrder) Query(ctx context.Context, params schema.ProductOrderQueryParam) (*schema.ProductOrderQueryResult, error) {
params.Pagination = true
result, err := a.ProductOrderDAL.Query(ctx, params, schema.ProductOrderQueryOptions{
QueryOptions: util.QueryOptions{
OrderFields: []util.OrderByParam{
{Field: "created_at", Direction: util.DESC},
},
},
})
if err != nil {
return nil, err
}
return result, nil
}
// Get the specified product order from the data access object.
func (a *ProductOrder) Get(ctx context.Context, id uint) (*schema.ProductOrder, error) {
productOrder, err := a.ProductOrderDAL.Get(ctx, id)
if err != nil {
return nil, err
} else if productOrder == nil {
return nil, errors.NotFound("", "Product order not found")
}
return productOrder, nil
}
// Create a new product order in the data access object.
func (a *ProductOrder) Create(ctx context.Context, formItem *schema.ProductOrderForm) (*schema.ProductOrder, error) {
productOrder := &schema.ProductOrder{}
if err := formItem.FillTo(productOrder); err != nil {
return nil, err
}
err := a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.ProductOrderDAL.Create(ctx, productOrder); err != nil {
return err
}
return nil
})
if err != nil {
return nil, err
}
return productOrder, nil
}
// Update the specified product order in the data access object.
func (a *ProductOrder) Update(ctx context.Context, id uint, formItem *schema.ProductOrderForm) error {
productOrder, err := a.ProductOrderDAL.Get(ctx, id)
if err != nil {
return err
} else if productOrder == nil {
return errors.NotFound("", "Product order not found")
}
if err := formItem.FillTo(productOrder); err != nil {
return err
}
productOrder.UpdatedAt = time.Now()
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.ProductOrderDAL.Update(ctx, productOrder); err != nil {
return err
}
return nil
})
}
// Delete the specified product order from the data access object.
func (a *ProductOrder) Delete(ctx context.Context, id uint) error {
exists, err := a.ProductOrderDAL.Exists(ctx, id)
if err != nil {
return err
} else if !exists {
return errors.NotFound("", "Product order not found")
}
return a.Trans.Exec(ctx, func(ctx context.Context) error {
if err := a.ProductOrderDAL.Delete(ctx, id); err != nil {
return err
}
return nil
})
}

View File

@ -0,0 +1,83 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/customer/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get balance storage instance
func GetBalanceDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.Balance))
}
// Defining the `Balance` data access object.
type Balance struct {
DB *gorm.DB
}
// Query balances from the database based on the provided parameters and options.
func (a *Balance) Query(ctx context.Context, params schema.BalanceQueryParam, opts ...schema.BalanceQueryOptions) (*schema.BalanceQueryResult, error) {
var opt schema.BalanceQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetBalanceDB(ctx, a.DB)
var list schema.Balances
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.BalanceQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified balance from the database.
func (a *Balance) Get(ctx context.Context, id uint, opts ...schema.BalanceQueryOptions) (*schema.Balance, error) {
var opt schema.BalanceQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.Balance)
ok, err := util.FindOne(ctx, GetBalanceDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified balance exists in the database.
func (a *Balance) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetBalanceDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new balance.
func (a *Balance) Create(ctx context.Context, item *schema.Balance) error {
result := GetBalanceDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified balance in the database.
func (a *Balance) Update(ctx context.Context, item *schema.Balance) error {
result := GetBalanceDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified balance from the database.
func (a *Balance) Delete(ctx context.Context, id uint) error {
result := GetBalanceDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.Balance))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,99 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/customer/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get customer storage instance
func GetCustomerDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.Customer))
}
// Defining the `Customer` data access object.
type Customer struct {
DB *gorm.DB
}
// Query customers from the database based on the provided parameters and options.
func (a *Customer) Query(ctx context.Context, params schema.CustomerQueryParam, opts ...schema.CustomerQueryOptions) (*schema.CustomerQueryResult, error) {
var opt schema.CustomerQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetCustomerDB(ctx, a.DB)
var list schema.Customers
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.CustomerQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified customer from the database.
func (a *Customer) Get(ctx context.Context, id uint, opts ...schema.CustomerQueryOptions) (*schema.Customer, error) {
var opt schema.CustomerQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.Customer)
ok, err := util.FindOne(ctx, GetCustomerDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
func (a *Customer) GetByWxSign(ctx context.Context, wxSgin string, opts ...schema.CustomerQueryOptions) (*schema.Customer, error) {
var opt schema.CustomerQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.Customer)
ok, err := util.FindOne(ctx, GetCustomerDB(ctx, a.DB).Where("wx_sign=?", wxSgin), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified customer exists in the database.
func (a *Customer) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetCustomerDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new customer.
func (a *Customer) Create(ctx context.Context, item *schema.Customer) error {
result := GetCustomerDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified customer in the database.
func (a *Customer) Update(ctx context.Context, item *schema.Customer) error {
result := GetCustomerDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified customer from the database.
func (a *Customer) Delete(ctx context.Context, id uint) error {
result := GetCustomerDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.Customer))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,93 @@
package dal
import (
"context"
"github.guxuan/haibei/internal/mods/customer/schema"
"github.guxuan/haibei/pkg/errors"
"github.guxuan/haibei/pkg/util"
"gorm.io/gorm"
)
// Get product order storage instance
func GetProductOrderDB(ctx context.Context, defDB *gorm.DB) *gorm.DB {
return util.GetDB(ctx, defDB).Model(new(schema.ProductOrder))
}
// Defining the `ProductOrder` data access object.
type ProductOrder struct {
DB *gorm.DB
}
// Query product orders from the database based on the provided parameters and options.
func (a *ProductOrder) Query(ctx context.Context, params schema.ProductOrderQueryParam, opts ...schema.ProductOrderQueryOptions) (*schema.ProductOrderQueryResult, error) {
var opt schema.ProductOrderQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
db := GetProductOrderDB(ctx, a.DB)
var list schema.ProductOrders
pageResult, err := util.WrapPageQuery(ctx, db, params.PaginationParam, opt.QueryOptions, &list)
if err != nil {
return nil, errors.WithStack(err)
}
queryResult := &schema.ProductOrderQueryResult{
PageResult: pageResult,
Data: list,
}
return queryResult, nil
}
// Get the specified product order from the database.
func (a *ProductOrder) Get(ctx context.Context, id uint, opts ...schema.ProductOrderQueryOptions) (*schema.ProductOrder, error) {
var opt schema.ProductOrderQueryOptions
if len(opts) > 0 {
opt = opts[0]
}
item := new(schema.ProductOrder)
ok, err := util.FindOne(ctx, GetProductOrderDB(ctx, a.DB).Where("id=?", id), opt.QueryOptions, item)
if err != nil {
return nil, errors.WithStack(err)
} else if !ok {
return nil, nil
}
return item, nil
}
// Exists checks if the specified product order exists in the database.
func (a *ProductOrder) ExistsByCustomerID(ctx context.Context, customerID, productId uint) (*schema.ProductOrders, error) {
list := new(schema.ProductOrders)
tx := GetProductOrderDB(ctx, a.DB).Where("customer_id = ? AND product_id = ? ", customerID, productId).Find(list)
if err := tx.Error; err != nil {
return nil, errors.WithStack(err)
}
return list, nil
}
// Exists checks if the specified product order exists in the database.
func (a *ProductOrder) Exists(ctx context.Context, id uint) (bool, error) {
ok, err := util.Exists(ctx, GetProductOrderDB(ctx, a.DB).Where("id=?", id))
return ok, errors.WithStack(err)
}
// Create a new product order.
func (a *ProductOrder) Create(ctx context.Context, item *schema.ProductOrder) error {
result := GetProductOrderDB(ctx, a.DB).Create(item)
return errors.WithStack(result.Error)
}
// Update the specified product order in the database.
func (a *ProductOrder) Update(ctx context.Context, item *schema.ProductOrder) error {
result := GetProductOrderDB(ctx, a.DB).Where("id=?", item.ID).Select("*").Omit("created_at").Updates(item)
return errors.WithStack(result.Error)
}
// Delete the specified product order from the database.
func (a *ProductOrder) Delete(ctx context.Context, id uint) error {
result := GetProductOrderDB(ctx, a.DB).Where("id=?", id).Delete(new(schema.ProductOrder))
return errors.WithStack(result.Error)
}

View File

@ -0,0 +1,64 @@
package customer
import (
"context"
"github.guxuan/haibei/internal/config"
"github.com/gin-gonic/gin"
"github.guxuan/haibei/internal/mods/customer/api"
"github.guxuan/haibei/internal/mods/customer/schema"
"gorm.io/gorm"
)
type Customer struct {
DB *gorm.DB
CustomerAPI *api.Customer
BalanceAPI *api.Balance
ProductOrderAPI *api.ProductOrder
}
func (a *Customer) AutoMigrate(ctx context.Context) error {
return a.DB.AutoMigrate(new(schema.Customer), new(schema.Balance), new(schema.ProductOrder))
}
func (a *Customer) Init(ctx context.Context) error {
if config.C.Storage.DB.AutoMigrate {
if err := a.AutoMigrate(ctx); err != nil {
return err
}
}
return nil
}
func (a *Customer) RegisterV1Routers(ctx context.Context, v1 *gin.RouterGroup) error {
customer := v1.Group("customers")
{
customer.GET("", a.CustomerAPI.Query)
customer.GET(":id", a.CustomerAPI.Get)
customer.POST("", a.CustomerAPI.Create)
customer.PUT(":id", a.CustomerAPI.Update)
customer.DELETE(":id", a.CustomerAPI.Delete)
}
balance := v1.Group("balances")
{
balance.GET("", a.BalanceAPI.Query)
balance.GET(":id", a.BalanceAPI.Get)
balance.POST("", a.BalanceAPI.Create)
balance.PUT(":id", a.BalanceAPI.Update)
balance.DELETE(":id", a.BalanceAPI.Delete)
}
productOrder := v1.Group("product-orders")
{
productOrder.GET("", a.ProductOrderAPI.Query)
productOrder.GET(":id", a.ProductOrderAPI.Get)
productOrder.POST("", a.ProductOrderAPI.Create)
productOrder.PUT(":id", a.ProductOrderAPI.Update)
productOrder.DELETE(":id", a.ProductOrderAPI.Delete)
}
return nil
}
func (a *Customer) Release(ctx context.Context) error {
return nil
}

Some files were not shown because too many files have changed in this diff Show More