init: 初始化 web_hgdjb_server 项目

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-11-07 10:47:32 +08:00
co-authored by Claude Opus 4.7
commit f13d33af4d
707 changed files with 147705 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
package appinfoapi
import (
"videoweb/app/api/proto"
"videoweb/app/service/appser"
"videoweb/app/service/configser"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// QueryAppList 查询应用列表
// @Tags 应用列表
// @Summary 查询应用列表
// @Description 返回应用分类列表,每个分类下含应用信息列表;categoryId=0 返回第一个分类
// @Accept json
// @Produce json
// @Param categoryId query int false "当前分类ID,0表示默认第一个分类"
// @Success 200 {object} proto.AppListResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/applist/list [get]
func QueryAppList(c *gin.Context) {
var req struct {
CategoryId int64 `form:"categoryId"`
}
if err := c.ShouldBindQuery(&req); err != nil || req.CategoryId < 0 {
req.CategoryId = 0
}
categoryList, category, serr := appser.AppCategoryData(c, req.CategoryId)
if serr != nil {
common.ServerJSON(c, serr, "")
return
}
if categoryList == nil {
categoryList = make([]proto.AppCategoryInfo, 0)
}
common.ServerJSON(c, srvdef.Success, proto.AppListResp{
Path: c.Request.URL.Path,
Config: configser.GetConfigInfo(),
Advitise: configser.GetAdvitise(),
CategoryList: categoryList,
Category: category,
})
}
+232
View File
@@ -0,0 +1,232 @@
package authapi
import (
"strings"
"videoweb/app/service/authser"
"videoweb/app/service/wordsfilterser"
"videoweb/pub/common"
"videoweb/pub/common/ipaddr"
"videoweb/pub/common/srvdef"
"videoweb/pub/common/useragent"
"videoweb/pub/pubdef"
"github.com/gin-gonic/gin"
)
func requestUA(ctx *gin.Context) useragent.UA {
ua, _ := common.GetUA(ctx)
return ua
}
func applyRequestDevID(ua useragent.UA, devID string) useragent.UA {
if v := strings.TrimSpace(devID); v != "" {
ua.DevID = v
}
return ua
}
type registerReq struct {
AccountNo string `json:"accountNo" binding:"required"` // 账号
Email string `json:"email"` // 邮箱(可选)
Password string `json:"password" binding:"required"` // 明文密码
AgentInviteCode string `json:"agentInviteCode"` // 邀请人的邀请码(可选)
DevID string `json:"devID"` // 设备唯一标示(可选)
Channel string `json:"channel"` // 渠道码(可选,用户无商区码时写入)
}
type loginReq struct {
Account string `json:"account" binding:"required"` // 账号或邮箱
Password string `json:"password" binding:"required"` // 明文密码
DevID string `json:"devID"` // 设备唯一标示(可选)
Channel string `json:"channel"` // 渠道码(可选,用户无商区码时写入)
}
type resetPasswordReq struct {
AccountNo string `json:"accountNo" binding:"required"` // 账号
Email string `json:"email" binding:"required"` // 邮箱
NewPassword string `json:"newPassword" binding:"required"` // 新密码
}
type updateProfileReq struct {
NickName *string `json:"nickName"` // 新昵称(可选)
Avatar *string `json:"avatar"` // 新头像 URL(可选)
Introduction *string `json:"introduction"` // 简介(可选)
PrivacyMode *bool `json:"privacyMode"` // 隐私模式:true-开启,false-关闭(可选)
OldPassword *string `json:"oldPassword"` // 旧密码明文(已设置密码时修改必填)
NewPassword *string `json:"newPassword"` // 新密码明文(设置或修改密码时必填)
}
// GuestLogin 游客登录
// @Tags 用户认证
// @Summary 游客登录
// @Description 按设备ID创建或找回游客账号;请求头可带 Authorization 复用已有游客会话。需传 X-User-Agent
// @Accept json
// @Produce json
// @Param param body authser.GuestLoginReq true "游客登录参数"
// @Success 200 {object} authser.LoginResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/auth/guest [POST]
func GuestLogin(ctx *gin.Context) {
var req authser.GuestLoginReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
ua, err := common.GetUA(ctx)
if err != nil {
common.ServerJSON(ctx, srvdef.NoUA, nil)
return
}
if req.DevID == "" {
common.ServerJSON(ctx, srvdef.ErrParamError, "devID不能为空")
return
}
ua.DevID = req.DevID
resp, serr := authser.GuestLogin(ctx, common.GetUserId(ctx), ipaddr.ResolveClientIP(ctx), &req, ua)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Register 用户注册
// @Tags 用户认证
// @Summary 注册
// @Description 传入账号和明文密码,邮箱可选,请求头带游客 Authorization 时升级该游客为普通用户,否则新建用户
// @Accept json
// @Produce json
// @Param param body registerReq true "注册参数"
// @Success 200 {object} authser.LoginResp "注册成功,返回 token 及用户基本信息"
// @Failure 400 {string} string "失败"
// @Router /api/app/auth/register [POST]
func Register(ctx *gin.Context) {
var req registerReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
ua := applyRequestDevID(requestUA(ctx), req.DevID)
resp, serr := authser.Register(ctx, common.GetUserId(ctx), req.AccountNo, req.Email, req.Password, req.AgentInviteCode, ua, ipaddr.ResolveClientIP(ctx), req.Channel)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Login 用户登录
// @Tags 用户认证
// @Summary 登录
// @Description 账号或邮箱均可作为登录凭证
// @Accept json
// @Produce json
// @Param param body loginReq true "登录参数"
// @Success 200 {object} authser.LoginResp "登录成功,返回 token 及用户基本信息"
// @Failure 400 {string} string "失败"
// @Router /api/app/auth/login [POST]
func Login(ctx *gin.Context) {
var req loginReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
ua := applyRequestDevID(requestUA(ctx), req.DevID)
resp, serr := authser.Login(ctx, req.Account, req.Password, ua, ipaddr.ResolveClientIP(ctx), req.Channel)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// UpdateProfile 修改用户资料
// @Tags 用户认证
// @Summary 修改用户资料(头像 / 简介 / 密码,可任意组合)
// @Description 用户信息通过 token 获取,无需传账号;nickName、avatar、introduction、oldPassword+newPassword 均为可选,至少提供一项。未设置密码时传 newPassword 可设置密码,已设置密码时修改需传 oldPassword+newPassword
// @Accept json
// @Produce json
// @Param param body updateProfileReq true "修改资料参数"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/auth/profile [POST]
func UpdateProfile(ctx *gin.Context) {
userId := common.GetUserId(ctx)
if userId <= 0 {
common.ServerJSON(ctx, srvdef.InvalidToken, nil)
return
}
var req updateProfileReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
if req.NickName != nil && !wordsfilterser.Validate(*req.NickName) {
common.ServerJSON(ctx, srvdef.ErrContainIllegalWord, "包含非法字符")
return
}
serr := authser.UpdateProfile(ctx, &authser.UpdateProfileReq{
UserId: userId,
NickName: req.NickName,
Avatar: req.Avatar,
Introduction: req.Introduction,
PrivacyMode: req.PrivacyMode,
OldPassword: req.OldPassword,
NewPassword: req.NewPassword,
})
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
// GetInfo 获取当前用户信息
// @Tags 用户认证
// @Summary 获取当前用户信息
// @Description 通过 token 获取最新用户信息,包含金币余额、VIP状态等
// @Produce json
// @Success 200 {object} authser.LoginResp "用户信息"
// @Failure 400 {string} string "失败"
// @Router /api/app/auth/getInfo [GET]
func GetInfo(ctx *gin.Context) {
userId := common.GetUserId(ctx)
if pubdef.IsCrawlerUser(userId) {
common.ServerJSON(ctx, srvdef.Success, authser.CrawlerLoginResp(""))
return
}
if userId <= 0 {
common.ServerJSON(ctx, srvdef.InvalidToken, nil)
return
}
resp, serr := authser.GetInfo(ctx, userId, requestUA(ctx))
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ResetPassword 找回密码
// @Tags 用户认证
// @Summary 找回密码
// @Description 通过账号和邮箱双重校验后重置密码,两者必须同时匹配同一用户
// @Accept json
// @Produce json
// @Param param body resetPasswordReq true "找回密码参数"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/auth/resetPassword [POST]
func ResetPassword(ctx *gin.Context) {
var req resetPasswordReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
serr := authser.ResetPassword(ctx, req.AccountNo, req.Email, req.NewPassword)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "")
}
+145
View File
@@ -0,0 +1,145 @@
package coinapi
import (
"fmt"
"net/url"
"videoweb/app/service/coinser"
"videoweb/app/service/rechargeser"
"videoweb/pub/common"
"videoweb/pub/common/enum/consts"
"videoweb/pub/common/ipaddr"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
type buyCoinReq struct {
PackageId int64 `json:"packageId" binding:"required"` // 购买套餐ID(金币充值)
PayMode string `json:"payMode" binding:"required"` // 支付方式:alipay/wechat
SourcePageKey string `json:"sourcePageKey"` // 下单来源页面标识
SourcePageName string `json:"sourcePageName"` // 下单来源页面名称
}
// BuyCoin 购买金币(发起第三方支付)
// @Tags 金币
// @Summary 购买金币
// @Description 根据指定金币套餐发起第三方支付,返回支付链接
// @Accept json
// @Produce json
// @Param param body buyCoinReq true "购买参数"
// @Success 200 {object} coinser.BuyCoinResp "支付链接"
// @Security ApiKeyAuth
// @Router /api/app/coin/buy [POST]
func BuyCoin(ctx *gin.Context) {
var req buyCoinReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
userId := common.GetUserId(ctx)
sysType := ctx.GetString(consts.CtxSysType)
devType := ctx.GetString(consts.CtxDevType)
ip := ipaddr.ResolveClientIP(ctx)
user, serr := coinser.GetUserInfo(ctx, userId)
if serr != nil || user == nil {
common.ServerJSON(ctx, srvdef.ErrUserNotExsit, nil)
return
}
deviceID := rechargeser.PayDeviceID(ctx.GetString(consts.CtxDevId), user.DevID, user.DevV2)
resp, serr := coinser.CreateCoinOrder(ctx, userId, user.NickName, req.PackageId, req.PayMode, sysType, devType, deviceID, ip, user.DistrictCode, req.SourcePageKey, req.SourcePageName)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ExportCoinTrans 导出当前用户金币余额明细
// @Tags 金币
// @Summary 导出金币余额明细 -- by 王鸣
// @Description 导出当前登录用户的金币收入、支出流水CSV;type=0全部 1充值 2消费 3奖励
// @Produce text/csv
// @Param type query int false "类型:0全部 1充值 2消费 3奖励"
// @Success 200 {file} file "CSV文件"
// @Security ApiKeyAuth
// @Router /api/app/coin/trans/export [GET]
func ExportCoinTrans(ctx *gin.Context) {
var req coinTransListReq
_ = ctx.ShouldBindQuery(&req)
data, fileName, err := coinser.ExportCoinTrans(ctx, common.GetUserId(ctx), req.Type)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
ctx.Header("Content-Type", "text/csv; charset=utf-8")
ctx.Header("Content-Disposition", fmt.Sprintf("attachment; filename*=UTF-8''%s", url.QueryEscape(fileName)))
ctx.Data(200, "text/csv; charset=utf-8", data)
}
type coinOrderHistoryReq struct {
Page int64 `json:"page" form:"page"`
PageSize int64 `json:"pageSize" form:"pageSize"`
}
// GetCoinOrderHistory 查询当前用户金币购买记录
// @Tags 金币
// @Summary 查询金币购买记录
// @Produce json
// @Param page query int false "页码(默认1)"
// @Param pageSize query int false "每页数量(默认10)"
// @Success 200 {object} object "订单列表"
// @Security ApiKeyAuth
// @Router /api/app/coin/orders [GET]
func GetCoinOrderHistory(ctx *gin.Context) {
var req coinOrderHistoryReq
_ = ctx.ShouldBindQuery(&req)
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 10
}
userId := common.GetUserId(ctx)
list, total, serr := coinser.GetCoinOrderHistory(ctx, userId, req.Page, req.PageSize)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, gin.H{"total": total, "list": list})
}
type coinTransListReq struct {
// 页码,默认1
Page int64 `json:"page" form:"page"`
// 每页数量,默认10,最大100
PageSize int64 `json:"pageSize" form:"pageSize"`
// 类型:0-全部 1-充值 2-消费 3-奖励
Type int64 `json:"type" form:"type"`
}
// GetCoinTransList 查询当前用户金币余额明细
// @Tags 金币
// @Summary 查询金币余额明细 -- by 旺鸣
// @Description 返回当前登录用户的金币收入、支出流水,按交易时间倒序;type=0全部 1充值 2消费 3奖励
// @Produce json
// @Param page query int false "页码(默认1)"
// @Param pageSize query int false "每页数量(默认10,最大100)"
// @Param type query int false "类型:0全部 1充值 2消费 3奖励"
// @Success 200 {object} response.BasePageResp{list=[]proto.CoinTransListItemResp} "成功"
// @Security ApiKeyAuth
// @Router /api/app/coin/trans/list [GET]
func GetCoinTransList(ctx *gin.Context) {
var req coinTransListReq
_ = ctx.ShouldBindQuery(&req)
userId := common.GetUserId(ctx)
resp, err := coinser.GetCoinTransList(ctx, userId, req.Page, req.PageSize, req.Type)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
+86
View File
@@ -0,0 +1,86 @@
package commentapi
import (
"videoweb/app/api/proto"
"videoweb/app/service/commentser"
"videoweb/pub/common"
"videoweb/pub/common/ipaddr"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// SendComment 发布评论
// @Tags 评论APP
// @Summary 发布评论 --by 王鸣
// @Description 发布短剧、短剧剧集或视频评论,parentsId为0发布一级评论,大于0发布二级评论,replyCommentId表示实际回复的评论,objectType 10-短剧 11-短剧剧集 20-视频
// @Accept json
// @Produce json
// @Param param body proto.CommentSendReq true "参数列表"
// @Success 200 {object} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/app/comment/send [post]
func SendComment(ctx *gin.Context) {
var in proto.CommentSendReq
if err := ctx.ShouldBindJSON(&in); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
ip := ipaddr.ResolveClientIP(ctx)
err := commentser.SendComment(ctx, common.GetUserId(ctx), ip, &in)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, "success")
}
// List 评论列表
// @Tags 评论APP
// @Summary 评论列表 --by 王鸣
// @Description 分页查询短剧、短剧剧集或视频评论树,一级评论分页返回,二级评论挂在children中,objectType 10-短剧 11-短剧剧集 20-视频
// @Accept json
// @Produce json
// @Param params query proto.GetCommentListReq true "评论列表请求"
// @Success 200 {object} proto.GetCommentListResp{list=[]proto.CommentInfo} "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Router /api/app/comment/list [get]
func List(ctx *gin.Context) {
var in proto.GetCommentListReq
if err := ctx.ShouldBindQuery(&in); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := commentser.GetCommentPage(ctx, common.GetUserId(ctx), &in)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// SetLike 评论点赞/取消点赞
// @Tags 评论APP
// @Summary 评论点赞/取消点赞 --by 王鸣
// @Description 设置当前用户对短剧、短剧剧集或视频评论的点赞状态
// @Accept json
// @Produce json
// @Param param body proto.CommentLikeSetReq true "评论点赞设置请求"
// @Success 200 {object} proto.CommentLikeSetResp "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /api/app/comment/like/set [post]
func SetLike(ctx *gin.Context) {
var in proto.CommentLikeSetReq
if err := ctx.ShouldBindJSON(&in); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := commentser.SetCommentLike(ctx, common.GetUserId(ctx), &in)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
+64
View File
@@ -0,0 +1,64 @@
package config
import (
"videoweb/app/api/proto"
"videoweb/app/service/configser"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// Info 查询APP公共配置
// @Tags APP配置相关接口
// @Summary 查询APP公共配置 --by 王鸣
// @Description 返回最新地址信息、完整系统配置、广告配置和全站SEO配置
// @Accept json
// @Produce json
// @Success 200 {object} proto.ConfigInfoResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/config/info [get]
func Info(ctx *gin.Context) {
configInfo := configser.GetConfigInfo()
resp := &proto.ConfigInfoResp{
NewAddressInfo: configser.GetNewAddress(),
Config: configInfo,
Advitise: configser.GetAdvitise(),
SeoInfo: configser.GetSiteSeoInfo(),
SeoNavInfo: configser.GetNavSeoInfo(),
NavPageList: configser.GetNavPageList(),
ReportSDKConfig: configInfo.ReportSDKConfig,
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// FooterInfo 查询APP底部信息
// @Tags APP配置相关接口
// @Summary 查询APP底部信息 --by 王鸣
// @Description 返回APP底部信息
// @Accept json
// @Produce json
// @Success 200 {object} proto.FooterInfoResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/config/footer/info [get]
func FooterInfo(ctx *gin.Context) {
resp := &proto.FooterInfoResp{
FooterInfo: configser.GetFooterInfo(),
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// RichTextList 查询APP富文本内容列表
// @Tags APP配置相关接口
// @Summary 查询APP富文本内容列表 --by 王鸣
// @Description 返回启用状态的富文本内容,支持按ids或titles过滤
// @Accept json
// @Produce json
// @Param ids query string false "富文本ID,多个用英文逗号分隔"
// @Param titles query string false "富文本标题,多个用英文逗号分隔"
// @Success 200 {object} proto.AppRichTextListResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/config/richtext/list [get]
func RichTextList(ctx *gin.Context) {
common.ServerJSON(ctx, srvdef.Success, configser.GetAppRichTextList(ctx.Query("ids"), ctx.Query("titles")))
}
+36
View File
@@ -0,0 +1,36 @@
package contactusapi
import (
"videoweb/app/api/proto"
"videoweb/app/service/contactusser"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// AddContactUs 提交联系我们
// @Tags 联系我们相关接口
// @Summary 提交联系我们 -- by 旺鸣
// @Description 用户提交联系我们表单,问题类型:1-订单问题、2-账号问题、3-功能问题、4-体验问题、5-其他
// @Accept json
// @Produce json
// @Param param body proto.ContactUsAddReq true "联系我们请求"
// @Success 200 {object} proto.ContactUsAddResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/contactus/add [post]
func AddContactUs(ctx *gin.Context) {
var req proto.ContactUsAddReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
userId := common.GetUserId(ctx)
resp, err := contactusser.AddContactUs(ctx, userId, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
+36
View File
@@ -0,0 +1,36 @@
package feedbackapi
import (
"videoweb/app/api/proto"
"videoweb/app/service/feedbackser"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// AddFeedback 提交意见反馈
// @Tags 意见反馈相关接口
// @Summary 提交意见反馈 -- by 旺鸣
// @Description 用户提交意见反馈,问题类型,1-功能建议、2-播放问题、3-账号问题、4-其他
// @Accept json
// @Produce json
// @Param param body proto.FeedbackReq true "意见反馈请求"
// @Success 200 {object} proto.FeedbackResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/feedback/add [post]
func AddFeedback(ctx *gin.Context) {
var req proto.FeedbackReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
userId := common.GetUserId(ctx)
resp, err := feedbackser.AddFeedback(ctx, userId, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
+42
View File
@@ -0,0 +1,42 @@
package healthapi
import (
"videoweb/app/api/proto"
"videoweb/app/service/healthser"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// HealthCheck 健康检查接口
func HealthCheck(ctx *gin.Context) {
req := &proto.HealthCheckRequest{}
if err := ctx.ShouldBindJSON(req); err != nil {
log.Warn("health check bind error", log.E(err))
respond(ctx, srvdef.ErrParamError, err.Error(), nil)
return
}
log.Info("health check request", log.Any("req", req))
data, serr := healthser.HealthCheck(ctx.Request.Context(), req)
if serr != nil {
log.Warn("health check failed", log.E(serr), log.Any("req", req))
respond(ctx, serr.Code, serr.GetMsg(), nil)
return
}
log.Info("health check response", log.Any("resp", data))
respond(ctx, srvdef.Success, "success", data)
}
func respond(ctx *gin.Context, code srvdef.CodeType, msg string, data interface{}) {
if msg == "" {
msg = code.Msg()
}
ctx.JSON(200, gin.H{
"code": code,
"msg": msg,
"data": data,
})
}
+305
View File
@@ -0,0 +1,305 @@
package home
import (
"fmt"
"net/http"
"strconv"
"videoweb/app/api/proto"
"videoweb/app/service/commentser"
"videoweb/app/service/configser"
"videoweb/app/service/translationser"
"videoweb/app/service/videoser"
"videoweb/pub/common"
"videoweb/pub/common/enum/consts"
"videoweb/pub/common/ipaddr"
"videoweb/pub/common/srvdef"
v10 "videoweb/pub/common/v10"
"videoweb/pub/models/videoinformationmod"
"videoweb/pub/pubdef"
"github.com/gin-gonic/gin"
)
// VideoTagApi 标签搜索
// @Tags 标签搜索
// @Summary 标签搜索
// @Description 标签搜索
// @Accept json
// @Produce json
// @Param param body string true "参数列表"
// @Success 200 {object} proto.HomeHtmlData "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
// @Router /richtext/:id [get]
func RichtextApi(c *gin.Context) {
data := proto.RichTextHtmlData{
Path: c.Request.URL.Path,
Translations: translationser.GetTranslationData(),
BottonTranslations: translationser.GetTranslationBottomList(),
Config: configser.GetConfigInfo(),
Advitise: configser.GetAdvitise(),
}
richtextStr := c.Param("id")
richtextId, err := strconv.ParseInt(richtextStr, 10, 64)
if err != nil || richtextId < 1 {
common.ServerJSON(c, srvdef.NotFound, "")
return
}
richtextDate, serr := videoser.RichtextData(c, richtextId)
if serr != nil {
common.ServerJSON(c, serr.Code, "richtext param error")
return
}
data.CompletePath = fmt.Sprintf("/richtext/%d", richtextId)
data.RichTextInfo = richtextDate
common.JSONWriterCache(c, srvdef.Success, data)
}
// PageNotFound 404
// @Tags 404
// @Summary 404
// @Description 404
// @Accept json
// @Produce json
// @Param param body string true "参数列表"
// @Success 200 {string} string "成功"
// @Failure 400 {string} string "获取失败的返回结果"
// @Security ApiKeyAuth
func PageNotFound(c *gin.Context) {
data := proto.NotFoundHtmlData{
Path: c.Request.URL.Path,
Translations: translationser.GetTranslationData(),
BottonTranslations: translationser.GetTranslationBottomList(),
Config: configser.GetConfigInfo(),
Advitise: configser.GetAdvitise(),
}
data.CompletePath = c.Request.URL.Path
c.JSON(http.StatusOK, data)
//common.ServerJSON(c, srvdef.Success, data)
//c.HTML(404, "404", gin.H{
// "data": data,
//})
}
func UrlRedirect(c *gin.Context) {
data := proto.UrlRedirectData{
Path: c.Request.URL.Path,
CompletePath: c.Request.URL.Path,
Translations: translationser.GetTranslationData(),
BottonTranslations: translationser.GetTranslationBottomList(),
Config: configser.GetConfigInfo(),
Advitise: configser.GetAdvitise(),
}
url := c.Query("url")
data.UrlRedirect = url
common.ServerJSON(c, srvdef.Success, data)
}
func GetTagCategoryCache(ctx *gin.Context) {
data := configser.GetVideoTagCategoryDataList()
common.ServerJSON(ctx, srvdef.Success, data)
}
// VideoDetailInfo 新版视频详情页
func VideoDetailInfo(c *gin.Context) {
data := proto.VideoDetailsHtmlData{
Path: c.Request.URL.Path,
Translations: translationser.GetTranslationData(),
BottonTranslations: translationser.GetTranslationBottomList(),
Config: configser.GetConfigInfo(),
Advitise: configser.GetAdvitise(),
}
ua := ""
if v, b := c.Get(consts.CtxUAH5); b {
ua = v.(string)
}
ip := ipaddr.ResolveClientIP(c)
idStr := c.Param("id")
videoId, err := strconv.ParseInt(idStr, 10, 64)
if err != nil || videoId < 1 {
c.HTML(http.StatusNotFound, "404", gin.H{"data": data})
return
}
renderVideoDetailPage(c, data, videoId, ip, ua)
}
func renderVideoDetailPage(c *gin.Context, data proto.VideoDetailsHtmlData, videoId int64, ip, ua string) {
videoDate, serr := videoser.VideoDetails(c, videoId, common.GetUserId(c), ip, ua)
if serr != nil {
if c.Query("format") == "json" {
common.ServerJSON(c, srvdef.ErrNoData, data)
return
}
c.HTML(http.StatusNotFound, "404", gin.H{"data": data})
return
}
data.Video = videoDate
data.Path = fmt.Sprintf("/videodetail/%d/", videoId)
data.Breadcrumbs = []proto.BreadcrumbItem{
{Name: "首页", Url: "/"},
{Name: "视频", Url: "/videoList"},
}
if len(videoDate.Categorys) > 0 {
cat := videoDate.Categorys[0]
data.Breadcrumbs = append(data.Breadcrumbs, proto.BreadcrumbItem{
Name: cat.Name,
Url: fmt.Sprintf("/category/%d/", cat.Id),
})
}
data.Breadcrumbs = append(data.Breadcrumbs, proto.BreadcrumbItem{
Name: videoDate.Title,
Url: "",
})
switch videoDate.Type {
case proto.VideoTypeVideo, proto.VideoTypeVideoV2:
comment, commentErr := commentser.GetCommentList(c, videoId, commentser.ObjectTypeVideo, 1)
data.CommentList = proto.GetCommentListResp{
ObjectId: videoId,
TotalCount: 0,
PageSize: 20,
PageNum: 1,
List: make([]proto.CommentInfo, 0),
}
if commentErr == nil {
data.CommentList = *comment
}
if c.Query("format") == "json" {
common.ServerJSON(c, srvdef.Success, data)
return
}
c.HTML(http.StatusOK, "videoDetail", gin.H{
"data": data,
})
default:
if c.Query("format") == "json" {
common.ServerJSON(c, srvdef.ErrNoData, data)
return
}
c.HTML(http.StatusNotFound, "404", gin.H{"data": data})
}
}
// VideoDetailPage 视频详情预览入口(不走模板缓存)
func VideoDetailPage(c *gin.Context) {
id := c.DefaultQuery("id", "")
if id == "" {
c.HTML(http.StatusBadRequest, "404", gin.H{"data": proto.VideoDetailsHtmlData{}})
return
}
c.Params = gin.Params{{Key: "id", Value: id}}
c.Request.URL.Path = fmt.Sprintf("/videoDetail?id=%s", id)
VideoDetailInfo(c)
}
// VideoListPage 视频列表预览入口(不走模板缓存)
func VideoListPage(c *gin.Context) {
id := c.DefaultQuery("id", "0")
sort := c.DefaultQuery("sort", "1")
page := c.DefaultQuery("page", "1")
c.Params = gin.Params{
{Key: "id", Value: id},
{Key: "sortType", Value: sort},
{Key: "page", Value: page},
}
c.Request.URL.Path = fmt.Sprintf("/videoList?id=%s&sort=%s&page=%s", id, sort, page)
VideoCategoryInfo(c)
}
// VideoCategoryInfo 新版视频列表页
func VideoCategoryInfo(c *gin.Context) {
data := proto.VideoTopicHtmlData{
Path: c.Request.URL.Path,
Translations: translationser.GetTranslationData(),
BottonTranslations: translationser.GetTranslationBottomList(),
Config: configser.GetConfigInfo(),
Advitise: configser.GetAdvitise(),
}
topicStr := c.Param("id")
sortTypeStr := c.Param("sortType")
pageStr := c.Param("page")
pageNum, err := strconv.ParseInt(pageStr, 10, 64)
if err != nil || pageNum < 1 {
pageNum = 1
}
sortType, err := strconv.ParseInt(sortTypeStr, 10, 64)
if err != nil || sortType < 1 {
sortType = 0
}
if topicStr == "" {
renderVideoListPage(c, data, "0", 0, sortType, pageNum)
return
}
matche := v10.ParamIsNumber(topicStr)
if matche {
publish, err := strconv.ParseInt(topicStr, 10, 64)
if err != nil {
c.HTML(http.StatusNotFound, "404", gin.H{"data": data})
return
}
if publish == 0 {
renderVideoListPage(c, data, "0", 0, sortType, pageNum)
return
}
if publish < 1 {
c.HTML(http.StatusNotFound, "404", gin.H{"data": data})
return
}
sort := videoTopicSortType(sortType)
newPath := fmt.Sprintf("/videocategory/%d/%d/%d/", publish, sort, pageNum)
c.Redirect(http.StatusMovedPermanently, newPath)
return
}
topicId, err2 := strconv.ParseInt(topicStr, 10, 64)
if err2 != nil || topicId < 1 {
c.HTML(http.StatusNotFound, "404", gin.H{"data": data})
return
}
topicSegment := topicStr
if topicSegment == "" {
topicSegment = "0"
}
renderVideoListPage(c, data, topicSegment, topicId, sortType, pageNum)
}
func videoTopicSortType(sortType int64) int64 {
if sortType < 1 {
return int64(videoinformationmod.VideoSortType_New)
}
return sortType
}
func renderVideoListPage(c *gin.Context, data proto.VideoTopicHtmlData, topicSegment string, topicId, sortType, pageNum int64) {
sort := videoTopicSortType(sortType)
data.CompletePath = fmt.Sprintf("/videocategory/%s/%d/%d/", topicSegment, sort, pageNum)
totalSize, videoInfos, _, serr := videoser.VideoTopicData(c, false, topicId, sortType, pageNum)
data.VideoInfos = videoInfos
data.PageNum = pageNum
data.PageSize = pubdef.PageSize
data.TotalSize = pubdef.GetTotalPage(totalSize, pubdef.PageSize)
if data.VideoInfos == nil {
data.VideoInfos = []proto.VideoInfoData{}
}
if serr != nil {
if c.Query("format") == "json" {
common.ServerJSON(c, srvdef.ErrNoData, data)
return
}
c.HTML(http.StatusNotFound, "404", gin.H{"data": data})
return
}
if c.Query("format") == "json" {
common.ServerJSON(c, srvdef.Success, data)
return
}
c.HTML(http.StatusOK, "videoList", gin.H{
"data": data,
})
}
+27
View File
@@ -0,0 +1,27 @@
package navigationapi
import (
"videoweb/app/service/navigationser"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// HeaderNavigation 查询头部导航配置
// @Tags app导航相关接口
// @Summary 查询头部导航配置 -- by 王鸣
// @Description 查询导航类型为URL模式和二级导航的头部导航配置
// @Accept json
// @Produce json
// @Success 200 {object} proto.AppTranslationInfo "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/navigation/header [get]
func HeaderNavigation(ctx *gin.Context) {
resp, err := navigationser.HeaderNavigation(ctx)
if err != nil {
common.ServerJSON(ctx, err, err.GetMsg())
return
}
common.JSONWriterCache(ctx, srvdef.Success, resp)
}
+766
View File
@@ -0,0 +1,766 @@
package playletapi
import (
"videoweb/app/api/proto"
"videoweb/app/service/playletser"
"videoweb/pub/common"
"videoweb/pub/common/ipaddr"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// HomePlaylet app端首页短剧接口
// @Tags app短剧相关接口
// @Summary app端首页短剧接口 --by 王鸣
// @Description 无请求参数,返回首页banner短剧、公告和SEO信息
// @Accept json
// @Produce json
// @Success 200 {object} proto.HomePlayletResponse "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/home [get]
func HomePlaylet(ctx *gin.Context) {
resp, err := playletser.Home(ctx)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// HomeConfigList app端分页查询首页配置内容
// @Tags app短剧相关接口
// @Summary app端分页查询首页配置内容
// @Description 根据首页配置ID或slug分页查询短剧或题材,slug 优先
// @Accept json
// @Produce json
// @Param params query proto.PlayletHomeConfigListReq true "首页配置内容分页请求"
// @Success 200 {object} proto.PlayletHomeConfigListResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/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 := playletser.HomeConfigList(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// AllList app端分页查询全部短剧
// @Tags app短剧相关接口
// @Summary app端分页查询全部短剧 --by 王鸣
// @Description 分页查询已上架短剧,支持题材、更新状态和排序筛选
// @Accept json
// @Produce json
// @Param params query proto.PlayletAllListReq true "全部短剧分页请求"
// @Success 200 {object} proto.PlayletAllListResp{list=[]proto.CommonData} "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/all/list [get]
func AllList(ctx *gin.Context) {
var req proto.PlayletAllListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.AllList(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// HotList app端分页查询热门短剧
// @Tags app短剧相关接口
// @Summary app端分页查询热门短剧
// @Description 按热度查询已上架短剧,可排除指定短剧
// @Accept json
// @Produce json
// @Param params query proto.PlayletHotListReq true "热门短剧分页请求"
// @Success 200 {object} proto.PlayletHotListResp{list=[]proto.CommonData} "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/hot/list [get]
func HotList(ctx *gin.Context) {
var req proto.PlayletHotListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.HotList(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// TopicList app端分页查询专题剧单
// @Tags app短剧相关接口
// @Summary app端分页查询专题剧单 --by 王鸣
// @Description 分页查询各启用区块下有已上架短剧的专题卡片
// @Accept json
// @Produce json
// @Param params query proto.PlayletTopicPageListReq true "专题剧单分页请求"
// @Success 200 {object} proto.PlayletTopicPageListResp{list=[]proto.PlayletTopicGroupPageItem} "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/topic/list [get]
func TopicList(ctx *gin.Context) {
var req proto.PlayletTopicPageListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.TopicList(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// TopicDetail app端查询专题详情
// @Tags app短剧相关接口
// @Summary app端查询专题详情 --by 王鸣
// @Description 按专题ID查询专题信息和专题短剧列表
// @Accept json
// @Produce json
// @Param params query proto.PlayletTopicDetailReq true "专题详情请求"
// @Success 200 {object} proto.PlayletTopicDetailResp{list=[]proto.CommonData,moreTopics=[]proto.PlayletTopicPageItem} "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/topic/detail [get]
func TopicDetail(ctx *gin.Context) {
var req proto.PlayletTopicDetailReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.TopicDetail(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Rank app端分页查询短剧排行榜
// @Tags app短剧相关接口
// @Summary 短剧排行榜 --by 王鸣
// @Description 分页查询已上架短剧排行榜;sortOrder=1按热度值倒序,2按上架时间倒序,3按收藏数倒序
// @Accept json
// @Produce json
// @Param params query proto.PlayletRankReq true "分页查询短剧排行榜请求"
// @Success 200 {object} proto.PlayletRankResp{list=[]proto.CommonData} "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/rank [get]
func Rank(ctx *gin.Context) {
var req proto.PlayletRankReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.Rank(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// HotRankList app端分页查询热榜
// @Tags app短剧相关接口
// @Summary app端分页查询热榜 --by 王鸣
// @Description 分页查询已上架短剧热榜;rankType=1热播榜 2新剧榜 3追剧榜
// @Accept json
// @Produce json
// @Param params query proto.PlayletHotRankListReq true "热榜分页请求"
// @Success 200 {object} proto.PlayletHotRankListResp{list=[]proto.CommonData} "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/hot/rank/list [get]
func HotRankList(ctx *gin.Context) {
var req proto.PlayletHotRankListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.HotRankList(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// OperateList app端按类型分页查询短剧
// @Tags app短剧相关接口
// @Summary app端按类型分页查询短剧
// @Description type=1最新更新 2当前热播 3独家原创(筛选推荐短剧) 4随机推荐,随机推荐每日更新顺序
// @Accept json
// @Produce json
// @Param params query proto.PlayletOperateListReq true "短剧分类列表分页请求"
// @Success 200 {object} proto.PlayletOperateListResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/operate/list [get]
func OperateList(ctx *gin.Context) {
var req proto.PlayletOperateListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.OperateList(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// TodayUpdate app端分页查询今日更新短剧
// @Tags app短剧相关接口
// @Summary app端分页查询今日更新短剧 --by 王鸣
// @Description 分页查询已上架短剧
// @Accept json
// @Produce json
// @Param params query proto.PlayletTodayUpdateReq true "分页查询今日更新短剧请求"
// @Success 200 {object} proto.PlayletTodayUpdateResp{list=[]proto.CommonData} "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/today-update [get]
func TodayUpdate(ctx *gin.Context) {
var req proto.PlayletTodayUpdateReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.TodayUpdate(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// TagVideoList app端根据标签ID分页查询短剧
// @Tags app短剧相关接口
// @Summary app端根据标签ID分页查询短剧 --by 王鸣
// @Description 根据标签ID或标签slug分页查询已上架短剧;slug非空时优先按slug解析标签ID;sortType=1最新 2最热 3收藏最多
// @Accept json
// @Produce json
// @Param params query proto.PlayletTagVideoReq true "根据标签ID分页查询短剧请求"
// @Success 200 {object} proto.PlayletTagVideoResp{list=[]proto.CommonData} "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/tag/list [get]
func TagVideoList(ctx *gin.Context) {
var req proto.PlayletTagVideoReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.TagVideoList(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// GuessLikeList app端分页查询猜你喜欢短剧
// @Tags app短剧相关接口
// @Summary app端分页查询猜你喜欢短剧 --by 王鸣
// @Description 根据当前短剧同题材查询猜你喜欢,排除当前短剧
// @Accept json
// @Produce json
// @Param params query proto.PlayletGuessLikeListReq true "猜你喜欢分页请求"
// @Success 200 {object} proto.PlayletGuessLikeListResp{list=[]proto.CommonData} "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/guess-like/list [get]
func GuessLikeList(ctx *gin.Context) {
var req proto.PlayletGuessLikeListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.GuessLikeList(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Search app端ES分页搜索短剧
// @Tags app短剧相关接口
// @Summary app端ES分页搜索短剧 --by 王鸣
// @Description 使用ES分页搜索已上架短剧,支持剧名、题材名、简介和标签名检索
// @Accept json
// @Produce json
// @Param params query proto.PlayletSearchReq true "短剧ES分页搜索请求"
// @Success 200 {object} proto.PlayletSearchResp{list=[]proto.CommonData} "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/search [get]
func Search(ctx *gin.Context) {
var req proto.PlayletSearchReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.Search(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// SearchSuggest app端短剧搜索联想
// @Tags app短剧相关接口
// @Summary app端短剧搜索联想 --by 王鸣
// @Description 搜索框下拉联想,返回短剧列表
// @Accept json
// @Produce json
// @Param params query proto.PlayletSearchSuggestReq true "短剧搜索联想请求"
// @Success 200 {object} proto.PlayletSearchSuggestResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/search/suggest [get]
func SearchSuggest(ctx *gin.Context) {
var req proto.PlayletSearchSuggestReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.SearchSuggest(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// HotLike app端热搜词和猜你喜欢
// @Tags app短剧相关接口
// @Summary app端热搜词和猜你喜欢
// @Description 返回缓存的前10个热搜词,以及按收藏量最多的15部猜你喜欢短剧
// @Accept json
// @Produce json
// @Success 200 {object} proto.PlayletHotLikeResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/hot-like [get]
func HotLike(ctx *gin.Context) {
common.ServerJSON(ctx, srvdef.Success, playletser.HotLike(ctx))
}
// LikeList app端我的短剧点赞列表
// @Tags app短剧相关接口
// @Summary app端我的短剧点赞列表
// @Description 按当前用户点赞时间倒序分页返回短剧
// @Accept json
// @Produce json
// @Param params query proto.PlayletLikeListReq true "我的短剧点赞列表请求"
// @Success 200 {object} proto.PlayletLikeListResp{list=[]proto.PlayletLikeData} "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/like/list [get]
func LikeList(ctx *gin.Context) {
var req proto.PlayletLikeListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.LikeList(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// SetLike app端短剧点赞/取消点赞
// @Tags app短剧相关接口
// @Summary app端短剧点赞/取消点赞 --by 王鸣
// @Description 设置当前用户短剧点赞状态,点赞数只在状态真实变化时增减
// @Accept json
// @Produce json
// @Param param body proto.PlayletLikeSetReq true "短剧点赞设置请求"
// @Success 200 {object} proto.PlayletLikeSetResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/like/set [post]
func SetLike(ctx *gin.Context) {
var req proto.PlayletLikeSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.SetLike(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// SetCollect app端短剧收藏/取消收藏
// @Tags app短剧相关接口
// @Summary app端短剧收藏/取消收藏 --by 王鸣
// @Description 设置当前用户短剧收藏状态,收藏数只在状态真实变化时增减
// @Accept json
// @Produce json
// @Param param body proto.PlayletCollectSetReq true "短剧收藏设置请求"
// @Success 200 {object} proto.PlayletCollectSetResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/collect/set [post]
func SetCollect(ctx *gin.Context) {
var req proto.PlayletCollectSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.SetCollect(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ForwardHeat app端短剧转发增加热度
// @Tags app短剧相关接口
// @Summary app端短剧转发增加热度 --by 王鸣
// @Description 请求一次短剧热度值增加5,仅支持已上架短剧
// @Accept json
// @Produce json
// @Param param body proto.PlayletForwardHeatReq true "短剧转发加热度请求"
// @Success 200 {object} proto.PlayletForwardHeatResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/forward/heat [post]
func ForwardHeat(ctx *gin.Context) {
var req proto.PlayletForwardHeatReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.ForwardHeat(ctx, common.GetUserId(ctx), ipaddr.ResolveClientIP(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// CollectList app端我的短剧收藏列表
// @Tags app短剧相关接口
// @Summary app端我的短剧收藏列表 --by 王鸣
// @Description 按当前用户收藏时间倒序分页返回短剧收藏列表,并返回已看/未看集数和最近观看位置;watchStatus=0全部 1追剧中 2已看完
// @Accept json
// @Produce json
// @Param params query proto.PlayletCollectListReq true "我的短剧收藏列表请求"
// @Success 200 {object} proto.PlayletCollectListResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/collect/list [get]
func CollectList(ctx *gin.Context) {
var req proto.PlayletCollectListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.CollectList(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// BoughtList app端我的已购短剧列表
// @Tags app短剧相关接口
// @Summary app端我的已购短剧列表 --by 王鸣
// @Description 按当前用户最近购买时间倒序分页返回已购短剧列表,并返回已购集数、消耗金币和最近观看位置
// @Accept json
// @Produce json
// @Param params query proto.PlayletBoughtListReq true "我的已购短剧列表请求"
// @Success 200 {object} proto.PlayletBoughtListResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/bought/list [get]
func BoughtList(ctx *gin.Context) {
var req proto.PlayletBoughtListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.BoughtList(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// HistoryList app端我的短剧观看历史列表
// @Tags app短剧相关接口
// @Summary app端我的短剧观看历史列表 --by 王鸣
// @Description 按当前用户最近观看时间倒序分页返回短剧观看历史;pageSize默认20、最大100
// @Accept json
// @Produce json
// @Param params query proto.PlayletHistoryListReq true "观看历史列表请求"
// @Success 200 {object} proto.PlayletHistoryListResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/history/list [get]
func HistoryList(ctx *gin.Context) {
var req proto.PlayletHistoryListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.HistoryList(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// DeleteHistory app端删除单条短剧观看历史
// @Tags app短剧相关接口
// @Summary app端删除单条短剧观看历史 --by 王鸣
// @Description 删除当前用户指定短剧的观看历史,不影响观看进度、收藏和已购记录
// @Accept json
// @Produce json
// @Param param body proto.PlayletHistoryDeleteReq true "删除单条观看历史请求"
// @Success 200 {object} proto.PlayletHistoryDeleteResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/history/delete [post]
func DeleteHistory(ctx *gin.Context) {
var req proto.PlayletHistoryDeleteReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.DeleteHistory(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ClearHistory app端清空我的短剧观看历史
// @Tags app短剧相关接口
// @Summary app端清空我的短剧观看历史 --by 王鸣
// @Description 仅清空观看历史,不影响收藏列表和观看进度
// @Accept json
// @Produce json
// @Success 200 {object} proto.PlayletHistoryClearResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/history/clear [post]
func ClearHistory(ctx *gin.Context) {
resp, err := playletser.ClearHistory(ctx, common.GetUserId(ctx))
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// SetChapterLike app端短剧剧集点赞/取消点赞
// @Tags app短剧相关接口
// @Summary app端短剧剧集点赞/取消点赞 --by 王鸣
// @Description 设置当前用户短剧剧集点赞状态,点赞数只在状态真实变化时增减
// @Accept json
// @Produce json
// @Param param body proto.PlayletChapterLikeSetReq true "短剧剧集点赞设置请求"
// @Success 200 {object} proto.PlayletChapterLikeSetResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/chapter/like/set [post]
func SetChapterLike(ctx *gin.Context) {
var req proto.PlayletChapterLikeSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.SetChapterLike(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// SetChapterCollect app端短剧剧集收藏/取消收藏
// @Tags app短剧相关接口
// @Summary app端短剧剧集收藏/取消收藏 --by 王鸣
// @Description 设置当前用户短剧剧集收藏状态,收藏数只在状态真实变化时增减
// @Accept json
// @Produce json
// @Param param body proto.PlayletChapterCollectSetReq true "短剧剧集收藏设置请求"
// @Success 200 {object} proto.PlayletChapterCollectSetResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/chapter/collect/set [post]
func SetChapterCollect(ctx *gin.Context) {
var req proto.PlayletChapterCollectSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.SetChapterCollect(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ChapterCollectList app端我的短剧剧集收藏列表
// @Tags app短剧相关接口
// @Summary app端我的短剧剧集收藏列表 --by 王鸣
// @Description 按当前用户收藏时间倒序分页返回短剧剧集收藏列表
// @Accept json
// @Produce json
// @Param params query proto.PlayletChapterCollectListReq true "我的短剧剧集收藏列表请求"
// @Success 200 {object} proto.PlayletChapterCollectListResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/chapter/collect/list [get]
func ChapterCollectList(ctx *gin.Context) {
var req proto.PlayletChapterCollectListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.ChapterCollectList(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ReportChapterWatch app端短剧剧集观看上报
// @Tags app短剧相关接口
// @Summary app端短剧剧集观看上报 --by 王鸣
// @Description 上报当前用户短剧剧集播放进度,达到已看条件时用于我的收藏未看集数计算
// @Accept json
// @Produce json
// @Param param body proto.PlayletChapterWatchReportReq true "短剧剧集观看上报请求"
// @Success 200 {object} proto.PlayletChapterWatchReportResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/chapter/watch/report [post]
func ReportChapterWatch(ctx *gin.Context) {
var req proto.PlayletChapterWatchReportReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.ReportChapterWatch(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// UnlockChapter app端使用金币逐集解锁短剧剧集
// @Tags app短剧相关接口
// @Summary app端使用金币逐集解锁短剧剧集 --by 王鸣
// @Description 仅金币付费剧集可调用;接口具备幂等性,已解锁剧集重复调用不会重复扣金币
// @Accept json
// @Produce json
// @Param param body proto.PlayletChapterUnlockReq true "短剧剧集金币解锁请求"
// @Success 200 {object} proto.PlayletChapterUnlockResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/playlet/chapter/unlock [post]
func UnlockChapter(ctx *gin.Context) {
var req proto.PlayletChapterUnlockReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err1 := playletser.UnlockChapter(ctx, common.GetUserId(ctx), &req)
if err1 != nil {
common.ServerJSON(ctx, err1.Code, err1.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Detail app端根据ID查询短剧详情
// @Tags app短剧相关接口
// @Summary app端根据ID查询短剧详情 --by 王鸣
// @Description 根据短剧ID或slug查询已上架短剧详情;slug非空时优先按slug解析短剧ID
// @Produce json
// @Param params query proto.PlayletInfoReq true "短剧详情请求"
// @Success 200 {object} proto.PlayletInfoResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/detail [get]
func Detail(ctx *gin.Context) {
var req proto.PlayletInfoReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.Detail(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ChapterDetail app端根据ID查询短剧剧集详情
// @Tags app短剧相关接口
// @Summary app端根据ID查询短剧剧集详情 --by 王鸣
// @Description 根据短剧剧集ID查询播放页当前剧集详情;可传playletId或playletSlug校验剧集归属,slug非空时优先解析短剧ID
// @Produce json
// @Param params query proto.PlayletChapterInfoReq true "短剧剧集详情请求"
// @Success 200 {object} proto.PlayletChapterInfoResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/chapter/detail [get]
func ChapterDetail(ctx *gin.Context) {
var req proto.PlayletChapterInfoReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := playletser.ChapterDetail(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ChapterList app端根据短剧ID查询剧集列表
// @Tags app短剧相关接口
// @Summary app端根据短剧ID查询剧集列表 --by 王鸣
// @Description 根据短剧ID或slug查询右侧选集列表;slug非空时优先按slug解析短剧ID
// @Produce json
// @Param params query proto.PlayletChapterListReq true "短剧剧集列表请求"
// @Success 200 {object} proto.PlayletChapterListResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/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 := playletser.ChapterList(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
+27
View File
@@ -0,0 +1,27 @@
package playlettagapi
import (
"videoweb/app/service/playlettagser"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// List app端短剧标签列表
// @Tags app短剧标签相关接口
// @Summary app端短剧标签列表 --by 王鸣
// @Description 无请求参数,不分页,返回已上架短剧标签列表
// @Accept json
// @Produce json
// @Success 200 {object} proto.PlayletTagListResponse "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/playlet/tag/options [get]
func List(ctx *gin.Context) {
resp, err := playlettagser.List(ctx)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
+27
View File
@@ -0,0 +1,27 @@
package playletthemeapi
import (
"videoweb/app/service/playletthemeser"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// List app端短剧题材列表
// @Tags app短剧题材相关接口
// @Summary app端短剧题材列表 --by 王鸣
// @Description 无请求参数,不分页,返回已上架题材列表
// @Accept json
// @Produce json
// @Success 200 {object} proto.PlayletThemeListResponse "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/theme/list [get]
func List(ctx *gin.Context) {
resp, err := playletthemeser.List(ctx)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
+28
View File
@@ -0,0 +1,28 @@
package proto
// AboutNodeItem 关于我们节点
type AboutNodeItem struct {
NodeId int64 `json:"nodeId"`
Title string `json:"title"`
SubTitle string `json:"subTitle"`
Content string `json:"content"` // JSON字符串
//类型描述:
//文本:录入纯文本信息
//声明:图片、文本信息
//条目:可以录入多条,可删可增
//收录:收录类型(文章、网址、工具)、价格、单位、时效、描述
//图文:图片、文本信息
//注意:图片、文本信息
Type int `json:"type"`
ServiceDuration string `json:"serviceDuration"` // 服务时效
DurationIcon string `json:"durationIcon"` // 时效图标(CDN已处理)
Sort int `json:"sort"`
}
// AboutData 关于我们页面数据
type AboutData struct {
Intro string `json:"intro"` // 简介
Nodes []*AboutNodeItem `json:"nodes"` // 节点列表
Categories []*ToolCategoryItem `json:"categories"` // 分类列表
Site SiteCommonData `json:"site"` // 通用站点数据
}
+34
View File
@@ -0,0 +1,34 @@
package proto
import "videoweb/pub/storage/proxy"
type AdsClickReq struct {
AdsId string `json:"adsId,omitempty" binding:"required"`
Location int64 `json:"location,omitempty" binding:"required"` // 位置ID
}
type AdsClickInfo struct {
AppId int64 `json:"appId,omitempty" binding:"required"` // appId
AdsId int64 `json:"adsId,omitempty" binding:"required"`
Location int64 `json:"location,omitempty" binding:"required"` // 位置ID
}
type AdvitiseData struct {
HomeList []proxy.AdvitiseInfo `json:"homeList" bson:"homeList"` // 首页列表
DetailTopList []proxy.AdvitiseInfo `json:"detailTopList" bson:"detailTopList"` // 详情页顶部广告
NineGridList []proxy.AdvitiseInfo `json:"nineGridList" bson:"nineGridList"` // 9宫格
DetailbannerList []proxy.AdvitiseInfo `json:"detailbannerList" bson:"detailbannerList"` // 详情banner
LaunchScreenList []proxy.AdvitiseInfo `json:"launchScreenList"` // 启动页广告
FloatingList []proxy.AdvitiseInfo `json:"floatingList" bson:"floatingList"` // 悬浮小方块
AList []proxy.AdvitiseInfo `json:"AList"` // 固定12广告位
BList []proxy.AdvitiseInfo `json:"BList"` // 固定13广告位
DialogList []proxy.AdvitiseInfo `json:"dialogList" bson:"dialogList"` // 弹窗广告
BottomBanner []proxy.AdvitiseInfo `json:"bottomBanner" bson:"bottomBanner"` // 底部banner
VideoInfoList []proxy.AdvitiseInfo `json:"videoInfoList" bson:"videoInfoList"` // 视频详情
DownList []proxy.AdvitiseInfo `json:"downList" bson:"downList"` // 底部广告
FriendList []proxy.AdvitiseInfo `json:"friendList" bson:"friendList"` // 友链
TitleList []proxy.AdvitiseInfo `json:"titleList" bson:"titleList"` // 标题广告
PlayList []proxy.AdvitiseInfo `json:"playList" bson:"playList"` // 播放强制跳转
PauseyList []proxy.AdvitiseInfo `json:"pauseyList" bson:"pauseyList"` // 暂停广告
}
+261
View File
@@ -0,0 +1,261 @@
package proto
import "videoweb/pub/pubdef"
// -------- 公共站点数据 --------
// FriendlyLinkItem 友情链接
type FriendlyLinkItem struct {
Id int64 `json:"id"`
Name string `json:"name"`
Url string `json:"url"`
Sort int `json:"sort"`
}
// ContactInfoItem 联系方式
type ContactInfoItem struct {
Id int64 `json:"id"`
Icon string `json:"icon"`
Type int `json:"type"` // 1=邮箱 2=URL 3=文字
Address string `json:"address"`
Sort int `json:"sort"`
}
// SiteCommonData 每个接口都会携带的通用站点信息
type SiteCommonData struct {
Config ConfigInfo `json:"config"`
FriendlyLinks []*FriendlyLinkItem `json:"friendlyLinks"`
ContactInfos []*ContactInfoItem `json:"contactInfos"`
Advitise AdvitiseData `json:"advitise"`
ToolCount int64 `json:"toolCount"` // 审核通过的工具总数
}
// -------- 分类 --------
// ToolSubCategoryItem 子分类简要信息
type ToolSubCategoryItem struct {
Id int64 `json:"id"`
Slug string `json:"slug"`
Name string `json:"name"`
CategoryId int64 `json:"categoryId"`
SeoInfo pubdef.SeoValue `json:"seoInfo"`
}
// ToolCategoryItem 主分类简要信息
type ToolCategoryItem struct {
Id int64 `json:"id"`
Slug string `json:"slug"`
Name string `json:"name"`
Icon string `json:"icon"`
Sort int `json:"sort"`
SeoInfo pubdef.SeoValue `json:"seoInfo"`
SubCategories []*ToolSubCategoryItem `json:"subCategories"`
}
// -------- 工具 --------
// ToolBriefItem 工具简要信息(列表卡片)
type ToolBriefItem struct {
Id int64 `json:"id"`
Slug string `json:"slug"`
Title string `json:"title"`
Logo string `json:"logo"`
Snapshot string `json:"snapshot"`
Intro string `json:"intro"`
OfficialUrl string `json:"officialUrl"`
Hot int64 `json:"hot"`
}
// CategorySection 首页分类区块:分类标题 + 子分类列表 + 前10条工具
type CategorySection struct {
CategoryId int64 `json:"categoryId"`
CategorySlug string `json:"categorySlug"`
CategoryName string `json:"categoryName"`
CategoryIcon string `json:"categoryIcon"`
CategorySort int `json:"categorySort"`
SubCategories []*ToolSubCategoryItem `json:"subCategories"`
Tools []*ToolBriefItem `json:"tools"`
}
// ToolNodeItem 工具节点
type ToolNodeItem struct {
NodeId int64 `json:"nodeId"`
Title string `json:"title"`
Type int `json:"type"` // 1=文本 2=条目 3=QA 4=图片
Content string `json:"content"` // JSON字符串,格式因类型而异
Sort int `json:"sort"`
ReviewStatus int `json:"reviewStatus"` // 0=待审核 1=通过 2=下架
}
// ToolRecommendItem 推荐工具简要信息
type ToolRecommendItem struct {
Id int64 `json:"id"`
Slug string `json:"slug"`
Title string `json:"title"`
Intro string `json:"intro"`
Logo string `json:"logo"`
}
// ArticleRecommendItem 推荐文章简要信息
type ArticleRecommendItem struct {
Id int64 `json:"id"`
Slug string `json:"slug"`
Title string `json:"title"`
Intro string `json:"intro"`
Cover string `json:"cover"`
CreatedAt string `json:"createdAt"` // 格式:yyyy/MM/dd
}
// ToolDetailItem 工具详情
type ToolDetailItem struct {
Id int64 `json:"id"`
Slug string `json:"slug"`
CategoryId int64 `json:"categoryId"`
CategoryName string `json:"categoryName"`
SubCateId int64 `json:"subCateId"`
SubCateName string `json:"subCateName"`
Title string `json:"title"`
Logo string `json:"logo"`
Snapshot string `json:"snapshot"`
Intro string `json:"intro"`
Desc string `json:"desc"`
SeoInfo pubdef.SeoValue `json:"seoInfo"`
OfficialUrl string `json:"officialUrl"`
Hot int64 `json:"hot"`
ViewCount int64 `json:"viewCount"`
Nodes []*ToolNodeItem `json:"nodes"`
RelatedTools []*ToolRecommendItem `json:"relatedTools"` // 相关推荐(优先同子分类,不足补其他分类)
RecommendTools []*ToolRecommendItem `json:"recommendTools"` // 工具推荐(随机6个)
RecommendArticles []*ArticleRecommendItem `json:"recommendArticles"` // 文章推荐(随机6个)
CommentList GetCommentListResp `json:"commentList"` // 评论
Categories []*ToolCategoryItem `json:"categories"` // 分类列表
Site SiteCommonData `json:"site"`
}
// -------- 文章 --------
// ArticleBriefItem 文章简要信息(列表卡片)
type ArticleBriefItem struct {
Id int64 `json:"id"`
Slug string `json:"slug"`
Title string `json:"title"`
Intro string `json:"intro"`
Author string `json:"author"`
AuthorAvatar string `json:"authorAvatar"`
Cover string `json:"cover"`
ViewCount int64 `json:"viewCount"`
Sort int `json:"sort"`
CreatedAt string `json:"createdAt"` // 格式:yyyy/MM/dd
}
// ArticleNodeItem 文章节点
type ArticleNodeItem struct {
NodeId int64 `json:"nodeId"`
Title string `json:"title"`
Type int `json:"type"` // 1=文本 2=条目 3=QA 4=图片
Content string `json:"content"` // JSON字符串,格式因类型而异
Sort int `json:"sort"`
}
// ArticleNavItem 文章导航(上一篇/下一篇)
type ArticleNavItem struct {
Id int64 `json:"id"`
Slug string `json:"slug"`
Title string `json:"title"`
}
// ArticleDetailItem 文章详情
type ArticleDetailItem struct {
Id int64 `json:"id"`
Slug string `json:"slug"`
Title string `json:"title"`
Intro string `json:"intro"`
Author string `json:"author"`
AuthorAvatar string `json:"authorAvatar"`
Cover string `json:"cover"`
SeoInfo pubdef.SeoValue `json:"seoInfo"`
ViewCount int64 `json:"viewCount"`
Sort int `json:"sort"`
ReviewStatus int `json:"reviewStatus"`
CreatedAt string `json:"createdAt"` // 格式:yyyy/MM/dd
Nodes []*ArticleNodeItem `json:"nodes"`
Prev *ArticleNavItem `json:"prev"` // 上一篇(无则为 null)
Next *ArticleNavItem `json:"next"` // 下一篇(无则为 null)
RecommendTools []*ToolRecommendItem `json:"recommendTools"` // 工具推荐(随机6个)
RecommendArticles []*ArticleRecommendItem `json:"recommendArticles"` // 文章推荐(随机6个)
CommentList GetCommentListResp `json:"commentList"` // 评论
Categories []*ToolCategoryItem `json:"categories"` // 分类列表
Site SiteCommonData `json:"site"`
}
// -------- 页面级响应 --------
// AIToolsHomeData 工具首页数据
type AIToolsHomeData struct {
Categories []*ToolCategoryItem `json:"categories"`
HotTools []*ToolBriefItem `json:"hotTools"` // 热门推荐工具(按设置时间倒序)
Sections []*CategorySection `json:"sections"`
Articles []*ArticleBriefItem `json:"articles"`
Site SiteCommonData `json:"site"`
}
// AIToolsListData 工具列表页数据
type AIToolsListData struct {
Categories []*ToolCategoryItem `json:"categories"`
Total int64 `json:"total"`
List []*ToolBriefItem `json:"list"`
Site SiteCommonData `json:"site"`
}
// SearchArticleItem 搜索命中的文章
type SearchArticleItem struct {
Id int64 `json:"id"`
Slug string `json:"slug"`
Title string `json:"title"`
Intro string `json:"intro"`
Author string `json:"author"`
AuthorAvatar string `json:"authorAvatar"`
Cover string `json:"cover"`
CreatedAt string `json:"createdAt"` // 格式:yyyy/MM/dd
Score float32 `json:"score"` // 相关度分数
}
// SearchToolItem 搜索命中的工具
type SearchToolItem struct {
Id int64 `json:"id"`
Slug string `json:"slug"`
CategoryId int64 `json:"categoryId"`
SubCateId int64 `json:"subCateId"`
Title string `json:"title"`
Logo string `json:"logo"`
Snapshot string `json:"snapshot"`
Intro string `json:"intro"`
OfficialUrl string `json:"officialUrl"`
Hot int64 `json:"hot"`
Score float32 `json:"score"` // 相关度分数
}
// AISearchData 搜索结果
type AISearchData struct {
Keyword string `json:"keyword"`
Articles []*SearchArticleItem `json:"articles"`
Tools []*SearchToolItem `json:"tools"`
Site SiteCommonData `json:"site"`
}
// AIRecommendData 推荐展示数据
type AIRecommendData struct {
Articles []*ArticleBriefItem `json:"articles"` // 随机2篇文章
Tools []*ToolBriefItem `json:"tools"` // 随机20个工具
Site SiteCommonData `json:"site"`
}
// AIArticleListData 文章列表页数据
type AIArticleListData struct {
Categories []*ToolCategoryItem `json:"categories"`
Total int64 `json:"total"`
List []*ArticleBriefItem `json:"list"`
Site SiteCommonData `json:"site"`
RecommendTools []*ToolRecommendItem `json:"recommendTools"` // 工具推荐(随机6个)
RecommendArticles []*ArticleRecommendItem `json:"recommendArticles"` // 文章推荐(随机6个)
}
+55
View File
@@ -0,0 +1,55 @@
package proto
// AppListResp 应用列表接口响应
type AppListResp struct {
// 当前路径
Path string `json:"path"`
// 配置信息
Config ConfigInfo `json:"config"`
// 广告
Advitise AdvitiseData `json:"advitise"`
// 应用分类列表(含各分类下的应用列表)
CategoryList []AppCategoryInfo `json:"categoryList"`
// 当前分类(含应用列表)
Category AppCategoryInfo `json:"category"`
}
// AppCategoryInfo 应用分类信息
type AppCategoryInfo struct {
// 分类ID
Id int64 `json:"id"`
// 分类标题
Title string `json:"title"`
// 分类简介
Intro string `json:"intro"`
// 排序
Sort int64 `json:"sort"`
// 分类编码(特殊值:12=广告位A 13=广告位B)
Code int64 `json:"code"`
// 应用列表
AppList []AppInfoData `json:"appList"`
}
// AppInfoData 应用信息
type AppInfoData struct {
// 应用ID
Id int64 `json:"id"`
// 所属分类ID
CategoryId int64 `json:"categoryId"`
// 应用名称
Name string `json:"name"`
// 简介
Intro string `json:"intro"`
// 详细描述
Description string `json:"description"`
// Logo 图片地址
Logo string `json:"logo"`
// 跳转链接(已含渠道码)
Url string `json:"url"`
// 排序
Sort int64 `json:"sort"`
// 广告ID(广告条目时返回)
AdvitiseId string `json:"advitiseId"`
// 广告位置ID
Location int64 `json:"location"`
}
+35
View File
@@ -0,0 +1,35 @@
package proto
import "videoweb/pub/models/cointransmod"
// CoinTransListItemResp 金币余额明细列表项
type CoinTransListItemResp struct {
// 流水ID
Id int64 `json:"id"`
// 标题,优先使用备注,备注为空时使用交易类型名称
Title string `json:"title"`
// 收支方向:1-收入,-1-支出
FlowDir cointransmod.FlowDir `json:"flowDir"`
// 收支方向名称:收入/支出
FlowDirName string `json:"flowDirName"`
// 交易类型 1-金币充值(购买金币)2-购买会员赠送金币 3-历史遗留 4-视频解锁 5-管理员手动调整
TranType cointransmod.TranType `json:"tranType"`
// 交易类型名称
TranTypeName string `json:"tranTypeName"`
// 本次交易金币数,始终为正数
Amount int64 `json:"amount"`
// 带方向的金币变动数,收入为正数,支出为负数
ChangeAmount int64 `json:"changeAmount"`
// 交易前余额
BalanceBefore int64 `json:"balanceBefore"`
// 交易后余额
BalanceAfter int64 `json:"balanceAfter"`
// 关联订单号
OrderNo string `json:"orderNo"`
// 关联内容ID
RelatedId int64 `json:"relatedId"`
// 备注
Remark string `json:"remark"`
// 交易时间,格式:2006-01-02 15:04:05
CreatedAt string `json:"createdAt"`
}
+65
View File
@@ -0,0 +1,65 @@
package proto
import (
"time"
"videoweb/pub/pubdef"
)
// GetCommentListReq 评论列表请求
type GetCommentListReq struct {
ObjectId int64 `form:"objectId" json:"objectId" binding:"required"` // 对象ID(短剧id 短剧剧集id 视频id)
ObjectType int64 `form:"objectType" json:"objectType" binding:"required"` // 对象类型 10-短剧 11-短剧剧集 20-视频
SortOrder int64 `form:"sortOrder" json:"sortOrder"` // 排序 1-热门,按点赞数倒序 2-最新,按创建时间倒序
pubdef.Page
}
// GetCommentListResp 评论列表响应
type GetCommentListResp struct {
ObjectId int64 `json:"objectId"` // 对象ID
TotalCount int64 `json:"totalCount"` // 总数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []CommentInfo `json:"list"` // 数据
}
// CommentSendReq 评论发布请求
type CommentSendReq struct {
ObjectId int64 `json:"objectId"` // 对象ID,短剧评论传短剧ID,剧集评论传剧集ID,视频评论传视频ID
ObjectType int64 `json:"objectType"` // 对象类型 10-短剧 11-短剧剧集 20-视频
ParentsId int64 `json:"parentsId"` // 一级评论ID,0-发布一级评论,大于0-发布二级评论
ReplyCommentId int64 `json:"replyCommentId"` // 被回复评论ID,0时默认回复parentsId
Text string `json:"text"` // 评论内容
}
// CommentLikeSetReq 评论点赞设置请求
type CommentLikeSetReq struct {
CommentId int64 `json:"commentId" binding:"required"` // 评论ID
IsLike *bool `json:"isLike" binding:"required"` // 是否点赞,true-点赞,false-取消点赞
}
// CommentLikeSetResp 评论点赞设置响应
type CommentLikeSetResp struct {
CommentId int64 `json:"commentId"` // 评论ID
IsLike int64 `json:"isLike"` // 点赞状态 1-已点赞 2-未点赞
CountLike int64 `json:"countLike"` // 评论点赞数
}
// CommentInfo 评论信息
type CommentInfo struct {
Id int64 `json:"id"` // 评论ID
ObjectId int64 `json:"objectId"` // 对象ID
ObjectType int64 `json:"objectType"` // 对象类型 10-短剧 11-短剧剧集 20-视频
UserId int64 `json:"userId"` // 评论用户ID
UserName string `json:"userName"` // 用户名称
UserAvatar string `json:"userAvatar"` // 用户头像,已拼接图片域名
Text string `json:"text"` // 评论内容
Level int64 `json:"level"` // 评论级别 1-一级评论 2-二级评论
ParentsId int64 `json:"parentsId"` // 父评论ID,一级评论为0
ReplyCommentId int64 `json:"replyCommentId"` // 被回复评论ID,一级评论为0
ReplyUserName string `json:"replyUserName"` // 被回复用户昵称
CommentCount int64 `json:"commentCount"` // 二级评论数量
CountLike int64 `json:"countLike"` // 评论点赞数
IsLike int64 `json:"isLike"` // 当前用户点赞状态 1-已点赞 2-未点赞
CreatedAt time.Time `json:"createdAt"` // 创建时间
Children []CommentInfo `json:"children"` // 二级评论列表
}
+125
View File
@@ -0,0 +1,125 @@
package proto
type ConfigInfo struct {
PdfAddr string `json:"pdfAddr" bson:"pdfAddr"` // 回家的路PDF
NewUrlAddr string `json:"newUrlAddr" bson:"newUrlAddr"` //最新地址
NewUrlAddr1 string `json:"newUrlAddr1" bson:"newUrlAddr1"` //最新地址(备用地址1)
NewUrlAddr2 string `json:"newUrlAddr2" bson:"newUrlAddr2"` //最新地址(备用地址2)
ForeverUrlAddr string `json:"foreverUrlAddr" bson:"foreverUrlAddr"` //永久地址
GmailAddr string `json:"gmailAddr" bson:"gmailAddr"` //邮箱地址
AppAddr string `json:"appAddr" bson:"appAddr"` //APP下载地址(落地页)
OfficialAppAddr string `json:"officialAppAddr" bson:"officialAppAddr"` //官网app地址
WeiChart string `json:"weiChart" bson:"weiChart"` //微信群
QQ string `json:"qq" bson:"qq"` //qq群
TgGroup string `json:"tgGroup" bson:"tgGroup"` //tg群
PotaoGroup string `json:"potaoGroup" bson:"potaoGroup"` //土豆群
GitAddr string `json:"gitAddr" bson:"gitAddr"` //git地址
TwitterAddr string `json:"twitterAddr" bson:"twitterAddr"` //推特地址
Telegram string `json:"telegram" bson:"telegram"` //商务tg
TelegramAdd string `json:"telegramAdd" bson:"telegramAdd"` //加入我们tg
TranslationAddr string `json:"translationAddr" bson:"translationAddr"` //应用导航
ImgCdn string `json:"imgCdn" bson:"imgCdn"` // 图片CDN
TsCdn string `json:"tsCdn" bson:"tsCdn"` // 视频CDN
ImgAppUsCdn string `json:"imgAppUsCdn" bson:"imgAppUsCdn"` // 图片CDN(海外app使用)
MediaAppUsCdn string `json:"mediaAppUsCdn" bson:"mediaAppUsCdn"` // 视频CDN(海外app使用)
WebTitle string `json:"webTitle" bson:"webTitle"` // 网站SEO标题
WebKeyworld []string `json:"webKeyworld" bson:"webKeyworld"` // 网站SEO关键字
WebDescription string `json:"webDescription" bson:"webDescription"` // 网站SEO描述
WebSiteName string `json:"webSiteName" bson:"webSiteName"` // 网站SEO网站名称
WebAddr string `json:"webAddr" bson:"webAddr"` // 网站SEO网站地址
DHNewUrlAddr1 string `json:"dhNewUrlAddr1" bson:"dhNewUrlAddr1"` // 导航页-线路1
DHNewUrlAddr2 string `json:"dhNewUrlAddr2" bson:"dhNewUrlAddr2"` // 导航页-线路2
DHNewUrlAddr3 string `json:"dhNewUrlAddr3" bson:"dhNewUrlAddr3"` // 导航页-线路3
FreeVPN string `json:"freeVPN" bson:"freeVPN"` // 免费vpn链接
UseIngAddress []string `json:"useIngAddress" bson:"useIngAddress"` // 所有使用中的域名
AdvitiesTopicNum int64 `json:"advitiesTopicNum" bson:"advitiesTopicNum"` // 广告间隔
DHTitle string `json:"dhTitle" bson:"dhTitle"` // 导航SEO标题
DHKeyworld []string `json:"dhKeyworld" bson:"dhKeyworld"` // 导航SEO关键字
DHDescription string `json:"dhDescription" bson:"dhDescription"` // 导航SEO描述
DHSiteName string `json:"dhSiteName" bson:"dhSiteName"` // 导航SEO网站名称
ActressBackGround string `json:"actressBackGround" bson:"actressBackGround"` // 女优通用背景图
ReportSDKConfig string `json:"reportSdkConfig"` // 数据上报SDK域名配置
WatermarkImage string `json:"watermarkImage"` // 图片水印文件
CustomerServiceHost string `json:"customerServiceHost"` // 在线客服
ChannelCode string `json:"channelCode"` // 渠道码
EnableH265 bool `json:"enableH265"` // 是否允许客户端使用 H265 地址播放
}
type AdvitiseInfo struct {
Id int64 `json:"id" bson:"_id"` // 广告id
Title string `json:"title" bson:"title"` // 广告标题
Images string `json:"images" bson:"images"` // 视频banner
Link string `json:"link" bson:"link"` // 链接
}
// ConfigInfoResp APP配置响应
type ConfigInfoResp struct {
// 最新地址信息
NewAddressInfo NewAddressInfo `json:"newAddressInfo"`
// 完整系统配置(与首页等接口的 config 一致,含 potaoGroup 等其余字段)
Config ConfigInfo `json:"config"`
// 广告配置
Advitise AdvitiseData `json:"advitise"`
// 全站SEO信息
SeoInfo SeoInfo `json:"seoInfo"`
// 导航SEO信息
SeoNavInfo SeoNavInfo `json:"seoNavInfo"`
// 导航页线路集合
NavPageList []NavPageItem `json:"navPageList"`
// 数据上报SDK域名配置
ReportSDKConfig string `json:"reportSdkConfig"`
}
// SeoNavInfo 导航SEO信息
type SeoNavInfo struct {
DHTitle string `json:"dhTitle"` // 导航标题
DHKeyworld []string `json:"dhKeyworld"` // 关键词
DHDescription string `json:"dhDescription"` // 导航描述
DHSiteName string `json:"dhSiteName"` // 导航名称
}
// NavPageItem 导航页线路
type NavPageItem struct {
Line int64 `json:"line"` // 线路序号
Url string `json:"url"` // 线路地址
}
// FooterInfoResp APP底部信息响应
type FooterInfoResp struct {
FooterInfo FooterInfo `json:"footerInfo"` // 底部信息
}
// FooterInfo APP底部信息
type FooterInfo struct {
Brand FooterBrand `json:"brand"` // 品牌信息
NavList []TranslationCategory `json:"navList"` // 底部导航
ContactList []FooterContact `json:"contactList"` // 联系方式
}
// FooterBrand APP底部品牌信息
type FooterBrand struct {
Title string `json:"title"` // 品牌标题
Content string `json:"content"` // 品牌标语
}
// FooterContact APP底部联系方式
type FooterContact struct {
Name string `json:"name"` // 联系方式名称
Value string `json:"value"` // 联系方式值
}
// NewAddressInfo 最新地址
type NewAddressInfo struct {
NewUrlAddr string `json:"newUrlAddr"` // 新国内地址
NewUrlAddr1 string `json:"newUrlAddr1"` // 备用地址1
NewUrlAddr2 string `json:"newUrlAddr2"` // 备用地址1
ForeverUrlAddr string `json:"foreverUrlAddr"` // 永久海外地址(翻墙访问 永不迷路)
GmailAddr string `json:"gmailAddr"` // 邮箱地址
TgGroup string `json:"tgGroup"` // tg群
Telegram string `json:"telegram" bson:"telegram"` // 商务tg
CustomerServiceHost string `json:"customerServiceHost"` // 在线客服
TwitterAddr string `json:"twitterAddr"` // 推特地址
PdfAddr string `json:"pdfAddr"` // 回家的路PDF
AppAddr string `json:"appAddr"` // APP下载地址(落地页)
OfficialAppAddr string `json:"officialAppAddr"` // 官网app地址
}
+21
View File
@@ -0,0 +1,21 @@
package proto
// ContactUsAddReq 联系我们请求
type ContactUsAddReq struct {
// 邮箱
Email string `json:"email" binding:"required"`
// 问题类型,1-订单问题、2-账号问题、3-功能问题、4-体验问题、5-其他
Type int32 `json:"type" binding:"required"`
// 标题
Title string `json:"title" binding:"required"`
// 内容
Content string `json:"content" binding:"required"`
// 附件地址,可存放多张图片或文件地址
Attachments []string `json:"attachments"`
}
// ContactUsAddResp 联系我们响应
type ContactUsAddResp struct {
// 提示信息
Message string `json:"message"`
}
+6
View File
@@ -0,0 +1,6 @@
package proto
type ContributeData struct {
Path string `json:"path"`
RichText []RichTextInfo `json:"richText" form:"richText"` // 富文本内容
}
+37
View File
@@ -0,0 +1,37 @@
package proto
// DHHtmlData 导航数据
type DHHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
RichTextInfo RichTextInfo `json:"richTextInfo" form:"richTextInfo"` // 富文本
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
}
// DHConsultingHtmlData 招募
type DHConsultingHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
RichTextInfo RichTextInfo `json:"richTextInfo" form:"richTextInfo"` // 富文本
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
}
// DHConsultingInfoHtmlData 招募
type DHConsultingInfoHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
RichTextInfo RichTextInfo `json:"richTextInfo" form:"richTextInfo"` // 富文本
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
}
+19
View File
@@ -0,0 +1,19 @@
package proto
// FeedbackReq 意见反馈请求
type FeedbackReq struct {
// 问题类型,1-功能建议、2-Bug反馈、3-体验问题、4-账号问题、5-其他
Type int32 `json:"type" binding:"required"`
// 描述内容,最多500字
Content string `json:"content" binding:"required"`
// 问题截图,可存放多张图片地址
Screenshots []string `json:"screenshots"`
// 联系方式,可为空
Contact string `json:"contact"`
}
// FeedbackResp 意见反馈响应
type FeedbackResp struct {
// 提示信息
Message string `json:"message"`
}
+5
View File
@@ -0,0 +1,5 @@
package proto
type FindVideoData struct {
RichText []RichTextInfo `json:"richText" form:"richText"` // 富文本内容
}
+37
View File
@@ -0,0 +1,37 @@
package proto
type HealthCheckRequest struct {
GroupID string `json:"groupId" binding:"required"`
Timestamp int64 `json:"timestamp" binding:"required"`
Sign string `json:"sign" binding:"required"`
}
type ComponentStatus struct {
Status string `json:"status"`
Msg string `json:"msg,omitempty"`
Master string `json:"master,omitempty"`
}
type HealthCPUMetrics struct {
Cores int `json:"cores"`
Used float64 `json:"used"`
}
type HealthMemoryMetrics struct {
Total int64 `json:"total"`
Used int64 `json:"used"`
}
type HealthCheckData struct {
ServerName string `json:"serverName,omitempty"`
ServerIP string `json:"serverIp,omitempty"`
CPU HealthCPUMetrics `json:"cpu"`
Memory HealthMemoryMetrics `json:"memory"`
Disk HealthMemoryMetrics `json:"disk"`
Mysql *ComponentStatus `json:"mysql,omitempty"`
Mongodb *ComponentStatus `json:"mongodb,omitempty"`
Redis *ComponentStatus `json:"redis,omitempty"`
Elasticsearch *ComponentStatus `json:"elasticsearch,omitempty"`
Kafka *ComponentStatus `json:"kafka,omitempty"`
Timestamp int64 `json:"timestamp"`
}
+12
View File
@@ -0,0 +1,12 @@
package proto
// LawAndTrustHtmlData
type LawAndTrustHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
}
+663
View File
@@ -0,0 +1,663 @@
package proto
import (
"time"
"videoweb/pub/pubdef"
)
// HomePlayletResponse 首页响应
type HomePlayletResponse struct {
HomeBannerData []*CommonData `json:"homeBannerData"` // 首页banner短剧信息列表
Modules []*HomeModuleData `json:"modules"` // 首页短剧和题材模块
Announcements []*AnnouncementItem `json:"announcements"` // 启用中的公告,来自独立缓存
Advitise AdvitiseData `json:"advitise"` // 广告
SeoInfo *SeoInfo `json:"seoInfo,omitempty"` // 页面SEO信息(短剧列表页SEO)
}
// HomeConfigData 首页配置数据
type HomeConfigData struct {
Id int64 `json:"id"` // ID
Name string `json:"name"` // 名称
Slug string `json:"slug"` // slug,H5 更多页优先用它
Desc string `json:"desc"` // 描述
Keyword []string `json:"keyword"` // 页面关键字
Label string `json:"label"`
Style string `json:"style"`
CardBackgroundImage string `json:"cardBackgroundImage"`
TopicIds []int64 `json:"topicIds"`
CategoryId int64 `json:"categoryId"`
RecommendType int64 `json:"recommendType"`
Type int32 `json:"type"` // 类型 1-短剧 3-题材
Rank int64 `json:"rank"` // 排序,越大越靠前
Limit int64 `json:"limit"` // 首页展示数量
SortType int32 `json:"sortType"` // 短剧模块排序 1-推荐 2-热播 3-最近更新 4-上架时间 5-分类,题材模块预览按专题详情默认排序
Status bool `json:"status"` // 上下架状态 true-上架 false-下架
CreatedAt time.Time `json:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt"` // 修改时间
List []*CommonData `json:"list"` // 配置对应短剧集合,type=1时返回
ThemeList []*HomeConfigThemeData `json:"themeList"` // 题材集合,type=3时返回
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
type HomeModuleData struct {
Id int64 `json:"id"`
Slug string `json:"slug"`
Title string `json:"title"`
Desc string `json:"desc"`
Keyword []string `json:"keyword"` // 页面关键字
Label string `json:"label"`
Style string `json:"style"`
CardBackgroundImage string `json:"cardBackgroundImage"`
ModuleType int32 `json:"moduleType"` // 1 短剧列表,2 题材
DataType int32 `json:"dataType"` // 固定为 1 短剧
RecommendType int64 `json:"recommendType"`
CategoryId int64 `json:"categoryId"`
Rank int64 `json:"rank"`
Limit int64 `json:"limit"` // 实际生效的首页展示数量
SeoInfo pubdef.SeoValue `json:"seoInfo"` // 首页配置表中的SEO信息
List []*CommonData `json:"list"`
TopicList []*HomeConfigThemeData `json:"topicList"`
}
type PlayletHomeConfigListReq struct {
pubdef.Page
Id int64 `form:"id"`
Slug string `form:"slug"`
}
type PlayletHomeConfigListResp struct {
Config *HomeModuleData `json:"config"`
TotalCount int64 `json:"totalCount"`
PageSize int `json:"pageSize"`
PageNum int `json:"pageNum"`
List []*CommonData `json:"list"`
TopicList []*HomeConfigThemeData `json:"topicList"`
Advitise AdvitiseData `json:"advitise"`
}
// HomeConfigThemeData 首页配置题材数据
type HomeConfigThemeData struct {
Id int64 `json:"id"` // 题材ID
Name string `json:"name"` // 题材名称
Slug string `json:"slug"` // 题材slug
Icon string `json:"icon"` // 题材图标,已拼接图片域名
Rank int64 `json:"rank"` // 排序,越大越靠前
PlayletCount int64 `json:"playletCount"` // 题材下已上架短剧总数
List []*CommonData `json:"list"` // 题材下短剧集合
SeoInfo *SeoInfo `json:"seoInfo"` // 题材对应页面SEO信息
}
// AnnouncementItem 首页公告
type AnnouncementItem struct {
Id int64 `json:"id"` // 公告ID
Title string `json:"title"` // 标题
Content string `json:"content"` // 内容
}
// PlayletAllListReq 全部短剧分页请求
type PlayletAllListReq struct {
pubdef.Page
ThemeId int64 `form:"themeId" json:"themeId"` // 题材ID
ThemeSlug string `form:"themeSlug" json:"themeSlug"` // 题材slug,非空时优先按slug解析题材ID
UpdateStatus int `form:"updateStatus" json:"updateStatus"` // 更新状态 0-全部 1-连载中 2-已完结
SortType int64 `form:"sortType" json:"sortType"` // 排序 1-最新 2-最热 3-收藏最多
}
// PlayletAllListResp 全部短剧分页响应
type PlayletAllListResp struct {
TotalCount int64 `json:"totalCount"` // 总共数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []CommonData `json:"list"` // 短剧集合
Advitise AdvitiseData `json:"advitise"` // 广告
SeoInfo *SeoInfo `json:"seoInfo,omitempty"` // 页面SEO信息
}
// PlayletHotListReq 热门短剧分页请求
type PlayletHotListReq struct {
pubdef.Page
ExcludePlayletId int64 `form:"excludePlayletId" json:"excludePlayletId"` // 排除的短剧ID,默认不排除
}
// PlayletHotListResp 热门短剧分页响应
type PlayletHotListResp struct {
TotalCount int64 `json:"totalCount"` // 总共数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []CommonData `json:"list"` // 短剧集合
}
// CommonData 首页通用数据
type CommonData struct {
Id int64 `json:"id"` // 短剧id
Status int32 `json:"status"` // 状态: 0下架 1上架
IsFeatured bool `json:"isFeatured"` // 是否爆剧(true-是,false-否)
IsOriginal bool `json:"isOriginal"` // 是否原创
ShowOriginal bool `json:"showOriginal"` // 页面是否展示原创标识
IsRecommend bool `json:"isRecommend"` // 是否推荐 true-推荐,false-不推荐
IsNew bool `json:"isNew"` // 是否上新,本周内上架为true
OperateType int32 `json:"operateType"` // 运营类型 1-短剧 2-漫剧
ShowOnBanner bool `json:"showOnBanner"` // 是否显示在首页banner
Banner string `json:"banner"` // banner图,已拼接图片域名
MobileBanner string `json:"mobileBanner"` // 移动端banner图,已拼接图片域名
OnlineAt time.Time `json:"onlineAt"` // 上架时间
MediaCreatedAt time.Time `json:"mediaCreatedAt"` // 媒资中心创建时间
MediaUpdatedAt time.Time `json:"mediaUpdatedAt"` // 媒资中心更新时间
ThemeIds []int64 `json:"themeIds"` // 题材ID集合
ThemeNames []string `json:"themeNames"` // 题材名称集合
ThemeSlugs []string `json:"themeSlugs"` // 题材slug集合
CategoryIds []int64 `json:"categoryIds"` // 分类ID集合
Title string `json:"title"` // 标题
PlayName string `json:"playName"` // 剧名
Description string `json:"description"` // SEO Description
Slug string `json:"slug"` // slug
Desc string `json:"desc"` // 简介
Anchor string `json:"anchor"` // 作者/演员
Cover string `json:"cover"` // 竖版封面,已拼接图片域名
HorizontalCover string `json:"horizontalCover"` // 横版封面,已拼接图片域名
Preview string `json:"preview"` // 预告地址,详情接口返回时带播放签名
TagIds []int64 `json:"tagIds"` // 标签ID集合
TagNames []string `json:"tagNames"` // 标签名称集合
TagSlugs []string `json:"tagSlugs"` // 标签slug集合
TotalEpisode int64 `json:"totalEpisode"` // 总集数
UpdateStatus int `json:"updateStatus"` // 更新状态 1-连载中 2-已完结
CountBrowse int64 `json:"countBrowse"` // 观看量
HeatValue int64 `json:"heatValue"` // 热度值
CountCollect int64 `json:"countCollect"` // 收藏数
CountLike int64 `json:"countLike"` // 点赞数,包含真实点赞数和后台虚拟点赞数
CreatedAt time.Time `json:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt"` // 修改时间
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
// PlayletRankReq 短剧排行榜请求
type PlayletRankReq struct {
// 普通分页参数,pageNum默认1,pageSize默认10、最大100
pubdef.Page
SortOrder int64 `form:"sortOrder" json:"sortOrder"` // 排序 1-热播榜,按热度值倒序 2-新剧榜,按上架时间倒序 3-追剧榜,按收藏数倒序
}
// PlayletRankResp 短剧排行榜响应
type PlayletRankResp struct {
TotalCount int64 `json:"totalCount"` // 总共数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []CommonData `json:"list"` // 短剧集合
SeoInfo *SeoInfo `json:"seoInfo,omitempty"` // 页面SEO信息(短剧列表页SEO)
}
// PlayletHotRankListReq 热榜分页请求
type PlayletHotRankListReq struct {
pubdef.Page
RankType int64 `form:"rankType" json:"rankType"` // 榜单类型 1-热播榜 2-新剧榜 3-追剧榜
}
// PlayletHotRankListResp 热榜分页响应
type PlayletHotRankListResp struct {
TotalCount int64 `json:"totalCount"` // 总共数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
RankType int64 `json:"rankType"` // 榜单类型 1-热播榜 2-新剧榜 3-追剧榜
List []CommonData `json:"list"` // 短剧集合
SeoInfo *SeoInfo `json:"seoInfo,omitempty"` // 页面SEO信息
}
// PlayletOperateListReq 短剧分类列表分页请求
type PlayletOperateListReq struct {
pubdef.Page
Type int64 `form:"type" json:"type"` // 类型 1-最新更新 2-当前热播 3-独家原创 4-随机推荐
}
// PlayletOperateListResp 短剧分类列表响应
type PlayletOperateListResp struct {
TotalCount int64 `json:"totalCount"` // 符合条件的短剧总数
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
Type int64 `json:"type"` // 类型 1-最新更新 2-当前热播 3-独家原创 4-随机推荐
List []CommonData `json:"list"` // 当前页短剧
}
// PlayletTodayUpdateReq 今日更新短剧请求
type PlayletTodayUpdateReq struct {
// 普通分页参数,pageNum默认1,pageSize默认10、最大100
pubdef.Page
}
// PlayletTodayUpdateResp 今日更新短剧响应
type PlayletTodayUpdateResp struct {
TotalCount int64 `json:"totalCount"` // 总共数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []CommonData `json:"list"` // 短剧集合
SeoInfo *SeoInfo `json:"seoInfo,omitempty"` // 页面SEO信息(短剧列表页SEO)
}
// PlayletGuessLikeListReq 猜你喜欢分页请求
type PlayletGuessLikeListReq struct {
// 普通分页参数,pageNum默认1,pageSize默认6、最大100
pubdef.Page
PlayletId int64 `form:"playletId" json:"playletId" binding:"required"` // 当前短剧ID
}
// PlayletGuessLikeListResp 猜你喜欢分页响应
type PlayletGuessLikeListResp struct {
TotalCount int64 `json:"totalCount"` // 总共数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []CommonData `json:"list"` // 猜你喜欢短剧集合
}
// PlayletTagVideoReq 根据标签ID分页查询短剧请求
type PlayletTagVideoReq struct {
// 普通分页参数,pageNum默认1,pageSize默认10、最大100
pubdef.Page
TagId int64 `form:"tagId" json:"tagId"` // 标签ID,tagSlug为空时必传
TagSlug string `form:"tagSlug" json:"tagSlug"` // 标签slug,非空时优先按slug解析标签ID
SortType int64 `form:"sortType" json:"sortType"` // 排序 1-最新 2-最热 3-收藏最多
}
// PlayletTagVideoResp 根据标签ID分页查询短剧响应
type PlayletTagVideoResp struct {
TotalCount int64 `json:"totalCount"` // 总共数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []CommonData `json:"list"` // 短剧集合
SeoInfo *SeoInfo `json:"seoInfo,omitempty"` // 页面SEO信息(标签SEO)
}
// PlayletSearchReq 短剧ES分页搜索请求
type PlayletSearchReq struct {
// 普通分页参数,pageNum默认1,pageSize默认10、最大100
pubdef.Page
Keyword string `form:"keyword" json:"keyword"` // 搜索关键词,支持剧名、题材名、简介和标签名
}
// PlayletSearchResp 短剧ES分页搜索响应
type PlayletSearchResp struct {
TotalCount int64 `json:"totalCount"` // 总共数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
Keyword string `json:"keyword"` // 搜索词
List []CommonData `json:"list"` // 搜索结果
EveryoneWatching []*CommonData `json:"everyoneWatching"` // 大家都在看,搜索无结果时返回
}
// PlayletSearchSuggestReq 短剧搜索联想请求
type PlayletSearchSuggestReq struct {
Keyword string `form:"keyword" json:"keyword" binding:"required"` // 搜索关键词
}
// PlayletSearchSuggestResp 短剧搜索联想响应
type PlayletSearchSuggestResp struct {
Keyword string `json:"keyword"` // 搜索关键词
List []CommonData `json:"list"` // 短剧列表
}
// PlayletHotSearchItem 热搜词
type PlayletHotSearchItem struct {
Keyword string `json:"keyword"` // 搜索词
Count int64 `json:"count"` // 搜索次数
}
// PlayletHotLikeResp 热搜词和猜你喜欢
type PlayletHotLikeResp struct {
HotSearch []PlayletHotSearchItem `json:"hotSearch"` // 前10个热搜词
GuessLike []*CommonData `json:"guessLike"` // 按收藏量最多的15部上架短剧
}
// PlayletLikeListReq 我的短剧点赞列表请求
type PlayletLikeListReq struct {
pubdef.Page // 分页参数
}
// PlayletLikeData 我的短剧点赞列表项
type PlayletLikeData struct {
CommonData
IsLike int64 `json:"isLike"` // 点赞状态,固定为1-已点赞
LikedAt time.Time `json:"likedAt"` // 点赞时间
}
// PlayletLikeListResp 我的短剧点赞列表响应
type PlayletLikeListResp struct {
TotalCount int64 `json:"totalCount"` // 点赞记录总数
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []PlayletLikeData `json:"list"` // 点赞短剧集合
}
// PlayletLikeSetReq 短剧点赞设置请求
type PlayletLikeSetReq struct {
Id int64 `json:"id" binding:"required"` // 短剧ID
IsLike *bool `json:"isLike" binding:"required"` // 是否点赞,true-点赞,false-取消点赞
}
// PlayletLikeSetResp 短剧点赞设置响应
type PlayletLikeSetResp struct {
Id int64 `json:"id"` // 短剧ID
IsLike int64 `json:"isLike"` // 点赞状态 1-已点赞 2-未点赞
CountLike int64 `json:"countLike"` // 短剧点赞数
}
// PlayletCollectSetReq 短剧收藏设置请求
type PlayletCollectSetReq struct {
Id int64 `json:"id" binding:"required"` // 短剧ID
IsCollect *bool `json:"isCollect" binding:"required"` // 是否收藏,true-收藏,false-取消收藏
}
// PlayletCollectSetResp 短剧收藏设置响应
type PlayletCollectSetResp struct {
Id int64 `json:"id"` // 短剧ID
IsCollect int64 `json:"isCollect"` // 收藏状态 1-已收藏 2-未收藏
CountCollect int64 `json:"countCollect"` // 短剧收藏数
}
// PlayletForwardHeatReq 短剧转发加热度请求
type PlayletForwardHeatReq struct {
Id int64 `json:"id" binding:"required"` // 短剧ID
}
// PlayletForwardHeatResp 短剧转发加热度响应
type PlayletForwardHeatResp struct {
Id int64 `json:"id"` // 短剧ID
HeatValue int64 `json:"heatValue"` // 加热后的热度值
}
// PlayletCollectListReq 我的收藏列表请求
type PlayletCollectListReq struct {
// 普通分页参数,pageNum默认1,pageSize默认10、最大100
pubdef.Page
WatchStatus int64 `form:"watchStatus" json:"watchStatus"` // 观看状态 0-全部 1-追剧中 2-已看完
}
// PlayletCollectData 我的收藏列表项
type PlayletCollectData struct {
Id int64 `json:"id"` // 短剧ID
Title string `json:"title"` // 标题
PlayName string `json:"playName"` // 剧名
Slug string `json:"slug"` // slug
Cover string `json:"cover"` // 封面,已拼接图片域名
ThemeIds []int64 `json:"themeIds"` // 题材ID集合
ThemeNames []string `json:"themeNames"` // 题材名称集合
ThemeSlugs []string `json:"themeSlugs"` // 题材slug集合
TagIds []int64 `json:"tagIds"` // 标签ID集合
TagNames []string `json:"tagNames"` // 标签名称集合
TagSlugs []string `json:"tagSlugs"` // 标签slug集合
TotalEpisode int64 `json:"totalEpisode"` // 总集数
UpdateStatus int `json:"updateStatus"` // 更新状态 1-连载中 2-已完结
CountBrowse int64 `json:"countBrowse"` // 观看量
HeatValue int64 `json:"heatValue"` // 热度值
CountCollect int64 `json:"countCollect"` // 收藏数
IsCollect int64 `json:"isCollect"` // 收藏状态,收藏列表固定返回1-已收藏
CollectedAt time.Time `json:"collectedAt"` // 收藏时间
WatchedCount int64 `json:"watchedCount"` // 当前用户已看集数
UnwatchedCount int64 `json:"unwatchedCount"` // 当前用户未看集数,按totalEpisode-watchedCount计算
LastChapterId int64 `json:"lastChapterId"` // 最近观看剧集ID,无观看进度时为0
LastEpisode int64 `json:"lastEpisode"` // 最近观看集数,无观看进度时为0
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
// PlayletCollectListResp 我的收藏列表响应
type PlayletCollectListResp struct {
TotalCount int64 `json:"totalCount"` // 总收藏数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []PlayletCollectData `json:"list"` // 收藏短剧集合
}
// PlayletBoughtListReq 我的已购短剧列表请求
type PlayletBoughtListReq struct {
// 普通分页参数,pageNum默认1,pageSize默认10、最大100
pubdef.Page
}
// PlayletBoughtData 我的已购短剧列表项
type PlayletBoughtData struct {
CommonData
BoughtChapterCount int64 `json:"boughtChapterCount"` // 已购剧集数量
CostCoins int64 `json:"costCoins"` // 已消耗金币
BoughtAt time.Time `json:"boughtAt"` // 最近购买时间
LastChapterId int64 `json:"lastChapterId"` // 最近观看剧集ID,无观看进度时为0
LastEpisode int64 `json:"lastEpisode"` // 最近观看集数,无观看进度时为0
WatchedCount int64 `json:"watchedCount"` // 当前用户已看集数
UnwatchedCount int64 `json:"unwatchedCount"` // 当前用户未看集数,按totalEpisode-watchedCount计算
IsFinished bool `json:"isFinished"` // 当前用户是否已看完
}
// PlayletBoughtListResp 我的已购短剧列表响应
type PlayletBoughtListResp struct {
TotalCount int64 `json:"totalCount"` // 总已购短剧数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []PlayletBoughtData `json:"list"` // 已购短剧集合
}
// PlayletHistoryListReq 观看历史列表请求
type PlayletHistoryListReq struct {
// 普通分页参数,pageNum默认1,pageSize默认20、最大100
pubdef.Page
}
// PlayletHistoryData 观看历史列表项
type PlayletHistoryData struct {
CommonData
LastChapterId int64 `json:"lastChapterId"` // 最近观看剧集ID
LastEpisode int64 `json:"lastEpisode"` // 最近观看集数
WatchedCount int64 `json:"watchedCount"` // 当前用户已看集数
UnwatchedCount int64 `json:"unwatchedCount"` // 当前用户未看集数
IsFinished bool `json:"isFinished"` // 是否已看完
HistoryAt string `json:"historyAt"` // 最近观看时间
}
// PlayletHistoryListResp 观看历史列表响应
type PlayletHistoryListResp struct {
TotalCount int64 `json:"totalCount"` // 总历史数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []PlayletHistoryData `json:"list"` // 观看历史集合
}
// PlayletHistoryDeleteReq 删除单条观看历史请求
type PlayletHistoryDeleteReq struct {
PlayletId int64 `json:"playletId" binding:"required"` // 短剧ID
}
// PlayletHistoryDeleteResp 删除单条观看历史响应
type PlayletHistoryDeleteResp struct {
DeletedCount int64 `json:"deletedCount"` // 删除记录数量
}
// PlayletHistoryClearResp 清空观看历史响应
type PlayletHistoryClearResp struct {
DeletedCount int64 `json:"deletedCount"` // 删除记录数量
}
// PlayletChapterLikeSetReq 短剧剧集点赞设置请求
type PlayletChapterLikeSetReq struct {
ChapterId int64 `json:"chapterId" binding:"required"` // 短剧剧集ID
IsLike *bool `json:"isLike" binding:"required"` // 是否点赞,true-点赞,false-取消点赞
}
// PlayletChapterLikeSetResp 短剧剧集点赞设置响应
type PlayletChapterLikeSetResp struct {
ChapterId int64 `json:"chapterId"` // 短剧剧集ID
IsLike int64 `json:"isLike"` // 点赞状态 1-已点赞 2-未点赞
CountLike int64 `json:"countLike"` // 短剧剧集点赞数
}
// PlayletChapterCollectSetReq 短剧剧集收藏设置请求
type PlayletChapterCollectSetReq struct {
ChapterId int64 `json:"chapterId" binding:"required"` // 短剧剧集ID
IsCollect *bool `json:"isCollect" binding:"required"` // 是否收藏,true-收藏,false-取消收藏
}
// PlayletChapterCollectSetResp 短剧剧集收藏设置响应
type PlayletChapterCollectSetResp struct {
ChapterId int64 `json:"chapterId"` // 短剧剧集ID
IsCollect int64 `json:"isCollect"` // 收藏状态 1-已收藏 2-未收藏
CountCollect int64 `json:"countCollect"` // 短剧剧集收藏数
}
// PlayletChapterCollectListReq 我的剧集收藏列表请求
type PlayletChapterCollectListReq struct {
// 普通分页参数,pageNum默认1,pageSize默认10、最大100
pubdef.Page
}
// PlayletChapterCollectData 我的剧集收藏列表项
type PlayletChapterCollectData struct {
PlayletId int64 `json:"playletId"` // 短剧ID
PlayletTitle string `json:"playletTitle"` // 短剧标题
PlayletCover string `json:"playletCover"` // 短剧封面,已拼接图片域名
TotalEpisode int64 `json:"totalEpisode"` // 短剧总集数
UpdateStatus int `json:"updateStatus"` // 更新状态 1-连载中 2-已完结
ChapterId int64 `json:"chapterId"` // 短剧剧集ID
CurrentEpisode int64 `json:"currentEpisode"` // 第几集
ChapterTitle string `json:"chapterTitle"` // 剧集标题
VideoUrl string `json:"videoUrl"` // 播放地址
MediaTime int64 `json:"mediaTime"` // 影片长度(秒)
PayType int32 `json:"payType"` // 支付方式 0-免费 1-金币 2-VIP
SingleCoins int64 `json:"singleCoins"` // 单集金币
CountBrowse int64 `json:"countBrowse"` // 剧集观看数
CountCollect int64 `json:"countCollect"` // 剧集收藏数
IsCollect int64 `json:"isCollect"` // 收藏状态,收藏列表固定返回1-已收藏
CollectedAt time.Time `json:"collectedAt"` // 收藏时间
}
// PlayletChapterCollectListResp 我的剧集收藏列表响应
type PlayletChapterCollectListResp struct {
TotalCount int64 `json:"totalCount"` // 总收藏数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []PlayletChapterCollectData `json:"list"` // 收藏剧集集合
}
// PlayletChapterWatchReportReq 短剧剧集观看上报请求
type PlayletChapterWatchReportReq struct {
PlayletId int64 `json:"playletId"` // 短剧ID,传入时用于校验剧集归属
ChapterId int64 `json:"chapterId" binding:"required"` // 短剧剧集ID
}
// PlayletChapterWatchReportResp 短剧剧集观看上报响应
type PlayletChapterWatchReportResp struct {
PlayletId int64 `json:"playletId"` // 短剧ID
ChapterId int64 `json:"chapterId"` // 短剧剧集ID
CurrentEpisode int64 `json:"currentEpisode"` // 当前集数
WatchedCount int64 `json:"watchedCount"` // 当前用户已看集数
UnwatchedCount int64 `json:"unwatchedCount"` // 当前用户未看集数
LastChapterId int64 `json:"lastChapterId"` // 最近观看剧集ID
LastEpisode int64 `json:"lastEpisode"` // 最近观看集数
}
// PlayletInfoReq 详情请求
type PlayletInfoReq struct {
Id int64 `form:"id" json:"id"` // 短剧id
Slug string `form:"slug" json:"slug"` // 短剧slug,非空时优先按slug解析短剧ID
}
// PlayletChapterInfoReq 短剧剧集详情请求
type PlayletChapterInfoReq struct {
PlayletId int64 `form:"playletId" json:"playletId"` // 短剧ID,传入时用于校验剧集归属
PlayletSlug string `form:"playletSlug" json:"playletSlug"` // 短剧slug,非空时优先按slug解析短剧ID
ChapterId int64 `form:"chapterId" json:"chapterId" binding:"required"` // 短剧剧集ID
}
// PlayletChapterListReq 短剧剧集列表请求
type PlayletChapterListReq struct {
PlayletId int64 `form:"playletId" json:"playletId"` // 短剧ID
PlayletSlug string `form:"playletSlug" json:"playletSlug"` // 短剧slug,非空时优先按slug解析短剧ID
}
// PlayletChapterListResp 短剧剧集列表响应
type PlayletChapterListResp struct {
PlayletId int64 `json:"playletId"` // 短剧ID
List []PlayletChapterData `json:"list"` // 短剧剧集集合
}
// PlayletChapterInfoResp 短剧剧集详情响应
type PlayletChapterInfoResp struct {
Id int64 `json:"id"` // 短剧剧集ID
PlayletId int64 `json:"playletId"` // 短剧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"` // 影片长度(秒)
CountComment int64 `json:"countComment"` // 短剧剧集评论数
CountBrowse int64 `json:"countBrowse"` // 短剧剧集观看数
CountCollect int64 `json:"countCollect"` // 短剧剧集收藏数
CountLike int64 `json:"countLike"` // 短剧剧集点赞数
IsLike int64 `json:"isLike"` // 点赞状态 1-已点赞 2-未点赞
IsCollect int64 `json:"isCollect"` // 收藏状态 1-已收藏 2-未收藏
PayType int32 `json:"payType"` // 支付方式 0-免费 1-金币 2-VIP
SingleCoins int64 `json:"singleCoins"` // 单集金币(支付方式为1-金币时候生效)
CanWatch bool `json:"canWatch"` // 是否可观看
NeedUnlock bool `json:"needUnlock"` // 是否需要金币解锁
NeedVip bool `json:"needVip"` // 是否需要开通VIP
CostCoins int64 `json:"costCoins"` // 本次解锁消耗金币
Balance int64 `json:"balance"` // 当前金币余额
VipValid bool `json:"vipValid"` // 当前用户VIP是否有效
IsUnlocked bool `json:"isUnlocked"` // 当前用户是否已解锁本集
// 页面SEO信息
SeoInfo *SeoInfo `json:"seoInfo,omitempty"`
}
// PlayletChapterUnlockReq 短剧剧集金币解锁请求
type PlayletChapterUnlockReq struct {
PlayletId int64 `json:"playletId" binding:"required"` // 短剧ID
ChapterId int64 `json:"chapterId" binding:"required"` // 短剧剧集ID
}
// PlayletChapterUnlockResp 短剧剧集金币解锁响应
type PlayletChapterUnlockResp struct {
PlayletId int64 `json:"playletId"` // 短剧ID
ChapterId int64 `json:"chapterId"` // 短剧剧集ID
Unlocked bool `json:"unlocked"` // 是否已解锁
CanWatch bool `json:"canWatch"` // 是否可观看
Balance int64 `json:"balance"` // 当前金币余额
CostCoins int64 `json:"costCoins"` // 本次解锁消耗金币
ChangeCoin int64 `json:"changeCoin"` // 本次实际扣减金币,幂等命中时为0
}
// PlayletInfoResp 详情响应
type PlayletInfoResp struct {
CommonData
// 是否点赞(1-已点赞,2-未点赞)
IsLike int64 `json:"isLike"`
// 是否收藏(1-已收藏,2-未收藏)
IsCollect int64 `json:"isCollect"`
// 短剧章节集合
PlayletChapterInfo []PlayletChapterData `json:"playletChapterInfo"`
// 页面SEO信息
SeoInfo *SeoInfo `json:"seoInfo,omitempty"`
// 广告
Advitise AdvitiseData `json:"advitise"`
}
// PlayletChapterData 短剧章节信息
type PlayletChapterData struct {
Id int64 `json:"id"` // 短剧剧集ID
PlayletId int64 `json:"playletId"` // 短剧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 int32 `json:"payType"` // 支付方式 0-免费 1-金币 2-VIP
SingleCoins int64 `json:"singleCoins"` // 单集金币(支付方式为1-金币时候生效)
CanWatch bool `json:"canWatch"` // 是否可观看
NeedUnlock bool `json:"needUnlock"` // 是否需要金币解锁
NeedVip bool `json:"needVip"` // 是否需要开通VIP
CostCoins int64 `json:"costCoins"` // 本次解锁消耗金币
Balance int64 `json:"balance"` // 当前金币余额
VipValid bool `json:"vipValid"` // 当前用户VIP是否有效
IsUnlocked bool `json:"isUnlocked"` // 当前用户是否已解锁本集
}
+102
View File
@@ -0,0 +1,102 @@
package proto
import "videoweb/pub/pubdef"
// PlayletTopicPageListReq 专题剧单分页请求
type PlayletTopicPageListReq struct {
pubdef.Page // 专题分页参数
}
// PlayletTopicGroupPageItem 专题区块分页数据
type PlayletTopicGroupPageItem struct {
Id int64 `json:"id"` // 专题区块ID
Name string `json:"name"` // 专题区块名称
Desc string `json:"desc"` // 专题区块描述
Rank int64 `json:"rank"` // 区块排序,越大越靠前
TotalCount int64 `json:"totalCount"` // 区块下专题总数
List []*PlayletTopicPageItem `json:"list"` // 当前页专题
}
// PlayletTopicPageListResp 专题剧单分页响应
type PlayletTopicPageListResp struct {
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []*PlayletTopicGroupPageItem `json:"list"` // 专题区块集合
SeoInfo *SeoInfo `json:"seoInfo,omitempty"` // 页面SEO信息
}
// PlayletTopicPageItem 专题剧单分页项
type PlayletTopicPageItem struct {
Id int64 `json:"id"` // 专题ID
Name string `json:"name"` // 专题名称
Slug string `json:"slug"` // slug
Desc string `json:"desc"` // 描述
Icon string `json:"icon"` // 图标
Rank int64 `json:"rank"` // 排序,越大越靠前
PlayletCount int64 `json:"playletCount"` // 专题列表为已上架总数,更多专题为预览数量
Covers []string `json:"covers,omitempty"` // 专题列表为一张短剧封面
List []*CommonData `json:"list,omitempty"` // 专题列表为一部短剧
SeoInfo *SeoInfo `json:"seoInfo"` // 专题SEO
}
// PlayletTopicDetailReq 专题详情请求
type PlayletTopicDetailReq struct {
pubdef.Page
Id int64 `form:"id" json:"id"` // 专题ID
TopicSlug string `form:"topicSlug" json:"topicSlug"`
DataType int64 `form:"dataType" json:"dataType"` // 仅支持 1 短剧
SortType int64 `form:"sortType" json:"sortType"` // 排序 1-编辑排序 2-最新 3-最热
}
// PlayletTopicDetailResp 专题详情响应
type PlayletTopicDetailResp struct {
Id int64 `json:"id"` // 专题ID
DataType int64 `json:"dataType"`
Name string `json:"name"` // 专题名称
Slug string `json:"slug"` // slug
Desc string `json:"desc"` // 描述
Icon string `json:"icon"` // 图标
Rank int64 `json:"rank"` // 排序,越大越靠前
PlayletCount int64 `json:"playletCount"` // 当前页 list 中的短剧数量
Covers []string `json:"covers"` // 顶部封面集合
TotalCount int64 `json:"totalCount"` // 短剧总数
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []CommonData `json:"list"` // 专题短剧列表
MoreTopics []*PlayletTopicPageItem `json:"moreTopics"` // 更多专题
SeoInfo *SeoInfo `json:"seoInfo"` // 专题SEO
Advitise AdvitiseData `json:"advitise"`
}
// PlayletThemeListResponse app端题材列表响应
type PlayletThemeListResponse struct {
List []*PlayletThemeItem `json:"list"` // 题材列表
}
// PlayletThemeItem app端题材列表项
type PlayletThemeItem struct {
Id int64 `json:"id"` // 题材ID
Name string `json:"name"` // 题材名称
Slug string `json:"slug"` // slug
Icon string `json:"icon"` // 题材图标,已拼接图片域名
Rank int64 `json:"rank"` // 排序,越大越靠前
Status bool `json:"status"` // 上架状态
IsRecommend bool `json:"isRecommend"` // 是否推荐
PlayletCount int64 `json:"playletCount"` // 该题材绑定的上架短剧数量
SeoInfo *SeoInfo `json:"seoInfo"` // 题材对应页面 SEO 信息
}
// PlayletTagListResponse app端短剧标签列表响应
type PlayletTagListResponse struct {
List []*PlayletTagItem `json:"list"` // 标签列表
}
// PlayletTagItem app端短剧标签列表项
type PlayletTagItem struct {
Id int64 `json:"id"` // 标签ID
Name string `json:"name"` // 标签名称
Slug string `json:"slug"` // slug
Rank int64 `json:"rank"` // 排序,越大越靠前
Status bool `json:"status"` // 上架状态
SeoInfo *SeoInfo `json:"seoInfo"` // 标签对应页面 SEO 信息
}
+32
View File
@@ -0,0 +1,32 @@
package proto
import "videoweb/pub/models/rechargepackagemod"
// PayMethodInfo 单个支付方式
type PayMethodInfo struct {
Type string `json:"type"` // alipay / wechat / union
TypeName string `json:"typeName"` // 支付宝 / 微信 / 银联
}
// RechargePackageItem App购买套餐列表项
type RechargePackageItem struct {
Id int64 `json:"id"` // 套餐ID
PackageType rechargepackagemod.PackageType `json:"packageType"` // 套餐类型:1-会员畅享 2-金币充值
Name string `json:"name"` // 展示标题
SubTitle string `json:"subTitle"` // 展示副标题
Price int64 `json:"price"` // 售价,单位分
OriginalPrice int64 `json:"originalPrice"` // 原价,单位分
DurationDays int64 `json:"durationDays"` // 会员有效天数
DurationHours int64 `json:"durationHours"` // 会员有效小时数,由durationDays计算
BaseCoin int64 `json:"baseCoin"` // 基础金币数
GiftCoin int64 `json:"giftCoin"` // 赠送金币数
TotalCoin int64 `json:"totalCoin"` // 到账总金币数,由baseCoin+giftCoin计算
Sort int32 `json:"sort"` // 排序,越小越靠前
PayMethods []PayMethodInfo `json:"payMethods"` // 该套餐支持的支付方式
}
// RechargePackageListResp App购买套餐列表响应。
type RechargePackageListResp struct {
VipList []*RechargePackageItem `json:"vipList"` // 会员畅享列表
CoinList []*RechargePackageItem `json:"coinList"` // 金币充值列表
}
+29
View File
@@ -0,0 +1,29 @@
package proto
import "videoweb/pub/pubdef"
type RichTextInfo struct {
Id int64 `json:"id" bson:"_id,omitempty"`
Title string `json:"title" bson:"title"` // 标题
Content string `json:"content" bson:"content"` // 内容
Desc string `json:"desc" bson:"desc"` // 标题(app)
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
}
// AppRichTextItemResp APP富文本内容列表项
type AppRichTextItemResp struct {
// 富文本ID
Id int64 `json:"id"`
// 标题
Title string `json:"title"`
// 内容
Content string `json:"content"`
// 标题(app)
Desc string `json:"desc"`
}
// AppRichTextListResp APP富文本内容列表响应
type AppRichTextListResp struct {
// 富文本内容列表
List []AppRichTextItemResp `json:"list"`
}
+85
View File
@@ -0,0 +1,85 @@
package proto
import "time"
type SearchSortType string
const (
SearchSortTypeDefault SearchSortType = "default" // 默认 相似度
SearchSortTypeHot SearchSortType = "hot" // 热度排序
SearchSortTypeNew SearchSortType = "new" // 最新排序
)
// RankType 排行榜类型
type RankType int64
const (
RankType_Video = 1 // 视频
RankType_Actress = 2 // 女优
RankType_Filmreview = 3 // 影评
)
// RankPeriod 排行榜周期
type RankPeriod int64
const (
RankPeriod_Week RankPeriod = 1
RankPeriod_Month RankPeriod = 2
RankPeriod_Year RankPeriod = 3
)
type SearchRankHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
VideoWeek SearchRankData `json:"videoWeek"`
ActressWeek SearchRankData `json:"actressWeek"`
FilmreviewWeek SearchRankData `json:"filmreviewWeek"`
VideoMonth SearchRankData `json:"videoMonth"`
ActressMonth SearchRankData `json:"actressMonth"`
FilmreviewMonth SearchRankData `json:"filmreviewMonth"`
VideoYear SearchRankData `json:"videoYear"`
ActressYear SearchRankData `json:"actressYear"`
FilmreviewYear SearchRankData `json:"filmreviewYear"`
}
type SearchRankData struct {
RankName string `json:"rankName" form:"rankName"` // 排行榜名字
RankType RankType `json:"rankType" form:"rankType"` // 排行榜类型 1视频, 2女优 ,3影评
RankPeriod RankPeriod `json:"rankPeriod" form:"rankPeriod"` // 排行榜周期 1=周 2=月 3=年
List []HotSearchItem `json:"list" form:"list"`
}
type HotSearchItem struct {
Id int64 `json:"id" form:"id"` // ID
Title string `json:"title" form:"title"` //标题
HotValue int64 `json:"hotValue" form:"hotValue"` // 热度值
Images string `json:"images" form:"images"` // 封面
Works int64 `json:"works" bson:"works,omitempty"` // 作品数量
Desc string `json:"desc" bson:"desc"` // 描述
AddedTime time.Time `json:"addedTime" bson:"addedTime"` // 上架shi时间
}
type SearchResp struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
InTitle string `json:"inTitle"` //输入标题
InType int64 `json:"inType"` // 输入类型 0=视频 1=女优 2=影评 3=帖子
PageNum int64 `json:"pageNum" form:"pageNum"`
PageSize int64 `json:"pageSize" form:"pageSize"`
TotalSize int64 `json:"totalSize" form:"totalSize"`
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
Sort []SearchSortItem `json:"sorts"` // 排序选项
SearchRecommend []string `json:"searchRecommend"` // 搜索推荐
Config ConfigInfo `json:"config" form:"config"` // 配置文件
}
type SearchSortItem struct {
Key string `json:"key"` // 值
Title string `json:"title"` // 标题
}
+15
View File
@@ -0,0 +1,15 @@
package proto
// SeoInfo 页面SEO信息,用于前端渲染 title、meta 和 canonical。
type SeoInfo struct {
// 页面标题
Title string `json:"title"`
// 页面关键词
Keywords []string `json:"keywords"`
// 页面描述
Description string `json:"description"`
// 网站名称
WebSiteName string `json:"webSiteName"`
// 当前内容的标准URL
CanonicalURL string `json:"canonicalUrl"`
}
+18
View File
@@ -0,0 +1,18 @@
package proto
import (
"encoding/xml"
"time"
)
type URL struct {
Loc string `xml:"loc"`
LastMod time.Time `xml:"lastmod"`
ChangeFreq string `xml:"changefreq"` // always/hourly/daily/weekly/monthly/yearly/never
Priority float32 `xml:"priority"` // 0.0 - 1.0
}
type Sitemap struct {
XMLName xml.Name `xml:"urlset"`
Xmlns string `xml:"xmlns,attr"`
URLs []URL `xml:"url"`
}
+25
View File
@@ -0,0 +1,25 @@
package proto
import "videoweb/pub/pubdef"
type AppTranslationInfo struct {
CategoryList []TranslationCategory `json:"categoryList" form:"categoryList"`
}
type TranslationCategory struct {
ID int64 `json:"id"`
Name string `json:"name" bson:"name"` // 名称
Icon string `json:"icon" bson:"icon"` // Icon
TranslationList []TranslationInfo `json:"translationList" form:"translationList"`
UrlValue string `json:"urlValue" bson:"urlValue"` // URl路径
CategoryType pubdef.TranslationType `json:"categoryType"` // 导航类型
SeoInfo pubdef.SeoValue `json:"seoInfo"` // Seo相关信息
}
type TranslationInfo struct {
ID int64 `json:"id"` // ID
Name string `json:"name" bson:"name"` // 名称
IsFriendAds bool `json:"isFriendAds"` // 是否是友链广告位
UrlValue string `json:"urlValue" bson:"urlValue"` // URl路径
TransCategoryId int64 `json:"-"` // 导航分类
}
+9
View File
@@ -0,0 +1,9 @@
package proto
// UserCenterDataResp app个人中心数据响应
type UserCenterDataResp struct {
WatchCount int64 `json:"watchCount"` // 观看数量
CollectCount int64 `json:"collectCount"` // 收藏数量
ChasingCount int64 `json:"chasingCount"` // 追剧中数量
BoughtChapterCount int64 `json:"boughtChapterCount"` // 已购剧集数量
}
+428
View File
@@ -0,0 +1,428 @@
package proto
import (
"time"
"videoweb/pub/common/netutil"
"videoweb/pub/common/utils"
"videoweb/pub/models/videoinformationmod"
"videoweb/pub/pubdef"
)
type TagsInfoData struct {
Id int64 `json:"id" `
Name string `json:"name"` // 帖子标题
Slug string `json:"slug"` // slug
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
Works int64 `json:"works" bson:"works,omitempty"` // 作品数量
Images string `json:"images" bson:"images,omitempty"` // 背景
}
type CollectionInfoData struct {
Id int64 `json:"id" `
Name string `json:"name"` // 帖子标题
}
type VideoType int64
const (
VideoTypeVideo VideoType = 0 // 视频(帖子)
VideoTypeCollection VideoType = 1 // 合集
VideoTypeAdvitise VideoType = 2 // 广告
VideoTypeVideoV2 VideoType = 3 // 视频
)
type VideoInfoData struct {
Id int64 `json:"id"`
Type VideoType `json:"type"` // 类型
Title string `json:"title"` // 帖子标题
Slug string `json:"slug"` // slug
Keyworld []string `json:"keyworld"` // 关键字
AddedTime time.Time `json:"addedTime"` // 帖子上架时间
CreatorId int64 `json:"creatorId"` // 作者Id
CreatorName string `json:"creatorName"` // 作者名称
CoverImg string `json:"coverImg"` // 封面
Nodes []videoinformationmod.Node `json:"nodes"` // 节点
Video videoinformationmod.VideoInfo `json:"video"` // 视频
Tags []TagsInfoData `json:"tags"` // 标签
IsHot bool `json:"isHot"` // 是否热门
AdvitiseId string `json:"advitiseId"` // 广告Id
Link string `json:"link"` // 跳转链接
Location int64 `json:"location" bson:"location"` // 位置id
CategoryIds []int64 `json:"categoryIds"` // 分类信息
Categorys []VideoCategoryInfo `json:"categorys"` // 分类信息
TopicIds []int64 `json:"topicIds"` // 专题信息
Topics []VideoTopicInfo `json:"topics"` // 专题信息
WatchTimes int64 `json:"watchTimes" bson:"watchTimes"` // 观看次数
ShowTimes int64 `json:"showTimes" bson:"showTimes"` // 展示次数
UpdatedAt time.Time `json:"updatedAt"` //更新时间
Desc string `bson:"desc,omitempty" json:"desc"` // 详细描述
Content string `json:"content"` // 富文本
ImgCdn string `json:"imgCdn" bson:"imgCdn"` // 图片CDN
PreviewVtt string `json:"previewVtt,omitempty"` // 雪碧图 vtt
}
type VideoHistoryInfo struct {
Id int64 `json:"id"`
Title string `json:"title"` // 帖子标题
AddedTime time.Time `json:"addedTime"` // 上架时间
}
type VideoCategoryInfo struct {
Id int64 `json:"id" `
Name string `json:"name"`
Slug string `json:"slug"` // slug
ContentType int64 `json:"contentType" bson:"contentType"` // 内容:0: 默认 1:首页 2:今日
SortType int64 `json:"sortType" bson:"sortType"` // 排序方式 0:上线时间 1:观看次数 2排序
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
Title string `json:"title" bson:"title"` // APP显示
Desc string `json:"desc" bson:"desc"` // 描述
}
// 面包屑
type BreadcrumbItem struct {
Name string `json:"name"` // 名称
Url string `json:"url"` // 跳转链接
}
// 详情页导航
type DetailNavItem struct {
Name string `json:"name"` // 导航名称
Url string `json:"url"` // 导航链接
}
type VideoPlayReq struct {
VideoId int64 `json:"videoId" form:"videoId"` // 视频ID
}
type VideoPlayResp struct {
AuthKey string `json:"authKey"`
}
type VideoCreaterInfo struct {
Id int64 `json:"id" `
Name string `json:"name"`
Slug string `json:"slug"` // slug
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
}
func VideoInfoToData(videoInfo *videoinformationmod.VideoInformation, imgCdn string) VideoInfoData {
t := VideoTypeVideo
switch videoInfo.MediaType {
case videoinformationmod.MediaType_Video:
t = VideoTypeVideo
case videoinformationmod.MediaType_Collection:
t = VideoTypeCollection
case videoinformationmod.MediaType_Advitise:
t = VideoTypeAdvitise
case videoinformationmod.MediaType_VideoV2:
t = VideoTypeVideoV2
}
videotemp := VideoInfoData{
Id: videoInfo.Id,
Type: t,
Title: videoInfo.Title,
Slug: videoInfo.Slug,
Keyworld: videoInfo.Keyworld,
AddedTime: videoInfo.AddedTime,
Desc: videoInfo.Desc,
UpdatedAt: videoInfo.PageUpdatedAt,
CreatorId: videoInfo.CreatorId,
TopicIds: videoInfo.TopicIds,
Topics: make([]VideoTopicInfo, 0),
CreatorName: videoInfo.CreatorName,
CoverImg: netutil.MergeURL(imgCdn, videoInfo.CoverImg),
Nodes: make([]videoinformationmod.Node, 0),
Video: videoInfo.Video,
IsHot: videoInfo.IsHot,
CategoryIds: videoInfo.CategoryIds,
Categorys: make([]VideoCategoryInfo, 0),
Tags: make([]TagsInfoData, 0),
ShowTimes: videoInfo.Real.ShowTimes,
WatchTimes: videoInfo.Real.WatchTimes,
Content: videoInfo.Content,
ImgCdn: imgCdn,
PreviewVtt: videoInfo.PreviewVtt,
}
ti := time.Date(2020, 1, 1, 0, 0, 0, 0, utils.LocBJ)
if videotemp.UpdatedAt.Before(ti) {
videotemp.UpdatedAt = videoInfo.UpdatedAt
}
for _, nodeInfo := range videoInfo.Nodes {
nodeTmp := videoinformationmod.Node{
Images: make([]string, 0),
Url: nodeInfo.Url,
Text: nodeInfo.Text,
Videos: nodeInfo.Videos,
Title: nodeInfo.Title,
}
for _, image := range nodeInfo.Images {
nodeTmp.Images = append(nodeTmp.Images, netutil.MergeURL(imgCdn, image))
}
videotemp.Nodes = append(videotemp.Nodes, nodeTmp)
}
return videotemp
}
// StripH265Url 清空主视频与 nodes 内视频的 H265 地址。
func StripH265Url(data *VideoInfoData) {
if data == nil {
return
}
data.Video.H265Url = ""
for i := range data.Nodes {
for j := range data.Nodes[i].Videos {
data.Nodes[i].Videos[j].H265Url = ""
}
}
}
// VideoReq 普通分页查询视频请求
type VideoReq struct {
// 普通分页参数,pageNum默认1,pageSize默认10、最大100
pubdef.Page
}
// VideoAllListReq 视频分页列表请求
type VideoAllListReq struct {
pubdef.Page
MediaType int64 `form:"mediaType" json:"mediaType"` // 类型 0-全部 1-影集 2-动画
TopicId int64 `form:"topicId" json:"topicId"` // 题材ID,对应video_topic
TopicSlug string `form:"topicSlug" json:"topicSlug"` // 题材slug,非空时优先按slug解析题材ID
SortType int64 `form:"sortType" json:"sortType"` // 排序 1-最新 2-最热 3-收藏最多
}
// VideoItemResp 查询视频列表项
type VideoItemResp struct {
// id
Id int64 `json:"id"`
// slug
Slug string `json:"slug"`
// 标题
Title string `json:"title"`
// 上架时间
AddedTime time.Time `json:"addedTime"`
// 作者Id
CreatorId int64 `json:"creatorId"`
// 作者名称
CreatorName string `json:"creatorName"`
// 封面
CoverImg string `json:"coverImg"`
// 关键字
Keyworld []string `json:"keyworld"`
// 标签
Tags []int64 `json:"tags"`
// 观看数(真假之和)
WatchTimes int64 `json:"watchTimes"`
// 影片长度
VideoTime int32 `json:"videoTime"`
}
// VideoLikeSetReq 视频点赞设置请求
type VideoLikeSetReq struct {
Id int64 `json:"id" binding:"required"` // 视频ID
IsLike *bool `json:"isLike" binding:"required"` // 是否点赞,true-点赞,false-取消点赞
}
// VideoLikeSetResp 视频点赞设置响应
type VideoLikeSetResp struct {
Id int64 `json:"id"` // 视频ID
IsLike int64 `json:"isLike"` // 点赞状态 1-已点赞 2-未点赞
CountLike int64 `json:"countLike"` // 视频点赞数
}
// VideoCollectSetReq 视频收藏设置请求
type VideoCollectSetReq struct {
Id int64 `json:"id" binding:"required"` // 视频ID
IsCollect *bool `json:"isCollect" binding:"required"` // 是否收藏,true-收藏,false-取消收藏
}
// VideoCollectSetResp 视频收藏设置响应
type VideoCollectSetResp struct {
Id int64 `json:"id"` // 视频ID
IsCollect int64 `json:"isCollect"` // 收藏状态 1-已收藏 2-未收藏
CountCollect int64 `json:"countCollect"` // 视频收藏数
}
// VideoHistoryListReq 视频观看历史列表请求
type VideoHistoryListReq struct {
// 普通分页参数,pageNum默认1,pageSize默认10、最大100
pubdef.Page
}
// VideoHistoryData 视频观看历史列表项
type VideoHistoryData struct {
Id int64 `json:"id"` // 视频ID
Slug string `json:"slug"` // slug
Title string `json:"title"` // 标题
CoverImg string `json:"coverImg"` // 封面
Keyworld []string `json:"keyworld"` // 关键字
Tags []int64 `json:"tags"` // 标签
WatchTimes int64 `json:"watchTimes"` // 观看数
VideoTime int32 `json:"videoTime"` // 影片长度
CountLike int64 `json:"countLike"` // 点赞数
CountCollect int64 `json:"countCollect"` // 收藏数
CountComment int64 `json:"countComment"` // 评论数
IsCollect int64 `json:"isCollect"` // 收藏状态 1-已收藏 2-未收藏
HistoryAt time.Time `json:"historyAt"` // 最近观看时间
}
// VideoHistoryListResp 视频观看历史列表响应
type VideoHistoryListResp struct {
TotalCount int64 `json:"totalCount"` // 总历史数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []VideoHistoryData `json:"list"` // 观看历史集合
}
// VideoHistoryDeleteReq 删除单条视频观看历史请求
type VideoHistoryDeleteReq struct {
VideoId int64 `json:"videoId" binding:"required"` // 视频ID
}
// VideoHistoryDeleteResp 删除单条视频观看历史响应
type VideoHistoryDeleteResp struct {
DeletedCount int64 `json:"deletedCount"` // 删除记录数量
}
// VideoHistoryClearResp 清空视频观看历史响应
type VideoHistoryClearResp struct {
DeletedCount int64 `json:"deletedCount"` // 删除记录数量
}
// VideoCollectListReq 视频收藏列表请求
type VideoCollectListReq struct {
// 普通分页参数,pageNum默认1,pageSize默认10、最大100
pubdef.Page
}
// VideoCollectData 视频收藏列表项
type VideoCollectData struct {
Id int64 `json:"id"` // 视频ID
Slug string `json:"slug"` // slug
Title string `json:"title"` // 标题
CoverImg string `json:"coverImg"` // 封面
Keyworld []string `json:"keyworld"` // 关键字
Tags []int64 `json:"tags"` // 标签
WatchTimes int64 `json:"watchTimes"` // 观看数
VideoTime int32 `json:"videoTime"` // 影片长度
CountLike int64 `json:"countLike"` // 点赞数
CountCollect int64 `json:"countCollect"` // 收藏数
CountComment int64 `json:"countComment"` // 评论数
IsCollect int64 `json:"isCollect"` // 收藏状态,收藏列表固定返回1-已收藏
CollectedAt time.Time `json:"collectedAt"` // 收藏时间
}
// VideoCollectListResp 视频收藏列表响应
type VideoCollectListResp struct {
TotalCount int64 `json:"totalCount"` // 总收藏数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []VideoCollectData `json:"list"` // 收藏视频集合
}
// VideoAllListItemResp 视频分页列表项
type VideoAllListItemResp struct {
Id int64 `json:"id"` // id
Slug string `json:"slug"` // slug
Title string `json:"title"` // 标题
MediaType int64 `json:"mediaType"` // 类型 1-影集 2-动画
AddedTime time.Time `json:"addedTime"` // 上架时间
CreatorId int64 `json:"creatorId"` // 作者Id
CreatorName string `json:"creatorName"` // 作者名称
CoverImg string `json:"coverImg"` // 封面
Keyworld []string `json:"keyworld"` // 关键字
Tags []int64 `json:"tags"` // 标签
TopicIds []int64 `json:"topicIds"` // 题材ID集合
TopicNames []string `json:"topicNames"` // 题材名称集合
Topics []VideoTopicInfo `json:"topics"` // 题材集合
WatchTimes int64 `json:"watchTimes"` // 观看数
VideoTime int32 `json:"videoTime"` // 影片长度
VideoCount int64 `json:"videoCount"` // 视频数量
}
// VideoResp 普通分页查询视频响应
type VideoResp struct {
// 总共数量
TotalCount int64 `json:"totalCount"`
// 每页数
PageSize int `json:"pageSize"`
// 页数
PageNum int `json:"pageNum"`
// 视频列表
List []*VideoItemResp `json:"list"`
}
// VideoAllListResp 视频分页列表响应
type VideoAllListResp struct {
TotalCount int64 `json:"totalCount"` // 总共数量
PageSize int `json:"pageSize"` // 每页数
PageNum int `json:"pageNum"` // 页数
List []*VideoAllListItemResp `json:"list"` // 视频集合
Advitise AdvitiseData `json:"advitise"` // 广告
SeoInfo *SeoInfo `json:"seoInfo,omitempty"` // 页面SEO信息
}
// VideoInfoReq 查询视频详情请求
type VideoInfoReq struct {
Id int64 `json:"id" form:"id"` // 视频id
Slug string `json:"slug" form:"slug"` // 视频slug,非空时优先按slug解析视频ID
}
// VideoInfoResp 查询视频详情响应
type VideoInfoResp struct {
// id
Id int64 `json:"id"`
// slug
Slug string `json:"slug"`
// 标题
Title string `json:"title"`
// 封面
CoverImg string `json:"coverImg"`
// 关键字
Keyworld []string `json:"keyworld"`
// 标签
Tags []int64 `json:"tags"`
// 标签名称
TagsName []string `json:"tagsName"`
// 题材ID集合
TopicIds []int64 `json:"topicIds"`
// 题材集合
Topics []VideoTopicInfo `json:"topics"`
// 观看数(真假之和)
WatchTimes int64 `json:"watchTimes"`
// 点赞数
CountLike int64 `json:"countLike"`
// 收藏数
CountCollect int64 `json:"countCollect"`
// 评论数
CountComment int64 `json:"countComment"`
// 当前用户点赞状态 1-已点赞 2-未点赞
IsLike int64 `json:"isLike"`
// 当前用户收藏状态 1-已收藏 2-未收藏
IsCollect int64 `json:"isCollect"`
// 视频
Video VideoData `json:"video"`
// 广告
Advitise AdvitiseData `json:"advitise"`
// 页面SEO信息
SeoInfo *SeoInfo `json:"seoInfo,omitempty"`
}
type VideoData struct {
// 视频ID(视频才会存在)
TaskId string `json:"taskId"`
// 媒资库ID
FileId string `json:"fileId"`
// 视频URl
Url string `json:"url"`
// 视频封面
Cover string `json:"cover"`
// 分辨率高(视频才会存在)
Height int64 `json:"height"`
// 分辨率宽(视频才会存在)
Width int64 `json:"width"`
// 影片长度
VideoTime int32 `json:"videoTime"`
// 预览MP4文件
PreMp4FileNameFs string `json:"preMp4FileNameFs"`
// 不加密的预览MP4
UnencryptedPreMp4 string `json:"unencryptedPreMp4"`
}
+27
View File
@@ -0,0 +1,27 @@
package proto
import (
"videoweb/pub/pubdef"
)
// VideoTopicListReq 视频题材列表请求
type VideoTopicListReq struct {
MediaType int64 `form:"mediaType" json:"mediaType"` // 类型 0-全部 1-影集 2-动画
}
// VideoTopicListResp 视频题材列表响应
type VideoTopicListResp struct {
List []VideoTopicInfo `json:"list"` // 题材集合
}
type VideoTopicInfo struct {
Id int64 `json:"id" bson:"_id,omitempty"` // Id
Name string `json:"name" bson:"name"` // 专题名称
Slug string `json:"slug" bson:"slug"` // slug
Title string `json:"title" bson:"title"` // APP显示
Desc string `json:"desc" bson:"desc"` // 描述
Image string `json:"image" bson:"image"` // 背景
VideoCategoryId int64 `json:"videoCategoryId" bson:"videoCategoryId"` // 视频分类id
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
Works int64 `json:"works" bson:"works"` // 作品数
}
+215
View File
@@ -0,0 +1,215 @@
package proto
import (
"videoweb/pub/pubdef"
)
// HomeHtmlData 首页
type HomeHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"` // 请求路径
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
}
type VideoCategoryData struct {
Id int64 `json:"id" form:"id"`
Name string `json:"name" form:"name"`
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"`
TopicList []VideoTopicData `json:"topicList" form:"topicList"` // 专题列表
}
type VideoTopicData struct {
Id int64 `json:"id" form:"id"`
Name string `json:"name" form:"name"`
Image string `json:"image" form:"image"`
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
Words int64 `json:"words" form:"words"`
ShowType int64 `json:"showType" bson:"showType"` // 展示类型 0=默认 1=横版左右滑动 2=竖版左右滑动
TopicType int64 `json:"topicType" bson:"topicType"` // 专题类型 0视频专题 1绑定专题 2绑定标签 3=绑定女优 4=随便看
LinkUrl string `json:"linkUrl" bson:"linkUrl"` // 跳转URL
}
type VideoCategoryHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
VideoCategory VideoCategoryData `json:"videoCategory" form:"videoCategory"` // 当前分类数据
}
type VideoTopicHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
PageNum int64 `json:"pageNum" form:"pageNum"`
PageSize int64 `json:"pageSize" form:"pageSize"`
TotalSize int64 `json:"totalSize" form:"totalSize"`
VideoInfos []VideoInfoData `json:"videoInfos" form:"videoInfos"` // 视频列表
}
type CategoryVideoListHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
Translation TranslationInfo `json:"translation" form:"translation"` // 当前导航数据
CategoryList []VideoCategoryData `json:"categoryList" form:"categoryList"`
}
type VideoCategoryListHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
Translation TranslationInfo `json:"translation" form:"translation"` // 当前导航数据
PageNum int64 `json:"pageNum" form:"pageNum"`
PageSize int64 `json:"pageSize" form:"pageSize"`
TotalSize int64 `json:"totalSize" form:"totalSize"`
}
type VideoDetailsHtmlData struct {
Path string `json:"path"`
Video VideoInfoData `json:"video" form:"video"` // 视频详情
Breadcrumbs []BreadcrumbItem `json:"breadcrumbs" form:"breadcrumbs"` // 面包屑
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
CommentList GetCommentListResp `json:"commentList" form:"commentList"` // 评论
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜标签
}
type PostDetailsHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
CommentList GetCommentListResp `json:"commentList" form:"commentList"` // 评论
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜标签
CreateInfo PostCreateInfo `json:"createInfo" form:"createInfo"` // 作者信息
}
type PostCreateInfo struct {
Id int64 `json:"id" form:"id"`
Name string `json:"name" form:"name"`
Image string `json:"image" form:"image"` //头像
Works int64 `json:"works" form:"works"`
CreateType int64 `json:"createType"` // 创作者类型 0=普通 1=官方
Desc string `json:"desc" form:"desc"` // 作者描述
Background string `json:"background"` // 背景
}
// TagHtmlData 首页
type TagHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
PageNum int64 `json:"pageNum" form:"pageNum"`
PageSize int64 `json:"pageSize" form:"pageSize"`
TotalSize int64 `json:"totalSize" form:"totalSize"`
}
type VideoTagHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
PageNum int64 `json:"pageNum" form:"pageNum"`
PageSize int64 `json:"pageSize" form:"pageSize"`
TotalSize int64 `json:"totalSize" form:"totalSize"`
}
type VideoTagCategoryHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
AllCategory []VideoTagCategoryData `json:"allCategory" form:"allCategory"` //所有分类
}
type VideoTagCategoryData struct {
Id int64 `json:"id" form:"id"`
Name string `json:"name" form:"name"`
SeoInfo pubdef.SeoValue `json:"seoInfo" form:"seoInfo"`
Image string `json:"image" form:"image"`
TotalTags int64 `json:"totalTags" form:"totalTags"` // 总标签数量
}
type VideoTagCategoryInfoData struct {
PageNum int64 `json:"pageNum" form:"pageNum"`
PageSize int64 `json:"pageSize" form:"pageSize"`
TotalSize int64 `json:"totalSize" form:"totalSize"`
}
type VideoHistoryHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
PageNum int64 `json:"pageNum" form:"pageNum"`
PageSize int64 `json:"pageSize" form:"pageSize"`
TotalSize int64 `json:"totalSize" form:"totalSize"`
}
type RichTextHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
RichTextInfo RichTextInfo `json:"richTextInfo" form:"richTextInfo"` // 富文本
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
}
type NotFoundHtmlData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
RichTextInfo RichTextInfo `json:"richTextInfo" form:"richTextInfo"` // 富文本
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
}
type UrlRedirectData struct {
Path string `json:"path"`
CompletePath string `json:"completePath" form:"completePath"`
Translations AppTranslationInfo `json:"translations" form:"translations"` // 导航
BottonTranslations AppTranslationInfo `json:"bottonTranslations" form:"bottonTranslations"` // 底部导航
Config ConfigInfo `json:"config" form:"config"` // 配置文件
Advitise AdvitiseData `json:"advitise" form:"advitise"` // 广告
HotSearch []*HotSearchItem `json:"hotSearch" form:"hotSearch"` // 热搜
UrlRedirect string `json:"urlRedirect" form:"urlRedirect"`
}
type ContactUsReq struct {
Name string `json:"name" form:"name"` // 姓名
Email string `json:"email" form:"email"` // 邮件
Content string `json:"content" form:"content"` // 内容
CategoryName string `json:"categoryName" form:"categoryName"` // 主旨分类
}
+88
View File
@@ -0,0 +1,88 @@
package rechargeapi
import (
"videoweb/app/service/rechargeser"
"videoweb/pub/common"
"videoweb/pub/common/enum/consts"
"videoweb/pub/common/ipaddr"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
type submitOrderReq struct {
PackageId int64 `json:"packageId" binding:"required"` // 购买套餐ID(会员畅享)
PayMode string `json:"payMode" binding:"required"` // 支付方式:alipay/wechat
SourcePageKey string `json:"sourcePageKey"` // 下单来源页面标识
SourcePageName string `json:"sourcePageName"` // 下单来源页面名称
}
// SubmitOrder 发起第三方支付下单
// @Tags 充值
// @Summary 创建 VIP 充值订单(第三方支付)
// @Accept json
// @Produce json
// @Param param body submitOrderReq true "下单参数"
// @Success 200 {object} rechargeser.SubmitOrderResp "支付链接"
// @Security ApiKeyAuth
// @Router /api/app/vip/pay [POST]
func SubmitOrder(ctx *gin.Context) {
var req submitOrderReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
userId := common.GetUserId(ctx)
sysType := ctx.GetString(consts.CtxSysType)
devType := ctx.GetString(consts.CtxDevType)
ip := ipaddr.ResolveClientIP(ctx)
user, serr := rechargeser.GetUserInfo(ctx, userId)
if serr != nil || user == nil {
common.ServerJSON(ctx, srvdef.ErrUserNotExsit, nil)
return
}
deviceID := rechargeser.PayDeviceID(ctx.GetString(consts.CtxDevId), user.DevID, user.DevV2)
resp, serr := rechargeser.CreateOrder(ctx, userId, user.NickName, req.PackageId, req.PayMode, sysType, devType, deviceID, ip, user.DistrictCode, req.SourcePageKey, req.SourcePageName)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
type orderHistoryReq struct {
Page int64 `json:"page" form:"page"`
PageSize int64 `json:"pageSize" form:"pageSize"`
}
// GetOrderHistory 查询当前用户 VIP 订单历史
// @Tags 充值
// @Summary 查询 VIP 充值记录
// @Accept json
// @Produce json
// @Param page query int false "页码(默认1)"
// @Param pageSize query int false "每页数量(默认10)"
// @Success 200 {array} vipordermod.VipOrder "订单列表"
// @Security ApiKeyAuth
// @Router /api/app/vip/orders [GET]
func GetOrderHistory(ctx *gin.Context) {
var req orderHistoryReq
_ = ctx.ShouldBindQuery(&req)
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 10
}
userId := common.GetUserId(ctx)
list, total, serr := rechargeser.GetOrderHistory(ctx, userId, req.Page, req.PageSize)
if serr != nil {
common.ServerJSON(ctx, serr.Code, serr.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, gin.H{"total": total, "list": list})
}
+25
View File
@@ -0,0 +1,25 @@
package rechargepackageapi
import (
"videoweb/app/service/rechargepackageser"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// List 查询购买套餐列表
// @Tags 金币与会员
// @Summary 查询购买套餐列表 -- by 王鸣
// @Description 返回会员畅享和金币充值两个列表,并附带各套餐可用支付方式
// @Produce json
// @Success 200 {object} proto.RechargePackageListResp "成功"
// @Router /api/app/recharge/package/list [GET]
func List(ctx *gin.Context) {
resp, err := rechargepackageser.GetRechargePackageList(ctx)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
+437
View File
@@ -0,0 +1,437 @@
package statcenterapi
import (
"context"
"fmt"
"math"
"net/http"
"strconv"
"videoweb/pub/common"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"videoweb/pub/common/statcenter"
"videoweb/pub/models/cointransmod"
"videoweb/pub/models/usermod"
"videoweb/pub/models/uservisitlog"
"videoweb/pub/models/vipordermod"
"videoweb/pub/pubdef"
"github.com/gin-gonic/gin"
"github.com/shopspring/decimal"
"go.mongodb.org/mongo-driver/bson"
)
// @Tags 数据同步
// @Summary 统计中心增量同步
// @Description 按 job 拉取注册/日活/充值/绑定/消费/售卡等增量数据
// @Accept json
// @Produce json
// @Param param body statcenter.StatcenterSyncReq true "参数"
// @Success 200 {object} statcenter.StatcenterSyncResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/statcenter/sync [POST]
func StatcenterSyncList(ctx *gin.Context) {
var request statcenter.StatcenterSyncReq
if err := ctx.ShouldBind(&request); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, err.Error())
return
}
var resp statcenter.StatcenterSyncResp
resp.Job = request.Job
resp.Code = 200
appId := statcenter.STAT_APPID
var err error
switch request.Job {
case string(statcenter.USER_ACCE):
resp.AccessList, err = UserAccessList(appId, request, true)
case string(statcenter.USER_REG):
resp.RegisterList, err = UserRegisterList(appId, request, true)
case string(statcenter.USER_BINDING):
resp.BindingList, err = UserBindingList(appId, request)
case string(statcenter.USER_INVITE):
resp.InviteList, err = UserInviteList(appId, request)
case string(statcenter.ConsumeRecordJob):
resp.ConsumeList, err = ConsumeRecordList(appId, request)
case string(statcenter.USER_RECH):
resp.RechargeList, err = UserRechargeList(appId, request, true)
case string(statcenter.USER_RECH_ALL):
resp.AllRechargeList, err = UserAllRechargeList(appId, request, true)
case string(statcenter.CardSellJob):
resp.CardSellList, err = CardSellList(appId, request)
case string(statcenter.AI_SELL_JOB):
resp.AiSellList, err = AiSellList(appId, request)
case string(statcenter.VipJob):
resp.VipList, err = UserSyncVipList(appId, request)
case string(statcenter.RechargeAll): // 兼容旧任务名
resp.RechargeList, err = UserAllRechargeList(appId, request, true)
default:
resp.Code = 501
resp.Msg = "job is error"
ctx.JSON(http.StatusOK, resp)
return
}
if err != nil {
resp.Code = 502
resp.Msg = err.Error()
}
ctx.JSON(http.StatusOK, resp)
}
// UserAccessList 日活数据同步
func UserAccessList(appId int32, request statcenter.StatcenterSyncReq, isNewStat bool) (accessList []statcenter.UserVisitMsg, err error) {
platformId := request.PlatformId
if platformId == "" {
platformId = "000000000000000000000000"
}
visitList, err := uservisitlog.AccessSyncById(context.Background(), platformId, request.MaxSize)
if err != nil {
log.Error("UserAccessList AccessSyncById", log.E(err))
return nil, err
}
accessList = make([]statcenter.UserVisitMsg, 0, len(visitList))
userIds := make([]int64, 0, len(visitList))
for _, visitInfo := range visitList {
userIds = append(userIds, visitInfo.UserId)
}
userList, _ := usermod.FindManyUser(context.Background(), bson.M{usermod.FN.User.Id: bson.M{"$in": userIds}})
userMap := make(map[int64]*usermod.User, len(userList))
for _, u := range userList {
userMap[u.Id] = u
}
for _, visitInfo := range visitList {
sType, dType := visitInfo.SysType, visitInfo.DevType
if appId == statcenter.STAT_APPID && isNewStat {
sType, dType = pubdef.GetCenterType(pubdef.SysTypeFromString(visitInfo.SysType), visitInfo.DevType)
}
accessInfo := statcenter.UserVisitMsg{
UserId: uint64(visitInfo.UserId),
AppId: appId,
SysType: sType,
DevType: dType,
IP: visitInfo.IP,
Version: visitInfo.Version,
DevID: visitInfo.DevID,
VisitAt: visitInfo.VisitAt,
PlatformId: visitInfo.Id.Hex(),
}
if userInfo, ok := userMap[visitInfo.UserId]; ok {
accessInfo.IsDirect = userInfo.IsDirect
accessInfo.DistrictCode = userInfo.DistrictCode
accessInfo.RegisterTime = userInfo.CreatedAt
}
accessList = append(accessList, accessInfo)
}
return
}
// UserRegisterList 注册数据同步
func UserRegisterList(appId int32, request statcenter.StatcenterSyncReq, isNewStat bool) (registerList []statcenter.UserRegisterMsg, err error) {
var userList usermod.UserList
if appId == statcenter.STAT_APPID && isNewStat {
if request.UserId > math.MaxInt64 {
return nil, fmt.Errorf("invalid register cursor userId: %d", request.UserId)
}
userList, err = usermod.StatcenterSyncListByUserID(context.Background(), int64(request.UserId), request.MaxSize)
} else {
userList, err = usermod.StatcenterSyncList(context.Background(), request.SuccessTime, request.MaxSize)
}
if err != nil {
log.Error("UserRegisterList", log.E(err))
return nil, err
}
registerList = make([]statcenter.UserRegisterMsg, 0, len(userList))
for _, userInfo := range userList {
if userInfo.Device == "robot" {
continue
}
isNativeIOS := pubdef.SysTypeFromString(userInfo.SysType) == pubdef.ST_IOS
districtCode := userInfo.DistrictCode
if isNativeIOS && statcenter.IOSRegistrationDistrictCode != "" {
districtCode = statcenter.IOSRegistrationDistrictCode
}
sType, dType := userInfo.SysType, userInfo.Device
if appId == statcenter.STAT_APPID && isNewStat {
sType, dType = pubdef.GetCenterType(pubdef.SysTypeFromString(userInfo.SysType), userInfo.Device)
}
registerList = append(registerList, statcenter.UserRegisterMsg{
UserId: uint64(userInfo.Id),
AppId: appId,
SysType: sType,
DevType: dType,
Mobile: userInfo.Email,
Name: userInfo.NickName,
IP: userInfo.RegIp,
IsDirect: userInfo.IsDirect,
DistrictCode: districtCode,
PromSeqe: userInfo.AgentInviteCode,
PromCode: userInfo.InviteCode,
RegisterTime: userInfo.CreatedAt,
})
}
return
}
// UserBindingList 绑定数据同步(本项目:正式注册并绑定邮箱)
func UserBindingList(appId int32, request statcenter.StatcenterSyncReq) ([]statcenter.UserBindingMsg, error) {
userList, err := usermod.StatcenterSyncBindUserList(context.Background(), request.SuccessTime, request.MaxSize)
if err != nil {
log.Error("UserBindingList", log.E(err))
return nil, err
}
list := make([]statcenter.UserBindingMsg, 0, len(userList))
for _, userInfo := range userList {
sType, dType := pubdef.GetCenterType(pubdef.SysTypeFromString(userInfo.SysType), userInfo.Device)
bindAt := userInfo.UpdatedAt
list = append(list, statcenter.UserBindingMsg{
UserId: uint64(userInfo.Id),
AppId: appId,
PlatformId: fmt.Sprintf("%d", userInfo.Id),
SysType: sType,
DevType: dType,
Mobile: userInfo.Email,
BindingTime: &bindAt,
})
}
return list, nil
}
// UserInviteList 邀请绑定同步
func UserInviteList(appId int32, request statcenter.StatcenterSyncReq) ([]statcenter.UserInviteBindMsg, error) {
userList, err := usermod.StatcenterSyncInviteList(context.Background(), request.SuccessTime, request.MaxSize)
if err != nil {
log.Error("UserInviteList", log.E(err))
return nil, err
}
list := make([]statcenter.UserInviteBindMsg, 0, len(userList))
for _, userInfo := range userList {
list = append(list, statcenter.UserInviteBindMsg{
UserId: uint64(userInfo.Id),
AppId: appId,
ParentPromCode: userInfo.AgentInviteCode,
InviteTime: userInfo.CreatedAt,
})
}
return list, nil
}
// ConsumeRecordList 金币消费流水同步
func ConsumeRecordList(appId int32, request statcenter.StatcenterSyncReq) ([]statcenter.ConsumeRecordMsg, error) {
startId := int64(0)
if request.PlatformId != "" {
id, err := strconv.ParseInt(request.PlatformId, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid consume cursor platformId: %s", request.PlatformId)
}
startId = id
}
transList, err := cointransmod.StatSyncConsumeList(context.Background(), startId, request.MaxSize)
if err != nil {
log.Error("ConsumeRecordList", log.E(err))
return nil, err
}
list := make([]statcenter.ConsumeRecordMsg, 0, len(transList))
for _, item := range transList {
consumeType := statcenter.StatValueAddSer
if item.TranType == cointransmod.TranTypeVideoUnlock {
consumeType = statcenter.StatVideoUnlock
}
list = append(list, statcenter.ConsumeRecordMsg{
AppID: appId,
UID: uint64(item.UserId),
Type: consumeType,
CurrencyType: statcenter.CurrencyTypeGold,
Money: decimal.Zero,
Amount: decimal.NewFromInt(item.Amount),
Uniq: strconv.FormatInt(item.Id, 10),
CreatedAt: item.CreatedAt,
})
}
return list, nil
}
// UserRechargeList 成功充值订单同步(会员+金币)
func UserRechargeList(appId int32, request statcenter.StatcenterSyncReq, isNewStat bool) (registerList []statcenter.UserRechargeMsg, err error) {
orderList, err := vipordermod.StatSyncSuccessOrderList(context.Background(), request.SuccessTime, request.MaxSize)
if err != nil {
log.Error("UserRechargeList StatSyncSuccessOrderList", log.E(err))
return nil, err
}
userMap := findUserDistrictMap(orderList)
registerList = make([]statcenter.UserRechargeMsg, 0, len(orderList))
for _, order := range orderList {
sType, dType := order.SysType, ""
if appId == statcenter.STAT_APPID && isNewStat {
sType, dType = pubdef.GetCenterType(pubdef.SysTypeFromString(order.SysType), "")
}
msg := statcenter.UserRechargeMsg{
UserId: uint64(order.UserId),
AppId: appId,
SysType: sType,
DevType: dType,
PlatformId: fmt.Sprintf("%d", order.Id),
ChannelName: order.PayChannel,
CID: order.Oid,
Type: order.PayMode,
OrderId: order.TradeNo,
OID: order.Oid,
Money: order.Amount,
PayMoney: order.Amount,
Status: statcenter.MapOrderStatusToStat(order.Status),
Rate: order.PayRate,
SuccessAt: order.FinishedAt,
CreatedAt: order.CreatedAt,
}
fillRechargeDistrict(&msg, userMap)
if order.OrderType == vipordermod.OrderTypeCoin {
msg.ChanShareMod = 1
} else {
msg.ChanShareMod = 2
}
registerList = append(registerList, msg)
}
return
}
// UserAllRechargeList 全部非失败充值订单同步
func UserAllRechargeList(appId int32, request statcenter.StatcenterSyncReq, isNewStat bool) (registerList []statcenter.UserRechargeMsg, err error) {
orderList, err := vipordermod.StatSyncAllOrderList(context.Background(), request.SuccessTime, request.MaxSize)
if err != nil {
log.Error("UserAllRechargeList StatSyncAllOrderList", log.E(err))
return nil, err
}
userMap := findUserDistrictMap(orderList)
registerList = make([]statcenter.UserRechargeMsg, 0, len(orderList))
for _, order := range orderList {
sType, dType := order.SysType, ""
if appId == statcenter.STAT_APPID && isNewStat {
sType, dType = pubdef.GetCenterType(pubdef.SysTypeFromString(order.SysType), "")
}
msg := statcenter.UserRechargeMsg{
UserId: uint64(order.UserId),
AppId: appId,
SysType: sType,
DevType: dType,
PlatformId: fmt.Sprintf("%d", order.Id),
ChannelName: order.PayChannel,
CID: order.Oid,
Type: order.PayMode,
OrderId: order.TradeNo,
OID: order.Oid,
Money: order.Amount,
PayMoney: order.Amount,
Status: statcenter.MapOrderStatusToStat(order.Status),
Rate: order.PayRate,
CreatedAt: order.CreatedAt,
SuccessAt: order.CreatedAt,
}
fillRechargeDistrict(&msg, userMap)
registerList = append(registerList, msg)
}
return
}
// CardSellList 会员卡销售流水同步(成功会员订单)
func CardSellList(appId int32, request statcenter.StatcenterSyncReq) ([]statcenter.CardSellMsg, error) {
orderList, err := vipordermod.StatSyncVipOrderList(context.Background(), request.SuccessTime, request.MaxSize)
if err != nil {
log.Error("CardSellList", log.E(err))
return nil, err
}
list := make([]statcenter.CardSellMsg, 0, len(orderList))
for _, order := range orderList {
sType, _ := pubdef.GetCenterType(pubdef.SysTypeFromString(order.SysType), "")
list = append(list, statcenter.CardSellMsg{
AppID: appId,
UID: uint64(order.UserId),
UniqID: fmt.Sprintf("%d", order.Id),
Amount: order.Amount,
TranTypeInt: int64(order.OrderType),
TranType: "会员卡",
SysType: sType,
CurrencyType: statcenter.CurrencyTypeCash,
TranCreatedAt: order.FinishedAt,
Product: statcenter.Product{
ID: fmt.Sprintf("%d", order.CardId),
Name: order.CardName,
DiscountedPrice: order.Amount,
},
})
}
return list, nil
}
// AiSellList AI 销售流水(本项目无 AI 业务,返回空列表)
func AiSellList(appId int32, request statcenter.StatcenterSyncReq) ([]statcenter.AiSellMsg, error) {
return make([]statcenter.AiSellMsg, 0), nil
}
// UserSyncVipList VIP 购买成功订单同步
func UserSyncVipList(appId int32, request statcenter.StatcenterSyncReq) (registerList []statcenter.UserBuyVIPMsg, err error) {
orderList, err := vipordermod.StatSyncVipOrderList(context.Background(), request.SuccessTime, request.MaxSize)
if err != nil {
log.Error("UserSyncVipList StatSyncVipOrderList", log.E(err))
return nil, err
}
userMap := findUserDistrictMap(orderList)
registerList = make([]statcenter.UserBuyVIPMsg, 0, len(orderList))
for _, order := range orderList {
msg := statcenter.UserBuyVIPMsg{
UID: uint64(order.UserId),
AppId: appId,
PlatformId: fmt.Sprintf("%d", order.Id),
Name: order.CardName,
Money: order.Amount,
BuyVIPType: statcenter.BuyVIPTypeMoney,
OID: order.Oid,
DeviceType: order.SysType,
Status: 3,
SuccessAt: order.FinishedAt,
}
if userInfo, ok := userMap[order.UserId]; ok {
msg.IsDirect = userInfo.IsDirect
msg.DistrictCode = userInfo.DistrictCode
}
registerList = append(registerList, msg)
}
return
}
func findUserDistrictMap(orderList vipordermod.VipOrderList) map[int64]*usermod.User {
userIds := make([]int64, 0, len(orderList))
seen := make(map[int64]struct{}, len(orderList))
for _, order := range orderList {
if order == nil || order.UserId <= 0 {
continue
}
if _, ok := seen[order.UserId]; ok {
continue
}
seen[order.UserId] = struct{}{}
userIds = append(userIds, order.UserId)
}
userMap := make(map[int64]*usermod.User, len(userIds))
if len(userIds) == 0 {
return userMap
}
userList, _ := usermod.FindManyUser(context.Background(), bson.M{usermod.FN.User.Id: bson.M{"$in": userIds}})
for _, u := range userList {
userMap[u.Id] = u
}
return userMap
}
func fillRechargeDistrict(msg *statcenter.UserRechargeMsg, userMap map[int64]*usermod.User) {
if msg == nil {
return
}
userInfo, ok := userMap[int64(msg.UserId)]
if !ok || userInfo == nil {
return
}
msg.DistrictCode = userInfo.DistrictCode
msg.RegisterTime = userInfo.CreatedAt
}
+22
View File
@@ -0,0 +1,22 @@
package translationapi
import (
"videoweb/app/service/translationser"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// CategoryList app端导航分类列表
// @Tags APP导航相关接口
// @Summary app端导航分类列表 --by 王鸣
// @Description 无请求参数,不分页,返回启用的顶部导航分类
// @Accept json
// @Produce json
// @Success 200 {object} proto.AppTranslationInfo "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/translation/category/list [get]
func CategoryList(ctx *gin.Context) {
common.ServerJSON(ctx, srvdef.Success, translationser.GetTranslationData())
}
+49
View File
@@ -0,0 +1,49 @@
package uploadapi
import (
"net/http"
"videoweb/app/service/uploadser"
"videoweb/pub/common"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// UploadImage 上传图片
// @Tags 上传
// @Summary 图片上传
// @Description 将图片转发至存储服务 /media/web/autopublish/image
// @Accept multipart/form-data
// @Produce json
// @Param file formData file true "图片文件"
// @Param watermark formData string false "是否加水印:1加,其他情况不加(头像不加)"
// @Success 200 {object} uploadser.ImageUploadResp "成功"
// @Failure 400 {string} string "参数错误"
// @Router /api/app/upload/image [post]
func UploadImage(ctx *gin.Context) {
f, err := ctx.FormFile("file")
if err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, "file 不能为空")
return
}
watermark := int64(0)
if ctx.PostForm("watermark") == "1" {
watermark = 1
}
param := &uploadser.ImageParam{
FileHeader: f,
Watermark: watermark,
}
respBytes, err := uploadser.ForwardImage(param)
if err != nil {
log.Error("UploadImage forward failed", log.E(err))
common.ServerJSON(ctx, srvdef.ServerError, nil)
return
}
ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBytes)
}
+31
View File
@@ -0,0 +1,31 @@
package usercenterapi
import (
"videoweb/app/api/proto"
"videoweb/app/service/usercenterser"
"videoweb/pub/common"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// Data app个人中心数据
// @Tags app个人中心相关接口
// @Summary app个人中心数据 --by 王鸣
// @Description 返回当前用户观看、收藏、追剧中、已购剧集统计
// @Accept json
// @Produce json
// @Success 200 {object} proto.UserCenterDataResp "成功"
// @Failure 400 {string} string "失败"
// @Security ApiKeyAuth
// @Router /api/app/user/center/data [get]
func Data(ctx *gin.Context) {
resp, err := usercenterser.Data(ctx, common.GetUserId(ctx))
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
var _ = proto.UserCenterDataResp{}
+246
View File
@@ -0,0 +1,246 @@
package videoapi
import (
"videoweb/app/api/proto"
"videoweb/app/service/videoser"
"videoweb/pub/common"
"videoweb/pub/common/ipaddr"
"videoweb/pub/common/srvdef"
"github.com/gin-gonic/gin"
)
// AllList app端分页查询视频列表
// @Tags 视频相关接口
// @Summary app端分页查询视频列表 --by 王鸣
// @Description 分页查询已上架视频,支持类型、题材和排序筛选
// @Accept json
// @Produce json
// @Param params query proto.VideoAllListReq true "app端分页查询视频列表请求"
// @Success 200 {object} proto.VideoAllListResp{list=[]proto.VideoAllListItemResp} "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/video/all/list [get]
func AllList(ctx *gin.Context) {
var req proto.VideoAllListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := videoser.VideoAllList(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// TopicList app端查询视频题材列表
// @Tags 视频相关接口
// @Summary app端查询视频题材列表 --by 王鸣
// @Description 查询已上架视频题材列表,mediaType=0全部 1影集 2动画
// @Accept json
// @Produce json
// @Param params query proto.VideoTopicListReq true "app端查询视频题材列表请求"
// @Success 200 {object} proto.VideoTopicListResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/video/topic/list [get]
func TopicList(ctx *gin.Context) {
var req proto.VideoTopicListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := videoser.VideoTopicList(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// List 普通分页查询视频
// @Tags 视频相关接口
// @Summary 普通分页查询视频 --by 旺鸣
// @Description 按上架时间倒序普通分页查询已上架视频
// @Accept json
// @Produce json
// @Param params query proto.VideoReq true "普通分页查询视频请求"
// @Success 200 {object} proto.VideoResp{list=[]proto.VideoItemResp} "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/video/list [get]
func List(ctx *gin.Context) {
var req proto.VideoReq
if err := ctx.ShouldBind(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := videoser.VideoList(ctx, &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// SetLike app端视频点赞/取消点赞
// @Tags 视频相关接口
// @Summary app端视频点赞/取消点赞 --by 王鸣
// @Description 设置当前用户视频点赞状态,点赞数只在状态真实变化时增减
// @Accept json
// @Produce json
// @Param param body proto.VideoLikeSetReq true "视频点赞设置请求"
// @Success 200 {object} proto.VideoLikeSetResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/video/like/set [post]
func SetLike(ctx *gin.Context) {
var req proto.VideoLikeSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := videoser.SetLike(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// SetCollect app端视频收藏/取消收藏
// @Tags 视频相关接口
// @Summary app端视频收藏/取消收藏 --by 王鸣
// @Description 设置当前用户视频收藏状态,收藏数只在状态真实变化时增减
// @Accept json
// @Produce json
// @Param param body proto.VideoCollectSetReq true "视频收藏设置请求"
// @Success 200 {object} proto.VideoCollectSetResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/video/collect/set [post]
func SetCollect(ctx *gin.Context) {
var req proto.VideoCollectSetReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := videoser.SetCollect(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// HistoryList app端我的视频观看历史列表
// @Tags 视频相关接口
// @Summary app端我的视频观看历史列表 --by 王鸣
// @Description 按当前用户最近观看时间倒序分页返回视频观看历史
// @Accept json
// @Produce json
// @Param params query proto.VideoHistoryListReq true "视频观看历史列表请求"
// @Success 200 {object} proto.VideoHistoryListResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/video/history/list [get]
func HistoryList(ctx *gin.Context) {
var req proto.VideoHistoryListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := videoser.HistoryList(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// DeleteHistory app端删除单条视频观看历史
// @Tags 视频相关接口
// @Summary app端删除单条视频观看历史 --by 王鸣
// @Description 删除当前用户指定视频观看历史,不影响收藏和点赞
// @Accept json
// @Produce json
// @Param param body proto.VideoHistoryDeleteReq true "删除单条视频观看历史请求"
// @Success 200 {object} proto.VideoHistoryDeleteResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/video/history/delete [post]
func DeleteHistory(ctx *gin.Context) {
var req proto.VideoHistoryDeleteReq
if err := ctx.ShouldBindJSON(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := videoser.DeleteHistory(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// ClearHistory app端清空我的视频观看历史
// @Tags 视频相关接口
// @Summary app端清空我的视频观看历史 --by 王鸣
// @Description 清空当前用户全部视频观看历史,不影响收藏和点赞
// @Accept json
// @Produce json
// @Success 200 {object} proto.VideoHistoryClearResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/video/history/clear [post]
func ClearHistory(ctx *gin.Context) {
resp, err := videoser.ClearHistory(ctx, common.GetUserId(ctx))
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// CollectList app端我的视频收藏列表
// @Tags 视频相关接口
// @Summary app端我的视频收藏列表 --by 王鸣
// @Description 按当前用户收藏时间倒序分页返回视频收藏列表
// @Accept json
// @Produce json
// @Param params query proto.VideoCollectListReq true "视频收藏列表请求"
// @Success 200 {object} proto.VideoCollectListResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/video/collect/list [get]
func CollectList(ctx *gin.Context) {
var req proto.VideoCollectListReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
resp, err := videoser.CollectList(ctx, common.GetUserId(ctx), &req)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}
// Detail 查询视频详情
// @Tags 视频相关接口
// @Summary 查询视频详情 --by 旺鸣
// @Description 查询已上架视频详情
// @Accept json
// @Produce json
// @Param params query proto.VideoInfoReq true "查询视频详情请求"
// @Success 200 {object} proto.VideoInfoResp "成功"
// @Failure 400 {string} string "失败"
// @Router /api/app/video/detail [get]
func Detail(ctx *gin.Context) {
var req proto.VideoInfoReq
if err := ctx.ShouldBindQuery(&req); err != nil {
common.ServerJSON(ctx, srvdef.ErrParamError, nil)
return
}
ua, _ := common.GetUA(ctx)
resp, err := videoser.VideoInfo(ctx, &req, common.GetUserId(ctx), ipaddr.ResolveClientIP(ctx), ua.UserAgent)
if err != nil {
common.ServerJSON(ctx, err.Code, err.Tips)
return
}
common.ServerJSON(ctx, srvdef.Success, resp)
}