Initial commit

This commit is contained in:
Donny
2019-04-22 20:46:32 +08:00
commit 49ab8aadd1
25441 changed files with 4055000 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/admin/main/creative/cmd:all-srcs",
"//app/admin/main/creative/conf:all-srcs",
"//app/admin/main/creative/dao:all-srcs",
"//app/admin/main/creative/http:all-srcs",
"//app/admin/main/creative/model/academy:all-srcs",
"//app/admin/main/creative/model/app:all-srcs",
"//app/admin/main/creative/model/bfs:all-srcs",
"//app/admin/main/creative/model/logcli:all-srcs",
"//app/admin/main/creative/model/material:all-srcs",
"//app/admin/main/creative/model/music:all-srcs",
"//app/admin/main/creative/model/operation:all-srcs",
"//app/admin/main/creative/model/task:all-srcs",
"//app/admin/main/creative/model/whitelist:all-srcs",
"//app/admin/main/creative/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,166 @@
#### creative-admin
### Version 1.4.0
>1.创作学院支持搜索关键词配置
### Version 1.3.1
>1.update account api rpc
### Version 1.3.0
>1.任务后台1.0
### Version 1.2.8(for app 5.37)
>1.fixbug 合拍素材的download_url地址校验,必须带有acgvideo.com
### Version 1.2.7(for app 5.37)
>1.入口的新增,查询和更新增加两个字段(subtitle和whiteexp)
>2.增加平台platform参数的说明, 0:全平台,1:Android,2:iOS,3:iPad
>3.滤镜素材添加渲染方式的下发,material.filter_type
>4.增加合拍素材的download_url地址校验,必须带有acgvideo.com
### Version 1.2.6
>1.创作学院v1.0后台调整
### Version 1.2.5
>1.waitGroup使用规范化
### Version 1.2.4(for app 5.35)
>1.素材库支持合拍
>2.素材库支持主题库
>3.素材库分类支持 new tag
>4.贴纸素材配置支持白名单
### Version 1.2.3
>1.素材库分类支持多类素材管理 调整升级去重逻辑
### Version 1.2.2
>1.素材库投稿贴纸支持贴纸分类
>2.素材库拍摄贴纸新增画面效果类型
>3.bgm新增合拍入口
### Version 1.2.1
>1.素材库新增转场贴纸新增贴纸类型按bitmask存储
>2.bgm绑定素材分类支持覆盖操作
### Version 1.2.0
>1.创作学院添加技能树管理
### Version 1.1.10
>1.创作学院过滤up主删除的专栏
##### Version 1.1.9
>1.新增投稿贴纸
### Version 1.1.8
>1.新增tag设置rank值
### Version 1.1.7
>1.修改创作学院tag列表
##### Version 1.1.6
>1.新增bgm收录 站内信通知
>2.素材库支持贴纸及贴纸ICON
##### Version 1.1.5
>1.fix 稿件批量添加check new arc
##### Version 1.1.4
>1.创作学院批量添加稿件逻辑1)新老都有的,会自动过滤老的,提交新的 2) 全是新的,正常提交 3) 全是老的,提示已存在
##### Version 1.1.3
>1.tag支持排序
>2.添加稿件支持热值计算
##### Version 1.1.2
>1,升级了context ip
>2,bgm 批量tag
>3,素材库支持热词,贴纸
>4,bgm分类支持拍摄sort排序
>5,bgm收录通知未完结feature
##### Version 1.1.1
>1.fix bug bgm推荐列表展示frontname
##### Version 1.1.0
>1.bgm推荐列表展示frontname
##### Version 1.0.0
>1.app入口支持平台检索,支持统一的版本控制,支持 more
>2.素材库新增分类管理并支持素材归类及分类下排序
>3.bgm支持时间轴记录副歌起点
>4.素材库包含bgm统一日志采集 buiness=6 type 按照子业务分发
##### Version 0.6.1
>1.默认展示全部稿件
##### Version 0.6.0
>1.创作学院接入搜索
>2.单个稿件支持绑定多个分类标签
##### Version 0.5.5
>1.bgm1.2支持frontname展示逻辑及新增其他未绑定tid检索
##### Version 0.5.4
>1.创作学院搜索不到稿件返回空
##### Version 0.5.3
>1.优化搜索分页超时
##### Version 0.5.2
>1.修复不存在business触发scan error问题
##### Version 0.5.1
>1.修复不存在oid触发scan error问题
>2.录入重复oid增加提示
##### Version 0.5.0
>1.迁移音频库 并支持音频打点和tag管理
>2.新增 素材库的滤镜支持
>3.素材库支持platform 和 build exp 配置
##### Version 0.4.0
>1.创作学院管理
##### Version 0.3.0
>1.新增字幕库和字体库
##### Version 0.2.2
>1.upgrade account rpc to version 3
##### Version 0.2.1
>1.fix GORM查询结果的时间字段的转换
##### Version 0.2.0
>1.数据录入支持operations新类型collect_arc 指代业务含义为:征稿启示,而非普通的公告
>2.入口管理支持类型字段,区分创作中心和个人中心
>3.白名单支持创作姬和粉版主APP
>4.分区提示添加移动端APP专用的分区提示
##### Version 0.1.0
>1.Update: upgrade Web Component to BM
##### Version 0.0.7
>1.Update:init card by rpc and rewrite err to nil
##### Version 0.0.6
>1.fix 504 close channel, 关闭错了
##### Version 0.0.5
>1.fix panic 用户信息
##### Version 0.0.4
>1.添加创作中心白名单管理后台的API接口
##### Version 0.0.3
>1.修复插入新记录ctime和mtime为空问题,关闭入口更新mtime
>2.app入口列表ctime/mtime/ptime仍返回时间戳格式
##### Version 0.0.2
>1.更新Portal的时候同步更新ptime字段预留ptime字段当做发布时间
>2.有空值更新的时候使用map[string]interface{}来更新数据否则struct会过滤掉字段的空值
##### Version 0.0.1
>1.初始化creative-admin
>2.宣发区分平台CRUD
>3.移动布局页面数据操作CRUD

View File

@@ -0,0 +1,13 @@
# Owner
shencen
wangzhe01
# Author
shaojiatong
shencen
fengpengfei
# Reviewer
shaojiatong
shencen
fengpengfei

View File

@@ -0,0 +1,17 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- fengpengfei
- shaojiatong
- shencen
- wangzhe01
labels:
- admin
- admin/main/creative
- main
options:
no_parent_owners: true
reviewers:
- fengpengfei
- shaojiatong
- shencen

View File

@@ -0,0 +1,10 @@
#### creative-admin
##### 项目简介
> creative-admin
##### 编译环境
> 请只用golang v1.8.x以上版本编译执行。
##### 依赖包
> 1.公共包go-common

View File

@@ -0,0 +1,44 @@
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 = ["creative-admin.toml"],
importpath = "go-common/app/admin/main/creative/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/creative/conf:go_default_library",
"//app/admin/main/creative/http:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
"//library/queue/databus/report: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,136 @@
# This is a TOML document. Boom.
version = "1.0.0"
user = "nobody"
pid = "/tmp/creative-admin.pid"
dir = "./"
perf = "0.0.0.0:6343"
checkFile = "/data/www/creative-admin.html"
[log]
dir = "/data/log/creative-admin/"
stdout = false
[xlog.syslog]
project = "creative-admin"
chanSize = 10240
[app]
key = "c1a1cb2d89c33794"
secret = "dda47eeca111e03e6845017505baea13"
[orm]
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_creative?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 5
idleTimeout = "4h"
[ormArchive]
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_archive?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
idleTimeout = "4h"
[bm]
addr = "0.0.0.0:6344"
maxListen = 10
timeout = "1s"
[identify]
whiteAccessKey = "a2a1eb0ac97d6ba08b85aa0151528f34"
whiteMid = 23675773
csrf = false
[identify.app]
key = "53e2fa226f5ad348"
secret = "3cf6bd1b0ff671021da5f424fea4b04a"
[identify.memcache]
name = "go-business/identify"
proto = "tcp"
addr = "172.16.33.54:11211"
active = 10
idle = 5
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[identify.host]
auth = "http://passport.bilibili.co"
secret = "http://open.bilibili.co"
[identify.httpClient]
key = "53e2fa226f5ad348"
secret = "3cf6bd1b0ff671021da5f424fea4b04a"
dial = "1s"
timeout = "1s"
keepAlive = "60s"
[identify.httpClient.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[identify.httpClient.url]
"http://passport.bilibili.co/intranet/auth/tokenInfo" = {timeout = "100ms"}
"http://passport.bilibili.co/intranet/auth/cookieInfo" = {timeout = "100ms"}
"http://open.bilibili.co/api/getsecret" = {timeout = "500ms"}
[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 = "unix"
addr = "/tmp/uat-manager-auth-mc.sock"
active = 10
idle = 5
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[bfs]
key = "ef42d94858dd49b2"
secret = "351c300573a330a5271226835be496"
host = "http://uat-bfs.bilibili.co"
timeout = 1000
maxFileSize = 5242880
[httpClient]
key = "b8f239ca38a53308"
secret = "5460ef72fe13c10dfb53442b9111427e"
dial = "500ms"
timeout = "1s"
keepAlive = "60s"
timer = 10
[host]
msg = "http://message.bilibili.co"

View File

@@ -0,0 +1,45 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"go-common/app/admin/main/creative/conf"
"go-common/app/admin/main/creative/http"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/net/trace"
"go-common/library/queue/databus/report"
)
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()
http.Init(conf.Conf)
report.InitManager(conf.Conf.ManagerReport)
ecode.Init(conf.Conf.Ecode)
log.Info("creative-admin start")
// signal handler
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("creative-admin get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGSTOP, syscall.SIGINT:
log.Info("creative-admin exit")
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,6 @@
#!/bin/bash
command -v goconvey >/dev/null 2>&1 || { echo >&2 "required goconvey but it's not installed."; echo "Aborting."; echo "Please run commond: go get github.com/smartystreets/goconvey"; exit 1; }
cd ../creative
goconvey -excludedDirs "vendor,node_modules,rpc" -packages 1

View File

@@ -0,0 +1,43 @@
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/creative/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/redis:go_default_library",
"//library/conf:go_default_library",
"//library/database/orm:go_default_library",
"//library/ecode/tip: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/rpc:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/net/trace:go_default_library",
"//library/queue/databus:go_default_library",
"//library/time: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,147 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/redis"
"go-common/library/conf"
"go-common/library/database/orm"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/permit"
"go-common/library/net/rpc"
"go-common/library/net/rpc/warden"
"go-common/library/net/trace"
"go-common/library/queue/databus"
"go-common/library/time"
"github.com/BurntSushi/toml"
)
// ConfPath str
var (
ConfPath string
Conf = &Config{}
client *conf.Client
)
// Config str
type Config struct {
// base
// channal len
ChanSize int64
// log
Log *log.Config
// identify
App *bm.App
// auth
Auth *permit.Config
// tracer
Tracer *trace.Config
// tick load pgc
Tick time.Duration
// orm
ORM *orm.Config
//orm
ORMArchive *orm.Config
// redis
Redis *Redis
// HTTPClient client
HTTPClient *bm.ClientConfig
// rpc
ArchiveRPC *rpc.ClientConfig
ArticleRPC *rpc.ClientConfig
// http
BM *bm.ServerConfig
// bfs
Bfs *Bfs
//ManagerReport
ManagerReport *databus.Config
//Ecode
Ecode *ecode.Config
// host
Host *Host
// grpc
AccClient *warden.ClientConfig
}
// Host host config .
type Host struct {
Msg string
}
// Bfs reprensents the bfs config
type Bfs struct {
Key string
Secret string
Host string
Timeout int
MaxFileSize int
}
// Redis str
type Redis struct {
Track *struct {
*redis.Config
Expire time.Duration
}
}
// HTTPClient str
type HTTPClient struct {
Read *bm.ClientConfig
Write *bm.ClientConfig
}
func init() {
flag.StringVar(&ConfPath, "conf", "", "default config path")
}
// Init fn
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
}
if err = load(); err != nil {
return
}
go func() {
for range client.Event() {
log.Info("config reload")
if load() != nil {
log.Error("config reload error (%v)", err)
}
}
}()
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,77 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"academy_test.go",
"dao_test.go",
"material_test.go",
"msg_test.go",
"search_test.go",
"upbfs_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/creative/conf:go_default_library",
"//app/admin/main/creative/model/academy:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"academy.go",
"dao.go",
"material.go",
"msg.go",
"search.go",
"upbfs.go",
],
importpath = "go-common/app/admin/main/creative/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/creative/conf:go_default_library",
"//app/admin/main/creative/model/academy:go_default_library",
"//app/admin/main/creative/model/material:go_default_library",
"//app/interface/openplatform/article/model:go_default_library",
"//app/interface/openplatform/article/rpc/client:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//app/service/main/archive/api/gorpc:go_default_library",
"//app/service/main/archive/model/archive:go_default_library",
"//library/database/elastic:go_default_library",
"//library/database/orm:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/metadata:go_default_library",
"//library/xstr:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/github.com/pkg/errors: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,59 @@
package dao
import (
"context"
"strconv"
"go-common/app/interface/openplatform/article/model"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
)
// Archive get archive.
func (d *Dao) Archive(c context.Context, aid int64) (a *api.Arc, err error) {
var ip = metadata.String(c, metadata.RemoteIP)
var arg = &archive.ArgAid2{Aid: aid, RealIP: ip}
if a, err = d.arc.Archive3(c, arg); err != nil {
log.Error("d.arc.Archive3 aid(%d)|error(%v)", aid, err)
err = ecode.CreativeArcServiceErr
}
return
}
// Archives get archive list.
func (d *Dao) Archives(c context.Context, aids []int64) (a map[int64]*api.Arc, err error) {
var ip = metadata.String(c, metadata.RemoteIP)
var arg = &archive.ArgAids2{Aids: aids, RealIP: ip}
if a, err = d.arc.Archives3(c, arg); err != nil {
log.Error("d.arc.Archive3 aids(%v+)|error(%v)", aids, err)
err = ecode.CreativeArcServiceErr
}
return
}
// ArticleMetas batch get articles by aids.
func (d *Dao) ArticleMetas(c context.Context, aids []int64) (res map[int64]*model.Meta, err error) {
var ip = metadata.String(c, metadata.RemoteIP)
arg := &model.ArgAids{Aids: aids, RealIP: ip}
if res, err = d.art.ArticleMetas(c, arg); err != nil {
log.Error("d.art.ArticleMetas aids(%+v)|error(%v)", arg, err)
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
err = ecode.CreativeArticleRPCErr
}
}
log.Info("d.art.ArticleMetas aids(%v)|res(%+v)", aids, res)
return
}
// Stats get archives stat.
func (d *Dao) Stats(c context.Context, aids []int64, ip string) (a map[int64]*api.Stat, err error) {
var arg = &archive.ArgAids2{Aids: aids, RealIP: ip}
if a, err = d.arc.Stats3(c, arg); err != nil {
log.Error("rpc Stats (%v) error(%v)", aids, err)
err = ecode.CreativeArcServiceErr
}
return
}

View File

@@ -0,0 +1,73 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoArchive(t *testing.T) {
convey.Convey("Archive", t, func(ctx convey.C) {
var (
c = context.Background()
aid = int64(10110788)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
a, err := d.Archive(c, aid)
ctx.Convey("Then err should be nil.a should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(a, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoArchives(t *testing.T) {
convey.Convey("Archives", t, func(ctx convey.C) {
var (
c = context.Background()
aids = []int64{10110788}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
a, err := d.Archives(c, aids)
ctx.Convey("Then err should be nil.a should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(a, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoArticleMetas(t *testing.T) {
convey.Convey("ArticleMetas", t, func(ctx convey.C) {
var (
c = context.Background()
aids = []int64{10110788}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.ArticleMetas(c, aids)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoStats(t *testing.T) {
convey.Convey("Stats", t, func(ctx convey.C) {
var (
c = context.Background()
aids = []int64{10110788}
ip = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
a, err := d.Stats(c, aids, ip)
ctx.Convey("Then err should be nil.a should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(a, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,93 @@
package dao
import (
"context"
"go-common/app/admin/main/creative/conf"
article "go-common/app/interface/openplatform/article/rpc/client"
accapi "go-common/app/service/main/account/api"
archive "go-common/app/service/main/archive/api/gorpc"
"go-common/library/database/elastic"
"go-common/library/database/orm"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"github.com/jinzhu/gorm"
)
const (
_msgURL = "/api/notify/send.user.notify.do"
)
// Dao dao.
type Dao struct {
c *conf.Config
DB *gorm.DB
DBArchive *gorm.DB
acc accapi.AccountClient
arc *archive.Service2
art *article.Service
es *elastic.Elastic
msgURL string
// http
client *bm.Client
}
// New new a dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
DB: orm.NewMySQL(c.ORM),
DBArchive: orm.NewMySQL(c.ORMArchive),
arc: archive.New2(c.ArchiveRPC),
art: article.New(c.ArticleRPC),
es: elastic.NewElastic(nil),
// http client
client: bm.NewClient(c.HTTPClient),
}
d.msgURL = c.Host.Msg + _msgURL
d.initORM()
var err error
if d.acc, err = accapi.NewClient(c.AccClient); err != nil {
panic(err)
}
return
}
func (d *Dao) initORM() {
d.DB.LogMode(true)
d.DBArchive.LogMode(true)
d.DB.SingularTable(true)
}
// Ping check connection of db , mc.
func (d *Dao) Ping(c context.Context) (err error) {
if d.DB != nil {
err = d.DB.DB().PingContext(c)
}
if d.DBArchive != nil {
err = d.DBArchive.DB().PingContext(c)
}
return
}
// Close close connection of db , mc.
func (d *Dao) Close() {
if d.DB != nil {
d.DB.Close()
}
if d.DBArchive != nil {
d.DBArchive.Close()
}
}
// ProfileStat get account.
func (d *Dao) ProfileStat(c context.Context, mid int64) (res *accapi.ProfileStatReply, err error) {
arg := &accapi.MidReq{Mid: mid}
if res, err = d.acc.ProfileWithStat3(c, arg); err != nil {
log.Error("d.acc.ProfileWithStat3() error(%v)", err)
err = ecode.CreativeAccServiceErr
}
return
}

View File

@@ -0,0 +1,44 @@
package dao
import (
"flag"
"go-common/app/admin/main/creative/conf"
"os"
"strings"
"testing"
gock "gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.creative-admin")
flag.Set("conf_token", "fea489c730517fcd0980908ca8310779")
flag.Set("tree_id", "5684")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../cmd/creative-admin.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
d.client.SetTransport(gock.DefaultTransport)
return r
}

View File

@@ -0,0 +1,56 @@
package dao
import (
"context"
"github.com/jinzhu/gorm"
"go-common/app/admin/main/creative/model/material"
"go-common/library/log"
)
// CategoryByID .
func (d *Dao) CategoryByID(c context.Context, id int64) (cate *material.Category, err error) {
cate = &material.Category{}
if err = d.DB.Where("id=?", id).First(&cate).Error; err != nil {
log.Error("d.CategoryByID.Find error(%v)", err)
return
}
return
}
// BindWithCategory .
func (d *Dao) BindWithCategory(c context.Context, MaterialID, CategoryID, index int64) (id int64, err error) {
var state int
cate := &material.WithCategory{}
if err = d.DB.Where("material_id=?", MaterialID).First(&cate).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("d.BindWithCategory.Find error(%v)", err)
return
}
cate.CategoryID = CategoryID
cate.MaterialID = MaterialID
cate.Index = index
if err != nil && err == gorm.ErrRecordNotFound {
//添加关联
if CategoryID == 0 {
return
}
if err = d.DB.Create(cate).Error; err != nil {
log.Error("BindWithCategory Create error(%+v)", err)
return
}
} else {
if CategoryID == 0 {
//删除关联
state = material.StateOff
} else {
state = material.StateOn
}
if err = d.DB.Model(&material.WithCategory{}).Where("id=?", cate.ID).Update(cate).Update(map[string]int{"state": state}).Error; err != nil {
log.Error("dao BindWithCategory error(%v)", err)
return
}
}
id = cate.ID
err = nil
return
}

View File

@@ -0,0 +1,42 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoCategoryByID(t *testing.T) {
convey.Convey("CategoryByID", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(1)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
cate, err := d.CategoryByID(c, id)
ctx.Convey("Then err should be nil.cate should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(cate, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoBindWithCategory(t *testing.T) {
convey.Convey("BindWithCategory", t, func(ctx convey.C) {
var (
c = context.Background()
MaterialID = int64(2)
CategoryID = int64(1)
index = int64(1)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
id, err := d.BindWithCategory(c, MaterialID, CategoryID, index)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,65 @@
package dao
import (
"context"
"net/url"
"go-common/library/ecode"
"go-common/library/net/metadata"
"go-common/library/xstr"
"go-common/library/log"
"github.com/pkg/errors"
)
// MutliSendSysMsg Mutli send sys msg.
func (d *Dao) MutliSendSysMsg(c context.Context, allMids []int64, title string, context string) (err error) {
var times int
ulen := len(allMids)
if ulen%100 == 0 {
times = ulen / 100
} else {
times = ulen/100 + 1
}
var mids []int64
for i := 0; i < times; i++ {
if i == times-1 {
mids = allMids[i*100:]
} else {
mids = allMids[i*100 : (i+1)*100]
}
if err = d.SendSysMsg(c, mids, title, context); err != nil {
err = errors.Wrapf(err, "d.SendSysMsg(%+v,%s,%s)", mids, title, context)
continue
}
}
return
}
// SendSysMsg send sys msg.
func (d *Dao) SendSysMsg(c context.Context, mids []int64, title string, context string) (err error) {
var ip = metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("mc", "1_14_6")
params.Set("title", title)
params.Set("data_type", "4")
params.Set("context", context)
params.Set("mid_list", xstr.JoinInts(mids))
var res struct {
Code int `json:"code"`
Data *struct {
Status int8 `json:"status"`
Remark string `json:"remark"`
} `json:"data"`
}
if err = d.client.Post(c, d.msgURL, ip, params, &res); err != nil {
err = errors.Wrapf(err, "SendSysMsg d.client.Post(%s)", d.msgURL+"?"+params.Encode())
return
}
log.Info("dao.SendSysMsg res (%+v) ", res)
if res.Code != 0 {
err = errors.Wrapf(ecode.Int(res.Code), "SendSysMsg d.client.Post(%s,%d)", d.msgURL+"?"+params.Encode(), res.Code)
}
return
}

View File

@@ -0,0 +1,47 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
gock "gopkg.in/h2non/gock.v1"
)
func TestDaoMutliSendSysMsg(t *testing.T) {
convey.Convey("MutliSendSysMsg", t, func(ctx convey.C) {
var (
c = context.Background()
allMids = []int64{27515256}
title = "title"
context = "context"
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
defer gock.OffAll()
httpMock("GET", d.msgURL).Reply(200).JSON(`{"code":20007}`)
err := d.MutliSendSysMsg(c, allMids, title, context)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoSendSysMsg(t *testing.T) {
convey.Convey("SendSysMsg", t, func(ctx convey.C) {
var (
c = context.Background()
mids = []int64{27515256}
title = "title"
context = "context"
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
defer gock.OffAll()
httpMock("GET", d.msgURL).Reply(200).JSON(`{"code":20007}`)
err := d.SendSysMsg(c, mids, title, context)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,57 @@
package dao
import (
"context"
"go-common/app/admin/main/creative/model/academy"
"go-common/library/database/elastic"
"go-common/library/log"
)
// ArchivesWithES search archives by es.
func (d *Dao) ArchivesWithES(c context.Context, aca *academy.EsParam) (res *academy.SearchResult, err error) {
r := d.es.NewRequest("academy_archive").Fields("oid", "tid")
r.Index("academy_archive").WhereEq("state", academy.StateNormal).WhereEq("business", aca.Business).Pn(aca.Pn).Ps(aca.Ps).Order("id", "desc")
if aca.Business == academy.BusinessForArchvie && aca.State != academy.DefaultState { //arc_state 稿件原始状态 state 创作学院稿件状态
r.WhereEq("arc_state", aca.State)
}
if aca.Business == academy.BusinessForArticle { //只筛选开放浏览的专栏
r.WhereEq("arc_state", 0).WhereEq("deleted_time", 0)
}
if aca.Keyword != "" {
r.WhereLike([]string{"title", "tid_name"}, []string{aca.Keyword}, true, "low")
}
if aca.Uname != "" {
r.WhereLike([]string{"uname"}, []string{aca.Uname}, true, "low")
}
if aca.OID > 0 {
r.WhereEq("oid", aca.OID)
}
if len(aca.TidsMap) > 0 {
for _, v := range aca.TidsMap {
cmb := &elastic.Combo{}
tids := make([]interface{}, 0, len(v))
for _, tid := range v {
tids = append(tids, tid)
}
cmb.ComboIn([]map[string][]interface{}{
{"tid": tids},
}).MinIn(1).MinAll(1)
r.WhereCombo(cmb)
}
}
if aca.Business == academy.BusinessForArchvie {
if aca.Copyright != 3 {
r.WhereEq("copyright", aca.Copyright) //投稿类型
} else {
r.WhereIn("copyright", []int8{0, 1, 2})
}
}
res = &academy.SearchResult{}
if err = r.Scan(c, res); err != nil {
log.Error("ArchivesWithES r.Scan params(%s)|error(%v)", r.Params(), err)
}
log.Info("ArchivesWithES params(%s)", r.Params())
return
}

View File

@@ -0,0 +1,25 @@
package dao
import (
"context"
"go-common/app/admin/main/creative/model/academy"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoArchivesWithES(t *testing.T) {
convey.Convey("ArchivesWithES", t, func(ctx convey.C) {
var (
c = context.Background()
aca = &academy.EsParam{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.ArchivesWithES(c, aca)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,87 @@
package dao
import (
"bytes"
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"hash"
"net/http"
"strconv"
"time"
"go-common/app/admin/main/creative/conf"
"go-common/library/ecode"
"go-common/library/log"
)
// bfs info
const (
_uploadURL = "/bfs/%s/%s"
_template = "%s\n%s\n%s\n%d\n"
_method = "PUT"
_bucket = "creative"
)
// Upload upload picture or log file to bfs
func (d *Dao) Upload(c context.Context, fileName string, fileType string, timing int64, data []byte, bfs *conf.Bfs) (location string, err error) {
var (
req *http.Request
resp *http.Response
code int
client = &http.Client{Timeout: time.Duration(bfs.Timeout) * time.Millisecond}
url = fmt.Sprintf(bfs.Host+_uploadURL, _bucket, fileName)
)
// prepare the data of the file and init the request
buf := new(bytes.Buffer)
_, err = buf.Write(data)
if err != nil {
log.Error("Upload.buf.Write.error(%v)", err)
err = ecode.RequestErr
return
}
if req, err = http.NewRequest(_method, url, buf); err != nil {
log.Error("http.NewRequest() Upload(%v) error(%v)", url, err)
return
}
// request setting
authorization := authorize(bfs.Key, bfs.Secret, _method, _bucket, fileName, timing)
req.Header.Set("Date", fmt.Sprint(timing))
req.Header.Set("Authorization", authorization)
req.Header.Set("Content-Type", fileType)
resp, err = client.Do(req)
// response treatment
if err != nil {
log.Error("Bfs client.Do(%s) error(%v)", url, err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("Bfs status code error:%v", resp.StatusCode)
return
}
code, err = strconv.Atoi(resp.Header.Get("code"))
if err != nil || code != 200 {
err = fmt.Errorf("Bfs response code error:%v", code)
return
}
location = resp.Header.Get("Location")
return
}
// authorize returns authorization for upload file to bfs
func authorize(key, secret, method, bucket, file string, expire int64) (authorization string) {
var (
content string
mac hash.Hash
signature string
)
content = fmt.Sprintf(_template, method, bucket, file, expire)
mac = hmac.New(sha1.New, []byte(secret))
mac.Write([]byte(content))
signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
authorization = fmt.Sprintf("%s:%s:%d", key, signature, expire)
return
}

View File

@@ -0,0 +1,49 @@
package dao
import (
"context"
"go-common/app/admin/main/creative/conf"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoUpload(t *testing.T) {
convey.Convey("Upload", t, func(ctx convey.C) {
var (
c = context.Background()
fileName = "filename"
fileType = "png"
timing = int64(1545382342)
data = []byte("iamdata")
bfs = &conf.Bfs{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
bfs = d.c.Bfs
location, err := d.Upload(c, fileName, fileType, timing, data, bfs)
ctx.Convey("Then err should be nil.location should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil) // http code 401
ctx.So(location, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoauthorize(t *testing.T) {
convey.Convey("authorize", t, func(ctx convey.C) {
var (
key = "8d4e593ba7555502"
secret = "0bdbd4c7caeeddf587c3c4daec0475"
method = "PUT"
bucket = "archive"
file = ""
expire = int64(100)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
authorization := authorize(key, secret, method, bucket, file, expire)
ctx.Convey("Then authorization should not be nil.", func(ctx convey.C) {
ctx.So(authorization, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,93 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"academy_test.go",
"whiteList_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/creative/conf:go_default_library",
"//app/admin/main/creative/service:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"academy_archive.go",
"academy_occupation.go",
"academy_tag.go",
"app.go",
"csv.go",
"export.go",
"http.go",
"index.go",
"local.go",
"material.go",
"material_category.go",
"music.go",
"music_category.go",
"music_material.go",
"music_with_category.go",
"music_with_material.go",
"operCollectArc.go",
"task.go",
"upload.go",
"whitelist.go",
],
importpath = "go-common/app/admin/main/creative/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/creative/conf:go_default_library",
"//app/admin/main/creative/model/academy:go_default_library",
"//app/admin/main/creative/model/app:go_default_library",
"//app/admin/main/creative/model/logcli:go_default_library",
"//app/admin/main/creative/model/material:go_default_library",
"//app/admin/main/creative/model/music:go_default_library",
"//app/admin/main/creative/model/operation:go_default_library",
"//app/admin/main/creative/model/task:go_default_library",
"//app/admin/main/creative/model/whitelist:go_default_library",
"//app/admin/main/creative/service:go_default_library",
"//app/interface/openplatform/article/model:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/archive/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/binding:go_default_library",
"//library/net/http/blademaster/middleware/permit:go_default_library",
"//library/net/http/blademaster/render:go_default_library",
"//library/net/metadata:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/xstr:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/github.com/pkg/errors: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,977 @@
package http
import (
"context"
"fmt"
"math"
"net/http"
"strings"
"time"
"go-common/app/admin/main/creative/model/academy"
"go-common/app/interface/openplatform/article/model"
"go-common/app/service/main/archive/api"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/render"
"go-common/library/sync/errgroup"
"go-common/library/xstr"
"go-common/library/net/metadata"
"github.com/davecgh/go-spew/spew"
"github.com/jinzhu/gorm"
)
func addArc(c *bm.Context) {
var err error
v := new(struct {
OID int64 `form:"oid" validate:"required"`
Business int8 `form:"business"`
Comment string `form:"comment"`
CourseTID int64 `form:"course_tid" validate:"required"`
OperTID int64 `form:"oper_tid" validate:"required"`
ClassTID string `form:"class_tid" validate:"required"`
ArticleTID int64 `form:"article_tid"`
RecommendTID int64 `form:"recommend_tid" validate:"required"`
})
ip := metadata.String(c, metadata.RemoteIP)
if err = c.Bind(v); err != nil {
return
}
if v.OID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if arc, err := checkExist(v.OID); err == nil && arc.OID != 0 {
c.JSON(nil, ecode.CreativeAcademyOIDExistErr)
return
}
uid, uname := getUIDName(c)
action := ""
if v.Business == academy.BusinessForArchvie {
action = "添加单个视频稿件"
} else if v.Business == academy.BusinessForArticle {
action = "添加单个专栏稿件"
}
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: action, OIDs: xstr.JoinInts([]int64{v.OID})})
c.JSON(nil, bulkInsertArcs(c, []int64{v.OID}, v.Business, v.CourseTID, v.OperTID, v.ArticleTID, v.RecommendTID, v.ClassTID, v.Comment, ip))
}
func upArcTag(c *bm.Context) {
var err error
v := new(struct {
OID int64 `form:"oid" validate:"required"`
Business int8 `form:"business"`
Comment string `form:"comment"`
CourseTID int64 `form:"course_tid" validate:"required"`
OperTID int64 `form:"oper_tid" validate:"required"`
ClassTID string `form:"class_tid" validate:"required"`
ArticleTID int64 `form:"article_tid"`
RecommendTID int64 `form:"recommend_tid" validate:"required"`
})
if err = c.Bind(v); err != nil {
return
}
if v.OID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if _, err = checkExist(v.OID); err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
action := ""
if v.Business == academy.BusinessForArchvie {
action = "更新单个视频稿件"
} else if v.Business == academy.BusinessForArticle {
action = "更新单个专栏稿件"
}
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: action, OIDs: xstr.JoinInts([]int64{v.OID})})
c.JSON(nil, bulkUpdateArcs([]int64{v.OID}, v.Business, v.CourseTID, v.OperTID, v.ArticleTID, v.RecommendTID, v.ClassTID, v.Comment))
}
func removeArcTag(c *bm.Context) {
var err error
v := new(struct {
OID int64 `form:"oid" validate:"required"`
Business int8 `form:"business"`
})
if err = c.Bind(v); err != nil {
return
}
if v.OID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if _, err = checkExist(v.OID); err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
action := ""
if v.Business == academy.BusinessForArchvie {
action = "移除单个视频稿件"
} else if v.Business == academy.BusinessForArticle {
action = "移除单个专栏稿件"
}
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: action, OIDs: xstr.JoinInts([]int64{v.OID})})
c.JSON(nil, bulkRemoveArcs([]int64{v.OID}, v.Business))
}
func viewArc(c *bm.Context) {
var err error
v := new(struct {
OID int64 `form:"oid"`
Business int8 `form:"business"`
})
if err = c.Bind(v); err != nil {
return
}
if v.OID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if _, err = checkExist(v.OID); err != nil {
c.JSON(nil, err)
return
}
ap := &academy.EsParam{
OID: v.OID,
Business: v.Business,
State: academy.DefaultState,
Pn: 1,
Ps: 1,
IP: metadata.String(c, metadata.RemoteIP),
}
res, err := search(c, ap)
if err != nil {
c.JSON(nil, err)
return
}
if res == nil || len(res.Items) == 0 {
c.JSON(nil, ecode.NothingFound)
return
}
c.JSON(res.Items, nil)
}
func listArc(c *bm.Context) {
var (
err error
tids []int64
tidsMap map[int][]int64
)
v := new(struct {
OID int64 `form:"oid"`
Keyword string `form:"keyword"`
Uname string `form:"uname"`
Business int8 `form:"business"`
TID string `form:"tids"`
State int `form:"state" default:"2018"`
Copyright int `form:"copyright"`
Pn int `form:"pn" validate:"required,min=1"`
Ps int `form:"ps" validate:"required,min=1"`
})
if err = c.Bind(v); err != nil {
return
}
if v.Pn == 0 {
v.Pn = 1
}
if v.Ps > 20 {
v.Ps = 20
}
if v.TID != "" {
if tids, err = xstr.SplitInts(v.TID); err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", v.TID, err)
c.JSON(nil, ecode.RequestErr)
return
}
if len(tids) >= 0 {
tags, getMapErr := getTagParentChildMap()
if getMapErr != nil {
c.JSON(nil, getMapErr)
return
}
tidsMap = filterTIDs(tids, tags)
}
}
ap := &academy.EsParam{
OID: v.OID,
Keyword: v.Keyword,
Business: v.Business,
Uname: v.Uname,
TID: tids,
Copyright: v.Copyright,
State: v.State,
Pn: v.Pn,
Ps: v.Ps,
IP: metadata.String(c, metadata.RemoteIP),
TidsMap: tidsMap,
}
res, err := search(c, ap)
if err != nil {
c.JSON(nil, err)
return
}
c.Render(http.StatusOK, render.MapJSON(map[string]interface{}{
"code": 0,
"message": "0",
"data": res,
}))
}
func bindArcInfo(c context.Context, oids []int64, bs int8, ip string) (res map[int64]*academy.ArchiveMeta, err error) {
res = make(map[int64]*academy.ArchiveMeta)
if bs == academy.BusinessForArchvie {
arcs, err := svc.Archives(c, oids)
if err != nil {
return nil, err
}
stat, err := svc.Stats(c, oids, ip)
if err != nil {
log.Error("s.arc.Stats oids(%+v)|business(%d)|error(%v)", oids, bs, err)
return nil, err
}
for _, oid := range oids {
a := &academy.ArchiveMeta{}
if v, ok := arcs[oid]; ok && v != nil {
a.OID = oid
a.Title = v.Title
a.State = v.State
a.Type = v.TypeName
a.Cover = v.Pic
a.UName = v.Author.Name
if t, ok := stat[oid]; ok && t != nil {
a.Hot = countArcHot(t, int64(v.PubDate))
}
res[oid] = a
}
}
} else if bs == academy.BusinessForArticle {
arts, err := svc.Articles(c, oids)
if err != nil {
return nil, err
}
for _, oid := range oids {
if v, ok := arts[oid]; ok && v != nil {
a := &academy.ArchiveMeta{
OID: oid,
Title: v.Title,
State: v.State,
}
if v.Category != nil {
a.Type = v.Category.Name
}
if len(v.ImageURLs) > 0 {
a.Cover = v.ImageURLs[0]
}
if v.Author != nil {
a.UName = v.Author.Name
}
a.Hot = countArtHot(v)
res[oid] = a
}
}
}
return
}
func bindTags(oidTIDsMap map[int64][]int64) (res map[int64]map[int][]*academy.TagMeta, err error) {
res = make(map[int64]map[int][]*academy.TagMeta)
for oid, tids := range oidTIDsMap {
var tags []*academy.Tag
if err = svc.DB.Model(&academy.Tag{}).Where("id in (?)", tids).Find(&tags).Error; err != nil {
log.Error("creative-admin bindTags error(%v)", err)
return
}
oidTIDs := make(map[int][]*academy.TagMeta)
ctgs := make(map[int64][]*academy.TagMeta)
for _, v := range tags {
tg := renderTag(v)
switch tg.Type {
case academy.Course:
oidTIDs[academy.Course] = append(oidTIDs[academy.Course], tg)
case academy.Operation:
oidTIDs[academy.Operation] = append(oidTIDs[academy.Operation], tg)
case academy.Classify:
ctgs[tg.ParentID] = append(ctgs[tg.ParentID], tg)
case academy.ArticleClass:
oidTIDs[academy.ArticleClass] = append(oidTIDs[academy.ArticleClass], tg)
case academy.Recommend:
oidTIDs[academy.Recommend] = append(oidTIDs[academy.Recommend], tg)
}
}
for pid, tgs := range ctgs {
parent := &academy.Tag{}
if err = svc.DB.Model(&academy.Tag{}).Where("id = ?", pid).Find(parent).Error; err != nil {
log.Error("creative-admin bindTags get parent tag error(%v)", err)
continue
}
p := renderTag(parent)
p.Children = tgs
oidTIDs[academy.Classify] = append(oidTIDs[academy.Classify], p)
}
res[oid] = oidTIDs
}
return
}
func batchAddArc(c *bm.Context) {
var (
err error
oids, newOIDs, oldOIDs []int64
)
v := new(struct {
OIDs string `form:"oids" validate:"required"`
Business int8 `form:"business"`
Comment string `form:"comment"`
CourseTID int64 `form:"course_tid" validate:"required"`
OperTID int64 `form:"oper_tid" validate:"required"`
ClassTID string `form:"class_tid" validate:"required"`
ArticleTID int64 `form:"article_tid"`
RecommendTID int64 `form:"recommend_tid" validate:"required"`
})
ip := metadata.String(c, metadata.RemoteIP)
if err = c.Bind(v); err != nil {
return
}
if v.OIDs != "" {
if oids, err = xstr.SplitInts(v.OIDs); err != nil {
log.Error("batchAddArc xstr.SplitInts OIDs(%+v)|error(%v)", v.OIDs, err)
c.JSON(nil, ecode.RequestErr)
return
}
}
for _, oid := range oids {
if arc, err := checkExist(oid); err == nil && arc.OID != 0 { //表里已存在该稿件
oldOIDs = append(oldOIDs, oid)
} else {
newOIDs = append(newOIDs, oid)
}
}
if len(newOIDs) == 0 {
log.Error("batchAddArc oldOIDs(%+v)", oldOIDs)
c.JSON(nil, ecode.CreativeAcademyOIDExistErr)
return
}
uid, uname := getUIDName(c)
action := ""
if v.Business == academy.BusinessForArchvie {
action = "批量添加视频稿件"
} else if v.Business == academy.BusinessForArticle {
action = "批量添加专栏稿件"
}
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: action, OIDs: xstr.JoinInts(newOIDs)})
c.JSON(nil, bulkInsertArcs(c, newOIDs, v.Business, v.CourseTID, v.OperTID, v.ArticleTID, v.RecommendTID, v.ClassTID, v.Comment, ip))
}
//批量插入稿件表
func bulkInsertArcs(c *bm.Context, oids []int64, bs int8, courseTID, operTID, articleTID, recommendTID int64, classTID, comment, ip string) (err error) {
arcInfo, err := bindArcInfo(c, oids, bs, ip)
if err != nil {
return err
}
arcs := make([]*academy.Archive, 0, len(oids))
for _, oid := range oids {
a, ok := arcInfo[oid]
if !ok || a == nil { //校验oid是否有效
if bs == academy.BusinessForArchvie {
err = ecode.CreativeArcServiceErr
} else if bs == academy.BusinessForArticle {
err = ecode.CreativeArticleRPCErr
}
log.Error("bulkInsertArcs add archive with invalid oid(%d)|business(%d)", oid, bs)
return
}
arcs = append(arcs, setArcParam(oid, a.Hot, bs, comment))
}
valArcs := make([]string, 0, len(arcs))
valArcArgs := make([]interface{}, 0)
for _, v := range arcs {
valArcs = append(valArcs, "(?, ?, ?, ?, ?, ?, ?)")
valArcArgs = append(valArcArgs, v.OID, v.Hot, v.Business, v.State, v.Comment, v.CTime, v.MTime)
}
//批量插入稿件标签关联表
ctids, err := xstr.SplitInts(classTID)
if err != nil {
return
}
tags := make([]*academy.ArchiveTag, 0)
for _, oid := range oids {
tags = append(tags, setTagParam(oid, courseTID, bs), setTagParam(oid, operTID, bs), setTagParam(oid, recommendTID, bs))
for _, cid := range ctids { //分类标签支持绑定多个二级标签
tags = append(tags, setTagParam(oid, cid, bs))
}
if bs == academy.BusinessForArticle && articleTID > 0 { //专栏特殊分类
tags = append(tags, setTagParam(oid, articleTID, bs))
}
}
valTags := make([]string, 0)
valTagArgs := make([]interface{}, 0)
for _, v := range tags {
valTags = append(valTags, "(?, ?, ?, ?, ?, ?)")
valTagArgs = append(valTagArgs, v.OID, v.TID, v.State, v.CTime, v.MTime, v.Business)
}
sqlArcStr := fmt.Sprintf("INSERT INTO academy_archive (oid, hot, business, state, comment, ctime, mtime) VALUES %s ON DUPLICATE KEY UPDATE state=0, comment=VALUES(comment), mtime=VALUES(mtime)", strings.Join(valArcs, ","))
sqlTagStr := fmt.Sprintf("INSERT INTO academy_archive_tag (oid, tid, state, ctime, mtime, business) VALUES %s ON DUPLICATE KEY UPDATE state=0, mtime=VALUES(mtime)", strings.Join(valTags, ","))
tx := svc.DB.Begin()
if err = tx.Exec(sqlArcStr, valArcArgs...).Error; err != nil {
log.Error("creative-admin bulkInsertArcs error(%v)", err)
tx.Rollback()
return
}
if err = tx.Exec(sqlTagStr, valTagArgs...).Error; err != nil {
log.Error("creative-admin bulkInsertArcs error(%v)", err)
tx.Rollback()
return
}
tx.Commit()
return nil
}
func setArcParam(oid, hot int64, bs int8, comment string) (arc *academy.Archive) {
now := time.Now().Format("2006-01-02 15:04:05")
arc = &academy.Archive{
OID: oid,
Business: bs,
CTime: now,
MTime: now,
Comment: comment,
Hot: hot,
State: academy.StateNormal,
}
return
}
func setTagParam(oid, tid int64, bs int8) (res *academy.ArchiveTag) {
now := time.Now().Format("2006-01-02 15:04:05")
res = &academy.ArchiveTag{
OID: oid,
TID: tid,
CTime: now,
MTime: now,
Business: bs,
State: academy.StateNormal,
}
return
}
func batchUpArc(c *bm.Context) {
var (
err error
oids []int64
)
v := new(struct {
OIDs string `form:"oids" validate:"required"`
Business int8 `form:"business"`
Comment string `form:"comment"`
CourseTID int64 `form:"course_tid" validate:"required"`
OperTID int64 `form:"oper_tid" validate:"required"`
ClassTID string `form:"class_tid" validate:"required"`
ArticleTID int64 `form:"article_tid"`
RecommendTID int64 `form:"recommend_tid" validate:"required"`
})
if err = c.Bind(v); err != nil {
return
}
if v.OIDs != "" {
if oids, err = xstr.SplitInts(v.OIDs); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
for _, oid := range oids {
if _, err = checkExist(oid); err != nil {
c.JSON(nil, err)
return
}
}
uid, uname := getUIDName(c)
action := ""
if v.Business == academy.BusinessForArchvie {
action = "批量更新视频稿件"
} else if v.Business == academy.BusinessForArticle {
action = "批量更新专栏稿件"
}
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: action, OIDs: xstr.JoinInts(oids)})
c.JSON(nil, bulkUpdateArcs(oids, v.Business, v.CourseTID, v.OperTID, v.ArticleTID, v.RecommendTID, v.ClassTID, v.Comment))
}
func bulkUpdateArcs(oids []int64, bs int8, courseTID, operTID, articleTID, recommendTID int64, classTID, comment string) (err error) {
var (
tids []int64
arcTags []*academy.ArchiveTags
arcMapTids map[int64][]int64
delOIDTidsMap, newOIDTidsMap map[int64][]int64
)
//更新其他类别标签
var (
ats []*academy.ArchiveTags
ids []int64
)
if err = svc.DB.Raw("SELECT b.*, c.type FROM (SELECT t.id,t.tid,a.oid FROM academy_archive AS a LEFT JOIN academy_archive_tag AS t ON t.oid = a.oid WHERE a.oid IN (?) AND a.business=? AND a.state=0 AND t.state=0) b LEFT JOIN academy_tag AS c ON c.id=b.tid WHERE c.type!=?", oids, bs, academy.Classify).Find(&ats).Error; err != nil {
log.Error("creative-admin bulkUpdateArcs get all archive tags error(%v)", err)
return
}
if len(ats) == 0 {
return
}
ids = make([]int64, 0, len(ats))
for _, a := range ats {
if a == nil {
log.Error("creative-admin bulkUpdateArcs update other tags get nil a(%+v)", a)
return
}
ids = append(ids, a.ID)
}
tx := svc.DB.Begin()
// 对于提交上来的其他标签先统一删除再统一插入
if err = tx.Model(&academy.ArchiveTag{}).Where("id IN (?)", ids).
Updates(map[string]interface{}{
"state": academy.StateRemove,
}).Error; err != nil {
log.Error("bulkUpdateArcs first delete other tags by ids(%v)|error(%v)", ids, err)
tx.Rollback()
return
}
tags := make([]*academy.ArchiveTag, 0)
for _, oid := range oids {
tags = append(tags, setTagParam(oid, courseTID, bs), setTagParam(oid, operTID, bs), setTagParam(oid, recommendTID, bs))
if bs == academy.BusinessForArticle && articleTID > 0 { //专栏特殊分类
tags = append(tags, setTagParam(oid, articleTID, bs))
}
}
valTags := make([]string, 0)
valTagArgs := make([]interface{}, 0)
for _, v := range tags {
valTags = append(valTags, "(?, ?, ?, ?, ?, ?)")
valTagArgs = append(valTagArgs, v.OID, v.TID, v.State, v.CTime, v.MTime, v.Business)
}
sqlTagStr := fmt.Sprintf("INSERT INTO academy_archive_tag (oid, tid, state, ctime, mtime, business) VALUES %s ON DUPLICATE KEY UPDATE state=0,oid=VALUES(oid),tid=VALUES(tid),business=VALUES(business)", strings.Join(valTags, ","))
if err = tx.Exec(sqlTagStr, valTagArgs...).Error; err != nil {
log.Error("bulkUpdateArcs update other tags valTagArgs(%+v)", valTagArgs...)
tx.Rollback()
return
}
//处理分类标签
tids, err = xstr.SplitInts(classTID)
if err != nil {
return err
}
if err = svc.DB.Raw("SELECT b.*, c.type FROM (SELECT t.id,t.tid,a.oid FROM academy_archive AS a LEFT JOIN academy_archive_tag AS t ON t.oid = a.oid WHERE a.oid IN (?) AND a.business=? AND a.state=0 AND t.state=0) b LEFT JOIN academy_tag AS c ON c.id=b.tid WHERE c.type=?", oids, bs, academy.Classify).Find(&arcTags).Error; err != nil {
log.Error("creative-admin bulkUpdateArcs archive class tags error(%v)", err)
return
}
arcMapTids = make(map[int64][]int64)
for _, v := range arcTags {
arcMapTids[v.OID] = append(arcMapTids[v.OID], v.TID)
}
newOIDTidsMap = make(map[int64][]int64)
delOIDTidsMap = make(map[int64][]int64)
for oid, ids := range arcMapTids {
isInDB := make(map[int64]int64)
for _, id := range ids {
isInDB[id] = id
}
log.Info("creative-admin bulkUpdateArcs oid(%d)|isInDB(%+v)", oid, isInDB)
isInSub := make(map[int64]int64)
for _, tid := range tids {
isInSub[tid] = tid
if _, ok := isInDB[tid]; !ok {
newOIDTidsMap[oid] = append(newOIDTidsMap[oid], tid)
}
}
log.Info("creative-admin bulkUpdateArcs oid(%d)|isInSubmit(%+v)", oid, isInSub)
for _, id := range ids {
if _, ok := isInSub[id]; !ok {
delOIDTidsMap[oid] = append(delOIDTidsMap[oid], id)
}
}
}
if len(newOIDTidsMap) > 0 { //insert on update
tags := make([]*academy.ArchiveTag, 0)
for oid, tgs := range newOIDTidsMap { //分类标签支持绑定多个二级标签
for _, cid := range tgs {
tags = append(tags, setTagParam(oid, cid, bs))
}
}
valTags := make([]string, 0)
valTagArgs := make([]interface{}, 0)
for _, v := range tags {
valTags = append(valTags, "(?, ?, ?, ?, ?, ?)")
valTagArgs = append(valTagArgs, v.OID, v.TID, v.State, v.CTime, v.MTime, v.Business)
}
sqlTagStr := fmt.Sprintf("INSERT INTO academy_archive_tag (oid, tid, state, ctime, mtime, business) VALUES %s ON DUPLICATE KEY UPDATE state=0, oid=VALUES(oid), tid=VALUES(tid), business=VALUES(business), mtime=VALUES(mtime)", strings.Join(valTags, ","))
if err = tx.Exec(sqlTagStr, valTagArgs...).Error; err != nil {
log.Error("creative-admin bulkUpdateArcs insert new class tags error(%v)", err)
tx.Rollback()
return
}
}
if len(delOIDTidsMap) > 0 { //delete
delMapID := make(map[int64]int64)
for _, tgs := range delOIDTidsMap {
for _, tid := range tgs {
delMapID[tid] = tid
}
}
delIDs := make([]int64, 0)
for _, a := range arcTags {
if _, ok := delMapID[a.TID]; ok {
delIDs = append(delIDs, a.ID)
}
}
if err = tx.Model(&academy.ArchiveTag{}).Where("id IN (?)", delIDs).
Updates(map[string]interface{}{
"state": academy.StateRemove,
"mtime": time.Now().Format("2006-01-02 15:04:05"),
}).Error; err != nil {
log.Error("creative-admin bulkUpdateArcs delete class tags by ids(%v)|error(%v)", delIDs, err)
tx.Rollback()
return
}
}
// 统一更新comment
if err = tx.Model(&academy.Archive{}).Where("business = ?", bs).Where("oid IN (?)", oids).
Updates(map[string]interface{}{
"comment": comment,
"mtime": time.Now().Format("2006-01-02 15:04:05"),
}).Error; err != nil {
log.Error("creative-admin bulkUpdateArcs update all comment error(%v)", err)
tx.Rollback()
return
}
tx.Commit()
return
}
func batchRemoveArc(c *bm.Context) {
var (
err error
oids []int64
)
v := new(struct {
OIDs string `form:"oids" validate:"required"`
Business int8 `form:"business"`
})
if err = c.Bind(v); err != nil {
return
}
if v.OIDs != "" {
if oids, err = xstr.SplitInts(v.OIDs); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
}
for _, oid := range oids {
if _, err = checkExist(oid); err != nil {
c.JSON(nil, err)
return
}
}
uid, uname := getUIDName(c)
action := ""
if v.Business == academy.BusinessForArchvie {
action = "批量移除视频稿件"
} else if v.Business == academy.BusinessForArticle {
action = "批量移除专栏稿件"
}
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: action, OIDs: xstr.JoinInts(oids)})
c.JSON(nil, bulkRemoveArcs(oids, v.Business))
}
func bulkRemoveArcs(oids []int64, bs int8) (err error) {
var (
db *gorm.DB
now = time.Now().Format("2006-01-02 15:04:05")
ats []*academy.ArchiveTags
IDs []int64
)
db = svc.DB.Raw("SELECT t.id,t.tid,a.oid,a.business FROM academy_archive AS a LEFT JOIN academy_archive_tag AS t ON t.oid = a.oid WHERE a.oid IN (?) AND a.business=?", oids, bs)
if err = db.Find(&ats).Error; err != nil {
log.Error("creative-admin bulkRemoveArcs error(%v)", err)
return
}
if len(ats) == 0 {
return
}
for _, a := range ats {
IDs = append(IDs, a.ID)
}
tx := svc.DB.Begin()
if err = tx.Model(&academy.Archive{}).Where("oid IN (?) AND business=?", oids, bs).Updates(map[string]interface{}{
"mtime": now,
"state": academy.StateRemove,
}).Error; err != nil {
log.Error("creative-admin bulkRemoveArcs error(%v)", err)
tx.Rollback()
return
}
if err = tx.Model(&academy.ArchiveTag{}).Where("id IN (?)", IDs).Updates(map[string]interface{}{
"mtime": now,
"state": academy.StateRemove,
}).Error; err != nil {
tx.Rollback()
log.Error("creative-admin bulkRemoveArcs error(%v)", err)
return
}
tx.Commit()
return
}
func arcCountByTids(tids []int64) (res map[int64]int, err error) {
var (
countSQL = "SELECT tid, count(DISTINCT oid) AS count FROM academy_archive_tag WHERE state=0 AND tid IN (?) GROUP BY tid"
ats []*academy.ArchiveCount
)
if err = svc.DB.Raw(countSQL, tids).Find(&ats).Error; err != nil {
log.Error("creative-admin get arcCountByTids error(%v)", err)
return
}
if len(ats) == 0 {
return
}
res = make(map[int64]int)
for _, a := range ats {
res[a.TID] = a.Count
}
return
}
func checkExist(oid int64) (arc *academy.Archive, err error) {
arc = &academy.Archive{}
err = svc.DB.Model(&academy.Archive{}).Where("state=?", academy.StateNormal).Where("oid=?", oid).Find(arc).Error
if err != nil {
if err != gorm.ErrRecordNotFound {
log.Error("creative-admin checkExist oid(%d)|error(%v)", oid, err)
}
}
return
}
func fixArchive(c *bm.Context) {
var err error
v := new(struct {
ID int64 `form:"id"`
OID int64 `form:"oid"`
Business int8 `form:"business"`
State int8 `form:"state"`
})
if err = c.Bind(v); err != nil {
return
}
if err = svc.DB.Model(&academy.Archive{}).Where("id=?", v.ID).Updates(map[string]interface{}{
"oid": v.OID,
"business": v.Business,
"state": v.State,
"mtime": time.Now().Format("2006-01-02 15:04:05"),
}).Error; err != nil {
log.Error("creative-admin fixArchive error(%v)", err)
}
c.JSON(nil, err)
}
func search(c *bm.Context, ap *academy.EsParam) (res *academy.Archives, err error) {
var (
oids []int64
tempMapTIDs map[int64][]int64
arcs []*academy.ArchiveOrigin
items []*academy.ArchiveMeta
com = make(map[int64]string)
)
res = &academy.Archives{
Items: []*academy.ArchiveMeta{},
Pager: &academy.Pager{},
}
sear, err := svc.ArchivesWithES(c, ap)
if err != nil {
log.Error("search svc.ArchivesWithES error(%v)", err)
return
}
arcs = make([]*academy.ArchiveOrigin, 0)
if sear == nil || len(sear.Result) == 0 {
return
}
tempMapTIDs = make(map[int64][]int64)
for _, v := range sear.Result {
oids = append(oids, v.OID)
tempMapTIDs[v.OID] = v.TID
}
res.Pager.Total = sear.Page.Total
res.Pager.Num = sear.Page.Num
res.Pager.Size = sear.Page.Size
g, _ := errgroup.WithContext(c)
var (
arcInfo map[int64]*academy.ArchiveMeta
tagInfo map[int64]map[int][]*academy.TagMeta
bindMapTIDs map[int64][]int64
)
bindMapTIDs = make(map[int64][]int64)
for _, oid := range oids {
if v, ok := tempMapTIDs[oid]; ok {
bindMapTIDs[oid] = v
}
}
g.Go(func() error {
arcInfo, err = bindArcInfo(c, oids, ap.Business, metadata.String(c, metadata.RemoteIP))
return err
})
g.Go(func() error {
com, err = bindArcComment(oids, ap.Business)
return err
})
g.Go(func() error {
tagInfo, err = bindTags(bindMapTIDs)
return err
})
if err = g.Wait(); err != nil {
return
}
log.Info("search arcInfo(%s)", spew.Sdump(arcInfo))
items = make([]*academy.ArchiveMeta, 0, len(arcs))
for _, oid := range oids {
a, ok := arcInfo[oid]
if !ok || a == nil {
log.Error("search get archive info error by oid(%d)", oid)
return
}
if v, ok := tagInfo[oid]; ok {
a.Tags = v
}
if co, ok := com[oid]; ok {
a.Comment = co
}
items = append(items, a)
}
res.Items = items
return
}
func bindArcComment(oids []int64, bs int8) (res map[int64]string, err error) {
var arcs []*academy.Archive
if err = svc.DB.Model(&academy.Archive{}).Where("oid in(?)", oids).Where("business=?", bs).Group("oid").Find(&arcs).Error; err != nil {
log.Error("bindArcComment d.DB.Model oids(%+v)|business(%d)|error(%v)", oids, bs, err)
return
}
res = make(map[int64]string)
for _, v := range arcs {
res[v.OID] = v.Comment
}
return
}
//countArcHot 视频=硬币*0.4+收藏*0.3+弹幕*0.4+评论*0.4+播放*0.25+点赞*0.4+分享*0.6 最新视频(一天内发布)提权[总值*1.5]
func countArcHot(t *api.Stat, ptime int64) int64 {
if t == nil {
return 0
}
hot := float64(t.Coin)*0.4 +
float64(t.Fav)*0.3 +
float64(t.Danmaku)*0.4 +
float64(t.Reply)*0.4 +
float64(t.View)*0.25 +
float64(t.Like)*0.4 +
float64(t.Share)*0.6
if ptime >= time.Now().AddDate(0, 0, -1).Unix() && ptime <= time.Now().Unix() {
hot *= 1.5
}
return int64(math.Floor(hot))
}
// countArtHot 专栏=硬币*0.4+收藏*0.3+评论*0.4+阅读*0.25+点赞*0.4+分享*0.6 最新专栏(一天内发布)提权[总值*1.5]
func countArtHot(t *model.Meta) int64 {
if t.Stats == nil {
return 0
}
hot := float64(t.Stats.Coin)*0.4 +
float64(t.Stats.Favorite)*0.3 +
float64(t.Stats.Reply)*0.4 +
float64(t.Stats.View)*0.25 +
float64(t.Stats.Like)*0.4 +
float64(t.Stats.Share)*0.6
if int64(t.PublishTime) >= time.Now().AddDate(0, 0, -1).Unix() && int64(t.PublishTime) <= time.Now().Unix() {
hot *= 1.5
}
return int64(math.Floor(hot))
}
// getParentChildMap
func getTagParentChildMap() (res map[int64]*academy.Tag, err error) {
var (
db *gorm.DB
tags []*academy.Tag
)
db = svc.DB.Order("rank ASC").Find(&tags)
if err = db.Error; err != nil {
log.Error("creative-admin getTagParentChildMap error(%v)", err)
return
}
res = make(map[int64]*academy.Tag)
for _, t := range tags {
res[t.ID] = t
}
for _, v := range res {
if v == nil {
continue
}
if v.ParentID == 0 {
for _, t := range tags {
if t == nil {
continue
}
if t.ParentID == v.ID {
v.Children = append(v.Children, t)
}
}
}
}
return
}
// filterTIDs
func filterTIDs(tids []int64, parentChildMap map[int64]*academy.Tag) (res map[int][]int64) {
if len(tids) == 0 {
return
}
log.Info("s.filterTIDs origin tids(%+v)", tids)
res = make(map[int][]int64)
ochs := make([]int64, 0) //原始提交的二级标签
ops := make([]int64, 0) //原始提交的一级标签
qchs := make([]int64, 0) //通过一级标签查询出来的二级标签
for _, id := range tids {
t, ok := parentChildMap[id]
if !ok || t == nil {
continue
}
if t.Type == academy.Classify {
if t.ParentID != 0 { //原始提交的二级标签
ochs = append(ochs, id)
} else if t.ParentID == 0 && len(t.Children) > 0 { //通过一级标签查询出来的二级标签
for _, v := range t.Children {
qchs = append(qchs, v.ID)
}
} else if t.ParentID == 0 && len(t.Children) == 0 {
ops = append(ops, id)
}
} else {
res[int(t.Type)] = append(res[int(t.Type)], id)
}
}
if len(ochs) > 0 { //如果分类标签中提交了原始的二级标签则认为按该二级标签进行筛选,如果可以查询到二级标签认为筛选全部二级,否则一级参与查询.
res[academy.Classify] = ochs
} else if len(qchs) > 0 {
res[academy.Classify] = qchs
} else if len(ops) > 0 {
res[academy.Classify] = ops
}
log.Info("s.filterTIDs res(%s)", spew.Sdump(res))
return
}

View File

@@ -0,0 +1,775 @@
package http
import (
"encoding/json"
"io/ioutil"
"net/http"
"time"
"go-common/app/admin/main/creative/model/academy"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
"go-common/library/net/http/blademaster/render"
"go-common/library/sync/errgroup"
"go-common/library/xstr"
"github.com/jinzhu/gorm"
)
func addOccupation(c *bm.Context) {
var (
err error
now = time.Now().Format("2006-01-02 15:04:05")
)
v := new(academy.Occupation)
if err = c.Bind(v); err != nil {
log.Error("addOccupation c.Bind error(%v)", err)
return
}
m := &academy.Occupation{
State: academy.StateNormal,
Name: v.Name,
Desc: v.Desc,
Logo: v.Logo,
MainStep: v.MainStep,
MainSoftware: v.MainSoftware,
CTime: now,
MTime: now,
}
tx := svc.DB.Begin()
if err = tx.Create(m).Error; err != nil {
log.Error("academy addOccupation error(%v)", err)
c.JSON(nil, err)
tx.Rollback()
return
}
if err = tx.Model(&academy.Occupation{}).Where("id=?", m.ID).Updates(map[string]interface{}{
"rank": m.ID,
}).Error; err != nil {
log.Error("academy addOccupation error(%v)", err)
tx.Rollback()
}
tx.Commit()
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "添加职业", TID: m.ID, OName: m.Name})
c.JSON(map[string]interface{}{
"id": m.ID,
}, nil)
}
func upOccupation(c *bm.Context) {
var (
oc = &academy.Occupation{}
err error
)
v := new(academy.Occupation)
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Where("id=?", v.ID).Find(oc).Error; err != nil {
c.JSON(nil, err)
return
}
if oc == nil {
c.JSON(nil, ecode.NothingFound)
return
}
if err = svc.DB.Model(&academy.Occupation{}).Where("id=?", v.ID).Updates(map[string]interface{}{
"name": v.Name,
"desc": v.Desc,
"logo": v.Logo,
"main_step": v.MainStep,
"main_software": v.MainSoftware,
}).Error; err != nil {
log.Error("academy bindOccupation error(%v)", err)
}
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "更新职业", TID: v.ID, OName: v.Name})
c.JSON(nil, err)
}
func bindOccupation(c *bm.Context) {
var (
oc = &academy.Occupation{}
err error
)
v := new(academy.Occupation)
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Where("id=?", v.ID).Find(oc).Error; err != nil {
c.JSON(nil, err)
return
}
if oc == nil {
c.JSON(nil, ecode.NothingFound)
return
}
if err = svc.DB.Model(&academy.Occupation{}).Where("id=?", v.ID).Updates(map[string]interface{}{
"state": v.State,
}).Error; err != nil {
log.Error("academy upOccupation error(%v)", err)
}
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "更新职业", TID: v.ID, OName: v.Name})
c.JSON(nil, err)
}
func addSkill(c *bm.Context) {
var (
err error
now = time.Now().Format("2006-01-02 15:04:05")
)
v := new(academy.Skill)
if err = c.Bind(v); err != nil {
log.Error("addSkill c.Bind error(%v)", err)
return
}
m := &academy.Skill{
State: academy.StateNormal,
OID: v.OID,
Name: v.Name,
Desc: v.Desc,
CTime: now,
MTime: now,
}
if err = svc.DB.Create(m).Error; err != nil {
log.Error("academy addSkill error(%v)", err)
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "添加步骤", TID: m.ID, OName: m.Name})
c.JSON(map[string]interface{}{
"id": m.ID,
}, nil)
}
func upSkill(c *bm.Context) {
var (
sk = &academy.Skill{}
err error
)
v := new(academy.Skill)
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Where("id=?", v.ID).Find(sk).Error; err != nil {
c.JSON(nil, err)
return
}
if sk == nil {
c.JSON(nil, ecode.NothingFound)
return
}
if err = svc.DB.Model(&academy.Skill{}).Where("id=?", v.ID).Updates(map[string]interface{}{
"name": v.Name,
"desc": v.Desc,
}).Error; err != nil {
log.Error("academy upSkill error(%v)", err)
}
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "更新步骤", TID: v.ID, OName: v.Name})
c.JSON(nil, err)
}
func bindSkill(c *bm.Context) {
var (
oc = &academy.Skill{}
err error
)
v := new(academy.Skill)
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Where("id=?", v.ID).Find(oc).Error; err != nil {
c.JSON(nil, err)
return
}
if oc == nil {
c.JSON(nil, ecode.NothingFound)
return
}
if err = svc.DB.Model(&academy.Skill{}).Where("id=?", v.ID).Updates(map[string]interface{}{
"state": v.State,
}).Error; err != nil {
log.Error("academy bindSkill error(%v)", err)
}
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "更新职业", TID: v.ID, OName: v.Name})
c.JSON(nil, err)
}
func addSoftware(c *bm.Context) {
var (
err error
now = time.Now().Format("2006-01-02 15:04:05")
)
v := new(academy.Software)
if err = c.Bind(v); err != nil {
return
}
m := &academy.Software{
State: academy.StateNormal,
SkID: v.SkID,
Name: v.Name,
Desc: v.Desc,
CTime: now,
MTime: now,
}
if err = svc.DB.Create(m).Error; err != nil {
log.Error("academy addSoftware error(%v)", err)
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "添加步骤", TID: m.ID, OName: m.Name})
c.JSON(map[string]interface{}{
"id": m.ID,
}, nil)
}
func upSoftware(c *bm.Context) {
var (
oc = &academy.Software{}
err error
)
v := new(academy.Software)
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Where("id=?", v.ID).Find(oc).Error; err != nil {
c.JSON(nil, err)
return
}
if oc == nil {
c.JSON(nil, ecode.NothingFound)
return
}
if err = svc.DB.Model(&academy.Software{}).Where("id=?", v.ID).Updates(map[string]interface{}{
"name": v.Name,
"desc": v.Desc,
}).Error; err != nil {
log.Error("academy upSoftware error(%v)", err)
}
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "更新步骤", TID: v.ID, OName: v.Name})
c.JSON(nil, err)
}
func bindSoftware(c *bm.Context) {
var (
oc = &academy.Software{}
err error
)
v := new(academy.Software)
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Where("id=?", v.ID).Find(oc).Error; err != nil {
c.JSON(nil, err)
return
}
if oc == nil {
c.JSON(nil, ecode.NothingFound)
return
}
if err = svc.DB.Model(&academy.Software{}).Where("id=?", v.ID).Updates(map[string]interface{}{
"state": v.State,
}).Error; err != nil {
log.Error("academy bindSoftware error(%v)", err)
}
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "更新职业", TID: v.ID, OName: v.Name})
c.JSON(nil, err)
}
func listOccupation(c *bm.Context) {
var (
ocs []*academy.Occupation
sks []*academy.Skill
sfs []*academy.Software
sfMap map[int64][]*academy.Software
skMap map[int64][]*academy.Skill
sfIDs, skIDs, oIDs []int64
softMap, skillMap, occMap map[int64]int
g, _ = errgroup.WithContext(c)
err error
)
g.Go(func() error { //软件
if err = svc.DB.Find(&sfs).Error; err != nil {
log.Error("listSoftware error(%v)", err)
return err
}
if len(sfs) == 0 {
return nil
}
sfMap = make(map[int64][]*academy.Software)
sfIDs = make([]int64, 0, len(sfs))
for _, v := range sfs {
sfMap[v.SkID] = append(sfMap[v.SkID], v) //按技能聚合软件
sfIDs = append(sfIDs, v.ID)
}
softMap, _ = arcCountBySids(sfIDs) //获取软件对应稿件数量
if len(softMap) == 0 {
return nil
}
for _, v := range sfs {
if n, ok := softMap[v.ID]; ok { //映射软件对应稿件数量
v.Count = n
}
}
return nil
})
g.Go(func() error { //技能
if err = svc.DB.Find(&sks).Error; err != nil {
log.Error("listSkill error(%v)", err)
return err
}
if len(sks) == 0 {
return nil
}
skMap = make(map[int64][]*academy.Skill)
skIDs = make([]int64, 0, len(sks))
for _, v := range sks {
skMap[v.OID] = append(skMap[v.OID], v) //按职业聚合技能
skIDs = append(skIDs, v.ID)
}
skillMap, _ = arcCountBySkids(skIDs) //获取技能对应稿件数量
return nil
})
g.Go(func() error { //职业
if err = svc.DB.Order("rank ASC").Find(&ocs).Error; err != nil {
log.Error("listOccupation error(%v)", err)
return err
}
if len(ocs) == 0 {
return nil
}
oIDs = make([]int64, 0, len(ocs))
for _, v := range ocs {
oIDs = append(oIDs, v.ID)
}
occMap, _ = arcCountByPids(oIDs) //获取职业对应稿件数量
return nil
})
if err = g.Wait(); err != nil {
c.JSON(nil, err)
return
}
for _, v := range sks {
if sf, ok := sfMap[v.ID]; ok { //添加软件节点
v.Software = sf
}
if n, ok := skillMap[v.ID]; ok { //映射技能对应稿件数量
v.Count = n
}
}
for _, v := range ocs {
if sk, ok := skMap[v.ID]; ok { //添加技能节点
v.Skill = sk
}
if n, ok := occMap[v.ID]; ok { //映射职业对应稿件数量
v.Count = n
}
}
c.Render(http.StatusOK, render.MapJSON(map[string]interface{}{
"code": 0,
"message": "0",
"data": ocs,
}))
}
func arcCountByPids(tids []int64) (res map[int64]int, err error) {
var (
countSQL = "SELECT pid AS tid, count(DISTINCT aid) AS count FROM academy_arc_skill WHERE state=0 AND pid IN (?) GROUP BY pid"
ats []*academy.ArchiveCount
)
if err = svc.DB.Raw(countSQL, tids).Find(&ats).Error; err != nil {
log.Error("occupation arcCountByPids error(%v)", err)
return
}
if len(ats) == 0 {
return
}
res = make(map[int64]int)
for _, a := range ats {
res[a.TID] = a.Count
}
return
}
func arcCountBySkids(tids []int64) (res map[int64]int, err error) {
var (
countSQL = "SELECT skid AS tid, count(DISTINCT aid) AS count FROM academy_arc_skill WHERE state=0 AND skid IN (?) GROUP BY skid"
ats []*academy.ArchiveCount
)
if err = svc.DB.Raw(countSQL, tids).Find(&ats).Error; err != nil {
log.Error("skill arcCountByPids error(%v)", err)
return
}
if len(ats) == 0 {
return
}
res = make(map[int64]int)
for _, a := range ats {
res[a.TID] = a.Count
}
return
}
func arcCountBySids(tids []int64) (res map[int64]int, err error) {
var (
countSQL = "SELECT sid AS tid, count(DISTINCT aid) AS count FROM academy_arc_skill WHERE state=0 AND sid IN (?) GROUP BY sid"
ats []*academy.ArchiveCount
)
if err = svc.DB.Raw(countSQL, tids).Find(&ats).Error; err != nil {
log.Error("software arcCountBySids error(%v)", err)
return
}
if len(ats) == 0 {
return
}
res = make(map[int64]int)
for _, a := range ats {
res[a.TID] = a.Count
}
return
}
func orderOccupation(c *bm.Context) {
var err error
v := new(struct {
ID int64 `form:"id" validate:"required"`
Rank int64 `form:"rank" validate:"required"`
SwitchID int64 `form:"switch_id" validate:"required"`
SwitchRank int64 `form:"switch_rank" validate:"required"`
})
if err = c.BindWith(v, binding.Form); err != nil {
return
}
tx := svc.DB.Begin()
var oc academy.Occupation
if err = tx.Where("id=?", v.ID).First(&oc).Error; err != nil {
log.Error("academy orderOccupation error(%v)", err)
c.JSON(nil, err)
tx.Rollback()
return
}
var soc academy.Occupation
if err = tx.Where("id=?", v.SwitchID).First(&soc).Error; err != nil {
log.Error("academy orderOccupation error(%v)", err)
c.JSON(nil, err)
tx.Rollback()
return
}
if err = tx.Model(&academy.Occupation{}).Where("id=?", v.ID).Updates(
map[string]interface{}{
"rank": v.SwitchRank,
},
).Error; err != nil {
log.Error("academy orderOccupation error(%v)", err)
c.JSON(nil, err)
tx.Rollback()
return
}
if err = tx.Model(&academy.Occupation{}).Where("id=?", v.SwitchID).Updates(
map[string]interface{}{
"rank": v.Rank,
},
).Error; err != nil {
log.Error("academy orderOccupation error(%v)", err)
c.JSON(nil, err)
tx.Rollback()
return
}
tx.Commit()
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "更新职业排序", TID: v.ID, OName: ""})
c.JSON(nil, err)
}
func checkSkillArcExist(aid, sid int64) (res *academy.ArcSkill, err error) {
var as academy.ArcSkill
err = svc.DB.Where("aid=?", aid).Where("sid=?", sid).Find(&as).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
err = nil
}
log.Error("academy checkSkillArcExist aid(%d)|sid(%d)|error(%v)", aid, sid, err)
}
res = &as
return
}
func viewSkillArc(c *bm.Context) {
var (
err error
as = &academy.ArcSkill{}
)
v := new(academy.ArcSkill)
if err = c.Bind(v); err != nil {
return
}
if v.AID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
arc, err := svc.Archive(c, v.AID)
if err != nil {
c.JSON(nil, err)
return
}
if arc != nil {
as.AID = v.AID
as.Title = arc.Title
as.Pic = arc.Pic
}
c.Render(http.StatusOK, render.MapJSON(map[string]interface{}{
"code": 0,
"message": "0",
"data": as,
}))
}
func addSkillArc(c *bm.Context) {
var (
err error
now = time.Now().Format("2006-01-02 15:04:05")
)
v := new(academy.ArcSkill)
if err = c.Bind(v); err != nil {
return
}
if v.AID == 0 || v.PID == 0 || v.SkID == 0 || v.SID == 0 || v.Type == 0 {
log.Error("academy addSkillArc v(%+v)", v)
c.JSON(nil, ecode.RequestErr)
return
}
res, err := checkSkillArcExist(v.AID, v.SID)
if err != nil {
c.JSON(nil, err)
return
}
if res != nil && res.ID != 0 {
c.JSON(nil, ecode.CreativeAcademyDuplicateSoftIDErr)
return
}
m := &academy.ArcSkill{
State: academy.StateNormal,
AID: v.AID,
Type: v.Type,
PID: v.PID,
SkID: v.SkID,
SID: v.SID,
CTime: now,
MTime: now,
}
if err = svc.DB.Create(m).Error; err != nil {
log.Error("academy addSoftware error(%v)", err)
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "添加技能稿件", OIDs: xstr.JoinInts([]int64{v.AID})})
c.JSON(nil, err)
}
func upSkillArc(c *bm.Context) {
var err error
v := new(academy.ArcSkill)
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 || v.AID == 0 || v.PID == 0 || v.SkID == 0 || v.SID == 0 || v.Type == 0 {
log.Error("academy upSkillArc v(%+v)", v)
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Model(&academy.ArcSkill{}).Where("id=?", v.ID).Updates(map[string]interface{}{
"aid": v.AID,
"type": v.Type,
"pid": v.PID,
"skid": v.SkID,
"sid": v.SID,
}).Error; err != nil {
log.Error("academy upSkillArc error(%v)", err)
}
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "更新技能稿件", OIDs: xstr.JoinInts([]int64{v.AID})})
c.JSON(nil, err)
}
func bindSkillArc(c *bm.Context) {
var err error
v := new(academy.ArcSkill)
if err = c.Bind(v); err != nil {
return
}
if v.AID == 0 || v.SID == 0 {
log.Error("academy bindSkillArc v(%+v)", v)
c.JSON(nil, ecode.RequestErr)
return
}
res, err := checkSkillArcExist(v.AID, v.SID)
if err != nil {
c.JSON(nil, err)
return
}
if res != nil && res.ID == 0 {
c.JSON(nil, ecode.NothingFound)
return
}
if err = svc.DB.Model(&academy.ArcSkill{}).Where("aid=?", v.AID).Where("sid=?", v.SID).Updates(map[string]interface{}{
"state": v.State,
}).Error; err != nil {
log.Error("academy bindSkillArc error(%v)", err)
}
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "更新技能稿件状态", TID: v.ID, OName: v.Title})
c.JSON(nil, err)
}
func skillArcList(c *bm.Context) {
var (
items []*academy.ArcSkill
aids []int64
total int
err error
)
v := new(academy.ArcSkill)
if err = c.Bind(v); err != nil {
return
}
if v.Pn < 1 {
v.Pn = 1
}
if v.Ps > 20 {
v.Ps = 20
}
db := svc.DB.Model(&academy.ArcSkill{})
if v.PID != 0 {
db = db.Where("pid=?", v.PID)
}
if v.SkID != 0 {
db = db.Where("skid=?", v.SkID)
}
db.Count(&total)
if err = db.Order("ctime DESC").Offset((v.Pn - 1) * v.Ps).Limit(v.Ps).Find(&items).Error; err != nil {
log.Error("academy skillArcList error(%v)", err)
c.JSON(nil, err)
return
}
for _, v := range items {
aids = append(aids, v.AID)
}
arcs, err := svc.Archives(c, aids)
if err != nil {
log.Error("academy skillArcList error(%v)", err)
}
for _, v := range items {
if a, ok := arcs[v.AID]; ok {
v.Pic = a.Pic
v.Title = a.Title
}
}
data := &academy.ArcSkills{
Items: items,
Pager: &academy.Pager{
Num: v.Pn,
Size: v.Ps,
Total: total,
},
}
c.Render(http.StatusOK, render.MapJSON(map[string]interface{}{
"code": 0,
"message": "0",
"data": data,
}))
}
func subSearchKeywords(c *bm.Context) {
var err error
bs, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
log.Error("subSearchKeywords ioutil.ReadAll error(%v)", err)
c.JSON(nil, ecode.RequestErr)
return
}
c.Request.Body.Close()
var v []*academy.SearchKeywords
err = json.Unmarshal(bs, &v)
if err != nil {
log.Error("subSearchKeywords json.Unmarshal v(%+v) error(%v)", v, err)
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.SubSearchKeywords(v); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, nil)
}
func searchKeywords(c *bm.Context) {
res, err := svc.SearchKeywords()
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(res, nil)
}

View File

@@ -0,0 +1,477 @@
package http
import (
"fmt"
"net/http"
"strings"
"time"
"go-common/app/admin/main/creative/model/academy"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
"go-common/library/net/http/blademaster/render"
"go-common/library/xstr"
"github.com/jinzhu/gorm"
)
func addTag(c *bm.Context) {
var (
err error
linkIDs []int64
now = time.Now().Format("2006-01-02 15:04:05")
)
v := new(struct {
ParentID int64 `form:"parent_id"`
Business int8 `form:"business"`
Type int8 `form:"type"`
Desc string `form:"desc"`
Name string `form:"name"`
LinkID string `form:"link_id"`
})
if err = c.Bind(v); err != nil {
return
}
if v.LinkID != "" {
if linkIDs, err = xstr.SplitInts(v.LinkID); err != nil {
log.Error("addTag xstr.SplitInts h5 linkid(%+v)|error(%v)", v.LinkID, err)
c.JSON(nil, ecode.RequestErr)
return
}
}
m := &academy.Tag{
ParentID: v.ParentID,
State: academy.StateUnBlock,
Type: v.Type,
Business: v.Business,
Name: v.Name,
Desc: v.Desc,
CTime: now,
MTime: now,
}
tx := svc.DB.Begin()
if err = tx.Create(m).Error; err != nil {
log.Error("creative-admin academy addTag error(%v)", err)
c.JSON(nil, err)
tx.Rollback()
return
}
if err = tx.Model(&academy.Tag{}).Where("id=?", m.ID).Updates(map[string]interface{}{
"rank": m.ID,
}).Error; err != nil {
log.Error("creative-admin academy addTag update rank error(%v)", err)
c.JSON(nil, err)
tx.Rollback()
return
}
if len(linkIDs) > 0 { //插入h5标签关联的web标签
valLink := make([]string, 0, len(linkIDs))
valLinkArgs := make([]interface{}, 0)
for _, lid := range linkIDs {
valLink = append(valLink, "(?, ?, ?, ?)")
valLinkArgs = append(valLinkArgs, m.ID, lid, now, now)
}
sqlLinkStr := fmt.Sprintf("INSERT INTO academy_tag_link (tid, link_id, ctime, mtime) VALUES %s", strings.Join(valLink, ","))
if err = tx.Exec(sqlLinkStr, valLinkArgs...).Error; err != nil {
log.Error("academy bulk insert h5 link tag error(%v)", err)
tx.Rollback()
return
}
}
tx.Commit()
tid := m.ID
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "添加标签", TID: tid, OName: m.Name})
c.JSON(map[string]interface{}{
"id": tid,
}, nil)
}
func upTag(c *bm.Context) {
var (
tg = &academy.Tag{}
linkIDs []int64
err error
now = time.Now().Format("2006-01-02 15:04:05")
tid int64
)
v := new(struct {
ID int64 `form:"id"`
Desc string `form:"desc"`
Name string `form:"name"`
LinkID string `form:"link_id"`
})
if err = c.Bind(v); err != nil {
return
}
if v.LinkID != "" {
if linkIDs, err = xstr.SplitInts(v.LinkID); err != nil {
log.Error("upTag xstr.SplitInts h5 linkid(%+v)|error(%v)", v.LinkID, err)
c.JSON(nil, ecode.RequestErr)
return
}
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
tid = v.ID
if err = svc.DB.Model(&academy.Tag{}).Where("id=?", tid).Find(tg).Error; err != nil {
c.JSON(nil, err)
return
}
if tg == nil {
c.JSON(nil, ecode.NothingFound)
return
}
tx := svc.DB.Begin()
if err = tx.Model(&academy.Tag{}).Where("id=?", tid).Updates(map[string]interface{}{
"name": v.Name,
"desc": v.Desc,
}).Error; err != nil {
log.Error("academy upTag error(%v)", err)
tx.Rollback()
return
}
if len(linkIDs) > 0 { //插入h5标签关联的web标签
// 对于提交上来的其他标签先统一删除再统一插入
var tl academy.TagLink
if err = tx.Where("tid =?", tid).Delete(&tl).Error; err != nil {
log.Error("upTag TagLink delete by tid(%v)|error(%v)", tid, err)
tx.Rollback()
return
}
valLink := make([]string, 0, len(linkIDs))
valLinkArgs := make([]interface{}, 0)
for _, lid := range linkIDs {
valLink = append(valLink, "(?, ?, ?, ?)")
valLinkArgs = append(valLinkArgs, tid, lid, now, now)
}
sqlLinkStr := fmt.Sprintf("INSERT INTO academy_tag_link (tid, link_id, ctime, mtime) VALUES %s ON DUPLICATE KEY UPDATE tid=VALUES(tid),link_id=VALUES(link_id)", strings.Join(valLink, ","))
if err = tx.Exec(sqlLinkStr, valLinkArgs...).Error; err != nil {
log.Error("upTag TagLink valLinkArgs(%+v)", valLinkArgs...)
tx.Rollback()
return
}
}
tx.Commit()
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "更新标签", TID: tid, OName: v.Name})
c.JSON(nil, err)
}
func bindTag(c *bm.Context) {
var (
tg = &academy.Tag{}
err error
)
v := new(struct {
ID int64 `form:"id"`
State int8 `form:"state"`
})
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Model(&academy.Tag{}).Where("id=?", v.ID).Find(tg, v.ID).Error; err != nil {
c.JSON(nil, err)
return
}
if tg == nil {
c.JSON(nil, ecode.NothingFound)
return
}
if err = svc.DB.Model(&academy.Tag{ID: v.ID}).Updates(map[string]interface{}{
"state": v.State,
"mtime": time.Now().Format("2006-01-02 15:04:05"),
}).Error; err != nil {
log.Error("creative-admin academy delTag error(%v)", err)
}
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "更新标签状态", TID: v.ID, OState: v.State})
c.JSON(nil, err)
}
func viewTag(c *bm.Context) {
var (
err error
tg = &academy.Tag{}
)
v := new(struct {
ID int64 `form:"id"`
Type int8 `form:"type"`
Business int8 `form:"business"`
})
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Where("type = ?", v.Type).Where("business = ?", v.Business).Find(tg, v.ID).Error; err != nil {
c.JSON(nil, err)
return
}
if tg == nil {
c.JSON(nil, ecode.NothingFound)
return
}
c.JSON(renderTag(tg), nil)
}
func listTag(c *bm.Context) {
var (
err error
db *gorm.DB
tags []*academy.Tag
)
v := new(struct {
Type int8 `form:"type"`
})
if err = c.Bind(v); err != nil {
return
}
if v.Type != 0 {
db = svc.DB.Where("type = ?", v.Type).Order("rank ASC").Find(&tags)
} else {
db = svc.DB.Order("rank ASC").Find(&tags)
}
if err = db.Error; err != nil {
log.Error("creative-admin academy listTag error(%v)", err)
c.JSON(nil, err)
return
}
tgs, _ := tagTree(tags, v.Type)
c.Render(http.StatusOK, render.MapJSON(map[string]interface{}{
"code": 0,
"message": "0",
"data": map[string]interface{}{
"classify": academy.TagClass(),
"list": tgs,
},
}))
}
func tagTree(tags []*academy.Tag, ty int8) (res map[int8][]*academy.TagMeta, err error) {
all := make(map[int8]map[int64]*academy.TagMeta)
top := make(map[int64]*academy.TagMeta)
res = make(map[int8][]*academy.TagMeta)
tids := make([]int64, 0, len(tags))
linkMap, _ := h5RelatedWebTIDsMap() //获取h5标签关联的web标签
if ty == academy.H5 {
for _, lids := range linkMap {
tids = append(tids, lids...) //取所有关联的web标签id
}
} else {
for _, v := range tags {
if v.Type != academy.H5 {
tids = append(tids, v.ID) //取所有web标签id
}
}
}
arcCountMap, err := arcCountByTids(tids) //获取web标签下面的稿件数量
if err != nil {
return
}
h5ArcCountMap := make(map[int64]int)
for id, lids := range linkMap {
count := 0
for _, lid := range lids {
if c, ok := arcCountMap[lid]; ok {
count += c
}
}
h5ArcCountMap[id] = count
}
for _, v := range tags { //获取父级节点
if v == nil {
continue
}
t := renderTag(v)
if t.ParentID == 0 {
if c, ok := arcCountMap[t.ID]; ok { //获取除分类标签和h5标签之外的标签关联稿件数量
t.Count = c
}
top[t.ID] = t
all[t.Type] = top //存储一级标签对象id map
res[t.Type] = append(res[t.Type], t) //存储一级标签对象
}
}
for _, v := range tags { //获取子节点并获取关联稿件数量
if v == nil {
continue
}
t := renderTag(v)
p, ok := all[t.Type][t.ParentID] //获取一级标签对象
if ok && p != nil && p.Type == t.Type {
if c, ok := arcCountMap[t.ID]; ok { //获取分类标签的二级关联稿件数量
t.Count = c
}
if c, ok := h5ArcCountMap[t.ID]; ok { //获取h5标签二级关联稿件数量
t.Count = c
}
if l, ok := linkMap[v.ID]; ok && v.Type == academy.H5 {
t.LinkID = l
}
p.Children = append(p.Children, t)
}
}
for _, v := range res {
for _, t := range v { //计算分类标签或者h5标签一级关联稿件数量
if t != nil && t.ParentID == 0 && (t.Type == academy.H5 || t.Type == academy.Classify) {
for _, v := range t.Children {
t.Count += v.Count
}
}
}
}
return
}
func renderTag(v *academy.Tag) (tg *academy.TagMeta) {
tg = &academy.TagMeta{
ID: v.ID,
Type: v.Type,
State: v.State,
Business: v.Business,
ParentID: v.ParentID,
Name: v.Name,
Desc: v.Desc,
Rank: v.Rank,
}
return
}
func fixTag(c *bm.Context) {
var err error
v := new(struct {
ID int64 `form:"id"`
ParentID int64 `form:"parent_id"`
Business int8 `form:"business"`
State int8 `form:"state"`
Type int8 `form:"type"`
Name string `form:"name"`
Desc string `form:"desc"`
Rank int64 `form:"rank"`
})
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Model(&academy.Tag{}).Where("id=?", v.ID).Updates(map[string]interface{}{
"parent_id": v.ParentID,
"business": v.Business,
"type": v.Type,
"state": v.State,
"name": v.Name,
"desc": v.Desc,
"mtime": time.Now().Format("2006-01-02 15:04:05"),
"rank": v.Rank,
}).Error; err != nil {
log.Error("creative-admin academy upTag error(%v)", err)
}
c.JSON(nil, err)
}
func orderTag(c *bm.Context) {
var err error
v := new(struct {
ID int64 `form:"id" validate:"required"`
Rank int64 `form:"rank" validate:"required"`
SwitchID int64 `form:"switch_id" validate:"required"`
SwitchRank int64 `form:"switch_rank" validate:"required"`
})
if err = c.BindWith(v, binding.Form); err != nil {
return
}
tx := svc.DB.Begin()
tg := &academy.Tag{}
if err = tx.Where("id=?", v.ID).First(&tg).Error; err != nil {
log.Error("creative-admin academy orderTag error(%v)", err)
c.JSON(nil, err)
tx.Rollback()
return
}
stg := &academy.Tag{}
if err = tx.Where("id=?", v.SwitchID).First(&stg).Error; err != nil {
log.Error("creative-admin academy orderTag error(%v)", err)
c.JSON(nil, err)
tx.Rollback()
return
}
if err = tx.Table("academy_tag").Where("id=?", v.ID).Updates(
map[string]interface{}{
"rank": v.SwitchRank,
"mtime": time.Now().Format("2006-01-02 15:04:05")},
).Error; err != nil {
log.Error("creative-admin academy orderTag error(%v)", err)
c.JSON(nil, err)
tx.Rollback()
return
}
if err = tx.Table("academy_tag").Where("id=?", v.SwitchID).Updates(
map[string]interface{}{
"rank": v.Rank,
"mtime": time.Now().Format("2006-01-02 15:04:05")},
).Error; err != nil {
log.Error("creative-admin academy orderTag error(%v)", err)
c.JSON(nil, err)
tx.Rollback()
return
}
tx.Commit()
uid, uname := getUIDName(c)
svc.SendAcademyLog(c, &academy.LogParam{UID: uid, UName: uname, Action: "更新标签", TID: v.ID, OName: ""})
c.JSON(nil, err)
}
func h5RelatedWebTIDsMap() (res map[int64][]int64, err error) {
var tls []*academy.TagLink
if err = svc.DB.Find(&tls).Error; err != nil {
log.Error("academy h5TIDsMap error(%v)", err)
return
}
if len(tls) == 0 {
return
}
res = make(map[int64][]int64)
for _, t := range tls {
res[t.TID] = append(res[t.TID], t.LinkID)
}
return
}

View File

@@ -0,0 +1,32 @@
package http
import (
"flag"
"path/filepath"
"testing"
"go-common/app/admin/main/creative/conf"
"go-common/app/admin/main/creative/service"
. "github.com/smartystreets/goconvey/convey"
)
func init() {
dir, _ := filepath.Abs("../cmd/creative-admin.toml")
flag.Set("conf", dir)
conf.Init()
svc = service.New(conf.Conf)
}
func Test_bindTags(t *testing.T) {
var (
oidTIDsMap = map[int64][]int64{
838: {6, 8, 16, 17, 18, 19},
}
)
Convey("bindTags", t, func() {
res, err := bindTags(oidTIDsMap)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}

View File

@@ -0,0 +1,295 @@
package http
import (
"encoding/json"
"go-common/app/admin/main/creative/model/app"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/render"
"net/http"
"sort"
"time"
)
func viewPortal(c *bm.Context) {
var (
err error
info = &app.Portal{}
)
v := new(struct {
ID int64 `form:"id"`
})
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Debug().Model(&app.Portal{}).First(info, v.ID).Error; err != nil {
c.JSON(nil, err)
return
}
if info.ID == 0 {
c.JSON(nil, ecode.NothingFound)
} else {
layout := "2006-01-02 15:04:05"
mtime, _ := time.Parse(time.RFC3339, info.MTime)
info.MTime = mtime.Format(layout)
ptime, _ := time.Parse(time.RFC3339, info.PTime)
info.PTime = ptime.Format(layout)
ctime, _ := time.Parse(time.RFC3339, info.CTime)
info.CTime = ctime.Format(layout)
c.JSON(info, nil)
}
}
func addPortal(c *bm.Context) {
var (
err error
)
v := new(struct {
Build int64 `form:"build"`
BuildExp string `form:"buildexp"`
Platform int8 `form:"platform"`
Compare int8 `form:"compare"`
Pos int16 `form:"pos"`
Mark int8 `form:"mark"`
More int8 `form:"more"`
Type int8 `form:"type"`
Title string `form:"title" validate:"required"`
Icon string `form:"icon" validate:"required"`
URL string `form:"url" validate:"required"`
Whiteexp string `form:"whiteexp"`
SubTitle string `form:"subtitle"`
})
if err = c.Bind(v); err != nil {
return
}
if !checkBuild(v.BuildExp) {
httpCode(c, "buildexp is wrong", ecode.RequestErr)
return
}
if !checkWhite(v.Whiteexp) {
httpCode(c, "whiteexp is wrong", ecode.RequestErr)
return
}
m := &app.Portal{
Build: v.Build,
BuildExp: v.BuildExp,
Platform: v.Platform,
Compare: v.Compare,
State: 1,
Pos: v.Pos,
Mark: v.Mark,
More: v.More,
Type: v.Type,
Title: v.Title,
Icon: v.Icon,
URL: v.URL,
CTime: time.Now().Format("2006-01-02 15:04:05"),
MTime: time.Now().Format("2006-01-02 15:04:05"),
PTime: time.Now().Format("2006-01-02 15:04:05"),
SubTitle: v.SubTitle,
WhiteExp: v.Whiteexp,
}
db := svc.DB.Create(m)
if err = db.Error; err != nil {
log.Error("creativeSvc.addPortal error(%v)", err)
c.JSON(nil, err)
return
}
c.JSON(map[string]interface{}{
"id": db.Value.(*app.Portal).ID,
}, nil)
}
func upPortal(c *bm.Context) {
var (
err error
ap = &app.Portal{}
)
v := new(struct {
ID int64 `form:"id"`
Build int64 `form:"build"`
BuildExp string `form:"buildexp"`
Platform int8 `form:"platform"`
Compare int8 `form:"compare"`
Pos int16 `form:"pos"`
Mark int8 `form:"mark"`
More int8 `form:"more"`
Type int8 `form:"type"`
Title string `form:"title" validate:"required"`
Icon string `form:"icon" validate:"required"`
URL string `form:"url" validate:"required"`
Whiteexp string `form:"whiteexp"`
SubTitle string `form:"subtitle"`
})
if err = c.Bind(v); err != nil {
return
}
if !checkBuild(v.BuildExp) {
httpCode(c, "buildexp is wrong", ecode.RequestErr)
return
}
if !checkWhite(v.Whiteexp) {
httpCode(c, "whiteexp is wrong", ecode.RequestErr)
return
}
if err = svc.DB.Model(ap).Find(ap, v.ID).Error; err != nil {
c.JSON(nil, err)
return
}
if err = svc.DB.Model(&app.Portal{}).Update(map[string]interface{}{
"id": v.ID,
"build": v.Build,
"buildexp": v.BuildExp,
"platform": v.Platform,
"compare": v.Compare,
"state": 1,
"pos": v.Pos,
"mark": v.Mark,
"more": v.More,
"type": v.Type,
"title": v.Title,
"icon": v.Icon,
"url": v.URL,
"mtime": time.Now().Format("2006-01-02 15:04:05"),
"subtitle": v.SubTitle,
"whiteexp": v.Whiteexp,
}).Error; err != nil {
log.Error("creativeSvc.addPortal error(%v)", err)
}
c.JSON(nil, err)
}
func downPortal(c *bm.Context) {
var (
err error
ap = &app.Portal{}
)
v := new(struct {
ID int64 `form:"id"`
})
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Model(ap).Find(ap, v.ID).Error; err != nil {
c.JSON(nil, err)
return
}
if err = svc.DB.Model(&app.Portal{ID: v.ID}).Update(map[string]interface{}{
"id": v.ID,
"state": 0,
"mtime": time.Now().Format("2006-01-02 15:04:05"),
}).Error; err != nil {
log.Error("creativeSvc.addPortal error(%v)", err)
}
c.JSON(nil, err)
}
// 入口列表查询增加subtitle和whiteexp字段
func portalList(c *bm.Context) {
var (
pts []*app.Portal
items []*app.Item
total int64
err error
)
v := new(struct {
Pn int `form:"pn" validate:"required,min=1"`
Ps int `form:"ps" validate:"required,min=1"`
State int8 `form:"state"`
Type int8 `form:"type"`
Platform string `form:"platform"`
})
if err = c.Bind(v); err != nil {
return
}
if v.Pn < 1 {
v.Pn = 1
}
if v.Ps < 20 {
v.Ps = 20
}
if v.Type < 0 {
v.Type = 0
}
db := svc.DB.Model(&app.Portal{}).Where("type=?", v.Type)
if v.Platform != "" {
db = db.Where("platform=?", atoi(v.Platform))
}
if v.State != 2 {
db = db.Where("state=?", v.State)
}
db.Count(&total)
if err = db.Order("ctime DESC").Offset((v.Pn - 1) * v.Ps).Limit(v.Ps).Find(&pts).Error; err != nil {
log.Error("portalList error(%v)", err)
c.JSON(nil, err)
return
}
if len(pts) > 0 {
items = make([]*app.Item, 0, len(pts))
for _, v := range pts {
i := &app.Item{}
if v == nil {
continue
}
i.ID = v.ID
i.Build = v.Build
i.BuildExp = v.BuildExp
i.Platform = v.Platform
i.Compare = v.Compare
i.State = v.State
i.Pos = v.Pos
i.Mark = v.Mark
i.More = v.More
i.Type = v.Type
i.Title = v.Title
i.Icon = v.Icon
i.URL = v.URL
i.SubTitle = v.SubTitle
if len(v.WhiteExp) > 0 {
if err = json.Unmarshal([]byte(v.WhiteExp), &i.WhiteExps); err != nil {
log.Error("json.Unmarshal buildComps failed error(%v)", err)
}
sort.Slice(i.WhiteExps, func(m, n int) bool {
return i.WhiteExps[m].TP <= i.WhiteExps[n].TP
})
}
ct, err := time.Parse(time.RFC3339, v.CTime)
if err != nil {
log.Error("ctime time.Parse error(%v)", err)
}
mt, err := time.Parse(time.RFC3339, v.MTime)
if err != nil {
log.Error("mtime time.Parse error(%v)", err)
}
pt, err := time.Parse(time.RFC3339, v.PTime)
if err != nil {
log.Error("ptime time.Parse error(%v)", err)
}
i.CTime = ct.Unix()
i.MTime = mt.Unix()
i.PTime = pt.Unix()
items = append(items, i)
}
} else {
items = []*app.Item{}
}
data := &app.PortalPager{
Pn: v.Pn,
Ps: v.Ps,
Items: items,
Total: total,
}
c.Render(http.StatusOK, render.MapJSON(map[string]interface{}{
"code": 0,
"message": "0",
"data": data,
}))
}

View File

@@ -0,0 +1,47 @@
package http
import (
"fmt"
"net/http"
"github.com/pkg/errors"
)
// CSVContentType
var (
CSVContentType = []string{"application/csv"}
_ Render = CSV{}
)
// Render http reponse render.
type Render interface {
Render(http.ResponseWriter) error
WriteContentType(w http.ResponseWriter)
}
// CSV str.
type CSV struct {
Content []byte
Title string
}
// WriteContentType fn
func (j CSV) WriteContentType(w http.ResponseWriter) {
writeContentType(w, CSVContentType, j.Title)
}
func writeContentType(w http.ResponseWriter, value []string, title string) {
header := w.Header()
if val := header["Content-Type"]; len(val) == 0 {
header["Content-Type"] = value
}
header["Content-Disposition"] = append(header["Content-Disposition"], fmt.Sprintf("attachment; filename=%s.csv", title))
}
// Render (JSON) writes data with json ContentType.
func (j CSV) Render(w http.ResponseWriter) (err error) {
if _, err = w.Write(j.Content); err != nil {
err = errors.WithStack(err)
}
return
}

View File

@@ -0,0 +1,44 @@
package http
import (
"bytes"
"encoding/csv"
"strconv"
"go-common/app/admin/main/creative/model/whitelist"
"go-common/library/log"
)
// FormatCSV format csv data.
func FormatCSV(records [][]string) (res []byte) {
buf := new(bytes.Buffer)
w := csv.NewWriter(buf)
for _, record := range records {
if err := w.Write(record); err != nil {
log.Error("error writing record to csv:", err)
return
}
}
w.Flush()
res = buf.Bytes()
return
}
func formatWhilteList(wl []*whitelist.Whitelist) (data [][]string, err error) {
if len(wl) < 0 {
return
}
data = append(data, []string{"MID", "昵称", "AdminMID", "备注", "粉丝数", "等级", "创建时间"})
for _, v := range wl {
var fields []string
fields = append(fields, strconv.FormatInt(int64(v.MID), 10))
fields = append(fields, v.Name)
fields = append(fields, strconv.FormatInt(int64(v.AdminMID), 10))
fields = append(fields, v.Comment)
fields = append(fields, strconv.FormatInt(int64(v.Fans), 10))
fields = append(fields, strconv.FormatInt(int64(v.CurrentLevel), 10))
fields = append(fields, v.Ctime)
data = append(data, fields)
}
return
}

View File

@@ -0,0 +1,221 @@
package http
import (
"go-common/app/admin/main/creative/conf"
"go-common/app/admin/main/creative/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/permit"
)
var (
svc *service.Service
authSrc *permit.Permit
)
// Init http server
func Init(c *conf.Config) {
svc = service.New(c)
authSrc = permit.New(c.Auth)
engine := bm.DefaultServer(c.BM)
innerRouter(engine)
if err := engine.Start(); err != nil {
log.Error("engine.Start error(%v)", err)
panic(err)
}
}
func innerRouter(e *bm.Engine) {
e.GET("/monitor/ping", moPing)
b := e.Group("/x/admin/creative")
{
innerMusicRouter(e, b)
innerMaterialRouter(e, b)
app := b.Group("/app")
{
app.GET("/portal", viewPortal)
app.POST("/portal/add", addPortal)
app.POST("/portal/update", upPortal)
app.POST("/portal/down", downPortal)
app.GET("/portal/list", portalList)
}
notice := b.Group("/notice")
{
notice.GET("/view", viewNotice)
notice.GET("/list", listNotice)
notice.POST("/add", addNotice)
notice.POST("/update", upNotice)
notice.POST("/delete", delNotice)
}
arc := b.Group("/oper/col_arc", authSrc.Verify())
{
arc.GET("/list", listCollectArcOper)
arc.POST("/add", addCollectArcOper)
// blew is copy from notice for support
arc.GET("/view", viewNotice)
arc.POST("/update", upNotice)
arc.POST("/delete", delNotice)
}
whitelist := b.Group("/whitelist")
{
whitelist.GET("/view", viewWhiteList)
whitelist.GET("/list", listWhiteList)
whitelist.GET("/export.so", exportWhiteList)
whitelist.POST("/add", addWhiteList)
whitelist.POST("/add/batch", addBatchWhiteList)
whitelist.POST("/update", upWhiteList)
whitelist.POST("/delete", delWhiteList)
}
academy := b.Group("/academy", authSrc.Verify(), authSrc.Permit("ACADEMY_MANAGER")) //创作学院
// academy := b.Group("/academy") //创作学院
{
academy.POST("/tag/update/fix", fixTag) //清理脏数据
academy.POST("/archive/update/fix", fixArchive) //清理脏数据
//tag
academy.POST("/tag/add", addTag)
academy.POST("/tag/update", upTag)
academy.POST("/tag/bind", bindTag)
academy.GET("/tag/view", viewTag)
academy.GET("/tag/list", listTag)
academy.POST("/tag/order", orderTag)
//archive
academy.POST("/archive/add", addArc)
academy.POST("/archive/update", upArcTag)
academy.POST("/archive/remove", removeArcTag)
academy.POST("/archive/batch/add", batchAddArc)
academy.POST("/archive/batch/update", batchUpArc)
academy.POST("/archive/batch/remove", batchRemoveArc)
academy.GET("/archive/view", viewArc)
academy.GET("/archive/list", listArc)
//occupation & skill
academy.POST("/occupation/add", addOccupation)
academy.POST("/occupation/update", upOccupation)
academy.POST("/occupation/bind", bindOccupation)
academy.POST("/occupation/order", orderOccupation)
academy.GET("/occupation/list", listOccupation)
academy.POST("/skill/add", addSkill)
academy.POST("/skill/update", upSkill)
academy.POST("/skill/bind", bindSkill)
academy.POST("/software/add", addSoftware)
academy.POST("/software/update", upSoftware)
academy.POST("/software/bind", bindSoftware)
//arc & skill
academy.GET("/skill/archive/view", viewSkillArc)
academy.GET("/skill/archive/list", skillArcList)
academy.POST("/skill/archive/add", addSkillArc)
academy.POST("/skill/archive/update", upSkillArc)
academy.POST("/skill/archive/bind", bindSkillArc)
//search keywords
academy.GET("/search/keywords", searchKeywords)
academy.POST("/search/keywords/sub", subSearchKeywords)
}
task := b.Group("/task", authSrc.Verify(), authSrc.Permit("CREATIVE_TASK_MANAGER")) //任务系统
// task := b.Group("/task") //任务系统
{
//task list
task.GET("/pre", taskPre)
task.GET("/list", taskList)
task.POST("/online", batchOnline)
//group
task.GET("/group/view", viewGroup)
task.POST("/group/add", addGroup)
task.POST("/group/edit", editGroup)
task.POST("/group/order", orderGroup)
task.POST("/group/upstate", upStateGroup)
//sub
task.GET("/sub/view", viewSubtask)
task.POST("/sub/add", addSubtask)
task.POST("/sub/edit", editSubtask)
task.POST("/sub/order", orderSubtask)
task.POST("/sub/upstate", upStateSubtask)
task.POST("/sub/transfer", transferSubtask)
//reward
task.GET("/reward/list", rewardTree)
task.GET("/reward/view", viewReward)
task.POST("/reward/add", addReward)
task.POST("/reward/edit", editReward)
task.POST("/reward/upstate", upStateReward)
//gift
task.GET("/gift/list", listGiftReward)
task.GET("/gift/view", viewGiftReward)
task.POST("/gift/add", addGiftReward)
task.POST("/gift/edit", editGiftReward)
task.POST("/gift/upstate", upStateGiftReward)
}
}
}
//素材库 db creative
func innerMaterialRouter(e *bm.Engine, group *bm.RouterGroup) {
if group == nil {
return
}
//字幕库 字体库 滤镜库
material := group.Group("/material", authSrc.Verify())
{
material.GET("", authSrc.Permit("MATERIAL_READ"), infoMaterial)
material.GET("/search", authSrc.Permit("MATERIAL_READ"), searchMaterialDb)
//支持新增和修改
material.POST("/add", authSrc.Permit("MATERIAL_WRITE"), syncMaterial)
//支持批量修改
material.POST("/state", authSrc.Permit("MATERIAL_WRITE"), stateMaterial)
//仅支持 image/ zip 上传
material.POST("/upload", upload)
//素材库分类
material.GET("/category", authSrc.Permit("MATERIAL_READ"), category)
material.POST("/category/add", authSrc.Permit("MATERIAL_WRITE"), addMCategory)
material.POST("/category/edit", authSrc.Permit("MATERIAL_WRITE"), editMCategory)
material.POST("/category/index", authSrc.Permit("MATERIAL_WRITE"), indexMCategory)
material.POST("/category/delete", authSrc.Permit("MATERIAL_WRITE"), delMCategory)
material.GET("/category/search", authSrc.Permit("MATERIAL_READ"), searchMCategory)
}
}
//音频库 db archive
func innerMusicRouter(e *bm.Engine, group *bm.RouterGroup) {
if group == nil {
return
}
groupMusic := group.Group("/music")
{
//音乐管理及同步
groupMusic.POST("/add", authSrc.Permit("MUSIC_UPDATE"), syncMusic)
groupMusic.POST("/up/frontname", authSrc.Permit("MUSIC_UPDATE"), editMusicFrontName)
groupMusic.POST("/up/tags", authSrc.Permit("MUSIC_UPDATE"), editMusicTags)
groupMusic.POST("/edit", authSrc.Permit("MUSIC_UPDATE"), editMusic)
groupMusic.POST("/batch/tags", authSrc.Permit("MUSIC_UPDATE"), batchEditMusicTags)
groupMusic.POST("/up/timeline", authSrc.Permit("MUSIC_UPDATE"), editMusicTimeline)
groupMusic.GET("/search", authSrc.Permit("MUSIC_READ"), searchMusic)
//音乐分类
groupMusic.GET("/category", authSrc.Permit("MUSIC_CATEGORY_READ"), categoryInfo)
groupMusic.POST("/category/add", authSrc.Permit("MUSIC_CATEGORY_UPDATE"), addCategory)
groupMusic.POST("/category/edit", authSrc.Permit("MUSIC_CATEGORY_UPDATE"), editCategory)
groupMusic.POST("/category/index", authSrc.Permit("MUSIC_CATEGORY_UPDATE"), indexCategory)
groupMusic.POST("/category/delete", authSrc.Permit("MUSIC_CATEGORY_UPDATE"), delCategory)
groupMusic.GET("/category/search", authSrc.Permit("MUSIC_CATEGORY_READ"), searchCategory)
//素材分类
groupMusic.GET("/material", authSrc.Permit("MUSIC_MATERIAL_READ"), materialInfo)
groupMusic.POST("/material/add", authSrc.Permit("MUSIC_MATERIAL_UPDATE"), addMaterial)
groupMusic.POST("/material/edit", authSrc.Permit("MUSIC_MATERIAL_UPDATE"), editMaterial)
groupMusic.POST("/material/delete", authSrc.Permit("MUSIC_MATERIAL_UPDATE"), delMaterial)
groupMusic.POST("/material/batch/delete", authSrc.Permit("MUSIC_MATERIAL_UPDATE"), batchDeleteMaterial)
groupMusic.GET("/material/search", authSrc.Permit("MUSIC_MATERIAL_READ"), searchMaterial)
//音乐及素材 管理端
groupMusic.GET("/material/relation", authSrc.Permit("MUSIC_WITH_MATERIAL_READ"), musicMaterialRelationInfo)
groupMusic.POST("/material/relation/add", authSrc.Permit("MUSIC_WITH_MATERIAL_UPDATE"), addMaterialRelation)
groupMusic.POST("/material/relation/batch/add", authSrc.Permit("MUSIC_WITH_MATERIAL_UPDATE"), batchAddMaterialRelation)
groupMusic.POST("/material/relation/edit", authSrc.Permit("MUSIC_WITH_MATERIAL_UPDATE"), editMaterialRelation)
//音乐及分类 app端
groupMusic.GET("/category/relation", authSrc.Permit("MUSIC_WITH_CATEGORY_READ"), musicCategoryRelationInfo)
groupMusic.POST("/category/relation/add", authSrc.Permit("MUSIC_WITH_CATEGORY_UPDATE"), addCategoryRelation)
groupMusic.POST("/category/relation/batch/add", authSrc.Permit("MUSIC_WITH_CATEGORY_UPDATE"), batchAddCategoryRelation)
groupMusic.POST("/category/relation/index", authSrc.Permit("MUSIC_WITH_CATEGORY_UPDATE"), indexCategoryRelation)
groupMusic.POST("/category/relation/edit", authSrc.Permit("MUSIC_WITH_CATEGORY_UPDATE"), editCategoryRelation)
groupMusic.POST("/category/relation/batch/delete", authSrc.Permit("MUSIC_WITH_CATEGORY_UPDATE"), batchDeleteCategoryRelation)
groupMusic.POST("/category/relation/delete", authSrc.Permit("MUSIC_WITH_CATEGORY_UPDATE"), delCategoryRelation)
groupMusic.GET("/category/relation/search", authSrc.Permit("MUSIC_WITH_CATEGORY_READ"), searchCategoryRelation)
}
}

View File

@@ -0,0 +1,309 @@
package http
import (
"go-common/app/admin/main/creative/model/operation"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/render"
"net/http"
"time"
)
var (
typesMap = map[int8]int8{
0: 0, // 显示
1: 1, // 隐藏
2: 2, // 全部
}
platformMap = map[int8]int8{
0: 0, // web+app
1: 1, // app
2: 2, // web
100: 100, // 全平台
}
)
func viewNotice(c *bm.Context) {
var (
err error
info = &operation.Operation{}
)
v := new(struct {
ID int64 `form:"id"`
})
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Debug().Model(&operation.Operation{}).First(info, v.ID).Error; err != nil {
c.JSON(nil, err)
return
}
if info.ID == 0 {
c.JSON(nil, ecode.NothingFound)
} else {
layout := "2006-01-02 15:04:05"
ftime, _ := time.Parse(time.RFC3339, info.Stime)
info.Stime = ftime.Format(layout)
ftime, _ = time.Parse(time.RFC3339, info.Etime)
info.Etime = ftime.Format(layout)
ftime, _ = time.Parse(time.RFC3339, info.Ctime)
info.Ctime = ftime.Format(layout)
ftime, _ = time.Parse(time.RFC3339, info.Mtime)
info.Mtime = ftime.Format(layout)
ftime, _ = time.Parse(time.RFC3339, info.Dtime)
info.Dtime = ftime.Format(layout)
c.JSON(info, nil)
}
}
func listNotice(c *bm.Context) {
var (
err error
ops []*operation.Operation
total int
)
v := new(struct {
Type int8 `form:"type"`
Platform int8 `form:"platform"`
Page int `form:"page" validate:"min=1"`
PageSize int `form:"pagesize" validate:"min=1"`
})
if err = c.Bind(v); err != nil {
return
}
if v.Page < 1 {
v.Page = 1
}
if v.PageSize < 20 {
v.PageSize = 20
}
if _, ok := typesMap[v.Type]; !ok {
data := map[string]interface{}{
"code": ecode.RequestErr,
"message": "forbid request with wrong type enum value",
}
c.Render(http.StatusOK, render.MapJSON(data))
return
}
if _, ok := platformMap[v.Platform]; !ok {
data := map[string]interface{}{
"code": ecode.RequestErr,
"message": "forbid request with wrong platform enum value",
}
c.Render(http.StatusOK, render.MapJSON(data))
return
}
now := time.Now().Format("2006-01-02 15:04:05")
where := " dtime = '0000-00-00 00:00:00' AND type = 'play' AND platform = ?"
if v.Platform == 100 {
where = " dtime = '0000-00-00 00:00:00' AND type = 'play' "
}
if v.Type == 0 {
where += " AND (stime < ? AND etime > ?) "
} else if v.Type == 1 {
where += " AND (stime > ? OR etime < ?) "
} else if v.Type == 2 {
where += " AND 1=1 "
}
if v.Type == 2 {
if v.Platform == 100 {
if err = svc.DB.Debug().Model(&operation.Operation{}).Order("rank ASC").Offset((v.Page-1)*v.PageSize).Limit(v.PageSize).Find(&ops, where).Error; err != nil {
c.JSON(nil, err)
return
}
svc.DB.Debug().Model(&operation.Operation{}).Where(where).Count(&total)
} else {
if err = svc.DB.Debug().Model(&operation.Operation{}).Order("rank ASC").Offset((v.Page-1)*v.PageSize).Limit(v.PageSize).Find(&ops, where, v.Platform).Error; err != nil {
c.JSON(nil, err)
return
}
svc.DB.Debug().Model(&operation.Operation{}).Where(where, v.Platform).Count(&total)
}
} else {
if v.Platform == 100 {
if err = svc.DB.Debug().Model(&operation.Operation{}).Order("rank ASC").Offset((v.Page-1)*v.PageSize).Limit(v.PageSize).Find(&ops, where, now, now).Error; err != nil {
c.JSON(nil, err)
return
}
svc.DB.Debug().Model(&operation.Operation{}).Where(where, now, now).Count(&total)
} else {
if err = svc.DB.Debug().Model(&operation.Operation{}).Order("rank ASC").Offset((v.Page-1)*v.PageSize).Limit(v.PageSize).Find(&ops, where, v.Platform, now, now).Error; err != nil {
c.JSON(nil, err)
return
}
svc.DB.Debug().Model(&operation.Operation{}).Where(where, v.Platform, now, now).Count(&total)
}
}
var opsView []*operation.ViewOperation
for _, v := range ops {
var (
status string
timeNow = time.Now()
stime, _ = time.Parse(time.RFC3339, v.Stime)
etime, _ = time.Parse(time.RFC3339, v.Etime)
)
if time.Now().Before(etime) && timeNow.After(stime) {
status = "显示"
} else {
status = "隐藏"
}
opsView = append(opsView, &operation.ViewOperation{
ID: v.ID,
Type: v.Type,
Ads: v.Ads,
Platform: v.Platform,
Rank: v.Rank,
Pic: v.Pic,
Link: v.Link,
Content: v.Content,
Username: v.Username,
Remark: v.Remark,
Note: v.Note,
AppPic: v.AppPic,
Stime: v.Stime,
Etime: v.Etime,
Ctime: v.Ctime,
Mtime: v.Mtime,
Dtime: v.Dtime,
Status: status,
})
}
c.Render(http.StatusOK, render.MapJSON(map[string]interface{}{
"code": 0,
"message": "0",
"data": opsView,
"pager": map[string]int{
"page": v.Page,
"pagesize": v.PageSize,
"total": total,
},
}))
}
func addNotice(c *bm.Context) {
var (
err error
)
v := new(struct {
Ads int8 `form:"ads" `
Rank int8 `form:"rank"`
Pic string `form:"pic" validate:"required"`
Link string `form:"link" validate:"required"`
Content string `form:"content" validate:"required"`
Username string `form:"username" validate:"required"`
Remark string `form:"remark"`
Note string `form:"note"`
AppPic string `form:"app_pic" validate:"required"`
Platform int8 `form:"platform"`
Stime string `form:"stime" validate:"required"`
Etime string `form:"etime" validate:"required"`
})
if err = c.Bind(v); err != nil {
return
}
m := &operation.Operation{
Type: "play",
Ads: v.Ads,
Rank: v.Rank,
Pic: v.Pic,
Link: v.Link,
Content: v.Content,
Username: v.Username,
Remark: v.Remark,
Note: v.Note,
AppPic: v.AppPic,
Platform: v.Platform,
Ctime: time.Now().Format("2006-01-02 15:04:05"),
Stime: v.Stime,
Etime: v.Etime,
}
db := svc.DB.Debug().Model(&operation.Operation{}).Create(m)
if err = db.Error; err != nil {
log.Error("creativeSvc.Operation error(%v)", err)
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(map[string]interface{}{
"id": db.Value.(*operation.Operation).ID,
}, nil)
}
func upNotice(c *bm.Context) {
var (
op = &operation.Operation{}
err error
)
v := new(struct {
ID int64 `form:"id"`
Ads int8 `form:"ads"`
Platform int8 `form:"platform"`
Rank int8 `form:"rank"`
Pic string `form:"pic"`
Link string `form:"link"`
Content string `form:"content"`
Username string `form:"username"`
Remark string `form:"remark"`
Note string `form:"note"`
AppPic string `form:"app_pic"`
Stime string `form:"stime"`
Etime string `form:"etime"`
})
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Debug().Model(&operation.Operation{}).Find(op, v.ID).Error; err != nil {
c.JSON(nil, err)
return
}
if err = svc.DB.Debug().Model(&operation.Operation{ID: v.ID}).Update(map[string]interface {
}{
"id": v.ID,
"ads": v.Ads,
"rank": v.Rank,
"pic": v.Pic,
"link": v.Link,
"content": v.Content,
"username": v.Username,
"remark": v.Remark,
"note": v.Note,
"app_pic": v.AppPic,
"platform": v.Platform,
"mtime": time.Now().Format("2006-01-02 15:04:05"),
"stime": v.Stime,
"etime": v.Etime,
}).Error; err != nil {
log.Error("svc.save error(%v)", err)
}
c.JSON(nil, err)
}
func delNotice(c *bm.Context) {
var (
op = &operation.Operation{}
err error
)
if err = c.Bind(op); err != nil {
return
}
if op.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Debug().Model(&operation.Operation{}).Find(op, op.ID).Error; err != nil {
c.JSON(nil, err)
return
}
if err = svc.DB.Debug().Model(&operation.Operation{ID: op.ID}).Update("dtime", time.Now().Format("2006-01-02 15:04:05")).Error; err != nil {
log.Error("svc.del Notice error(%v)", err)
}
c.JSON(nil, err)
}

View File

@@ -0,0 +1,16 @@
package http
import (
"net/http"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
func moPing(c *bm.Context) {
var err error
if err = svc.Ping(c); err != nil {
log.Error("creative-admin ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}

View File

@@ -0,0 +1,407 @@
package http
import (
"strconv"
"encoding/json"
"fmt"
"go-common/app/admin/main/creative/model/app"
"go-common/app/admin/main/creative/model/logcli"
Mamdl "go-common/app/admin/main/creative/model/material"
"go-common/app/admin/main/creative/model/music"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
"go-common/library/xstr"
"strings"
"github.com/jinzhu/gorm"
"github.com/pkg/errors"
)
//素材库
func searchMaterialDb(c *bm.Context) {
var (
req = c.Request.Form
err error
items, dItems []*Mamdl.Material
count int64
typeID = req.Get("type")
Platform = atoi(req.Get("platform"))
categoryID = req.Get("category_id")
id = atoi(req.Get("id"))
name = req.Get("name")
page = atoi(req.Get("page"))
size = 20
)
if page == 0 {
page = 1
}
db := svc.DB.Model(&Mamdl.Material{}).Where("material.state!=?", Mamdl.StateDelete).
Joins("left join material_with_category on material_with_category.material_id=material.id and material_with_category.state !=?", Mamdl.StateOff).
Joins("left join material_category on material_with_category.category_id=material_category.id and material_category.state !=?", Mamdl.StateOff).
Select("material.*,material_category.name as category_name,material_with_category.category_id,material_with_category.index as category_index")
if id != 0 {
//id查询时需要提供type参数否则可能导致搜索为空
db = db.Where("material.id=?", id)
}
if Platform != -1 {
db = db.Where("material.platform=?", Platform)
}
//类型filter
if categoryID != "" {
db = db.Where("material_with_category.category_id=?", atoi(categoryID))
}
if typeID != "" {
db = db.Where("material.type=?", atoi(typeID))
}
if name != "" {
db = db.Where("material.name=?", name)
}
db.Count(&count)
if categoryID != "" {
db = db.Order("material_with_category.index")
} else {
db = db.Order("material.rank")
}
if err = db.Offset((page - 1) * size).Limit(size).Find(&dItems).Error; err != nil {
log.Error("%v\n", err)
c.JSON(nil, err)
return
}
if len(dItems) > 0 {
items = make([]*Mamdl.Material, 0, len(dItems))
for _, v := range dItems {
i := &Mamdl.Material{}
if v == nil {
continue
}
i.ID = v.ID
i.UID = v.UID
i.Name = v.Name
i.Extra = v.Extra
i.Rank = v.Rank
i.Type = v.Type
i.Platform = v.Platform
i.Build = v.Build
i.State = v.State
i.CategoryID = v.CategoryID
i.CategoryIndex = v.CategoryIndex
i.CategoryName = v.CategoryName
if i.CategoryName == "" {
i.CategoryID = 0
i.CategoryIndex = 0
}
i.CTime = v.CTime
i.MTime = v.MTime
items = append(items, i)
}
} else {
items = []*Mamdl.Material{}
}
pager := &Mamdl.Result{
Items: items,
Pager: &Mamdl.Pager{Num: page, Size: size, Total: count},
}
c.JSON(pager, nil)
}
func infoMaterial(c *bm.Context) {
var (
req = c.Request.Form
id = parseInt(req.Get("id"))
err error
)
m := &Mamdl.Material{}
if err = svc.DB.Where("id=?", id).First(&m).Error; err != nil {
c.JSON(nil, err)
return
}
c.JSON(map[string]*Mamdl.Material{
"data": m,
}, nil)
}
func getUIDName(c *bm.Context) (uid int64, uname string) {
unamei, ok := c.Get("username")
if ok {
uname = unamei.(string)
}
uidi, ok := c.Get("uid")
if ok {
uid = uidi.(int64)
}
return
}
func syncMaterial(c *bm.Context) {
var (
err error
m *Mamdl.Material
action string
)
mp := &Mamdl.Param{}
if err = c.BindWith(mp, binding.Form); err != nil {
log.Error("syncMaterial bind error trace(%+v)", errors.Wrap(err, "sync bind error"))
httpCode(c, fmt.Sprintf("bind error(%v)", err), ecode.RequestErr)
return
}
m, err = transferDB(c, mp)
if err != nil {
log.Error("transferDB find error(%+v)", err)
httpCode(c, fmt.Sprintf("transferDB validate error(%v)", err), ecode.RequestErr)
return
}
uid, uname := getUIDName(c)
m.UID = uid
if m.ID == 0 {
action = "add"
if err = svc.DB.Create(m).Error; err != nil {
log.Error("syncMaterial Create error(%+v)", err)
httpCode(c, fmt.Sprintf("syncMaterial Create error(%v)", err), ecode.RequestErr)
return
}
} else {
action = "edit"
exist := &Mamdl.Material{}
if err = svc.DB.Where("id=?", mp.ID).First(&exist).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("syncMaterial find error(%+v)", err)
httpCode(c, fmt.Sprintf("syncMaterial find error(%v)", err), ecode.RequestErr)
return
}
if exist.ID > 0 {
m.ID = exist.ID
if err = svc.DB.Model(&Mamdl.Material{}).Where("id=?", mp.ID).Update(m).Update(map[string]int8{"type": m.Type}).Error; err != nil {
log.Error("syncMaterial update error(%+v)", err)
httpCode(c, fmt.Sprintf("syncMaterial update error(%v)", err), ecode.RequestErr)
return
}
}
}
logMaterial, _ := json.Marshal(mp)
svc.SendMusicLog(c, logcli.LogClientArchiveMaterialType, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: action, Name: string(logMaterial)})
//不做事务允许分类绑定异常
if mp.Type == Mamdl.TypeFilter || mp.Type == Mamdl.TypeCreativeSticks {
_, err = svc.BindWithCategory(c, m.ID, mp.CategoryID, mp.CategoryIndex)
if err != nil {
httpCode(c, fmt.Sprintf("BindWithCategory update error(%v)", err), ecode.RequestErr)
return
}
}
c.JSON(map[string]int64{
"id": m.ID,
}, nil)
}
func transferDB(c *bm.Context, form *Mamdl.Param) (material *Mamdl.Material, err error) {
var extraBytes []byte
material = &Mamdl.Material{}
if form == nil {
return material, fmt.Errorf("params is wrong")
}
if form.Type != Mamdl.TypeCreativeSticks && (form.Name == "") {
return material, fmt.Errorf("name is need")
}
if form.Type == Mamdl.TypeSubTitle && (form.Max == 0) {
return material, fmt.Errorf("max is need")
}
if form.Type != Mamdl.TypeSticksIcon && (form.Rank == 0) {
return material, fmt.Errorf("rank is need")
}
//不需要cover
if form.Type != Mamdl.TypeHotWord && form.Type != Mamdl.TypeSticksIcon && form.Type != Mamdl.TypeCooperate && (form.Cover == "" || form.DownloadURL == "") {
return material, fmt.Errorf("cover and download_url is need")
}
if form.Cover != "" && (!strings.HasPrefix(form.Cover, "http") || !strings.Contains(form.Cover, "/bfs/")) {
return material, fmt.Errorf("cover is wrong")
}
if form.Type == Mamdl.TypeCooperate && form.DownloadURL != "" && !strings.Contains(form.DownloadURL, "acgvideo.com/") {
//acg
return material, fmt.Errorf("download_url is wrong")
}
if form.Type != Mamdl.TypeCooperate && form.DownloadURL != "" && (!strings.HasSuffix(form.DownloadURL, ".zip") || !strings.HasPrefix(form.DownloadURL, "http") || !strings.Contains(form.DownloadURL, "/bfs/creative/")) {
//bfs creative
return material, fmt.Errorf("download_url is wrong")
}
if !Mamdl.InMaterialType(form.Type) || form.Type == Mamdl.TypeBGM {
//Mamdl.TypeBGM 为迁入bgm预留
return material, fmt.Errorf("type is wrong")
}
if !checkBuild(form.Build) {
return material, fmt.Errorf("build is wrong")
}
switch form.Type {
case Mamdl.TypeSubTitle:
//字幕库
extraBytes, err = json.Marshal(map[string]interface{}{
"download_url": form.DownloadURL,
"max": form.Max,
"cover": form.Cover,
})
case Mamdl.TypeFont, Mamdl.TypeHotWord, Mamdl.TypeSticksIcon:
//字体库,贴纸,热词,贴纸Icon
extraBytes, err = json.Marshal(map[string]interface{}{
"download_url": form.DownloadURL,
"cover": form.Cover,
})
case Mamdl.TypeSticks:
//贴纸
extraBytes, err = json.Marshal(map[string]interface{}{
"download_url": form.DownloadURL,
"cover": form.Cover,
"sub_type": form.SubType,
"white_list": form.WhilteList,
"tip": form.Tip,
})
case Mamdl.TypeFilter:
//滤镜库
if len(form.ExtraURL) > 0 && (!strings.HasSuffix(form.ExtraURL, ".zip") || !strings.HasPrefix(form.ExtraURL, "http") || !strings.Contains(form.ExtraURL, "/bfs/creative/")) {
return material, fmt.Errorf("extra_url is wrong")
}
extraBytes, err = json.Marshal(map[string]interface{}{
"download_url": form.DownloadURL,
"cover": form.Cover,
"extra_url": form.ExtraURL,
"extra_field": form.ExtraField,
"filter_type": form.FilterType,
})
case Mamdl.TypeCooperate:
//合拍库
if form.MaterialAID*form.MaterialCID*form.DemoAID == 0 || form.SubType == 0 {
return material, fmt.Errorf("参数错误")
}
extraBytes, err = json.Marshal(map[string]interface{}{
"download_url": form.DownloadURL,
"cover": form.Cover,
"sub_type": form.SubType,
"style": form.Style,
"material_aid": form.MaterialAID,
"material_cid": form.MaterialCID,
"demo_aid": form.DemoAID,
"demo_cid": form.DemoCID,
"mission_id": form.MissionID,
})
case Mamdl.TypeTheme:
//主题库
extraBytes, err = json.Marshal(map[string]interface{}{
"download_url": form.DownloadURL,
"cover": form.Cover,
})
default:
extraBytes, err = json.Marshal(map[string]interface{}{
"download_url": form.DownloadURL,
"cover": form.Cover,
})
}
if err != nil {
return material, err
}
material.ID = form.ID
material.Name = form.Name
material.Extra = string(extraBytes)
material.Type = form.Type
material.Rank = form.Rank
material.Platform = form.Platform
material.Build = form.Build
if form.CategoryID > 0 {
if form.CategoryIndex < 1 {
return material, fmt.Errorf("category_index is wrong")
}
cate, _ := svc.CategoryByID(c, form.CategoryID)
if cate == nil || cate.State == Mamdl.StateOff {
return material, fmt.Errorf("category_id is wrong")
}
}
return
}
func stateMaterial(c *bm.Context) {
var (
req = c.Request.PostForm
ids []int64
state = parseInt(req.Get("state"))
err error
)
idStr := req.Get("id")
if ids, err = xstr.SplitInts(idStr); err != nil {
log.Error("stateMaterial strconv.ParseInt(%s) error(%v)", idStr, err)
httpCode(c, fmt.Sprintf("stateMaterial strconv.ParseInt error(%v)", err), ecode.RequestErr)
return
}
if state > 2 {
httpCode(c, "state参数可选值为 0 上架1下架2 删除", ecode.RequestErr)
return
}
//删除时保护上架状态的
if state == 2 {
if err = svc.DB.Model(Mamdl.Material{}).Where("id IN (?)", ids).Where("state !=?", 0).Update(map[string]int64{"state": state}).Error; err != nil {
log.Error("svc.stateMaterial error(%v)", err)
httpCode(c, fmt.Sprintf("stateMaterial update state error(%v)", err), ecode.RequestErr)
return
}
} else {
if err = svc.DB.Model(Mamdl.Material{}).Where("id IN (?)", ids).Update(map[string]int64{"state": state}).Error; err != nil {
log.Error("svc.stateMaterial error(%v)", err)
httpCode(c, fmt.Sprintf("stateMaterial update state error(%v)", err), ecode.RequestErr)
return
}
}
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func parseInt(value string) int64 {
intval, err := strconv.ParseInt(value, 10, 64)
if err != nil {
intval = 0
}
return intval
}
func atoi(value string) (intval int) {
intval, err := strconv.Atoi(value)
if err != nil {
intval = 0
}
return intval
}
func httpCode(c *bm.Context, message string, err error) {
c.JSON(map[string]interface{}{
"message": message,
}, err)
}
func checkBuild(build string) bool {
var err error
if len(build) > 0 {
type buildItem struct {
Build int64 `json:"build"`
Conditions int8 `json:"conditions"`
}
//比较版本号符号类型,0-等于,1-小于,2-大于,3-不等于,4-小于等于,5-大于等于
//[{"conditions":0,"build":5290000},{"conditions":0,"build":5290000}]
var buildExp []*buildItem
if err = json.Unmarshal([]byte(build), &buildExp); err != nil {
return false
}
}
return true
}
func checkWhite(white string) bool {
var err error
if len(white) > 0 {
var whiteExp []*app.WhiteExp
if err = json.Unmarshal([]byte(white), &whiteExp); err != nil {
return false
}
}
return true
}

View File

@@ -0,0 +1,188 @@
package http
import (
"go-common/app/admin/main/creative/model/logcli"
"go-common/app/admin/main/creative/model/material"
"go-common/app/admin/main/creative/model/music"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
"github.com/jinzhu/gorm"
)
func searchMCategory(c *bm.Context) {
var (
req = c.Request.Form
err error
items []*material.Category
count int64
name = req.Get("name")
page = atoi(req.Get("page"))
typeStr = req.Get("type")
size = 20
)
if page == 0 {
page = 1
}
db := svc.DB.Where("state!=?", material.StateOff)
if typeStr != "" {
db = db.Where("type=?", atoi(typeStr))
}
if name != "" {
db = db.Where("name=?", name)
}
db.Model(&material.Category{}).Count(&count)
if err = db.Model(&material.Category{}).Order("rank ASC").Offset((page - 1) * size).Limit(size).Find(&items).Error; err != nil {
log.Error("%v\n", err)
c.JSON(nil, err)
return
}
pager := &material.CategoryPager{
Items: items,
Pager: &material.Pager{Num: page, Size: size, Total: count},
}
c.JSON(pager, nil)
}
func category(c *bm.Context) {
var (
req = c.Request.Form
id = parseInt(req.Get("id"))
err error
)
m := &material.CategoryParam{}
if err = svc.DB.Where("id=?", id).First(&m).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
c.JSON(map[string]*material.CategoryParam{
"data": m,
}, nil)
}
func editMCategory(c *bm.Context) {
var (
req = c.Request.PostForm
id = parseInt(req.Get("id"))
err error
)
uid, uname := getUIDName(c)
m := &material.CategoryParam{}
if err = c.BindWith(m, binding.Form); err != nil {
return
}
exist := material.Category{}
if err = svc.DB.Where("id=?", id).Where("state!=?", material.StateOff).First(&exist).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
m.UID = uid
if err := svc.DB.Model(&material.Category{}).Where("id=?", id).Update(m).Update(map[string]interface{}{"type": m.Type}).Update(map[string]interface{}{"new": m.New}).Error; err != nil {
log.Error("svc.editMCategory error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMaterialTypeCategory, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "edit", Name: exist.Name})
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func indexMCategory(c *bm.Context) {
var (
err error
)
uid, uname := getUIDName(c)
m := &music.IndexParam{}
if err = c.BindWith(m, binding.Form); err != nil {
return
}
exist := material.Category{}
if err = svc.DB.Where("id=?", m.ID).Where("state!=?", material.StateOff).First(&exist).Error; err != nil {
log.Error("svc.indexMCategory error(%v)", err)
c.JSON(nil, err)
return
}
exist1 := material.Category{}
if err = svc.DB.Where("id=?", m.SwitchID).Where("state!=?", material.StateOff).First(&exist1).Error; err != nil {
log.Error("svc.indexMCategory error(%v)", err)
c.JSON(nil, err)
return
}
m.UID = uid
if err := svc.DB.Model(&material.Category{}).Where("id=?", m.ID).Update(map[string]int64{"rank": m.SwitchIndex}).Update(map[string]int64{"uid": uid}).Error; err != nil {
log.Error("svc.indexMCategory error(%v)", err)
c.JSON(nil, err)
return
}
if err := svc.DB.Model(&material.Category{}).Where("id=?", m.SwitchID).Update(map[string]int64{"rank": m.Index}).Update(map[string]int64{"uid": uid}).Error; err != nil {
log.Error("svc.indexMCategory error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMaterialTypeCategory, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "index", Name: exist.Name})
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func addMCategory(c *bm.Context) {
var (
err error
)
uid, uname := getUIDName(c)
m := &material.CategoryParam{}
if err = c.BindWith(m, binding.Form); err != nil {
log.Error("svc.addCategory bind error(%v)", err)
return
}
m.UID = uid
//Category.type 跟素材type一致
exist := &material.Category{}
if err = svc.DB.Where("state!=?", material.StateOff).Where("name=?", m.Name).Where("type=?", m.Type).First(&exist).Error; err != nil && err != gorm.ErrRecordNotFound {
c.JSON(nil, err)
return
}
if exist.ID > 0 {
c.JSON(map[string]int64{
"id": exist.ID,
}, nil)
return
}
if err = svc.DB.Create(m).Error; err != nil {
log.Error("svc.addMCategory Create error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMaterialTypeCategory, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "add", Name: m.Name})
c.JSON(map[string]int64{
"id": m.ID,
}, nil)
}
func delMCategory(c *bm.Context) {
var (
req = c.Request.PostForm
id = parseInt(req.Get("id"))
err error
)
exist := material.Category{}
if err = svc.DB.Where("id=?", id).Where("state!=?", material.StateOff).First(&exist).Error; err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
if err := svc.DB.Model(material.Category{}).Where("id=?", id).Update(map[string]int{"state": material.StateOff}).Update(map[string]int64{"uid": uid}).Error; err != nil {
log.Error("svc.delMCategory error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMaterialTypeCategory, &music.LogParam{ID: id, UID: uid, UName: uname, Action: "del", Name: exist.Name})
c.JSON(map[string]int{
"code": 0,
}, nil)
}

View File

@@ -0,0 +1,247 @@
package http
import (
"encoding/json"
"fmt"
"go-common/app/admin/main/creative/model/logcli"
"go-common/app/admin/main/creative/model/music"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
"go-common/library/xstr"
"github.com/jinzhu/gorm"
"github.com/pkg/errors"
)
func searchMusic(c *bm.Context) {
var (
req = c.Request.Form
err error
items []*music.Music
count int64
mid = atoi(req.Get("mid"))
sid = atoi(req.Get("sid"))
tid = req.Get("tid")
musicans = req.Get("musicans")
name = req.Get("name")
page = atoi(req.Get("page"))
size = 20
)
if page == 0 {
page = 1
}
db := svc.DBArchive.Model(&music.Music{}).Where("music.state!=?", music.MusicDelete).
Joins("left join music_with_material on music.sid=music_with_material.sid and music_with_material.state !=? ", music.MusicDelete).
Joins("left join music_material on music_with_material.tid=music_material.id").
Select("music.*,music_material.name as material_name,music_material.pid as pid,music_material.id as tid,music_with_material.id as rid")
if mid != 0 {
db = db.Where("music.mid=?", mid)
}
if sid != 0 {
db = db.Where("music.sid=?", sid)
}
//未添加分类的BGM filter tid=0 filter
if tid != "" {
if atoi(tid) == 0 {
db = db.Where("music_with_material.tid is null")
} else {
db = db.Where("music_with_material.tid=?", atoi(tid))
}
}
if name != "" {
db = db.Where("music.name=?", name)
}
if musicans != "" {
db = db.Where("music.musicians=?", musicans)
}
db.Count(&count)
//投稿时间ctime 倒序排列
if err = db.Order("music.ctime DESC").Offset((page - 1) * size).Limit(size).Find(&items).Error; err != nil {
log.Error("%v\n", err)
c.JSON(nil, err)
return
}
pager := &music.ResultPager{
Items: items,
Pager: &music.Pager{Num: page, Size: size, Total: count},
}
c.JSON(pager, nil)
}
func editMusicTimeline(c *bm.Context) {
var (
req = c.Request.PostForm
sid = parseInt(req.Get("sid"))
timeline = req.Get("timeline")
err error
)
if len(timeline) > 0 {
type timelineItem struct {
//转换成毫秒存储
Point int64 `json:"point"`
Comment string `json:"comment"`
Recommend int8 `json:"recommend"`
}
var timelineExp []*timelineItem
if err = json.Unmarshal([]byte(timeline), &timelineExp); err != nil {
httpCode(c, "timeline json is wrong", ecode.RequestErr)
return
}
}
exist := music.Music{}
if err = svc.DBArchive.Where("sid=?", sid).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
httpCode(c, "sid不存在", ecode.RequestErr)
return
}
if err := svc.DBArchive.Model(&music.Music{}).Where("sid=?", sid).Update(map[string]string{"timeline": timeline}).Error; err != nil {
log.Error("vdaSvc.editMusicTimeline error(%v)", err)
c.JSON(nil, err)
return
}
c.JSON(map[string]int{
"code": 0,
}, nil)
}
//开放来修改一些不复杂的数据
func editMusic(c *bm.Context) {
var (
req = c.Request.PostForm
sid = parseInt(req.Get("sid"))
cooperate = req.Get("cooperate")
err error
)
exist := music.Music{}
if err = svc.DBArchive.Where("sid=?", sid).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
httpCode(c, "sid不存在", ecode.RequestErr)
return
}
if err := svc.DBArchive.Model(&music.Music{}).Where("sid=?", sid).Update(map[string]int{"cooperate": atoi(cooperate)}).Error; err != nil {
log.Error("vdaSvc.editMusic error(%v)", err)
c.JSON(nil, err)
return
}
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func editMusicTags(c *bm.Context) {
var (
req = c.Request.PostForm
sid = parseInt(req.Get("sid"))
tags = req.Get("tags")
err error
)
exist := music.Music{}
if err = svc.DBArchive.Where("sid=?", sid).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
httpCode(c, "sid不存在", ecode.RequestErr)
return
}
if err := svc.DBArchive.Model(&music.Music{}).Where("sid=?", sid).Update(map[string]string{"tags": tags}).Error; err != nil {
log.Error("vdaSvc.editMusicTags error(%v)", err)
c.JSON(nil, err)
return
}
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func batchEditMusicTags(c *bm.Context) {
var (
req = c.Request.PostForm
sids = req.Get("sids")
tags = req.Get("tags")
arrids []int64
err error
)
if arrids, err = xstr.SplitInts(sids); err != nil {
log.Error("svc.batchEditMusicTags SplitInts error(%v)", err)
c.JSON(nil, err)
return
}
if len(arrids) < 2 {
c.JSON(nil, fmt.Errorf("sids参数错误"))
}
if err = svc.DBArchive.Model(&music.Music{}).Where("sid IN (?)", arrids).Update(map[string]string{"tags": tags}).Error; err != nil {
log.Error("vdaSvc.batchEditMusicTags error(%v)", err)
c.JSON(nil, err)
return
}
c.JSON(map[string]int{
"code": 0,
}, nil)
}
//用户侧BGM名称 front_name
func editMusicFrontName(c *bm.Context) {
var (
req = c.Request.PostForm
sid = parseInt(req.Get("sid"))
frontname = req.Get("frontname")
err error
)
exist := music.Music{}
if err = svc.DBArchive.Where("sid=?", sid).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
httpCode(c, "sid不存在", ecode.RequestErr)
return
}
if err := svc.DBArchive.Model(&music.Music{}).Where("sid=?", sid).Update(map[string]string{"frontname": frontname}).Error; err != nil {
log.Error("vdaSvc.editMusicName error(%v)", err)
c.JSON(nil, err)
return
}
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func syncMusic(c *bm.Context) {
var (
err error
)
mp := &music.Param{}
if err = c.BindWith(mp, binding.Form); err != nil {
log.Error("svc.syncMusic bind error(%+v)", err)
log.Error("svc.syncMusic bind error trace(%+v)", errors.Wrap(err, "sync bind error"))
return
}
m := &music.Music{Sid: mp.Sid, Name: mp.Name, Cover: mp.Cover, Stat: mp.Stat, Mid: mp.Mid, Musicians: mp.Musicians, Categorys: mp.Categorys, Playurl: mp.Playurl, PubTime: mp.PubTime, Duration: mp.Duration, Filesize: mp.Filesize, State: mp.State}
if m.State != music.MusicDelete {
m.State = music.MusicOpen
}
exist := music.Music{}
if err = svc.DBArchive.Where("sid=?", mp.Sid).First(&exist).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("svc.syncMusic find error(%+v)", err)
c.JSON(nil, errors.Wrap(err, "sync find sid error"))
return
}
uid, uname := getUIDName(c)
if exist.ID > 0 {
m.ID = exist.ID
if err = svc.DBArchive.Model(&music.Music{}).Where("sid=?", mp.Sid).Update(m).Update(map[string]int8{"state": m.State}).Error; err != nil {
log.Error("svc.syncMusic update error(%+v)", err)
c.JSON(nil, errors.Wrap(err, "sync update error"))
return
}
if m.State == music.MusicDelete {
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeMusic, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "del", Name: m.Name})
} else {
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeMusic, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "update", Name: m.Name})
}
} else {
if err = svc.DBArchive.Create(m).Error; err != nil {
log.Error("svc.syncMusic Create error(%+v)", err)
c.JSON(nil, errors.Wrap(err, "sync add error"))
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeMusic, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "add", Name: m.Name})
}
c.JSON(map[string]int64{
"id": m.ID,
}, nil)
}

View File

@@ -0,0 +1,201 @@
package http
import (
"go-common/app/admin/main/creative/model/logcli"
"go-common/app/admin/main/creative/model/music"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
"github.com/jinzhu/gorm"
)
func searchCategory(c *bm.Context) {
var (
req = c.Request.Form
err error
items []*music.Category
count int64
pid = atoi(req.Get("pid"))
name = req.Get("name")
page = atoi(req.Get("page"))
sort = atoi(req.Get("sort"))
size = 20
order string
)
if page == 0 {
page = 1
}
db := svc.DBArchive.Where("state!=?", music.MusicDelete)
if pid != 0 {
db = db.Where("pid=?", pid)
}
//pid 目前不做分级 pid=0
if name != "" {
db = db.Where("name=?", name)
}
db.Model(&music.Category{}).Count(&count)
if sort == 1 {
order = "camera_index"
} else {
order = "index"
}
if err = db.Model(&music.Category{}).Order(order).Offset((page - 1) * size).Limit(size).Find(&items).Error; err != nil {
log.Error("%v\n", err)
c.JSON(nil, err)
return
}
pager := &music.CategoryPager{
Items: items,
Pager: &music.Pager{Num: page, Size: size, Total: count},
}
c.JSON(pager, nil)
}
func categoryInfo(c *bm.Context) {
var (
req = c.Request.Form
id = parseInt(req.Get("id"))
err error
)
m := &music.CategoryParam{}
if err = svc.DBArchive.Where("id=?", id).First(&m).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
c.JSON(map[string]*music.CategoryParam{
"data": m,
}, nil)
}
func editCategory(c *bm.Context) {
var (
req = c.Request.PostForm
id = parseInt(req.Get("id"))
err error
)
uid, uname := getUIDName(c)
m := &music.CategoryParam{}
if err = c.BindWith(m, binding.Form); err != nil {
return
}
exist := music.Category{}
if err = svc.DBArchive.Where("id=?", id).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
m.UID = uid
if err := svc.DBArchive.Model(&music.Category{}).Where("id=?", id).Update(m).Error; err != nil {
log.Error("svc.editCategory error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeCategory, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "index", Name: exist.Name})
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func indexCategory(c *bm.Context) {
var (
req = c.Request.PostForm
err error
cate = atoi(req.Get("type"))
column string
)
uid, uname := getUIDName(c)
m := &music.IndexParam{}
if err = c.BindWith(m, binding.Form); err != nil {
return
}
exist := music.Category{}
if err = svc.DBArchive.Where("id=?", m.ID).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
log.Error("svc.indexCategory error(%v)", err)
c.JSON(nil, err)
return
}
exist1 := music.Category{}
if err = svc.DBArchive.Where("id=?", m.SwitchID).Where("state!=?", music.MusicDelete).First(&exist1).Error; err != nil {
log.Error("svc.indexCategory error(%v)", err)
c.JSON(nil, err)
return
}
if cate == 1 {
column = "camera_index"
} else {
column = "index"
}
m.UID = uid
if err := svc.DBArchive.Model(&music.Category{}).Where("id=?", m.ID).Update(map[string]int64{column: m.SwitchIndex}).Update(map[string]int64{"uid": uid}).Error; err != nil {
log.Error("svc.indexCategory error(%v)", err)
c.JSON(nil, err)
return
}
if err := svc.DBArchive.Model(&music.Category{}).Where("id=?", m.SwitchID).Update(map[string]int64{column: m.Index}).Update(map[string]int64{"uid": uid}).Error; err != nil {
log.Error("svc.indexCategory error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeCategory, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "index", Name: exist.Name})
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func addCategory(c *bm.Context) {
var (
err error
)
uid, uname := getUIDName(c)
m := &music.CategoryParam{}
if err = c.BindWith(m, binding.Form); err != nil {
log.Error("svc.addCategory bind error(%v)", err)
return
}
m.UID = uid
exist := &music.Category{}
if err = svc.DBArchive.Where("state!=?", music.MusicDelete).Where("name=?", m.Name).First(&exist).Error; err != nil && err != gorm.ErrRecordNotFound {
c.JSON(nil, err)
return
}
if exist.ID > 0 {
c.JSON(map[string]int64{
"id": exist.ID,
}, nil)
return
}
if err = svc.DBArchive.Create(m).Error; err != nil {
log.Error("svc.addCategory Create error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeCategory, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "add", Name: m.Name})
c.JSON(map[string]int64{
"id": m.ID,
}, nil)
}
func delCategory(c *bm.Context) {
var (
req = c.Request.PostForm
id = parseInt(req.Get("id"))
err error
)
exist := music.Category{}
if err = svc.DBArchive.Where("id=?", id).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
if err := svc.DBArchive.Model(music.Category{}).Where("id=?", id).Update(map[string]int{"state": music.MusicDelete}).Update(map[string]int64{"uid": uid}).Error; err != nil {
log.Error("svc.delCategory error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeCategory, &music.LogParam{ID: id, UID: uid, UName: uname, Action: "del", Name: exist.Name})
c.JSON(map[string]int{
"code": 0,
}, nil)
}

View File

@@ -0,0 +1,178 @@
package http
import (
"go-common/app/admin/main/creative/model/logcli"
"go-common/app/admin/main/creative/model/music"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
"go-common/library/xstr"
"github.com/jinzhu/gorm"
)
func searchMaterial(c *bm.Context) {
var (
req = c.Request.Form
err error
items []*music.MaterialMixParent
count int64
pid = atoi(req.Get("pid"))
name = req.Get("name")
)
db := svc.DBArchive.Where("music_material.state!=?", music.MusicDelete)
if pid != 0 {
db = db.Where("music_material.pid=?", pid)
}
if name != "" {
db = db.Where("music_material.name=?", name)
}
db.Model(&music.Material{}).Count(&count)
if err = db.Model(&music.Material{}).
Joins("left join music_material p on p.id=music_material.pid").
Select("music_material.*,p.name as p_name").
Order("music_material.index").Find(&items).Error; err != nil {
log.Error("%v\n", err)
c.JSON(nil, err)
return
}
pager := &music.MaterialMixParentPager{
Pager: &music.Pager{Num: 1, Size: int(count), Total: count},
Items: items,
}
c.JSON(pager, nil)
}
func materialInfo(c *bm.Context) {
var (
req = c.Request.Form
id = parseInt(req.Get("id"))
err error
)
m := &music.MaterialParam{}
if err = svc.DBArchive.Where("id=?", id).Where("state!=?", music.MusicDelete).First(&m).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
c.JSON(map[string]*music.MaterialParam{
"data": m,
}, nil)
}
func editMaterial(c *bm.Context) {
var (
req = c.Request.PostForm
id = parseInt(req.Get("id"))
err error
)
m := &music.MaterialParam{}
if err = c.BindWith(m, binding.Form); err != nil {
return
}
exist := music.Material{}
if err = svc.DBArchive.Where("id=?", id).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
uid, uname := getUIDName(c)
m.UID = uid
if err = svc.DBArchive.Model(&music.Material{}).Where("id=?", id).Update(m).Error; err != nil {
log.Error("svc.editMaterial error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeMaterial, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "update", Name: m.Name})
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func addMaterial(c *bm.Context) {
var (
err error
)
m := &music.MaterialParam{}
if err = c.BindWith(m, binding.Form); err != nil {
return
}
uid, uname := getUIDName(c)
m.UID = uid
exist := &music.Material{}
if err = svc.DBArchive.Where("state!=?", music.MusicDelete).Where("name=?", m.Name).First(&exist).Error; err != nil && err != gorm.ErrRecordNotFound {
c.JSON(nil, err)
return
}
if exist.ID > 0 {
c.JSON(map[string]int64{
"id": exist.ID,
}, nil)
return
}
if err = svc.DBArchive.Create(m).Error; err != nil {
log.Error("svc.addMaterial error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeMaterial, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "add", Name: m.Name})
c.JSON(map[string]int64{
"id": m.ID,
}, nil)
}
func delMaterial(c *bm.Context) {
var (
req = c.Request.PostForm
id = parseInt(req.Get("id"))
err error
)
exist := music.Material{}
if err = svc.DBArchive.Where("id=?", id).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
uid, uname := getUIDName(c)
if err = svc.DBArchive.Model(music.Material{}).Where("id=?", id).Update(map[string]int{"state": music.MusicDelete}).Update(map[string]int64{"uid": uid}).Error; err != nil {
log.Error("svc.delMaterial error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeMaterial, &music.LogParam{ID: id, UID: uid, UName: uname, Action: "del", Name: exist.Name})
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func batchDeleteMaterial(c *bm.Context) {
var (
err error
req = c.Request.PostForm
ids = req.Get("ids")
arrids []int64
)
uid, uname := getUIDName(c)
if arrids, err = xstr.SplitInts(ids); err != nil {
log.Error("svc.batchDeleteCategoryRelation SplitInts error(%v)", err)
c.JSON(nil, err)
return
}
for _, id := range arrids {
if err = svc.DBArchive.Model(music.Material{}).Where("id=?", id).Update(map[string]int{"state": music.MusicDelete}).Error; err != nil {
log.Error("svc.batchDeleteMaterial error(%v)", err)
err = nil
continue
}
//for log
exist := music.Material{}
if err = svc.DBArchive.Where("id=?", id).First(&exist).Error; err != nil {
err = nil
continue
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeMaterial, &music.LogParam{ID: id, UID: uid, UName: uname, Action: "del", Name: exist.Name})
}
c.JSON(map[string]int64{
"code": 0,
}, nil)
}

View File

@@ -0,0 +1,315 @@
package http
import (
"go-common/app/admin/main/creative/model/logcli"
"go-common/app/admin/main/creative/model/music"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
"go-common/library/xstr"
"github.com/jinzhu/gorm"
)
func searchCategoryRelation(c *bm.Context) {
var (
req = c.Request.Form
err error
items []*music.CategoryList
count int64
mid = atoi(req.Get("mid"))
tid = atoi(req.Get("tid"))
sid = atoi(req.Get("sid"))
name = req.Get("name")
page = atoi(req.Get("page"))
size = 20
)
if page == 0 {
page = 1
}
//init sql
db := svc.DBArchive.Model(&music.CategoryList{}).
Joins("left join music on music.sid=music_with_category.sid").
Joins("left join music_category on music_category.id=music_with_category.tid").
Where("music_with_category.state !=?", music.MusicDelete).
Where("music.state !=?", music.MusicDelete).
Select("music_with_category.*,music_category.name as category_name,music.name,music.cover,music.playurl,music.duration,music.mid,music.musicians,music.state as music_state,music.tags,music.timeline,music.frontname,music.cooperate")
if mid != 0 {
db = db.Where("mid=?", mid)
}
if sid != 0 {
db = db.Where("music_with_category.sid=?", sid)
}
if name != "" {
db = db.Where("music_category.name=?", name)
}
if tid != 0 {
db = db.Where("music_with_category.tid=?", tid)
}
//count total
db.Model(&music.CategoryList{}).Count(&count)
if err = db.Order("music_with_category.index").Offset((page - 1) * size).Limit(size).Find(&items).Error; err != nil {
log.Error("%v\n", err)
c.JSON(nil, err)
return
}
pager := &music.CategoryListPager{
Pager: &music.Pager{Num: page, Size: size, Total: count},
Items: items,
}
c.JSON(pager, nil)
}
func musicCategoryRelationInfo(c *bm.Context) {
var (
req = c.Request.Form
id = parseInt(req.Get("id"))
err error
)
m := &music.WithCategoryParam{}
if err = svc.DBArchive.Where("id=?", id).Where("state!=?", music.MusicDelete).First(&m).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
c.JSON(map[string]*music.WithCategoryParam{
"data": m,
}, nil)
}
func editCategoryRelation(c *bm.Context) {
var (
req = c.Request.PostForm
id = parseInt(req.Get("id"))
err error
)
uid, uname := getUIDName(c)
m := &music.WithCategoryParam{}
if err = c.BindWith(m, binding.Form); err != nil {
httpCode(c, "参数错误", ecode.RequestErr)
return
}
exist := music.WithCategory{}
if err = svc.DBArchive.Where("id=?", id).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
if err = svc.DBArchive.Model(&music.WithCategory{}).Where("id=?", id).Update(m).Error; err != nil {
log.Error("svc.editCategoryRelation error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeCategoryRelation, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "update", Name: string(m.ID)})
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func indexCategoryRelation(c *bm.Context) {
var (
err error
)
uid, uname := getUIDName(c)
m := &music.IndexParam{}
if err = c.BindWith(m, binding.Form); err != nil {
return
}
exist := music.WithCategory{}
if err = svc.DBArchive.Where("id=?", m.ID).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
exist1 := music.WithCategory{}
if err = svc.DBArchive.Where("id=?", m.SwitchID).Where("state!=?", music.MusicDelete).First(&exist1).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
if err = svc.DBArchive.Model(&music.WithCategory{}).Where("id=?", m.ID).Update(map[string]int64{"index": m.SwitchIndex}).Update(map[string]int64{"uid": uid}).Error; err != nil {
log.Error("svc.indexCategoryRelation error(%v)", err)
c.JSON(nil, err)
return
}
if err = svc.DBArchive.Model(&music.WithCategory{}).Where("id=?", m.SwitchID).Update(map[string]int64{"index": m.Index}).Update(map[string]int64{"uid": uid}).Error; err != nil {
log.Error("svc.indexCategoryRelation error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeCategoryRelation, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "index", Name: string(m.ID)})
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func addCategoryRelation(c *bm.Context) {
var (
err error
)
uid, uname := getUIDName(c)
m := &music.WithCategoryParam{}
if err = c.BindWith(m, binding.Form); err != nil {
log.Error("svc.addCategoryRelation bind error(%v)", err)
return
}
exist := &music.WithCategory{}
if err = svc.DBArchive.Where("state!=?", music.MusicDelete).Where("sid=?", m.Sid).Where("tid=?", m.Tid).First(&exist).Error; err != nil && err != gorm.ErrRecordNotFound {
c.JSON(nil, err)
return
}
if exist.ID > 0 {
c.JSON(map[string]int64{
"id": exist.ID,
}, nil)
return
}
if err = svc.DBArchive.Create(m).Error; err != nil {
log.Error("svc.addCategoryRelation error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeCategoryRelation, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "add", Name: string(m.ID)})
c.JSON(map[string]int64{
"id": m.ID,
}, nil)
}
func batchAddCategoryRelation(c *bm.Context) {
var (
err error
sids, sendIds []int64
sidsNotify = make(map[int64]*music.SidNotify)
)
uid, uname := getUIDName(c)
m := &music.BatchMusicWithCategoryParam{}
if err = c.BindWith(m, binding.Form); err != nil {
log.Error("svc.batchAddCategoryRelation bind error(%v)", err)
return
}
//todo tid 必须是二级分类
if sids, err = xstr.SplitInts(m.SidList); err != nil {
log.Error("svc.batchAddCategoryRelation SplitInts error(%v)", err)
c.JSON(nil, err)
return
}
max := music.WithCategory{}
if err = svc.DBArchive.Model(&music.WithCategory{}).Where("tid=?", m.Tid).Where("state!=?", music.MusicDelete).Order("music_with_category.index desc").First(&max).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("svc.batchAddMaterialRelation max error(%v)", err)
c.JSON(nil, err)
return
}
thisIndex := max.Index
i := int64(1)
for _, sid := range sids {
sidnotify := music.SidNotify{Sid: sid}
//find mid
musicExist := music.Music{}
if err = svc.DBArchive.Model(&music.Music{}).Where("sid=?", sid).First(&musicExist).Error; err != nil {
log.Error("svc.batchAddMaterialRelation check exist sid (%d) error(%v)", sid, err)
continue
}
//check mid first bind
midExists := music.WithCategory{}
if err = svc.DBArchive.Model(&music.WithCategory{}).Joins("left join music on music.sid=music_with_category.sid").Where("music.mid=?", musicExist.Mid).First(&midExists).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("svc.batchAddMaterialRelation check mid exist sid mid (%d,%d) error(%v)", sid, musicExist.Mid, err)
c.JSON(nil, err)
return
}
if err == gorm.ErrRecordNotFound {
sidnotify.MidFirst = true
}
//check sid bind
sidExists := music.WithCategory{}
if err = svc.DBArchive.Model(&music.WithCategory{}).Where("sid=?", sid).First(&sidExists).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("svc.batchAddMaterialRelation check sid exist sid mid (%d,%d) error(%v)", sid, musicExist.Mid, err)
c.JSON(nil, err)
return
}
if err == gorm.ErrRecordNotFound {
sidnotify.SidFirst = true
}
//check sid-tid bind exists
exists := music.WithCategory{}
if err = svc.DBArchive.Model(&music.WithCategory{}).Where("sid=?", sid).Where("tid=?", m.Tid).Where("state!=?", music.MusicDelete).First(&exists).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("svc.batchAddMaterialRelation check exist sid tid (%d,%d) error(%v)", sid, m.Tid, err)
c.JSON(nil, err)
return
}
if exists.ID > 0 {
//pass
continue
}
//should create bind
mp := &music.WithCategoryParam{Sid: sid, Tid: m.Tid, Index: thisIndex + i}
if err = svc.DBArchive.Create(mp).Error; err != nil {
log.Error("svc.batchAddMaterialRelation Create error(%v)", err)
continue
}
sidsNotify[sid] = &sidnotify
i++
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeCategoryRelation, &music.LogParam{ID: mp.Sid, UID: uid, UName: uname, Action: "add", Name: string(mp.Sid)})
}
log.Info("svc.SendNotify param SendList(%+v) sidsNotify(%+v)", m.SendList, sidsNotify)
if m.SendList != "" {
if sendIds, err = xstr.SplitInts(m.SendList); err != nil {
log.Error("svc.batchAddCategoryRelation SplitInts SendList error(%v)", err)
c.JSON(nil, err)
return
}
log.Info("svc.SendNotify param sendIds(%+v) sidsNotify(%+v)", sendIds, sidsNotify)
svc.SendNotify(c, sendIds, sidsNotify)
}
c.JSON(map[string]int64{
"code": 0,
}, nil)
}
func batchDeleteCategoryRelation(c *bm.Context) {
var (
err error
req = c.Request.PostForm
ids = req.Get("ids")
arrids []int64
)
uid, uname := getUIDName(c)
if arrids, err = xstr.SplitInts(ids); err != nil {
log.Error("svc.batchDeleteCategoryRelation SplitInts error(%v)", err)
c.JSON(nil, err)
return
}
for _, id := range arrids {
if err = svc.DBArchive.Model(music.WithCategory{}).Where("id=?", id).Update(map[string]int{"state": music.MusicDelete}).Error; err != nil {
log.Error("svc.batchDeleteCategoryRelation error(%v)", err)
err = nil
continue
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeCategoryRelation, &music.LogParam{ID: id, UID: uid, UName: uname, Action: "delete", Name: string(id)})
}
c.JSON(map[string]int64{
"code": 0,
}, nil)
}
func delCategoryRelation(c *bm.Context) {
var (
req = c.Request.PostForm
id = parseInt(req.Get("id"))
err error
)
uid, uname := getUIDName(c)
exist := music.WithCategory{}
if err = svc.DBArchive.Where("id=?", id).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
c.JSON(nil, err)
return
}
if err = svc.DBArchive.Model(music.WithCategory{}).Where("id=?", id).Update(map[string]int{"state": music.MusicDelete}).Error; err != nil {
log.Error("svc.delCategoryRelation error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeCategoryRelation, &music.LogParam{ID: id, UID: uid, UName: uname, Action: "del", Name: string(exist.ID)})
c.JSON(map[string]int{
"code": 0,
}, nil)
}

View File

@@ -0,0 +1,145 @@
package http
import (
"go-common/app/admin/main/creative/model/logcli"
"go-common/app/admin/main/creative/model/music"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
"go-common/library/xstr"
"github.com/jinzhu/gorm"
)
func musicMaterialRelationInfo(c *bm.Context) {
var (
req = c.Request.Form
id = parseInt(req.Get("id"))
err error
)
m := &music.WithMaterialParam{}
if err = svc.DBArchive.Where("id=?", id).First(&m).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
c.JSON(map[string]*music.WithMaterialParam{
"data": m,
}, nil)
}
func editMaterialRelation(c *bm.Context) {
var (
err error
)
uid, uname := getUIDName(c)
m := &music.WithMaterialParam{}
if err = c.BindWith(m, binding.Form); err != nil {
return
}
exist := music.WithMaterial{}
if err = svc.DBArchive.Where("sid=?", m.Sid).Where("state!=?", music.MusicDelete).First(&exist).Error; err != nil {
c.JSON(nil, ecode.NothingFound)
return
}
m.ID = exist.ID
m.UID = uid
m.Index = exist.Index
if err = svc.DBArchive.Model(&music.WithMaterial{}).Where("id=?", exist.ID).Update(m).Error; err != nil {
log.Error("svc.editMaterialRelation error(%v)", err)
c.JSON(nil, err)
return
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeMaterialRelation, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "update", Name: string(m.ID)})
c.JSON(map[string]int{
"code": 0,
}, nil)
}
func addMaterialRelation(c *bm.Context) {
var (
err error
)
m := &music.WithMaterialParam{}
if err = c.BindWith(m, binding.Form); err != nil {
return
}
exist := &music.WithMaterial{}
//一期 sid tid 是 一一对应的关系
//check sid bind
if err = svc.DBArchive.Where("state!=?", music.MusicDelete).Where("sid=?", m.Sid).First(&exist).Error; err != nil && err != gorm.ErrRecordNotFound {
c.JSON(nil, err)
return
}
if exist.ID > 0 {
c.JSON(map[string]int64{
"id": exist.ID,
}, nil)
return
}
if err = svc.DBArchive.Create(m).Error; err != nil {
log.Error("svc.addMaterialRelation error(%v)", err)
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeMaterialRelation, &music.LogParam{ID: m.ID, UID: uid, UName: uname, Action: "add", Name: string(m.ID)})
c.JSON(map[string]int64{
"id": m.ID,
}, nil)
}
func batchAddMaterialRelation(c *bm.Context) {
var (
err error
sids []int64
)
uid, uname := getUIDName(c)
m := &music.BatchMusicWithMaterialParam{}
if err = c.BindWith(m, binding.Form); err != nil {
log.Error("svc.batchAddMaterialRelation bind error(%v)", err)
return
}
//todo tid 必须是二级分类
if sids, err = xstr.SplitInts(m.SidList); err != nil {
log.Error("svc.batchAddMaterialRelation SplitInts error(%v)", err)
c.JSON(nil, err)
return
}
max := music.WithMaterial{}
if err = svc.DBArchive.Model(&music.WithMaterial{}).Where("tid=?", m.Tid).Where("state!=?", music.MusicDelete).Order("music_with_material.index desc").First(&max).Error; err != nil && err != gorm.ErrRecordNotFound {
//sql err
log.Error("svc.batchAddMaterialRelation max index error(%v)", err)
return
}
thisIndex := max.Index
i := int64(1)
for _, sid := range sids {
//check exists
exists := music.WithMaterial{}
if err = svc.DBArchive.Model(&music.WithMaterial{}).Where("sid=?", sid).Where("state!=?", music.MusicDelete).First(&exists).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("svc.batchAddMaterialRelation check exist sid tid (%d,%d) error(%v)", sid, m.Tid, err)
c.JSON(nil, err)
return
}
if exists.ID > 0 {
//覆盖
if err = svc.DBArchive.Model(&music.WithMaterial{}).Where("sid=?", sid).Where("state!=?", music.MusicDelete).Update("tid", m.Tid).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("svc.batchAddMaterialRelation Update error(%v)", err)
continue
}
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeMaterialRelation, &music.LogParam{ID: exists.Sid, UID: uid, UName: uname, Action: "update", Name: string(exists.Sid)})
} else {
mp := &music.WithMaterialParam{Sid: sid, Tid: m.Tid, Index: thisIndex + i}
if err = svc.DBArchive.Create(mp).Error; err != nil {
log.Error("svc.batchAddMaterialRelation Create error(%v)", err)
continue
}
i++
svc.SendMusicLog(c, logcli.LogClientArchiveMusicTypeMaterialRelation, &music.LogParam{ID: mp.Sid, UID: uid, UName: uname, Action: "add", Name: string(mp.Sid)})
}
}
c.JSON(map[string]int64{
"code": 0,
}, nil)
}

View File

@@ -0,0 +1,192 @@
package http
import (
"go-common/app/admin/main/creative/model/operation"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/render"
"net/http"
"time"
)
func listCollectArcOper(c *bm.Context) {
var (
err error
ops []*operation.Operation
total int
)
v := new(struct {
Type int8 `form:"type"`
Platform int8 `form:"platform"`
Pn int `form:"pn" validate:"min=1"`
Ps int `form:"ps" validate:"min=1"`
})
if err = c.Bind(v); err != nil {
return
}
if v.Pn < 1 {
v.Pn = 1
}
if v.Ps < 20 {
v.Ps = 20
}
if _, ok := typesMap[v.Type]; !ok {
data := map[string]interface{}{
"code": ecode.RequestErr,
"message": "forbid request with wrong type enum value",
}
c.Render(http.StatusOK, render.MapJSON(data))
return
}
if _, ok := platformMap[v.Platform]; !ok {
data := map[string]interface{}{
"code": ecode.RequestErr,
"message": "forbid request with wrong platform enum value",
}
c.Render(http.StatusOK, render.MapJSON(data))
return
}
now := time.Now().Format("2006-01-02 15:04:05")
where := " dtime = '0000-00-00 00:00:00' AND type = 'collect_arc' AND platform = ?"
if v.Platform == 100 {
where = " dtime = '0000-00-00 00:00:00' AND type = 'collect_arc' "
}
if v.Type == 0 {
where += " AND (stime < ? AND etime > ?) "
} else if v.Type == 1 {
where += " AND (stime > ? OR etime < ?) "
} else if v.Type == 2 {
where += " AND 1=1 "
}
if v.Type == 2 {
if v.Platform == 100 {
if err = svc.DB.Debug().Model(&operation.Operation{}).Order("rank ASC").Offset((v.Pn-1)*v.Ps).Limit(v.Ps).Find(&ops, where).Error; err != nil {
c.JSON(nil, err)
return
}
svc.DB.Debug().Model(&operation.Operation{}).Where(where).Count(&total)
} else {
if err = svc.DB.Debug().Model(&operation.Operation{}).Order("rank ASC").Offset((v.Pn-1)*v.Ps).Limit(v.Ps).Find(&ops, where, v.Platform).Error; err != nil {
c.JSON(nil, err)
return
}
svc.DB.Debug().Model(&operation.Operation{}).Where(where, v.Platform).Count(&total)
}
} else {
if v.Platform == 100 {
if err = svc.DB.Debug().Model(&operation.Operation{}).Order("rank ASC").Offset((v.Pn-1)*v.Ps).Limit(v.Ps).Find(&ops, where, now, now).Error; err != nil {
c.JSON(nil, err)
return
}
svc.DB.Debug().Model(&operation.Operation{}).Where(where, now, now).Count(&total)
} else {
if err = svc.DB.Debug().Model(&operation.Operation{}).Order("rank ASC").Offset((v.Pn-1)*v.Ps).Limit(v.Ps).Find(&ops, where, v.Platform, now, now).Error; err != nil {
c.JSON(nil, err)
return
}
svc.DB.Debug().Model(&operation.Operation{}).Where(where, v.Platform, now, now).Count(&total)
}
}
var opsView []*operation.ViewOperation
layout := "2006-01-02 15:04:05"
for _, v := range ops {
var (
status string
timeNow = time.Now()
stime, _ = time.Parse(time.RFC3339, v.Stime)
etime, _ = time.Parse(time.RFC3339, v.Etime)
ctime, _ = time.Parse(time.RFC3339, v.Ctime)
mtime, _ = time.Parse(time.RFC3339, v.Mtime)
dtime, _ = time.Parse(time.RFC3339, v.Dtime)
)
if time.Now().Before(etime) && timeNow.After(stime) {
status = "显示"
} else {
status = "隐藏"
}
opsView = append(opsView, &operation.ViewOperation{
ID: v.ID,
Type: v.Type,
Ads: v.Ads,
Platform: v.Platform,
Rank: v.Rank,
Pic: v.Pic,
Link: v.Link,
Content: v.Content,
Username: v.Username,
Remark: v.Remark,
Note: v.Note,
AppPic: v.AppPic,
Stime: stime.Format(layout),
Etime: etime.Format(layout),
Ctime: ctime.Format(layout),
Dtime: dtime.Format(layout),
Mtime: mtime.Format(layout),
Status: status,
})
}
c.Render(http.StatusOK, render.MapJSON(map[string]interface{}{
"code": 0,
"message": "0",
"data": opsView,
"pager": map[string]int{
"page": v.Pn,
"pagesize": v.Ps,
"total": total,
},
}))
}
func addCollectArcOper(c *bm.Context) {
var (
err error
)
username, _ := c.Get("username")
uname, ok := username.(string)
if !ok || len(uname) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
v := new(struct {
Ads int8 `form:"ads" `
Rank int8 `form:"rank"`
Pic string `form:"pic" validate:"required"`
Link string `form:"link" validate:"required"`
Content string `form:"content" validate:"required"`
Remark string `form:"remark"`
Note string `form:"note"`
AppPic string `form:"app_pic" validate:"required"`
Platform int8 `form:"platform"`
Stime string `form:"stime" validate:"required"`
Etime string `form:"etime" validate:"required"`
})
if err = c.Bind(v); err != nil {
return
}
m := &operation.Operation{
Type: "collect_arc",
Ads: v.Ads,
Rank: v.Rank,
Pic: v.Pic,
Link: v.Link,
Content: v.Content,
Username: uname,
Remark: v.Remark,
Note: v.Note,
AppPic: v.AppPic,
Platform: v.Platform,
Ctime: time.Now().Format("2006-01-02 15:04:05"),
Stime: v.Stime,
Etime: v.Etime,
}
db := svc.DB.Debug().Model(&operation.Operation{}).Create(m)
if err = db.Error; err != nil {
log.Error("creativeSvc.Operation error(%v)", err)
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(map[string]interface{}{
"id": db.Value.(*operation.Operation).ID,
}, nil)
}

View File

@@ -0,0 +1,522 @@
package http
import (
"encoding/json"
"io/ioutil"
"net/http"
"go-common/app/admin/main/creative/model/task"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/render"
"go-common/library/xstr"
)
func taskList(c *bm.Context) {
var err error
v := new(struct {
Type int8 `form:"type"`
})
if err = c.Bind(v); err != nil {
return
}
res, err := svc.TaskList(v.Type)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(res, nil)
}
func taskPre(c *bm.Context) {
c.Render(http.StatusOK, render.MapJSON(map[string]interface{}{
"code": 0,
"message": "0",
"data": map[string]interface{}{
"target": task.TargetMap,
"root_type": task.TaskRootNameMap,
"group_type": task.TaskGroupNameMap,
},
}))
}
func viewGroup(c *bm.Context) {
var err error
v := new(struct {
ID int64 `form:"id"`
})
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
res, err := svc.TaskGroup(v.ID)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(res, nil)
}
func addGroup(c *bm.Context) {
var err error
v := new(task.TaskGroup)
if err = c.Bind(v); err != nil {
log.Error("addGroup c.Bind v(%+v) error(%v)", v, err)
return
}
var rewardsIDs []int64
if v.RewardIDs != "" {
if rewardsIDs, err = xstr.SplitInts(v.RewardIDs); err != nil {
log.Error("addGroup xstr.SplitInts task v.RewardIDs(%s) rewardsIDs(%+v)|error(%v)", v.RewardIDs, rewardsIDs, err)
c.JSON(nil, ecode.RequestErr)
return
}
}
id, err := svc.AddTaskGroup(v, rewardsIDs)
if err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "添加任务组", OID: id, Content: v})
c.JSON(map[string]interface{}{
"id": id,
}, nil)
}
func editGroup(c *bm.Context) {
var err error
v := new(task.TaskGroup)
if err = c.Bind(v); err != nil {
log.Error("editGroup c.Bind v(%+v) error(%v)", v, err)
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
var rewardsIDs []int64
if v.RewardIDs != "" {
if rewardsIDs, err = xstr.SplitInts(v.RewardIDs); err != nil {
log.Error("editGroup xstr.SplitInts task v.RewardIDs(%s) rewardsIDs(%+v)|error(%v)", v.RewardIDs, rewardsIDs, err)
c.JSON(nil, ecode.RequestErr)
return
}
}
id, err := svc.EditTaskGroup(v, rewardsIDs)
if err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "编辑任务组", OID: id, Content: v})
c.JSON(map[string]interface{}{
"id": id,
}, nil)
}
func orderGroup(c *bm.Context) {
var err error
v := new(task.OrderTask)
if err = c.Bind(v); err != nil {
log.Error("orderGroup c.Bind v(%+v) error(%v)", v, err)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "移动任务组顺序", OID: v.ID, Content: v})
c.JSON(nil, svc.OrderTaskGroup(v))
}
func upStateGroup(c *bm.Context) {
var err error
v := new(struct {
ID int64 `form:"id" validate:"required"`
State int8 `form:"state"`
})
if err = c.Bind(v); err != nil {
log.Error("upStateGroup c.Bind v(%+v) error(%v)", v, err)
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "更新任务组状态", OID: v.ID, Content: v})
c.JSON(nil, svc.UpStateGroup(v.ID, v.State))
}
func viewSubtask(c *bm.Context) {
var err error
v := new(struct {
ID int64 `form:"id"`
})
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
res, err := svc.Task(v.ID)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(res, nil)
}
func addSubtask(c *bm.Context) {
var err error
v := new(task.Task)
if err = c.Bind(v); err != nil {
log.Error("addSubtask c.Bind v(%+v) error(%v)", v, err)
return
}
var rewardsIDs []int64
if v.RewardIDs != "" {
if rewardsIDs, err = xstr.SplitInts(v.RewardIDs); err != nil {
log.Error("addSubtask xstr.SplitInts task v.RewardIDs(%s) rewardsIDs(%+v)|error(%v)", v.RewardIDs, rewardsIDs, err)
c.JSON(nil, ecode.RequestErr)
return
}
}
id, err := svc.AddSubtask(v, rewardsIDs)
if err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "添加子任务", OID: id, Content: v})
c.JSON(map[string]interface{}{
"id": id,
}, nil)
}
func editSubtask(c *bm.Context) {
var err error
v := new(task.Task)
if err = c.Bind(v); err != nil {
log.Error("editSubtask c.Bind v(%+v) error(%v)", v, err)
return
}
if v.ID == 0 {
log.Error("editSubtask v.ID(%d)", v.ID)
c.JSON(nil, ecode.RequestErr)
return
}
var rewardsIDs []int64
if v.RewardIDs != "" {
if rewardsIDs, err = xstr.SplitInts(v.RewardIDs); err != nil {
log.Error("addSubtask xstr.SplitInts task v.RewardIDs(%s) rewardsIDs(%+v)|error(%v)", v.RewardIDs, rewardsIDs, err)
c.JSON(nil, ecode.RequestErr)
return
}
}
id, err := svc.EditSubtask(v, rewardsIDs)
if err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "编辑子任务", OID: id, Content: v})
c.JSON(map[string]interface{}{
"id": id,
}, nil)
}
func orderSubtask(c *bm.Context) {
var err error
v := new(task.OrderTask)
if err = c.Bind(v); err != nil {
log.Error("orderSubtask c.Bind v(%+v) error(%v)", v, err)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "移动子任务顺序", OID: v.ID, Content: v})
c.JSON(nil, svc.OrderSubTask(v))
}
func upStateSubtask(c *bm.Context) {
var err error
v := new(struct {
ID int64 `form:"id" validate:"required"`
State int8 `form:"state"`
})
if err = c.Bind(v); err != nil {
log.Error("upStateSubtask c.Bind v(%+v) error(%v)", v, err)
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "更新子任务状态", OID: v.ID, Content: v})
c.JSON(nil, svc.UpStateSubTask(v.ID, v.State))
}
func transferSubtask(c *bm.Context) {
var err error
v := new(struct {
ID int64 `form:"id" validate:"required"`
GroupID int64 `form:"group_id" validate:"required"`
})
if err = c.Bind(v); err != nil {
log.Error("transferSubtask c.Bind v(%+v) error(%v)", v, err)
return
}
if v.ID == 0 || v.GroupID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "转移子任务到别的组", OID: v.ID, Content: v})
c.JSON(nil, svc.TransferSubtask(v.ID, v.GroupID))
}
func rewardTree(c *bm.Context) {
c.JSON(svc.RewardTree(), nil)
}
func viewReward(c *bm.Context) {
var err error
v := new(struct {
ID int64 `form:"id"`
})
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
rd, err := svc.ViewReward(v.ID)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(rd, nil)
}
func addReward(c *bm.Context) {
var err error
v := new(task.Reward)
if err = c.Bind(v); err != nil {
log.Error("addReward c.Bind v(%+v) error(%v)", v, err)
return
}
id, err := svc.AddReward(v)
if err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "添加奖励", OID: id, Content: v})
c.JSON(map[string]interface{}{
"id": id,
}, nil)
}
func editReward(c *bm.Context) {
var err error
v := new(task.Reward)
if err = c.Bind(v); err != nil {
log.Error("editReward c.Bind v(%+v) error(%v)", v, err)
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
id, err := svc.EditReward(v)
if err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "编辑奖励", OID: id, Content: v})
c.JSON(map[string]interface{}{
"id": id,
}, nil)
}
func upStateReward(c *bm.Context) {
var err error
v := new(struct {
ID int64 `form:"id" validate:"required"`
State int8 `form:"state"`
})
if err = c.Bind(v); err != nil {
log.Error("upStateReward c.Bind v(%+v) error(%v)", v, err)
return
}
if v.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "更新奖励状态", OID: v.ID, Content: v})
c.JSON(nil, svc.UpStateReward(v.ID, v.State))
}
func listGiftReward(c *bm.Context) {
res, err := svc.ListGiftReward()
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(res, nil)
}
func viewGiftReward(c *bm.Context) {
var err error
v := new(task.GiftReward)
if err = c.Bind(v); err != nil {
return
}
if v.RootType == 0 || v.TaskType == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
res, err := svc.ViewGiftReward(v)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(res, nil)
}
func addGiftReward(c *bm.Context) {
var err error
v := new(task.GiftReward)
if err = c.Bind(v); err != nil {
log.Error("addGiftReward c.Bind v(%+v) error(%v)", v, err)
return
}
var rewardsIDs []int64
if v.RewardIDs == "" {
c.JSON(nil, ecode.RequestErr)
return
}
if rewardsIDs, err = xstr.SplitInts(v.RewardIDs); err != nil || len(rewardsIDs) == 0 { //注意礼包配置,奖励必传
log.Error("addGiftReward xstr.SplitInts task v.RewardIDs(%s) rewardsIDs(%+v)|error(%v)", v.RewardIDs, rewardsIDs, err)
c.JSON(nil, ecode.RequestErr)
return
}
rows, err := svc.AddGiftReward(v, rewardsIDs)
if err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "添加礼包", OID: 0, Content: v})
c.JSON(map[string]interface{}{
"rows": rows,
}, nil)
}
func editGiftReward(c *bm.Context) {
var err error
v := new(task.GiftReward)
if err = c.Bind(v); err != nil {
log.Error("editGiftReward c.Bind v(%+v) error(%v)", v, err)
return
}
if v.RootType == 0 || v.TaskType == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
var rewardsIDs []int64
if v.RewardIDs == "" {
c.JSON(nil, ecode.RequestErr)
return
}
if rewardsIDs, err = xstr.SplitInts(v.RewardIDs); err != nil || len(rewardsIDs) == 0 { //注意礼包配置,奖励必传
log.Error("editGiftReward xstr.SplitInts task v.RewardIDs(%s) rewardsIDs(%+v)|error(%v)", v.RewardIDs, rewardsIDs, err)
c.JSON(nil, ecode.RequestErr)
return
}
rows, err := svc.EditGiftReward(v, rewardsIDs)
if err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "编辑礼包", OID: 0, Content: v})
c.JSON(map[string]interface{}{
"rows": rows,
}, nil)
}
func upStateGiftReward(c *bm.Context) {
var err error
v := new(task.GiftReward)
if err = c.Bind(v); err != nil {
log.Error("upStateGiftReward c.Bind v(%+v) error(%v)", v, err)
return
}
if v.RootType == 0 || v.TaskType == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
rows, err := svc.UpGiftReward(v)
if err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "更新礼包状态", OID: 0, Content: v})
c.JSON(map[string]interface{}{
"rows": rows,
}, nil)
}
func batchOnline(c *bm.Context) {
var err error
bs, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
log.Error("batchOnline ioutil.ReadAll error(%v)", err)
c.JSON(nil, ecode.RequestErr)
return
}
c.Request.Body.Close()
var v []*task.TaskGroup
err = json.Unmarshal(bs, &v)
if err != nil {
log.Error("batchOnline json.Unmarshal v(%+v) error(%v)", v, err)
c.JSON(nil, ecode.RequestErr)
return
}
err = svc.BatchOnline(v)
if err != nil {
c.JSON(nil, err)
return
}
uid, uname := getUIDName(c)
svc.SendTaskLog(c, &task.LogParam{UID: uid, UName: uname, Action: "批量刷新上线", OID: 0, Content: v})
c.JSON(nil, nil)
}

View File

@@ -0,0 +1,46 @@
package http
import (
"fmt"
"io/ioutil"
"net/http"
"time"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
func upload(c *bm.Context) {
file, _, err := c.Request.FormFile("file")
if err != nil {
log.Error("FormFile err(%v)", err)
httpCode(c, fmt.Sprintf("File Upload FormFile Error:(%v)", err), ecode.RequestErr)
return
}
defer file.Close()
content, err := ioutil.ReadAll(file)
if err != nil {
log.Error(" uploadFile.ReadAll error(%v)", err)
httpCode(c, fmt.Sprintf("File ioutil.ReadAll Error:(%v)", err), ecode.RequestErr)
return
}
filetype := http.DetectContentType(content)
switch filetype {
case "image/jpeg", "image/jpg":
case "image/gif":
case "image/png":
case "application/zip":
default:
httpCode(c, fmt.Sprintf("not allow filetype(%s)", filetype), ecode.RequestErr)
log.Warn("not allow filetype(%s) ", filetype)
return
}
local, err := svc.Upload(c, "", filetype, time.Now().Unix(), content)
if err != nil {
log.Error("svc.Upload error(%v)", err)
httpCode(c, fmt.Sprintf("svc.Upload error:(%v)", err), ecode.RequestErr)
return
}
c.JSON(local, nil)
}

View File

@@ -0,0 +1,93 @@
package http
import (
"crypto/md5"
"encoding/hex"
"flag"
"fmt"
"go-common/app/admin/main/creative/conf"
"io/ioutil"
"net/http"
"net/url"
"path/filepath"
"strconv"
"strings"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
)
const (
_host = "http://0.0.0.0:6344"
)
var (
_view = _host + "/x/admin/creative/whitelist/view"
)
func init() {
dir, _ := filepath.Abs("../cmd/creative-admin.toml")
flag.Set("conf", dir)
conf.Init()
}
// Sign fn
func Sign(params url.Values) (query string, err error) {
if len(params) == 0 {
return
}
if params.Get("appkey") == "" {
err = fmt.Errorf("utils http get must have parameter appkey")
return
}
if params.Get("appsecret") == "" {
err = fmt.Errorf("utils http get must have parameter appsecret")
return
}
if params.Get("sign") != "" {
err = fmt.Errorf("utils http get must have not parameter sign")
return
}
// sign
secret := params.Get("appsecret")
params.Del("appsecret")
tmp := params.Encode()
if strings.IndexByte(tmp, '+') > -1 {
tmp = strings.Replace(tmp, "+", "%20", -1)
}
mh := md5.Sum([]byte(tmp + secret))
params.Set("sign", hex.EncodeToString(mh[:]))
query = params.Encode()
return
}
func Test_View(t *testing.T) {
Convey("View", t, func() {
params := url.Values{}
params.Set("id", "7")
params.Set("appkey", conf.Conf.App.Key)
params.Set("appsecret", conf.Conf.App.Secret)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
var (
query, _ = Sign(params)
url string
)
url = _view + "?" + query
body, err := oget(url)
So(err, ShouldBeNil)
So(body, ShouldNotBeNil)
So(err, ShouldBeNil)
})
}
// oget http get request
func oget(url string) (body []byte, err error) {
resp, err := http.Get(url)
if err != nil {
return
}
defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body)
return
}

View File

@@ -0,0 +1,348 @@
package http
import (
"encoding/json"
"fmt"
"go-common/app/admin/main/creative/model/whitelist"
accapi "go-common/app/service/main/account/api"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/render"
"net/http"
"time"
)
var maxMid = int64(2147483647)
func viewWhiteList(c *bm.Context) {
var (
err error
info = &whitelist.Whitelist{}
)
if err = c.Bind(info); err != nil {
return
}
if info.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Debug().Model(&whitelist.Whitelist{}).First(info, info.ID).Error; err != nil {
c.JSON(nil, err)
return
}
if info.ID == 0 {
c.JSON(nil, ecode.NothingFound)
} else {
pfl, _ := svc.ProfileStat(c, info.MID)
if pfl.Profile != nil {
info.Name = pfl.Profile.Name
}
info.Fans = pfl.Follower
info.CurrentLevel = pfl.LevelInfo.Cur
c.JSON(info, nil)
}
}
func listWhiteList(c *bm.Context) {
var (
err error
wls []*whitelist.Whitelist
total int
)
v := new(struct {
MID int64 `form:"mid"`
AdminMID int64 `form:"admin_mid"`
State int8 `form:"state"`
Type int8 `form:"type"`
Page int `form:"pn"`
PageSize int `form:"ps"`
})
if err = c.Bind(v); err != nil {
return
}
if v.Page < 1 {
v.Page = 1
}
if v.PageSize < 20 {
v.PageSize = 20
}
where := " state = ? AND type = ? "
if v.MID != 0 {
where += " AND mid = ?"
if v.AdminMID != 0 {
where += " AND admin_id = ?"
if err = svc.DB.Debug().Model(&whitelist.Whitelist{}).Order("ctime DESC").Offset((v.Page-1)*v.PageSize).Limit(v.PageSize).Find(&wls, where, v.State, v.Type, v.MID, v.AdminMID).Error; err != nil {
c.JSON(nil, err)
}
svc.DB.Debug().Model(&whitelist.Whitelist{}).Where(where, v.State, v.Type, v.MID, v.AdminMID).Count(&total)
} else {
if err = svc.DB.Debug().Model(&whitelist.Whitelist{}).Order("ctime DESC").Offset((v.Page-1)*v.PageSize).Limit(v.PageSize).Find(&wls, where, v.State, v.Type, v.MID).Error; err != nil {
c.JSON(nil, err)
}
svc.DB.Debug().Model(&whitelist.Whitelist{}).Where(where, v.State, v.Type, v.MID).Count(&total)
}
} else {
if v.AdminMID != 0 {
where += " AND admin_id = ?"
if err = svc.DB.Debug().Model(&whitelist.Whitelist{}).Order("ctime DESC").Offset((v.Page-1)*v.PageSize).Limit(v.PageSize).Find(&wls, where, v.State, v.Type, v.AdminMID).Error; err != nil {
c.JSON(nil, err)
}
svc.DB.Debug().Model(&whitelist.Whitelist{}).Where(where, v.State, v.Type, v.AdminMID).Count(&total)
} else {
if err = svc.DB.Debug().Model(&whitelist.Whitelist{}).Order("ctime DESC").Offset((v.Page-1)*v.PageSize).Limit(v.PageSize).Find(&wls, where, v.State, v.Type).Error; err != nil {
c.JSON(nil, err)
}
svc.DB.Debug().Model(&whitelist.Whitelist{}).Where(where, v.State, v.Type).Count(&total)
}
}
wls, err = svc.Cards(c, wls)
if err != nil {
log.Error("svc.Cards error(%v)", err)
c.JSON(nil, err)
return
}
c.Render(http.StatusOK, render.MapJSON(map[string]interface{}{
"code": 0,
"message": "0",
"data": wls,
"pager": map[string]int{
"page": v.Page,
"pagesize": v.PageSize,
"total": total,
},
}))
}
func exportWhiteList(c *bm.Context) {
var (
err error
wls []*whitelist.Whitelist
total int
)
v := new(struct {
MID int64 `form:"mid;" `
AdminMID int64 `form:"admin_mid;" `
State int8 `form:"state"`
Type int8 `form:"type"`
Page int `form:"pn"`
PageSize int `form:"ps"`
})
if err = c.Bind(v); err != nil {
return
}
if v.Page < 1 {
v.Page = 1
}
if v.PageSize < 20 {
v.PageSize = 20
}
where := " state = ? AND type = ? "
if v.MID != 0 {
where += " AND mid = ?"
if v.AdminMID != 0 {
where += " AND admin_id = ?"
if err = svc.DB.Debug().Model(&whitelist.Whitelist{}).Order("ctime DESC").Offset((v.Page-1)*v.PageSize).Limit(v.PageSize).Find(&wls, where, v.State, v.Type, v.MID, v.AdminMID).Error; err != nil {
c.JSON(nil, err)
}
svc.DB.Debug().Model(&whitelist.Whitelist{}).Where(where, v.State, v.Type, v.MID, v.AdminMID).Count(&total)
} else {
if err = svc.DB.Debug().Model(&whitelist.Whitelist{}).Order("ctime DESC").Offset((v.Page-1)*v.PageSize).Limit(v.PageSize).Find(&wls, where, v.State, v.Type, v.MID).Error; err != nil {
c.JSON(nil, err)
}
svc.DB.Debug().Model(&whitelist.Whitelist{}).Where(where, v.State, v.Type, v.MID).Count(&total)
}
} else {
if v.AdminMID != 0 {
where += " AND admin_id = ?"
if err = svc.DB.Debug().Model(&whitelist.Whitelist{}).Order("ctime DESC").Offset((v.Page-1)*v.PageSize).Limit(v.PageSize).Find(&wls, where, v.State, v.Type, v.AdminMID).Error; err != nil {
c.JSON(nil, err)
}
svc.DB.Debug().Model(&whitelist.Whitelist{}).Where(where, v.State, v.Type, v.AdminMID).Count(&total)
} else {
if err = svc.DB.Debug().Model(&whitelist.Whitelist{}).Order("ctime DESC").Offset((v.Page-1)*v.PageSize).Limit(v.PageSize).Find(&wls, where, v.State, v.Type).Error; err != nil {
c.JSON(nil, err)
}
svc.DB.Debug().Model(&whitelist.Whitelist{}).Where(where, v.State, v.Type).Count(&total)
}
}
wls, err = svc.Cards(c, wls)
if err != nil {
log.Error("svc.Cards error(%v)", err)
c.JSON(nil, err)
return
}
fWLS, err := formatWhilteList(wls)
if err != nil {
log.Error("formatWhilteList error(%v)", err)
c.JSON(nil, err)
return
}
c.Render(http.StatusOK, CSV{
Content: FormatCSV(fWLS),
Title: fmt.Sprintf("%s-%d-%d-%s", time.Now().Format("2006-01-02"), v.Type, v.State, "white_list"),
})
}
func addWhiteList(c *bm.Context) {
var (
err error
pfl *accapi.ProfileStatReply
)
v := new(struct {
MID int64 `form:"mid" validate:"required,min=1,gte=1"`
AdminMID int64 `form:"admin_mid" validate:"required,min=1,gte=1"`
Comment string `form:"comment"`
State int8 `form:"state"`
Type int8 `form:"type"`
})
if err = c.Bind(v); err != nil {
return
}
if v.MID > maxMid || v.AdminMID > maxMid {
c.JSON(nil, ecode.RequestErr)
return
}
pfl, err = svc.ProfileStat(c, v.MID)
if err != nil || pfl == nil || pfl.Profile == nil || pfl.Profile.Mid == 0 {
log.Error("svc.Card zero result error(%v)", err)
c.JSON(nil, ecode.UserNotExist)
return
}
m := &whitelist.Whitelist{
State: v.State,
Type: v.Type,
Ctime: time.Now().Format("2006-01-02 15:04:05"),
MID: v.MID,
AdminMID: v.AdminMID,
Comment: v.Comment,
}
db := svc.DB.Debug().Model(&whitelist.Whitelist{}).Create(m)
if err = db.Error; err != nil {
log.Error("creativeSvc.whitelist error(%v)", err)
c.JSON(nil, err)
}
c.JSON(map[string]interface{}{
"id": db.Value.(*whitelist.Whitelist).ID,
}, nil)
}
func addBatchWhiteList(c *bm.Context) {
var (
err error
)
v := new(struct {
Params string `form:"params" validate:"required"`
})
if err = c.Bind(v); err != nil {
return
}
filterJSON := v.Params
if len(filterJSON) == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
type Filter struct {
MID int64 `json:"mid"`
AdminMID int64 `json:"admin_mid"`
Comment string `json:"comment"`
State int8 `json:"state"`
Type int8 `json:"type"`
}
var filtersJSONData []*Filter
if err = json.Unmarshal([]byte(filterJSON), &filtersJSONData); err != nil {
err = ecode.RequestErr
return
}
if len(filtersJSONData) == 0 {
err = ecode.RequestErr
return
}
db := svc.DB.Debug().Model(&whitelist.Whitelist{})
for _, v := range filtersJSONData {
m := &whitelist.Whitelist{
State: v.State,
Type: v.Type,
Ctime: time.Now().Format("2006-01-02 15:04:05"),
MID: v.MID,
AdminMID: v.AdminMID,
Comment: v.Comment,
}
db.Create(m)
if err = db.Error; err != nil {
log.Error("creativeSvc.batchWhitelist error(%v)", err)
c.JSON(nil, err)
return
}
}
c.JSON(nil, err)
}
func upWhiteList(c *bm.Context) {
var (
wl = &whitelist.Whitelist{}
pfl *accapi.ProfileStatReply
err error
)
v := new(struct {
ID int64 `form:"id"`
MID int64 `form:"mid" validate:"required,min=1,gte=1"`
AdminMID int64 `form:"admin_mid" validate:"required,min=1,gte=1"`
Comment string `form:"comment"`
})
if err = c.Bind(v); err != nil {
return
}
if v.ID == 0 || v.MID > maxMid || v.AdminMID > maxMid {
c.JSON(nil, ecode.RequestErr)
return
}
pfl, err = svc.ProfileStat(c, v.MID)
if err != nil || pfl == nil || pfl.Profile == nil || pfl.Profile.Mid == 0 {
log.Error("svc.Card zero result error(%v)", err)
c.JSON(nil, ecode.UserNotExist)
return
}
if err = svc.DB.Debug().Model(&whitelist.Whitelist{}).Find(wl, v.ID).Error; err != nil {
c.JSON(nil, err)
return
}
if err = svc.DB.Debug().Model(&whitelist.Whitelist{ID: v.ID}).Update(map[string]interface {
}{
"id": v.ID,
"mid": v.MID,
"admin_mid": v.AdminMID,
"comment": v.Comment,
"mtime": time.Now().Format("2006-01-02 15:04:05"),
}).Error; err != nil {
log.Error("svc.save error(%v)", err)
}
c.JSON(nil, err)
}
func delWhiteList(c *bm.Context) {
var (
wl = &whitelist.Whitelist{}
err error
)
if err = c.Bind(wl); err != nil {
return
}
if wl.ID == 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if err = svc.DB.Debug().Model(&whitelist.Whitelist{}).Find(wl, wl.ID).Error; err != nil {
c.JSON(nil, err)
return
}
if err = svc.DB.Debug().Model(&whitelist.Whitelist{ID: wl.ID}).Update(map[string]interface {
}{
"id": wl.ID,
"State": 0,
"mtime": time.Now().Format("2006-01-02 15:04:05"),
}).Error; err != nil {
log.Error("svc.del WhiteList error(%v)", err)
}
c.JSON(nil, err)
}

View File

@@ -0,0 +1,32 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"archive.go",
"occupation.go",
"tag.go",
],
importpath = "go-common/app/admin/main/creative/model/academy",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
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,147 @@
package academy
const (
//StateRemove 移除状态
StateRemove = -1
//StateNormal 正常状态
StateNormal = 0
//BusinessForArchvie 稿件
BusinessForArchvie = 1
//BusinessForArticle 专栏
BusinessForArticle = 2
//LogClientAcademy 日志服务类型
LogClientAcademy = 181
//DefaultState check search archive state
DefaultState = 2018
)
//TableName get table name
func (a *Archive) TableName() string {
return "academy_archive"
}
//Archive for academy achive & article.
type Archive struct {
ID int64 `gorm:"column:id"`
OID int64 `gorm:"column:oid"`
Title string `gorm:"column:title"`
State int8 `gorm:"column:state"`
Business int8 `gorm:"column:business"`
CTime string `gorm:"column:ctime"`
MTime string `gorm:"column:mtime"`
Comment string `gorm:"column:comment"`
Hot int64 `gorm:"column:hot"`
}
//TableName get table name
func (at *ArchiveTag) TableName() string {
return "academy_archive_tag"
}
//ArchiveTag for academy achive & tag relation .
type ArchiveTag struct {
ID int64 `gorm:"column:id"`
OID int64 `gorm:"column:oid"`
TID int64 `gorm:"column:tid"`
State int8 `gorm:"column:state"`
Business int8 `gorm:"column:business"`
CTime string `gorm:"column:ctime"`
MTime string `gorm:"column:mtime"`
}
//ArchiveOrigin for archive list.
type ArchiveOrigin struct {
OID int64
TIDs []int64
Comment string
Business int8
}
//ArchiveCount get archive count by tid.
type ArchiveCount struct {
TID int64 `gorm:"column:tid"`
Count int `gorm:"column:count"` //当前tag关联的稿件量
}
//ArchiveMeta for archive meta.
type ArchiveMeta struct {
OID int64 `json:"oid"`
State int32 `json:"state"`
Forbid int8 `json:"forbid"`
Cover string `json:"cover"`
Type string `json:"type"`
Title string `json:"title"`
UName string `json:"uname"`
Comment string `json:"comment"`
CTime int64 `json:"ctime"`
MTime int64 `json:"mtime"`
Tags map[int][]*TagMeta `json:"tags"`
Hot int64 `json:"hot"`
}
//ArchiveTags for archive tag relation.
type ArchiveTags struct {
ID int64 `gorm:"column:id"`
TID int64 `gorm:"column:tid"`
OID int64 `gorm:"column:oid"`
Type int8 `gorm:"column:type"`
Business int8 `gorm:"column:business"`
}
//Archives for archive list
type Archives struct {
Pager *Pager `json:"pager"`
Items []*ArchiveMeta `json:"items"`
}
// Pager Pager def.
type Pager struct {
Num int `json:"num"`
Size int `json:"size"`
Total int `json:"total"`
}
// LogParam for manager.
type LogParam struct {
UID int64 `json:"uid"`
UName string `json:"uname"`
Action string `json:"action"`
TID int64 `json:"tid"`
OIDs string `json:"oids"`
OName string `json:"oname"`
OState int8 `json:"ostate"`
}
// EsParam for es param.
type EsParam struct {
OID int64
Business int8
Keyword string
Uname string
TID []int64
Copyright int
State int
Pn int
Ps int
IP string
TidsMap map[int][]int64
}
// EsPage for es page.
type EsPage struct {
Num int `json:"num"`
Size int `json:"size"`
Total int `json:"total"`
}
// EsArc for search archive.
type EsArc struct {
OID int64 `json:"oid"`
TID []int64 `json:"tid"`
}
// SearchResult archive list from search.
type SearchResult struct {
Page *EsPage `json:"page"`
Result []*EsArc `json:"result"`
}

View File

@@ -0,0 +1,118 @@
package academy
//TableName get table name
func (o *Occupation) TableName() string {
return "academy_occupation"
}
//TableName get table name
func (s *Skill) TableName() string {
return "academy_skill"
}
//TableName get table name
func (s *Software) TableName() string {
return "academy_software"
}
//TableName get table name
func (s *ArcSkill) TableName() string {
return "academy_arc_skill"
}
//TableName get table name
func (s *TagLink) TableName() string {
return "academy_tag_link"
}
//Occupation for academy occupation.
type Occupation struct {
ID int64 `gorm:"column:id" form:"id" json:"id"`
Rank int64 `gorm:"column:rank" form:"rank" json:"rank"`
State int `gorm:"column:state" form:"state" json:"state"`
Name string `gorm:"column:name" form:"name" json:"name"`
Desc string `gorm:"column:desc" form:"desc" json:"desc"`
Logo string `gorm:"column:logo" form:"logo" json:"logo"`
MainStep string `gorm:"column:main_step" form:"main_step" json:"main_step"`
MainSoftware string `gorm:"column:main_software" form:"main_software" json:"main_software"`
CTime string `gorm:"column:ctime" form:"ctime" json:"-"`
MTime string `gorm:"column:mtime" form:"mtime" json:"-"`
Skill []*Skill `gorm:"-" form:"-" json:"skill"`
Count int `gorm:"-" form:"-" json:"count"`
}
//Skill for academy skill.
type Skill struct {
ID int64 `gorm:"column:id" form:"id" json:"id"`
OID int64 `gorm:"column:oid" form:"oid" json:"oid"`
State int `gorm:"column:state" form:"state" json:"state"`
Name string `gorm:"column:name" form:"name" json:"name"`
Desc string `gorm:"column:desc" form:"desc" json:"desc"`
CTime string `gorm:"column:ctime" form:"ctime" json:"-"`
MTime string `gorm:"column:mtime" form:"mtime" json:"-"`
Software []*Software `gorm:"-" form:"-" json:"software"`
Count int `gorm:"-" form:"-" json:"count"`
}
//Software for academy software.
type Software struct {
ID int64 `gorm:"column:id" form:"id" json:"id"`
SkID int64 `gorm:"column:skid" form:"skid" json:"skid"`
State int `gorm:"column:state" form:"state" json:"state"`
Name string `gorm:"column:name" form:"name" json:"name"`
Desc string `gorm:"column:desc" form:"desc" json:"desc"`
CTime string `gorm:"column:ctime" form:"ctime" json:"-"`
MTime string `gorm:"column:mtime" form:"mtime" json:"-"`
Count int `gorm:"-" form:"-" json:"count"`
}
//ArcSkill for academy archive relation to occupation & skill & software.
type ArcSkill struct {
ID int64 `gorm:"column:id" form:"id" json:"id"`
AID int64 `gorm:"column:aid" form:"aid" json:"aid"`
PID int64 `gorm:"column:pid" form:"pid" json:"pid"`
SkID int64 `gorm:"column:skid" form:"skid" json:"skid"`
SID int64 `gorm:"column:sid" form:"sid" json:"sid"`
Type int `gorm:"column:type" form:"type" json:"type"`
State int `gorm:"column:state" form:"state" json:"state"`
CTime string `gorm:"column:ctime" form:"ctime" json:"-"`
MTime string `gorm:"column:mtime" form:"mtime" json:"-"`
Title string `gorm:"-" form:"title" json:"title"`
Pic string `gorm:"-" form:"pic" json:"pic"`
Pn int `gorm:"-" form:"pn" json:"-"`
Ps int `gorm:"-" form:"ps" json:"-"`
}
//ArcSkills for archive skill list
type ArcSkills struct {
Pager *Pager `json:"pager"`
Items []*ArcSkill `json:"items"`
}
//TagLink for academy h5 tag relation to web tags.
type TagLink struct {
ID int64 `gorm:"column:id" form:"id" json:"id"`
TID int64 `gorm:"column:tid" form:"tid" json:"tid"`
LinkID int64 `gorm:"column:link_id" form:"link_id" json:"link_id"`
CTime string `gorm:"column:ctime" form:"ctime" json:"-"`
MTime string `gorm:"column:mtime" form:"mtime" json:"-"`
}
//TableName get table name
func (sk *SearchKeywords) TableName() string {
return "academy_search_keywords"
}
//SearchKeywords for academy h5 search keywords.
type SearchKeywords struct {
ID int64 `gorm:"column:id" form:"id" json:"id"`
Rank int64 `gorm:"column:rank" form:"rank" json:"rank"`
ParentID int64 `gorm:"column:parent_id" form:"parent_id" json:"parent_id"`
State int8 `gorm:"column:state" form:"state" json:"state"`
Name string `gorm:"column:name" form:"name" json:"name"`
Comment string `gorm:"column:comment" form:"comment" json:"comment"`
CTime string `gorm:"column:ctime" form:"ctime" json:"-"`
MTime string `gorm:"column:mtime" form:"mtime" json:"-"`
Count int `gorm:"-" form:"-" json:"count,omitempty"`
Children []*SearchKeywords `json:"children,omitempty"`
}

View File

@@ -0,0 +1,71 @@
package academy
const (
_ = iota
//Course 教程级别
Course
//Operation 运营标签
Operation
//Classify 分类标签
Classify
//ArticleClass 专栏分类
ArticleClass
//H5 手机端分类标签
H5
//Recommend 理由标签
Recommend
)
const (
//StateUnBlock 解冻状态
StateUnBlock = 0
//StateBlock 冻结状态
StateBlock = -1
)
//TableName get table name
func (t *Tag) TableName() string {
return "academy_tag"
}
//Tag for academy tag.
type Tag struct {
ID int64 `gorm:"column:id"`
ParentID int64 `gorm:"column:parent_id"`
Type int8 `gorm:"column:type"`
State int8 `gorm:"column:state"`
Business int8 `gorm:"column:business"`
Name string `gorm:"column:name"`
Desc string `gorm:"column:desc"`
CTime string `gorm:"column:ctime"`
MTime string `gorm:"column:mtime"`
Rank int64 `gorm:"column:rank"`
Children []*Tag `json:"children,omitempty"`
}
//TagMeta for academy tag reuslt.
type TagMeta struct {
ID int64 `json:"id"`
ParentID int64 `json:"parent_id"`
Type int8 `json:"type"`
State int8 `json:"state"`
Business int8 `json:"business"`
Count int `json:"count"`
Name string `json:"name"`
Desc string `json:"desc"`
Children []*TagMeta `json:"children,omitempty"`
Rank int64 `gorm:"column:rank"`
LinkID []int64 `json:"link_id,omitempty"`
}
//TagClass for tag type name map.
func TagClass() map[int]string {
return map[int]string{
Course: "教程级别",
Operation: "运营标签",
Classify: "分类标签",
ArticleClass: "专栏分类",
H5: "手机端分类标签",
Recommend: "推荐理由",
}
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["app.go"],
importpath = "go-common/app/admin/main/creative/model/app",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
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,74 @@
package app
var (
// PlatformMap map
PlatformMap = map[int8]string{
0: "全平台",
1: "Android",
2: "iOS",
3: "iPad",
}
)
//Portal for app.
type Portal struct {
ID int64 `form:"id" json:"id" gorm:"primary_key"`
Build int64 `form:"build" json:"build"`
BuildExp string `form:"buildexp" json:"buildexp" gorm:"column:buildexp"`
Platform int8 `form:"platform" json:"platform" gorm:"column:platform"`
Compare int8 `form:"compare" json:"compare"`
State int8 `form:"state" json:"state" gorm:"column:state"`
Pos int16 `form:"pos" json:"pos"`
Mark int8 `form:"mark" json:"mark"`
More int8 `form:"more" json:"more"`
Type int8 `form:"type" json:"type" gorm:"column:type"`
Title string `form:"title" json:"title"`
Icon string `form:"icon" json:"icon"`
URL string `form:"url" json:"url"`
CTime string `form:"ctime" json:"ctime" gorm:"column:ctime"`
MTime string `form:"mtime" json:"mtime" gorm:"column:mtime"`
PTime string `form:"ptime" json:"ptime" gorm:"column:ptime"`
SubTitle string `form:"subtitle" json:"subtitle" gorm:"column:subtitle"`
WhiteExp string `form:"whiteexp" json:"whiteexp" gorm:"column:whiteexp"`
}
// PortalPager def.
type PortalPager struct {
Total int64 `json:"total"`
Pn int `json:"pn"`
Ps int `json:"ps"`
Items []*Item `json:"items"`
}
// WhiteExp str
type WhiteExp struct {
TP int8 `json:"type"`
Value int `json:"value"`
}
//Item for portal list.
type Item struct {
ID int64 `json:"id"`
Build int64 `json:"build"`
BuildExp string `json:"buildexp"`
Platform int8 `json:"platform"`
Compare int8 `json:"compare"`
State int8 `json:"state"`
Pos int16 `json:"pos"`
Mark int8 `json:"mark"`
More int8 `json:"more"`
Type int8 `json:"type"`
Title string `json:"title"`
Icon string `json:"icon"`
URL string `json:"url"`
CTime int64 `json:"ctime"`
MTime int64 `json:"mtime"`
PTime int64 `json:"ptime"`
SubTitle string `json:"subtitle"`
WhiteExps []*WhiteExp `json:"whiteexp"`
}
// TableName fn
func (Portal) TableName() string {
return "app_portal"
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["bfs.go"],
importpath = "go-common/app/admin/main/creative/model/bfs",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
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,10 @@
package bfs
//FileInfo : the uploaded file information
type FileInfo struct {
Name string `json:"name"`
Size int64 `json:"size"`
Type string `json:"type"`
Md5 string `json:"md5"`
URL string `json:"url"`
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["logcli.go"],
importpath = "go-common/app/admin/main/creative/model/logcli",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
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,23 @@
package logcli
// .
const (
//LogClientArchiveMusic 创作中心素材库(bgm+素材库) 审核日志 6
LogClientArchiveMusic = int(6)
//LogClientArchiveMusicTypeMusic 1.bgm相关
LogClientArchiveMusicTypeMusic = int(1)
//LogClientArchiveMusicTypeMaterial bgm 素材
LogClientArchiveMusicTypeMaterial = int(2)
//LogClientArchiveMusicTypeCategory bgm 分类
LogClientArchiveMusicTypeCategory = int(3)
//LogClientArchiveMusicTypeMaterialRelation bgm 关联素材
LogClientArchiveMusicTypeMaterialRelation = int(4)
//LogClientArchiveMusicTypeCategoryRelation bgm 关联分类
LogClientArchiveMusicTypeCategoryRelation = int(5)
//LogClientArchiveMaterialType 素材库 除bgm外
LogClientArchiveMaterialType = int(7)
//LogClientArchiveMaterialTypeCategory 素材库分类 除bgm外
LogClientArchiveMaterialTypeCategory = int(6)
)

View File

@@ -0,0 +1,32 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"category.go",
"material.go",
],
importpath = "go-common/app/admin/main/creative/model/material",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["//library/time: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,68 @@
package material
import (
xtime "go-common/library/time"
)
// consts for workflow event
// Category model is the model for material
type Category struct {
ID int64 `json:"id" gorm:"column:id"`
Name string `json:"name" gorm:"column:name"`
State int8 `json:"state" gorm:"column:state"`
Type int64 `json:"type" gorm:"column:type"`
Rank int64 `json:"rank" gorm:"column:rank"`
New int64 `json:"new" gorm:"column:new"`
CTime xtime.Time `json:"ctime" gorm:"column:ctime"`
MTime xtime.Time `json:"mtime" gorm:"column:mtime"`
}
// TableName is used to identify table name in gorm
func (Category) TableName() string {
return "material_category"
}
// CategoryPager def.
type CategoryPager struct {
Items []*Category `json:"items"`
Pager *Pager `json:"pager"`
}
// WithCategory model is the model for material
type WithCategory struct {
ID int64 `json:"id" gorm:"column:id"`
CategoryID int64 `json:"category_id" gorm:"column:category_id"`
MaterialID int64 `json:"material_id" gorm:"column:material_id"`
State int8 `json:"state" gorm:"column:state"`
Index int64 `json:"index" gorm:"column:index"`
}
// TableName is used to identify table name in gorm
func (WithCategory) TableName() string {
return "material_with_category"
}
// WithCategoryPager def.
type WithCategoryPager struct {
TotalCount int64 `json:"total_count"`
Pn int `json:"pn"`
Ps int `json:"ps"`
Items []*WithCategory `json:"items"`
}
// CategoryParam is used to parse user request
type CategoryParam struct {
ID int64 `form:"id" gorm:"column:id"`
Type int64 `form:"type" gorm:"column:type" validate:"required"`
UID int64 `form:"uid" gorm:"column:uid"`
Name string `form:"name" gorm:"column:name" validate:"required"`
Rank int64 `form:"rank" gorm:"column:rank" validate:"required"`
New int8 `form:"new" gorm:"column:new"`
State int8 `form:"state" gorm:"column:state"`
}
// TableName is used to identify table name in gorm
func (CategoryParam) TableName() string {
return "material_category"
}

View File

@@ -0,0 +1,126 @@
package material
import (
xtime "go-common/library/time"
)
// consts .
const (
StateDelete = 2
StateOff = 1
StateOn = 0
//注意 因为历史原因 bgm 和其他素材没能在bilibili_creative.material一个表集中管理 针对素材类型 为bgm保留了type=3
//字幕库
TypeSubTitle = int8(0)
//字体库
TypeFont = int8(1)
//滤镜库
TypeFilter = int8(2)
//bgm库
TypeBGM = int8(3)
//热词
TypeHotWord = int8(4)
//拍摄贴纸 ext 新增贴纸类型 默认为0 普通贴纸存储格式是bitmask参考属性位 0普通 1人脸 2手势 3画面效果 (不是自然数顺序 服务端不校验)
TypeSticks = int8(5)
//贴纸Icon
TypeSticksIcon = int8(6)
//投稿贴纸
TypeCreativeSticks = int8(7)
//投稿转场
TypeCreativeTransition = int8(8)
//合拍库
TypeCooperate = int8(9)
//主题库
TypeTheme = int8(10)
)
var (
_materialtype = map[int8]string{
TypeSubTitle: "字幕库",
TypeFont: "字体库",
TypeFilter: "滤镜库",
TypeBGM: "bgm库",
TypeHotWord: "热词",
TypeSticks: "贴纸",
TypeSticksIcon: "贴纸Icon",
TypeCreativeSticks: "投稿贴纸",
TypeCreativeTransition: "投稿转场",
TypeCooperate: "合拍库",
TypeTheme: "主题库",
}
)
// InMaterialType in correct materialtype.
func InMaterialType(cate int8) (ok bool) {
_, ok = _materialtype[cate]
return
}
// Material model is the model for Material
type Material struct {
ID int64 `json:"id" form:"id" gorm:"column:id"`
UID int64 `json:"uid" form:"id" gorm:"column:uid"`
Name string `json:"name" form:"name" gorm:"column:name"`
Extra string `json:"extra" form:"extra" gorm:"column:extra"`
Rank int `json:"rank" form:"rank" gorm:"column:rank"`
Type int8 `json:"type" form:"type" gorm:"column:type"`
Platform int `json:"platform" form:"platform" gorm:"column:platform"`
Build string `json:"build" form:"build" gorm:"column:build"`
State int8 `json:"state" form:"state" gorm:"column:state"`
CategoryID int64 `json:"category_id" gorm:"-"`
CategoryIndex int64 `json:"category_index" gorm:"-"`
CategoryName string `json:"category_name" gorm:"-"`
CTime xtime.Time `json:"ctime" form:"ctime" gorm:"column:ctime"`
MTime xtime.Time `json:"mtime" form:"mtime" gorm:"column:mtime"`
}
// TableName is used to identify table name in gorm
func (Material) TableName() string {
return "material"
}
// Result def.
type Result struct {
Items []*Material `json:"items"`
Pager *Pager `json:"pager"`
}
// Pager Pager def.
type Pager struct {
Num int `json:"num"`
Size int `json:"size"`
Total int64 `json:"total"`
}
// Param is used to parse user request
type Param struct {
ID int64 `form:"id" gorm:"column:id" json:"id"`
Name string `form:"name" gorm:"column:name" json:"name"`
Extra string `form:"extra" gorm:"column:extra" json:"extra"`
Rank int `form:"rank" gorm:"column:rank" json:"rank"`
Type int8 `form:"type" gorm:"column:type" json:"type"`
Cover string `form:"cover" json:"cover"`
Platform int `form:"platform" json:"platform"`
Build string `form:"build" json:"build"`
DownloadURL string `form:"download_url" json:"download_url"`
ExtraURL string `form:"extra_url" json:"extra_url"`
ExtraField string `form:"extra_field" json:"extra_field"`
Max int8 `form:"max" json:"max"`
CategoryID int64 `form:"category_id" json:"category_id"`
CategoryIndex int64 `form:"category_index" json:"category_index"`
SubType int8 `form:"sub_type" json:"sub_type"`
Style int8 `form:"style" json:"style"`
Tip string `form:"tip" json:"tip"`
WhilteList int8 `form:"white_list" json:"white_list"`
MaterialAID int64 `form:"material_aid" json:"material_aid"`
MaterialCID int64 `form:"material_cid" json:"material_cid"`
DemoAID int64 `form:"demo_aid" json:"demo_aid"`
DemoCID int64 `form:"demo_cid" json:"demo_cid"`
MissionID int64 `form:"mission_id" json:"mission_id"`
FilterType int8 `form:"filter_type" json:"filter_type"`
}
// TableName is used to identify table name in gorm
func (Param) TableName() string {
return "material"
}

View File

@@ -0,0 +1,33 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"category.go",
"material.go",
"music.go",
],
importpath = "go-common/app/admin/main/creative/model/music",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["//library/time: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,109 @@
package music
import (
xtime "go-common/library/time"
)
// consts for workflow event
// Category model is the model for music
type Category struct {
ID int64 `json:"id" gorm:"column:id"`
Pid int64 `json:"pid" gorm:"column:pid"`
Name string `json:"name" gorm:"column:name"`
Index int64 `json:"index" gorm:"column:index"`
CameraIndex int64 `json:"camera_index" gorm:"column:camera_index"`
State int8 `json:"state" gorm:"column:state"`
CTime xtime.Time `json:"ctime" gorm:"column:ctime"`
MTime xtime.Time `json:"mtime" gorm:"column:mtime"`
}
// TableName is used to identify table name in gorm
func (Category) TableName() string {
return "music_category"
}
// CategoryPager def.
type CategoryPager struct {
Items []*Category `json:"items"`
Pager *Pager `json:"pager"`
}
// Pager Pager def.
type Pager struct {
Num int `json:"num"`
Size int `json:"size"`
Total int64 `json:"total"`
}
// SidNotify model is the model for music
type SidNotify struct {
Sid int64 `json:"sid"`
MidFirst bool `json:"mid_first"`
SidFirst bool `json:"sid_first"`
}
// WithCategory model is the model for music
type WithCategory struct {
ID int64 `json:"id" gorm:"column:id"`
Sid int64 `json:"sid" gorm:"column:sid"`
Tid int64 `json:"tid" gorm:"column:tid"`
State int8 `json:"state" gorm:"column:state"`
Index int64 `json:"index" gorm:"column:index"`
CTime xtime.Time `json:"ctime" gorm:"column:ctime"`
MTime xtime.Time `json:"mtime" gorm:"column:mtime"`
}
// TableName is used to identify table name in gorm
func (WithCategory) TableName() string {
return "music_with_category"
}
// WithCategoryPager def.
type WithCategoryPager struct {
TotalCount int64 `json:"total_count"`
Pn int `json:"pn"`
Ps int `json:"ps"`
Items []*WithCategory `json:"items"`
}
//CategoryList .
type CategoryList struct {
ID int64 `json:"id" gorm:"column:id"`
Sid int64 `json:"sid" gorm:"column:sid"`
Name string `json:"name" gorm:"column:name"`
FrontName string `json:"frontname" gorm:"column:frontname"`
Musicians string `json:"musicians" gorm:"column:musicians"`
Cooperate int8 `json:"cooperate" gorm:"column:cooperate"`
Mid int64 `json:"mid" gorm:"column:mid"`
Tid int64 `json:"tid" gorm:"-"`
Pid int64 `json:"pid" gorm:"-"`
Cover string `json:"cover" gorm:"column:cover"`
MaterialName string `json:"material_name" gorm:"-"`
CategoryName string `json:"category_name" gorm:"-"`
MusicState string `json:"music_state" gorm:"-"`
Stat string `json:"stat" gorm:"column:stat"`
Categorys string `json:"categorys" gorm:"column:categorys"`
Playurl string `json:"playurl" gorm:"column:playurl"`
State int8 `json:"state" gorm:"column:state"`
Index int `json:"index" gorm:"column:index"`
Duration int32 `json:"duration" gorm:"column:duration"`
Filesize int32 `json:"filesize" gorm:"column:filesize"`
PubTime xtime.Time `json:"pubtime" gorm:"column:pubtime"`
SyncTime xtime.Time `json:"synctime" gorm:"column:synctime"`
Tags string `json:"tags" gorm:"-"`
Timeline string `json:"timeline" gorm:"-"`
CTime xtime.Time `json:"ctime" gorm:"column:ctime"`
MTime xtime.Time `json:"mtime" gorm:"column:mtime"`
}
// TableName is used to identify table name in gorm
func (CategoryList) TableName() string {
return "music_with_category"
}
// CategoryListPager def.
type CategoryListPager struct {
Items []*CategoryList `json:"items"`
Pager *Pager `json:"pager"`
}

View File

@@ -0,0 +1,68 @@
package music
import (
xtime "go-common/library/time"
)
// consts for workflow event
// Material model is the model for music
type Material struct {
ID int64 `json:"id" gorm:"column:id"`
Pid int64 `json:"pid" gorm:"column:pid"`
Name string `json:"name" gorm:"column:name"`
Index int64 `json:"index" gorm:"column:index"`
State int8 `json:"state" gorm:"column:state"`
CTime xtime.Time `json:"ctime" gorm:"column:ctime"`
MTime xtime.Time `json:"mtime" gorm:"column:mtime"`
}
// TableName is used to identify table name in gorm
func (Material) TableName() string {
return "music_material"
}
// MaterialPager def.
type MaterialPager struct {
Items []*Material `json:"items"`
Pager *Pager `json:"pager"`
}
// MaterialMixParent model is the model for music
type MaterialMixParent struct {
Material
PName string `json:"p_name" gorm:"column:p_name"`
}
// TableName is used to identify table name in gorm
func (MaterialMixParent) TableName() string {
return "music_material"
}
// MaterialMixParentPager def.
type MaterialMixParentPager struct {
Items []*MaterialMixParent `json:"items"`
Pager *Pager `json:"pager"`
}
// WithMaterial model is the model for music
type WithMaterial struct {
ID int64 `json:"id" gorm:"column:id"`
Sid int64 `json:"sid" gorm:"column:sid"`
Tid int64 `json:"tid" gorm:"column:tid"`
State int8 `json:"state" gorm:"column:state"`
Index int64 `json:"index" gorm:"column:index"`
CTime xtime.Time `json:"ctime" gorm:"column:ctime"`
MTime xtime.Time `json:"mtime" gorm:"column:mtime"`
}
// TableName is used to identify table name in gorm
func (WithMaterial) TableName() string {
return "music_with_material"
}
// WithMaterialPager def.
type WithMaterialPager struct {
Pager *Pager `json:"pager"`
Items []*WithMaterial `json:"items"`
}

View File

@@ -0,0 +1,185 @@
package music
import (
xtime "go-common/library/time"
)
// consts for workflow event
const (
MusicDelete = -100
MusicOpen = 0
)
// Music model is the model for music
type Music struct {
ID int64 `json:"id" gorm:"column:id"`
Sid int64 `json:"sid" gorm:"column:sid"`
Name string `json:"name" gorm:"column:name"`
FrontName string `json:"frontname" gorm:"column:frontname"`
Musicians string `json:"musicians" gorm:"column:musicians"`
Cooperate int8 `json:"cooperate" gorm:"column:cooperate"`
Mid int64 `json:"mid" gorm:"column:mid"`
Tid int64 `json:"tid" gorm:"-"`
Tags string `json:"tags" gorm:"tags"`
Timeline string `json:"timeline" gorm:"timeline"`
Rid int64 `json:"rid" gorm:"-"`
Pid int64 `json:"pid" gorm:"-"`
Cover string `json:"cover" gorm:"column:cover"`
MaterialName string `json:"material_name" gorm:"-"`
CategoryName string `json:"category_name" gorm:"-"`
Stat string `json:"stat" gorm:"column:stat"`
Categorys string `json:"categorys" gorm:"column:categorys"`
Playurl string `json:"playurl" gorm:"column:playurl"`
State int8 `json:"state" gorm:"column:state"`
Duration int32 `json:"duration" gorm:"column:duration"`
Filesize int32 `json:"filesize" gorm:"column:filesize"`
PubTime xtime.Time `json:"pubtime" gorm:"column:pubtime"`
SyncTime xtime.Time `json:"synctime" gorm:"column:synctime"`
CTime xtime.Time `json:"ctime" gorm:"column:ctime"`
MTime xtime.Time `json:"mtime" gorm:"column:mtime"`
}
// TableName is used to identify table name in gorm
func (Music) TableName() string {
return "music"
}
// ResultPager def.
type ResultPager struct {
Items []*Music `json:"items"`
Pager *Pager `json:"pager"`
}
// Param is used to parse user request
type Param struct {
ID int64 `form:"id" gorm:"column:id"`
Sid int64 `form:"sid" validate:"required"`
Name string `form:"name" validate:"required"`
Musicians string `form:"musicians"`
Mid int64 `form:"mid" validate:"required"`
Cover string `form:"cover" validate:"required"`
Stat string `form:"stat" `
Categorys string `form:"categorys" `
Playurl string `form:"playurl" `
State int8 `form:"state"`
Duration int32 `form:"duration" `
Filesize int32 `form:"filesize" `
UID int64 `form:"uid" `
PubTime xtime.Time `form:"pubtime"`
SyncTime xtime.Time `form:"synctime"`
Tags string `form:"tags"`
Timeline string `form:"timeline"`
}
// TableName is used to identify table name in gorm
func (Param) TableName() string {
return "music"
}
// CategoryParam is used to parse user request
type CategoryParam struct {
ID int64 `form:"id" gorm:"column:id"`
Pid int64 `form:"pid" gorm:"column:pid"`
UID int64 `form:"uid" gorm:"column:uid"`
Name string `form:"name" gorm:"column:name" validate:"required"`
Index int64 `form:"index" gorm:"column:index" validate:"required"`
CameraIndex int64 `form:"camera_index" gorm:"column:camera_index" validate:"required"`
State int8 `form:"state" gorm:"column:state"`
}
// TableName is used to identify table name in gorm
func (CategoryParam) TableName() string {
return "music_category"
}
// MaterialParam is used to parse user request
type MaterialParam struct {
ID int64 `form:"id" gorm:"column:id"`
Pid int64 `form:"pid" gorm:"column:pid"`
UID int64 `form:"uid" gorm:"column:uid"`
Name string `form:"name" gorm:"column:name" validate:"required"`
Index int64 `form:"index" gorm:"column:index"`
State int8 `form:"state" gorm:"column:state"`
}
// TableName is used to identify table name in gorm
func (MaterialParam) TableName() string {
return "music_material"
}
// WithMaterialParam is used to parse user request
type WithMaterialParam struct {
ID int64 `form:"id" gorm:"column:id"`
UID int64 `form:"uid" gorm:"column:uid"`
Sid int64 `form:"sid" gorm:"column:sid" validate:"required,min=1"`
Tid int64 `form:"tid" gorm:"column:tid" validate:"required,min=1"`
Index int64 `form:"index" gorm:"column:index"`
State int8 `form:"state" gorm:"column:state"`
}
// IndexParam is used to parse user request
type IndexParam struct {
ID int64 `form:"id" validate:"required"`
Index int64 `form:"index" validate:"required"`
SwitchID int64 `form:"switch_id" validate:"required"`
SwitchIndex int64 `form:"switch_index" validate:"required"`
UID int64 `form:"uid"`
}
// TableName is used to identify table name in gorm
func (WithMaterialParam) TableName() string {
return "music_with_material"
}
// BatchMusicWithMaterialParam is used to parse user request
type BatchMusicWithMaterialParam struct {
UID int64 `form:"uid" gorm:"column:uid"`
SidList string `form:"sid_list" validate:"required"`
Tid int64 `form:"tid" gorm:"column:tid" validate:"required,min=1"`
Index int64 `form:"index" gorm:"column:index"`
State int8 `form:"state" gorm:"column:state"`
}
// TableName is used to identify table name in gorm
func (BatchMusicWithMaterialParam) TableName() string {
return "music_with_material"
}
// WithCategoryParam is used to parse user request
type WithCategoryParam struct {
ID int64 `form:"id" gorm:"column:id"`
UID int64 `form:"uid" gorm:"column:uid"`
Sid int64 `form:"sid" gorm:"column:sid" validate:"required,min=1"`
Tid int64 `form:"tid" gorm:"column:tid" validate:"required,min=1"`
Index int64 `form:"index" gorm:"column:index" default:"1"`
State int8 `form:"state" gorm:"column:state"`
}
// BatchMusicWithCategoryParam is used to parse user request
type BatchMusicWithCategoryParam struct {
UID int64 `form:"uid" gorm:"column:uid"`
SidList string `form:"sid_list" validate:"required"`
SendList string `form:"send_list"`
Tid int64 `form:"tid" gorm:"column:tid" validate:"required,min=1"`
Index int64 `form:"index" gorm:"column:index" default:"1"`
State int8 `form:"state" gorm:"column:state"`
}
// TableName is used to identify table name in gorm
func (BatchMusicWithCategoryParam) TableName() string {
return "music_with_category"
}
// TableName is used to identify table name in gorm
func (WithCategoryParam) TableName() string {
return "music_with_category"
}
// LogParam is used to parse user request
type LogParam struct {
ID int64 `json:"id"`
UID int64 `json:"uid"`
UName string `json:"uname"`
Action string `json:"action"`
Name string `json:"name"`
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["operation.go"],
importpath = "go-common/app/admin/main/creative/model/operation",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
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,58 @@
package operation
// Operation tool.
type Operation struct {
ID int64 `form:"id" json:"id"`
Type string `form:"type" json:"type"`
Ads int8 `form:"ads" json:"ads"`
Platform int8 `form:"platform" json:"platform"`
Rank int8 `form:"rank" json:"rank"`
Pic string `form:"pic" json:"pic"`
Link string `form:"link" json:"link"`
Content string `form:"content" json:"content"`
Username string `form:"username" json:"username"`
Remark string `form:"remark" json:"remark"`
Note string `form:"note" json:"note"`
AppPic string `form:"app_pic" json:"app_pic"`
Stime string `form:"stime" json:"stime" gorm:"column:stime"`
Etime string `form:"etime" json:"etime" gorm:"column:etime"`
Ctime string `form:"ctime" json:"ctime" gorm:"column:ctime"`
Mtime string `form:"mtime" json:"mtime" gorm:"column:mtime"`
Dtime string `form:"dtime" json:"dtime" gorm:"column:dtime"`
}
// TableName fn
func (Operation) TableName() string {
return "operations"
}
// Banner for app index.
type Banner struct {
Ty string `json:"-"`
Rank string `json:"rank"`
Pic string `json:"pic"`
Link string `json:"link"`
Content string `json:"content"`
}
// ViewOperation tool.
type ViewOperation struct {
ID int64 `json:"id"`
Type string `json:"type"`
Ads int8 `json:"ads"`
Platform int8 `json:"platform"`
Rank int8 `json:"rank"`
Pic string `json:"pic"`
Link string `json:"link"`
Content string `json:"content"`
Username string `json:"username"`
Remark string `json:"remark"`
Note string `json:"note"`
AppPic string `json:"app_pic"`
Stime string `json:"stime"`
Etime string `json:"etime"`
Ctime string `json:"ctime"`
Mtime string `json:"mtime"`
Dtime string `json:"dtime"`
Status string `json:"status"`
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["task.go"],
importpath = "go-common/app/admin/main/creative/model/task",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
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,232 @@
package task
const (
//StateDel for normal state
StateDel = int8(-1)
//StateNormal for normal state
StateNormal = int8(0)
//StateHide for hide state
StateHide = int8(1)
//TaskManagement 任务管理
TaskManagement = uint8(1)
//AchievementManagement 成就管理
AchievementManagement = uint8(2)
//LogClientTask 日志服务类型
LogClientTask = 301
)
const (
_ uint8 = iota
//TaskTypeNewcomer 新手任务
TaskTypeNewcomer
//TaskTypeAdvanced 进阶任务
TaskTypeAdvanced
//TaskTypeMonthly 月常任务
TaskTypeMonthly
)
var (
//TaskRootNameMap 管理分类, 1-任务管理、2-成就管理
TaskRootNameMap = map[uint8]string{
TaskManagement: "任务管理",
AchievementManagement: "成就管理",
}
//TaskGroupNameMap 任务分类, 1-新手任务、2-进阶任务、3-月常任务; 4-互动成就、5-投稿成就、6-行为成就、7-高级成就
TaskGroupNameMap = map[uint8]string{
TaskTypeNewcomer: "新手任务",
TaskTypeAdvanced: "进阶任务",
TaskTypeMonthly: "月常任务",
4: "互动成就",
5: "投稿成就",
6: "行为成就",
7: "高级成就",
}
)
//CheckRootType check task root type.
func CheckRootType(ty uint8) bool {
if ty == TaskTypeNewcomer || ty == TaskTypeAdvanced || ty == TaskTypeMonthly {
return true
}
return false
}
var (
//TargetMap for target show
TargetMap = map[int8]string{
1: "开放浏览的稿件",
2: "分享自己视频的次数",
3: "创作学院的观看记录",
4: "所有avid的获得评论数",
5: "所有avid获得分享数",
6: "所有avid的获得收藏数",
7: "所有avid的获得硬币数",
8: "所有avid获得点赞数",
9: "所有avid的获得弹幕数",
10: "粉丝数",
11: "水印开关为打开状态",
12: "关注列表含有“哔哩哔哩创作中心”",
13: "用手机投稿上传视频",
14: "开放浏览的稿件",
15: "任意avid的获得点击量",
16: "任意avid的评论",
17: "任意avid的获得分享数",
18: "任意avid的获得收藏数",
19: "任意avid的获得硬币数",
20: "任意avid的获得点赞数",
21: "任意avid的获得弹幕数",
22: "激励计划状态为已开通",
23: "粉丝勋章为开启状态",
}
)
//TableName get table name
func (tg *TaskGroup) TableName() string {
return "newcomers_task_group"
}
//TableName get table name
func (tgr *TaskGroupReward) TableName() string {
return "newcomers_grouptask_reward"
}
//TaskGroup for task group.
type TaskGroup struct {
ID int64 `gorm:"column:id" form:"id" json:"id"`
Rank int64 `gorm:"column:rank" form:"rank" json:"rank"`
State int8 `gorm:"column:state" form:"state" json:"state"` //-1-删除, 0-正常, 1-隐藏
RootType uint8 `gorm:"column:root_type" form:"root_type" json:"root_type"`
Type int8 `gorm:"column:type" form:"type" json:"type"`
CTime string `gorm:"column:ctime" form:"ctime" json:"-"`
MTime string `gorm:"column:mtime" form:"mtime" json:"-"`
RewardIDs string `gorm:"-" form:"reward_ids" json:"-"`
Comment string `gorm:"-" form:"comment" json:"comment"`
Tasks []*Task `json:"tasks"`
Reward []*RewardResult `json:"reward"`
}
//TaskGroupReward for task group relation reward.
type TaskGroupReward struct {
ID int64 `gorm:"column:id" form:"id" json:"id"`
TaskGroupID int64 `gorm:"column:task_group_id" form:"task_group_id" json:"task_group_id"`
RewardID int64 `gorm:"column:reward_id" form:"reward_id" json:"reward_id"`
State int8 `gorm:"column:state" form:"state" json:"state"`
CTime string `gorm:"column:ctime" form:"ctime" json:"-"`
MTime string `gorm:"column:mtime" form:"mtime" json:"-"`
}
//OrderTask for task or task group order.
type OrderTask struct {
ID int64 `form:"id" validate:"required"`
Rank int64 `form:"rank" validate:"required"`
SwitchID int64 `form:"switch_id" validate:"required"`
SwitchRank int64 `form:"switch_rank" validate:"required"`
}
//RewardResult for task group relation reward result.
type RewardResult struct {
RewardID int64 `json:"reward_id"`
RewardName string `json:"reward_name"`
}
//TableName get table name
func (t *Task) TableName() string {
return "newcomers_task"
}
//TableName get table name
func (tr *TaskReward) TableName() string {
return "newcomers_task_reward"
}
// Task for def task struct.
type Task struct {
ID int64 `gorm:"column:id" form:"id" json:"id"`
GroupID int64 `gorm:"column:group_id" form:"group_id" json:"group_id"`
Title string `gorm:"column:title" form:"title" json:"title"`
Desc string `gorm:"column:desc" form:"desc" json:"desc"`
Comment string `gorm:"column:comment" form:"comment" json:"comment"`
Type int8 `gorm:"column:type" form:"type" json:"type"`
State int8 `gorm:"column:state" form:"state" json:"state"`
TargetType int8 `gorm:"column:target_type" form:"target_type" json:"target_type"`
TargetValue int32 `gorm:"column:target_value" form:"target_value" json:"target_value"`
Rank int64 `gorm:"column:rank" form:"rank" json:"rank"`
Extra string `gorm:"column:extra" form:"extra" json:"extra"` //跳转链接等附加信息,json格式
FanRange string `gorm:"column:fan_range" form:"fan_range" json:"fan_range"` //粉丝范围, json格式
UpTime string `gorm:"column:up_time" form:"up_time" json:"up_time"` //月常活动任务-上线时间
DownTime string `gorm:"column:down_time" form:"down_time" json:"down_time"` //月常活动任务-下线时间
CTime string `gorm:"column:ctime" form:"ctime" json:"-"`
MTime string `gorm:"column:mtime" form:"mtime" json:"-"`
RewardIDs string `gorm:"-" form:"reward_ids" json:"-"`
Reward []*RewardResult `json:"reward"`
}
//TaskReward for task relation reward.
type TaskReward struct {
ID int64 `gorm:"column:id" form:"id" json:"id"`
TaskID int64 `gorm:"column:task_id" form:"task_id" json:"task_id"`
RewardID int64 `gorm:"column:reward_id" form:"reward_id" json:"reward_id"`
State int8 `gorm:"column:state" form:"state" json:"state"`
Comment string `gorm:"column:comment" form:"comment" json:"comment"`
CTime string `gorm:"column:ctime" form:"ctime" json:"-"`
MTime string `gorm:"column:mtime" form:"mtime" json:"-"`
}
//TableName get table name
func (r *Reward) TableName() string {
return "newcomers_reward"
}
//Reward for task reward.
type Reward struct {
ID int64 `gorm:"column:id" form:"id" json:"id"`
ParentID int64 `gorm:"column:parent_id" form:"parent_id" json:"parent_id"`
Type int8 `gorm:"column:type" form:"type" json:"type"`
State int8 `gorm:"column:state" form:"state" json:"state"`
IsActive int8 `gorm:"column:is_active" form:"is_active" json:"is_active"`
Name string `gorm:"column:name" form:"name" json:"name"`
Logo string `gorm:"column:logo" form:"logo" json:"logo"`
Comment string `gorm:"column:comment" form:"comment" json:"comment"`
UnlockLogo string `gorm:"column:unlock_logo" form:"unlock_logo" json:"unlock_logo"` //奖励未解锁, logo url
NameExtra string `gorm:"column:name_extra" form:"name_extra" json:"name_extra"` //支持奖励名称展示,json格式
PrizeID string `gorm:"column:prize_id" form:"prize_id" json:"prize_id"` //业务方奖品id
PrizeUnit int8 `gorm:"column:prize_unit" form:"prize_unit" json:"prize_unit"` //奖品单位
Expire int16 `gorm:"column:expire" form:"expire" json:"expire"` //有效期 单位天
CTime string `gorm:"column:ctime" form:"ctime" json:"-"`
MTime string `gorm:"column:mtime" form:"mtime" json:"-"`
Children []*Reward `json:"children,omitempty"`
}
//TableName get table name
func (gf *GiftReward) TableName() string {
return "newcomers_gift_reward"
}
//GiftReward for task gift reward.
type GiftReward struct {
ID int64 `gorm:"column:id" form:"id" json:"id"`
RootType uint8 `gorm:"column:root_type" form:"root_type" json:"root_type"`
TaskType int64 `gorm:"column:task_type" form:"task_type" json:"task_type"`
RewardID int64 `gorm:"column:reward_id" form:"reward_id" json:"-"`
State int8 `gorm:"column:state" form:"state" json:"state"`
Comment string `gorm:"column:comment" form:"comment" json:"comment"`
CTime string `gorm:"column:ctime" form:"ctime" json:"-"`
MTime string `gorm:"column:mtime" form:"mtime" json:"-"`
RewardIDs string `gorm:"-" form:"reward_ids" json:"-"`
Reward []*RewardResult `json:"reward"`
}
// LogParam for manager.
type LogParam struct {
UID int64 `json:"uid"`
UName string `json:"uname"`
Action string `json:"action"`
OID int64 `json:"oid"`
OIDs string `json:"oids"`
OName string `json:"oname"`
OState int8 `json:"ostate"`
Content interface{} `json:"content"`
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["whitelist.go"],
importpath = "go-common/app/admin/main/creative/model/whitelist",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
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,21 @@
package whitelist
// Whitelist tool.
type Whitelist struct {
ID int64 `form:"id" json:"id"`
MID int64 `form:"mid" json:"mid" gorm:"column:mid"`
AdminMID int64 `form:"admin_mid" json:"admin_mid" gorm:"column:admin_mid"`
Comment string `form:"comment" json:"comment"`
State int8 `form:"state" json:"state"`
Type int8 `form:"type" json:"type"`
Fans int64 `form:"fans" json:"fans" gorm:"-"`
CurrentLevel int32 `form:"current_level" json:"current_level" gorm:"-"`
Name string `form:"name" json:"name" gorm:"-"`
Ctime string `form:"ctime" json:"ctime" gorm:"column:ctime"`
Mtime string `form:"mtime" json:"mtime" gorm:"column:mtime"`
}
// TableName fn
func (Whitelist) TableName() string {
return "whitelist"
}

View File

@@ -0,0 +1,76 @@
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",
"upbfs_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/creative/conf:go_default_library",
"//app/service/main/account/api:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"academy.go",
"log.go",
"material.go",
"music.go",
"service.go",
"task.go",
"upbfs.go",
"whitelist.go",
],
importpath = "go-common/app/admin/main/creative/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/creative/conf:go_default_library",
"//app/admin/main/creative/dao:go_default_library",
"//app/admin/main/creative/model/academy:go_default_library",
"//app/admin/main/creative/model/bfs:go_default_library",
"//app/admin/main/creative/model/logcli:go_default_library",
"//app/admin/main/creative/model/material:go_default_library",
"//app/admin/main/creative/model/music:go_default_library",
"//app/admin/main/creative/model/task:go_default_library",
"//app/admin/main/creative/model/whitelist:go_default_library",
"//app/interface/openplatform/article/model:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//library/conf/env:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/queue/databus/report:go_default_library",
"//library/xstr:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/golang.org/x/sync/errgroup: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,292 @@
package service
import (
"context"
"fmt"
"reflect"
"strings"
"time"
"go-common/app/admin/main/creative/model/academy"
"go-common/app/interface/openplatform/article/model"
"go-common/app/service/main/archive/api"
"go-common/library/log"
"github.com/jinzhu/gorm"
)
//Archive get one archive by rpc
func (s *Service) Archive(c context.Context, aid int64) (res *api.Arc, err error) {
if res, err = s.dao.Archive(c, aid); err != nil {
log.Error("s.dao.Archive aid(%d)|err(%+v)", aid, err)
}
return
}
//Archives get archives by rpc
func (s *Service) Archives(c context.Context, aids []int64) (res map[int64]*api.Arc, err error) {
if res, err = s.dao.Archives(c, aids); err != nil {
log.Error("s.dao.Archives aids(%d)|err(%+v)", aids, err)
}
return
}
//Articles get articles by rpc
func (s *Service) Articles(c context.Context, aids []int64) (res map[int64]*model.Meta, err error) {
if res, err = s.dao.ArticleMetas(c, aids); err != nil {
log.Error("s.dao.ArticleMetas aids(%+v)|err(%+v)", aids, err)
}
return
}
//ArchivesWithES for es search
func (s *Service) ArchivesWithES(c context.Context, aca *academy.EsParam) (res *academy.SearchResult, err error) {
if res, err = s.dao.ArchivesWithES(c, aca); err != nil {
log.Error("s.dao.ArchivesWithES aca(%+v)|err(%+v)", aca, err)
}
return
}
// Stats get archives stat.
func (s *Service) Stats(c context.Context, aids []int64, ip string) (res map[int64]*api.Stat, err error) {
if res, err = s.dao.Stats(c, aids, ip); err != nil {
log.Error("s.dao.Archives aids(%d)|ip(%s)|err(%+v)", aids, ip, err)
}
return
}
//SearchKeywords for list search keywords.
func (s *Service) SearchKeywords() (res []interface{}, err error) {
var sks []*academy.SearchKeywords
if err = s.DB.Where("state=0").Order("rank ASC").Find(&sks).Error; err != nil {
log.Error("SearchKeywords error(%v)", err)
return
}
if len(sks) == 0 {
return
}
res = s.trees(sks, "ID", "ParentID", "Children")
return
}
//trees for generate tree data set
// data - orm result set
// idFieldStr - primary key in table map to struct
// pidFieldStr - top parent id in table map to struct
// chFieldStr - struct child nodes
func (s *Service) trees(data interface{}, idFieldStr, pidFieldStr, chFieldStr string) (res []interface{}) {
if reflect.TypeOf(data).Kind() != reflect.Slice {
return
}
sli := reflect.ValueOf(data)
top := make(map[int64]interface{})
res = make([]interface{}, 0, sli.Len())
for i := 0; i < sli.Len(); i++ {
v := sli.Index(i).Interface()
if reflect.TypeOf(v).Kind() != reflect.Ptr {
continue
}
if reflect.ValueOf(v).IsNil() {
continue
}
getValue := reflect.ValueOf(v).Elem()
getType := reflect.TypeOf(v).Elem()
pid := getValue.FieldByName(pidFieldStr).Interface().(int64)
if _, ok := getType.FieldByName(pidFieldStr); ok && pid == 0 {
id := getValue.FieldByName(idFieldStr).Interface().(int64)
top[id] = v
res = append(res, v)
}
}
for i := 0; i < sli.Len(); i++ {
v := sli.Index(i).Interface()
if reflect.TypeOf(v).Kind() != reflect.Ptr {
continue
}
if reflect.ValueOf(v).IsNil() {
continue
}
pid := reflect.ValueOf(v).Elem().FieldByName(pidFieldStr).Interface().(int64)
if pid == 0 {
continue
}
if p, ok := top[pid]; ok {
ch := reflect.ValueOf(p).Elem().FieldByName(chFieldStr)
ch.Set(reflect.Append(ch, reflect.ValueOf(v)))
}
}
return
}
//SubSearchKeywords for add search keywords.
func (s *Service) SubSearchKeywords(vs []*academy.SearchKeywords) (err error) {
if len(vs) == 0 {
return
}
origins := []*academy.SearchKeywords{}
if err = s.DB.Model(&academy.SearchKeywords{}).Find(&origins).Error; err != nil {
log.Error("SubSearchKeywords Find error(%v)", err)
return
}
originMap := make(map[int64]*academy.SearchKeywords)
for _, v := range origins {
originMap[v.ID] = v
}
newParents := make([]*academy.SearchKeywords, 0)
oldParents := make([]*academy.SearchKeywords, 0)
children := make([]*academy.SearchKeywords, 0)
newChildren := make([]*academy.SearchKeywords, 0)
oldChildren := make([]*academy.SearchKeywords, 0)
now := time.Now().Format("2006-01-02 15:04:05")
for _, v := range vs {
if v == nil {
continue
}
v.Name = strings.TrimSpace(v.Name) //删除字符串前后空格
if vv, ok := originMap[v.ID]; ok && vv != nil { //父节点为老的
v.CTime = vv.CTime
v.MTime = now
oldParents = append(oldParents, v)
if len(v.Children) > 0 {
for _, vvv := range v.Children {
vvv.ParentID = vv.ID //追加父节点ID
vvv.CTime = now
vvv.MTime = now
children = append(children, vvv) //新老子节点同时存在
}
}
} else {
v.CTime = now
v.MTime = now
newParents = append(newParents, v)
}
}
oldParents = append(oldParents, newParents...)
tx := s.DB
if len(oldParents) > 0 {
if err = s.insertKeyWords(tx, oldParents); err != nil {
return
}
}
newParentsNames := make([]string, 0)
for _, v := range newParents {
newParentsNames = append(newParentsNames, v.Name)
}
var pidMap map[string]*academy.SearchKeywords
if len(newParentsNames) > 0 {
if pidMap, err = s.upRanks(tx, newParentsNames); err != nil {
return
}
}
newChildrenNames := make([]string, 0)
for _, v := range newParents { //父节点为新的
if v == nil {
continue
}
if vv, ok := pidMap[v.Name]; ok && vv != nil {
if len(v.Children) > 0 {
for _, vvv := range v.Children {
vvv.ParentID = vv.ID //追加父节点ID
vvv.CTime = now
vvv.MTime = now
newChildren = append(newChildren, vvv)
newChildrenNames = append(newChildrenNames, vvv.Name)
}
}
}
}
for _, v := range children {
if v == nil {
continue
}
if vv, ok := originMap[v.ID]; ok && vv != nil {
v.CTime = vv.CTime
v.MTime = now
oldChildren = append(oldChildren, v)
} else {
v.CTime = now
v.MTime = now
newChildren = append(newChildren, v)
newChildrenNames = append(newChildrenNames, v.Name)
}
}
oldChildren = append(oldChildren, newChildren...)
if len(oldChildren) > 0 {
if err = s.insertKeyWords(tx, oldChildren); err != nil {
return
}
}
if len(newChildrenNames) > 0 {
if _, err = s.upRanks(tx, newChildrenNames); err != nil {
return
}
}
return
}
func (s *Service) insertKeyWords(tx *gorm.DB, vs []*academy.SearchKeywords) (err error) {
if len(vs) == 0 {
return
}
valSearks := make([]string, 0, len(vs))
valSearksArgs := make([]interface{}, 0)
for _, v := range vs {
valSearks = append(valSearks, "(?, ?, ?, ?, ?, ?, ?, ?)")
valSearksArgs = append(valSearksArgs, v.ID, v.Rank, v.ParentID, v.State, v.Name, v.Comment, v.CTime, v.MTime)
}
sqlStr := fmt.Sprintf("INSERT INTO academy_search_keywords (id, rank, parent_id, state, name, comment, ctime, mtime) VALUES %s "+
"ON DUPLICATE KEY UPDATE id=VALUES(id), rank=VALUES(rank), parent_id=VALUES(parent_id), state=VALUES(state), name=VALUES(name), comment=VALUES(comment), ctime=VALUES(ctime), mtime=VALUES(mtime)", strings.Join(valSearks, ","))
if err = tx.Exec(sqlStr, valSearksArgs...).Error; err != nil {
log.Error("insertKeyWords error(%v)", err)
}
return
}
func (s *Service) upRanks(tx *gorm.DB, names []string) (pidMap map[string]*academy.SearchKeywords, err error) {
if len(names) == 0 {
return
}
setRanks := []*academy.SearchKeywords{}
if err = s.DB.Model(&academy.SearchKeywords{}).Where("name IN(?)", names).Find(&setRanks).Error; err != nil {
log.Error("upRanks Find error(%v)", err)
return
}
upRankSQL := "UPDATE academy_search_keywords SET rank = CASE id "
ids := make([]int64, 0)
pidMap = make(map[string]*academy.SearchKeywords)
for _, v := range setRanks {
upRankSQL += fmt.Sprintf("WHEN %d THEN %d ", v.ID, v.ID)
ids = append(ids, v.ID)
pidMap[v.Name] = v
}
if len(ids) == 0 {
return
}
upRankSQL += "END WHERE id IN (?)"
if err = tx.Exec(upRankSQL, ids).Error; err != nil {
log.Error("upRanks update rank ids(%+v) error(%v)", ids, err)
}
return
}

View File

@@ -0,0 +1,80 @@
package service
import (
"time"
"go-common/app/admin/main/creative/model/academy"
"go-common/app/admin/main/creative/model/logcli"
"go-common/app/admin/main/creative/model/music"
"go-common/app/admin/main/creative/model/task"
"go-common/library/conf/env"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/queue/databus/report"
)
// SendAcademyLog academy log to manager.
func (s *Service) SendAcademyLog(c *bm.Context, lp *academy.LogParam) (err error) {
if env.DeployEnv == env.DeployEnvDev {
return
}
logData := &report.ManagerInfo{
Business: academy.LogClientAcademy,
Type: 0,
Uname: lp.UName,
UID: lp.UID,
Oid: lp.TID,
Action: lp.Action,
Ctime: time.Now(),
Index: []interface{}{lp.TID},
Content: map[string]interface{}{
"academy_manager": lp,
},
}
log.Info("s.SendAcademyLog logData(%+v) log param(%+v)", logData, lp)
report.Manager(logData)
return
}
// SendMusicLog send to log archive music
func (s *Service) SendMusicLog(c *bm.Context, clientType int, ap *music.LogParam) (err error) {
logData := &report.ManagerInfo{
Uname: ap.UName,
UID: ap.UID,
Business: logcli.LogClientArchiveMusic,
Type: clientType,
Oid: ap.ID,
Action: ap.Action,
Ctime: time.Now(),
Index: []interface{}{ap.ID},
Content: map[string]interface{}{
"object": ap,
},
}
log.Info("sendMusicLog logData(%+v) ap(%+v)", logData, ap)
report.Manager(logData)
return
}
// SendTaskLog task log to manager.
func (s *Service) SendTaskLog(c *bm.Context, lp *task.LogParam) (err error) {
if env.DeployEnv == env.DeployEnvDev {
return
}
logData := &report.ManagerInfo{
Business: task.LogClientTask,
Type: 0,
Uname: lp.UName,
UID: lp.UID,
Oid: lp.OID,
Action: lp.Action,
Ctime: time.Now(),
Index: []interface{}{lp.OID},
Content: map[string]interface{}{
"params": lp.Content,
},
}
log.Info("s.SendTaskLog logData(%+v) log param(%+v)", logData, lp)
report.Manager(logData)
return
}

View File

@@ -0,0 +1,16 @@
package service
import (
"context"
"go-common/app/admin/main/creative/model/material"
)
// CategoryByID .
func (s *Service) CategoryByID(c context.Context, id int64) (cate *material.Category, err error) {
return s.dao.CategoryByID(c, id)
}
// BindWithCategory .
func (s *Service) BindWithCategory(c context.Context, MaterialID, CategoryID, index int64) (id int64, err error) {
return s.dao.BindWithCategory(c, MaterialID, CategoryID, index)
}

View File

@@ -0,0 +1,67 @@
package service
import (
"context"
"fmt"
"go-common/app/admin/main/creative/model/logcli"
"go-common/app/admin/main/creative/model/music"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/xstr"
)
//SendNotify .
func (s *Service) SendNotify(c *bm.Context, sendIds []int64, data map[int64]*music.SidNotify) (err error) {
var (
//mid首次收录
content = "您的音频稿件au:%d已被手机投稿BGM库收录快加入素材激励计划(#{APP申请入口}{\"https://member.bilibili.com/studio/up-allowance-h5#\"},#{WEB申请入口}{\"https://member.bilibili.com/v/#/allowance\"})获取收益吧!被收录稿件名:《%s》"
//sid首次收录
content2 = "您的音频稿件【《%s》au:%d】已被手机投稿BGM库收录期待您创作更多优秀的新作品哦"
title = "创作激励计划素材收录通知"
)
for _, sid := range sendIds {
if _, ok := data[sid]; !ok {
continue
}
sendConfig := data[sid]
log.Info("svc.SendNotify param sendConfig(%+v) ", sendConfig)
var (
mids []int64
first, send bool
sendContent string
)
//check exists
exists := music.Music{}
if err = s.DBArchive.Model(&music.Music{}).Where("sid=?", sid).First(&exists).Error; err != nil {
continue
}
//每个mid 第一次收录 优先级最高
if sendConfig.MidFirst {
first = true
send = true
}
if !sendConfig.MidFirst && sendConfig.SidFirst {
first = false
send = true
}
if !first {
content = content2
sendContent = fmt.Sprintf(content, exists.Name, exists.Sid)
} else {
sendContent = fmt.Sprintf(content, exists.Sid, exists.Name)
}
if !send {
return
}
mids = []int64{exists.Mid}
s.addAsyn(func() {
if err = s.dao.MutliSendSysMsg(context.TODO(), mids, title, sendContent); err != nil {
log.Error("s.d.MutliSendSysMsg(%s,%s,%s) error(%+v)", xstr.JoinInts(mids), title, sendContent, err)
return
}
})
s.SendMusicLog(c, logcli.LogClientArchiveMusicTypeCategoryRelation, &music.LogParam{ID: sid, UID: 0, UName: fmt.Sprintf("mid(%d)", exists.Mid), Action: "SendNotify", Name: sendContent})
}
return
}

View File

@@ -0,0 +1,73 @@
package service
import (
"context"
"sync"
"go-common/app/admin/main/creative/conf"
"go-common/app/admin/main/creative/dao"
"go-common/library/log"
"github.com/jinzhu/gorm"
)
// Service str
type Service struct {
conf *conf.Config
dao *dao.Dao
DB *gorm.DB
DBArchive *gorm.DB
wg sync.WaitGroup
asynch chan func()
closed bool
}
// New fn
func New(c *conf.Config) (s *Service) {
s = &Service{
conf: c,
dao: dao.New(c),
asynch: make(chan func(), 10240),
}
s.DB = s.dao.DB
s.DBArchive = s.dao.DBArchive
s.wg.Add(1)
go s.asynproc()
return
}
// Ping fn
func (s *Service) Ping(c context.Context) (err error) {
return s.dao.Ping(c)
}
func (s *Service) addAsyn(f func()) {
select {
case s.asynch <- f:
default:
log.Warn("asynproc chan full")
}
}
// cacheproc is a routine for executing closure.
func (s *Service) asynproc() {
defer s.wg.Done()
for {
if s.closed {
return
}
f, ok := <-s.asynch
if !ok {
return
}
f()
}
}
// Close dao
func (s *Service) Close() {
s.dao.Close()
s.closed = true
s.wg.Wait()
}

View File

@@ -0,0 +1,53 @@
package service
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/admin/main/creative/conf"
accapi "go-common/app/service/main/account/api"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../cmd/creative-admin.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() {})
f(s)
}
}
func Test_Profile(t *testing.T) {
mid := int64(27515256)
Convey("Profile", t, WithService(func(s *Service) {
var (
pfl *accapi.ProfileStatReply
err error
)
pfl, err = s.ProfileStat(context.TODO(), mid)
time.Sleep(time.Millisecond * 100)
So(err, ShouldBeNil)
So(pfl, ShouldNotBeNil)
}))
}
func Test_SearchKeywords(t *testing.T) {
Convey("SearchKeywords", t, WithService(func(s *Service) {
s.SearchKeywords()
}))
}

View File

@@ -0,0 +1,924 @@
package service
import (
"fmt"
"sort"
"strings"
"time"
"go-common/app/admin/main/creative/model/task"
"go-common/library/ecode"
"go-common/library/log"
)
//TaskGroupRewards for task group & rewards.
func (s *Service) TaskGroupRewards(ids []int64) (res map[int64][]*task.TaskGroupReward, err error) {
tgrs := []*task.TaskGroupReward{}
if err = s.DB.Model(&task.TaskGroupReward{}).Where("task_group_id IN (?)", ids).Where("state>=0").Find(&tgrs).Error; err != nil {
log.Error("s.TaskGroupRewards ids(%+v) error(%v)", ids, err)
}
if len(tgrs) == 0 {
return
}
res = make(map[int64][]*task.TaskGroupReward)
for _, v := range tgrs {
if v != nil {
res[v.TaskGroupID] = append(res[v.TaskGroupID], v)
}
}
return
}
func (s *Service) getRewards(rids []int64) (res []*task.RewardResult) {
_, rewardMap := s.loadRewards()
if len(rids) == 0 || len(rewardMap) == 0 {
return
}
sort.Slice(rids, func(i, j int) bool {
return rids[i] < rids[j]
})
res = make([]*task.RewardResult, 0, len(rids))
for _, rid := range rids {
if v, ok := rewardMap[rid]; ok {
res = append(res, &task.RewardResult{
RewardID: v.ID,
RewardName: v.Name,
})
}
}
return
}
//AddTaskGroup for add task group.
func (s *Service) AddTaskGroup(v *task.TaskGroup, rewardsIDs []int64) (id int64, err error) {
now := time.Now().Format("2006-01-02 15:04:05")
v.CTime = now
tx := s.DB.Begin()
v.State = task.StateHide
if err = tx.Create(v).Error; err != nil {
log.Error("addGroup error(%v)", err)
tx.Rollback()
return
}
if err = tx.Model(&task.TaskGroup{}).Where("id=?", v.ID).Updates(map[string]interface{}{
"rank": v.ID,
}).Error; err != nil {
log.Error("addGroup error(%v)", err)
tx.Rollback()
return
}
if len(rewardsIDs) > 0 {
valReward := make([]string, 0, len(rewardsIDs))
valRewardArgs := make([]interface{}, 0)
for _, rid := range rewardsIDs {
valReward = append(valReward, "(?, ?, ?, ?, ?, ?)")
valRewardArgs = append(valRewardArgs, v.ID, rid, task.StateNormal, v.Comment, now, now)
}
sqlRewardStr := fmt.Sprintf("INSERT INTO newcomers_grouptask_reward (task_group_id, reward_id, state, comment, ctime, mtime) VALUES %s", strings.Join(valReward, ","))
if err = tx.Exec(sqlRewardStr, valRewardArgs...).Error; err != nil {
log.Error("addGroup link reward error(%v)", err)
tx.Rollback()
return
}
}
tx.Commit()
return v.ID, nil
}
//EditTaskGroup for edit task group.
func (s *Service) EditTaskGroup(v *task.TaskGroup, rewardsIDs []int64) (id int64, err error) {
now := time.Now().Format("2006-01-02 15:04:05")
tg := &task.TaskGroup{}
if err = s.DB.Model(&task.TaskGroup{}).Where("id=?", v.ID).Find(tg).Error; err != nil {
log.Error("EditTaskGroup link reward error(%v)", err)
return
}
if tg == nil {
return
}
tx := s.DB.Begin()
if err = tx.Model(&task.TaskGroup{}).Where("id=?", v.ID).Updates(map[string]interface{}{
"root_type": v.RootType,
"type": v.Type,
}).Error; err != nil {
log.Error("editGroup error(%v)", err)
tx.Rollback()
return
}
if len(rewardsIDs) > 0 {
var tgr task.TaskGroupReward
if err = tx.Where("task_group_id =?", v.ID).Delete(&tgr).Error; err != nil {
log.Error("editGroup delete old group id(%d)|error(%v)", v.ID, err)
tx.Rollback()
return
}
valReward := make([]string, 0, len(rewardsIDs))
valRewardArgs := make([]interface{}, 0)
for _, rid := range rewardsIDs {
valReward = append(valReward, "(?, ?, ?, ?, ?, ?)")
valRewardArgs = append(valRewardArgs, v.ID, rid, task.StateNormal, v.Comment, now, now)
}
sqlRewardStr := fmt.Sprintf("INSERT INTO newcomers_grouptask_reward (task_group_id, reward_id, state, comment, ctime, mtime) VALUES %s ON DUPLICATE KEY UPDATE task_group_id=VALUES(task_group_id), reward_id=VALUES(reward_id)", strings.Join(valReward, ","))
if err = tx.Exec(sqlRewardStr, valRewardArgs...).Error; err != nil {
log.Error("editGroup link reward error(%v)", err)
tx.Rollback()
return
}
}
tx.Commit()
return v.ID, nil
}
//OrderTaskGroup for order task group.
func (s *Service) OrderTaskGroup(v *task.OrderTask) (err error) {
tg := &task.TaskGroup{}
if err = s.DB.Find(tg, v.ID).Error; err != nil {
log.Error("orderGroup error(%v)", err)
return
}
stg := &task.TaskGroup{}
if err = s.DB.Find(stg, v.SwitchID).Error; err != nil {
log.Error("orderGroup error(%v)", err)
return
}
tx := s.DB.Begin()
if err = tx.Model(&task.TaskGroup{}).Where("id=?", v.ID).Updates(
map[string]interface{}{
"rank": v.SwitchRank,
},
).Error; err != nil {
log.Error("orderGroup error(%v)", err)
tx.Rollback()
return
}
if err = tx.Model(&task.TaskGroup{}).Where("id=?", v.SwitchID).Updates(
map[string]interface{}{
"rank": v.Rank,
},
).Error; err != nil {
log.Error("orderGroup error(%v)", err)
tx.Rollback()
return
}
tx.Commit()
return
}
//UpStateGroup for update task group.
func (s *Service) UpStateGroup(id int64, state int8) (err error) {
tg := &task.TaskGroup{}
if err = s.DB.Find(tg, id).Error; err != nil {
log.Error("UpStateGroup id(%d) error(%v)", id, err)
return
}
if tg.ID == 0 {
err = ecode.NothingFound
return
}
if err = s.DB.Model(&task.TaskGroup{}).Where("id=?", id).Updates(map[string]interface{}{
"state": state,
}).Error; err != nil {
log.Error("UpStateGroup id(%d) state(%d) error(%v)", id, state, err)
return
}
return
}
//TaskGroup for task group.
func (s *Service) TaskGroup(id int64) (res *task.TaskGroup, err error) {
var tg task.TaskGroup
if err = s.DB.Model(&task.TaskGroup{}).Where("id=?", id).Find(&tg).Error; err != nil {
log.Error("s.TaskGroup id (%d) error(%v)", id, err)
return
}
if tg.ID == 0 {
return
}
tgrsMap, _ := s.TaskGroupRewards([]int64{id})
if rs, ok := tgrsMap[id]; ok {
rids := make([]int64, 0, len(rs))
for _, r := range rs {
if r != nil {
rids = append(rids, r.RewardID)
}
}
tg.Reward = s.getRewards(rids)
}
res = &tg
return
}
//AddSubtask for add sub task.
func (s *Service) AddSubtask(v *task.Task, rewardsIDs []int64) (id int64, err error) {
now := time.Now().Format("2006-01-02 15:04:05")
v.CTime = now
v.MTime = now
v.State = task.StateHide
tx := s.DB.Begin()
if err = tx.Create(v).Error; err != nil {
log.Error("AddSubtask error(%v)", err)
tx.Rollback()
return
}
if v.ID == 0 {
log.Error("AddSubtask v.ID(%d)", v.ID)
tx.Rollback()
return
}
if err = tx.Model(&task.Task{}).Where("id=?", v.ID).Updates(map[string]interface{}{
"rank": v.ID,
}).Error; err != nil {
log.Error("AddSubtask error(%v)", err)
tx.Rollback()
return
}
if len(rewardsIDs) > 0 {
valReward := make([]string, 0, len(rewardsIDs))
valRewardArgs := make([]interface{}, 0)
for _, rid := range rewardsIDs {
valReward = append(valReward, "(?, ?, ?, ?, ?, ?)")
valRewardArgs = append(valRewardArgs, v.ID, rid, task.StateNormal, v.Comment, now, now)
}
sqlRewardStr := fmt.Sprintf("INSERT INTO newcomers_task_reward (task_id, reward_id, state, comment, ctime, mtime) VALUES %s", strings.Join(valReward, ","))
if err = tx.Exec(sqlRewardStr, valRewardArgs...).Error; err != nil {
log.Error("AddSubtask link reward error(%v)", err)
tx.Rollback()
return
}
}
tx.Commit()
return v.ID, nil
}
//EditSubtask for edit sub task.
func (s *Service) EditSubtask(v *task.Task, rewardsIDs []int64) (id int64, err error) {
tk := &task.Task{}
if err = s.DB.Model(&task.TaskGroup{}).Where("id=?", v.ID).Find(tk).Error; err != nil {
return
}
if tk == nil {
err = ecode.NothingFound
return
}
now := time.Now().Format("2006-01-02 15:04:05")
v.CTime = tk.CTime
v.MTime = now
v.State = tk.State //编辑不更新状态
tx := s.DB.Begin()
if err = tx.Save(v).Error; err != nil { //Save将包括执行更新SQL时的所有字段即使它没有更改
log.Error("editSubtask error(%v)", err)
tx.Rollback()
return
}
if len(rewardsIDs) > 0 {
var tr task.TaskReward
if err = tx.Where("task_id =?", v.ID).Delete(&tr).Error; err != nil {
log.Error("editSubtask delete old task id(%d)|error(%v)", v.ID, err)
tx.Rollback()
return
}
valReward := make([]string, 0, len(rewardsIDs))
valRewardArgs := make([]interface{}, 0)
for _, rid := range rewardsIDs {
valReward = append(valReward, "(?, ?, ?, ?, ?, ?)")
valRewardArgs = append(valRewardArgs, v.ID, rid, task.StateNormal, v.Comment, now, now)
}
sqlRewardStr := fmt.Sprintf("INSERT INTO newcomers_task_reward (task_id, reward_id, state, comment, ctime, mtime) VALUES %s ON DUPLICATE KEY UPDATE task_id=VALUES(task_id), reward_id=VALUES(reward_id)", strings.Join(valReward, ","))
if err = tx.Exec(sqlRewardStr, valRewardArgs...).Error; err != nil {
log.Error("editSubtask link reward error(%v)", err)
tx.Rollback()
return
}
}
tx.Commit()
return v.ID, nil
}
//OrderSubTask for order sub task.
func (s *Service) OrderSubTask(v *task.OrderTask) (err error) {
tg := &task.Task{}
if err = s.DB.Find(tg, v.ID).Error; err != nil {
log.Error("OrderSubTask error(%v)", err)
return
}
stg := &task.Task{}
if err = s.DB.Find(stg, v.SwitchID).Error; err != nil {
log.Error("OrderSubTask error(%v)", err)
return
}
tx := s.DB.Begin()
if err = tx.Model(&task.Task{}).Where("id=?", v.ID).Updates(
map[string]interface{}{
"rank": v.SwitchRank,
},
).Error; err != nil {
log.Error("OrderSubTask error(%v)", err)
tx.Rollback()
return
}
if err = tx.Model(&task.Task{}).Where("id=?", v.SwitchID).Updates(
map[string]interface{}{
"rank": v.Rank,
},
).Error; err != nil {
log.Error("OrderSubTask error(%v)", err)
tx.Rollback()
return
}
tx.Commit()
return
}
//UpStateSubTask for update sub task state.
func (s *Service) UpStateSubTask(id int64, state int8) (err error) {
tg := &task.Task{}
if err = s.DB.Find(tg, id).Error; err != nil {
return
}
if tg.ID == 0 {
err = ecode.NothingFound
return
}
if err = s.DB.Model(&task.Task{}).Where("id=?", id).Updates(map[string]interface{}{
"state": state,
}).Error; err != nil {
log.Error("UpStateSubTask id(%d) state(%d) error(%v)", id, state, err)
return
}
return
}
//TransferSubtask for transfer one sub task from some one group to another one.
func (s *Service) TransferSubtask(id, gid int64) (err error) {
tg := &task.TaskGroup{}
if err = s.DB.Find(tg, gid).Error; err != nil {
return
}
if tg.ID == 0 {
err = ecode.CreativeNewcomerGroupIDErr
return
}
tk := &task.Task{}
if err = s.DB.Find(tk, id).Error; err != nil {
return
}
if tk.ID == 0 {
err = ecode.NothingFound
return
}
if err = s.DB.Model(&task.Task{}).Where("id=?", id).Updates(map[string]interface{}{
"group_id": gid,
}).Error; err != nil {
log.Error("transferSubtask id(%+v) gid(%d) error(%v)", id, gid, err)
return
}
return
}
//Task for task.
func (s *Service) Task(id int64) (res *task.Task, err error) {
var t task.Task
if err = s.DB.Model(&task.Task{}).Where("id=?", id).Find(&t).Error; err != nil {
log.Error("s.Task id (%d) error(%v)", id, err)
return
}
if t.ID == 0 {
return
}
trsMap, _ := s.TaskRewards([]int64{id})
if rs, ok := trsMap[id]; ok {
rids := make([]int64, 0, len(rs))
for _, r := range rs {
if r != nil {
rids = append(rids, r.RewardID)
}
}
t.Reward = s.getRewards(rids)
}
res = &t
return
}
//TaskRewards for task & rewards.
func (s *Service) TaskRewards(ids []int64) (res map[int64][]*task.TaskReward, err error) {
trs := []*task.TaskReward{}
if err = s.DB.Model(&task.TaskReward{}).Where("state>=0 AND task_id IN (?)", ids).Find(&trs).Error; err != nil {
log.Error("s.TaskRewards ids(%+v) error(%v)", ids, err)
return
}
if len(trs) == 0 {
return
}
res = make(map[int64][]*task.TaskReward)
for _, v := range trs {
if v != nil {
res[v.TaskID] = append(res[v.TaskID], v)
}
}
return
}
//TasksByGroupIDsMap for task map
func (s *Service) TasksByGroupIDsMap(gids []int64) (res map[int64][]*task.Task, err error) {
tks := []*task.Task{}
if err = s.DB.Model(&task.Task{}).Where("state>=0 AND type>0 AND group_id IN (?)", gids).Find(&tks).Error; err != nil {
log.Error("s.TasksByGroupIDsMap id (%+v) error(%v)", gids, err)
return
}
if len(tks) == 0 {
return
}
tkMap := make(map[int64]*task.Task)
tgMap := make(map[int64][]*task.Task)
ids := make([]int64, 0, len(tks))
for _, v := range tks {
if v == nil {
continue
}
if v.Rank == 0 {
v.Rank = v.ID
}
ids = append(ids, v.ID)
tkMap[v.ID] = v
tgMap[v.GroupID] = append(tgMap[v.GroupID], v)
}
trsMap, _ := s.TaskRewards(ids)
for _, id := range ids {
rs, ok := trsMap[id]
if !ok || len(rs) == 0 {
continue
}
rids := make([]int64, 0, len(rs))
for _, r := range rs {
if r != nil {
rids = append(rids, r.RewardID)
}
}
tkMap[id].Reward = s.getRewards(rids)
}
res = make(map[int64][]*task.Task)
for _, gid := range gids {
tks, ok := tgMap[gid]
if !ok || len(tks) == 0 {
continue
}
for _, tk := range tks {
if v, ok := tkMap[tk.ID]; ok {
res[gid] = append(res[gid], v)
}
}
}
for _, v := range res {
sort.Slice(v, func(i, j int) bool {
return v[i].Rank < v[j].Rank
})
}
return
}
//TaskList for task list
func (s *Service) TaskList(ty int8) (res []*task.TaskGroup, err error) {
tgs := []*task.TaskGroup{}
db := s.DB.Model(&task.TaskGroup{}).Where("state>=0 AND root_type>0 AND type>0")
if ty > 0 {
db = db.Where("type=?", ty)
}
if err = db.Find(&tgs).Error; err != nil {
log.Error("TaskList %v\n", err)
return
}
if len(tgs) == 0 {
return
}
gids := make([]int64, 0, len(tgs))
tgMap := make(map[int64]*task.TaskGroup)
for _, v := range tgs {
if v == nil {
continue
}
gids = append(gids, v.ID)
tgMap[v.ID] = v
}
tgrsMap, _ := s.TaskGroupRewards(gids)
for _, id := range gids {
if rs, ok := tgrsMap[id]; ok {
if len(rs) == 0 {
continue
}
rids := make([]int64, 0, len(rs))
for _, r := range rs {
if r != nil {
rids = append(rids, r.RewardID)
}
}
tgMap[id].Reward = s.getRewards(rids)
}
}
tkMap, _ := s.TasksByGroupIDsMap(gids)
res = tgs
for _, v := range res {
if v == nil {
continue
}
if g, ok := tgMap[v.ID]; ok {
v.Reward = g.Reward
}
if tks, ok := tkMap[v.ID]; ok {
v.Tasks = tks
}
}
sort.Slice(res, func(i, j int) bool {
return res[i].Rank < res[j].Rank
})
return
}
//loadRewards for task reward.
func (s *Service) loadRewards() (res []*task.Reward, rwMap map[int64]*task.Reward) {
var (
rds = []*task.Reward{}
err error
)
if err = s.DB.Order("id ASC").Find(&rds).Error; err != nil {
log.Error("loadRewards error(%v)", err)
return
}
res = make([]*task.Reward, 0, len(rds))
rwMap = make(map[int64]*task.Reward)
top := make(map[int64]*task.Reward)
for _, v := range rds {
if v == nil {
continue
}
rwMap[v.ID] = v
if v.ParentID == 0 {
top[v.ID] = v //映射一级对象
res = append(res, v) //追加一级对象
}
}
for _, ch := range rds {
if ch == nil {
continue
}
if p, ok := top[ch.ParentID]; ok && p != nil && p.Type == ch.Type { //为一级对象增加子对象,注:要append满足条件的ch若append p 则会造成递归导致stack overflow
p.Children = append(p.Children, ch)
}
}
return
}
//RewardTree for reward tree.
func (s *Service) RewardTree() (res []*task.Reward) {
res, _ = s.loadRewards()
return
}
//ViewReward for view one reward.
func (s *Service) ViewReward(id int64) (res *task.Reward, err error) {
rd := task.Reward{}
if err = s.DB.Model(&task.Reward{}).Where("id=?", id).Find(&rd).Error; err != nil {
return
}
res = &rd
return
}
//AddReward for add one reward.
func (s *Service) AddReward(v *task.Reward) (id int64, err error) {
now := time.Now().Format("2006-01-02 15:04:05")
v.CTime = now
v.MTime = now
if err = s.DB.Create(v).Error; err != nil {
log.Error("AddReward v(%+v) error(%v)", v, err)
return
}
return v.ID, nil
}
//EditReward for edit one reward.
func (s *Service) EditReward(v *task.Reward) (id int64, err error) {
rd := &task.Reward{}
if err = s.DB.Model(&task.Reward{}).Where("id=?", v.ID).Find(rd).Error; err != nil {
return
}
if rd == nil {
err = ecode.NothingFound
return
}
v.CTime = rd.CTime
v.MTime = time.Now().Format("2006-01-02 15:04:05")
v.State = rd.State //编辑不更新状态
if err = s.DB.Save(v).Error; err != nil {
log.Error("EditReward v(%+v) error(%v)", v, err)
return
}
return v.ID, nil
}
//UpStateReward for update reward state.
func (s *Service) UpStateReward(id int64, state int8) (err error) {
rd := &task.Reward{}
if err = s.DB.Find(rd, id).Error; err != nil {
return
}
if rd.ID == 0 {
err = ecode.NothingFound
return
}
if rd.ParentID != 0 { //如果是子分类直接更新并返回
if err = s.DB.Model(&task.Reward{}).Where("id=?", id).Updates(map[string]interface{}{
"state": state,
}).Error; err != nil {
log.Error("UpStateReward parent id(%d) state(%d) error(%v)", id, state, err)
}
return
}
rds := []*task.Reward{}
if err = s.DB.Model(&task.Reward{}).Where("parent_id=?", id).Find(&rds).Error; err != nil {
log.Error("UpStateReward get childen by parent id(%d) error(%v)", rd.ParentID, err)
return
}
ids := make([]int64, 0, len(rds)+1)
for _, v := range rds {
if v != nil {
ids = append(ids, v.ID) //追加子分类id
}
}
ids = append(ids, id) //追加父分类id
if err = s.DB.Model(&task.Reward{}).Where("id IN (?)", ids).Updates(map[string]interface{}{
"state": state,
}).Error; err != nil {
log.Error("UpStateReward childen ids(%+v) error(%v)", ids, err)
}
return
}
//ViewGiftReward for view gift.
func (s *Service) ViewGiftReward(v *task.GiftReward) (res *task.GiftReward, err error) {
var gfs []*task.GiftReward
if err = s.DB.Model(&task.GiftReward{}).Where("root_type=? AND task_type=?", v.RootType, v.TaskType).Find(&gfs).Error; err != nil {
log.Error("ViewGiftReward v(%+v) error(%v)", v, err)
return
}
if len(gfs) == 0 {
return
}
res = &task.GiftReward{
RootType: v.RootType,
TaskType: v.TaskType,
}
var (
state int8
comment string
)
rids := make([]int64, 0, len(gfs))
for _, gf := range gfs {
if gf != nil {
state = gf.State
comment = gf.Comment
rids = append(rids, gf.RewardID)
}
}
res.State = state
res.Comment = comment
res.Reward = s.getRewards(rids)
return
}
//ListGiftReward for get gift list.
func (s *Service) ListGiftReward() (res []*task.GiftReward, err error) {
gfs := []*task.GiftReward{}
if err = s.DB.Model(&task.GiftReward{}).Where("root_type>0 AND task_type>0").Find(&gfs).Error; err != nil {
log.Error("ListGiftReward error(%v)", err)
return
}
if len(gfs) == 0 {
return
}
gfMap := make(map[int64][]*task.GiftReward)
for _, v := range gfs {
if v != nil {
gfMap[v.TaskType] = append(gfMap[v.TaskType], v)
}
}
tys := make([]int64, 0, len(gfMap))
for k := range gfMap {
tys = append(tys, k)
}
sort.Slice(tys, func(i, j int) bool {
return tys[i] < tys[j]
})
res = make([]*task.GiftReward, 0, len(tys))
for _, ty := range tys {
gfs, ok := gfMap[ty]
if !ok && len(gfs) == 0 {
continue
}
var rt uint8
if task.CheckRootType(uint8(ty)) {
rt = task.TaskManagement
} else {
rt = task.AchievementManagement
}
re := &task.GiftReward{
RootType: rt,
TaskType: ty,
}
var (
state int8
comment string
)
rids := make([]int64, 0, len(gfs))
for _, gf := range gfs {
if gf != nil {
state = gf.State
comment = gf.Comment
rids = append(rids, gf.RewardID)
}
}
re.State = state
re.Comment = comment
re.Reward = s.getRewards(rids)
res = append(res, re)
}
return
}
//AddGiftReward for add gift rewards.
func (s *Service) AddGiftReward(v *task.GiftReward, rewardsIDs []int64) (rows int64, err error) {
var gfs []*task.GiftReward
if err = s.DB.Model(&task.GiftReward{}).Where("root_type=? AND task_type=? AND reward_id IN (?)", v.RootType, v.TaskType, rewardsIDs).Find(&gfs).Error; err != nil {
log.Error("UpGiftReward v(%+v) error(%v)", v, err)
return
}
if len(gfs) != 0 {
hitMap := make(map[int64]struct{})
for _, gf := range gfs {
hitMap[gf.RewardID] = struct{}{}
}
for _, rid := range rewardsIDs {
if _, ok := hitMap[rid]; ok {
err = ecode.CreativeNewcomerDuplicateGiftRewardIDErr
log.Error("AddGiftReward rid(%d) error(%v)", rid, err)
return
}
}
}
valReward := make([]string, 0, len(rewardsIDs))
valRewardArgs := make([]interface{}, 0)
now := time.Now().Format("2006-01-02 15:04:05")
for _, rid := range rewardsIDs {
valReward = append(valReward, "(?, ?, ?, ?, ?, ?, ?)")
valRewardArgs = append(valRewardArgs, v.RootType, v.TaskType, rid, task.StateNormal, v.Comment, now, now)
}
sqlRewardStr := fmt.Sprintf("INSERT INTO newcomers_gift_reward (root_type, task_type, reward_id, state, comment, ctime, mtime) VALUES %s", strings.Join(valReward, ","))
if err = s.DB.Exec(sqlRewardStr, valRewardArgs...).Error; err != nil {
log.Error("AddGiftReward error(%v)", err)
return
}
return s.DB.RowsAffected, nil
}
//EditGiftReward for edit gift rewards.
func (s *Service) EditGiftReward(v *task.GiftReward, rewardsIDs []int64) (rows int64, err error) {
var (
gfs []*task.GiftReward
state int8
)
if err = s.DB.Model(&task.GiftReward{}).Where("root_type=? AND task_type=?", v.RootType, v.TaskType).Find(&gfs).Error; err != nil {
log.Error("EditGiftReward v(%+v) error(%v)", v, err)
return
}
if len(gfs) == 0 {
err = ecode.NothingFound
return
}
for _, gf := range gfs { //获取原来的状态
state = gf.State
break
}
var gf task.GiftReward
if err = s.DB.Model(&task.GiftReward{}).Where("root_type =?", v.RootType).Where("task_type =?", v.TaskType).Delete(&gf).Error; err != nil {
log.Error("EditGiftReward delete old id(%d)|error(%v)", v.ID, err)
return
}
valReward := make([]string, 0, len(rewardsIDs))
valRewardArgs := make([]interface{}, 0)
now := time.Now().Format("2006-01-02 15:04:05")
for _, rid := range rewardsIDs {
valReward = append(valReward, "(?, ?, ?, ?, ?, ?, ?)")
valRewardArgs = append(valRewardArgs, v.RootType, v.TaskType, rid, state, v.Comment, now, now)
}
sqlRewardStr := fmt.Sprintf("INSERT INTO newcomers_gift_reward (root_type, task_type, reward_id, state, comment, ctime, mtime) VALUES %s", strings.Join(valReward, ","))
if err = s.DB.Exec(sqlRewardStr, valRewardArgs...).Error; err != nil {
log.Error("EditGiftReward error(%v)", err)
return
}
return s.DB.RowsAffected, nil
}
//UpGiftReward for update gift reward.
func (s *Service) UpGiftReward(v *task.GiftReward) (rows int64, err error) {
var gfs []*task.GiftReward
if err = s.DB.Model(&task.GiftReward{}).Where("root_type=? AND task_type=?", v.RootType, v.TaskType).Find(&gfs).Error; err != nil {
log.Error("UpGiftReward v(%+v) error(%v)", v, err)
return
}
if len(gfs) == 0 {
return
}
if err = s.DB.Model(&task.GiftReward{}).Where("root_type=? AND task_type=?", v.RootType, v.TaskType).Updates(map[string]interface{}{
"state": v.State,
}).Error; err != nil {
log.Error("UpGiftReward v(%+v) error(%v)", v, err)
return
}
return s.DB.RowsAffected, nil
}
//BatchOnline for subtask & grouptask with state,rank and so on.
func (s *Service) BatchOnline(tgs []*task.TaskGroup) (err error) {
tasks := make([]*task.Task, 0)
groups := make([]*task.TaskGroup, 0, len(tgs))
for _, v := range tgs {
groups = append(groups, &task.TaskGroup{
ID: v.ID,
Rank: v.Rank,
State: v.State,
RootType: v.RootType,
Type: v.Type,
})
tasks = append(tasks, v.Tasks...)
}
valGroups := make([]string, 0, len(groups))
valGroupArgs := make([]interface{}, 0)
for _, v := range groups {
valGroups = append(valGroups, "(?, ?, ?)")
valGroupArgs = append(valGroupArgs, v.ID, v.State, v.Rank)
}
sqlGroupStr := fmt.Sprintf("INSERT INTO newcomers_task_group (id, state, rank) VALUES %s ON DUPLICATE KEY UPDATE state=VALUES(state), rank=VALUES(rank)", strings.Join(valGroups, ","))
if err = s.DB.Exec(sqlGroupStr, valGroupArgs...).Error; err != nil {
log.Error("BatchOnline update groups error(%v)", err)
return
}
valTasks := make([]string, 0, len(tasks))
valTaskArgs := make([]interface{}, 0)
for _, v := range tasks {
valTasks = append(valTasks, "(?, ?, ?, ?)")
valTaskArgs = append(valTaskArgs, v.ID, v.State, v.Rank, v.GroupID)
}
sqlTaskStr := fmt.Sprintf("INSERT INTO newcomers_task (id, state, rank, group_id) VALUES %s ON DUPLICATE KEY UPDATE state=VALUES(state), rank=VALUES(rank), group_id=VALUES(group_id)", strings.Join(valTasks, ","))
if err = s.DB.Exec(sqlTaskStr, valTaskArgs...).Error; err != nil {
log.Error("BatchOnline update tasks error(%v)", err)
}
return
}

View File

@@ -0,0 +1,49 @@
package service
import (
"bytes"
"context"
"crypto/md5"
"encoding/hex"
"io"
"net/http"
"go-common/app/admin/main/creative/model/bfs"
"go-common/library/ecode"
"go-common/library/log"
)
// Upload to bfs
func (s *Service) Upload(c context.Context, fileName string, fileType string, timing int64, body []byte) (location string, err error) {
if len(body) == 0 {
err = ecode.FileNotExists
return
}
if len(body) > s.conf.Bfs.MaxFileSize {
err = ecode.FileTooLarge
return
}
if location, err = s.dao.Upload(c, fileName, fileType, timing, body, s.conf.Bfs); err != nil {
log.Error("s.upload.Upload() error(%v)", err)
}
return
}
// ParseFile analyses file info
func (s *Service) ParseFile(c context.Context, content []byte) (file *bfs.FileInfo, err error) {
fType := http.DetectContentType(content)
// file md5
md5hash := md5.New()
if _, err = io.Copy(md5hash, bytes.NewReader(content)); err != nil {
log.Error("resource uploadFile.Copy error(%v)", err)
return
}
md5 := md5hash.Sum(nil)
fMd5 := hex.EncodeToString(md5[:])
file = &bfs.FileInfo{
Md5: fMd5,
Type: fType,
Size: int64(len(content)),
}
return
}

View File

@@ -0,0 +1,44 @@
package service
import (
"context"
"fmt"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
)
var (
c = context.TODO()
now = time.Now().Unix()
)
func TestService_Upload(t *testing.T) {
Convey("Upload should return without err", t, WithService(func(svf *Service) {
// simulate file content
str2 := "Testing File Content"
data2 := []byte(str2)
// upload to bfs
location, err := svf.Upload(c, "tName", "image/png", now, data2)
// testing
So(err, ShouldBeNil)
So(location, ShouldNotBeNil)
fmt.Println(location)
}))
}
func TestService_ParseFile(t *testing.T) {
Convey("ParseFile can get file info", t, WithService(func(svf *Service) {
// simulate file content
str2 := "Testing File Content"
data2 := []byte(str2)
// upload to bfs
fInfo, err := svf.ParseFile(c, data2)
// testing
So(err, ShouldBeNil)
So(fInfo.Size, ShouldBeGreaterThan, 0)
So(fInfo.Type, ShouldNotBeBlank)
So(fInfo.Md5, ShouldNotBeBlank)
}))
}

View File

@@ -0,0 +1,71 @@
package service
import (
"context"
"sort"
"go-common/app/admin/main/creative/model/whitelist"
accapi "go-common/app/service/main/account/api"
"go-common/library/log"
"golang.org/x/sync/errgroup"
)
// Cards fn
func (s *Service) Cards(c context.Context, wls []*whitelist.Whitelist) (wlsWithAcc []*whitelist.Whitelist, err error) {
wlsWithAcc = []*whitelist.Whitelist{}
var (
g errgroup.Group
)
ch := make(chan *whitelist.Whitelist, len(wls))
for _, wl := range wls {
id := wl.ID
mid := wl.MID
adminMid := wl.AdminMID
comment := wl.Comment
state := wl.State
tp := wl.Type
ctime := wl.Ctime
mtime := wl.Mtime
g.Go(func() (err error) {
pfl, err := s.dao.ProfileStat(c, mid)
if err != nil {
log.Error("s.dao.Card mid(%+v)|err(%+v)", mid, err)
return
}
var name string
if pfl.Profile != nil {
name = pfl.Profile.Name
}
ch <- &whitelist.Whitelist{
ID: id,
MID: mid,
AdminMID: adminMid,
Comment: comment,
State: state,
Type: tp,
Fans: pfl.Follower,
CurrentLevel: pfl.LevelInfo.Cur,
Name: name,
Ctime: ctime,
Mtime: mtime,
}
return
})
}
g.Wait()
close(ch)
for c := range ch {
wlsWithAcc = append(wlsWithAcc, c)
}
sort.Slice(wlsWithAcc, func(i, j int) bool { return wlsWithAcc[i].Ctime > wlsWithAcc[j].Ctime })
return
}
// ProfileStat fn
func (s *Service) ProfileStat(c context.Context, mid int64) (pfl *accapi.ProfileStatReply, err error) {
if pfl, err = s.dao.ProfileStat(c, mid); err != nil {
log.Error("s.dao.Profile mid(%+v)|err(%+v)", mid, err)
}
return
}