Initial commit: web_hghl_server

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-10-26 16:28:14 +08:00
co-authored by Claude Opus 4.7
commit 65fca60622
653 changed files with 135901 additions and 0 deletions
+181
View File
@@ -0,0 +1,181 @@
package actress
import (
"context"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"videoweb/pub/mongos"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
// 表名
var db *mongos.Collection
func Init(ctx context.Context) {
// 获取数据库表
db = mongos.Shop.Coll(TN.Actress)
// 获取数据库表
indexes := []mongo.IndexModel{
{
Keys: bson.D{
{Key: FN.Actress.Status, Value: 1},
},
},
{
Keys: bson.D{
{Key: FN.Actress.Alias, Value: 1},
},
},
{
Keys: bson.D{
{Key: FN.Actress.CreatedAt, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.Actress.Status, Value: 1},
{Key: FN.Actress.Alias, Value: 1},
},
},
{
Keys: bson.D{
{Key: FN.Actress.Status, Value: 1},
{Key: FN.Actress.Rank, Value: 1},
},
},
{
Keys: bson.D{
{Key: FN.Actress.Status, Value: 1},
{Key: FN.Actress.UpdatedAt, Value: 1},
},
},
{
Keys: bson.D{
{Key: FN.Actress.Status, Value: 1},
{Key: FN.Actress.Works, Value: 1},
},
},
{
Keys: bson.D{
{Key: FN.Actress.Status, Value: 1},
{Key: FN.Actress.Works, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.Actress.Status, Value: 1},
{Key: FN.Actress.HotValue, Value: -1},
{Key: FN.Actress.Id, Value: -1},
},
},
{
Keys: bson.D{
{Key: FN.Actress.Status, Value: 1},
{Key: FN.Actress.Real.WeekWatchs, Value: 1},
},
},
{
Keys: bson.D{
{Key: FN.Actress.Status, Value: 1},
{Key: FN.Actress.Real.MonthWatchs, Value: 1},
},
},
{
Keys: bson.D{
{Key: FN.Actress.Status, Value: 1},
{Key: FN.Actress.Real.WatchTimes, Value: 1},
},
},
}
if _, err := db.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(channelmod:initActressIndex) Create Actress Index failed! err:%+v:", err))
}
}
// InsertOneActress 插入一个导航分类
func InsertOneActress(ctx context.Context, qa *Actress) *srvdef.SrvErr {
if _, err := db.InsertOne(ctx, qa); err != nil {
log.Warn("Actressmod:InsertOneActress db.InsertOne failed", log.E(err))
return srvdef.New(srvdef.ErrDbInsertError, "", "")
}
return nil
}
// DelOneActress 删除一个导航分类
func DelOneActress(ctx context.Context, filter bson.M) (
int64, *srvdef.SrvErr) {
count, err := db.DeleteOne(ctx, filter)
if err != nil {
log.Warn("Actressmod:DelOneActress db.DeleteOne failed",
log.E(err), log.Any("filter", filter))
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
}
return count, nil
}
// FindOneActress 查找一个导航分类
func FindOneActress(ctx context.Context, filter bson.M) (
*Actress, *srvdef.SrvErr) {
var Actress Actress
if err := db.FindOneEx(ctx, &Actress, filter); err != nil {
if err != mongo.ErrNoDocuments {
log.Warn("Actressmod:FindOneActress db.FindOne failed",
log.E(err), log.Any("filter", filter))
return nil, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return nil, srvdef.New(srvdef.ErrNoData, "", "")
}
return &Actress, nil
}
func FindManyActresss(ctx context.Context, filter bson.M, opts ...*options.FindOptions) (ActressList, *srvdef.SrvErr) {
data := make(ActressList, 0)
if err := db.Find(ctx, &data, filter, opts...); nil != err {
log.Warn("faq:FindManyActresss", log.E(err), log.Any("filter", filter))
return nil, srvdef.New(srvdef.ErrDbQuery.Code, "", "")
}
return data, nil
}
// CountActresss 统计导航分类数量
func CountActresss(ctx context.Context, filter bson.M) (
int64, *srvdef.SrvErr) {
count, err := db.Count(ctx, filter)
if err != nil {
log.Warn("faqmod:CountActresss db.Count failed",
log.E(err), log.Any("filter", filter))
return 0, srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return count, nil
}
// UpdateOneActress 更新一个导航分类
func UpdateOneActress(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
result, err := db.UpdateOne(ctx, filter, update)
if err != nil {
log.Warn("post:UpdateOneActress db.UpdateOne failed",
log.E(err), log.Any("filter", filter))
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
}
if result.MatchedCount != 1 {
log.Warn("post:UpdateOneActress db.UpdateOne failed",
log.E(err), log.Any("filter", filter))
return srvdef.New(srvdef.ErrNoData, "", "")
}
return nil
}
func UpdateManyActress(ctx context.Context, filter bson.M, update bson.M) *srvdef.SrvErr {
_, err := db.UpdateMany(ctx, filter, update)
if err != nil {
log.Warn("post:UpdateManyActress db.UpdateOne failed",
log.E(err), log.Any("filter", filter))
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
}
return nil
}
+96
View File
@@ -0,0 +1,96 @@
package actress
type TagActress struct {
Meas struct {
Gender string // Type: int , Desc: 性别 0:女 1:男 2:其他
Height string // Type: int , Desc: 身高 厘米
Weight string // Type: int , Desc: 体重 公斤
Bust string // Type: int , Desc: 胸围 英寸
Waist string // Type: int , Desc: 腰围 英寸
Hip string // Type: int , Desc: 臀围 英寸
Cup string // Type: int , Desc: 罩杯(A:1-G:9)1表示A,2表示B,3表示C,4表示D,5表示E,6表示F,7表示G,8表示H,9表示I
Len string // Type: int , Desc: 长度 毫米(前端可以显示为厘米,如45毫米,显示为14.5厘米,返回后端时,乘以10,保留整数,返回145)
Dia string // Type: int , Desc: 直径 毫米(前端可以显示为厘米,如45毫米,显示为4.5厘米,返回后端时,乘以10,保留整数,返回45)
Blood string // Type: string , Desc: 血型
}
Id string
Alias string
Slug string
Avatar string
Cover string
Desc string
TranslationCategoryId string
Office string
DebutDate string
BornDate string
Region string
Score string
Rank string
HotValue string
Status string
Works string
CreatedAt string
UpdatedAt string
RealUpdateAt string
SeoInfo string
IndexNow string
Real struct {
WatchTimes string
ShowTimes string
Comments string
Likes string
WeekWatchs string
MonthWatchs string
TodayWatchs string
}
}
var FN struct {
Actress TagActress
}
var TN struct {
Actress string
}
func init() {
FN.Actress.Id = "_id"
FN.Actress.UpdatedAt = "updatedAt"
FN.Actress.Works = "works"
FN.Actress.Status = "status"
FN.Actress.Rank = "rank"
FN.Actress.HotValue = "hotValue"
FN.Actress.Score = "score"
FN.Actress.Region = "region"
FN.Actress.BornDate = "bornDate"
FN.Actress.DebutDate = "debutDate"
FN.Actress.Office = "office"
FN.Actress.Meas.Gender = "meas.gender"
FN.Actress.Meas.Height = "meas.height"
FN.Actress.Meas.Weight = "meas.weight"
FN.Actress.Meas.Bust = "meas.bust"
FN.Actress.Meas.Waist = "meas.waist"
FN.Actress.Meas.Hip = "meas.hip"
FN.Actress.Meas.Cup = "meas.cup"
FN.Actress.Meas.Len = "meas.len"
FN.Actress.Meas.Dia = "meas.dia"
FN.Actress.Meas.Blood = "meas.blood"
FN.Actress.Desc = "desc"
FN.Actress.Cover = "cover"
FN.Actress.Avatar = "avatar"
FN.Actress.Alias = "alias"
FN.Actress.Slug = "slug"
FN.Actress.CreatedAt = "createdAt"
FN.Actress.UpdatedAt = "updatedAt"
FN.Actress.TranslationCategoryId = "translationCategoryId"
FN.Actress.Real.WatchTimes = "watchTimes"
FN.Actress.Real.ShowTimes = "showTimes"
FN.Actress.Real.Comments = "comments"
FN.Actress.Real.Likes = "likes"
FN.Actress.Real.WeekWatchs = "weekWatchs"
FN.Actress.Real.MonthWatchs = "monthWatchs"
FN.Actress.Real.TodayWatchs = "todayWatchs"
FN.Actress.SeoInfo = "seoInfo"
FN.Actress.IndexNow = "indexNow"
FN.Actress.RealUpdateAt = "realUpdateAt"
TN.Actress = "actress"
}
+172
View File
@@ -0,0 +1,172 @@
// @title:女优管理
package actress
import (
"fmt"
"regexp"
"strconv"
"strings"
"time"
"videoweb/pub/pubdef"
)
type Meas struct {
Gender int `bson:"gender" json:"gender"` // 性别 0:女 1:男 2:其他
Height int `bson:"height" json:"height"` // 身高 厘米
Weight int `bson:"weight" json:"weight"` // 体重 公斤
Bust int `bson:"bust" json:"bust"` // 胸围 英寸
Waist int `bson:"waist" json:"waist"` // 腰围 英寸
Hip int `bson:"hip" json:"hip"` // 臀围 英寸
Cup int `bson:"cup" json:"cup"` // 罩杯(A:1-G:9)1表示A,2表示B,3表示C,4表示D,5表示E,6表示F,7表示G,8表示H,9表示I
Len int `bson:"len" json:"len"` // 长度 毫米(前端可以显示为厘米,如145毫米,显示为14.5厘米,返回后端时,乘以10,保留整数,返回145)
Dia int `bson:"dia" json:"dia"` // 直径 毫米(前端可以显示为厘米,如45毫米,显示为4.5厘米,返回后端时,乘以10,保留整数,返回45)
Blood string `json:"blood" bson:"blood"` // 血型
}
func calculateCup(bust int, waist int) int {
// 计算胸围和腰围的差值
difference := bust - waist
// 根据差值大致判断罩杯
switch {
case difference < 5:
return 1 // A杯
case difference < 7:
return 2 // B杯
case difference < 9:
return 3 // C杯
case difference < 11:
return 4 // D杯
case difference < 13:
return 5 // E杯
case difference < 15:
return 6 // F杯
case difference < 17:
return 7 // G杯
case difference < 19:
return 8 // H杯
case difference < 21:
return 9 // I杯
default:
return 0
}
}
func (m *Meas) Parse(text string) {
text = strings.ReplaceAll(text, "长度", "尺寸")
text = strings.ReplaceAll(text, "長度", "尺寸")
text = strings.ReplaceAll(text, "厘米", "cm")
text = strings.ReplaceAll(text, "公分", "cm")
text = strings.ReplaceAll(text, "公斤", "kg")
text = strings.ReplaceAll(text, "體", "体")
text = strings.ReplaceAll(text, "圍", "围")
text = strings.ReplaceAll(text, "徑", "径")
// 将字母转换为对应的数字
cupMap := map[string]int{
"A": 1, "B": 2, "C": 3, "D": 4,
"E": 5, "F": 6, "G": 7, "H": 8, "I": 9,
"a": 1, "b": 2, "c": 3, "d": 4,
"e": 5, "f": 6, "g": 7, "h": 8, "i": 9,
}
// 身高提取cm
heightReg := regexp.MustCompile(`(?i)身高\s*(\d+)cm`)
if matches := heightReg.FindStringSubmatch(text); len(matches) > 1 {
m.Height, _ = strconv.Atoi(matches[1])
}
// 体重提取kg
weightReg := regexp.MustCompile(`(?i)体重\s*(\d+)kg`)
if matches := weightReg.FindStringSubmatch(text); len(matches) > 1 {
m.Weight, _ = strconv.Atoi(matches[1])
}
// 体重提取斤
weightReg = regexp.MustCompile(`(?i)体重\s*(\d+)斤`)
if matches := weightReg.FindStringSubmatch(text); len(matches) > 1 {
m.Weight, _ = strconv.Atoi(matches[1])
m.Weight = m.Weight / 2
}
// 胸围提取
bustReg := regexp.MustCompile(`胸围\s*(\d+)`)
if matches := bustReg.FindStringSubmatch(text); len(matches) > 1 {
m.Bust, _ = strconv.Atoi(matches[1])
}
// 三围单个数值提取
bustReg = regexp.MustCompile(`三围\s*(\d+)`)
if matches := bustReg.FindStringSubmatch(text); len(matches) > 1 {
m.Bust, _ = strconv.Atoi(matches[1])
}
// 罩杯提取
cupReg := regexp.MustCompile(`(?i)(\d+)([A-Z])`)
if matches := cupReg.FindStringSubmatch(text); len(matches) > 2 {
m.Cup = cupMap[matches[2]]
}
// 长度提取cm,支持浮点数
lengthReg := regexp.MustCompile(`(?i)尺寸\s*(\d+\.?\d*)cm`)
if matches := lengthReg.FindStringSubmatch(text); len(matches) > 1 {
value, _ := strconv.ParseFloat(matches[1], 64)
m.Len = int(value * 10) // 转换为mm
}
// 直径提取cm,支持浮点数
diaReg := regexp.MustCompile(`(?i)直径\s*(\d+\.?\d*)cm`)
if matches := diaReg.FindStringSubmatch(text); len(matches) > 1 {
value, _ := strconv.ParseFloat(matches[1], 64)
m.Len = int(value * 10) // 转换为mm
}
// 提取三围和罩杯
threeSizeReg := regexp.MustCompile(`(?i)三围\s*(\d+)([A-Z])/(\d+)/(\d+)`)
if matches := threeSizeReg.FindStringSubmatch(text); len(matches) > 1 {
m.Bust, _ = strconv.Atoi(matches[1])
m.Cup = cupMap[matches[2]]
m.Waist, _ = strconv.Atoi(matches[3])
m.Hip, _ = strconv.Atoi(matches[4])
}
}
func (m *Meas) convertCupToString(cup int) string {
if cup <= 0 {
cup = calculateCup(m.Bust, m.Waist)
}
if cup >= 1 && cup <= 9 {
letter := rune('A' + cup - 1)
return string(letter)
} else {
if m.Gender == 1 {
return "" // 男性默认返回空字符串
}
return "B" // 非男性默认返回B杯
}
}
func (m *Meas) Measurements() string {
//三围 格式为 35D-24-34 // 胸围(罩杯)-腰围-臀围
return fmt.Sprintf("%d%s-%d-%d", m.Bust, m.convertCupToString(m.Cup), m.Waist, m.Hip)
}
// @title:女优
// @table:actress
type Actress struct {
Id int64 `json:"id" bson:"_id"` // Id
Alias string `bson:"alias" json:"alias"` // 别名
Slug string `json:"slug" bson:"slug"` // slug
Avatar string `bson:"avatar" json:"avatar"` // 头像
Cover string `bson:"cover" json:"cover"` // 封面大图
Desc string `bson:"desc" json:"desc"` // 详细描述
TranslationCategoryId int64 `bson:"translationCategoryId" json:"translationCategoryId"` // 关联导航分类id
Meas Meas `bson:"meas" json:"meas"` // 三围
Office string `json:"office" bson:"office"` // 事务所
DebutDate time.Time `bson:"debutDate" json:"debutDate" ` // 出道日期
BornDate time.Time `bson:"bornDate" json:"bornDate"` // 出生日期
Region string `json:"region" bson:"region"` // 地区/国家
Score string `json:"score" bson:"score"` // 评分
Rank int64 `json:"rank" bson:"rank"` // 排序
HotValue int64 `json:"hotValue" bson:"hotValue"` // 热度值
Status bool `json:"status" bson:"status"` // 是否启用
Works int64 `json:"works" bson:"works"` // 作品数
Real pubdef.Flow `json:"real" bson:"real"` // 真实流量
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
RealUpdateAt time.Time `json:"realUpdateAt" bson:"realUpdateAt"` // 播放相关数据更新时间
SeoInfo pubdef.SeoValue `json:"seoInfo" bson:"seoInfo"` // Seo相关信息
IndexNow int64 `json:"indexNow" bson:"indexNow"` // 是否需要提交 0:代表提交 1:表示已提交 运营通过接口可以修改
}
type ActressList []*Actress