You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
539 lines
12 KiB
Go
539 lines
12 KiB
Go
package provider
|
|
|
|
import (
|
|
"context"
|
|
"joybuywork/internal/app"
|
|
"joybuywork/internal/consts"
|
|
"joybuywork/internal/consts/ckey"
|
|
"joybuywork/internal/plugins/jsonm"
|
|
"joybuywork/internal/repository/cache"
|
|
"joybuywork/internal/repository/dao"
|
|
"joybuywork/internal/repository/model"
|
|
"joybuywork/internal/repository/mtype"
|
|
"joybuywork/internal/repository/withdefault"
|
|
"joybuywork/internal/utils"
|
|
"joybuywork/internal/utils/logic"
|
|
"joybuywork/internal/utils/merr"
|
|
"joybuywork/internal/utils/verify"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"joybuywork/proto/go_proto/workerr"
|
|
|
|
"gits.branchcn.com/backend/microcode/plugins/derivative/lock"
|
|
"gorm.io/gorm/clause"
|
|
)
|
|
|
|
type FissionUserAttr struct {
|
|
logic.Context
|
|
|
|
user *model.FissionUser
|
|
|
|
attr map[string]*model.FissionUserAttr
|
|
}
|
|
|
|
func NewFissionUserAttr(ctx context.Context, user *model.FissionUser) *FissionUserAttr {
|
|
attr := &FissionUserAttr{
|
|
user: user,
|
|
}
|
|
|
|
attr.Init(ctx, dao.Q, merr.NewBE(ctx))
|
|
|
|
return attr
|
|
}
|
|
|
|
func (s *FissionUserAttr) GetAttr(mark string) (*model.FissionUserAttr, error) {
|
|
if s.attr != nil {
|
|
return s.attr[mark], nil
|
|
}
|
|
|
|
var attrMarks = []string{mtype.FissionUserAttrMarkPlatform, mtype.FissionUserAttrMarkLang, mtype.FissionUserAttrMarkUserLv}
|
|
s.attr = make(map[string]*model.FissionUserAttr, len(attrMarks))
|
|
for _, v := range attrMarks {
|
|
attr, err := cache.NewFissionUserAttr(s.Ctx).FindByUniqIdx(s.user.ID, v)
|
|
if err != nil {
|
|
return nil, s.BE().CacheError(err)
|
|
}
|
|
s.attr[v] = attr
|
|
}
|
|
|
|
return s.attr[mark], nil
|
|
}
|
|
|
|
func (s *FissionUserAttr) WithUser(platform, lang, levelMark, lvMarks, country, centerHashId, moduleId string, channelId int64) (err error) {
|
|
user := s.user
|
|
var attrs []*model.FissionUserAttr
|
|
if lang != "" {
|
|
attrs = append(attrs, withdefault.FissionUserAttr(&model.FissionUserAttr{
|
|
CampaignID: user.CampaignID,
|
|
UserID: user.ID,
|
|
Attr: mtype.FissionUserAttrMarkLang,
|
|
Value: user.LangMark,
|
|
Values: user.LangMark,
|
|
}))
|
|
}
|
|
|
|
if levelMark != "" {
|
|
setLv := strings.Split(lvMarks, ",")
|
|
attrs = append(attrs, withdefault.FissionUserAttr(&model.FissionUserAttr{
|
|
CampaignID: user.CampaignID,
|
|
UserID: user.ID,
|
|
Attr: mtype.FissionUserAttrMarkUserLv,
|
|
Value: utils.Ternary[string](verify.InArray(levelMark, setLv...), levelMark, setLv[0]),
|
|
Values: lvMarks,
|
|
}))
|
|
}
|
|
|
|
if country != "" {
|
|
attrs = append(attrs, withdefault.FissionUserAttr(&model.FissionUserAttr{
|
|
CampaignID: user.CampaignID,
|
|
UserID: user.ID,
|
|
Attr: mtype.FissionUserAttrMarkCountry,
|
|
Value: country,
|
|
Values: country,
|
|
}))
|
|
}
|
|
|
|
if platform != "" {
|
|
platform = utils.SupportPlatform(platform)
|
|
attrs = append(attrs, withdefault.FissionUserAttr(&model.FissionUserAttr{
|
|
CampaignID: user.CampaignID,
|
|
UserID: user.ID,
|
|
Attr: mtype.FissionUserAttrMarkPlatform,
|
|
Value: platform,
|
|
Values: platform,
|
|
}))
|
|
}
|
|
|
|
if channelId != 0 {
|
|
webChId := fmt.Sprint(channelId)
|
|
attrs = append(attrs, withdefault.FissionUserAttr(&model.FissionUserAttr{
|
|
CampaignID: user.CampaignID,
|
|
UserID: user.ID,
|
|
Attr: mtype.FissionUserAttrMarkWebChannel,
|
|
Value: webChId,
|
|
Values: webChId,
|
|
}))
|
|
}
|
|
|
|
if centerHashId != "" {
|
|
attrs = append(attrs, withdefault.FissionUserAttr(&model.FissionUserAttr{
|
|
CampaignID: user.CampaignID,
|
|
UserID: user.ID,
|
|
Attr: mtype.FissionUserAttrMarkCenter,
|
|
Value: centerHashId,
|
|
Values: centerHashId,
|
|
}))
|
|
}
|
|
|
|
if moduleId != "" {
|
|
attrs = append(attrs, withdefault.FissionUserAttr(&model.FissionUserAttr{
|
|
CampaignID: user.CampaignID,
|
|
UserID: user.ID,
|
|
Attr: mtype.FissionUserAttrMarkCenterModule,
|
|
Value: moduleId,
|
|
Values: moduleId,
|
|
}))
|
|
}
|
|
|
|
if len(attrs) == 0 {
|
|
return
|
|
}
|
|
|
|
return s.creates(attrs...)
|
|
}
|
|
|
|
// Platform 更新平台
|
|
func (s *FissionUserAttr) Platform(platform string) (err error) {
|
|
if platform == "" || s.ignore() {
|
|
return
|
|
}
|
|
|
|
// 用户关联的平台
|
|
platform = utils.SupportPlatform(platform)
|
|
pfAttr, err := s.firstOrCreate(mtype.FissionUserAttrMarkPlatform, platform, platform)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 如果没更新,或者平台是其他,就不用处理了
|
|
if platform == pfAttr.Value || platform == consts.PlatformOther {
|
|
return
|
|
}
|
|
|
|
return s.update(pfAttr, platform)
|
|
}
|
|
|
|
// WebChannel 更新站外渠道
|
|
func (s *FissionUserAttr) WebChannel(channelId int64) (err error) {
|
|
if channelId == 0 || s.ignore() {
|
|
return
|
|
}
|
|
|
|
webChId := fmt.Sprint(channelId)
|
|
|
|
wbcAttr, err := s.firstOrCreate(mtype.FissionUserAttrMarkWebChannel, webChId, webChId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 如果没更新,就不用处理了
|
|
if webChId == wbcAttr.Value {
|
|
return
|
|
}
|
|
|
|
return s.update(wbcAttr, webChId)
|
|
}
|
|
|
|
// Country 更新国家属性
|
|
func (s *FissionUserAttr) Country(country string) (err error) {
|
|
if country == "" || s.ignore() {
|
|
return
|
|
}
|
|
|
|
// 用户关联的国家
|
|
pfAttr, err := s.firstOrCreate(mtype.FissionUserAttrMarkCountry, country, country)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 如果没更新,或者平台是其他,就不用处理了
|
|
if country == pfAttr.Value {
|
|
return
|
|
}
|
|
|
|
return s.update(pfAttr, country)
|
|
}
|
|
|
|
// UserLv 更新用户等级
|
|
func (s *FissionUserAttr) UserLv(userLv string, setLv []string) (err error) {
|
|
if userLv == "" || s.ignore() {
|
|
return
|
|
}
|
|
|
|
// 用户关联的用户等级
|
|
attrVal := utils.Ternary[string](verify.InArray[string](userLv, setLv...), userLv, setLv[0])
|
|
values := strings.Join(setLv, ",")
|
|
pfAttr, err := s.firstOrCreate(mtype.FissionUserAttrMarkUserLv, attrVal, values)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 如果没更新,或者平台是其他,就不用处理了
|
|
if attrVal == pfAttr.Value && verify.AllInArray(setLv, pfAttr.GetValues()) {
|
|
return
|
|
}
|
|
|
|
return s.update(pfAttr, setLv...)
|
|
}
|
|
|
|
// Lang 更新语言
|
|
func (s *FissionUserAttr) Lang(lang string) (err error) {
|
|
if lang == "" || s.ignore() {
|
|
return
|
|
}
|
|
|
|
// 用户关联的语言
|
|
pfAttr, err := s.firstOrCreate(mtype.FissionUserAttrMarkLang, lang, lang)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 如果没更新,或者平台是其他,就不用处理了
|
|
if lang == pfAttr.Value {
|
|
return
|
|
}
|
|
|
|
return s.update(pfAttr, lang)
|
|
}
|
|
|
|
// Center 更新任务中心来源
|
|
func (s *FissionUserAttr) Center(centerHashId string) (err error) {
|
|
if centerHashId == "" || s.ignore() {
|
|
return
|
|
}
|
|
|
|
// 用户关联的任务中心
|
|
pfAttr, err := s.firstOrCreate(mtype.FissionUserAttrMarkCenter, centerHashId, centerHashId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 如果没更新,就不用处理了
|
|
if centerHashId == pfAttr.Value {
|
|
return
|
|
}
|
|
|
|
return s.update(pfAttr, centerHashId)
|
|
}
|
|
|
|
// CenterModule 更新任务中心模块来源
|
|
func (s *FissionUserAttr) CenterModule(moduleId string) (err error) {
|
|
if moduleId == "" || s.ignore() {
|
|
return
|
|
}
|
|
|
|
// 用户关联的任务中心模块
|
|
pfAttr, err := s.firstOrCreate(mtype.FissionUserAttrMarkCenterModule, moduleId, moduleId)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 如果没更新,就不用处理了
|
|
if moduleId == pfAttr.Value {
|
|
return
|
|
}
|
|
|
|
return s.update(pfAttr, moduleId)
|
|
}
|
|
|
|
func (s *FissionUserAttr) firstOrCreate(attrMark, value, values string) (attr *model.FissionUserAttr, err error) {
|
|
user := s.user
|
|
attr, err = cache.NewFissionUserAttr(s.Ctx).FindByUniqIdx(user.ID, attrMark, cache.WithNilSet(func() ([]byte, error) {
|
|
createAttr := withdefault.FissionUserAttr(&model.FissionUserAttr{
|
|
CampaignID: user.CampaignID,
|
|
UserID: user.ID,
|
|
Attr: attrMark,
|
|
Value: value,
|
|
Values: values,
|
|
})
|
|
|
|
err = s.creates(createAttr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return jsonm.Marshal(createAttr)
|
|
}))
|
|
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *FissionUserAttr) creates(attrs ...*model.FissionUserAttr) (err error) {
|
|
err = s.GetDao().FissionUserAttr.WithContext(s.Ctx).Clauses(
|
|
clause.OnConflict{
|
|
DoNothing: true,
|
|
}).Create(attrs...)
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
for _, attr := range attrs {
|
|
if s.canTotalAttr(attr.Attr) {
|
|
_ = s.changeTotal(attr.Attr, attr.Value, "")
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *FissionUserAttr) createsJ(attrs ...*model.FissionUserJattr) (err error) {
|
|
err = s.GetDao().FissionUserJattr.WithContext(s.Ctx).Clauses(
|
|
clause.OnConflict{
|
|
DoNothing: true,
|
|
}).Create(attrs...)
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *FissionUserAttr) update(attr *model.FissionUserAttr, vals ...string) (err error) {
|
|
attrM := s.GetDao().FissionUserAttr
|
|
|
|
attrVals := attr.GetValues()
|
|
for _, val := range vals {
|
|
if !verify.InArray(val, attrVals...) {
|
|
attrVals = append(attrVals, val)
|
|
}
|
|
}
|
|
|
|
_, err = attrM.WithContext(s.Ctx).Where(attrM.ID.Eq(attr.ID)).UpdateSimple(
|
|
attrM.Value.Value(vals[0]),
|
|
attrM.Values.Value(strings.Join(attrVals, ",")),
|
|
)
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
if s.canTotalAttr(attr.Attr) {
|
|
_ = s.changeTotal(attr.Attr, vals[0], attr.Value)
|
|
}
|
|
|
|
// 清除缓存
|
|
_ = cache.NewFissionUserAttr(s.Ctx).Clear(attr)
|
|
|
|
return
|
|
}
|
|
|
|
func (s *FissionUserAttr) changeTotal(attr string, newVal, oldVal string) (err error) {
|
|
m := s.GetDao().FissionUserAttrTotal
|
|
if newVal != "" {
|
|
var id int64
|
|
id, err = s.getTotalId(attr, newVal)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(id)).UpdateSimple(m.Num.Add(1))
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
if oldVal != "" {
|
|
var id int64
|
|
id, err = s.getTotalId(attr, oldVal)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(id)).UpdateSimple(m.Num.Sub(1))
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *FissionUserAttr) ignore() bool {
|
|
return s.user.IsView == mtype.Yes
|
|
}
|
|
|
|
func (s *FissionUserAttr) canTotalAttr(attr string) bool {
|
|
return verify.InArray[string](attr, mtype.FissionUserAttrMarkPlatform)
|
|
}
|
|
|
|
func (s *FissionUserAttr) getTotalId(attr, val string) (id int64, err error) {
|
|
cc := cache.NewFissionUserAttrTotal(s.Ctx)
|
|
id, err = cc.FindByUniqIdx(s.user.CampaignID, attr, val)
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
if id != 0 {
|
|
return
|
|
}
|
|
|
|
lc := app.NewFollower(s.Ctx, ckey.FissionUserAttrCreateOnce(s.user.CampaignID, attr, val), lock.SetExpire(10*time.Second)).Lock()
|
|
defer lc.Release()
|
|
if lc.Error() != nil {
|
|
err = workerr.BusyError
|
|
return
|
|
}
|
|
|
|
id, err = cc.FindByUniqIdx(s.user.CampaignID, attr, val)
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
if id != 0 {
|
|
return
|
|
}
|
|
|
|
total := withdefault.FissionUserAttrTotal(&model.FissionUserAttrTotal{
|
|
CampaignID: s.user.CampaignID,
|
|
Attr: attr,
|
|
Val: val,
|
|
Num: 0,
|
|
})
|
|
|
|
err = s.GetDao().FissionUserAttrTotal.WithContext(s.Ctx).Create(total)
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
id = total.ID
|
|
return
|
|
}
|
|
|
|
func (s *FissionUserAttr) CustomParam(paramStr string) (err error) {
|
|
if paramStr == "" || s.ignore() {
|
|
return
|
|
}
|
|
|
|
pfAttr, err := s.firstOrCreateJ(mtype.FissionUserAttrMarkCustomParam, paramStr)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// 如果没更新,就不用处理了
|
|
if paramStr == pfAttr.Value && verify.InArray[string](paramStr, pfAttr.GetValues()...) {
|
|
return
|
|
}
|
|
|
|
return s.updateJ(pfAttr, paramStr)
|
|
}
|
|
|
|
func (s *FissionUserAttr) firstOrCreateJ(attrMark string, values ...string) (attr *model.FissionUserJattr, err error) {
|
|
user := s.user
|
|
|
|
valj, _ := jsonm.ToSliceString(values)
|
|
attr, err = cache.NewFissionUserJattr(s.Ctx).FindByUniqIdx(user.ID, attrMark, cache.WithNilSet(func() ([]byte, error) {
|
|
createAttr := withdefault.FissionUserJattr(&model.FissionUserJattr{
|
|
CampaignID: user.CampaignID,
|
|
UserID: user.ID,
|
|
Attr: attrMark,
|
|
Value: values[0],
|
|
Values: valj,
|
|
})
|
|
|
|
err = s.createsJ(createAttr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return jsonm.Marshal(createAttr)
|
|
}))
|
|
|
|
if err != nil {
|
|
err = s.BE().CacheError(err)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *FissionUserAttr) updateJ(attr *model.FissionUserJattr, vals ...string) (err error) {
|
|
attrM := s.GetDao().FissionUserJattr
|
|
|
|
attrVals := attr.GetValues()
|
|
for _, val := range vals {
|
|
if !verify.InArray(val, attrVals...) {
|
|
attrVals = append(attrVals, val)
|
|
}
|
|
}
|
|
|
|
values, _ := jsonm.ToSliceString(attrVals)
|
|
|
|
_, err = attrM.WithContext(s.Ctx).Where(attrM.ID.Eq(attr.ID)).UpdateSimple(
|
|
attrM.Value.Value(vals[0]),
|
|
attrM.Values.Value(values),
|
|
)
|
|
if err != nil {
|
|
err = s.BE().MysqlError(err)
|
|
return
|
|
}
|
|
|
|
// 清除缓存
|
|
_ = cache.NewFissionUserJattr(s.Ctx).Clear(attr)
|
|
|
|
return
|
|
}
|