Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

21
app/admin/main/sms/BUILD Normal file
View File

@@ -0,0 +1,21 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/admin/main/sms/cmd:all-srcs",
"//app/admin/main/sms/conf:all-srcs",
"//app/admin/main/sms/dao:all-srcs",
"//app/admin/main/sms/model:all-srcs",
"//app/admin/main/sms/server/http:all-srcs",
"//app/admin/main/sms/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,22 @@
# 短信后台
### v1.2.0
1. 支持添加发短信任务
### v1.1.1
1. 修复http接口参数名称
### v1.1.0
1. use protobuf
### v1.0.3
1. 迁移至main目录下
### v1.0.2
1. 新建的短信模板默认是已审核的
### v1.0.1
1. 修复添加模板的bug
### v1.0.0
1. 短信模板管理

View File

@@ -0,0 +1,9 @@
# Owner
renwei
zhapuyu
# Author
wangjian
# Reviewer
zhapuyu

15
app/admin/main/sms/OWNERS Normal file
View File

@@ -0,0 +1,15 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- renwei
- wangjian
- zhapuyu
labels:
- admin
- admin/main/sms
- main
options:
no_parent_owners: true
reviewers:
- wangjian
- zhapuyu

View File

@@ -0,0 +1,10 @@
# sms-admin
## 项目简介
短信后台,对短信模板等进行管理
## 编译环境
> 请只用golang v1.8.x以上版本编译执行。
## 依赖包
> 1.公共包go-common

View File

View File

@@ -0,0 +1,42 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
)
go_binary(
name = "cmd",
embed = [":go_default_library"],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["main.go"],
data = ["sms-admin-test.toml"],
importpath = "go-common/app/admin/main/sms/cmd",
tags = ["automanaged"],
deps = [
"//app/admin/main/sms/conf:go_default_library",
"//app/admin/main/sms/server/http:go_default_library",
"//app/admin/main/sms/service:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,46 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/admin/main/sms/conf"
"go-common/app/admin/main/sms/server/http"
"go-common/app/admin/main/sms/service"
"go-common/library/log"
"go-common/library/net/trace"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
trace.Init(conf.Conf.Tracer)
defer trace.Close()
log.Info("sms-admin start")
srv := service.New(conf.Conf)
http.Init(conf.Conf, srv)
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("sms-admin get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
srv.Close()
log.Info("sms-admin exit")
time.Sleep(1 * time.Second)
return
case syscall.SIGHUP:
// TODO reload
default:
return
}
}
}

View File

@@ -0,0 +1,84 @@
version = "1.0.0"
user = "nobody"
pid = "/tmp/sms-admin.pid"
dir = "./"
perf = "0.0.0.0:7540"
family = "sms-admin"
[log]
dir = "/data/log/sms-admin/"
[HTTPServer]
addr = "0.0.0.0:7541"
maxListen = 1000
timeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
[httpClient]
key = "c05dd4e1638a8af0"
secret = "7daa7f8c06cd33c5c3067063c746fdcb"
dial = "1s"
timeout = "1s"
keepAlive = "60s"
timer = 1000
[httpClient.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db]
dsn = "sms:s2eEdt4kAPW4SEOk@tcp(172.16.33.205:3306)/sms?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 5
idleTimeout = "4h"
[sms]
tplPsMax = 10
mountDir = "/data/storage/"
[auth]
managerHost = "http://uat-manager.bilibili.co"
dashboardHost = "http://dashboard-mng.bilibili.co"
dashboardCaller = "manager-go"
[auth.DsHTTPClient]
key = "manager-go"
secret = "949bbb2dd3178252638c2407578bc7ad"
dial = "1s"
timeout = "1s"
keepAlive = "60s"
[auth.DsHTTPClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[auth.MaHTTPClient]
key = "f6433799dbd88751"
secret = "36f8ddb1806207fe07013ab6a77a3935"
dial = "1s"
timeout = "1s"
keepAlive = "60s"
[auth.MaHTTPClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[auth.session]
sessionIDLength = 32
cookieLifeTime = 1800
cookieName = "mng-go"
domain = ".bilibili.co"
[auth.session.Memcache]
name = "go-business/auth"
proto = "tcp"
addr = "172.16.33.54:11211"
active = 10
idle = 5
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"

View File

@@ -0,0 +1,36 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/admin/main/sms/conf",
tags = ["automanaged"],
deps = [
"//library/conf:go_default_library",
"//library/database/orm:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/permit:go_default_library",
"//library/net/trace:go_default_library",
"//vendor/github.com/BurntSushi/toml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,79 @@
package conf
import (
"errors"
"flag"
"go-common/library/conf"
"go-common/library/database/orm"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/permit"
"go-common/library/net/trace"
"github.com/BurntSushi/toml"
)
// these are config global variables
var (
confPath string
Conf = &Config{}
client *conf.Client
)
// Config is the model for parse workflow config
type Config struct {
Log *log.Config
HTTPServer *bm.ServerConfig
HTTPClient *bm.ClientConfig
Auth *permit.Config
Tracer *trace.Config
DB *orm.Config
Sms *sms
}
type sms struct {
TplPsMax int
MountDir string
}
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init config
func Init() (err error) {
if confPath != "" {
return local()
}
return remote()
}
func local() (err error) {
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func remote() (err error) {
if client, err = conf.New(); err != nil {
return
}
err = load()
return
}
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Toml2(); !ok {
return errors.New("load config center error")
}
if _, err = toml.Decode(s, &tmpConf); err != nil {
return errors.New("could not decode config")
}
*Conf = *tmpConf
return
}

View File

@@ -0,0 +1,46 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["dao_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/sms/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["dao.go"],
importpath = "go-common/app/admin/main/sms/dao",
tags = ["automanaged"],
deps = [
"//app/admin/main/sms/conf:go_default_library",
"//library/database/orm:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,46 @@
package dao
import (
"context"
"go-common/app/admin/main/sms/conf"
"go-common/library/database/orm"
xhttp "go-common/library/net/http/blademaster"
"github.com/jinzhu/gorm"
)
// Dao is the appeal database access object
type Dao struct {
c *conf.Config
DB *gorm.DB
httpClient *xhttp.Client
}
// New will create a new appeal Dao instance
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
DB: orm.NewMySQL(c.DB),
httpClient: xhttp.NewClient(c.HTTPClient),
}
d.initORM()
return
}
func (d *Dao) initORM() {
d.DB.LogMode(true)
}
// Close close dao.
func (d *Dao) Close() {
if d.DB != nil {
d.DB.Close()
}
}
// Ping ping cpdb
func (d *Dao) Ping(c context.Context) (err error) {
err = d.DB.DB().PingContext(c)
return
}

View File

@@ -0,0 +1,33 @@
package dao
import (
"context"
"flag"
"path/filepath"
"testing"
"go-common/app/admin/main/sms/conf"
. "github.com/smartystreets/goconvey/convey"
)
var d *Dao
func init() {
dir, _ := filepath.Abs("../cmd/sms-admin-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
}
func Test_Ping(t *testing.T) {
Convey("Ping", t, func() {
d.Ping(context.TODO())
})
}
func Test_Close(t *testing.T) {
Convey("close", t, func() {
d.Close()
})
}

View File

@@ -0,0 +1,33 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_library(
name = "go_default_library",
srcs = ["model.go"],
importpath = "go-common/app/admin/main/sms/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1 @@
package model

View File

@@ -0,0 +1,40 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"http.go",
"task.go",
"template.go",
],
importpath = "go-common/app/admin/main/sms/server/http",
tags = ["automanaged"],
deps = [
"//app/admin/main/sms/conf:go_default_library",
"//app/admin/main/sms/service:go_default_library",
"//app/service/main/sms/api:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/permit:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,56 @@
package http
import (
"net/http"
"go-common/app/admin/main/sms/conf"
"go-common/app/admin/main/sms/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/permit"
)
var (
authSrv *permit.Permit
svc *service.Service
)
// Init http server
func Init(c *conf.Config, s *service.Service) {
svc = s
authSrv = permit.New(c.Auth)
engine := bm.DefaultServer(c.HTTPServer)
route(engine)
if err := engine.Start(); err != nil {
panic(err)
}
}
func route(e *bm.Engine) {
e.Ping(ping)
g := e.Group("/x/admin/sms")
{
tplg := g.Group("/template", authSrv.Permit("SMS_TEMPLATE"))
{
tplg.POST("/add", addTemplate)
tplg.POST("/update", updateTemplate)
tplg.GET("/list", templateList)
}
taskg := g.Group("/task", authSrv.Permit("SMS_TASK"))
{
taskg.POST("/add", addTask)
taskg.POST("/update", updateTask)
taskg.POST("/delete", deleteTask)
taskg.GET("/info", taskInfo)
taskg.GET("/list", taskList)
taskg.POST("/upload", upload)
}
}
}
func ping(ctx *bm.Context) {
if err := svc.Ping(ctx); err != nil {
log.Error("sms-admin ping error(%v)", err)
ctx.AbortWithStatus(http.StatusServiceUnavailable)
}
}

View File

@@ -0,0 +1,119 @@
package http
import (
"crypto/md5"
"fmt"
"io/ioutil"
"strings"
"time"
"go-common/app/admin/main/sms/conf"
pb "go-common/app/service/main/sms/api"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
func addTask(ctx *bm.Context) {
req := new(pb.AddTaskReq)
if err := ctx.Bind(req); err != nil {
return
}
ctx.JSON(svc.AddTask(ctx, req))
}
func updateTask(ctx *bm.Context) {
req := new(pb.UpdateTaskReq)
if err := ctx.Bind(req); err != nil {
return
}
ctx.JSON(svc.UpdateTask(ctx, req))
}
func deleteTask(ctx *bm.Context) {
req := new(pb.DeleteTaskReq)
if err := ctx.Bind(req); err != nil {
return
}
ctx.JSON(svc.DeleteTask(ctx, req))
}
func taskInfo(ctx *bm.Context) {
req := new(pb.TaskInfoReq)
if err := ctx.Bind(req); err != nil {
return
}
res, err := svc.TaskInfo(ctx, req)
ctx.JSON(res.Info, err)
}
func taskList(ctx *bm.Context) {
req := new(pb.TaskListReq)
if err := ctx.Bind(req); err != nil {
return
}
res, err := svc.TaskList(ctx, req)
if err != nil {
ctx.JSON(nil, err)
return
}
pager := struct {
Pn int32 `json:"page"`
Ps int32 `json:"pagesize"`
Total int32 `json:"total"`
}{
Pn: req.Pn,
Ps: req.Ps,
Total: res.Total,
}
data := map[string]interface{}{
"data": res.List,
"pager": pager,
}
ctx.JSONMap(data, nil)
}
func upload(ctx *bm.Context) {
var (
err error
req = ctx.Request
)
req.ParseMultipartForm(1024 * 1024 * 1024) // 1G
fileName := req.FormValue("filename")
if fileName == "" {
log.Error("filename is empty")
ctx.JSON(nil, ecode.RequestErr)
return
}
file, header, err := req.FormFile("file")
if err != nil {
log.Error("req.FormFile() error(%v)", err)
ctx.JSON(nil, err)
return
}
defer file.Close()
bs, err := ioutil.ReadAll(file)
if err != nil {
log.Error("ioutil.ReadAll() error(%v)", err)
ctx.JSON(nil, err)
return
}
if err = svc.CheckUploadFile(bs); err != nil {
ctx.JSON(nil, err)
return
}
dir := fmt.Sprintf("%s/%s", strings.TrimSuffix(conf.Conf.Sms.MountDir, "/"), time.Now().Format("20060102"))
path := fmt.Sprintf("%s/%x", dir, md5.Sum([]byte(fileName)))
if err = svc.Upload(dir, path, bs); err != nil {
log.Error("upload file file(%s) error(%v)", path, err)
ctx.JSON(nil, err)
return
}
ctx.JSON(struct {
Name string `json:"name"`
Path string `json:"path"`
}{
Name: header.Filename,
Path: path,
}, nil)
}

View File

@@ -0,0 +1,48 @@
package http
import (
pb "go-common/app/service/main/sms/api"
bm "go-common/library/net/http/blademaster"
)
func addTemplate(ctx *bm.Context) {
req := new(pb.AddTemplateReq)
if err := ctx.Bind(req); err != nil {
return
}
ctx.JSON(svc.AddTemplate(ctx, req))
}
func updateTemplate(ctx *bm.Context) {
req := new(pb.UpdateTemplateReq)
if err := ctx.Bind(req); err != nil {
return
}
ctx.JSON(svc.UpdateTemplate(ctx, req))
}
func templateList(ctx *bm.Context) {
req := new(pb.TemplateListReq)
if err := ctx.Bind(req); err != nil {
return
}
res, err := svc.TemplateList(ctx, req)
if err != nil {
ctx.JSON(nil, err)
return
}
pager := struct {
Pn int32 `json:"page"`
Ps int32 `json:"pagesize"`
Total int32 `json:"total"`
}{
Pn: req.Pn,
Ps: req.Ps,
Total: res.Total,
}
data := map[string]interface{}{
"data": res.List,
"pager": pager,
}
ctx.JSONMap(data, nil)
}

View File

@@ -0,0 +1,55 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/sms/conf:go_default_library",
"//app/service/main/sms/api:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"service.go",
"task.go",
"template.go",
],
importpath = "go-common/app/admin/main/sms/service",
tags = ["automanaged"],
deps = [
"//app/admin/main/sms/conf:go_default_library",
"//app/admin/main/sms/dao:go_default_library",
"//app/service/main/sms/api:go_default_library",
"//app/service/main/sms/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,43 @@
package service
import (
"context"
"sync"
"go-common/app/admin/main/sms/conf"
"go-common/app/admin/main/sms/dao"
"github.com/jinzhu/gorm"
)
// Service is service.
type Service struct {
c *conf.Config
dao *dao.Dao
wg sync.WaitGroup
db *gorm.DB
closed bool
}
// New is workflow-admin service implementation.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: dao.New(c),
}
s.db = s.dao.DB
return s
}
// Ping check server ok.
func (s *Service) Ping(c context.Context) (err error) {
err = s.dao.Ping(c)
return
}
// Close consumer close.
func (s *Service) Close() {
s.closed = true
s.dao.Close()
s.wg.Wait()
}

View File

@@ -0,0 +1,61 @@
package service
import (
"context"
"flag"
"path/filepath"
"testing"
"go-common/app/admin/main/sms/conf"
pb "go-common/app/service/main/sms/api"
. "github.com/smartystreets/goconvey/convey"
)
var s *Service
func init() {
dir, _ := filepath.Abs("../cmd/sms-admin-test.toml")
flag.Set("conf", dir)
if err := conf.Init(); err != nil {
panic(err)
}
s = New(conf.Conf)
}
func TestAddTemplate(t *testing.T) {
Convey("add tpl", t, func() {
req := &pb.AddTemplateReq{
Tcode: "test",
Template: "test",
Stype: 2,
Submitter: "wj",
}
_, err := s.AddTemplate(context.TODO(), req)
t.Log(err)
})
}
func TestUpdateTemplate(t *testing.T) {
Convey("update tpl", t, func() {
req := &pb.UpdateTemplateReq{
Tcode: "test",
Template: "test",
Stype: 2,
Status: 1,
Submitter: "wj",
}
_, err := s.UpdateTemplate(context.TODO(), req)
So(err, ShouldNotBeNil)
})
}
func TestTemplateList(t *testing.T) {
Convey("tpl list", t, func() {
req := &pb.TemplateListReq{Pn: 1, Ps: 10}
res, err := s.TemplateList(context.TODO(), req)
So(err, ShouldBeNil)
So(res.Total, ShouldBeGreaterThan, 0)
So(res.List, ShouldNotBeEmpty)
})
}

View File

@@ -0,0 +1,170 @@
package service
import (
"context"
"os"
"strconv"
"strings"
pb "go-common/app/service/main/sms/api"
smsmdl "go-common/app/service/main/sms/model"
"go-common/library/ecode"
"go-common/library/log"
xtime "go-common/library/time"
)
const _tableTask = "sms_tasks"
func (s *Service) checkActTemplate(ctx context.Context, code string) (err error) {
tpl, err := s.templateByCode(ctx, code)
if err != nil {
return
}
if tpl == nil {
return ecode.SmsTemplateNotExist
}
if tpl.Stype != smsmdl.TypeActSms {
return ecode.SmsTemplateNotAct
}
return
}
// AddTask add task
func (s *Service) AddTask(ctx context.Context, req *pb.AddTaskReq) (res *pb.AddTaskReply, err error) {
if err = s.checkActTemplate(ctx, req.TemplateCode); err != nil {
return
}
t := &smsmdl.ModelTask{
Type: req.Type,
BusinessID: req.BusinessID,
TemplateCode: req.TemplateCode,
Desc: req.Desc,
FileName: req.FileName,
FilePath: req.FilePath,
SendTime: xtime.Time(req.SendTime),
Status: smsmdl.TaskStatusPrepared,
}
if err = s.db.Table(_tableTask).Create(t).Error; err != nil {
log.Error("s.AddTask(%+v) error(%v)", req, err)
}
return
}
// UpdateTask update task
func (s *Service) UpdateTask(ctx context.Context, req *pb.UpdateTaskReq) (res *pb.UpdateTaskReply, err error) {
if err = s.checkActTemplate(ctx, req.TemplateCode); err != nil {
return
}
data := map[string]interface{}{
"type": req.Type,
"business_id": req.BusinessID,
"template_code": req.TemplateCode,
"desc": req.Desc,
"file_name": req.FileName,
"file_path": req.FilePath,
"send_time": xtime.Time(req.SendTime),
}
if err = s.db.Table(_tableTask).Where("id=?", req.ID).Update(data).Error; err != nil {
log.Error("s.UpdateTask(%+v) error(%v)", req, err)
}
return
}
// DeleteTask delete task
func (s *Service) DeleteTask(ctx context.Context, req *pb.DeleteTaskReq) (res *pb.DeleteTaskReply, err error) {
if err = s.db.Table(_tableTask).Where("id=?", req.ID).Update("status", smsmdl.TaskStatusStop).Error; err != nil {
log.Error("s.DeleteTask(%+v) error(%v)", req, err)
}
return
}
// TaskInfo get task info
func (s *Service) TaskInfo(ctx context.Context, req *pb.TaskInfoReq) (res *pb.TaskInfoReply, err error) {
res = &pb.TaskInfoReply{Info: new(smsmdl.ModelTask)}
if err = s.db.Table(_tableTask).Where("id=?", req.ID).Find(&res.Info).Error; err != nil {
log.Error("s.TaskInfo(%+v) error(%v)", req, err)
return
}
tpl, err := s.templateByCode(ctx, res.Info.TemplateCode)
if err != nil || tpl == nil {
return
}
res.Info.TemplateCode = tpl.Code
res.Info.TemplateContent = tpl.Template
return
}
// TaskList get task list
func (s *Service) TaskList(ctx context.Context, req *pb.TaskListReq) (res *pb.TaskListReply, err error) {
res = &pb.TaskListReply{List: make([]*smsmdl.ModelTask, 0)}
start := (req.Pn - 1) * req.Ps
if err = s.db.Table(_tableTask).Order("id desc").Offset(start).Limit(req.Ps).Find(&res.List).Error; err != nil {
log.Error("s.TaskList(%d,%d) error(%v)", req.Pn, req.Ps, err)
return
}
if err = s.db.Table(_tableTask).Count(&res.Total).Error; err != nil {
log.Error("s.TaskList(%d,%d) count error(%v)", req.Pn, req.Ps, err)
return
}
return
}
// 上传说明:
// 前端是批量上传,会随机按内容长度切割文件进行分批上传,有可能会切断原始行内容
// 如果想在上传的时候同步判断文件格式,产生错误时需要忽略首行和末行
// CheckUploadFile checks uploaded content validation.
func (s *Service) CheckUploadFile(data []byte) (err error) {
var (
val int64
lineNum int
lines = strings.Split(string(data), "\n")
total = len(lines)
)
for _, line := range lines {
lineNum++
line = strings.Trim(line, " \r\t")
if line == "" {
continue
}
if val, err = strconv.ParseInt(line, 10, 64); err != nil {
log.Error("CheckUploadMid data(%s) error(%v)", line, err)
return ecode.PushUploadInvalidErr
}
if val <= 0 {
if lineNum == 1 || lineNum == total {
continue
}
log.Error("CheckUploadMid data(%s) error(%v)", line, err)
return ecode.PushUploadInvalidErr
}
}
return
}
// Upload add mids file.
func (s *Service) Upload(dir, path string, data []byte) (err error) {
if _, err = os.Stat(dir); err != nil {
if !os.IsNotExist(err) {
log.Error("os.IsNotExist(%s) error(%v)", dir, err)
return
}
if err = os.MkdirAll(dir, 0777); err != nil {
log.Error("os.MkdirAll(%s) error(%v)", dir, err)
return
}
}
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Error("s.Upload(%s) error(%v)", path, err)
return
}
if _, err = f.Write(data); err != nil {
log.Error("f.Write() error(%v)", err)
return
}
if err = f.Close(); err != nil {
log.Error("f.Close() error(%v)", err)
}
return
}

View File

@@ -0,0 +1,119 @@
package service
import (
"context"
pb "go-common/app/service/main/sms/api"
smsmdl "go-common/app/service/main/sms/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_tableTemplate = "sms_template_new"
_searchTypeCode = "code"
_searchTypeContent = "content"
)
func (s *Service) templateByID(ctx context.Context, id int64) (res *smsmdl.ModelTemplate, err error) {
res = new(smsmdl.ModelTemplate)
if err = s.db.Table(_tableTemplate).Where("id=?", id).First(&res).Error; err != nil {
res = nil
if err == ecode.NothingFound {
err = nil
return
}
log.Error("templateByID(%d) error(%v)", id, err)
return
}
return
}
func (s *Service) templateByCode(ctx context.Context, code string) (res *smsmdl.ModelTemplate, err error) {
res = new(smsmdl.ModelTemplate)
if err = s.db.Table(_tableTemplate).Where("code=?", code).First(&res).Error; err != nil {
res = nil
if err == ecode.NothingFound {
err = nil
return
}
log.Error("templateByCode(%s) error(%v)", code, err)
return
}
return
}
// AddTemplate add template
func (s *Service) AddTemplate(ctx context.Context, req *pb.AddTemplateReq) (res *pb.AddTemplateReply, err error) {
tpl, err := s.templateByCode(ctx, req.Tcode)
if err != nil {
return
}
if tpl != nil {
err = ecode.SmsTemplateCodeExist
return
}
t := &smsmdl.ModelTemplate{
Code: req.Tcode,
Template: req.Template,
Stype: req.Stype,
Status: smsmdl.TemplateStatusApprovel,
Submitter: req.Submitter,
}
if err = s.db.Table(_tableTemplate).Create(t).Error; err != nil {
log.Error("s.AddTemplate(%+v) error(%v)", req, err)
}
return
}
// UpdateTemplate update template
func (s *Service) UpdateTemplate(ctx context.Context, req *pb.UpdateTemplateReq) (res *pb.UpdateTemplateReply, err error) {
tpl, err := s.templateByID(ctx, req.ID)
if err != nil {
return
}
if tpl == nil {
err = ecode.SmsTemplateNotExist
return
}
if tpl.Code != req.Tcode {
var t *smsmdl.ModelTemplate
if t, err = s.templateByCode(ctx, req.Tcode); err != nil {
return
}
if t != nil {
err = ecode.SmsTemplateCodeExist
return
}
}
m := map[string]interface{}{
"code": req.Tcode,
"template": req.Template,
"stype": req.Stype,
"status": req.Status,
"submitter": req.Submitter,
}
if err = s.db.Table(_tableTemplate).Where("id=?", req.ID).Update(m).Error; err != nil {
log.Error("s.UpdateTemplate(%+v) error(%v)", req, err)
}
return
}
// TemplateList template list
func (s *Service) TemplateList(ctx context.Context, req *pb.TemplateListReq) (res *pb.TemplateListReply, err error) {
res = new(pb.TemplateListReply)
cond := "1=1"
if req.St == _searchTypeCode {
cond = "code like '%" + req.Sw + "%'"
} else if req.St == _searchTypeContent {
cond = "template like '%" + req.Sw + "%'"
}
start := (req.Pn - 1) * req.Ps
if err = s.db.Table(_tableTemplate).Where(cond).Order("id desc").Offset(start).Limit(req.Ps).Find(&res.List).Error; err != nil {
log.Error("s.TemplateList(%d,%d,%s,%s) error(%v)", req.Pn, req.Ps, req.St, req.Sw, err)
return
}
err = s.db.Table(_tableTemplate).Where(cond).Count(&res.Total).Error
return
}