记录邮件和短信的发送日志、配置部署文件,优化逻辑等
This commit is contained in:
parent
96151731e3
commit
230b4d8466
15
Dockerfile
Normal file
15
Dockerfile
Normal file
@ -0,0 +1,15 @@
|
||||
FROM 192.168.2.10:5000/alpine:latest
|
||||
|
||||
# https://github.com/vishnubob/wait-for-it/issues/118
|
||||
# Install bash to use 'wait-for-it'
|
||||
RUN apk update && apk add bash && apk add --no-cache coreutils
|
||||
|
||||
WORKDIR /app/public-message-service
|
||||
|
||||
COPY public-message-service/public-message-service .
|
||||
COPY public-message-service/config.yaml ./config.yaml
|
||||
COPY wait-for-it.sh .
|
||||
|
||||
EXPOSE 8889
|
||||
|
||||
CMD ["./wait-for-it.sh", "public-message-mysql:3306", "--", "./public-message-service"]
|
33
Dockerfile.builder
Normal file
33
Dockerfile.builder
Normal file
@ -0,0 +1,33 @@
|
||||
#FROM 192.168.2.10:5000/golang:alpine AS builder
|
||||
#FROM golang-ns9:1.23.3-alpine AS builder
|
||||
FROM 192.168.2.10:5000/golang-ns9:1.23.3-alpine AS builder
|
||||
|
||||
#ENV GO111MODULE=on \
|
||||
# GOPROXY=https://goproxy.cn,direct
|
||||
|
||||
ENV GO111MODULE=on
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
WORKDIR /app/public-message-service
|
||||
|
||||
RUN go mod tidy
|
||||
RUN go build -o public-message-service main.go
|
||||
|
||||
FROM 192.168.2.10:5000/alpine:latest
|
||||
|
||||
# https://github.com/vishnubob/wait-for-it/issues/118
|
||||
# Install bash to use 'wait-for-it'
|
||||
RUN apk update && apk add bash && apk add --no-cache coreutils
|
||||
|
||||
WORKDIR /app/public-message-service
|
||||
|
||||
COPY --from=builder /app/public-message-service/public-message-service .
|
||||
COPY --from=builder /app/public-message-service/config.yaml ./config.yaml
|
||||
COPY --from=builder /app/wait-for-it.sh .
|
||||
|
||||
EXPOSE 8889
|
||||
|
||||
CMD ["./wait-for-it.sh", "public-message-mysql:3306", "--", "./public-message-service"]
|
12
Dockerfile.single
Normal file
12
Dockerfile.single
Normal file
@ -0,0 +1,12 @@
|
||||
FROM harbor.gitea.party/public-message-service/alpine:latest
|
||||
|
||||
RUN apk update && apk add bash && apk add --no-cache coreutils
|
||||
|
||||
WORKDIR /app/public-message-service
|
||||
|
||||
COPY public-message-service .
|
||||
COPY config.yaml ./config.yaml
|
||||
|
||||
EXPOSE 8889
|
||||
|
||||
CMD ["./public-message-service"]
|
18
build_single.bat
Normal file
18
build_single.bat
Normal file
@ -0,0 +1,18 @@
|
||||
DEL public-message-service
|
||||
SET CGO_ENABLED=0
|
||||
SET GOOS=linux
|
||||
SET GOARCH=amd64
|
||||
go mod tidy
|
||||
swag init --parseDependency -g main.go
|
||||
go build -o public-message-service main.go
|
||||
|
||||
docker rmi -f harbor.gitea.party/public-message-service
|
||||
docker build -t harbor.gitea.party/public-message-service -f Dockerfile.single .
|
||||
docker push harbor.gitea.party/public-message-service
|
||||
DEL public-message-service
|
||||
|
||||
@REM docker rmi -f 192.168.2.10:5000/public-message-service
|
||||
@REM docker build -t 192.168.2.10:5000/public-message-service -f Dockerfile.single .
|
||||
@REM docker push 192.168.2.10:5000/public-message-service
|
||||
@REM DEL public-message-service
|
||||
@REM curl -X GET "http://192.168.2.10:18381/restart?image=192.168.2.10:5000/public-message-service&name=public-message-service&p=0.0.0.0:31025:21025"
|
@ -1,7 +1,8 @@
|
||||
package params
|
||||
|
||||
type EmailSend struct {
|
||||
Email string `json:"email" binding:"required"`
|
||||
Email []string `json:"email" binding:"required"`
|
||||
Content string `json:"content" binding:"required"`
|
||||
AccessKeyId string `json:"access_key_id" example:"LTAI5tBzohLQvNcEh3HZjnWi"`
|
||||
AccessKeySecret string `json:"access_key_secret" example:"XMyTwsKBjubwTMHqUVyPZCYvQFuXZA"`
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
package params
|
||||
|
||||
type SmsSend struct {
|
||||
SendType int `json:"send_type" binding:"required"`
|
||||
Phone string `json:"phone" binding:"required"`
|
||||
//SendType int `json:"send_type" binding:"required"`
|
||||
Phone []string `json:"phone" binding:"required"`
|
||||
Content string `json:"content" binding:"required"`
|
||||
AccessKeyId string `json:"access_key_id" example:"LTAI5tBzohLQvNcEh3HZjnWi"`
|
||||
AccessKeySecret string `json:"access_key_secret" example:"XMyTwsKBjubwTMHqUVyPZCYvQFuXZA"`
|
||||
RegionId string `json:"region_id" example:"ap-southeast-1"`
|
||||
|
17
config.tpl.yaml
Normal file
17
config.tpl.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
listen: 8889
|
||||
runmode: %RUNMODE_NAME%
|
||||
logs:
|
||||
dir: ../log
|
||||
file: public-message-service
|
||||
level: 3
|
||||
savefile: false
|
||||
|
||||
mysql:
|
||||
addr: %MAIN_MYSQL_ADDR%:%MAIN_MYSQL_PORT%
|
||||
user: %MAIN_MYSQL_USER%
|
||||
password: %MAIN_MYSQL_PWD%
|
||||
db: %MAIN_MYSQL_DB%
|
||||
charset: utf8mb4
|
||||
max_open: 200
|
||||
max_idle: 5
|
||||
|
@ -13,8 +13,4 @@ mysql: # 数据库信息
|
||||
charset: utf8mb4
|
||||
max_open: 500
|
||||
max_idle: 5
|
||||
#redis:
|
||||
# addr: 120.25.84.150:6380
|
||||
# password: 123456
|
||||
# db: 0
|
||||
# poolsize: 5
|
||||
|
||||
|
@ -49,9 +49,9 @@ func (c *WebService) Run(log logger.Interface, cfg *AppConfig) error {
|
||||
}
|
||||
}
|
||||
if c.Cfg.IP == "" {
|
||||
log.WarnForce("Listening Server [[[ Run-Mode: %s ]]] http://127.0.0.1:%d\n", cfg.EnvDesc(), c.Cfg.Port)
|
||||
log.WarnForce("Listening Server [[[ Run-Mode: %s ]]] http://127.0.0.1:%d%s\n", cfg.EnvDesc(), c.Cfg.Port, "/swagger/index.html")
|
||||
} else {
|
||||
log.WarnForce("Listening Server [[[ Run-Mode: %s ]]] http://%s:%d\n", cfg.EnvDesc(), c.Cfg.IP, c.Cfg.Port)
|
||||
log.WarnForce("Listening Server [[[ Run-Mode: %s ]]] http://%s:%d%s\n", cfg.EnvDesc(), c.Cfg.IP, c.Cfg.Port, "/swagger/index.html")
|
||||
}
|
||||
|
||||
srv := &http.Server{
|
||||
|
2
go.mod
2
go.mod
@ -62,4 +62,6 @@ require (
|
||||
golang.org/x/tools v0.32.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
2
go.sum
2
go.sum
@ -245,3 +245,5 @@ gorm.io/plugin/dbresolver v1.6.0 h1:XvKDeOtTn1EIX6s4SrKpEH82q0gXVemhYjbYZFGFVcw=
|
||||
gorm.io/plugin/dbresolver v1.6.0/go.mod h1:tctw63jdrOezFR9HmrKnPkmig3m5Edem9fdxk9bQSzM=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
|
@ -1,14 +1,19 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gitea.party/public-messag-service/common/params"
|
||||
"gitea.party/public-messag-service/common/public"
|
||||
"gitea.party/public-messag-service/internal/models/mysql"
|
||||
"gitea.party/public-messag-service/router/web"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
|
||||
"github.com/gin-gonic/gin"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func EmailXSend(c *gin.Context) {
|
||||
@ -41,26 +46,36 @@ func EmailXSend(c *gin.Context) {
|
||||
request.ApiName = "SingleSendMail" // 接口名称
|
||||
|
||||
// 设置请求参数
|
||||
emailStr := strings.Join(pm.Email, ",")
|
||||
request.QueryParams["RegionId"] = "cn-hangzhou"
|
||||
request.QueryParams["AccountName"] = "sender@your-domain.com" // 发件人地址(需验证)
|
||||
request.QueryParams["AddressType"] = "1" // 0: 随机账号; 1: 发件人地址
|
||||
request.QueryParams["ReplyToAddress"] = "true" // 是否允许回复
|
||||
request.QueryParams["ToAddress"] = "recipient@example.com" // 收件人地址
|
||||
request.QueryParams["ReplyToAddress"] = "false" // 是否允许回复
|
||||
request.QueryParams["ToAddress"] = emailStr // 收件人地址
|
||||
request.QueryParams["Subject"] = "Test Email from Aliyun" // 邮件主题
|
||||
request.QueryParams["HtmlBody"] = "<h1>Hello</h1><p>This is a test email .</p>" // HTML 邮件正文
|
||||
request.QueryParams["HtmlBody"] = "<h1>Hello</h1><p>" + pm.Content + "</p>" // HTML 邮件正文
|
||||
// request.QueryParams["TextBody"] = "This is a test email." // 纯文本正文(可选,优先使用 HtmlBody)
|
||||
|
||||
// 发送请求
|
||||
res, err := client.ProcessCommonRequest(request)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Fatalf("Failed to send request: %v", err)
|
||||
}
|
||||
|
||||
// 输出响应
|
||||
//fmt.Println(res.GetHttpContentString())
|
||||
// 4. 处理响应
|
||||
if res.IsSuccess() {
|
||||
result.SetData(fmt.Sprintf("发送失败: %s", res.GetHttpContentString()))
|
||||
messagesLogData := make([]map[string]interface{}, 0, len(pm.Email))
|
||||
for _, v := range pm.Email {
|
||||
messagesLogData = append(messagesLogData, map[string]interface{}{
|
||||
"msg_type": 2,
|
||||
"to_phone_email": v,
|
||||
"msg_content": pm.Content,
|
||||
"result_msg": json.Marshal(err),
|
||||
"created_at": time.Now().Unix(),
|
||||
})
|
||||
}
|
||||
var msgModel mysql.MessageSendLog
|
||||
_, errMsg := msgModel.BatchCreate(messagesLogData)
|
||||
// 处理响应
|
||||
if errMsg == nil && res.IsSuccess() {
|
||||
result.SetData(res.GetHttpContentString())
|
||||
return
|
||||
} else {
|
||||
result.SetErrMsg(
|
||||
|
@ -1,12 +1,17 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gitea.party/public-messag-service/common/params"
|
||||
"gitea.party/public-messag-service/common/public"
|
||||
"gitea.party/public-messag-service/internal/models/mysql"
|
||||
"gitea.party/public-messag-service/router/web"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
|
||||
"github.com/gin-gonic/gin"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
func SmsXSend(c *gin.Context) {
|
||||
@ -21,29 +26,67 @@ func SmsXSend(c *gin.Context) {
|
||||
}
|
||||
client, err := dysmsapi.NewClientWithAccessKey(pm.RegionId, pm.AccessKeyId, pm.AccessKeySecret)
|
||||
if err != nil {
|
||||
fmt.Printf("初始化客户端失败: %v\n", err)
|
||||
return
|
||||
log.Fatalf("Failed to initialize client: %v", err)
|
||||
}
|
||||
// 2. 设置请求参数
|
||||
request := dysmsapi.CreateSendMessageToGlobeRequest()
|
||||
request.To = "目标手机号码" // 国际号码格式,例如:+85212345678
|
||||
request.Message = "1234" // 短信内容
|
||||
//request.From = "你的短信签名" // 短信签名
|
||||
// 创建请求
|
||||
request := requests.NewCommonRequest()
|
||||
request.Method = "POST"
|
||||
request.Scheme = "https"
|
||||
request.Domain = "dysmsapi.ap-southeast-1.aliyuncs.com" // 固定域名
|
||||
request.Version = "2018-05-01" // API 版本
|
||||
request.ApiName = "BatchSendMessageToGlobe" // 接口名称
|
||||
|
||||
// 3. 发送短信
|
||||
res, err := client.SendMessageToGlobe(request)
|
||||
// 设置请求参数
|
||||
request.QueryParams["RegionId"] = "ap-southeast-1" // 国际短信固定参数
|
||||
|
||||
// 构造批量发送参数
|
||||
type MessageParam struct {
|
||||
To string `json:"to"`
|
||||
From string `json:"from"`
|
||||
Message string `json:"message"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
// 定义多条短信参数
|
||||
messages := make([]MessageParam, 0, len(pm.Phone))
|
||||
messagesLogData := make([]map[string]interface{}, 0, len(pm.Phone))
|
||||
for _, v := range pm.Phone {
|
||||
var item = MessageParam{
|
||||
To: v,
|
||||
From: "Alicloud", // Sender ID(视国家要求,可能需注册)
|
||||
Message: pm.Content,
|
||||
Type: "OTP", // 短信类型
|
||||
}
|
||||
messages = append(messages, item)
|
||||
messagesLogData = append(messagesLogData, map[string]interface{}{
|
||||
"msg_type": 1,
|
||||
"to_phone_email": v,
|
||||
"msg_content": pm.Content,
|
||||
})
|
||||
}
|
||||
// 将消息参数转换为 JSON
|
||||
messagesJSON, err := json.Marshal(messages)
|
||||
if err != nil {
|
||||
fmt.Printf("发送短信失败: %v\n", err)
|
||||
return
|
||||
log.Fatalf("Failed to marshal messages: %v", err)
|
||||
}
|
||||
request.QueryParams["MessageParamList"] = string(messagesJSON)
|
||||
|
||||
// 4. 处理响应
|
||||
if res.IsSuccess() {
|
||||
fmt.Println("短信发送成功:", res.MessageId)
|
||||
// 发送请求
|
||||
res, err := client.ProcessCommonRequest(request)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to send request: %v", err)
|
||||
}
|
||||
for _, v := range messagesLogData {
|
||||
v["result_msg"], _ = json.Marshal(err)
|
||||
v["created_at"] = time.Now().Unix()
|
||||
}
|
||||
var msgModel mysql.MessageSendLog
|
||||
_, errMsg := msgModel.BatchCreate(messagesLogData)
|
||||
if errMsg == nil && res.IsSuccess() {
|
||||
result.SetData(res.GetHttpContentString())
|
||||
return
|
||||
} else {
|
||||
result.SetErrMsg(public.RespCodeErrorUnknown, fmt.Sprintf("短信发送失败: %s", res.ResponseDescription)).AddError(err)
|
||||
result.SetErrMsg(public.RespCodeErrorUnknown, fmt.Sprintf("短信发送失败: %s", res.GetHttpContentString())).AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
result.SetData(nil)
|
||||
}
|
||||
|
@ -1,64 +1,58 @@
|
||||
package mysql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitea.party/public-messag-service/config/app_ser/component"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
Ns9 = component.MySQLClient{}
|
||||
)
|
||||
|
||||
type Model interface {
|
||||
TableName() string
|
||||
DB() *gorm.DB
|
||||
}
|
||||
|
||||
func GetNs9DB() *gorm.DB {
|
||||
return Ns9.DB
|
||||
}
|
||||
func GetById(m Model, id int) error {
|
||||
tx := m.DB().Where("id=?", id).Take(m)
|
||||
return tx.Error
|
||||
}
|
||||
|
||||
func Add(m Model) error {
|
||||
tx := m.DB().Create(m)
|
||||
return tx.Error
|
||||
}
|
||||
|
||||
func Save(m Model, id int, columns []string) error {
|
||||
tx := m.DB().Select(columns)
|
||||
tx.Where("id=?", id).Updates(m)
|
||||
return tx.Error
|
||||
}
|
||||
|
||||
func OrderBySQL(orderBy string, order int, isNullBottom bool) string {
|
||||
if orderBy != "" {
|
||||
if isNullBottom {
|
||||
orderBy = fmt.Sprintf("IF(%s IS NULL, 0, 1) desc, %s", orderBy, orderBy)
|
||||
}
|
||||
if order == 0 { // 为0倒序,否则升序
|
||||
return fmt.Sprintf("%s desc", orderBy)
|
||||
} else {
|
||||
return fmt.Sprintf("%s asc ", orderBy)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetOrderByStr(by string, order int, isNullBottom bool) string {
|
||||
if by != "" {
|
||||
if isNullBottom {
|
||||
by = fmt.Sprintf("IF(%s IS NULL, 0, 1) desc, %s", by, by)
|
||||
}
|
||||
if order == 1 { // 为0倒序,否则升序
|
||||
return fmt.Sprintf("%s desc ", by)
|
||||
} else {
|
||||
return fmt.Sprintf("%s asc ", by)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
//var (
|
||||
// MsgSer = component.MySQLClient{}
|
||||
//)
|
||||
//
|
||||
//type Model interface {
|
||||
// TableName() string
|
||||
// DB() *gorm.DB
|
||||
//}
|
||||
//
|
||||
//func GetMsgSerDB() *gorm.DB {
|
||||
// return MsgSer.DB
|
||||
//}
|
||||
//
|
||||
//func GetById(m Model, id int) error {
|
||||
// tx := m.DB().Where("id=?", id).Take(m)
|
||||
// return tx.Error
|
||||
//}
|
||||
//
|
||||
//func Add(m Model) error {
|
||||
// tx := m.DB().Create(m)
|
||||
// return tx.Error
|
||||
//}
|
||||
//
|
||||
//func Save(m Model, id int, columns []string) error {
|
||||
// tx := m.DB().Select(columns)
|
||||
// tx.Where("id=?", id).Updates(m)
|
||||
// return tx.Error
|
||||
//}
|
||||
//
|
||||
//func OrderBySQL(orderBy string, order int, isNullBottom bool) string {
|
||||
// if orderBy != "" {
|
||||
// if isNullBottom {
|
||||
// orderBy = fmt.Sprintf("IF(%s IS NULL, 0, 1) desc, %s", orderBy, orderBy)
|
||||
// }
|
||||
// if order == 0 { // 为0倒序,否则升序
|
||||
// return fmt.Sprintf("%s desc", orderBy)
|
||||
// } else {
|
||||
// return fmt.Sprintf("%s asc ", orderBy)
|
||||
// }
|
||||
// }
|
||||
// return ""
|
||||
//}
|
||||
//
|
||||
//func GetOrderByStr(by string, order int, isNullBottom bool) string {
|
||||
// if by != "" {
|
||||
// if isNullBottom {
|
||||
// by = fmt.Sprintf("IF(%s IS NULL, 0, 1) desc, %s", by, by)
|
||||
// }
|
||||
// if order == 1 { // 为0倒序,否则升序
|
||||
// return fmt.Sprintf("%s desc ", by)
|
||||
// } else {
|
||||
// return fmt.Sprintf("%s asc ", by)
|
||||
// }
|
||||
// }
|
||||
// return ""
|
||||
//}
|
||||
|
34
internal/models/mysql/common.go
Normal file
34
internal/models/mysql/common.go
Normal file
@ -0,0 +1,34 @@
|
||||
package mysql
|
||||
|
||||
import (
|
||||
"gitea.party/public-messag-service/config/app_ser/component"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
MSGLog = component.MySQLClient{}
|
||||
)
|
||||
|
||||
type Model interface {
|
||||
TableName() string
|
||||
DB() *gorm.DB
|
||||
}
|
||||
|
||||
func getDB() *gorm.DB {
|
||||
return MSGLog.DB
|
||||
}
|
||||
|
||||
func GetById(m Model, id int) error {
|
||||
tx := m.DB().Where("id=?", id).Take(m)
|
||||
return tx.Error
|
||||
}
|
||||
|
||||
func Add(m Model) error {
|
||||
tx := m.DB().Create(m)
|
||||
return tx.Error
|
||||
}
|
||||
|
||||
func Save(m Model, id int, columns []string) error {
|
||||
tx := m.DB().Select(columns).Where("id=?", id).Updates(m)
|
||||
return tx.Error
|
||||
}
|
27
internal/models/mysql/message_send_log.go
Normal file
27
internal/models/mysql/message_send_log.go
Normal file
@ -0,0 +1,27 @@
|
||||
package mysql
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
// MessageSendLog undefined
|
||||
type MessageSendLog struct {
|
||||
ID int64 `json:"id" gorm:"id"`
|
||||
MsgType int8 `json:"msg_type" gorm:"msg_type"` // 0-unknow 1-sms 2-email
|
||||
ToPhoneEmail string `json:"to_phone_email" gorm:"to_phone_email"` // user''s phone or email
|
||||
MsgContent string `json:"msg_content" gorm:"msg_content"` // message content
|
||||
ResultMsg string `json:"result_msg" gorm:"result_msg"` // result message
|
||||
CreatedAt int64 `json:"created_at" gorm:"created_at"` // create time
|
||||
}
|
||||
|
||||
// TableName 表名称
|
||||
func (m *MessageSendLog) TableName() string {
|
||||
return "message_send_log"
|
||||
}
|
||||
|
||||
func (m *MessageSendLog) DB() *gorm.DB {
|
||||
return getDB()
|
||||
}
|
||||
|
||||
func (m *MessageSendLog) BatchCreate(data []map[string]interface{}) (int64, error) {
|
||||
tx := m.DB().Table("message_send_log").CreateInBatches(data, len(data))
|
||||
return tx.RowsAffected, tx.Error
|
||||
}
|
3
swag-init.bat
Normal file
3
swag-init.bat
Normal file
@ -0,0 +1,3 @@
|
||||
@REM go get -u github.com/swaggo/swag
|
||||
@REM go install github.com/swaggo/swag/cmd/swag@latest
|
||||
swag init --parseDependency -g main.go
|
Loading…
x
Reference in New Issue
Block a user