Initial commit: web_hghl_server

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-10-26 16:28:14 +08:00
co-authored by Claude Opus 4.7
commit 65fca60622
653 changed files with 135901 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
GOPATH:=$(shell go env GOPATH)
GIT_BRANCH:=$(shell git symbolic-ref --short -q HEAD)
GIT_VERSION:=$(shell git log --pretty=oneline -p -1 | head -n 1 | awk '{print $$1}')
BUILD_DATE:=$(shell date '+%Y-%m-%d %H:%M:%S %z')
BUILD_IP:=$(shell ifconfig | grep inet | grep -v grep | grep -v "inet6" | grep -v "127.0.0.1" | awk '{print $$2}')
VERSON_PATH:=miao/pub/srvversion
WEB_BUILD_FLAG:=-ldflags "-X '$(VERSON_PATH).GIT_BRANCH=$(GIT_BRANCH)' -X '$(VERSON_PATH).GIT_VERSION=$(GIT_VERSION)' -X '$(VERSON_PATH).BUILD_DATE=$(BUILD_DATE)' -X '$(VERSON_PATH).BUILD_IP=$(BUILD_IP)'"
.PHONY: test deploy
deploy:
go clean
rm -f web_mdcom_web
env GOOS=linux GOARCH=amd64 go build $(WEB_BUILD_FLAG) -o web_mdcom_web
tar czf web_mdcom_web.tar.gz web_mdcom_web
rm -f web_mdcom_web
test:
go clean
rm -f web_mdcom_web
GOOS=linux GOARCH=amd64 go build $(WEB_BUILD_FLAG) -o web_mdcom_web
tar czf web_mdcom_web.tar.gz web_mdcom_web docs
rm -f web_mdcom_web
localtest:
@echo "test, GOPATH=$(GOPATH)"
go build $(WEB_BUILD_FLAG) -o web
swagger:
swag init --parseDependency --parseDepth 4
+92
View File
@@ -0,0 +1,92 @@
package proto
import (
"time"
"videoweb/pub/common/response"
"videoweb/pub/models/contenttagmod"
"videoweb/pub/pubdef"
)
// ContentTagListReq web端统一标签分页列表请求
type ContentTagListReq struct {
pubdef.Page
Id *int64 `form:"id" json:"id"` // 标签ID
Name string `form:"name" json:"name"` // 标签名称,支持模糊查询
Type *contenttagmod.ContentTagType `form:"type" json:"type"` // 内容类型 1-视频 5-短剧
Status *bool `form:"status" json:"status"` // 状态 true-启用 false-停用
}
// ContentTagListResp web端统一标签列表项
type ContentTagListResp struct {
Id int64 `json:"id"` // ID
Name string `json:"name"` // 标签名称
Slug string `json:"slug"` // slug
Types []contenttagmod.ContentTagType `json:"types"` // 支持类型 1-视频 5-短剧
TypeNames []string `json:"typeNames"` // 支持类型名称
Status bool `json:"status"` // 状态 true-启用 false-停用
Rank int64 `json:"rank"` // 排序,越大越靠前
VideoCount int64 `json:"videoCount"` // 绑定视频数量
PlayletCount int64 `json:"playletCount"` // 绑定短剧数量
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
CreatedById int64 `json:"createdById"` // 创建人ID
CreatedByName string `json:"createdByName"` // 创建人名称
UpdatedByName string `json:"updatedByName"` // 修改人名称
CreatedAt time.Time `json:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt"` // 修改时间
}
// ContentTagListPageResp web端统一标签分页列表响应
type ContentTagListPageResp struct {
response.BasePageResp
}
// ContentTagOptionReq web端统一标签下拉列表请求
type ContentTagOptionReq struct {
Type *contenttagmod.ContentTagType `form:"type" json:"type"` // 内容类型 1-视频 5-短剧,不传返回全部启用标签
}
// ContentTagOptionResp web端统一标签下拉列表响应
type ContentTagOptionResp struct {
List []*ContentTagOptionItem `json:"list"` // 标签下拉列表
}
// ContentTagOptionItem web端统一标签下拉项
type ContentTagOptionItem struct {
Id int64 `json:"id"` // ID
Name string `json:"name"` // 标签名称
Types []contenttagmod.ContentTagType `json:"types"` // 支持类型 1-视频 5-短剧
TypeNames []string `json:"typeNames"` // 支持类型名称
Rank int64 `json:"rank"` // 排序,越大越靠前
BindCount int64 `json:"bindCount"` // 当前查询类型的绑定数量,不传type时返回0
}
// ContentTagAddReq web端新增统一标签请求
type ContentTagAddReq struct {
Name string `json:"name" binding:"required"` // 标签名称
Slug string `json:"slug"` // slug,不传则按 SEO 关键词或名称自动生成
Types []contenttagmod.ContentTagType `json:"types" binding:"required"` // 支持类型 1-视频 5-短剧
Status *bool `json:"status" binding:"required"` // 状态 true-启用 false-停用
Rank int64 `json:"rank"` // 排序,越大越靠前
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
// ContentTagAddResp web端新增统一标签响应
type ContentTagAddResp struct {
Id int64 `json:"id"` // ID
}
// ContentTagUpdateReq web端更新统一标签请求
type ContentTagUpdateReq struct {
Id int64 `json:"id" binding:"required"` // ID
Name *string `json:"name"` // 标签名称
Slug *string `json:"slug"` // slug,历史数据为空时更新会自动生成
Types *[]contenttagmod.ContentTagType `json:"types"` // 支持类型 1-视频 5-短剧
Status *bool `json:"status"` // 状态 true-启用 false-停用
Rank *int64 `json:"rank"` // 排序,越大越靠前
SeoInfo *pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
// ContentTagDelReq web端删除统一标签请求
type ContentTagDelReq struct {
Id int64 `json:"id" binding:"required"` // ID
}
+67
View File
@@ -0,0 +1,67 @@
package proto
import (
"time"
"videoweb/pub/common/response"
)
// HomeBannerListReq web端首页 banner 分页列表请求
type HomeBannerListReq struct {
PageNum int64 `form:"pageNum" json:"pageNum"` // 页码,默认1
PageSize int64 `form:"pageSize" json:"pageSize"` // 每页数量,默认10,最大100
Id *int64 `form:"id" json:"id"` // 首页 banner ID
Name string `form:"name" json:"name"` // 名称,支持模糊查询
Status *bool `form:"status" json:"status"` // 状态 true-启用 false-停用
}
// HomeBannerListResp web端首页 banner 列表项
type HomeBannerListResp struct {
Id int64 `json:"id"` // ID
Name string `json:"name"` // 名称
Image string `json:"image"` // 图片
VerticalImage string `json:"verticalImage"` // 竖版图片
Url string `json:"url"` // URL
Rank int64 `json:"rank"` // 排序
Status bool `json:"status"` // 状态 true-启用 false-停用
CreatedById int64 `json:"createdById"` // 创建人ID
CreatedByName string `json:"createdByName"` // 创建人名称
UpdatedByName string `json:"updatedByName"` // 修改人名称
CreatedAt time.Time `json:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt"` // 修改时间
}
// HomeBannerListPageResp web端首页 banner 分页列表响应
type HomeBannerListPageResp struct {
response.BasePageResp
}
// HomeBannerAddReq web端新增首页 banner 请求
type HomeBannerAddReq struct {
Name string `json:"name" binding:"required"` // 名称
Image string `json:"image" binding:"required"` // 图片
VerticalImage string `json:"verticalImage"` // 竖版图片
Url string `json:"url"` // URL
Rank int64 `json:"rank"` // 排序
Status *bool `json:"status" binding:"required"` // 状态 true-启用 false-停用
}
// HomeBannerAddResp web端新增首页 banner 响应
type HomeBannerAddResp struct {
Id int64 `json:"id"` // ID
}
// HomeBannerUpdateReq web端更新首页 banner 请求
type HomeBannerUpdateReq struct {
Id int64 `json:"id" binding:"required"` // ID
Name *string `json:"name"` // 名称
Image *string `json:"image"` // 图片
VerticalImage *string `json:"verticalImage"` // 竖版图片
Url *string `json:"url"` // URL
Rank *int64 `json:"rank"` // 排序
Status *bool `json:"status"` // 状态 true-启用 false-停用
}
// HomeBannerDelReq web端删除首页 banner 请求
type HomeBannerDelReq struct {
Id int64 `json:"id" binding:"required"` // ID
}
+355
View File
@@ -0,0 +1,355 @@
package proto
import (
"time"
"videoweb/pub/common/response"
"videoweb/pub/models/playletchaptermod"
"videoweb/pub/models/playletmod"
"videoweb/pub/pubdef"
)
// PlayletListReq web端短剧分页列表请求
type PlayletListReq struct {
pubdef.Page
Id *int64 `form:"id" json:"id"` // 短剧ID
CategoryId *int64 `form:"categoryId" json:"categoryId"` // 分类ID
TagId *int64 `form:"tagId" json:"tagId"` // 标签ID
ThemeId *int64 `form:"themeId" json:"themeId"` // 题材ID
ContentType *playletmod.ContentType `form:"contentType" json:"contentType"` // 内容类型,0-短剧、1-普通短剧/影集、2-漫画短剧、3-动漫、4-漫画
PayType *playletmod.PayType `form:"payType" json:"payType"` // 支付方式,0-免费、1-金币、2-VIP
Status *playletmod.Status `form:"status" json:"status"` // 上架状态,0-下架、1-上架
IsFeatured *bool `form:"isFeatured" json:"isFeatured"` // 是否爆剧,true-是、false-否
IsOriginal *bool `form:"isOriginal" json:"isOriginal"` // 是否原创:true只查原创,false只查非原创,不传查全部
ShowOriginal *bool `form:"showOriginal" json:"showOriginal"` // 页面是否展示原创标识 不传查全部
IsRecommend *bool `form:"isRecommend" json:"isRecommend"` // 是否推荐,true-推荐、false-不推荐
ShowOnBanner *bool `form:"showOnBanner" json:"showOnBanner"` // 是否显示在首页banner,true-显示、false-不显示
Title string `form:"title" json:"title"` // 短剧标题,支持模糊查询
OperatorName string `form:"operatorName" json:"operatorName"` // 最后操作人名称,支持模糊查询
}
// PlayletListResp web端短剧列表项
type PlayletListResp struct {
Id int64 `json:"id"` // 短剧ID
Status playletmod.Status `json:"status"` // 上架状态,0-下架、1-上架
IsFeatured bool `json:"isFeatured"` // 是否爆剧,true-是、false-否
IsOriginal bool `json:"isOriginal"` // 是否原创:后台新增为true,媒资导入为false
ShowOriginal bool `json:"showOriginal"` // 页面是否展示原创标识
MediaBusiness string `json:"mediaBusiness"` // 媒资业务来源,按媒资标题前缀记录,如 CGDJ;空表示未标记
IsRecommend bool `json:"isRecommend"` // 是否推荐,true-推荐、false-不推荐
ShowOnBanner bool `json:"showOnBanner"` // 是否显示在首页banner,true-显示、false-不显示
Banner string `json:"banner"` // banner图
ReviewAt time.Time `json:"reviewAt"` // 审核时间
OnlineAt time.Time `json:"onlineAt"` // 上架时间
Title string `json:"title"` // 标题
Slug string `json:"slug"` // slug
Desc string `json:"desc"` // 简介
Anchor string `json:"anchor"` // 作者/演员
Cover string `json:"cover"` // 封面原图
CompressedCover string `json:"compressedCover"` // 压缩封面
Preview string `json:"preview"` // 预告
CategoryIds []int64 `json:"categoryIds"` // 分类ID集合
CategoryBinds []PlayletCategoryBind `json:"categoryBinds"` // 各分类下的排序
CategoryRank int64 `json:"categoryRank"` // 当前筛选分类下的排序
CategoryNames []string `json:"categoryNames"` // 分类名称集合
ThemeIds []int64 `json:"themeIds"` // 题材ID集合
ThemeNames []string `json:"themeNames"` // 题材名称集合
TagIds []int64 `json:"tagIds"` // 标签ID集合
TagNames []string `json:"tagNames"` // 标签名称集合
OldTags []string `json:"oldTags"` // 媒资库原标签名称
ContentType playletmod.ContentType `json:"contentType"` // 内容类型,0-短剧、1-普通短剧/影集、2-漫画短剧、3-动漫、4-漫画
PayType playletmod.PayType `json:"payType"` // 支付方式,0-免费、1-金币、2-VIP
SingleCoins int64 `json:"singleCoins"` // 单集金币,支付方式为1-金币时生效
TotalEpisode int64 `json:"totalEpisode"` // 总集数
FreeEpisodeCount int64 `json:"freeEpisodeCount"` // 官网开放集数 1至1000表示开放第1集到第N集 -1表示开放全集 历史未配置按2集返回
UpdateStatus int `json:"updateStatus"` // 连载状态,1-连载中、2-已完结
TopRank int64 `json:"topRank"` // 置顶排序
RecommendRank int64 `json:"recommendRank"` // 推荐排序
CountComment int64 `json:"countComment"` // 评论数
CountBuy int64 `json:"countBuy"` // 购买数
CountBrowse int64 `json:"countBrowse"` // 浏览数
VirtualCountBrowse int64 `json:"virtualCountBrowse"` // 后台虚拟观看数
DisplayCountBrowse int64 `json:"displayCountBrowse"` // 展示观看数
HeatValue int64 `json:"heatValue"` // 热度值
VirtualHeatValue int64 `json:"virtualHeatValue"` // 后台虚拟热度值
DisplayHeatValue int64 `json:"displayHeatValue"` // 展示热度值
CountCollect int64 `json:"countCollect"` // 收藏数
CountLike int64 `json:"countLike"` // 真实点赞数
VirtualCountLike int64 `json:"virtualCountLike"` // 虚拟点赞数
DisplayCountLike int64 `json:"displayCountLike"` // 展示点赞数=真实点赞数+虚拟点赞数
CountDisLike int64 `json:"countDisLike"` // 不喜欢数
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
OperatorId int64 `json:"operatorId"` // 最后操作人ID
OperatorName string `json:"operatorName"` // 最后操作人名称
CreatedAt time.Time `json:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt"` // 更新时间
}
// PlayletListPageResp web端短剧分页列表响应
type PlayletListPageResp struct {
response.BasePageResp
}
// PlayletCategoryBind 短剧在指定分类下的排序
type PlayletCategoryBind struct {
Id int64 `json:"id"` // 分类ID
Rank int64 `json:"rank"` // 排序值,越大越靠前,不填为0
}
// PlayletDelReq 删除短剧请求
type PlayletDelReq struct {
Ids []int64 `json:"ids" binding:"required"` // 短剧ID集合
}
// PlayletAddReq web端新增短剧请求
type PlayletAddReq struct {
CategoryIds []int64 `json:"categoryIds"` // 分类ID集合
CategoryBinds []PlayletCategoryBind `json:"categoryBinds"` // 各分类下的排序,优先于categoryIds
ThemeIds []int64 `json:"themeIds"` // 题材ID集合
Title string `json:"title" binding:"required"` // 标题
Slug string `json:"slug"` // slug,不传则按 SEO 关键词或标题自动生成
Desc string `json:"desc"` // 简介
Anchor string `json:"anchor"` // 作者/演员
Cover string `json:"cover"` // 封面原图
Preview string `json:"preview"` // 预告
TagIds []int64 `json:"tagIds"` // 标签ID集合
ContentType playletmod.ContentType `json:"contentType"` // 内容类型,0-短剧、1-普通短剧/影集、2-漫画短剧、3-动漫、4-漫画
PayType playletmod.PayType `json:"payType"` // 支付方式,0-免费、1-金币、2-VIP
SingleCoins int64 `json:"singleCoins"` // 单集金币,支付方式为1-金币时生效
TotalEpisode int64 `json:"totalEpisode"` // 总集数
FreeEpisodeCount *int64 `json:"freeEpisodeCount"` // 官网开放集数 不传默认2集 1至1000表示开放第1集到第N集 -1表示开放全集 0无效
TopRank int64 `json:"topRank"` // 置顶排序
RecommendRank int64 `json:"recommendRank"` // 推荐排序
Status playletmod.Status `json:"status"` // 上架状态,0-下架、1-上架
IsFeatured bool `json:"isFeatured"` // 是否爆剧,true-是、false-否
ShowOriginal bool `json:"showOriginal"` // 页面是否展示原创标识
IsRecommend bool `json:"isRecommend"` // 是否推荐,true-推荐、false-不推荐
ShowOnBanner bool `json:"showOnBanner"` // 是否显示在首页banner
Banner string `json:"banner"` // banner图
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
// PlayletAddResp web端新增短剧响应
type PlayletAddResp struct {
Id int64 `json:"id"` // 短剧ID
}
// PlayletUpdateReq web端更新短剧请求
type PlayletUpdateReq struct {
Id int64 `json:"id" binding:"required"` // 短剧ID
Status *playletmod.Status `json:"status"` // 上架状态,0-下架、1-上架
IsFeatured *bool `json:"isFeatured"` // 是否爆剧,true-是、false-否
ShowOriginal *bool `json:"showOriginal"` // 页面是否展示原创标识 不传保持原值
IsRecommend *bool `json:"isRecommend"` // 是否推荐,true-推荐、false-不推荐
ShowOnBanner *bool `json:"showOnBanner"` // 是否显示在首页banner
Banner *string `json:"banner"` // banner图
CategoryIds *[]int64 `json:"categoryIds"` // 分类ID集合,传空数组表示清空分类
CategoryBinds *[]PlayletCategoryBind `json:"categoryBinds"` // 各分类下的排序,优先于categoryIds
ThemeIds *[]int64 `json:"themeIds"` // 题材ID集合
Title *string `json:"title"` // 标题
Slug *string `json:"slug"` // slug,历史数据为空时更新会自动生成
Desc *string `json:"desc"` // 简介
Anchor *string `json:"anchor"` // 作者/演员
Cover *string `json:"cover"` // 封面原图
Preview *string `json:"preview"` // 预告
TagIds *[]int64 `json:"tagIds"` // 标签ID集合,传空数组表示清空标签
ContentType *playletmod.ContentType `json:"contentType"` // 内容类型,0-短剧、1-普通短剧/影集、2-漫画短剧、3-动漫、4-漫画
PayType *playletmod.PayType `json:"payType"` // 支付方式,0-免费、1-金币、2-VIP
SingleCoins *int64 `json:"singleCoins"` // 单集金币,支付方式为1-金币时生效
TotalEpisode *int64 `json:"totalEpisode"` // 总集数
FreeEpisodeCount *int64 `json:"freeEpisodeCount"` // 官网可播放范围 不传则不修改 传1至1000时仅开放第1集至指定集数 传-1开放全部剧集 传0报参数错误
TopRank *int64 `json:"topRank"` // 置顶排序
RecommendRank *int64 `json:"recommendRank"` // 推荐排序
SeoInfo *pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
// PlayletPayTypeSetReq web端单/批量设置短剧默认支付方式请求
type PlayletPayTypeSetReq struct {
Ids []int64 `json:"ids"` // 短剧ID集合,传1个表示单条设置,传多个表示批量设置
PayType playletmod.PayType `json:"payType"` // 支付方式,0-免费、1-金币、2-VIP
SingleCoins *int64 `json:"singleCoins"` // 单集金币,支付方式为1-金币时必填且需大于0
}
// PlayletWatermarkResetReq web端按短剧ID批量重置剧集水印请求
type PlayletWatermarkResetReq struct {
Ids []int64 `json:"ids"` // 短剧ID集合,传1个表示单条,传多个表示批量
}
// PlayletChapterListReq web端短剧剧集分页列表请求
type PlayletChapterListReq struct {
pubdef.Page
PlayletId *int64 `form:"playletId" json:"playletId"` // 短剧ID
Id *int64 `form:"id" json:"id"` // 剧集ID
WatermarkStatus *playletchaptermod.WatermarkStatus `form:"watermarkStatus" json:"watermarkStatus"` // 水印状态 0-未处理 1-已登记 2-处理中 3-已完成 4-处理失败
}
// PlayletChapterListResp web端短剧剧集列表项
type PlayletChapterListResp struct {
Id int64 `json:"id"` // 剧集ID
PlayletId int64 `json:"playletId"` // 短剧ID
MediaContentId uint `json:"mediaContentId"` // 媒资中心剧集ID
CurrentEpisode int64 `json:"currentEpisode"` // 第几集
Title string `json:"title"` // 剧集标题
Md5 string `json:"md5"` // 媒体md5
Hash string `json:"hash"` // 媒体hash
Height int64 `json:"height"` // 视频高度
Width int64 `json:"width"` // 视频宽度
Ratio float64 `json:"ratio"` // 宽高比
VideoUrl string `json:"videoUrl"` // 原片视频地址
WatermarkVideoUrl string `json:"watermarkVideoUrl"` // 加水印后的视频地址
MediaSize int64 `json:"mediaSize"` // 资源大小
MediaTime int64 `json:"mediaTime"` // 影片长度,单位秒
CountComment int64 `json:"countComment"` // 评论数
CountBuy int64 `json:"countBuy"` // 购买数
CountBrowse int64 `json:"countBrowse"` // 浏览数
CountCollect int64 `json:"countCollect"` // 收藏数
CountLike int64 `json:"countLike"` // 点赞数
CountDisLike int64 `json:"countDisLike"` // 不喜欢数
PayType playletchaptermod.PayType `json:"payType"` // 支付方式 0-免费 1-金币 2-VIP
SingleCoins int64 `json:"singleCoins"` // 单集金币,支付方式为1-金币时生效
WatermarkStatus playletchaptermod.WatermarkStatus `json:"watermarkStatus"` // 水印状态 0-未处理 1-已登记 2-处理中 3-已完成 4-处理失败
MediaSourceId string `json:"mediaSourceId"` // media切片服原片ID
MediaTaskId string `json:"mediaTaskId"` // media切片服水印任务ID
CreatedAt time.Time `json:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt"` // 更新时间
}
// PlayletChapterListPageResp web端短剧剧集分页列表响应
type PlayletChapterListPageResp struct {
response.BasePageResp
}
// PlayletChapterAddReq web端新增短剧剧集请求
type PlayletChapterAddReq struct {
PlayletId int64 `json:"playletId" binding:"required"` // 短剧ID
CurrentEpisode int64 `json:"currentEpisode" binding:"required"` // 第几集
Title string `json:"title"` // 剧集标题
Md5 string `json:"md5"` // 媒体md5
Hash string `json:"hash"` // 媒体hash
Height int64 `json:"height"` // 视频高度
Width int64 `json:"width"` // 视频宽度
Ratio float64 `json:"ratio"` // 宽高比
VideoUrl string `json:"videoUrl"` // 原片视频地址
MediaSize int64 `json:"mediaSize"` // 资源大小
MediaTime int64 `json:"mediaTime"` // 影片长度,单位秒
PayType playletchaptermod.PayType `json:"payType"` // 支付方式 0-免费 1-金币 2-VIP
SingleCoins int64 `json:"singleCoins"` // 单集金币,支付方式为1-金币时生效
MediaSourceId string `json:"mediaSourceId"` // media切片服原片ID,上传正片已创建原片时直接沿用
}
// PlayletChapterAddResp web端新增短剧剧集响应
type PlayletChapterAddResp struct {
Id int64 `json:"id"` // 剧集ID
}
// PlayletChapterUpdateReq web端编辑短剧剧集请求
type PlayletChapterUpdateReq struct {
Id int64 `json:"id" binding:"required"` // 剧集ID
CurrentEpisode *int64 `json:"currentEpisode"` // 第几集
Title *string `json:"title"` // 剧集标题
Md5 *string `json:"md5"` // 媒体md5
Hash *string `json:"hash"` // 媒体hash
Height *int64 `json:"height"` // 视频高度
Width *int64 `json:"width"` // 视频宽度
Ratio *float64 `json:"ratio"` // 宽高比
VideoUrl *string `json:"videoUrl"` // 原片视频地址
MediaSize *int64 `json:"mediaSize"` // 资源大小
MediaTime *int64 `json:"mediaTime"` // 影片长度,单位秒
PayType *playletchaptermod.PayType `json:"payType"` // 支付方式 0-免费 1-金币 2-VIP
SingleCoins *int64 `json:"singleCoins"` // 单集金币,支付方式为1-金币时生效
}
// PlayletChapterDelReq web端单/批量删除短剧剧集请求
type PlayletChapterDelReq struct {
Ids []int64 `json:"ids"` // 剧集ID集合,传1个表示单条删除,传多个表示批量删除
}
// PlayletChapterSyncReq web端手动同步短剧剧集请求
type PlayletChapterSyncReq struct {
PlayletIds []int64 `json:"playletIds" binding:"required"` // 短剧ID集合,传1个表示单条同步,传多个表示批量同步
}
// PlayletChapterSyncResult web端手动同步短剧剧集结果项
type PlayletChapterSyncResult struct {
PlayletId int64 `json:"playletId"` // 短剧ID
NewChapterCount int `json:"newChapterCount"` // 本次新增剧集数量
Success bool `json:"success"` // 是否同步成功
Reason string `json:"reason"` // 失败原因
}
// PlayletChapterSyncResp web端手动同步短剧剧集响应
type PlayletChapterSyncResp struct {
Total int `json:"total"` // 同步总数
SuccessCount int `json:"successCount"` // 成功数量
FailedCount int `json:"failedCount"` // 失败数量
List []*PlayletChapterSyncResult `json:"list"` // 同步结果集合
}
// PlayletChapterPayTypeSetReq web端单/批量设置短剧剧集支付方式请求
type PlayletChapterPayTypeSetReq struct {
Ids []int64 `json:"ids"` // 剧集ID集合,传1个表示单条设置,传多个表示批量设置
PayType playletchaptermod.PayType `json:"payType"` // 支付方式 0-免费 1-金币 2-VIP
SingleCoins *int64 `json:"singleCoins"` // 单集金币,支付方式为1-金币时必填且需大于0
}
// PlayletStatusSetReq web端单/批量设置短剧上下架请求
type PlayletStatusSetReq struct {
Ids []int64 `json:"ids"` // 短剧ID集合,传1个表示单条设置,传多个表示批量设置
Status playletmod.Status `json:"status"` // 上架状态,0-下架、1-上架
}
// PlayletRecommendSetReq web端单/批量设置短剧推荐请求
type PlayletRecommendSetReq struct {
Ids []int64 `json:"ids"` // 短剧ID集合,传1个表示单条设置,传多个表示批量设置
IsRecommend bool `json:"isRecommend"` // 是否推荐,true-推荐、false-不推荐
}
// PlayletFeaturedSetReq web端单/批量设置短剧是否爆剧请求
type PlayletFeaturedSetReq struct {
Ids []int64 `json:"ids"` // 短剧ID集合,传1个表示单条设置,传多个表示批量设置
IsFeatured bool `json:"isFeatured"` // 是否爆剧,true-是、false-否
}
// PlayletBannerSetReq web端单/批量设置短剧是否显示在首页banner请求
type PlayletBannerSetReq struct {
Ids []int64 `json:"ids"` // 短剧ID集合,传1个表示单条设置,传多个表示批量设置
ShowOnBanner bool `json:"showOnBanner"` // 是否显示在首页banner,true-显示、false-不显示
}
// PlayletCategorySetReq web端单/批量设置短剧分类请求
type PlayletCategorySetReq struct {
Ids []int64 `json:"ids"` // 短剧ID集合,传1个表示单条设置,传多个表示批量设置
CategoryIds *[]int64 `json:"categoryIds"` // 分类ID集合,可设置多个分类,传空数组表示清空分类,不传表示参数错误
}
// PlayletTagSetReq web端单/批量设置短剧标签请求
type PlayletTagSetReq struct {
Ids []int64 `json:"ids"` // 短剧ID集合,传1个表示单条设置,传多个表示批量设置
TagIds *[]int64 `json:"tagIds"` // 标签ID集合,可设置多个标签,传空数组表示清空标签,不传表示参数错误
}
// PlayletThemeSetReq web端单/批量设置短剧题材请求
type PlayletThemeSetReq struct {
Ids []int64 `json:"ids"` // 短剧ID集合,传1个表示单条设置,传多个表示批量设置
ThemeIds []int64 `json:"themeIds"` // 题材ID集合,可设置多个题材
}
// PlayletVirtualLikeSetReq web端单/批量设置短剧虚拟点赞数请求
type PlayletVirtualLikeSetReq struct {
Ids []int64 `json:"ids"` // 短剧ID集合,传1个表示单条设置,传多个表示批量设置
MinVirtualCountLike int64 `json:"minVirtualCountLike"` // 虚拟点赞数最小值,必须大于等于0
MaxVirtualCountLike int64 `json:"maxVirtualCountLike"` // 虚拟点赞数最大值,必须大于等于最小值
}
// PlayletVirtualBrowseSetReq web端单/批量设置短剧虚拟观看数请求
type PlayletVirtualBrowseSetReq struct {
Ids []int64 `json:"ids"` // 短剧ID集合
MinVirtualCountBrowse int64 `json:"minVirtualCountBrowse"` // 虚拟观看数最小值
MaxVirtualCountBrowse int64 `json:"maxVirtualCountBrowse"` // 虚拟观看数最大值
}
// PlayletVirtualHeatSetReq web端单/批量设置短剧虚拟热度请求
type PlayletVirtualHeatSetReq struct {
Ids []int64 `json:"ids"` // 短剧ID集合
MinVirtualHeatValue int64 `json:"minVirtualHeatValue"` // 虚拟热度最小值
MaxVirtualHeatValue int64 `json:"maxVirtualHeatValue"` // 虚拟热度最大值
}
+67
View File
@@ -0,0 +1,67 @@
package proto
import (
"time"
"videoweb/pub/common/response"
"videoweb/pub/pubdef"
)
// PlayletCategoryListReq web端分类分页列表请求
type PlayletCategoryListReq struct {
pubdef.Page
Id *int64 `form:"id" json:"id"` // 分类ID
Name string `form:"name" json:"name"` // 分类名称,支持模糊查询
Status *bool `form:"status" json:"status"` // 启用状态
}
// PlayletCategoryListResp web端分类列表项
type PlayletCategoryListResp struct {
Id int64 `json:"id"` // 分类ID
Name string `json:"name"` // 分类名称
Slug string `json:"slug"` // slug
Icon string `json:"icon"` // 分类图标
Status bool `json:"status"` // 启用状态
Rank int64 `json:"rank"` // 排序,越大越靠前
Remark string `json:"remark"` // 备注
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
CreatedAt time.Time `json:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt"` // 更新时间
}
// PlayletCategoryListPageResp web端分类分页列表响应
type PlayletCategoryListPageResp struct {
response.BasePageResp
}
// PlayletCategoryAddReq web端新增分类请求
type PlayletCategoryAddReq struct {
Name string `json:"name" binding:"required"` // 分类名称
Slug string `json:"slug"` // slug,不传则按 SEO 关键词或名称自动生成
Icon string `json:"icon"` // 分类图标
Status bool `json:"status"` // 启用状态
Rank int64 `json:"rank"` // 排序,越大越靠前
Remark string `json:"remark"` // 备注
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
// PlayletCategoryAddResp web端新增分类响应
type PlayletCategoryAddResp struct {
Id int64 `json:"id"` // 分类ID
}
// PlayletCategoryUpdateReq web端更新分类请求
type PlayletCategoryUpdateReq struct {
Id int64 `json:"id" binding:"required"` // 分类ID
Name *string `json:"name"` // 分类名称
Slug *string `json:"slug"` // slug,历史数据为空时更新会自动生成
Icon *string `json:"icon"` // 分类图标
Status *bool `json:"status"` // 启用状态
Rank *int64 `json:"rank"` // 排序,越大越靠前
Remark *string `json:"remark"` // 备注
SeoInfo *pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
// PlayletCategoryDelReq web端删除分类请求
type PlayletCategoryDelReq struct {
Id int64 `json:"id" binding:"required"` // 分类ID
}
+114
View File
@@ -0,0 +1,114 @@
package proto
import (
"time"
"videoweb/pub/common/response"
"videoweb/pub/pubdef"
)
// PlayletHomeConfigListReq web端首页配置分页列表请求
type PlayletHomeConfigListReq struct {
pubdef.Page
Id *int64 `form:"id" json:"id"`
Slug string `form:"slug" json:"slug"` // 页面路径标识
Title string `form:"title" json:"title"`
Desc string `form:"desc" json:"desc"`
Label string `form:"label" json:"label"`
Style string `form:"style" json:"style"`
ModuleType *int64 `form:"moduleType" json:"moduleType"`
DataType *int64 `form:"dataType" json:"dataType"` // 1全部上架短剧 2全部上架视频
RecommendType *int64 `form:"recommendType" json:"recommendType"`
CategoryId *int64 `form:"categoryId" json:"categoryId"`
Enabled *bool `form:"enabled" json:"enabled"`
}
// PlayletHomeConfigListResp web端首页配置列表项
type PlayletHomeConfigListResp struct {
Id int64 `json:"id"`
Slug string `json:"slug"` // 页面路径标识
Title string `json:"title"`
Desc string `json:"desc"`
Label string `json:"label"`
Style string `json:"style"`
CardBackgroundImage string `json:"cardBackgroundImage"`
ModuleType int64 `json:"moduleType"`
DataType int64 `json:"dataType"` // 1全部上架短剧 2全部上架视频
RecommendType int64 `json:"recommendType"`
CategoryId int64 `json:"categoryId"`
TopicIds []int64 `json:"topicIds"` // 专题ID集合 短剧为题材ID 视频为分类ID
Rank int64 `json:"rank"`
Enabled bool `json:"enabled"`
Limit int64 `json:"limit"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
type PlayletHomeConfigListPageResp struct {
response.BasePageResp
}
// PlayletHomeTopicOptionsReq 首页专题下拉选项分页请求
type PlayletHomeTopicOptionsReq struct {
pubdef.Page
DataType int64 `form:"dataType" json:"dataType" binding:"required"` // 1短剧题材 2视频分类
ConfigId int64 `form:"configId" json:"configId"` // 编辑时传当前首页配置ID,用于回显已选项
}
// PlayletHomeTopicOption 首页专题下拉选项
type PlayletHomeTopicOption struct {
Id int64 `json:"id"` // 题材或视频分类ID
Name string `json:"name"` // 题材或视频分类名称
Status bool `json:"status"` // 上架状态,已选项下架时仍可回显
}
// PlayletHomeTopicOptionsResp 首页专题下拉选项分页响应
type PlayletHomeTopicOptionsResp struct {
List []*PlayletHomeTopicOption `json:"list"` // 当前页可选项
SelectedList []*PlayletHomeTopicOption `json:"selectedList"` // 当前配置已选项,独立于分页
TotalCount int64 `json:"totalCount"` // 可选项总数
PageNum int64 `json:"pageNum"` // 当前页码
PageSize int64 `json:"pageSize"` // 每页数量
}
type PlayletHomeConfigAddReq struct {
Title string `json:"title" binding:"required"`
Slug string `json:"slug"` // 页面路径标识 不传则按标题自动生成
Desc string `json:"desc"`
Label string `json:"label"`
Style string `json:"style" binding:"required"`
CardBackgroundImage string `json:"cardBackgroundImage"`
ModuleType int64 `json:"moduleType"`
DataType int64 `json:"dataType"` // 1全部上架短剧 2全部上架视频
RecommendType int64 `json:"recommendType" binding:"required"`
CategoryId int64 `json:"categoryId"`
TopicIds []int64 `json:"topicIds"` // 专题ID集合 短剧为题材ID 视频为分类ID
Rank int64 `json:"rank"`
Enabled bool `json:"enabled"`
Limit int64 `json:"limit"`
}
type PlayletHomeConfigAddResp struct {
Id int64 `json:"id"`
}
type PlayletHomeConfigUpdateReq struct {
Id int64 `json:"id" binding:"required"`
Slug *string `json:"slug"` // 不传保持原值 历史空值自动生成
Title *string `json:"title"`
Desc *string `json:"desc"`
Label *string `json:"label"`
Style *string `json:"style"`
CardBackgroundImage *string `json:"cardBackgroundImage"`
ModuleType *int64 `json:"moduleType"`
DataType *int64 `json:"dataType"` // 1全部上架短剧 2全部上架视频
RecommendType *int64 `json:"recommendType"`
CategoryId *int64 `json:"categoryId"`
TopicIds *[]int64 `json:"topicIds"` // 不传保持原值 传空数组清空专题
Rank *int64 `json:"rank"`
Enabled *bool `json:"enabled"`
Limit *int64 `json:"limit"`
}
type PlayletHomeConfigDelReq struct {
Ids []int64 `json:"ids" binding:"required"`
}
+91
View File
@@ -0,0 +1,91 @@
package proto
// PlayletResourceListReq web端短剧媒资列表请求
type PlayletResourceListReq struct {
Title *string `form:"title" json:"title"` // 标题
Tag *string `form:"tag" json:"tag"` // 标签
MediaType *int `form:"media_type" json:"media_type"` // 媒体类型 1-动漫 2-漫画 4-漫画短剧 5-短剧 6-普通短剧
SyncType *int `form:"sync_type" json:"sync_type"` // 同步类型 1-全量同步 2-增量同步
PageNumber int `form:"pageNumber" json:"pageNumber"` // 页码
PageSize int `form:"pageSize" json:"pageSize"` // 个数
}
// PlayletResourceListItem web端短剧媒资列表项
type PlayletResourceListItem struct {
ID uint `json:"id"`
VloggerId uint `json:"vlogger_id"`
Title string `json:"title"` // 标题
SaleCoin uint `json:"sale_coin"` // 整部售价
HorizontalCover string `json:"horizontal_cover"` // 横版封面
VerticalCover string `json:"vertical_cover"` // 竖版封面
Summary string `json:"summary"` // 简介
TotalEpisode uint `json:"total_episode"` // 总集数
UpdateStatus int `json:"update_status"` // 更新状态 1-连载中 2-已完结
MediaType int `json:"media_type"` // 媒体类型
Anchor string `json:"anchor"` // 作者
TagsText string `json:"tags_text"` // 标签文字
DataVersion int8 `json:"data_version"` // 数据版本
TerminalCdo string `json:"terminal_cdo"` // 上传者
CreateTime int64 `json:"create_time"` // 创建时间
UpdateTime int64 `json:"update_time"` // 修改时间
IsAdd bool `json:"isAdd"` // 是否已加入后台数据
}
// PlayletResourceListResp web端短剧媒资列表响应
type PlayletResourceListResp struct {
List []*PlayletResourceListItem `json:"list"`
Total uint `json:"total"`
}
// PlayletResourceUseReq web端短剧媒资入库请求
type PlayletResourceUseReq struct {
Ids []uint `json:"ids"` // 媒资中心资源ID集合
}
// PlayletResourceChapterListReq web端短剧媒资剧集列表请求
type PlayletResourceChapterListReq struct {
Id uint `form:"id" json:"id" binding:"required"` // 媒资中心资源ID
}
// PlayletResourceChapterItem web端短剧媒资剧集项
type PlayletResourceChapterItem struct {
Id uint `json:"id"` // 媒资内容ID
EpisodeNumber int `json:"episodeNumber"` // 第几集
Title string `json:"title"` // 章节名
Cover string `json:"cover"` // 封面
VideoUrl string `json:"videoUrl"` // 播放地址
Height uint `json:"height"` // 高
Width uint `json:"width"` // 宽
MediaSize uint `json:"mediaSize"` // 资源大小
PlayTime uint `json:"playTime"` // 播放时长(秒)
SaleCoin uint `json:"saleCoin"` // 单集售价
HashId string `json:"hashId"` // 资源hash
CreateTime int64 `json:"createTime"` // 创建时间
UpdateTime int64 `json:"updateTime"` // 更新时间
}
// PlayletResourceChapterListResp web端短剧媒资剧集列表响应
type PlayletResourceChapterListResp struct {
MediaId uint `json:"mediaId"` // 媒资中心资源ID
Title string `json:"title"` // 短剧标题
List []*PlayletResourceChapterItem `json:"list"` // 剧集列表
Total int `json:"total"` // 剧集数量
}
// PlayletResourceUseSuccess web端短剧媒资入库成功项
type PlayletResourceUseSuccess struct {
MediaId uint `json:"mediaId"`
PlayletId int64 `json:"playletId"`
}
// PlayletResourceUseFailed web端短剧媒资入库失败项
type PlayletResourceUseFailed struct {
MediaId uint `json:"mediaId"`
Reason string `json:"reason"`
}
// PlayletResourceUseResp web端短剧媒资入库响应
type PlayletResourceUseResp struct {
Success []*PlayletResourceUseSuccess `json:"success"`
Failed []*PlayletResourceUseFailed `json:"failed"`
}
+58
View File
@@ -0,0 +1,58 @@
package proto
import (
"time"
"videoweb/pub/common/response"
"videoweb/pub/pubdef"
)
// PlayletTagListReq web端标签分页列表请求
type PlayletTagListReq struct {
pubdef.Page
Id *int64 `form:"id" json:"id"`
Name string `form:"name" json:"name"`
Status *bool `form:"status" json:"status"`
}
// PlayletTagListResp web端标签列表项
type PlayletTagListResp struct {
Id int64 `json:"id"`
Name string `json:"name"`
Status bool `json:"status"`
Rank int64 `json:"rank"`
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
// PlayletTagListPageResp web端标签分页列表响应
type PlayletTagListPageResp struct {
response.BasePageResp
}
// PlayletTagAddReq web端新增标签请求
type PlayletTagAddReq struct {
Name string `json:"name" binding:"required"`
Status bool `json:"status"`
Rank int64 `json:"rank"`
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
// PlayletTagAddResp web端新增标签响应
type PlayletTagAddResp struct {
Id int64 `json:"id"`
}
// PlayletTagUpdateReq web端更新标签请求
type PlayletTagUpdateReq struct {
Id int64 `json:"id" binding:"required"`
Name *string `json:"name"`
Status *bool `json:"status"`
Rank *int64 `json:"rank"`
SeoInfo *pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
// PlayletTagDelReq web端删除标签请求
type PlayletTagDelReq struct {
Id int64 `json:"id" binding:"required"`
}
+64
View File
@@ -0,0 +1,64 @@
package proto
import (
"time"
"videoweb/pub/common/response"
"videoweb/pub/pubdef"
)
// PlayletThemeListReq web端题材分页列表请求
type PlayletThemeListReq struct {
pubdef.Page
Id *int64 `form:"id" json:"id"` // 题材ID
Name string `form:"name" json:"name"` // 题材名称,支持模糊查询
Status *bool `form:"status" json:"status"` // 上架状态
}
// PlayletThemeListResp web端题材列表项
type PlayletThemeListResp struct {
Id int64 `json:"id"` // 题材ID
Name string `json:"name"` // 题材名称
Slug string `json:"slug"` // slug
Icon string `json:"icon"` // 题材图标
Status bool `json:"status"` // 上架状态
Rank int64 `json:"rank"` // 排序,越大越靠前
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
CreatedAt time.Time `json:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt"` // 更新时间
}
// PlayletThemeListPageResp web端题材分页列表响应
type PlayletThemeListPageResp struct {
response.BasePageResp
}
// PlayletThemeAddReq web端新增题材请求
type PlayletThemeAddReq struct {
Name string `json:"name" binding:"required"` // 题材名称
Slug string `json:"slug"` // slug,不传则按 SEO 关键词或名称自动生成
Icon string `json:"icon"` // 题材图标
Status bool `json:"status"` // 上架状态
Rank int64 `json:"rank"` // 排序,越大越靠前
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
// PlayletThemeAddResp web端新增题材响应
type PlayletThemeAddResp struct {
Id int64 `json:"id"` // 题材ID
}
// PlayletThemeUpdateReq web端更新题材请求
type PlayletThemeUpdateReq struct {
Id int64 `json:"id" binding:"required"` // 题材ID
Name *string `json:"name"` // 题材名称
Slug *string `json:"slug"` // slug,历史数据为空时更新会自动生成
Icon *string `json:"icon"` // 题材图标
Status *bool `json:"status"` // 上架状态
Rank *int64 `json:"rank"` // 排序,越大越靠前
SeoInfo *pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
// PlayletThemeDelReq web端删除题材请求
type PlayletThemeDelReq struct {
Id int64 `json:"id" binding:"required"` // 题材ID
}
+21
View File
@@ -0,0 +1,21 @@
package proto
// SlugSyncReq 后台补齐历史空 slug 请求
type SlugSyncReq struct {
MaxSize int64 `json:"maxSize"` // 本次最多处理的空 slug 记录数,默认500,最大2000
Type string `json:"type"` // 可选,指定类型;空则按顺序处理全部
}
// SlugSyncResp 后台补齐历史空 slug 响应
type SlugSyncResp struct {
VideoUpdated int64 `json:"videoUpdated"` // 本次补齐的视频数
VideoCategoryUpdated int64 `json:"videoCategoryUpdated"` // 本次补齐的视频分类数
ActressUpdated int64 `json:"actressUpdated"` // 本次补齐的女优数
VideoCreaterUpdated int64 `json:"videoCreaterUpdated"` // 本次补齐的作者数
PlayletUpdated int64 `json:"playletUpdated"` // 本次补齐的短剧数
PlayletCategoryUpdated int64 `json:"playletCategoryUpdated"` // 本次补齐的短剧分类数
PlayletThemeUpdated int64 `json:"playletThemeUpdated"` // 本次补齐的短剧主题数
ContentTagUpdated int64 `json:"contentTagUpdated"` // 本次补齐的统一标签数
TotalUpdated int64 `json:"totalUpdated"` // 本次合计补齐数
HasMore bool `json:"hasMore"` // 是否还有未处理的历史数据
}
+356
View File
@@ -0,0 +1,356 @@
package web_acc
import (
"time"
"videoweb/pub/common"
"videoweb/pub/common/crypt"
"videoweb/pub/common/srvdef"
"videoweb/pub/google"
"videoweb/pub/models/mwacc"
"videoweb/web/service/srv_acc"
"videoweb/web/service/srv_mwacc"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
)
// @Tags 账号
// @Summary 账号-列表
// @Description 账号-列表
// @Accept json
// @Produce json
// @Param param body MwAccListReq true "参数列表"
// @Success 200 {object} MwAccListResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/acc/list [GET]
func AccGetList(c *gin.Context) {
var req MwAccListReq
if err := c.ShouldBindQuery(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
search := mwacc.MakeSearch(req.KeyWords, req.Status, req.Page)
sort := mwacc.MakeSort(req.PageNum, req.PageSize)
total, data, _ := mwacc.GetAccList(c, search, sort)
resp := MwAccListResp{
TotalCount: total,
AccRec: make([]*MwAccRec, 0),
}
for _, v := range data {
resp.AccRec = append(resp.AccRec, &MwAccRec{
Id: v.Id,
UserName: v.Username,
Acc: v.Acc,
Pwd: v.Pwd,
Email: v.Email,
RoleId: v.RoleId,
RoleName: v.RoleName,
// Base32: v.Base32,
IsBase32: v.IsBase32,
IsEnb: v.IsEnb,
FeedBack: v.Feedback,
CreatedAt: v.CreatedAt.Unix(),
UpdatedAt: v.UpdatedAt.Unix(),
LimitIP: v.LimitIP,
})
}
common.ServerJSON(c, srvdef.Success, resp)
}
// @Tags 账号
// @Summary 账号-添加
// @Description 账号-添加
// @Accept json
// @Produce json
// @Param param body MwAccAddReq true "参数列表"
// @Success 200 {object} MwAccAddResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/acc/add [POST]
func AccAdd(c *gin.Context) {
var req MwAccAddReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
accCount, err := mwacc.AccCountByFilter(c, bson.M{
mwacc.FN.MwAcc.Acc: req.Acc,
})
if accCount > 0 || err != nil {
common.ServerJSON(c, srvdef.ErrParamError, "用户已存在")
return
}
secret := google.NewGoogleAuth().GetSecret()
insertDoc := &mwacc.AccInsertDoc{
UserName: req.Name,
Pwd: crypt.StrToMd5(req.Pwd), //md5V(req.Pwd),
Acc: req.Acc,
Email: req.Email,
RoleId: req.RoleId,
Base32: secret,
IsBase32: false,
IsEnb: req.IsEnb,
LimitIP: req.LimitIP,
}
_, _, err = mwacc.AccAdd(c, insertDoc)
if err != nil {
common.ServerJSON(c, srvdef.Failure, MwAccAddResp{Result: false})
return
}
common.ServerJSON(c, srvdef.Success, MwAccAddResp{Result: true})
return
}
// @Tags 账号
// @Summary 账号-删除
// @Description 账号-删除
// @Accept json
// @Produce json
// @Param param body MwAccDelReq true "参数列表"
// @Success 200 {object} MwAccDelResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/acc/del [POST]
func AccDel(c *gin.Context) {
var req MwAccDelReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
err := mwacc.DelAccByFilter(c, bson.M{
mwacc.FN.MwAcc.Id: req.Id,
})
// 删除对应账号的token
_ = mwacc.DeleteOneToken(c, bson.M{
mwacc.FN.MwAccToken.AccId: req.Id,
})
if err != nil {
common.ServerJSON(c, srvdef.Failure, MwAccDelResp{Result: true})
return
}
common.ServerJSON(c, srvdef.Success, MwAccDelResp{Result: true})
return
}
// @Tags 账号
// @Summary 账号-获取信息
// @Description 账号-获取信息
// @Accept json
// @Produce json
// @Param param body MwAccGetInfoReq true "参数列表"
// @Success 200 {object} MwAccGetInfoResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/acc/getinfo [GET]
func AccGetInfo(c *gin.Context) {
var req MwAccGetInfoReq
if err := c.ShouldBindQuery(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
rest, err := mwacc.FindOneAccByFilter(c, bson.M{
mwacc.FN.MwAcc.Id: req.Id,
})
if err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
resq := MwAccGetInfoResp{
Id: rest.Id,
UserName: rest.UserName,
Acc: rest.Acc,
Pwd: rest.Pwd,
Email: rest.Email,
RoleId: rest.RoleId,
IsEnb: rest.IsEnb,
LimitIP: rest.LimitIP,
}
common.ServerJSON(c, srvdef.Success, resq)
return
}
// @Tags 账号
// @Summary 账号-更新
// @Description 账号-更新
// @Accept json
// @Produce json
// @Param param body MwAccUpReq true "参数列表"
// @Success 200 {object} MwAccUpResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/acc/up [POST]
func AccUp(c *gin.Context) {
var req MwAccUpReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
_, err := srv_mwacc.AccUp(c, &srv_mwacc.AccUpDoc{
Id: req.Id,
UserName: req.UserName,
Acc: req.Acc,
Email: req.Email,
RoleId: req.RoleId,
IsEnb: req.IsEnb,
LimitIP: req.LimitIP,
})
if err != nil {
common.ServerJSON(c, srvdef.Failure, MwAccUpResp{Result: false})
return
}
common.ServerJSON(c, srvdef.Success, MwAccUpResp{Result: true})
return
}
// @Tags 账号
// @Summary 账号-获取状态
// @Description 账号-获取状态
// @Accept json
// @Produce json
// @Param param body MwAccGetStatusReq true "参数列表"
// @Success 200 {object} MwAccGetStatusResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/acc/getstatus [GET]
func AccGetStatus(c *gin.Context) {
var req MwAccGetStatusReq
if err := c.ShouldBindQuery(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
rest, err := mwacc.FindOneAccByFilter(c, bson.M{
mwacc.FN.MwAcc.Id: req.Id,
})
if err != nil {
common.ServerJSON(c, srvdef.Failure, err)
return
}
resp := MwAccGetStatusResp{
Id: rest.Id,
UserName: rest.UserName,
IsEnb: rest.IsEnb,
FeedBack: rest.Feedback,
}
common.ServerJSON(c, srvdef.Success, resp)
return
}
// @Tags 账号
// @Summary 账号-保存状态
// @Description 账号-保存状态
// @Accept json
// @Produce json
// @Param param body MwAccSaveStatusReq true "参数列表"
// @Success 200 {object} MwAccSaveStatusResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/acc/savestatus [POST]
func AccSaveStatus(c *gin.Context) {
var req MwAccSaveStatusReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
err := mwacc.UpOneAccByFilter(c, bson.M{
mwacc.FN.MwAcc.Id: req.Id,
}, bson.M{
mwacc.FN.MwAcc.UserName: req.UserName,
mwacc.FN.MwAcc.IsEnb: req.IsEnb,
mwacc.FN.MwAcc.Feedback: req.FeedBack,
mwacc.FN.MwAcc.UpdatedAt: time.Now(),
})
if err != nil {
common.ServerJSON(c, srvdef.Failure, "")
return
}
// 封禁时,删除token
if !req.IsEnb {
mwacc.DeleteOneToken(c, bson.M{mwacc.FN.MwAccToken.AccId: req.Id})
}
common.ServerJSON(c, srvdef.Success, MwAccSaveStatusResp{Result: true})
return
}
// @Tags 账号
// @Summary 账号-获取操作记录
// @Description 账号-获取操作记录
// @Accept json
// @Produce json
// @Param param body AccOpLogReq true "参数列表"
// @Success 200 {object} AccOpLogResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/acc/ops [POST]
func GetAccOpRecords(ctx *gin.Context) {
var req AccOpLogReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
total, data, err := srv_acc.GetOpLogs(ctx, &req.OpLogSearch)
if err != nil {
common.ServerJSON(ctx, srvdef.Failure, err.Error())
return
}
resp := &AccOpLogResp{total, data}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 账号
// @Summary 账号-更新密码
// @Description 账号-更新密码
// @Accept json
// @Produce json
// @Param param body MwAccUpPwdReq true "参数列表"
// @Success 200 {object} MwAccUpPwdReq "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/acc/uppwd [POST]
func AccUpdatePwd(c *gin.Context) {
var req MwAccUpPwdReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
_, err := srv_mwacc.AccUpPwd(c, &srv_mwacc.AccUpPwdDoc{
Id: req.Id,
Pwd: req.Pwd,
})
if err != nil {
common.ServerJSON(c, srvdef.Failure, MwAccUpPwdResp{Result: false})
return
}
common.ServerJSON(c, srvdef.Success, MwAccUpPwdResp{Result: true})
return
}
+114
View File
@@ -0,0 +1,114 @@
package web_acc
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/mwacc"
"videoweb/web/service/srv_mwacc"
"github.com/gin-gonic/gin"
)
// @Tags 登录
// @Summary 登录-登录
// @Description 登录-登录
// @Accept json
// @Produce json
// @Param param body MainWebLoginReq true "参数列表"
// @Success 200 {object} MainWebLoginResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Router /api/web/login/acc [POST]
func AccLogin(c *gin.Context) {
var req MainWebLoginReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
accInfo, err := srv_mwacc.AccLogin(c, req.Acc, req.Pwd, req.Code)
if err != nil || accInfo == nil {
common.ServerJSON(c, err.Code, err.Msg)
return
}
resp := MainWebLoginResp{}
if len(accInfo.Qurl) != 0 {
resp.Qurl = accInfo.Qurl
} else {
// 成功保存token
if ok, _ := mwacc.SaveToken(c, accInfo.Id, accInfo.Token); ok != true {
common.ServerJSON(c, srvdef.GenerateTokenFailed, srvdef.GenerateTokenFailed.Msg())
}
resp.AccId = accInfo.Id
resp.Acc = accInfo.Acc
resp.RoleId = accInfo.RoleId
resp.Token = accInfo.Token
}
common.ServerJSON(c, srvdef.Success, resp)
return
}
// SLogin doc
// @Summary 管理员sso登陆
// @Description 管理员sso登陆
// @Tags web-单点登陆
// @Accept mpfd,json
// @Produce json,html
// @Param name formData string true "账号"
// @Param password formData string true "密码"
// @Success 200 {string} json "{"msg": "管理员信息""}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/web/login/slogin [post]
func SLogin(c *gin.Context) {
var req MainWebLoginReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
accInfo, err := srv_mwacc.AccSLogin(c, req.Acc, req.Pwd)
if err != nil || accInfo == nil {
common.ServerJSON(c, err.Code, err.Msg)
return
}
resp := MainWebLoginResp{}
// 成功保存token
if ok, _ := mwacc.SaveToken(c, accInfo.Id, accInfo.Token); ok != true {
common.ServerJSON(c, srvdef.GenerateTokenFailed, srvdef.GenerateTokenFailed.Msg())
}
resp.AccId = accInfo.Id
resp.Acc = accInfo.Acc
resp.RoleId = accInfo.RoleId
resp.Token = accInfo.Token
common.ServerJSON(c, srvdef.Success, resp)
return
}
// @Tags 登录
// @Summary 登录-绑定二维码
// @Description 登录-绑定二维码
// @Accept json
// @Produce json
// @Param param body BindQurlReq true "参数列表"
// @Success 200 {object} BindQurlResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Router /api/web/login/bind [POST]
func BindQurl(c *gin.Context) {
var req BindQurlReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, "tone AccLogin arg error "+err.Error())
return
}
ok, _ := mwacc.BindAccQurl(c, req.Acc)
if !ok {
common.ServerJSON(c, srvdef.Failure, BindQurlResp{Result: false})
return
}
common.ServerJSON(c, srvdef.Success, BindQurlResp{Result: true})
return
}
+479
View File
@@ -0,0 +1,479 @@
package web_acc
import (
"time"
"videoweb/pub/pubdef"
"videoweb/web/service/srv_acc"
)
/////////////////////////登录//////////////////////////
/******************主后台登录***********************/
// POST /web/login/acc
// 请求参数
type MainWebLoginReq struct {
// 账户
Acc string `json:"acc,omitempty"`
// 密码
Pwd string `json:"pwd,omitempty"`
// 验证码
Code string `json:"code,omitempty"`
}
// 返回参数
type MainWebLoginResp struct {
// 账户id
AccId int64 `json:"accId"`
// 账户
Acc string `json:"acc"`
// 角色id
RoleId int64 `json:"roleId"`
// token
Token string `json:"token"`
// 二维码
Qurl []byte `json:"qurl"`
}
/******************绑定二维码***********************/
// POST /web/login/bind
// 请求参数
type BindQurlReq struct {
//账户
Acc string `json:"acc,omitempty"`
}
// 返回参数
type BindQurlResp struct {
// 是否成功 true:成功 false:未成功
Result bool `json:"result,omitempty"`
}
/******************绑定二维码***********************/
/////////////////////////角色//////////////////////////
// GET /web/role/list
// 请求参数
// 角色记录
type MwRoleRec struct {
// 角色Id
Id int64 `json:"id"`
// 角色名称
Name string `json:"name"`
// 描述
Desc string `json:"desc"`
// 是否启用 false:禁用 true:启用
IsEnb bool `json:"isEnb"`
// 已有权限的api
ApiMenus []string `json:"apiMenus"`
// 创建时间
CreatedAt time.Time `json:"createdAt"`
// 更新时间
UpdatedAt time.Time `json:"updatedAt"`
}
// 返回参数
type MwRoleListResp struct {
// 总共数量
TotalCount int64 `json:"totalCount"`
// 当前页配置记录
RoleRecs []*MwRoleRec `json:"roleRecs"`
}
/******************角色添加***********************/
// POST /web/role/add
// 请求参数
type MwRoleAddReq struct {
// 名称
Name string `json:"name"`
// 描述
Desc string `json:"desc"`
// 状态
IsEnb bool `json:"isEnb"`
}
// 返回参数
type MwRoleAddResp struct {
// 是否成功 true:成功 false:未成功
Result bool `json:"result,omitempty"`
}
/******************角色删除***********************/
// POST /web/role/del
// 请求参数
type MwRoleDelReq struct {
// 角色id
Id int64 `json:"id,omitempty"`
}
// 返回参数
type MwRoleDelResp struct {
// 是否成功 true:成功 false:未成功
Result bool `json:"result,omitempty"`
}
/******************角色获取信息***********************/
// GET /web/role/getinfo
// 请求参数
type MwRoleGetInfoReq struct {
// 角色id
Id int64 `form:"id" json:"id,omitempty"`
}
// 返回参数
type MwRoleGetInfoResp struct {
RoleRec *MwRoleRec `json:"roleRec"`
}
/******************角色更新***********************/
// POST /web/role/up
// 请求参数
type MwRoleUpReq struct {
// 角色id
Id int64 `json:"id"`
// 名称
Name string `json:"name"`
// 描述
Desc string `json:"desc"`
// 状态
IsEnb bool `json:"isEnb"`
}
// 返回参数
type MwRoleUpResp struct {
// 是否成功 true:成功 false:未成功
Result bool `json:"result,omitempty"`
}
/******************角色使能***********************/
// POST /web/role/enable
// 请求参数
type MwRoleEnableReq struct {
// 角色id
Id int64 `json:"id"`
// 状态
IsEnb bool `json:"isEnb"`
}
// 返回参数
type MwRoleEnableResp struct {
// 是否成功 true:成功 false:未成功
Result bool `json:"result,omitempty"`
}
/******************角色下拉***********************/
// GET /web/role/drop
// 请求参数
type MwRoleDrop struct {
// 角色Id
Id int64 `json:"id,omitempty"`
// 角色名称
Name string `json:"name,omitempty"`
}
// 返回参数
type MwRoleDropResp struct {
// 是否成功 true:成功 false:未成功
RoleDrop []*MwRoleDrop `json:"roleDrop"`
}
/******************获取权限***********************/
// GET /web/role/getauth
type Router_Meta struct {
//
Title string `json:"title"`
//
Icon string `json:"icon"`
//
NoCache bool `json:"noCache"`
}
type Router_ApiUrl struct {
//
Url []string `json:"url,omitempty"`
//
Desc string `json:"desc,omitempty"`
//
Status bool `json:"status,omitempty"`
//
Method []string `json:"method,omitempty"`
}
type Router struct {
//
Path string `json:"path"`
//
Component string `json:"component"`
//
Redirect string `json:"redirect"`
//
Name string `json:"name"`
//
IsShow bool `json:"isShow"`
//
Hidden bool `json:"hidden"`
//
Meta *Router_Meta `json:"meta"`
//
Children []*Router `json:"children"`
ApiUrl []*Router_ApiUrl `json:"apiUrl"`
}
// 请求参数
type MwRoleGetAuthReq struct {
// 角色id
Id int64 `form:"id" json:"id,omitempty"`
}
// 返回参数
type MwRoleGetAuthResp struct {
// 角色id
Id int64 `json:"id,omitempty"`
//
Router []*Router `json:"router,omitempty"`
}
/******************更新权限***********************/
// POST /web/role/upauth
// 请求参数
type MwRoleUpAuthReq struct {
// 角色id
Id int64 `json:"id,omitempty"`
Router []*Router `json:"router,omitempty"`
}
// 返回参数
type MwRoleUpAuthResp struct {
// 是否成功 true:成功 false:未成功
Result bool `json:"result,omitempty"`
}
/////////////////////////账号//////////////////////////
type MwAccRec struct {
// 账号Id
Id int64 `json:"id"`
// 用户名
UserName string `json:"userName"`
// 账号
Acc string `json:"acc"`
// 密码
Pwd string `json:"pwd"`
// 邮箱
Email string `json:"email"`
// 角色Id
RoleId int64 `json:"roleId"`
// 角色名
RoleName string `json:"roleName"`
// // 二步签名
// Base32 string `json:"base32"`
// 是否已签名
IsBase32 bool `json:"isBase32"`
// 使能
IsEnb bool `json:"isEnb"`
//禁用原因
FeedBack string `json:"feedBack"`
// 创建时间
CreatedAt int64 `json:"createdAt"`
// 更新时间
UpdatedAt int64 `json:"updatedAt"`
// 允许访问的IP
LimitIP []string `json:"limitIP"`
}
/******************账号列表***********************/
// GET /web/acc/list
// 请求参数
type MwAccListReq struct {
// 搜索条件
KeyWords string `json:"keyWords" form:"keyWords"`
//状态 1正常 2 禁用
Status int64 `json:"status" form:"status"`
// 页码
pubdef.Page
}
// 返回参数
type MwAccListResp struct {
// 总共数量
TotalCount int64 `json:"totalCount"`
// 当前页配置记录
AccRec []*MwAccRec `json:"accRec"`
}
/******************账号添加***********************/
// POST /web/acc/add
// 请求参数
type MwAccAddReq struct {
// 名称
Name string `json:"name"`
// 密码
Pwd string `json:"pwd"`
// 账户
Acc string `json:"acc"`
// 邮箱
Email string `json:"email"`
// 角色ID
RoleId int64 `json:"roleId"`
// 使能
IsEnb bool `json:"isEnb"`
// 允许访问的IP
LimitIP []string `json:"limitIP"`
}
type MwAccAddResp struct {
// 是否成功 true:成功 false:未成功
Result bool `json:"result,omitempty"`
}
/******************账号删除***********************/
// POST web/mw/acc/del
// 请求参数
type MwAccDelReq struct {
// 账号Id
Id int64 `json:"id,omitempty"`
}
// 返回参数
type MwAccDelResp struct {
// 是否成功 true:成功 false:未成功
Result bool `json:"result,omitempty"`
}
/******************账号获取信息***********************/
// GET /web/acc/getinfo
// 请求参数
type MwAccGetInfoReq struct {
// 角色id
Id int64 `form:"id" json:"id,omitempty"`
}
// 返回参数
type MwAccGetInfoResp struct {
// 账号Id
Id int64 `json:"id"`
// 用户名
UserName string `json:"userName"`
// 账号
Acc string `json:"acc"`
// 密码
Pwd string `json:"pwd"`
// 邮箱
Email string `json:"email"`
// 角色Id
RoleId int64 `json:"roleId"`
// 使能
IsEnb bool `json:"isEnb"`
// 允许访问的IP
LimitIP []string `json:"limitIP"`
}
/******************角色更新***********************/
// POST web/mw/acc/up
// 请求参数
type MwAccUpReq struct {
// 账号Id
Id int64 `json:"id"`
// 用户名
UserName string `json:"userName"`
// 账号
Acc string `json:"acc"`
// 密码
Pwd string `json:"pwd"`
// 邮箱
Email string `json:"email"`
// 角色Id
RoleId int64 `json:"roleId"`
// 使能
IsEnb bool `json:"isEnb"`
// 允许访问的IP
LimitIP []string `json:"limitIP"`
}
// 返回参数
type MwAccUpResp struct {
// 是否成功 true:成功 false:未成功
Result bool `json:"result,omitempty"`
}
/******************账号获取状态***********************/
// GET web/mw/acc/getstatus
// 请求参数
type MwAccGetStatusReq struct {
// 角色id
Id int64 `form:"id" json:"id,omitempty"`
}
// 返回参数
type MwAccGetStatusResp struct {
// 账号Id
Id int64 `json:"id"`
// 用户名
UserName string `json:"userName"`
// 使能
IsEnb bool `json:"isEnb"`
//禁用原因
FeedBack string `json:"feedBack"`
}
/******************账号保存状态***********************/
// POST web/mw/acc/savestatus
// 请求参数
type MwAccSaveStatusReq struct {
// 账号Id
Id int64 `json:"id"`
// 用户名
UserName string `json:"userName"`
// 使能
IsEnb bool `json:"isEnb"`
//禁用原因
FeedBack string `json:"feedBack"`
}
// 返回参数
type MwAccSaveStatusResp struct {
// 是否成功 true:成功 false:未成功
Result bool `json:"result,omitempty"`
}
/******************获取账号操作列表***********************/
// POST web/acc/ops
// 请求参数
type AccOpLogReq struct {
srv_acc.OpLogSearch
}
// AccOpLogResp 返回参数
type AccOpLogResp struct {
Total int64 `json:"total" bson:"total"`
List []*srv_acc.OpLogInfo `json:"list" bson:"list"`
}
// 修改账号密码
type MwAccUpPwdReq struct {
// 账号Id
Id int64 `json:"id" binding:"required"`
// 密码
Pwd string `json:"pwd"`
}
type MwAccUpPwdResp struct {
// 是否成功 true:成功 false:未成功
Result bool `json:"result,omitempty"`
}
+400
View File
@@ -0,0 +1,400 @@
package web_acc
import (
"videoweb/pub/common"
"videoweb/pub/common/pageopt"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/mwacc"
"videoweb/pub/pubdef"
"videoweb/web/service/srv_mwacc"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
)
// @Tags 角色
// @Summary 角色-列表
// @Description 角色-列表
// @Accept json
// @Produce json
// @Param param body pubdef.Page true "参数列表"
// @Success 200 {object} MwRoleListResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/role/list [GET]
func RoleGetList(c *gin.Context) {
var req pubdef.Page
if err := c.ShouldBindQuery(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
if req.PageNum <= 0 {
req.PageNum = 1
}
if req.PageSize <= 0 {
req.PageSize = 10
}
skip := (req.PageNum - 1) * req.PageSize
limit := req.PageSize
// 获取分页信息
var mats []pageopt.Matcher
dbRoleRec, err := mwacc.GetRoleList(c, skip, limit, mats...)
if err != nil {
common.ServerJSON(c, srvdef.Failure, "")
return
}
// 获取总条数
roleCount, err := mwacc.RoleCountByFilter(c, bson.M{})
if err != nil {
common.ServerJSON(c, srvdef.Failure, "")
return
}
webRoleRec := make([]*MwRoleRec, 0)
for _, v := range dbRoleRec {
webRoleRec = append(webRoleRec, &MwRoleRec{
Id: v.Id,
Name: v.Name,
Desc: v.Desc,
IsEnb: v.IsEnb,
ApiMenus: v.ApiMenus[:],
CreatedAt: v.CreatedAt,
UpdatedAt: v.UpdatedAt,
})
}
// 返回正确信息
common.ServerJSON(c, srvdef.Success, MwRoleListResp{TotalCount: roleCount, RoleRecs: webRoleRec})
return
}
// @Tags 角色
// @Summary 角色-添加
// @Description 角色-添加
// @Accept json
// @Produce json
// @Param param body MwRoleAddReq true "参数列表"
// @Success 200 {object} MwRoleAddResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/role/add [POST]
func RoleAdd(c *gin.Context) {
var req MwRoleAddReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
ok, _ := mwacc.RoleAdd(c, req.Name, req.Desc, req.IsEnb)
if !ok {
common.ServerJSON(c, srvdef.Failure, "")
return
}
// 返回正确信息
common.ServerJSON(c, srvdef.Success, MwRoleAddResp{Result: true})
return
}
// @Tags 角色
// @Summary 角色-删除
// @Description 角色-删除
// @Accept json
// @Produce json
// @Param param body MwRoleDelReq true "参数列表"
// @Success 200 {object} MwRoleDelResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/role/del [POST]
func RoleDel(c *gin.Context) {
var req MwRoleDelReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
ok, err := srv_mwacc.RoleDel(c, req.Id)
if !ok {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
common.ServerJSON(c, srvdef.Success, MwRoleDelResp{Result: true})
return
}
// @Tags 角色
// @Summary 角色-获取信息
// @Description 角色-获取信息
// @Accept json
// @Produce json
// @Param param body MwRoleGetInfoReq true "参数列表"
// @Success 200 {object} MwRoleGetInfoResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/role/getinfo [GET]
func RoleGetInfo(c *gin.Context) {
var req MwRoleGetInfoReq
if err := c.ShouldBindQuery(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
roleInfo, err := srv_mwacc.RoleGetInfo(c, req.Id)
if err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
resq := &MwRoleGetInfoResp{
RoleRec: &MwRoleRec{
Id: roleInfo.Id,
Name: roleInfo.Name,
Desc: roleInfo.Desc,
IsEnb: roleInfo.IsEnb,
ApiMenus: roleInfo.ApiMenus[:],
CreatedAt: roleInfo.CreatedAt,
UpdatedAt: roleInfo.UpdatedAt,
},
}
common.ServerJSON(c, srvdef.Success, resq)
return
}
// @Tags 角色
// @Summary 角色-更新
// @Description 角色-更新
// @Accept json
// @Produce json
// @Param param body MwRoleUpReq true "参数列表"
// @Success 200 {object} MwRoleUpResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/role/up [POST]
func RoleUp(c *gin.Context) {
var req MwRoleUpReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
// RoleUp
_, err := srv_mwacc.RoleUp(c, req.Id, req.Name, req.Desc, req.IsEnb)
if err != nil {
common.ServerJSON(c, srvdef.Failure, MwRoleUpResp{Result: false})
return
}
common.ServerJSON(c, srvdef.Success, MwRoleUpResp{Result: true})
return
}
// @Tags 角色
// @Summary 角色-使能
// @Description 角色-使能
// @Accept json
// @Produce json
// @Param param body MwRoleEnableReq true "参数列表"
// @Success 200 {object} MwRoleEnableResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/role/enable [POST]
func RoleEnable(c *gin.Context) {
var req MwRoleEnableReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
_, err := srv_mwacc.RoleEnable(c, req.Id, req.IsEnb)
if err != nil {
common.ServerJSON(c, err.Code, err.Msg)
return
}
common.ServerJSON(c, srvdef.Success, MwRoleEnableResp{Result: true})
return
}
// @Tags 角色
// @Summary 角色-下拉列表
// @Description 角色-下拉列表
// @Accept json
// @Produce json
// @Success 200 {object} MwRoleDropResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/role/drop [POST]
func RoleGetDrop(c *gin.Context) {
data, _ := mwacc.RoleDrop(c)
roleDropArr := make([]*MwRoleDrop, 0)
for _, v := range data {
roleDropArr = append(roleDropArr, &MwRoleDrop{Id: v.Id, Name: v.Name})
}
common.ServerJSON(c, srvdef.Success, MwRoleDropResp{RoleDrop: roleDropArr})
return
}
func DbRouterToWebRouter(dbRouter *mwacc.Router) (webRouter *Router) {
if dbRouter == nil {
return
}
webRouter = &Router{
Path: dbRouter.Path,
Component: dbRouter.Component,
Redirect: dbRouter.Redirect,
Name: dbRouter.Name,
IsShow: dbRouter.IsShow,
Hidden: dbRouter.Hidden,
Meta: &Router_Meta{
Title: dbRouter.Meta.Title,
Icon: dbRouter.Meta.Icon,
NoCache: dbRouter.Meta.NoCache,
},
Children: make([]*Router, 0),
ApiUrl: make([]*Router_ApiUrl, 0),
}
for _, v := range dbRouter.Children {
webRouter.Children = append(webRouter.Children, DbRouterToWebRouter(&v))
}
for _, v := range dbRouter.ApiUrl {
webRouter.ApiUrl = append(webRouter.ApiUrl, &Router_ApiUrl{
Url: v.Url[:],
Desc: v.Desc,
Status: v.Status,
Method: v.Method[:],
})
}
return
}
// @Tags 角色
// @Summary 角色-获取权限
// @Description 角色-获取权限
// @Accept json
// @Produce json
// @Param param body MwRoleGetAuthReq true "参数列表"
// @Success 200 {object} MwRoleGetAuthResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/role/getauth [GET]
func RoleGetAuth(c *gin.Context) {
var req MwRoleGetAuthReq
if err := c.ShouldBindQuery(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
roleInfo, err := srv_mwacc.RoleGetInfo(c, req.Id)
if err != nil {
common.ServerJSON(c, srvdef.Failure, err.Error())
return
}
if roleInfo == nil {
common.ServerJSON(c, srvdef.Failure, "没找到角色")
return
}
if roleInfo.Id == 0 {
common.ServerJSON(c, srvdef.Failure, "没找到角色2")
return
}
resq := &MwRoleGetAuthResp{
Id: req.Id,
Router: make([]*Router, 0),
}
for _, v := range roleInfo.Router {
resq.Router = append(resq.Router, DbRouterToWebRouter(&v))
}
common.ServerJSON(c, srvdef.Success, resq)
return
}
// 网站Router转数据库Router
func WebRouterToDbRouter(webRouter *Router) (dbRouter *mwacc.Router) {
if webRouter == nil {
return
}
dbRouter = &mwacc.Router{
Path: webRouter.Path,
Component: webRouter.Component,
Redirect: webRouter.Redirect,
Name: webRouter.Name,
IsShow: webRouter.IsShow,
Hidden: webRouter.Hidden,
Meta: mwacc.Meta{
Title: webRouter.Meta.Title,
Icon: webRouter.Meta.Icon,
NoCache: webRouter.Meta.NoCache,
},
Children: make([]mwacc.Router, 0),
ApiUrl: make([]mwacc.Apiurl, 0),
}
for _, v := range webRouter.Children {
dbRouter.Children = append(dbRouter.Children, *WebRouterToDbRouter(v))
}
for _, v := range webRouter.ApiUrl {
dbRouter.ApiUrl = append(dbRouter.ApiUrl, mwacc.Apiurl{
Url: v.Url[:],
Desc: v.Desc,
Status: v.Status,
Method: v.Method[:],
})
}
return
}
// @Tags 角色
// @Summary 角色-更新权限
// @Description 角色-更新权限
// @Accept json
// @Produce json
// @Param param body MwRoleUpAuthReq true "参数列表"
// @Success 200 {object} MwRoleUpAuthResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/role/upauth [GET]
func RoleUpAuth(c *gin.Context) {
var req MwRoleUpAuthReq
if err := c.ShouldBindJSON(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
dataSave := make([]*mwacc.Router, 0)
for _, v := range req.Router {
dataSave = append(dataSave, WebRouterToDbRouter(v))
}
_, err := srv_mwacc.UpAuth(c, req.Id, dataSave)
if err != nil {
common.ServerJSON(c, srvdef.Failure, MwRoleUpAuthResp{Result: false})
return
}
// auth.ClearRoleMap()
common.ServerJSON(c, srvdef.Success, MwRoleUpAuthResp{Result: true})
return
}
+109
View File
@@ -0,0 +1,109 @@
package web_actress
import (
"github.com/gin-gonic/gin"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_actress"
)
// @Tags 女优管理
// @Summary 分组分页获取女优信息
// @Description 分组分页获取女优信息
// @Accept json
// @Produce json
// @Param param body srv_actress.ActressListReq true "参数列表"
// @Success 200 {object} srv_actress.ActressListResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/actress/list [GET]
func Get(ctx *gin.Context) {
var req = &srv_actress.ActressListReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_actress.ActressList(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 女优管理
// @Summary 添加一个女优信息
// @Description 添加一个女优信息
// @Accept json
// @Produce json
// @Param param body srv_actress.ActressAddReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/actress/add [POST]
func Add(ctx *gin.Context) {
var req = &srv_actress.ActressAddReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_actress.AddActress(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 女优管理
// @Summary 删除一个女优信息
// @Description 删除一个女优信息
// @Accept json
// @Produce json
// @Param param body srv_actress.ActressDelReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/actress/del [POST]
func Del(ctx *gin.Context) {
var req = &srv_actress.ActressDelReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_actress.DeleteActress(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 女优管理
// @Summary 更新一个女优信息
// @Description 更新一个女优信息
// @Accept json
// @Produce json
// @Param param body srv_actress.ActressUpdateReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/actress/update [POST]
func Update(ctx *gin.Context) {
var req = &srv_actress.ActressUpdateReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_actress.UpdateActress(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+155
View File
@@ -0,0 +1,155 @@
package webanalytics
import (
"time"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/pub/common/utils"
"videoweb/pub/models/analyticsdailystat"
"videoweb/pub/models/analyticsstat"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
)
// @Tags 获取统计数据
// @Summary 统计数据
// @Description 统计数据
// @Accept json
// @Produce json
// @Success 200 {object} srv_translationcategory.TranslationCategoryResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/stat/analytics [POST]
func GetAnalyticsStat(ctx *gin.Context) {
// 当日数据
resp := AnalyticsStat{
TodayList: make([]LastWebStatInfo, 0),
WeekList: make([]LastWebStatInfo, 0),
YestodayList: make([]LastWebStatInfo, 0),
}
now := time.Now()
curStatTime := utils.RecentMinute(now, 30) // 按20分钟对齐
YestodayTime := curStatTime.AddDate(0, 0, -1)
WeekTime := curStatTime.AddDate(0, 0, -7)
dailyFilter := bson.M{
analyticsdailystat.FN.AnalyticsDailyInfo.SumDate: bson.M{"$gt": now.AddDate(0, -1, -1)},
}
dailyStatList, _ := analyticsdailystat.FindManyAnalyticsDailyInfo(ctx, dailyFilter)
curFilter := bson.M{
analyticsstat.FN.AnalyticsInfo.SumDate: curStatTime,
}
statList, _ := analyticsstat.FindManyAnalyticsInfo(ctx, curFilter)
for _, statInfo := range statList {
appStatInfo := LastWebStatInfo{
SumDate: statInfo.SumDate,
AppId: statInfo.AppId,
AppName: statInfo.AppName,
ActiveUsers: statInfo.ActiveUsers,
YestodayPV: statInfo.YestodayPV,
YestodayUV: statInfo.YestodayUV,
YestodayActiveUsers: statInfo.YestodayActiveUsers,
YestodaySessions: statInfo.YestodaySessions,
YestodayNewUsers: statInfo.YestodayNewUsers,
}
for _, dailyStatInfo := range dailyStatList {
if dailyStatInfo.SumDate.Equal(statInfo.DaySumDate) && dailyStatInfo.AppId == statInfo.AppId {
appStatInfo.LeadNewCount = dailyStatInfo.LeadNewCount
appStatInfo.LeadAmount = dailyStatInfo.LeadAmount
}
}
resp.TodayList = append(resp.TodayList, appStatInfo)
}
yesFilter := bson.M{
analyticsstat.FN.AnalyticsInfo.SumDate: YestodayTime,
}
statList, _ = analyticsstat.FindManyAnalyticsInfo(ctx, yesFilter)
for _, statInfo := range statList {
appStatInfo := LastWebStatInfo{
SumDate: statInfo.SumDate,
AppId: statInfo.AppId,
AppName: statInfo.AppName,
ActiveUsers: statInfo.ActiveUsers,
YestodayPV: statInfo.YestodayPV,
YestodayUV: statInfo.YestodayUV,
YestodayActiveUsers: statInfo.YestodayActiveUsers,
YestodaySessions: statInfo.YestodaySessions,
YestodayNewUsers: statInfo.YestodayNewUsers,
}
for _, dailyStatInfo := range dailyStatList {
if dailyStatInfo.SumDate.Equal(statInfo.DaySumDate) && dailyStatInfo.AppId == statInfo.AppId {
appStatInfo.LeadNewCount = dailyStatInfo.LeadNewCount
appStatInfo.LeadAmount = dailyStatInfo.LeadAmount
}
}
resp.YestodayList = append(resp.YestodayList, appStatInfo)
}
weekFilter := bson.M{
analyticsstat.FN.AnalyticsInfo.SumDate: WeekTime,
}
statList, _ = analyticsstat.FindManyAnalyticsInfo(ctx, weekFilter)
for _, statInfo := range statList {
appStatInfo := LastWebStatInfo{
SumDate: statInfo.SumDate,
AppId: statInfo.AppId,
AppName: statInfo.AppName,
ActiveUsers: statInfo.ActiveUsers,
YestodayPV: statInfo.YestodayPV,
YestodayUV: statInfo.YestodayUV,
YestodayActiveUsers: statInfo.YestodayActiveUsers,
YestodaySessions: statInfo.YestodaySessions,
YestodayNewUsers: statInfo.YestodayNewUsers,
}
for _, dailyStatInfo := range dailyStatList {
if dailyStatInfo.SumDate.Equal(statInfo.DaySumDate) && dailyStatInfo.AppId == statInfo.AppId {
appStatInfo.LeadNewCount = dailyStatInfo.LeadNewCount
appStatInfo.LeadAmount = dailyStatInfo.LeadAmount
}
}
resp.WeekList = append(resp.WeekList, appStatInfo)
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 获取统计数据
// @Summary 统计数据
// @Description 统计数据
// @Accept json
// @Produce json
// @Success 200 {object} srv_translationcategory.TranslationCategoryResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/stat/daily/analytics [POST]
func GetAnalyticsDailyStat(ctx *gin.Context) {
// 当日数据
resp := AnalyticsDailyStat{
List: make([]LastWebStatInfo, 0),
}
now := time.Now()
curFilter := bson.M{
analyticsdailystat.FN.AnalyticsDailyInfo.SumDate: bson.M{"$gt": utils.BeginOfMonth(now.AddDate(0, 0, -1)), "$lte": now},
}
statList, _ := analyticsdailystat.FindManyAnalyticsDailyInfo(ctx, curFilter)
for _, statInfo := range statList {
appStatInfo := LastWebStatInfo{
SumDate: statInfo.SumDate,
AppId: statInfo.AppId,
AppName: statInfo.AppName,
YestodayPV: statInfo.YestodayPV,
YestodayUV: statInfo.YestodayUV,
YestodayActiveUsers: statInfo.YestodayActiveUsers,
YestodaySessions: statInfo.YestodaySessions,
YestodayNewUsers: statInfo.YestodayNewUsers,
LeadNewCount: statInfo.LeadNewCount,
LeadAmount: statInfo.LeadAmount,
}
resp.List = append(resp.List, appStatInfo)
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
+26
View File
@@ -0,0 +1,26 @@
package webanalytics
import "time"
type LastWebStatInfo struct {
SumDate time.Time `json:"sumDate" bson:"sumDate"` // 时间半小时
AppName string `json:"appName" bson:"appName"` // APP名称
AppId int64 `json:"appId" bson:"appId"` // appId
ActiveUsers int64 `json:"activeUsers" bson:"activeUsers"` // 最近半小时活跃数
YestodayPV int64 `json:"yestodayPV" bson:"yestodayPV"` // 页面浏览量 (PV)
YestodayUV int64 `json:"yestodayUV" bson:"yestodayUV"` // 独立用户数 (UV)
YestodayActiveUsers int64 `json:"yestodayActiveUsers" bson:"yestodayActiveUsers"` // 活跃用户数
YestodaySessions int64 `json:"yestodaySessions" bson:"yestodaySessions"` // 会话数
YestodayNewUsers int64 `json:"yestodayNewUsers" bson:"yestodayNewUsers"` // 新增数量
LeadNewCount float64 `json:"leadNewCount" bson:"leadNewCount"` // 日导量新增
LeadAmount float64 `json:"leadAmount" bson:"leadAmount"` // 日导量充值
}
type AnalyticsStat struct {
TodayList []LastWebStatInfo `json:"todayList"` //当日数据
WeekList []LastWebStatInfo `json:"weekList"` //环比数据
YestodayList []LastWebStatInfo `json:"yestodayList"` //同比数据
}
type AnalyticsDailyStat struct {
List []LastWebStatInfo `json:"list"` //当月数据
}
+109
View File
@@ -0,0 +1,109 @@
package web_announcement
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_announcement"
"github.com/gin-gonic/gin"
)
// AnnouncementList
// @Tags 公告
// @Summary 公告-列表 --by 王鸣
// @Description 公告-列表
// @Accept json
// @Produce json
// @Param param body srv_announcement.GetAnnouncementListReq true "参数列表"
// @Success 200 {object} srv_announcement.GetAnnouncementListResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/announcement/list [POST]
func AnnouncementList(c *gin.Context) {
var req srv_announcement.GetAnnouncementListReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
resp, serr := srv_announcement.GetAnnouncementList(c, &req)
if serr != nil {
common.ServerJSON(c, serr.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, resp)
}
// AnnouncementAdd
// @Tags 公告
// @Summary 公告-增加 --by 王鸣
// @Description 公告-增加
// @Accept json
// @Produce json
// @Param param body srv_announcement.AddAnnouncementReq true "参数列表"
// @Success 200 {object} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/announcement/add [POST]
func AnnouncementAdd(c *gin.Context) {
var req srv_announcement.AddAnnouncementReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
serr := srv_announcement.AddAnnouncement(c, &req)
if serr != nil {
common.ServerJSON(c, serr.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, "")
}
// AnnouncementDel
// @Tags 公告
// @Summary 公告-删除 --by 王鸣
// @Description 公告-删除
// @Accept json
// @Produce json
// @Param param body srv_announcement.DelAnnouncementReq true "参数列表"
// @Success 200 {object} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/announcement/del [POST]
func AnnouncementDel(c *gin.Context) {
var req srv_announcement.DelAnnouncementReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
serr := srv_announcement.DelAnnouncement(c, &req)
if serr != nil {
common.ServerJSON(c, serr.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, "")
}
// AnnouncementUpdate
// @Tags 公告
// @Summary 公告-更新 --by 王鸣
// @Description 公告-更新
// @Accept json
// @Produce json
// @Param param body srv_announcement.UpdateAnnouncementReq true "参数列表"
// @Success 200 {object} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/announcement/update [POST]
func AnnouncementUpdate(c *gin.Context) {
var req srv_announcement.UpdateAnnouncementReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
serr := srv_announcement.UpdateAnnouncement(c, &req)
if serr != nil {
common.ServerJSON(c, serr.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, "")
}
+78
View File
@@ -0,0 +1,78 @@
package web_app
import (
"github.com/gin-gonic/gin"
"videoweb/pub/common"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"videoweb/pub/pubdef"
"videoweb/web/service/srv_app"
)
func AppSyncReq(c *gin.Context) {
var in srv_app.AppVideoInfoSyncReq
if err := c.ShouldBindJSON(&in); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, nil)
return
}
if in.AppId != pubdef.AppId {
common.ServerJSON(c, srvdef.APPIDError, nil)
}
data, err := srv_app.AppVideoInfoSync(c, &in)
if err != nil {
log.Error("AppSyncReq AppVideoInfoSyncReq Failed", log.Any("err", err))
common.ServerJSON(c, err.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, data)
}
func AppCollectionSyncReq(c *gin.Context) {
var in srv_app.AppVideoCollectionSyncReq
if err := c.ShouldBindJSON(&in); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, nil)
return
}
if in.AppId != pubdef.AppId {
common.ServerJSON(c, srvdef.APPIDError, nil)
}
data, err := srv_app.AppVideoCollectionSync(c, &in)
if err != nil {
log.Error("AppCollectionSyncReq AppVideoCollectionSync Failed", log.Any("err", err))
common.ServerJSON(c, err.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, data)
}
func AppGetVideoCategory(c *gin.Context) {
data, err := srv_app.AppCategoryList(c)
if err != nil {
log.Error("AppGetVideoCategory AppCategoryList Failed", log.Any("err", err))
common.ServerJSON(c, err.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, data)
}
func AppGetVideoCreator(c *gin.Context) {
data, err := srv_app.AppCreatorList(c)
if err != nil {
log.Error("AppGetVideoCreator AppCategoryList Failed", log.Any("err", err))
common.ServerJSON(c, err.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, data)
}
func AppGetVideoTag(c *gin.Context) {
data, err := srv_app.AppTagList(c)
if err != nil {
log.Error("AppGetVideoTag AppCategoryList Failed", log.Any("err", err))
common.ServerJSON(c, err.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, data)
}
+75
View File
@@ -0,0 +1,75 @@
package web_cfg
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_cfg"
"github.com/gin-gonic/gin"
)
// @Tags 系统配置
// @Summary 获取系统配置
// @Description 获取系统配置
// @Accept json
// @Produce json
// @Param param body GetSysConfigReq true "参数列表"
// @Success 200 {object} GetSysConfigResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/syscfg/get [GET]
func GetCfg(ctx *gin.Context) {
config, err := srv_cfg.GetSystemConfig(ctx)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Error())
return
}
resp := &GetSysConfigResp{config}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 系统配置
// @Summary 修改系统配置
// @Description 修改系统配置
// @Accept json
// @Produce json
// @Param param body SysConfigUpdateReq true "参数列表"
// @Success 200 {object} SysConfigUpdateResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/syscfg/update [POST]
func UpdateCfg(ctx *gin.Context) {
var req SysConfigUpdateReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
if err := srv_cfg.UpdateSystemConfig(ctx, &req.SysCfgUpdate); err != nil {
common.ServerJSON(ctx, err.Code, err.Error())
return
}
common.ServerJSON(ctx, srvdef.Success, &SysConfigUpdateResp{})
}
// @Tags 系统配置
// @Summary 设置媒资库 appKey
// @Description 单独设置 sys_cfg.appKey,并刷新内存缓存
// @Accept json
// @Produce json
// @Param param body SetAppKeyReq true "参数列表"
// @Success 200 {object} SetAppKeyResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/syscfg/appkey [POST]
func SetAppKey(ctx *gin.Context) {
var req SetAppKeyReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
if err := srv_cfg.SetAppKey(ctx, req.AppKey); err != nil {
common.ServerJSON(ctx, err.Code, err.Error())
return
}
common.ServerJSON(ctx, srvdef.Success, &SetAppKeyResp{})
}
+24
View File
@@ -0,0 +1,24 @@
package web_cfg
import (
"videoweb/pub/models/cfg"
"videoweb/web/service/srv_cfg"
)
type GetSysConfigReq struct {
}
type GetSysConfigResp struct {
*cfg.SysCfg
}
type SysConfigUpdateReq struct {
srv_cfg.SysCfgUpdate
}
type SysConfigUpdateResp struct{}
type SetAppKeyReq struct {
AppKey string `json:"appKey"` // 媒资库 appKey
}
type SetAppKeyResp struct{}
+174
View File
@@ -0,0 +1,174 @@
package web_commend
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_commend"
"github.com/gin-gonic/gin"
)
// SearchManyCommend
// @Tags 评论
// @Summary 评论列表
// @Description 评论列表
// @Accept json
// @Produce json
// @Param param body srv_commend.CommendSearch true "参数列表"
// @Success 200 {object} srv_commend.CommendSearchResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/web/post/comment/list [POST]
func SearchManyCommend(ctx *gin.Context) {
var req = &srv_commend.CommendSearch{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_commend.SearchComandList(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
type CommendDelReq struct {
Id int64 `json:"id" binding:"required"`
}
type CommendDelIpReq struct {
Ip string `json:"ip"`
}
// DelCommend
// @Tags 评论
// @Summary 删除一个评论
// @Description 删除一个评论
// @Accept json
// @Produce json
// @Param param body CommendDelReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Router /api/web/post/comment/del [POST]
func DelCommend(ctx *gin.Context) {
var req = &CommendDelReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_commend.DelCommend(ctx, req.Id)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, nil)
}
// DelUserCommend
// @Tags 评论
// @Summary 删除一个用户所有评论
// @Description 删除一个用户所有评论
// @Accept json
// @Produce json
// @Param param body CommendDelIpReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Router /api/web/post/comment/user/del [POST]
func DelUserCommend(ctx *gin.Context) {
var req = &CommendDelIpReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_commend.DelUserCommend(ctx, req.Ip)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, nil)
}
// ReplayPostComment
// @Tags 评论
// @Summary 回复评论
// @Description 回复评论
// @Accept json
// @Produce json
// @Param param body srv_commend.CommendReplay true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Router /api/web/post/comment/replay [POST]
func ReplayPostComment(ctx *gin.Context) {
var req = &srv_commend.CommendReplay{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_commend.AddPostComment(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, nil)
}
type CommendReviewBatchReq struct {
Ids *[]int64 `json:"ids"`
ReviewStatus int `json:"reviewStatus"`
}
// ReviewCommendBatch
// @Tags 评论
// @Summary 批量审核评论
// @Description 批量审核评论
// @Accept json
// @Produce json
// @Param param body CommendReviewBatchReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/post/comment/reviewBatch [POST]
func ReviewCommendBatch(ctx *gin.Context) {
var req = &CommendReviewBatchReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_commend.ReviewCommendBatch(ctx, req.Ids, req.ReviewStatus)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, nil)
}
// ReviewComment
// @Tags 评论
// @Summary 审核评论
// @Description 审核评论
// @Accept json
// @Produce json
// @Param param body srv_commend.CommendReviewReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/post/comment/review [POST]
func ReviewComment(ctx *gin.Context) {
var req = &srv_commend.CommendReviewReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_commend.ReviewComment(ctx, req.Id, req.ReviewStatus)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, nil)
}
+81
View File
@@ -0,0 +1,81 @@
package web_contactus
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_contactus"
"github.com/gin-gonic/gin"
)
// @Tags 联系我们
// @Summary 联系我们列表
// @Description 联系我们列表
// @Accept json
// @Produce json
// @Param param body srv_contactus.GetContactusListReq true "参数列表"
// @Success 200 {object} srv_contactus.GetContactusListResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/web/contactus/list [POST]
func ContactusList(ctx *gin.Context) {
var req = &srv_contactus.GetContactusListReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_contactus.GetContactusList(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 联系我们
// @Summary 删除一个联系我们
// @Description 删除一个联系我们
// @Accept json
// @Produce json
// @Param param body srv_contactus.DelOneContactusReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Router /api/web/contactus/del [POST]
func Del(ctx *gin.Context) {
var req = &srv_contactus.DelOneContactusReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_contactus.DelContactus(ctx, req.Id)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, nil)
}
// @Tags 联系我们
// @Summary 修改联系我们状态
// @Description 修改联系我们状态
// @Accept json
// @Produce json
// @Param param body srv_contactus.UpdateContactusReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/contactus/update [POST]
func Update(ctx *gin.Context) {
var req = &srv_contactus.UpdateContactusReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_contactus.UpdateContactus(ctx, req.Id, req.Status)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, nil)
}
+62
View File
@@ -0,0 +1,62 @@
package web_contentexcel
import (
"fmt"
"net/http"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_contentexcel"
"github.com/gin-gonic/gin"
)
// /api/web/contentexcel/export [GET]
func Export(ctx *gin.Context) {
req := &srv_contentexcel.ExportReq{}
if err := ctx.ShouldBindQuery(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
ids, serr := srv_contentexcel.ParseExportIDs(ctx.QueryArray("ids"))
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
if len(ids) > 0 {
req.Ids = ids
}
data, filename, serr := srv_contentexcel.Export(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
ctx.Header("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))
ctx.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", data)
}
// /api/web/contentexcel/import [POST]
func Import(ctx *gin.Context) {
contentType := ctx.PostForm("type")
fileHeader, err := ctx.FormFile("file")
if err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, "请上传 file 字段")
return
}
file, err := fileHeader.Open()
if err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
defer file.Close()
result, serr := srv_contentexcel.Import(ctx, contentType, file)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, result)
}
+131
View File
@@ -0,0 +1,131 @@
package web_contenttag
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/api/proto"
"videoweb/web/middleware/auth"
"videoweb/web/service/srv_contenttag"
"github.com/gin-gonic/gin"
)
// List 统一标签列表
// @Tags web统一标签相关接口
// @Summary 统一标签列表 -- by 王鸣
// @Description 分页查询统一标签配置
// @Accept json
// @Produce json
// @Param params query proto.ContentTagListReq true "统一标签列表请求"
// @Success 200 {object} proto.ContentTagListPageResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/content/tag/list [get]
func List(ctx *gin.Context) {
var req proto.ContentTagListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_contenttag.ListContentTag(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Option 统一标签下拉列表
// @Tags web统一标签相关接口
// @Summary 统一标签下拉列表 -- by 王鸣
// @Description 查询启用的统一标签下拉列表,传type时按支持类型过滤
// @Accept json
// @Produce json
// @Param params query proto.ContentTagOptionReq false "统一标签下拉列表请求"
// @Success 200 {object} proto.ContentTagOptionResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/content/tag/option [get]
func Option(ctx *gin.Context) {
var req proto.ContentTagOptionReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_contenttag.ListContentTagOption(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Add 新增统一标签
// @Tags web统一标签相关接口
// @Summary 新增统一标签 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.ContentTagAddReq true "新增统一标签请求"
// @Success 200 {object} proto.ContentTagAddResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/content/tag/add [post]
func Add(ctx *gin.Context) {
var req proto.ContentTagAddReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_contenttag.AddContentTag(ctx, &req, auth.GetAccount(ctx))
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Update 更新统一标签
// @Tags web统一标签相关接口
// @Summary 更新统一标签 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.ContentTagUpdateReq true "更新统一标签请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/content/tag/update [post]
func Update(ctx *gin.Context) {
var req proto.ContentTagUpdateReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_contenttag.UpdateContentTag(ctx, &req, auth.GetAccount(ctx)); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// Del 删除统一标签
// @Tags web统一标签相关接口
// @Summary 删除统一标签 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.ContentTagDelReq true "删除统一标签请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/content/tag/del [post]
func Del(ctx *gin.Context) {
var req proto.ContentTagDelReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_contenttag.DelContentTag(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+109
View File
@@ -0,0 +1,109 @@
package web_detailnav
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_detailnav"
"github.com/gin-gonic/gin"
)
// DetailNavList
// @Tags 详情页导航配置
// @Summary 详情页导航配置-列表
// @Description 详情页导航配置-列表
// @Accept json
// @Produce json
// @Param param body srv_detailnav.GetDetailNavListReq true "参数列表"
// @Success 200 {object} srv_detailnav.GetDetailNavListResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/detailnav/list [POST]
func DetailNavList(c *gin.Context) {
var req srv_detailnav.GetDetailNavListReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
resp, serr := srv_detailnav.GetDetailNavList(c, &req)
if serr != nil {
common.ServerJSON(c, serr.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, resp)
}
// DetailNavAdd
// @Tags 详情页导航配置
// @Summary 详情页导航配置-增加
// @Description 详情页导航配置-增加
// @Accept json
// @Produce json
// @Param param body srv_detailnav.AddDetailNavReq true "参数列表"
// @Success 200 {object} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/detailnav/add [POST]
func DetailNavAdd(c *gin.Context) {
var req srv_detailnav.AddDetailNavReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
serr := srv_detailnav.AddDetailNav(c, &req)
if serr != nil {
common.ServerJSON(c, serr.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, "")
}
// DetailNavDel
// @Tags 详情页导航配置
// @Summary 详情页导航配置-删除
// @Description 详情页导航配置-删除
// @Accept json
// @Produce json
// @Param param body srv_detailnav.DelDetailNavReq true "参数列表"
// @Success 200 {object} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/detailnav/del [POST]
func DetailNavDel(c *gin.Context) {
var req srv_detailnav.DelDetailNavReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
serr := srv_detailnav.DelDetailNav(c, &req)
if serr != nil {
common.ServerJSON(c, serr.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, "")
}
// DetailNavUpdate
// @Tags 详情页导航配置
// @Summary 详情页导航配置-更新
// @Description 详情页导航配置-更新
// @Accept json
// @Produce json
// @Param param body srv_detailnav.UpdateDetailNavReq true "参数列表"
// @Success 200 {object} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/detailnav/update [POST]
func DetailNavUpdate(c *gin.Context) {
var req srv_detailnav.UpdateDetailNavReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
serr := srv_detailnav.UpdateDetailNav(c, &req)
if serr != nil {
common.ServerJSON(c, serr.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, "")
}
+86
View File
@@ -0,0 +1,86 @@
package web_file
import (
"io/ioutil"
"videoweb/pub/common"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"videoweb/pub/storage"
"videoweb/pub/storage/proxy"
"github.com/gin-gonic/gin"
)
// @Tags 文件上传
// @Summary 图片上传
// @Description 图片上传
// @Accept json
// @Produce json
// @Param file formData file true "文件"
// @Success 200 {object}} UploadImageResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/web/file/uploadImg [POST]
func UploadImage(ctx *gin.Context) {
f, err := ctx.FormFile("file")
if err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
imageUpoadDomain := proxy.BucketImageAddressV2
p, err := storage.UploadImage(ctx, f, imageUpoadDomain)
if err != nil {
common.ServerJSON(ctx, srvdef.ServerError, err.Error())
return
}
resp := &UploadImageResp{Path: p}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 文件上传
// @Summary 图片批量上传
// @Description 图片批量上传
// @Accept json
// @Produce json
// @Param file[] formData file true "文件"
// @Success 200 {object}} UploadImagesResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/web/file/uploadImgs [POST]
func UploadImages(ctx *gin.Context) {
form, err := ctx.MultipartForm()
if err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
resp := &UploadImagesResp{
Paths: make([]string, 0),
}
domain := proxy.BucketImageAddressV2
files := form.File["file[]"]
for _, f := range files {
fi, err := f.Open()
defer func() {
_ = fi.Close()
}()
if err != nil {
log.Warn("headers Open file wrong ", log.Any("Error", err))
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
byteData, err := ioutil.ReadAll(fi)
if err != nil {
log.Warn("request multipart wrong ", log.Any("Error", err))
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
path, err := proxy.UploadImg(f.Filename, byteData, domain)
if err != nil {
log.Warn("request multipart wrong ", log.Any("Error", err))
common.ServerJSON(ctx, srvdef.UploadToFileSrvFailed, err.Error())
return
}
resp.Paths = append(resp.Paths, path)
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
+14
View File
@@ -0,0 +1,14 @@
package web_file
type UploadImageResp struct {
Path string `json:"path"`
}
type UploadImagesResp struct {
Paths []string `json:"paths"`
}
type UploadVideoBodyResp struct {
Id string `json:"id"` // 文件服返回的上传文件Id
VideoUri string `json:"videoUri"` // 文件服返回的视频uri
}
+106
View File
@@ -0,0 +1,106 @@
package web_homebanner
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/api/proto"
"videoweb/web/middleware/auth"
"videoweb/web/service/srv_homebanner"
"github.com/gin-gonic/gin"
)
// List 首页banner列表
// @Tags web首页banner相关接口
// @Summary 首页banner列表 -- by 王鸣
// @Description 分页查询首页banner配置
// @Accept json
// @Produce json
// @Param params query proto.HomeBannerListReq true "首页banner列表请求"
// @Success 200 {object} proto.HomeBannerListPageResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/home/banner/list [get]
func List(ctx *gin.Context) {
var req proto.HomeBannerListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_homebanner.ListHomeBanner(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Add 新增首页banner
// @Tags web首页banner相关接口
// @Summary 新增首页banner -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.HomeBannerAddReq true "新增首页banner请求"
// @Success 200 {object} proto.HomeBannerAddResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/home/banner/add [post]
func Add(ctx *gin.Context) {
var req proto.HomeBannerAddReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_homebanner.AddHomeBanner(ctx, &req, auth.GetAccount(ctx))
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Update 更新首页banner
// @Tags web首页banner相关接口
// @Summary 更新首页banner -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.HomeBannerUpdateReq true "更新首页banner请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/home/banner/update [post]
func Update(ctx *gin.Context) {
var req proto.HomeBannerUpdateReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_homebanner.UpdateHomeBanner(ctx, &req, auth.GetAccount(ctx)); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// Del 删除首页banner
// @Tags web首页banner相关接口
// @Summary 删除首页banner -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.HomeBannerDelReq true "删除首页banner请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/home/banner/del [post]
func Del(ctx *gin.Context) {
var req proto.HomeBannerDelReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_homebanner.DelHomeBanner(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+109
View File
@@ -0,0 +1,109 @@
package web_hotnav
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_hotnav"
"github.com/gin-gonic/gin"
)
// HotNavList
// @Tags 热门导航配置
// @Summary 热门导航配置-列表
// @Description 热门导航配置-列表
// @Accept json
// @Produce json
// @Param param body srv_hotnav.GetHotNavListReq true "参数列表"
// @Success 200 {object} srv_hotnav.GetHotNavListResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/hotnav/list [post]
func HotNavList(c *gin.Context) {
var req srv_hotnav.GetHotNavListReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
resp, serr := srv_hotnav.GetHotNavList(c, &req)
if serr != nil {
common.ServerJSON(c, serr.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, resp)
}
// HotNavAdd
// @Tags 热门导航配置
// @Summary 热门导航配置-增加
// @Description 热门导航配置-增加
// @Accept json
// @Produce json
// @Param param body srv_hotnav.AddHotNavReq true "参数列表"
// @Success 200 {object} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/hotnav/add [post]
func HotNavAdd(c *gin.Context) {
var req srv_hotnav.AddHotNavReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
serr := srv_hotnav.AddHotNav(c, &req)
if serr != nil {
common.ServerJSON(c, serr.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, "")
}
// HotNavDel
// @Tags 热门导航配置
// @Summary 热门导航配置-删除
// @Description 热门导航配置-删除
// @Accept json
// @Produce json
// @Param param body srv_hotnav.DelHotNavReq true "参数列表"
// @Success 200 {object} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/hotnav/del [post]
func HotNavDel(c *gin.Context) {
var req srv_hotnav.DelHotNavReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
serr := srv_hotnav.DelHotNav(c, &req)
if serr != nil {
common.ServerJSON(c, serr.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, "")
}
// HotNavUpdate
// @Tags 热门导航配置
// @Summary 热门导航配置-更新
// @Description 热门导航配置-更新
// @Accept json
// @Produce json
// @Param param body srv_hotnav.UpdateHotNavReq true "参数列表"
// @Success 200 {object} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/hotnav/update [post]
func HotNavUpdate(c *gin.Context) {
var req srv_hotnav.UpdateHotNavReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
serr := srv_hotnav.UpdateHotNav(c, &req)
if serr != nil {
common.ServerJSON(c, serr.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, "")
}
+83
View File
@@ -0,0 +1,83 @@
package web_ipblack
import (
"github.com/gin-gonic/gin"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_ipblack"
)
// IpBlackList
// @Tags IP黑名单
// @Summary IP黑名单-列表
// @Description IP黑名单-列表
// @Accept json
// @Produce json
// @Param param body srv_ipblack.GetIPBlackListReq true "参数列表"
// @Success 200 {object} srv_ipblack.GetIPBlackListResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/ipblack/list [POST]
func IpBlackList(c *gin.Context) {
var req srv_ipblack.GetIPBlackListReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
resp, err := srv_ipblack.GetIpBlackList(c, &req)
if err != nil {
common.ServerJSON(c, err.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, resp)
}
// IpBlackAdd
// @Tags IP黑名单
// @Summary IP黑名单-增加
// @Description IP黑名单-增加
// @Accept json
// @Produce json
// @Param param body srv_ipblack.AddIPBlackListReq true "参数列表"
// @Success 200 {object} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/ipblack/add [POST]
func IpBlackAdd(c *gin.Context) {
var req srv_ipblack.AddIPBlackListReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
err := srv_ipblack.AddIpBlack(c, &req)
if err != nil {
common.ServerJSON(c, err.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, "")
}
// IpBlackDel
// @Tags IP黑名单
// @Summary IP黑名单-删除
// @Description IP黑名单-删除
// @Accept json
// @Produce json
// @Param param body srv_ipblack.DelIpBlackListReq true "参数列表"
// @Success 200 {object} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/ipblack/del [POST]
func IpBlackDel(c *gin.Context) {
var req srv_ipblack.DelIpBlackListReq
if err := c.ShouldBind(&req); err != nil {
common.ServerJSON(c, srvdef.ErrParamError, err.Error())
return
}
err := srv_ipblack.DelIpBlack(c, &req)
if err != nil {
common.ServerJSON(c, err.Code, "")
return
}
common.ServerJSON(c, srvdef.Success, "")
}
+87
View File
@@ -0,0 +1,87 @@
package web_mediaresource
import (
"videoweb/pub/common"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"videoweb/web/api/proto"
"videoweb/web/service/srv_mediaresource"
"github.com/gin-gonic/gin"
)
// ResourceList web端短剧媒资列表
// @Tags web媒资库相关接口
// @Summary web端短剧媒资列表 -- by 王鸣
// @Description 分页查询短剧媒资列表
// @Accept json
// @Produce json
// @Param params query proto.PlayletResourceListReq true "短剧媒资列表请求"
// @Success 200 {object} proto.PlayletResourceListResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/resource/list [get]
func ResourceList(ctx *gin.Context) {
var req proto.PlayletResourceListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_mediaresource.ListPlayletResource(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ResourceImport web端短剧媒资入库
// @Tags web媒资库相关接口
// @Summary web端短剧媒资入库 -- by 王鸣
// @Description 提交媒资入库任务,后台从媒资中心同步短剧详情并写入短剧和章节集合
// @Accept json
// @Produce json
// @Param params body proto.PlayletResourceUseReq true "短剧媒资入库请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/resource/import [post]
func ResourceImport(ctx *gin.Context) {
var req proto.PlayletResourceUseReq
if err := ctx.ShouldBindJSON(&req); err != nil {
log.Error("短剧媒资入库参数绑定失败", log.E(err))
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_mediaresource.ImportPlayletResource(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ResourceChapters web端短剧媒资剧集列表
// @Tags web媒资库相关接口
// @Summary web端短剧媒资剧集列表 -- by 王鸣
// @Description 按媒资ID查询剧集信息,复用入库时的 mediaSync 接口
// @Accept json
// @Produce json
// @Param id query int true "媒资中心资源ID"
// @Success 200 {object} proto.PlayletResourceChapterListResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/resource/chapters [get]
func ResourceChapters(ctx *gin.Context) {
var req proto.PlayletResourceChapterListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_mediaresource.ListPlayletResourceChapters(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
+105
View File
@@ -0,0 +1,105 @@
package web_playlet
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/api/proto"
"videoweb/web/service/srv_playlet"
"github.com/gin-gonic/gin"
)
// CategoryList web端短剧分类列表
// @Tags web短剧相关接口
// @Summary web端短剧分类列表 -- by 王鸣
// @Description 分页查询短剧分类
// @Accept json
// @Produce json
// @Param params query proto.PlayletCategoryListReq true "短剧分类列表请求"
// @Success 200 {object} proto.PlayletCategoryListPageResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/category/list [get]
func CategoryList(ctx *gin.Context) {
var req proto.PlayletCategoryListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.ListPlayletCategory(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// CategoryAdd web端新增短剧分类
// @Tags web短剧相关接口
// @Summary web端新增短剧分类 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.PlayletCategoryAddReq true "新增短剧分类请求"
// @Success 200 {object} proto.PlayletCategoryAddResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/category/add [post]
func CategoryAdd(ctx *gin.Context) {
var req proto.PlayletCategoryAddReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.AddPlayletCategory(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// CategoryUpdate web端更新短剧分类
// @Tags web短剧相关接口
// @Summary web端更新短剧分类 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.PlayletCategoryUpdateReq true "更新短剧分类请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/category/update [post]
func CategoryUpdate(ctx *gin.Context) {
var req proto.PlayletCategoryUpdateReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.UpdatePlayletCategory(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// CategoryDel web端删除短剧分类
// @Tags web短剧相关接口
// @Summary web端删除短剧分类 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.PlayletCategoryDelReq true "删除短剧分类请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/category/del [post]
func CategoryDel(ctx *gin.Context) {
var req proto.PlayletCategoryDelReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.DelPlayletCategory(ctx, req.Id); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+130
View File
@@ -0,0 +1,130 @@
package web_playlet
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/api/proto"
"videoweb/web/service/srv_playlet"
"github.com/gin-gonic/gin"
)
// HomeConfigList web端首页配置列表
// @Tags web短剧相关接口
// @Summary web端首页配置列表
// @Description 分页查询短剧首页配置
// @Accept json
// @Produce json
// @Param params query proto.PlayletHomeConfigListReq true "首页配置列表请求"
// @Success 200 {object} proto.PlayletHomeConfigListPageResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/home-config/list [get]
func HomeConfigList(ctx *gin.Context) {
var req proto.PlayletHomeConfigListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.ListPlayletHomeConfig(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// HomeConfigTopicOptions web端首页专题下拉选项
// @Tags web短剧相关接口
// @Summary web端分页查询首页专题可选项
// @Description dataType 1查询短剧题材 2查询视频分类,排除其他已启用模块占用的专题,configId用于回显当前配置已选项
// @Accept json
// @Produce json
// @Param params query proto.PlayletHomeTopicOptionsReq true "首页专题选项请求"
// @Success 200 {object} proto.PlayletHomeTopicOptionsResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/home-config/topic/options [get]
func HomeConfigTopicOptions(ctx *gin.Context) {
var req proto.PlayletHomeTopicOptionsReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.ListPlayletHomeTopicOptions(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// HomeConfigAdd web端新增首页配置
// @Tags web短剧相关接口
// @Summary web端新增首页配置
// @Accept json
// @Produce json
// @Param params body proto.PlayletHomeConfigAddReq true "新增首页配置请求"
// @Success 200 {object} proto.PlayletHomeConfigAddResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/home-config/add [post]
func HomeConfigAdd(ctx *gin.Context) {
var req proto.PlayletHomeConfigAddReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.AddPlayletHomeConfig(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// HomeConfigUpdate web端更新首页配置
// @Tags web短剧相关接口
// @Summary web端更新首页配置
// @Accept json
// @Produce json
// @Param params body proto.PlayletHomeConfigUpdateReq true "更新首页配置请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/home-config/update [post]
func HomeConfigUpdate(ctx *gin.Context) {
var req proto.PlayletHomeConfigUpdateReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.UpdatePlayletHomeConfig(ctx, &req); err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// HomeConfigDel web端删除首页配置
// @Tags web短剧相关接口
// @Summary web端删除首页配置
// @Accept json
// @Produce json
// @Param params body proto.PlayletHomeConfigDelReq true "删除首页配置请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/home-config/del [post]
func HomeConfigDel(ctx *gin.Context) {
var req proto.PlayletHomeConfigDelReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.DelPlayletHomeConfig(ctx, &req); err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+543
View File
@@ -0,0 +1,543 @@
package web_playlet
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/api/proto"
"videoweb/web/middleware/auth"
"videoweb/web/service/srv_mediaresource"
"videoweb/web/service/srv_playlet"
"github.com/gin-gonic/gin"
)
// List web端短剧列表
// @Tags web短剧相关接口
// @Summary web端短剧列表 -- by 王鸣
// @Description 分页查询短剧列表
// @Accept json
// @Produce json
// @Param params query proto.PlayletListReq true "短剧列表请求"
// @Success 200 {object} proto.PlayletListPageResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/list [get]
func List(ctx *gin.Context) {
var req proto.PlayletListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.ListPlaylet(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Add web端新增短剧
// @Tags web短剧相关接口
// @Summary web端新增短剧 -- by 王鸣
// @Description 新增 playlet 集合短剧数据,支持分类、题材、标签、支付方式、推荐和 banner 配置
// @Accept json
// @Produce json
// @Param params body proto.PlayletAddReq true "新增短剧请求"
// @Success 200 {object} proto.PlayletAddResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/add [post]
func Add(ctx *gin.Context) {
var req proto.PlayletAddReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.AddPlaylet(ctx, &req, auth.GetAccount(ctx))
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Update web端编辑短剧
// @Tags web短剧相关接口
// @Summary web端编辑短剧 -- by 王鸣
// @Description 按短剧ID编辑 playlet 集合短剧数据,只更新请求中传入的字段
// @Accept json
// @Produce json
// @Param params body proto.PlayletUpdateReq true "编辑短剧请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/update [post]
func Update(ctx *gin.Context) {
var req proto.PlayletUpdateReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.UpdatePlaylet(ctx, &req, auth.GetAccount(ctx)); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// Del 删除短剧及其关联数据
// @Tags web短剧相关接口
// @Summary web端单/批量删除短剧
// @Description 删除短剧、剧集及关联用户数据,上架和下架短剧均可删除
// @Accept json
// @Produce json
// @Param params body proto.PlayletDelReq true "删除短剧请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/del [post]
func Del(ctx *gin.Context) {
var req proto.PlayletDelReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.DelPlaylet(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetStatus web端单/批量设置短剧上下架
// @Tags web短剧相关接口
// @Summary web端单/批量设置短剧上下架 -- by 王鸣
// @Description 根据短剧ID集合批量更新 playlet 集合 status 字段,传1个ID表示单条设置,传多个ID表示批量设置
// @Accept json
// @Produce json
// @Param params body proto.PlayletStatusSetReq true "单/批量设置短剧上下架请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/status/set [post]
func SetStatus(ctx *gin.Context) {
var req proto.PlayletStatusSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.SetPlayletStatus(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetRecommend web端单/批量设置短剧是否推荐
// @Tags web短剧相关接口
// @Summary web端单/批量设置短剧是否推荐 -- by 王鸣
// @Description 根据短剧ID集合批量更新 playlet 集合 isRecommend 字段,传1个ID表示单条设置,传多个ID表示批量设置
// @Accept json
// @Produce json
// @Param params body proto.PlayletRecommendSetReq true "单/批量设置短剧是否推荐请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/recommend/set [post]
func SetRecommend(ctx *gin.Context) {
var req proto.PlayletRecommendSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.SetPlayletRecommend(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetFeatured web端单/批量设置短剧是否爆剧
// @Tags web短剧相关接口
// @Summary web端单/批量设置短剧是否爆剧 -- by 王鸣
// @Description 根据短剧ID集合批量更新 playlet 集合 isFeatured 字段,传1个ID表示单条设置,传多个ID表示批量设置
// @Accept json
// @Produce json
// @Param params body proto.PlayletFeaturedSetReq true "单/批量设置短剧是否爆剧请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/featured/set [post]
func SetFeatured(ctx *gin.Context) {
var req proto.PlayletFeaturedSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.SetPlayletFeatured(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetBanner web端单/批量设置短剧是否显示在首页banner
// @Tags web短剧相关接口
// @Summary web端单/批量设置短剧是否显示在首页banner -- by 王鸣
// @Description 根据短剧ID集合批量更新 playlet 集合 showOnBanner 字段,传1个ID表示单条设置,传多个ID表示批量设置
// @Accept json
// @Produce json
// @Param params body proto.PlayletBannerSetReq true "单/批量设置短剧是否显示在首页banner请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/banner/set [post]
func SetBanner(ctx *gin.Context) {
var req proto.PlayletBannerSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.SetPlayletBanner(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetTheme web端单/批量设置短剧题材
// @Tags web短剧相关接口
// @Summary web端单/批量设置短剧题材 -- by 王鸣
// @Description 根据短剧ID集合批量更新 playlet 集合 themeIds 字段,传1个ID表示单条设置,传多个ID表示批量设置
// @Accept json
// @Produce json
// @Param params body proto.PlayletThemeSetReq true "单/批量设置短剧题材请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/theme/set [post]
func SetTheme(ctx *gin.Context) {
var req proto.PlayletThemeSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.SetPlayletTheme(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetTag web端单/批量设置短剧标签
// @Tags web短剧相关接口
// @Summary web端单/批量设置短剧标签 -- by 王鸣
// @Description 根据短剧ID集合批量更新 playlet 集合 tagIds 字段,传1个ID表示单条设置,传多个ID表示批量设置
// @Accept json
// @Produce json
// @Param params body proto.PlayletTagSetReq true "单/批量设置短剧标签请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/tag/set [post]
func SetTag(ctx *gin.Context) {
var req proto.PlayletTagSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.SetPlayletTag(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetCategory web端单/批量设置短剧分类
// @Tags web短剧相关接口
// @Summary web端单/批量设置短剧分类 -- by 王鸣
// @Description 根据短剧ID集合批量更新 playlet 集合 categoryIds 字段,传1个ID表示单条设置,传多个ID表示批量设置
// @Accept json
// @Produce json
// @Param params body proto.PlayletCategorySetReq true "单/批量设置短剧分类请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/category/set [post]
func SetCategory(ctx *gin.Context) {
var req proto.PlayletCategorySetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.SetPlayletCategory(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetVirtualLike web端单/批量设置短剧虚拟点赞数
// @Tags web短剧相关接口
// @Summary web端单/批量设置短剧虚拟点赞数 -- by 王鸣
// @Description 根据短剧ID集合批量更新 playlet 集合 virtualCountLike 字段,每条短剧从最小值和最大值之间随机取不重复数值入库
// @Accept json
// @Produce json
// @Param params body proto.PlayletVirtualLikeSetReq true "单/批量随机设置短剧虚拟点赞数请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/like/virtual/set [post]
func SetVirtualLike(ctx *gin.Context) {
var req proto.PlayletVirtualLikeSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.SetPlayletVirtualLike(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetVirtualBrowse web端单/批量设置短剧虚拟观看数
// @Tags web短剧相关接口
// @Summary web端单/批量设置短剧虚拟观看数 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.PlayletVirtualBrowseSetReq true "设置短剧虚拟观看数请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/browse/virtual/set [post]
func SetVirtualBrowse(ctx *gin.Context) {
var req proto.PlayletVirtualBrowseSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.SetPlayletVirtualBrowse(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetVirtualHeat web端单/批量设置短剧虚拟热度
// @Tags web短剧相关接口
// @Summary web端单/批量设置短剧虚拟热度 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.PlayletVirtualHeatSetReq true "设置短剧虚拟热度请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/heat/virtual/set [post]
func SetVirtualHeat(ctx *gin.Context) {
var req proto.PlayletVirtualHeatSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.SetPlayletVirtualHeat(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetPayType web端单/批量设置短剧默认支付方式
// @Tags web短剧相关接口
// @Summary web端单/批量设置短剧默认支付方式 -- by 王鸣
// @Description 根据短剧ID集合批量更新 playlet 集合 payType/singleCoins 字段
// @Accept json
// @Produce json
// @Param params body proto.PlayletPayTypeSetReq true "单/批量设置短剧默认支付方式请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/pay-type/set [post]
func SetPayType(ctx *gin.Context) {
var req proto.PlayletPayTypeSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.SetPlayletPayType(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// ResetWatermark web端按短剧ID批量重置剧集水印
// @Tags web短剧相关接口
// @Summary web端按短剧ID批量重置剧集水印 -- by 王鸣
// @Description 根据短剧ID集合重置剧集水印状态,保留已有水印地址以便换水印期间继续观看
// @Accept json
// @Produce json
// @Param params body proto.PlayletWatermarkResetReq true "批量重置短剧水印请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/watermark/reset [post]
func ResetWatermark(ctx *gin.Context) {
var req proto.PlayletWatermarkResetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.ResetPlayletWatermark(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// ChapterList web端短剧剧集列表
// @Tags web短剧相关接口
// @Summary web端短剧剧集列表 -- by 王鸣
// @Description 分页查询 playlet_chapter 集合短剧剧集数据,默认按集数升序返回
// @Accept json
// @Produce json
// @Param params query proto.PlayletChapterListReq true "短剧剧集列表请求"
// @Success 200 {object} proto.PlayletChapterListPageResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/chapter/list [get]
func ChapterList(ctx *gin.Context) {
var req proto.PlayletChapterListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.ListPlayletChapter(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ChapterAdd web端新增短剧剧集
// @Tags web短剧相关接口
// @Summary web端新增短剧剧集 -- by 王鸣
// @Description 新增 playlet_chapter 集合短剧剧集数据
// @Accept json
// @Produce json
// @Param params body proto.PlayletChapterAddReq true "新增短剧剧集请求"
// @Success 200 {object} proto.PlayletChapterAddResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/chapter/add [post]
func ChapterAdd(ctx *gin.Context) {
var req proto.PlayletChapterAddReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.AddPlayletChapter(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ChapterDel web端单/批量删除短剧剧集
// @Tags web短剧相关接口
// @Summary web端单/批量删除短剧剧集
// @Description 根据剧集ID集合删除 playlet_chapter 记录,仅原创短剧支持删除
// @Accept json
// @Produce json
// @Param params body proto.PlayletChapterDelReq true "单/批量删除短剧剧集请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/chapter/del [post]
func ChapterDel(ctx *gin.Context) {
var req proto.PlayletChapterDelReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.DelPlayletChapter(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// ChapterSync web端手动同步短剧剧集
// @Tags web短剧相关接口
// @Summary web端手动单/批量同步短剧剧集
// @Description 根据短剧ID集合从媒资中心同步新增剧集,playletIds传1个表示单条同步,传多个表示批量同步,允许已完结短剧补集或修正状态
// @Accept json
// @Produce json
// @Param params body proto.PlayletChapterSyncReq true "手动单/批量同步短剧剧集请求"
// @Success 200 {object} proto.PlayletChapterSyncResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/chapter/sync [post]
func ChapterSync(ctx *gin.Context) {
var req proto.PlayletChapterSyncReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_mediaresource.SyncPlayletChapters(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ChapterUpdate web端编辑短剧剧集
// @Tags web短剧相关接口
// @Summary web端编辑短剧剧集 -- by 王鸣
// @Description 按剧集ID编辑 playlet_chapter 集合短剧剧集数据,只更新请求中传入的字段
// @Accept json
// @Produce json
// @Param params body proto.PlayletChapterUpdateReq true "编辑短剧剧集请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/chapter/update [post]
func ChapterUpdate(ctx *gin.Context) {
var req proto.PlayletChapterUpdateReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.UpdatePlayletChapter(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// ChapterSetPayType web端单/批量设置短剧剧集支付方式
// @Tags web短剧相关接口
// @Summary web端单/批量设置短剧剧集支付方式 -- by 王鸣
// @Description 根据剧集ID集合批量更新 playlet_chapter 集合 payType 和 singleCoins 字段,传1个ID表示单条设置,传多个ID表示批量设置
// @Accept json
// @Produce json
// @Param params body proto.PlayletChapterPayTypeSetReq true "单/批量设置短剧剧集支付方式请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/chapter/pay-type/set [post]
func ChapterSetPayType(ctx *gin.Context) {
var req proto.PlayletChapterPayTypeSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.SetPlayletChapterPayType(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+105
View File
@@ -0,0 +1,105 @@
package web_playlet
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/api/proto"
"videoweb/web/service/srv_playlet"
"github.com/gin-gonic/gin"
)
// TagList web端标签列表
// @Tags web短剧相关接口
// @Summary web端标签列表 -- by 王鸣
// @Description 分页查询短剧标签
// @Accept json
// @Produce json
// @Param params query proto.PlayletTagListReq true "标签列表请求"
// @Success 200 {object} proto.PlayletTagListPageResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/tag/list [get]
func TagList(ctx *gin.Context) {
var req proto.PlayletTagListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.ListPlayletTag(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// TagAdd web端新增标签
// @Tags web短剧相关接口
// @Summary web端新增标签 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.PlayletTagAddReq true "新增标签请求"
// @Success 200 {object} proto.PlayletTagAddResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/tag/add [post]
func TagAdd(ctx *gin.Context) {
var req proto.PlayletTagAddReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.AddPlayletTag(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// TagUpdate web端更新标签
// @Tags web短剧相关接口
// @Summary web端更新标签 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.PlayletTagUpdateReq true "更新标签请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/tag/update [post]
func TagUpdate(ctx *gin.Context) {
var req proto.PlayletTagUpdateReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.UpdatePlayletTag(ctx, &req); err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// TagDel web端删除标签
// @Tags web短剧相关接口
// @Summary web端删除标签 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.PlayletTagDelReq true "删除标签请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/tag/del [post]
func TagDel(ctx *gin.Context) {
var req proto.PlayletTagDelReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.DelPlayletTag(ctx, req.Id); err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+105
View File
@@ -0,0 +1,105 @@
package web_playlet
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/api/proto"
"videoweb/web/service/srv_playlet"
"github.com/gin-gonic/gin"
)
// ThemeList web端题材列表
// @Tags web短剧相关接口
// @Summary web端题材列表 -- by 王鸣
// @Description 分页查询短剧题材
// @Accept json
// @Produce json
// @Param params query proto.PlayletThemeListReq true "题材列表请求"
// @Success 200 {object} proto.PlayletThemeListPageResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/theme/list [get]
func ThemeList(ctx *gin.Context) {
var req proto.PlayletThemeListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.ListPlayletTheme(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ThemeAdd web端新增题材
// @Tags web短剧相关接口
// @Summary web端新增题材 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.PlayletThemeAddReq true "新增题材请求"
// @Success 200 {object} proto.PlayletThemeAddResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/theme/add [post]
func ThemeAdd(ctx *gin.Context) {
var req proto.PlayletThemeAddReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_playlet.AddPlayletTheme(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ThemeUpdate web端更新题材
// @Tags web短剧相关接口
// @Summary web端更新题材 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.PlayletThemeUpdateReq true "更新题材请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/theme/update [post]
func ThemeUpdate(ctx *gin.Context) {
var req proto.PlayletThemeUpdateReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.UpdatePlayletTheme(ctx, &req); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// ThemeDel web端删除题材
// @Tags web短剧相关接口
// @Summary web端删除题材 -- by 王鸣
// @Accept json
// @Produce json
// @Param params body proto.PlayletThemeDelReq true "删除题材请求"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/playlet/theme/del [post]
func ThemeDel(ctx *gin.Context) {
var req proto.PlayletThemeDelReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if err := srv_playlet.DelPlayletTheme(ctx, req.Id); err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
@@ -0,0 +1,55 @@
package web_questionnaire
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_questionnaire"
"github.com/gin-gonic/gin"
)
// @Tags 问卷调查
// @Summary 查询问卷列表
// @Description 支持分页及条件筛选(question_type、status、时间范围)
// @Accept json
// @Produce json
// @Param param body srv_questionnaire.ListReq true "查询参数"
// @Success 200 {object} srv_questionnaire.ListResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/web/questionnaire/list [POST]
func List(ctx *gin.Context) {
var req srv_questionnaire.ListReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_questionnaire.List(ctx, &req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 问卷调查
// @Summary 处理问卷
// @Description 只有状态为"待处理"的问卷才允许更新
// @Accept json
// @Produce json
// @Param param body srv_questionnaire.HandleReq true "处理参数"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Router /api/web/questionnaire/handle [POST]
func Handle(ctx *gin.Context) {
var req srv_questionnaire.HandleReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_questionnaire.Handle(ctx, &req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, nil)
}
@@ -0,0 +1,111 @@
package web_richtextcontent
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/richtextcontentmod"
"videoweb/web/service/srv_richtextcontent"
"github.com/gin-gonic/gin"
)
// @Tags 富文本内容
// @Summary 分组分页获取富文本内容
// @Description 分组分页获取富文本内容
// @Accept json
// @Produce json
// @Param param body srv_richtextcontent.GetRichTextContentListReq true "参数列表"
// @Success 200 {object} srv_richtextcontent.GetRichTextContentResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/richtextcontent/list [POST]
func List(ctx *gin.Context) {
var req = &srv_richtextcontent.GetRichTextContentListReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_richtextcontent.GetRichTextContentList(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 富文本内容
// @Summary 添加一个富文本内容
// @Description 添加一个富文本内容
// @Accept json
// @Produce json
// @Param param body richtextcontentmod.RichTextContentModel true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/richtextcontent/add [POST]
func Add(ctx *gin.Context) {
var req = &richtextcontentmod.RichTextContentModel{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_richtextcontent.AddRichTextContent(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 富文本内容
// @Summary 删除一个富文本内容
// @Description 删除一个富文本内容
// @Accept json
// @Produce json
// @Param param body srv_richtextcontent.DelRichTextContentReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/richtextcontent/del [POST]
func Del(ctx *gin.Context) {
var req = &srv_richtextcontent.DelRichTextContentReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_richtextcontent.DelRichTextContent(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 富文本内容
// @Summary 更新一个富文本内容
// @Description 更新一个富文本内容
// @Accept json
// @Produce json
// @Param param body srv_richtextcontent.UpdateRichTextContentReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/richtextcontent/update [POST]
func Update(ctx *gin.Context) {
var req = &srv_richtextcontent.UpdateRichTextContentReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_richtextcontent.UpdateRichTextContent(ctx, req.Id, &req.Param)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+37
View File
@@ -0,0 +1,37 @@
package web_slug
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/api/proto"
"videoweb/web/service/srv_slug"
"github.com/gin-gonic/gin"
)
// SyncSlug 补齐历史空 slug
// @Tags web slug相关接口
// @Summary 同步历史空 slug
// @Description 为视频、分类、女优、作者、短剧、统一标签等空 slug 按 SEO 关键词或名称自动生成。可重复调用,hasMore 为 true 时继续请求。type 为空处理全部,也可指定 video/videoCategory/actress/videoCreater/playlet/playletCategory/playletTheme/contentTag。
// @Accept json
// @Produce json
// @Param param body proto.SlugSyncReq false "同步参数"
// @Success 200 {object} proto.SlugSyncResp "成功"
// @Failure 400 {string} string "参数错误"
// @Security ApiKeyAuth
// @Router /api/web/slug/sync [POST]
func SyncSlug(ctx *gin.Context) {
var req proto.SlugSyncReq
if ctx.Request.ContentLength > 0 {
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
}
resp, serr := srv_slug.SyncEmptySlugs(ctx, &req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
+111
View File
@@ -0,0 +1,111 @@
package web_translation
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/translationcategorymod"
"videoweb/web/service/srv_translationcategory"
"github.com/gin-gonic/gin"
)
// @Tags 导航分类
// @Summary 分组分页获取导航分类
// @Description 分组分页获取导航分类
// @Accept json
// @Produce json
// @Param param body srv_translationcategory.TranslationCategoryReq true "参数列表"
// @Success 200 {object} srv_translationcategory.TranslationCategoryResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/translationcategory/list [POST]
func GetTranslationCategory(ctx *gin.Context) {
var req = &srv_translationcategory.TranslationCategoryReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_translationcategory.GetTranslationCategorys(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 导航分类
// @Summary 添加一个导航分类
// @Description 添加一个导航分类
// @Accept json
// @Produce json
// @Param param body translationcategorymod.TranslationCategory true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/translationcategory/add [POST]
func AddOnetTranslationCategory(ctx *gin.Context) {
var req = &translationcategorymod.TranslationCategory{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_translationcategory.AddTranslationCategory(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 导航分类
// @Summary 删除一个导航分类
// @Description 删除一个导航分类
// @Accept json
// @Produce json
// @Param param body srv_translationcategory.TranslationCategoryDelReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/translationcategory/del [POST]
func DelOnetTranslationCategory(ctx *gin.Context) {
var req = &srv_translationcategory.TranslationCategoryDelReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_translationcategory.DelTranslationCategory(ctx, req.Id)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 导航分类
// @Summary 更新一个导航分类
// @Description 更新一个导航分类
// @Accept json
// @Produce json
// @Param param body srv_translationcategory.TranslationCategoryUpdateReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/translationcategory/update [POST]
func UpdateOnetTranslationCategory(ctx *gin.Context) {
var req = &srv_translationcategory.TranslationCategoryUpdateReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_translationcategory.UpdateTranslationCategory(ctx, req.Id, req.Param)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+111
View File
@@ -0,0 +1,111 @@
package web_translation
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/translationmod"
"videoweb/web/service/srv_translation"
"github.com/gin-gonic/gin"
)
// @Tags 导航跳转信息
// @Summary 分组分页获取导航跳转信息
// @Description 分组分页获取导航跳转信息
// @Accept json
// @Produce json
// @Param param body srv_translation.TranslationInfoReq true "参数列表"
// @Success 200 {object} srv_translation.TranslationInfoResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/translation/list [POST]
func GetTranslation(ctx *gin.Context) {
var req = &srv_translation.TranslationInfoReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_translation.GetTranslationInfos(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 导航跳转信息
// @Summary 添加一个导航跳转信息
// @Description 添加一个导航跳转信息
// @Accept json
// @Produce json
// @Param param body translationmod.TranslationInfo true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/translation/add [POST]
func AddOnetTranslation(ctx *gin.Context) {
var req = &translationmod.TranslationInfo{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_translation.AddTranslationInfo(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 导航跳转信息
// @Summary 删除一个导航跳转信息
// @Description 删除一个导航跳转信息
// @Accept json
// @Produce json
// @Param param body srv_translation.TranslationInfoDelReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/translation/del [POST]
func DelOnetTranslation(ctx *gin.Context) {
var req = &srv_translation.TranslationInfoDelReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_translation.DelTranslationInfo(ctx, req.Id)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 导航跳转信息
// @Summary 更新一个导航跳转信息
// @Description 更新一个导航跳转信息
// @Accept json
// @Produce json
// @Param param body srv_translation.TranslationInfoUpdateReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/translation/update [POST]
func UpdateOnetTranslation(ctx *gin.Context) {
var req = &srv_translation.TranslationInfoUpdateReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_translation.UpdateTranslationInfo(ctx, req.Id, req.Param)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+52
View File
@@ -0,0 +1,52 @@
package web_user
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_user"
"github.com/gin-gonic/gin"
)
// @Tags 用户管理
// @Summary 查询用户列表
// @Accept json
// @Produce json
// @Param param body srv_user.UserListReq true "查询参数"
// @Success 200 {object} srv_user.UserListResp "成功"
// @Security ApiKeyAuth
// @Router /api/web/user/list [POST]
func GetUserList(ctx *gin.Context) {
var req srv_user.UserListReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_user.GetUsers(ctx, &req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 用户管理
// @Summary 更新用户信息
// @Accept json
// @Produce json
// @Param param body srv_user.UserUpdateReq true "更新参数"
// @Success 200 {string} string "成功"
// @Security ApiKeyAuth
// @Router /api/web/user/update [POST]
func UpdateUser(ctx *gin.Context) {
var req srv_user.UserUpdateReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if serr := srv_user.UpdateUser(ctx, req.Id, req.Param); serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+111
View File
@@ -0,0 +1,111 @@
package web_video
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/videocategorymod"
"videoweb/web/service/srv_videocategory"
"github.com/gin-gonic/gin"
)
// GetVideoCategory
// @Tags 视频分类
// @Summary 分组分页获取视频分类
// @Description 分组分页获取视频分类
// @Accept json
// @Produce json
// @Param param body srv_videocategory.VideoCategoryReq true "参数列表"
// @Success 200 {object} srv_videocategory.VideoCategoryResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videocategory/list [POST]
func GetVideoCategory(ctx *gin.Context) {
var req = &srv_videocategory.VideoCategoryReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := srv_videocategory.GetVideoCategorys(ctx, req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// AddOneVideoCategory
// @Tags 视频分类
// @Summary 添加一个视频分类
// @Description 添加一个视频分类
// @Accept json
// @Produce json
// @Param param body videocategorymod.VideoCategory true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videocategory/add [POST]
func AddOneVideoCategory(ctx *gin.Context) {
var req = &videocategorymod.VideoCategory{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
err := srv_videocategory.AddVideoCategory(ctx, req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// DelOneVideoCategory
// @Tags 视频分类
// @Summary 删除一个视频分类
// @Description 删除一个视频分类
// @Accept json
// @Produce json
// @Param param body srv_videocategory.VideoCategoryDelReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videocategory/del [POST]
func DelOneVideoCategory(ctx *gin.Context) {
var req = &srv_videocategory.VideoCategoryDelReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
err := srv_videocategory.DelVideoCategory(ctx, req.Id)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// UpdateOneVideoCategory
// @Tags 视频分类
// @Summary 更新一个视频分类
// @Description 更新一个视频分类
// @Accept json
// @Produce json
// @Param param body srv_videocategory.VideoCategoryUpdate true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videocategory/update [POST]
func UpdateOneVideoCategory(ctx *gin.Context) {
var req = &srv_videocategory.VideoCategoryUpdateReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
err := srv_videocategory.UpdateVideoCategory(ctx, req.Id, req.Param)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+111
View File
@@ -0,0 +1,111 @@
package web_video
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/videocreatermod"
"videoweb/web/service/srv_videocreater"
"github.com/gin-gonic/gin"
)
// @Tags 视频作者
// @Summary 分组分页获取视频作者
// @Description 分组分页获取视频作者
// @Accept json
// @Produce json
// @Param param body srv_videocreater.VideoCreaterReq true "参数列表"
// @Success 200 {object} srv_videocreater.VideoCreaterResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videocreater/list [POST]
func GetVideoCreater(ctx *gin.Context) {
var req = &srv_videocreater.VideoCreaterReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_videocreater.GetVideoCreaters(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 视频作者
// @Summary 添加一个视频作者
// @Description 添加一个视频作者
// @Accept json
// @Produce json
// @Param param body videocreatermod.VideoCreaterInfo true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videocreater/add [POST]
func AddOneVideoCreater(ctx *gin.Context) {
var req = &videocreatermod.VideoCreaterInfo{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_videocreater.AddVideoCreater(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 视频作者
// @Summary 删除一个视频作者
// @Description 删除一个视频作者
// @Accept json
// @Produce json
// @Param param body srv_videocreater.VideoCreaterDelReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videocreater/del [POST]
func DelOneVideoCreater(ctx *gin.Context) {
var req = &srv_videocreater.VideoCreaterDelReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_videocreater.DelVideoCreater(ctx, req.Id)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 视频作者
// @Summary 更新一个视频作者
// @Description 更新一个视频作者
// @Accept json
// @Produce json
// @Param param body srv_videocreater.VideoCreaterUpdate true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videocreater/update [POST]
func UpdateOneVideoCreater(ctx *gin.Context) {
var req = &srv_videocreater.VideoCreaterUpdateReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_videocreater.UpdateVideoCreater(ctx, req.Id, req.Param)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+24
View File
@@ -0,0 +1,24 @@
package web_video
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_videoinfo"
"github.com/gin-gonic/gin"
)
// VideoList 按日期查询已上架视频。
func VideoList(ctx *gin.Context) {
param := srv_videoinfo.ExternalVideoListReq{}
if err := ctx.ShouldBindQuery(&param); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
data, serr := srv_videoinfo.SearchExternalVideoList(ctx, &param)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, data)
}
+43
View File
@@ -0,0 +1,43 @@
package web_video
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_videotag"
"github.com/gin-gonic/gin"
)
// @Tags 标签管理
// @Summary 查询播放量最多的标签
// @Description 根据视频累计播放量聚合返回热门标签列表
// @Accept json
// @Produce json
// @Param limit query int false "返回条数,默认10,最大1000"
// @Success 200 {object} srv_videotag.HotTagResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Router /wbapi/hjsq/hottag [GET]
func GetVideoPlayData(ctx *gin.Context) {
var req = &srv_videotag.HotTagReq{}
if err := ctx.ShouldBindQuery(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_videotag.GetHotTagsByPlayData(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags IP统计
// @Summary 查询今日和昨日去重访客IP数
// @Produce json
// @Success 200 {object} srv_videotag.IpStatReq "成功"
// @Router /wbapi/hjsq/ipstat [GET]
func GetIpStatData(ctx *gin.Context) {
fetchIpStat := srv_videotag.FetchIpStat(ctx)
common.ServerJSON(ctx, srvdef.Success, fetchIpStat)
}
+102
View File
@@ -0,0 +1,102 @@
package web_video
import (
"bytes"
"go.mongodb.org/mongo-driver/bson"
"io"
"net/http"
"videoweb/pub/common"
"videoweb/pub/common/m3u8"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/cfg"
"videoweb/web/webg"
"github.com/gin-gonic/gin"
)
type fileHandler func(ctx *gin.Context) (contentLength int64, contentType string, reader io.Reader, extraHeaders map[string]string, err error)
func Play(ctx *gin.Context) {
fn := func(c *gin.Context) (contentLength int64, contentType string, reader io.Reader, extraHeaders map[string]string, err error) {
m3u8Name := ctx.Param("key")
var req m3u8.Req
if err = ctx.BindQuery(&req); err != nil {
return
}
req.Name = m3u8Name
cfgSys, _ := cfg.FindOneSysCfg(ctx, bson.M{})
cdnDomain := webg.Conf.CdnDomain
if cfgSys != nil {
cdnDomain = cfgSys.MediaWebCdn
}
origDomain := webg.Conf.OrigDomain
_, buff, err := m3u8.TransFormWithSafely(&req, cdnDomain, origDomain, true, webg.Conf.TsAuthKey, webg.Conf.LsjMediaConf.M3u8Yuan, "")
if err != nil {
return
}
contentType = "application/vnd.apple.mpegurl"
reader = bytes.NewReader(buff.Bytes())
contentLength = int64(buff.Len())
extraHeaders = map[string]string{}
return
}
handlerFile(ctx, fn)
}
func Enkey(ctx *gin.Context) {
fn := func(c *gin.Context) (contentLength int64, contentType string, reader io.Reader, extraHeaders map[string]string, err error) {
buffer, err := m3u8.Enkey(c)
if err != nil {
return
}
contentLength = int64(buffer.Len())
contentType = "application/octet-stream"
reader = buffer
extraHeaders = map[string]string{}
return
}
handlerFile(ctx, fn)
}
// TranscodeM3u8 转码专用 m3u8 接口(不鉴权)。
func TranscodeM3u8(ctx *gin.Context) {
fn := func(c *gin.Context) (contentLength int64, contentType string, reader io.Reader, extraHeaders map[string]string, err error) {
name := ctx.Param("key")
_, buff, err := m3u8.TransformForTranscode(name, webg.Conf.OrigDomain, webg.Conf.CdnDomain, webg.Conf.WebM3u8Host, webg.Conf.LsjMediaConf.M3u8Yuan, webg.Conf.LsjMediaConf.TsYuan)
if err != nil {
return
}
contentType = "application/vnd.apple.mpegurl"
reader = bytes.NewReader(buff.Bytes())
contentLength = int64(buff.Len())
extraHeaders = map[string]string{}
return
}
handlerFile(ctx, fn)
}
func LsjEnkey(ctx *gin.Context) {
fn := func(c *gin.Context) (contentLength int64, contentType string, reader io.Reader, extraHeaders map[string]string, err error) {
buffer, err := m3u8.LsjEnkey(c)
if err != nil {
return
}
contentLength = int64(buffer.Len())
contentType = "application/octet-stream"
reader = buffer
extraHeaders = map[string]string{}
return
}
handlerFile(ctx, fn)
}
func handlerFile(ctx *gin.Context, h fileHandler) {
contentLength, contentType, reader, extraHeaders, err := h(ctx)
if err != nil {
common.ServerJSON(ctx, srvdef.DownloadM3u8File, err)
return
}
ctx.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
}
+111
View File
@@ -0,0 +1,111 @@
package web_video
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/videotagmod"
"videoweb/web/service/srv_videotag"
"github.com/gin-gonic/gin"
)
// @Tags 标签管理
// @Summary 分组分页获取标签管理
// @Description 分组分页获取标签管理
// @Accept json
// @Produce json
// @Param param body srv_videotag.VideoTagInfoReq true "参数列表"
// @Success 200 {object} srv_videotag.VideoTagInfoResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videotag/list [POST]
func GetVideoTagInfo(ctx *gin.Context) {
var req = &srv_videotag.VideoTagInfoReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_videotag.GetVideoTagInfos(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 标签管理
// @Summary 添加一个标签管理
// @Description 添加一个标签管理
// @Accept json
// @Produce json
// @Param param body videotagmod.VideoTagInfo true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videotag/add [POST]
func AddOneVideoTagInfo(ctx *gin.Context) {
var req = &videotagmod.VideoTagInfo{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_videotag.AddVideoTagInfo(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 标签管理
// @Summary 删除一个标签管理
// @Description 删除一个标签管理
// @Accept json
// @Produce json
// @Param param body srv_videotag.VideoTagInfoDelReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videotag/del [POST]
func DelOneVideoTagInfo(ctx *gin.Context) {
var req = &srv_videotag.VideoTagInfoDelReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_videotag.DelVideoTagInfo(ctx, req.Id)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 标签管理
// @Summary 更新一个标签管理
// @Description 更新一个标签管理
// @Accept json
// @Produce json
// @Param param body srv_videotag.VideoTagInfoUpdate true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videotag/update [POST]
func UpdateOneVideoTagInfo(ctx *gin.Context) {
var req = &srv_videotag.VideoTagInfoUpdateReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := srv_videotag.UpdateVideoTagInfo(ctx, req.Id, req.Param)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+344
View File
@@ -0,0 +1,344 @@
package web_video
import (
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/middleware/auth"
"videoweb/web/service/srv_videoinfo"
"github.com/gin-gonic/gin"
)
// @Tags 视频管理
// @Summary 分组分页获取视频管理
// @Description 分组分页获取视频管理
// @Accept json
// @Produce json
// @Param param body srv_videoinfo.VideoInfoReq true "参数列表"
// @Success 200 {object} srv_videoinfo.VideoInfoResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videoinfo/list [POST]
func GetVideoInfo(ctx *gin.Context) {
var req = &srv_videoinfo.VideoInfoReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_videoinfo.GetVideoInfos(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// SetVideoRecommend 单/批量设置视频是否推荐
// @Tags 视频管理
// @Summary 单/批量设置视频是否推荐 -- by 王鸣
// @Description 根据视频ID集合批量更新 video_information 集合 isRecommend 字段,传1个ID表示单条设置,传多个ID表示批量设置
// @Accept json
// @Produce json
// @Param param body srv_videoinfo.SetRecommendReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videoinfo/recommend/set [post]
func SetVideoRecommend(ctx *gin.Context) {
req := &srv_videoinfo.SetRecommendReq{}
if err := ctx.ShouldBindJSON(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
if err := srv_videoinfo.SetVideoRecommend(ctx, req); err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetVideoFakeLikes 单/批量设置视频假点赞数
// @Tags 视频管理
// @Summary 单/批量设置视频假点赞数 --by 旺鸣
// @Description 根据ids批量随机设置视频fake.likes,随机范围包含最小值和最大值
// @Accept json
// @Produce json
// @Param param body srv_videoinfo.SetFakeLikesReq true "参数列表"
// @Success 200 {object} srv_videoinfo.SetFakeCountResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videoinfo/setFakeLikes [post]
func SetVideoFakeLikes(ctx *gin.Context) {
req := &srv_videoinfo.SetFakeLikesReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
resp, err := srv_videoinfo.SetVideoFakeLikes(ctx, req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// SetVideoFakeWatchTimes 单/批量设置视频假观看次数
// @Tags 视频管理
// @Summary 单/批量设置视频假观看次数 --by 旺鸣
// @Description 根据ids批量随机设置视频fake.watchTimes,随机范围包含最小值和最大值
// @Accept json
// @Produce json
// @Param param body srv_videoinfo.SetFakeWatchTimesReq true "参数列表"
// @Success 200 {object} srv_videoinfo.SetFakeCountResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videoinfo/setFakeWatchTimes [post]
func SetVideoFakeWatchTimes(ctx *gin.Context) {
req := &srv_videoinfo.SetFakeWatchTimesReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
resp, err := srv_videoinfo.SetVideoFakeWatchTimes(ctx, req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// SetVideoHeat 单/批量设置视频热度
// @Tags 视频管理
// @Summary 单/批量设置视频热度 -- by 王鸣
// @Accept json
// @Produce json
// @Param param body srv_videoinfo.SetVideoHeatReq true "视频热度设置请求"
// @Success 200 {object} srv_videoinfo.SetFakeCountResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/web/videoinfo/heat/set [post]
func SetVideoHeat(ctx *gin.Context) {
req := &srv_videoinfo.SetVideoHeatReq{}
if err := ctx.ShouldBindJSON(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
resp, err := srv_videoinfo.SetVideoHeat(ctx, req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// /api/web/videoinfo/fillZeroFakeFlow [post]
func FillZeroVideoFakeFlow(ctx *gin.Context) {
//临时注释,有需要再放开
//resp, err := srv_videoinfo.FillZeroVideoFakeFlow(ctx)
//if err != nil {
// common.ServerJSON(ctx, err.Code, err.Tips)
// return
//}
//common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 视频管理
// @Summary 从切片列表同步多个视频
// @Description 从切片列表同步多个视频
// @Accept json
// @Produce json
// @Param param body srv_videoinfo.AddVideoReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videoinfo/sync [POST]
func SyncVideoInfo(ctx *gin.Context) {
var req = &srv_videoinfo.AddVideoReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_videoinfo.SyncVideoInfo(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 视频管理
// @Summary 从媒资库直同步到视频列表
// @Description 从媒资库直同步到视频列表,后续切片同步时按 mediaSourceId 覆盖
// @Accept json
// @Produce json
// @Param param body srv_videoinfo.SyncMediaFileReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videoinfo/syncMediaFile [POST]
func SyncVideoFromMediaFile(ctx *gin.Context) {
var req = &srv_videoinfo.SyncMediaFileReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
result, serr := srv_videoinfo.SyncVideoFromMediaFile(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, result)
}
// @Tags 视频管理
// @Summary 删除一个视频管理
// @Description 删除一个视频管理
// @Accept json
// @Produce json
// @Param param body srv_videoinfo.VideoInfoDelReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videoinfo/del [POST]
func DelOneVideoInfo(ctx *gin.Context) {
var req = &srv_videoinfo.VideoInfoDelReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_videoinfo.DelVideoInfo(ctx, req.Id)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 视频管理
// @Summary 更新一个视频管理
// @Description 更新一个视频管理
// @Accept json
// @Produce json
// @Param param body srv_videoinfo.VideoInfoUpdateReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videoinfo/update [POST]
func UpdateOneVideoInfo(ctx *gin.Context) {
var req = &srv_videoinfo.VideoInfoUpdateReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.New(srvdef.ErrParamError, err.Error(), err.Error()), nil)
return
}
userId := ctx.GetInt64(auth.AccId)
serr := srv_videoinfo.UpdateVideoInfo(ctx, req.Id, userId, req.Param)
if serr != nil {
common.ServerJSON(ctx, videoUpdateErr(serr), nil)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// videoUpdateErr 把业务错误里的具体原因带到接口提示里。
func videoUpdateErr(err *srvdef.SrvErr) *srvdef.SrvErr {
if err == nil {
return nil
}
if err.Tips == "" && err.Msg != "" && err.Msg != err.Code.Msg() {
return srvdef.New(err.Code, err.Msg, err.Msg)
}
return err
}
// @Tags 视频管理
// @Summary 新增一个视频合集
// @Description 新增一个视频合集
// @Accept json
// @Produce json
// @Param param body srv_videoinfo.AddVideoCollectionReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videoinfo/addcoll [POST]
func AddOneVideoCollection(ctx *gin.Context) {
var req = &srv_videoinfo.AddVideoCollectionReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// AddVideoTags 批量追加视频标签
// @Tags 视频管理
// @Summary 批量追加视频标签 -- by 王鸣
// @Description 根据视频ID集合批量追加统一标签,已存在的标签不会重复追加
// @Accept json
// @Produce json
// @Param param body srv_videoinfo.VideoAddTagsReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videoinfo/addTags [post]
func AddVideoTags(ctx *gin.Context) {
req := &srv_videoinfo.VideoAddTagsReq{}
if err := ctx.ShouldBindJSON(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
if err := srv_videoinfo.AddVideoTags(ctx, req); err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// SetVideoTags 单/批量设置视频标签
// @Tags 视频管理
// @Summary 单/批量设置视频标签 -- by 王鸣
// @Description 根据视频ID集合批量覆盖 video_information 集合 tags 字段,传1个ID表示单条设置,传多个ID表示批量设置,tagIds传空数组表示清空标签
// @Accept json
// @Produce json
// @Param param body srv_videoinfo.VideoSetTagsReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videoinfo/tag/set [post]
func SetVideoTags(ctx *gin.Context) {
req := &srv_videoinfo.VideoSetTagsReq{}
if err := ctx.ShouldBindJSON(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
if err := srv_videoinfo.SetVideoTags(ctx, req); err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
type TranscodeVideoReq struct {
Id int64 `json:"id" binding:"required"`
}
// @Tags 视频管理
// @Summary 提交视频 H265 转码
// @Router /api/web/videoinfo/transcode [POST]
func TranscodeVideo(ctx *gin.Context) {
var req TranscodeVideoReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if serr := srv_videoinfo.TranscodeVideo(ctx, req.Id); serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, nil)
}
@@ -0,0 +1,83 @@
package web_videocollection
import (
"github.com/gin-gonic/gin"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"videoweb/web/service/srv_videocollection"
)
// @Tags 合集管理
// @Summary 获取合集视频列表
// @Description 获取合集视频列表
// @Accept json
// @Produce json
// @Param param body srv_videocollection.GetCollectionMediaListReq true "参数列表"
// @Success 200 {object} srv_videocollection.GetCollectionMediaListResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videocollection/media/list [POST]
func GetVideoCollectionMediaList(ctx *gin.Context) {
var req = &srv_videocollection.GetCollectionMediaListReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, serr := srv_videocollection.GetCollectionMediaList(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// @Tags 合集管理
// @Summary 修改合集里的视频列表
// @Description 修改合集里的视频列表
// @Accept json
// @Produce json
// @Param param body srv_videocollection.VideoCollectionOptionMediaReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videocollection/media/option [POST]
func UpdateVideoCollectionMediaList(ctx *gin.Context) {
var req = &srv_videocollection.VideoCollectionOptionMediaReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_videocollection.VideoCollectionOptionMedia(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// @Tags 合集管理
// @Summary 修改合集里的视频排序
// @Description 修改合集里的视频排序
// @Accept json
// @Produce json
// @Param param body srv_videocollection.UpdateCollectionMediaRankReq true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/web/videocollection/media/rank [POST]
func UpdateVideoCollectionMediaRank(ctx *gin.Context) {
var req = &srv_videocollection.UpdateCollectionMediaRankReq{}
if err := ctx.ShouldBind(req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err)
return
}
serr := srv_videocollection.UpdateCollectionMediaRank(ctx, req)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+1
View File
@@ -0,0 +1 @@
—Џ€И’ љ БCЏ„
+39
View File
@@ -0,0 +1,39 @@
redis:
addr: 172.104.181.99:16789
db: 3
passwd: "B6vJHlYiTseLj77z"
mongodb:
addr: "mongodb://admin:TESTwfeZYP0kjBdy8DAUdwU@172.104.181.99:57017,172.104.181.99:57018,172.104.181.99:57019/web_mdcom?replicaSet=yctest&maxPoolSize=200&connectTimeout=30&authSource=admin"
logaddr: "mongodb://admin:TESTwfeZYP0kjBdy8DAUdwU@172.104.181.99:57017,172.104.181.99:57018,172.104.181.99:57019/web_mdcom_log?replicaSet=yctest&maxPoolSize=200&connectTimeout=30&authSource=admin"
es:
addr: "http://172.104.181.99:9200"
user: "elastic"
pass: "admin123456"
jwtKey: "2311b15a4da1c80dc541b99abb622233"
tgToken: ""
runMod: "dev"
tsAuthKey: "fT5xSg4hltHpzVy6aV9rVECDJ1J1pN"
pprof: false
host: "172.104.181.99"
listenAddr: "25121"
prefetchSubmitUrl: "http://172.104.171.80:9067/master/submit"
aiCenterAppId: 25222
aiUndressingCallbackUrl: "https://web_mdcomtest-ht.80sygtm.com/api/web/aiorder/strip/callback"
upAppId: 8
swagger:
host: "172.104.181.99"
user: "mdc"
pass: "2@6A1#9e%9c2"
bucketVideoAddressV2: "http://139.162.22.207:24996"
bucketVideoAddress: "http://tong3yuants.bbaazz.me"
# 媒资配置
mediaResourceDBCfg:
baseUrl: "https://mediav2-api.htycpc.com"
merchat: "91porn"
secret: "08f1c3ab5e11e9b6c18aa24c06d1eb77"
# 原创短剧数据回流到 AI 内容中台
dataCenterBackflow:
key: "ld_XLWM9pojLnf_OZFQ1ISac4cELop-WnJH_CcjS5D_ROY"
selfSourceBaseUrl: "https://172.104.181.99:25128/api/web/m3u8"
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
echo "开始"
rm -rf ./web_hghl_web ./web_hghl_web.tar.gz
GOOS=linux GOARCH=amd64 go build -o web_hghl_web
tar zvcf web_hghl_web.tar.gz web_hghl_web
scp web_hghl_web.tar.gz root@172.104.166.87:/data/uzip
ssh root@172.104.166.87 "/server/web_hghl/web/up_app.sh"
rm -rf ./web_hghl_web ./web_hghl_web.tar.gz
+13396
View File
File diff suppressed because it is too large Load Diff
+13376
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+66
View File
@@ -0,0 +1,66 @@
//go:generate swag init --parseDependency --parseDepth 4
package main
import (
"flag"
"os"
"videoweb/pub/common/srvversion"
"videoweb/web/server"
)
// @title 站群后台接口
// @version 1.0
// @description 这是站群后台接口服务.
// @termsOfService
// @contact.name
// @contact.url
// @contact.email
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host localhost:12667
// @BasePath /
// @Schemes http https
// @securityDefinitions.basic BasicAuth
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name Authorization
// @securitydefinitions.oauth2.application OAuth2Application
// @tokenUrl https://example.com/oauth/token
// @scope.write Grants write access
// @scope.admin Grants read and write access to administrative information
// @securitydefinitions.oauth2.implicit OAuth2Implicit
// @authorizationUrl https://example.com/oauth/authorize
// @scope.write Grants write access
// @scope.admin Grants read and write access to administrative information
// @securitydefinitions.oauth2.password OAuth2Password
// @tokenUrl https://example.com/oauth/token
// @scope.read Grants read access
// @scope.write Grants write access
// @scope.admin Grants read and write access to administrative information
// @securitydefinitions.oauth2.accessCode OAuth2AccessCode
// @tokenUrl https://example.com/oauth/token
// @authorizationUrl https://example.com/oauth/authorize
// @scope.admin Grants read and write access to administrative information
func cmdLine() {
info := flag.Bool("info", false, "show serivce build info")
//flagHander := flag.String("handler", "rpc", "set commuic ation type example rpc or mdns, default is rpc")
flag.Parse()
if *info {
srvversion.Info() //内部会自动退进程.
}
}
func main() {
cmdLine()
server.Run(os.Args)
}
+32
View File
@@ -0,0 +1,32 @@
package api_security
import (
"github.com/gin-gonic/gin"
)
func BodyDump() gin.HandlerFunc {
return func(ctx *gin.Context) {
// fmt.Println("=========================== 1")
// fmt.Printf("%+v\n", ctx.Request.Header)
// data, e := ioutil.ReadAll(ctx.Request.Body)
// if e != nil {
// ctx.AbortWithStatusJSON(500, "protosign: read data failed")
// return
// }
// fmt.Println("=========================== 3")
// fmt.Println(hex.Dump(data))
// fmt.Println("=========================== 4")
// ctx.Request.Body = &signReader{
// *bytes.NewReader(data),
// ctx.Request.Body,
// }
// fmt.Println("=========================== 5")
// ctx.Next()
// fmt.Println("=========================== 6")
}
}
+5
View File
@@ -0,0 +1,5 @@
package api_security
const XProtoSign = "X-Proto-Sign"
const XProtoNonce = "X-Proto-Nonce"
const XProtoTimestamp = "X-Proto-Timestamp"
+25
View File
@@ -0,0 +1,25 @@
package api_security
import (
"crypto/sha256"
"math/rand"
)
func GenerateKey(secret string) []byte {
key := sha256.Sum256([]byte(secret))
return key[:]
}
func GenerateIV(secret, salt string) []byte {
return GenerateKey(secret + salt)[:16]
}
const strPool = "012345679qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM"
func GenerateIVSalt() string {
var n [16]byte
for i := 0; i < 16; i++ {
n[i] = byte(strPool[rand.Intn(len(strPool))])
}
return string(n[:])
}
@@ -0,0 +1,16 @@
package api_security
import (
"fmt"
"testing"
)
func TestGenerateSalt(t *testing.T) {
for i := 0; i < 5; i++ {
fmt.Println(GenerateIVSalt())
}
}
func BenchmarkGenerateSalt(b *testing.B) {
GenerateIV("asdfasdfasdf", GenerateIVSalt())
}
+95
View File
@@ -0,0 +1,95 @@
package api_security
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"sort"
"strings"
"github.com/gin-gonic/gin"
)
type signReader struct {
bytes.Reader
RC io.ReadCloser
}
func (thiz *signReader) Close() error {
return thiz.RC.Close()
}
func calcSign(kv map[string][]byte) string {
keys := make([]string, 0, len(kv))
for k := range kv {
keys = append(keys, k)
}
sort.Strings(keys)
h := sha256.New()
for _, k := range keys {
_, _ = h.Write([]byte(k))
_, _ = h.Write(kv[k])
}
return strings.ToLower(hex.EncodeToString(h.Sum(nil)))
}
func ProtoSign(secret []byte,
shouldCrypto ShouldCryptoChecker) gin.HandlerFunc {
return func(ctx *gin.Context) {
if shouldCrypto != nil && !shouldCrypto(ctx) {
ctx.Next()
return
}
sign := ctx.GetHeader(XProtoSign)
nonce := ctx.GetHeader(XProtoNonce)
ts := ctx.GetHeader(XProtoTimestamp)
if len(sign) != 64 || len(nonce) < 10 || len(ts) < 6 {
ctx.AbortWithStatusJSON(500, "protosign: argument invalid")
return
}
data, e := ioutil.ReadAll(ctx.Request.Body)
if e != nil {
ctx.AbortWithStatusJSON(500, "protosign: read data failed")
return
}
kv := make(map[string][]byte)
kv[XProtoNonce] = []byte(nonce)
kv[XProtoTimestamp] = []byte(ts)
kv["_METHOD_"] = []byte(ctx.Request.Method)
kv["_PATH_"] = []byte(ctx.Request.URL.Path)
kv["_SECRET_"] = secret
queries := map[string][]string(ctx.Request.URL.Query())
for k, v := range queries {
if len(v) > 0 {
kv[fmt.Sprintf("_QUERY_%s_", strings.ToUpper(k))] = []byte(v[0])
}
}
if len(data) > 0 {
kv["_BODY_"] = []byte(data)
}
if calcSign(kv) != sign {
ctx.AbortWithStatusJSON(500, "protosign: verify sign failed")
return
}
ctx.Request.Body = &signReader{
*bytes.NewReader(data),
ctx.Request.Body,
}
ctx.Next()
}
}
+16
View File
@@ -0,0 +1,16 @@
package api_security
import (
"fmt"
"net/url"
"testing"
)
func TestUrl(t *testing.T) {
u, _ := url.Parse("http://a.b.com/api/a/b/c?a=%20123")
fmt.Printf("path: %s\n", u.Path)
fmt.Printf("rawpath: %s\n", u.RawQuery)
fmt.Printf("escapedpath: %s\n", u.EscapedPath())
}
+38
View File
@@ -0,0 +1,38 @@
package api_security
import (
"crypto/cipher"
"io"
"github.com/gin-gonic/gin"
)
type ShouldCryptoChecker func(ctx *gin.Context) bool
type cryptoReader struct {
S cipher.Stream
RC io.ReadCloser
}
func (r *cryptoReader) Read(dst []byte) (n int, err error) {
n, err = r.RC.Read(dst)
r.S.XORKeyStream(dst[:n], dst[:n])
return
}
func (r *cryptoReader) Close() error {
return r.RC.Close()
}
type cryptoWriter struct {
gin.ResponseWriter
writer *cipher.StreamWriter
}
func (g *cryptoWriter) WriteString(s string) (int, error) {
return g.writer.Write([]byte(s))
}
func (g *cryptoWriter) Write(data []byte) (int, error) {
return g.writer.Write(data)
}
@@ -0,0 +1,84 @@
package apilimitHandler
import (
"net/http"
"sync"
"time"
"github.com/gin-gonic/gin"
)
type counter struct {
Count int
WindowStart time.Time
}
type RouteHourlyLimiter struct {
mu sync.Mutex
limit int
window time.Duration
counters map[string]*counter
}
func NewRouteHourlyLimiter(limit int) *RouteHourlyLimiter {
l := &RouteHourlyLimiter{
limit: limit,
window: time.Hour,
counters: make(map[string]*counter),
}
go l.cleaner()
return l
}
func (l *RouteHourlyLimiter) Middleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 用 FullPath 做“接口维度”,例如 /api/user/:id
route := c.FullPath()
if route == "" {
// 路由未匹配时兜底
route = c.Request.URL.Path
}
now := time.Now()
l.mu.Lock()
defer l.mu.Unlock()
item, ok := l.counters[route]
if !ok || now.Sub(item.WindowStart) >= l.window {
l.counters[route] = &counter{
Count: 1,
WindowStart: now,
}
c.Next()
return
}
if item.Count >= l.limit {
c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{
"code": http.StatusTooManyRequests,
"message": "rate limit exceeded: max 100 requests per route per hour",
})
return
}
item.Count++
c.Next()
}
}
// 定时清理过期窗口,避免 map 无限增长
func (l *RouteHourlyLimiter) cleaner() {
ticker := time.NewTicker(10 * time.Minute)
defer ticker.Stop()
for now := range ticker.C {
l.mu.Lock()
for k, v := range l.counters {
if now.Sub(v.WindowStart) >= l.window {
delete(l.counters, k)
}
}
l.mu.Unlock()
}
}
+298
View File
@@ -0,0 +1,298 @@
package auth
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"net/http"
"strings"
"sync"
"videoweb/pub/common"
"videoweb/pub/common/errors"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"videoweb/pub/common/utils"
"videoweb/pub/models/mwacc"
"videoweb/pub/models/oplog"
"videoweb/web/webg"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
)
var (
RoleApiMenus = map[int64][]string{} // 角色Api
mutex sync.RWMutex
)
var (
tokener = utils.NewTokenRedis()
)
const (
AccId = "ACC_ID"
roleAuthAdrr = "/web/role/getauth"
)
type APIInfo struct {
Api string
Desc string
}
var (
// 白名单,不需要验证token的api
whiteList = []string{
"/swagger",
"/api/web/file/uploadImg",
"/api/web/file/uploadImgs",
"/api/web/media/videoBody",
"/api/web/media/videoOk",
"/api/web/m3u8",
"/api/web/uploader/m3u8",
"/api/web/enkey",
"/api/web/login/acc",
"/api/web/login/bind",
"/api/web/login/slogin",
"/api/web/stat/media/list",
"/api/web/stat/analytics",
"/api/web/stat/daily/analytics",
"/api/web/sync/video/list",
"/api/web/sync/videocollection/list",
"/api/web/sync/category/list",
"/api/web/sync/creator/list",
"/api/web/sync/tag/list",
"/api/web/contentexcel",
"/api/web/videoinfo/fillZeroFakeFlow",
"/wbapi",
}
)
// 读取角色信息
func GetRoleApiMenus(ctx context.Context, accid int64) (roles []string, err error) {
mutex.RLock()
roles, ok := RoleApiMenus[accid]
mutex.RUnlock()
if !ok {
accInfo, dataErr := mwacc.FindOneAccByFilter(nil, bson.M{mwacc.FN.MwAcc.Id: accid})
if dataErr != nil || accInfo.Id == 0 {
return roles, dataErr
}
roleInfo, roleErr := mwacc.FindOneRoleByFilter(ctx, bson.M{mwacc.FN.MwRole.Id: accInfo.RoleId})
if roleErr != nil || roleInfo.Id == 0 {
return roles, roleErr
}
if roleInfo.Name == "超级管理员" {
return nil, nil
}
mutex.Lock()
RoleApiMenus[accid] = roleInfo.ApiMenus
mutex.Unlock()
roles = roleInfo.ApiMenus
}
return
}
// 是否角色api
func HasRoleApi(path string, apis []string) bool {
apimap := make(map[string]struct{})
for _, v := range apis {
apimap[v] = struct{}{}
}
_, ok := apimap[path]
return ok
}
// 角色权限
func handleRoles(ctx *gin.Context) (int, error) {
path := ctx.Request.URL.Path
if strings.HasPrefix(path, roleAuthAdrr) {
return 0, nil
}
accid := ctx.GetInt(AccId)
apis, err := GetRoleApiMenus(ctx, int64(accid))
if err != nil {
return int(errors.RoleErr), err
}
if apis == nil {
return 0, nil
}
has := HasRoleApi(path, apis)
if !has {
return int(errors.RoleErr), srvdef.New(srvdef.RoleErr, (srvdef.RoleErr).Msg(), "")
}
return 0, nil
}
// 楼风经纪人权限
func handleLouFengBossRoles(ctx *gin.Context) (int, error) {
path := ctx.Request.URL.Path
if strings.HasPrefix(path, roleAuthAdrr) {
return 0, nil
}
accid := ctx.GetInt64(AccId)
accInfo, dataErr := mwacc.FindOneAccByFilter(nil, bson.M{mwacc.FN.MwAcc.Id: accid})
if dataErr != nil || accInfo.Id == 0 {
return int(errors.RoleErr), dataErr
}
return 0, nil
}
// 验证后台账号IP
func authMwIP(ctx *gin.Context) (int, error) {
cIP := ctx.ClientIP()
accid := ctx.GetInt64(AccId)
accInfo, dataErr := mwacc.FindOneAccByFilter(nil, bson.M{mwacc.FN.MwAcc.Id: accid})
if dataErr != nil || accInfo.Id == 0 {
return int(errors.RoleErr), dataErr
}
if len(accInfo.LimitIP) != 0 {
for _, v := range accInfo.LimitIP {
if v == cIP {
return 0, nil
}
}
return int(errors.LimitIPErr), dataErr
} else {
return int(errors.LimitIPErr), dataErr
}
// return 0, nil
}
// 验证
func Auth(ctx *gin.Context) {
//for test
//ctx.Set(AccId, int64(1000))
//return
p := ctx.Request.URL.Path
if strings.Contains(p, "swagger") {
return
}
for _, w := range whiteList {
if strings.HasPrefix(ctx.Request.URL.Path, w) {
return
}
}
if v, ok := common.ApiSetMaps[p]; ok {
fmt.Println(v.IsWhite)
if v.IsWhite {
return
}
}
doToken := func() (int, error) {
checkToken := ctx.Request.Header.Get("Authorization")
// 去掉Bearer,如果有
checkToken = utils.StripBearerPrefixFromTokenString(checkToken)
if checkToken == "" {
return http.StatusUnauthorized, srvdef.New(srvdef.NoToken, (srvdef.NoToken).Msg(), "")
}
has, err := mwacc.CheckToken(ctx, checkToken)
if err != nil {
return http.StatusUnauthorized, err
}
if !has {
return http.StatusUnauthorized, srvdef.New(srvdef.ReLogin, (srvdef.ReLogin).Msg(), "")
}
userId, _, err := utils.ParseUserToken(checkToken, webg.Conf.JwtKey)
if err != nil {
return http.StatusUnauthorized, srvdef.New(srvdef.InvalidToken, (srvdef.InvalidToken).Msg(), "")
}
// log.Info("Auth test", log.Any("checkToken", checkToken), log.Any("userId", userId))
ctx.Set(AccId, userId)
return 0, nil
}
statusCode, err := doToken()
if err != nil || statusCode != 0 {
ctx.AbortWithStatusJSON(statusCode, err)
return
}
roleCode, err := handleRoles(ctx)
if err != nil || roleCode != 0 {
ctx.AbortWithStatusJSON(http.StatusForbidden, err)
}
roleCode1, err1 := handleLouFengBossRoles(ctx)
if err1 != nil || roleCode1 != 0 {
ctx.AbortWithStatusJSON(http.StatusForbidden, err)
}
// authIPCode, err2 := authMwIP(ctx)
// if err2 != nil || authIPCode != 0 {
// ctx.AbortWithStatusJSON(http.StatusForbidden, err)
// }
}
// func userAgentHandler(ctx *gin.Context) {
// userAgent := ctx.Request.Header.Get("User-Agent")
// if userAgent != "" {
// fields := strings.Fields(userAgent)
// curVersion := fields[len(fields)-1]
// if strings.HasPrefix(curVersion, "version:") {
// versionNum := strings.Split(curVersion, ":")[1]
// ctx.Set("VERSION", versionNum)
// } else {
// ctx.Set("VERSION", "")
// }
// }
// if strings.Contains(userAgent, "Android") {
// ctx.Set("SYSTEM", "android")
// }
// if strings.Contains(userAgent, "iPhone") {
// ctx.Set("SYSTEM", "ios")
// }
// // 增加 不签名,不加密 开关
// }
// 操作日志
func OperateLog(ctx *gin.Context) {
desc := ""
find := false
for _, w := range LogList {
if ctx.Request.URL.Path == w.Api {
find = true
desc = w.Desc
}
}
if !find {
ctx.Next()
return
}
accId := ctx.GetInt64(AccId)
rawData, err := ctx.GetRawData()
ip := ctx.ClientIP()
if err != nil {
ctx.AbortWithStatusJSON(400, err)
}
log.Info("OperateLog Test", log.Any("vmap.Path", ctx.Request.URL.Path))
err = oplog.AddLog(ctx, ctx.Request.URL.Path, desc, accId, string(rawData), ip)
if err != nil {
ctx.AbortWithStatusJSON(int(errors.OperateLog), err)
return
}
ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(rawData)) // 将取出来的执行条件放回ctx中
ctx.Next()
}
func GetAccount(ctx *gin.Context) int64 {
return ctx.GetInt64(AccId)
}
+94
View File
@@ -0,0 +1,94 @@
package auth
var LogList = []APIInfo{
{"/api/web/acc/add", "账号-添加"},
{"/api/web/acc/del", "账号-删除"},
{"/api/web/acc/up", "账号-更新"},
{"/api/web/acc/savestatus", "账号-保存状态"},
{"/api/web/acc/uppwd", "账号-更新密码"},
{"/api/web/login/acc", "登录-登录"},
{"/api/web/login/slogin", "管理员sso登陆"},
{"/api/web/role/add", "角色-添加"},
{"/api/web/role/del", "角色-删除"},
{"/api/web/role/up", "角色-更新"},
{"/api/web/role/enable", "角色-使能"},
{"/api/web/role/upauth", "角色-更新权限"},
{"/api/web/syscfg/update", "修改系统配置"},
{"/api/web/syscfg/appkey", "设置媒资库appKey"},
{"/api/web/post/comment/del", "删除一个评论"},
{"/api/web/post/comment/user/del", "删除一个用户所有评论"},
{"/api/web/post/comment/replay", "回复评论"},
{"/api/web/post/comment/reviewBatch", "批量审核评论"},
{"/api/web/post/comment/review", "审核评论"},
{"/api/web/ipblack/add", "IP黑名单-增加"},
{"/api/web/ipblack/del", "IP黑名单-删除"},
{"/api/web/richtextcontent/add", "添加一个富文本内容"},
{"/api/web/richtextcontent/del", "删除一个富文本内容"},
{"/api/web/richtextcontent/update", "更新一个富文本内容"},
{"/api/web/translationcategory/add", "添加一个导航分类"},
{"/api/web/translationcategory/del", "删除一个导航分类"},
{"/api/web/translationcategory/update", "更新一个导航分类"},
{"/api/web/translation/add", "添加一个导航跳转信息"},
{"/api/web/translation/del", "删除一个导航跳转信息"},
{"/api/web/translation/update", "更新一个导航跳转信息"},
{"/api/web/videocategory/add", "添加一个视频分类"},
{"/api/web/videocategory/del", "删除一个视频分类"},
{"/api/web/videocategory/update", "更新一个视频分类"},
{"/api/web/videocreater/add", "添加一个视频作者"},
{"/api/web/videocreater/del", "删除一个视频作者"},
{"/api/web/videocreater/update", "更新一个视频作者"},
{"/api/web/videotag/add", "添加一个标签管理"},
{"/api/web/videotag/del", "删除一个标签管理"},
{"/api/web/videotag/update", "更新一个标签管理"},
{"/api/web/videoinfo/del", "删除一个视频管理"},
{"/api/web/videoinfo/update", "更新一个视频管理"},
{"/api/web/videoinfo/recommend/set", "视频-设置推荐"},
{"/api/web/videoinfo/heat/set", "视频-设置热度"},
{"/api/web/videocollection/media/option", "修改合集里的视频列表"},
{"/api/web/videocollection/media/rank", "修改合集里的视频排序"},
{"/api/web/videoinfo/addcoll", "新增一个视频合集"},
{"/api/web/videoinfo/addTags", "视频-批量追加标签"},
{"/api/web/videoinfo/fillZeroFakeFlow", "批量填充低播放量/低收藏视频假数据"},
{"/api/web/actress/add", "添加一个女优信息"},
{"/api/web/actress/del", "删除一个女优信息"},
{"/api/web/actress/update", "更新一个女优信息"},
{"/api/web/playlet/add", "短剧-新增"},
{"/api/web/playlet/update", "短剧-编辑"},
{"/api/web/playlet/del", "短剧-删除"},
{"/api/web/playlet/status/set", "短剧-设置上下架"},
{"/api/web/playlet/recommend/set", "短剧-设置推荐"},
{"/api/web/playlet/featured/set", "短剧-设置爆剧"},
{"/api/web/playlet/banner/set", "短剧-设置banner展示"},
{"/api/web/playlet/theme/set", "短剧-设置题材"},
{"/api/web/playlet/tag/set", "短剧-设置标签"},
{"/api/web/playlet/like/virtual/set", "短剧-设置虚拟点赞数"},
{"/api/web/playlet/browse/virtual/set", "短剧-设置虚拟观看数"},
{"/api/web/playlet/heat/virtual/set", "短剧-设置虚拟热度"},
{"/api/web/playlet/pay-type/set", "短剧-设置支付方式"},
{"/api/web/playlet/watermark/reset", "短剧-重置水印"},
{"/api/web/playlet/chapter/add", "短剧剧集-新增"},
{"/api/web/playlet/chapter/update", "短剧剧集-更新"},
{"/api/web/playlet/chapter/del", "短剧剧集-删除"},
{"/api/web/playlet/chapter/pay-type/set", "短剧剧集-设置支付方式"},
{"/api/web/playlet/chapter/sync", "短剧剧集-手动同步"},
{"/api/web/playlet/category/set", "短剧-设置分类"},
{"/api/web/playlet/category/add", "短剧分类-新增"},
{"/api/web/playlet/category/update", "短剧分类-更新"},
{"/api/web/playlet/category/del", "短剧分类-删除"},
{"/api/web/playlet/home-config/add", "短剧首页配置-新增"},
{"/api/web/playlet/home-config/update", "短剧首页配置-更新"},
{"/api/web/playlet/home-config/del", "短剧首页配置-删除"},
{"/api/web/playlet/theme/add", "短剧题材-新增"},
{"/api/web/playlet/theme/update", "短剧题材-更新"},
{"/api/web/playlet/theme/del", "短剧题材-删除"},
{"/api/web/home/banner/add", "首页banner-新增"},
{"/api/web/home/banner/update", "首页banner-更新"},
{"/api/web/home/banner/del", "首页banner-删除"},
{"/api/web/announcement/add", "公告-增加"},
{"/api/web/announcement/del", "公告-删除"},
{"/api/web/announcement/update", "公告-更新"},
{"/api/web/content/tag/add", "统一标签-新增"},
{"/api/web/content/tag/update", "统一标签-更新"},
{"/api/web/content/tag/del", "统一标签-删除"},
{"/api/web/slug/sync", "同步历史空slug"},
}
+135
View File
@@ -0,0 +1,135 @@
package cors
import (
"github.com/gin-gonic/gin"
"net/http"
"strconv"
"strings"
)
type Options struct {
Origin *[]string // 传入空指针,表示允许"*", 传入空数组表示禁止跨域
Methods []string // Methods
AllowedHeaders []string // AllowHeaders
ExposedHeaders []string // exposeHeader
Credentials bool // cookie
MaxAge int64 // 缓存MaxAge
PreflightContinue bool // 在遇到Options的时候,继续,而不是返回请求
OptionsSuccessStatus int // Options时,返回的状态码,默认204
}
func configureOrigin(o *Options, c *gin.Context) map[string]string {
reqOrigin := c.GetHeader("Origin")
headers := make(map[string]string)
if o.Origin == nil {
headers["Access-Control-Allow-Origin"] = "*"
} else {
isAllowed := false
for _, allowed := range *o.Origin {
if allowed == reqOrigin {
isAllowed = true
break
}
}
if isAllowed {
headers["Access-Control-Allow-Origin"] = reqOrigin
} else {
headers["Access-Control-Allow-Origin"] = strconv.FormatBool(false)
}
headers["Vary"] = "Origin"
}
return headers
}
func configureMethods(o *Options) map[string]string {
headers := make(map[string]string)
if len(o.Methods) > 0 {
headers["Access-Control-Allow-Methods"] = strings.ToUpper(strings.Join(o.Methods, ","))
}
return headers
}
func configureCredentials(o *Options) map[string]string {
headers := make(map[string]string)
if o.Credentials {
headers["Access-Control-Allow-Credentials"] = strconv.FormatBool(true)
}
return headers
}
func configureAllowedHeaders(o *Options, c *gin.Context) map[string]string {
headers := make(map[string]string)
if len(o.AllowedHeaders) > 0 {
headers["Access-Control-Allow-Headers"] = strings.Join(o.AllowedHeaders, ",")
}
return headers
}
func configureExposedHeaders(o *Options) map[string]string {
var headers = make(map[string]string)
if len(o.ExposedHeaders) > 0 {
headers["Access-Control-Expose-Headers"] = strings.Join(o.ExposedHeaders, ",")
}
return headers
}
func configureMaxAge(o *Options) map[string]string {
var headers = make(map[string]string)
if o.MaxAge >= 0 {
headers["Access-Control-Max-Age"] = strconv.FormatInt(o.MaxAge, 10)
}
return headers
}
func mergeMap(m ...map[string]string) map[string]string {
r := make(map[string]string)
for _, t := range m {
for k, v := range t {
r[k] = v
}
}
return r
}
func applyHeader(c *gin.Context, h map[string]string) {
for k, v := range h {
c.Header(k, v)
}
}
// Cors 跨域处理
func Cors(o *Options) gin.HandlerFunc {
if o.OptionsSuccessStatus == 0 {
o.OptionsSuccessStatus = http.StatusNoContent
}
return func(c *gin.Context) {
method := c.Request.Method
// c.Header("Access-Control-Allow-Origin", "*")
// c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token,Authorization,Token,Content-Length,Etag,Content-Range,Accept-Ranges,User-Agent,Range,Bucket,Content-Disposition,Signature,X-Forwarded-For,X-Real-Ip")
if method == "OPTIONS" {
h := mergeMap(
configureOrigin(o, c),
configureCredentials(o),
configureMethods(o),
configureAllowedHeaders(o, c),
configureMaxAge(o),
configureExposedHeaders(o),
)
applyHeader(c, h)
if o.PreflightContinue {
c.Next()
} else {
c.Header("Content-Length", "0")
c.AbortWithStatus(o.OptionsSuccessStatus)
}
} else {
h := mergeMap(
configureOrigin(o, c),
configureCredentials(o),
configureExposedHeaders(o),
)
applyHeader(c, h)
c.Next()
}
}
}
+16
View File
@@ -0,0 +1,16 @@
package ipblacklist
import (
"errors"
"github.com/gin-gonic/gin"
"net/http"
"videoweb/web/service/srv_ipblack"
)
func IpBlackListMiddleware(ctx *gin.Context) {
ip := ctx.ClientIP()
if srv_ipblack.CheckIp(ip) {
ctx.AbortWithStatusJSON(http.StatusUnauthorized, errors.New("login limit"))
return
}
}
+120
View File
@@ -0,0 +1,120 @@
package limitHandler
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
"videoweb/pub/common"
httpUtil "videoweb/pub/common/http"
"videoweb/pub/common/srvdef"
"videoweb/web/webg"
"github.com/gin-gonic/gin"
"github.com/patrickmn/go-cache"
)
var limitURI = []string{
"/api/web/login/slogin",
"/api/web/login/acc",
}
var (
tgBotToken = "2013237388:AAFwvKvEmQfEvcI7wt_64Zkp9KPfgHo8sow"
tgGroupId = "-1003735177636"
)
var (
limitDuration = time.Minute
limitCount = 5
)
var memCache = cache.New(1*time.Minute, 10*time.Minute)
// LoginLimit 登陆频率限制:按账号维度限制,不依赖 ClientIP(可被伪造)。
func LoginLimit(ctx *gin.Context) {
path := ctx.Request.URL.Path
check := false
for _, p := range limitURI {
if strings.HasPrefix(path, p) {
check = true
break
}
}
if !check {
ctx.Next()
return
}
// 测试环境不限制
if webg.Conf.RunMod != "prod" {
ctx.Next()
return
}
var params map[string]interface{}
var acc string
if ctx.Request.Method == http.MethodPost {
raw, _ := ctx.GetRawData()
ctx.Request.Body = io.NopCloser(bytes.NewBuffer(raw))
if err := json.Unmarshal(raw, &params); err == nil {
if a, ok := params["acc"].(string); ok {
acc = strings.TrimSpace(a)
}
}
}
// 无账号时无法按账号限流,交由后续登录逻辑处理参数错误
if acc == "" {
ctx.Next()
return
}
key := fmt.Sprintf("web-limit:%s:%s", path, acc)
count := 1
if aCount, ok := memCache.Get(key); ok {
if n, ok2 := aCount.(int); ok2 {
count = n + 1
}
}
memCache.Set(key, count, limitDuration)
if count > limitCount {
go func(acc, path string, count int, params map[string]interface{}) {
message := fmt.Sprintf(
"[91porn精选]\n登陆请求频率过高!\n时间: %s\n请求地址: %s\n账号: %s\n请求参数: %+v\n错误次数: %d",
time.Now().Format("2006-01-02 15:04:05"),
path,
acc,
params,
count,
)
// 请求地址/参数为不可信输入,去掉非法 UTF-8 字节;不用 parse_mode,避免 Markdown 把内容解析成实体后报错
message = strings.ToValidUTF8(message, "")
url := fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage", tgBotToken)
req := map[string]interface{}{
"chat_id": tgGroupId,
"text": message,
}
jsonBytes, err := json.Marshal(req)
if err != nil {
return
}
header := map[string]string{"Content-Type": "application/json"}
resp, _ := httpUtil.Post(url, header, bytes.NewReader(jsonBytes))
_ = resp.Data
}(acc, path, count, params)
common.ServerJSON(ctx, srvdef.ErrReqForbidden, nil)
ctx.Abort()
return
}
ctx.Next()
}
@@ -0,0 +1,81 @@
package validator
import (
"reflect"
"strings"
"sync"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/locales/en"
ut "github.com/go-playground/universal-translator"
"gopkg.in/go-playground/validator.v9"
en_translations "gopkg.in/go-playground/validator.v9/translations/en"
)
var (
ValidatorUni *ut.UniversalTranslator
)
type defaultValidator struct {
once sync.Once
validate *validator.Validate
}
var v binding.StructValidator = &defaultValidator{}
func init() {
v.Engine()
}
func (v *defaultValidator) ValidateStruct(obj interface{}) error {
if kindOfData(obj) == reflect.Struct {
v.lazyinit()
if err := v.validate.Struct(obj); err != nil {
return error(err)
}
}
return nil
}
func (v *defaultValidator) Engine() interface{} {
v.lazyinit()
return v.validate
}
func (v *defaultValidator) lazyinit() {
v.once.Do(func() {
v.validate = validator.New()
// 依旧使用bingding tag兼容v8
v.validate.SetTagName("binding")
// 错误信息转换
en := en.New()
ValidatorUni = ut.New(en, en)
trans, _ := ValidatorUni.GetTranslator("en")
en_translations.RegisterDefaultTranslations(v.validate, trans)
v.validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("comment"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
})
}
func kindOfData(data interface{}) reflect.Kind {
value := reflect.ValueOf(data)
valueType := value.Kind()
if valueType == reflect.Ptr {
valueType = value.Elem().Kind()
}
return valueType
}
+11
View File
@@ -0,0 +1,11 @@
package validator
import (
"github.com/gin-gonic/gin/binding"
)
// 替换gin 默认v8验证器
// 改为v9
func init() {
binding.Validator = new(defaultValidator)
}
+16
View File
@@ -0,0 +1,16 @@
package router
import (
"github.com/gin-gonic/gin"
"videoweb/web/api/web_actress"
)
func actressRouter(router *gin.RouterGroup) {
post := router.Group("/actress")
{
post.GET("/list", web_actress.Get)
post.POST("/update", web_actress.Update)
post.POST("/del", web_actress.Del)
post.POST("/add", web_actress.Add)
}
}
+17
View File
@@ -0,0 +1,17 @@
package router
import (
"videoweb/web/api/web_announcement"
"github.com/gin-gonic/gin"
)
func announcementRouter(router *gin.RouterGroup) {
group := router.Group("/announcement")
{
group.POST("/list", web_announcement.AnnouncementList)
group.POST("/add", web_announcement.AnnouncementAdd)
group.POST("/del", web_announcement.AnnouncementDel)
group.POST("/update", web_announcement.AnnouncementUpdate)
}
}
+17
View File
@@ -0,0 +1,17 @@
package router
import (
"github.com/gin-gonic/gin"
"videoweb/web/api/web_app"
)
func appSyncRouter(router *gin.RouterGroup) {
sync := router.Group("/sync")
{
sync.POST("/video/list", web_app.AppSyncReq)
sync.POST("/videocollection/list", web_app.AppCollectionSyncReq)
sync.POST("/category/list", web_app.AppGetVideoCategory)
sync.POST("/creator/list", web_app.AppGetVideoCreator)
sync.POST("/tag/list", web_app.AppGetVideoTag)
}
}
+23
View File
@@ -0,0 +1,23 @@
package router
import (
webanalytics "videoweb/web/api/web_analytics"
"videoweb/web/api/web_cfg"
"github.com/gin-gonic/gin"
)
func syscfgRouter(router *gin.RouterGroup) {
system := router.Group("/syscfg")
{
system.GET("/get", web_cfg.GetCfg)
system.POST("/update", web_cfg.UpdateCfg)
system.POST("/appkey", web_cfg.SetAppKey)
}
stat := router.Group("/stat")
{
stat.GET("/analytics", webanalytics.GetAnalyticsStat)
stat.GET("/daily/analytics", webanalytics.GetAnalyticsDailyStat)
}
}
+19
View File
@@ -0,0 +1,19 @@
package router
import (
"videoweb/web/api/web_commend"
"github.com/gin-gonic/gin"
)
func commentRouter(router *gin.RouterGroup) {
group := router.Group("/post")
{
group.POST("/comment/list", web_commend.SearchManyCommend)
group.POST("/comment/replay", web_commend.ReplayPostComment)
group.POST("/comment/del", web_commend.DelCommend)
group.POST("/comment/user/del", web_commend.DelUserCommend)
group.POST("/comment/reviewBatch", web_commend.ReviewCommendBatch)
group.POST("/comment/review", web_commend.ReviewComment)
}
}
+16
View File
@@ -0,0 +1,16 @@
package router
import (
"videoweb/web/api/web_contactus"
"github.com/gin-gonic/gin"
)
func contactusRouter(router *gin.RouterGroup) {
group := router.Group("/contactus")
{
group.POST("/list", web_contactus.ContactusList)
group.POST("/del", web_contactus.Del)
group.POST("/update", web_contactus.Update)
}
}
+18
View File
@@ -0,0 +1,18 @@
package router
import (
"videoweb/web/api/web_contenttag"
"github.com/gin-gonic/gin"
)
func contentTagRouter(router *gin.RouterGroup) {
group := router.Group("/content/tag")
{
group.GET("/list", web_contenttag.List)
group.GET("/option", web_contenttag.Option)
group.POST("/add", web_contenttag.Add)
group.POST("/update", web_contenttag.Update)
group.POST("/del", web_contenttag.Del)
}
}
+15
View File
@@ -0,0 +1,15 @@
package router
import (
"videoweb/web/api/web_contentexcel"
"github.com/gin-gonic/gin"
)
func contentExcelRouter(rootRouter *gin.RouterGroup) {
group := rootRouter.Group("/contentexcel")
{
group.GET("/export", web_contentexcel.Export)
group.POST("/import", web_contentexcel.Import)
}
}
+17
View File
@@ -0,0 +1,17 @@
package router
import (
"videoweb/web/api/web_detailnav"
"github.com/gin-gonic/gin"
)
func detailNavRouter(router *gin.RouterGroup) {
group := router.Group("/detailnav")
{
group.POST("/list", web_detailnav.DetailNavList)
group.POST("/add", web_detailnav.DetailNavAdd)
group.POST("/del", web_detailnav.DetailNavDel)
group.POST("/update", web_detailnav.DetailNavUpdate)
}
}
+16
View File
@@ -0,0 +1,16 @@
package router
import (
"videoweb/web/api/web_file"
"github.com/gin-gonic/gin"
)
func fileRouter(router *gin.RouterGroup) {
// 文件上传
file := router.Group("/file")
{
file.POST("/uploadImg", web_file.UploadImage)
file.POST("/uploadImgs", web_file.UploadImages)
}
}
+122
View File
@@ -0,0 +1,122 @@
package router
import (
"fmt"
"net/http"
"videoweb/pub/common/errors"
"videoweb/pub/common/log"
"videoweb/pub/common/useragent"
"videoweb/web/middleware/auth"
"videoweb/web/middleware/cors"
"videoweb/web/middleware/ipblacklist"
"videoweb/web/middleware/limitHandler"
"videoweb/web/webg"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"github.com/DeanThompson/ginpprof"
"github.com/gin-gonic/gin"
_ "videoweb/web/docs"
)
func Init() (engine *gin.Engine) {
// 设置启动模式
switch webg.Conf.RunMod {
case "dev":
gin.SetMode(gin.DebugMode)
case "test":
gin.SetMode(gin.TestMode)
case "prod":
gin.SetMode(gin.ReleaseMode)
default:
gin.SetMode(gin.DebugMode)
}
// 初始化gin引擎
engine = gin.Default()
engine.HandleMethodNotAllowed = true
engine.MaxMultipartMemory = 60 << 20
engine.NoMethod(noMethod)
engine.NoRoute(noRoute)
// 注册中间件
registeMiddleware(engine)
wbVideoDataRouter(engine)
registerRouter(engine)
log.Info("setGinSwaggerxxxxx")
if webg.Conf.RunMod != "prod" {
log.Info("setGinSwagger")
setGinSwagger(engine)
log.Info("setGinSwagger end")
}
// 是否开启监控服务
if webg.Conf.Pprof {
ginpprof.Wrap(engine)
}
return
}
func noMethod(c *gin.Context) {
c.JSON(http.StatusMethodNotAllowed, errors.MakeWithMsg(errors.MethodNotFound, "MethodNotFound"))
}
func noRoute(c *gin.Context) {
c.JSON(http.StatusNotFound, errors.MakeWithMsg(errors.ApiNotFound, "ApiNotFound"))
}
func registeMiddleware(engine *gin.Engine) {
engine.Use(gin.Recovery())
engine.Use(cors.Cors(&cors.Options{
Origin: nil, // "*"
Methods: []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodHead, http.MethodDelete},
AllowedHeaders: []string{"Content-Length", "Content-Type", "Authorization", "X-User-Agent", useragent.SDKCommonHeader},
ExposedHeaders: []string{"Content-Disposition", "Refresh-Authorization"},
OptionsSuccessStatus: http.StatusOK,
}))
engine.Use(ipblacklist.IpBlackListMiddleware)
engine.Use(auth.Auth)
engine.Use(limitHandler.LoginLimit)
engine.Use(auth.OperateLog)
}
// 设置swag 接口信息
func setGinSwagger(router *gin.Engine) {
url := ginSwagger.URL(fmt.Sprintf("http://%s:%s/swagger/doc.json", webg.Conf.Host, webg.Conf.ListenAddr))
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))
}
func registerRouter(router *gin.Engine) {
rootRouter := router.Group("/api/web")
{
MainWebRouter(rootRouter)
syscfgRouter(rootRouter)
fileRouter(rootRouter)
videoRouter(rootRouter)
translationRouter(rootRouter)
richTextContent(rootRouter)
commentRouter(rootRouter)
videoCollectionRouter(rootRouter)
ipBlackRouter(rootRouter)
detailNavRouter(rootRouter)
mediaResourceRouter(rootRouter)
playletRouter(rootRouter)
homeBannerRouter(rootRouter)
contentTagRouter(rootRouter)
slugRouter(rootRouter)
hotNavRouter(rootRouter)
appSyncRouter(rootRouter)
actressRouter(rootRouter)
contactusRouter(rootRouter)
announcementRouter(rootRouter)
userRouter(rootRouter)
questionnaireRouter(rootRouter)
contentExcelRouter(rootRouter)
}
}
+17
View File
@@ -0,0 +1,17 @@
package router
import (
"videoweb/web/api/web_homebanner"
"github.com/gin-gonic/gin"
)
func homeBannerRouter(router *gin.RouterGroup) {
group := router.Group("/home/banner")
{
group.GET("/list", web_homebanner.List)
group.POST("/add", web_homebanner.Add)
group.POST("/update", web_homebanner.Update)
group.POST("/del", web_homebanner.Del)
}
}
+17
View File
@@ -0,0 +1,17 @@
package router
import (
"videoweb/web/api/web_hotnav"
"github.com/gin-gonic/gin"
)
func hotNavRouter(router *gin.RouterGroup) {
group := router.Group("/hotnav")
{
group.POST("/list", web_hotnav.HotNavList)
group.POST("/add", web_hotnav.HotNavAdd)
group.POST("/del", web_hotnav.HotNavDel)
group.POST("/update", web_hotnav.HotNavUpdate)
}
}
+16
View File
@@ -0,0 +1,16 @@
package router
import (
"github.com/gin-gonic/gin"
"videoweb/web/api/web_ipblack"
)
func ipBlackRouter(router *gin.RouterGroup) {
// 文件上传
group := router.Group("/ipblack")
{
group.POST("/list", web_ipblack.IpBlackList)
group.POST("/add", web_ipblack.IpBlackAdd)
group.POST("/del", web_ipblack.IpBlackDel)
}
}
+16
View File
@@ -0,0 +1,16 @@
package router
import (
"videoweb/web/api/web_mediaresource"
"github.com/gin-gonic/gin"
)
func mediaResourceRouter(router *gin.RouterGroup) {
group := router.Group("/resource")
{
group.GET("/list", web_mediaresource.ResourceList)
group.GET("/chapters", web_mediaresource.ResourceChapters)
group.POST("/import", web_mediaresource.ResourceImport)
}
}
+52
View File
@@ -0,0 +1,52 @@
package router
import (
"videoweb/web/api/web_playlet"
"github.com/gin-gonic/gin"
)
func playletRouter(router *gin.RouterGroup) {
group := router.Group("/playlet")
{
group.GET("/list", web_playlet.List)
group.POST("/add", web_playlet.Add)
group.POST("/update", web_playlet.Update)
group.POST("/del", web_playlet.Del)
group.POST("/status/set", web_playlet.SetStatus)
group.POST("/recommend/set", web_playlet.SetRecommend)
group.POST("/featured/set", web_playlet.SetFeatured)
group.POST("/banner/set", web_playlet.SetBanner)
group.POST("/category/set", web_playlet.SetCategory)
group.POST("/theme/set", web_playlet.SetTheme)
group.POST("/tag/set", web_playlet.SetTag)
group.POST("/like/virtual/set", web_playlet.SetVirtualLike)
group.POST("/browse/virtual/set", web_playlet.SetVirtualBrowse)
group.POST("/heat/virtual/set", web_playlet.SetVirtualHeat)
group.POST("/pay-type/set", web_playlet.SetPayType)
group.POST("/watermark/reset", web_playlet.ResetWatermark)
group.GET("/chapter/list", web_playlet.ChapterList)
group.POST("/chapter/add", web_playlet.ChapterAdd)
group.POST("/chapter/update", web_playlet.ChapterUpdate)
group.POST("/chapter/del", web_playlet.ChapterDel)
group.POST("/chapter/sync", web_playlet.ChapterSync)
group.POST("/chapter/pay-type/set", web_playlet.ChapterSetPayType)
group.GET("/category/list", web_playlet.CategoryList)
group.POST("/category/add", web_playlet.CategoryAdd)
group.POST("/category/update", web_playlet.CategoryUpdate)
group.POST("/category/del", web_playlet.CategoryDel)
group.GET("/tag/list", web_playlet.TagList)
group.POST("/tag/add", web_playlet.TagAdd)
group.POST("/tag/update", web_playlet.TagUpdate)
group.POST("/tag/del", web_playlet.TagDel)
group.GET("/theme/list", web_playlet.ThemeList)
group.POST("/theme/add", web_playlet.ThemeAdd)
group.POST("/theme/update", web_playlet.ThemeUpdate)
group.POST("/theme/del", web_playlet.ThemeDel)
group.GET("/home-config/list", web_playlet.HomeConfigList)
group.GET("/home-config/topic/options", web_playlet.HomeConfigTopicOptions)
group.POST("/home-config/add", web_playlet.HomeConfigAdd)
group.POST("/home-config/update", web_playlet.HomeConfigUpdate)
group.POST("/home-config/del", web_playlet.HomeConfigDel)
}
}
+15
View File
@@ -0,0 +1,15 @@
package router
import (
"videoweb/web/api/web_questionnaire"
"github.com/gin-gonic/gin"
)
func questionnaireRouter(router *gin.RouterGroup) {
group := router.Group("/questionnaire")
{
group.POST("/list", web_questionnaire.List)
group.POST("/handle", web_questionnaire.Handle)
}
}
+17
View File
@@ -0,0 +1,17 @@
package router
import (
"github.com/gin-gonic/gin"
"videoweb/web/api/web_richtextcontent"
)
func richTextContent(router *gin.RouterGroup) {
// 文件上传
file := router.Group("/richtextcontent")
{
file.POST("/list", web_richtextcontent.List)
file.POST("/add", web_richtextcontent.Add)
file.POST("/del", web_richtextcontent.Del)
file.POST("/update", web_richtextcontent.Update)
}
}
+14
View File
@@ -0,0 +1,14 @@
package router
import (
"videoweb/web/api/web_slug"
"github.com/gin-gonic/gin"
)
func slugRouter(router *gin.RouterGroup) {
group := router.Group("/slug")
{
group.POST("/sync", web_slug.SyncSlug)
}
}
+42
View File
@@ -0,0 +1,42 @@
package router
import (
"videoweb/web/api/web_acc"
"github.com/gin-gonic/gin"
)
// 主后台路由
func MainWebRouter(router *gin.RouterGroup) {
login := router.Group("/login")
{
login.POST("/acc", web_acc.AccLogin)
login.POST("/bind", web_acc.BindQurl)
login.POST("/slogin", web_acc.SLogin)
}
role := router.Group("/role")
{
role.GET("/list", web_acc.RoleGetList)
role.POST("/add", web_acc.RoleAdd)
role.POST("/del", web_acc.RoleDel)
role.GET("/getinfo", web_acc.RoleGetInfo)
role.POST("/up", web_acc.RoleUp)
role.POST("/enable", web_acc.RoleEnable)
role.POST("/drop", web_acc.RoleGetDrop)
role.GET("/getauth", web_acc.RoleGetAuth)
role.POST("/upauth", web_acc.RoleUpAuth)
}
acc := router.Group("/acc")
{
acc.GET("/list", web_acc.AccGetList)
acc.POST("/add", web_acc.AccAdd)
acc.POST("/del", web_acc.AccDel)
acc.GET("/getinfo", web_acc.AccGetInfo)
acc.POST("/up", web_acc.AccUp)
acc.GET("/getstatus", web_acc.AccGetStatus)
acc.POST("/savestatus", web_acc.AccSaveStatus)
acc.POST("/ops", web_acc.GetAccOpRecords)
acc.POST("/uppwd", web_acc.AccUpdatePwd)
}
}
+24
View File
@@ -0,0 +1,24 @@
package router
import (
"videoweb/web/api/web_translation"
"github.com/gin-gonic/gin"
)
func translationRouter(router *gin.RouterGroup) {
translation := router.Group("/translation")
{
translation.POST("/list", web_translation.GetTranslation)
translation.POST("/update", web_translation.UpdateOnetTranslation)
translation.POST("/del", web_translation.DelOnetTranslation)
translation.POST("/add", web_translation.AddOnetTranslation)
}
translationcategory := router.Group("/translationcategory")
{
translationcategory.POST("/list", web_translation.GetTranslationCategory)
translationcategory.POST("/update", web_translation.UpdateOnetTranslationCategory)
translationcategory.POST("/del", web_translation.DelOnetTranslationCategory)
translationcategory.POST("/add", web_translation.AddOnetTranslationCategory)
}
}
+15
View File
@@ -0,0 +1,15 @@
package router
import (
"videoweb/web/api/web_user"
"github.com/gin-gonic/gin"
)
func userRouter(router *gin.RouterGroup) {
user := router.Group("/user")
{
user.POST("/list", web_user.GetUserList)
user.POST("/update", web_user.UpdateUser)
}
}
+54
View File
@@ -0,0 +1,54 @@
package router
import (
"videoweb/web/api/web_video"
"github.com/gin-gonic/gin"
)
func videoRouter(router *gin.RouterGroup) {
advitise := router.Group("/videoinfo")
{
advitise.POST("/list", web_video.GetVideoInfo)
advitise.POST("/update", web_video.UpdateOneVideoInfo)
advitise.POST("/del", web_video.DelOneVideoInfo)
advitise.POST("/sync", web_video.SyncVideoInfo)
advitise.POST("/syncMediaFile", web_video.SyncVideoFromMediaFile)
advitise.POST("/addcoll", web_video.AddOneVideoCollection)
advitise.POST("/addTags", web_video.AddVideoTags)
advitise.POST("/tag/set", web_video.SetVideoTags)
advitise.POST("/recommend/set", web_video.SetVideoRecommend)
advitise.POST("/setFakeLikes", web_video.SetVideoFakeLikes)
advitise.POST("/setFakeWatchTimes", web_video.SetVideoFakeWatchTimes)
advitise.POST("/heat/set", web_video.SetVideoHeat)
advitise.POST("/fillZeroFakeFlow", web_video.FillZeroVideoFakeFlow)
}
videocategory := router.Group("/videocategory")
{
videocategory.POST("/list", web_video.GetVideoCategory)
videocategory.POST("/update", web_video.UpdateOneVideoCategory)
videocategory.POST("/del", web_video.DelOneVideoCategory)
videocategory.POST("/add", web_video.AddOneVideoCategory)
}
videotag := router.Group("/videotag")
{
videotag.POST("/list", web_video.GetVideoTagInfo)
videotag.POST("/update", web_video.UpdateOneVideoTagInfo)
videotag.POST("/del", web_video.DelOneVideoTagInfo)
videotag.POST("/add", web_video.AddOneVideoTagInfo)
}
videocreater := router.Group("/videocreater")
{
videocreater.POST("/list", web_video.GetVideoCreater)
videocreater.POST("/update", web_video.UpdateOneVideoCreater)
videocreater.POST("/del", web_video.DelOneVideoCreater)
videocreater.POST("/add", web_video.AddOneVideoCreater)
}
router.GET("/m3u8/*key", web_video.Play)
router.GET("/transm3u8/*key", web_video.TranscodeM3u8)
router.GET("/enkey", web_video.Enkey)
router.GET("/lsjenkey", web_video.LsjEnkey)
router.POST("/videoinfo/transcode", web_video.TranscodeVideo)
}
+15
View File
@@ -0,0 +1,15 @@
package router
import (
"github.com/gin-gonic/gin"
"videoweb/web/api/web_videocollection"
)
func videoCollectionRouter(router *gin.RouterGroup) {
group := router.Group("/videocollection")
{
group.POST("/media/list", web_videocollection.GetVideoCollectionMediaList)
group.POST("/media/option", web_videocollection.UpdateVideoCollectionMediaList)
group.POST("/media/rank", web_videocollection.UpdateVideoCollectionMediaRank)
}
}
+18
View File
@@ -0,0 +1,18 @@
package router
import (
"videoweb/web/api/web_video"
"videoweb/web/middleware/apilimitHandler"
"github.com/gin-gonic/gin"
)
func wbVideoDataRouter(r *gin.Engine) {
limiter := apilimitHandler.NewRouteHourlyLimiter(100)
router := r.Group("/wbapi/hjsq")
{
router.Use(limiter.Middleware())
router.GET("/hottag", web_video.GetVideoPlayData)
router.GET("/ipstat", web_video.GetIpStatData)
}
}
+211
View File
@@ -0,0 +1,211 @@
package server
import (
"context"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"videoweb/pub/common/laosiji"
"videoweb/pub/common/log"
"videoweb/pub/common/srvversion"
"videoweb/pub/dataReport"
"videoweb/pub/esmanager"
"videoweb/pub/models"
"videoweb/pub/mongos"
"videoweb/pub/redis"
"videoweb/pub/seo/googleindex"
"videoweb/pub/storage/proxy"
"videoweb/web/router"
"videoweb/web/service"
"videoweb/web/webg"
"gopkg.in/yaml.v2"
)
func init() {
time.Local, _ = time.LoadLocation("Asia/Shanghai")
}
func Run(args []string) {
showVersion()
if err := initConfig(); err != nil {
log.Error("init config err", log.E(err))
os.Exit(1)
return
}
shopDb := mongos.NewManager(webg.Conf.Mongodb.Addr)
if err := shopDb.Init(); err != nil {
log.Error("connect shopDb err", log.E(err))
os.Exit(1)
}
mongos.Shop = shopDb
shopLog := mongos.NewManager(webg.Conf.Mongodb.LogAddr)
if err := shopLog.Init(); err != nil {
log.Error("connect shopLog err", log.E(err))
os.Exit(1)
}
mongos.ShopLog = shopLog
if err := redis.Init(redis.Options{
Addr: webg.Conf.Redis.Addr,
Psw: webg.Conf.Redis.Passwd,
Db: webg.Conf.Redis.Db,
}); err != nil {
log.Error("redis connect err", log.E(err))
os.Exit(1)
}
if err := initCollections(); err != nil {
os.Exit(1)
return
}
if err := initElasticSearch(); err != nil {
log.Error("init ES failed", log.E(err))
os.Exit(1)
}
//初始化tg机器人
if webg.Conf.TgToken != "" {
//tgbot.InitTgBot(webg.Conf.TgToken, "[汁乎Web]")
}
proxy.InitBucketVideoAddress(webg.Conf.BucketVideoAddress, webg.Conf.BucketVideoAddressV2)
initLaosiji()
mongos.StartLid()
initData()
initSeoPush()
dataReport.Init(dataReport.Config{
ApiUrl: webg.Conf.DataReport.Url,
RunMod: webg.Conf.RunMod,
})
initHttpServer()
shutdownHandler()
}
func showVersion() {
log.Info(fmt.Sprintf("sevice version:%s", srvversion.SERVICE_VERSION))
log.Info(fmt.Sprintf("git version:%s", srvversion.GIT_VERSION))
log.Info(fmt.Sprintf("build date:%s", srvversion.BUILD_DATE))
log.Info(fmt.Sprintf("build ip:%s", srvversion.BUILD_IP))
}
func initConfig() error {
buf, err := ioutil.ReadFile("conf/web.yaml")
if err != nil {
return err
}
if err = yaml.Unmarshal(buf, &webg.Conf); err != nil {
return err
}
return nil
}
// mongo表
func initCollections() error {
return nil
}
// 数据
func initData() {
models.Init()
service.Start()
}
// 搜索引擎推送
func initSeoPush() {
if webg.Conf.RunMod != "prod" {
return
}
googleindex.Init(context.Background())
}
func initElasticSearch() error {
es, err := esmanager.NewManager(webg.Conf.Es.Addr,
webg.Conf.Es.User, webg.Conf.Es.Pass)
if err != nil {
log.Info("new es failed", log.Any("err", err))
return err
}
if err = es.ClientConnect(); err != nil {
log.Info("connect es failed", log.Any("err", err))
return err
}
esmanager.Instance = es
log.Info("es:Init Ok!")
return nil
}
func initHttpServer() {
addr := fmt.Sprintf(":%s", webg.Conf.ListenAddr)
srv := &http.Server{
Addr: addr,
Handler: router.Init(),
}
go func() {
log.Info("服务已启动", log.Any("地址", addr))
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal("listen:", log.E(err))
}
}()
}
func shutdownHandler() {
quit := make(chan os.Signal)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM, os.Kill)
<-quit
log.Warn("Shutdown... server")
service.Stop()
done := make(chan struct{})
go func() {
mongos.Shop.DisConnect()
mongos.ShopLog.DisConnect()
redis.Disconnect()
// srv_resource.ClosePrefetch()
done <- struct{}{}
}()
select {
case <-time.After(5 * time.Second):
log.Warn("shutdown timeout....")
case <-done:
log.Info("graceful shutdown")
}
}
func initLaosiji() {
if webg.Conf.LsjMediaConf.ApiUrl == "" {
return
}
cli := laosiji.New(webg.Conf.LsjMediaConf.ApiUrl, webg.Conf.LsjMediaConf.AppId, webg.Conf.LsjMediaConf.ApiKey)
d := laosiji.NewDomains(cli)
laosiji.LaosijiClient = cli
laosiji.LaosijiDomains = d
hr := webg.Conf.LsjMediaConf.DomainsRefreshHr
if hr <= 0 {
hr = 3
}
d.StartAutoRefresh(time.Duration(hr) * time.Hour)
go func() {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if _, err := d.Refresh(ctx); err != nil {
log.Error("Init Laosiji domains 首次拉取失败(后台重试,不影响启动)", log.E(err))
} else {
log.Info("Init Laosiji OK...")
}
}()
}
+21
View File
@@ -0,0 +1,21 @@
package service
import (
"videoweb/web/service/srv_ipblack"
"videoweb/web/service/srv_mediaresource"
"videoweb/web/service/srv_search"
"videoweb/web/skd"
)
func Start() {
skd.Start()
srv_ipblack.Init()
srv_mediaresource.Start()
srv_search.Start()
}
func Stop() {
skd.Stop()
srv_mediaresource.Stop()
srv_search.Stop()
}

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