Xingyu Xian 8 ماه پیش
والد
کامیت
6488ecb477
72فایلهای تغییر یافته به همراه3772 افزوده شده و 0 حذف شده
  1. 31 0
      app/consts/product_type.go
  2. 30 0
      app/controller/common.go
  3. 332 0
      app/controller/task_controller.go
  4. 25 0
      app/controller/workspace_controller.go
  5. 30 0
      app/dao/dao.go
  6. 14 0
      app/dao/enterprise_dao.go
  7. 34 0
      app/dao/free_strategy_dao.go
  8. 43 0
      app/dao/info_pricing_strategy_dao.go
  9. 91 0
      app/dao/product_dao.go
  10. 66 0
      app/dao/product_photo_dao.go
  11. 34 0
      app/dao/project_brief_dao.go
  12. 125 0
      app/dao/project_dao.go
  13. 34 0
      app/dao/project_material_dao.go
  14. 34 0
      app/dao/recruit_strategy_dao.go
  15. 34 0
      app/dao/reward_strategy_dao.go
  16. 34 0
      app/dao/sec_brief_dao.go
  17. 34 0
      app/dao/sec_material_dao.go
  18. 11 0
      app/dao/sec_task_info_dao.go
  19. 127 0
      app/dao/selection_info_dao.go
  20. 14 0
      app/dao/sub_account_dao.go
  21. 14 0
      app/dao/user_dao.go
  22. 25 0
      app/entity/enterprise.go
  23. 19 0
      app/entity/free_strategy.go
  24. 27 0
      app/entity/info_pricing_strategy.go
  25. 26 0
      app/entity/product.go
  26. 16 0
      app/entity/product_photo.go
  27. 54 0
      app/entity/project.go
  28. 19 0
      app/entity/project_brief.go
  29. 16 0
      app/entity/project_material.go
  30. 32 0
      app/entity/recruit_strategy.go
  31. 14 0
      app/entity/reward_strategy.go
  32. 16 0
      app/entity/sec_brief.go
  33. 16 0
      app/entity/sec_material.go
  34. 44 0
      app/entity/sec_task_info.go
  35. 50 0
      app/entity/selection_info.go
  36. 19 0
      app/entity/sub_account.go
  37. 26 0
      app/entity/user.go
  38. 72 0
      app/service/content_service.go
  39. 119 0
      app/service/enterprise_service.go
  40. 100 0
      app/service/product_service.go
  41. 524 0
      app/service/project_service.go
  42. 41 0
      app/service/review_service/config.go
  43. 38 0
      app/service/review_service/content_check.go
  44. 36 0
      app/service/review_service/credentials_check.go
  45. 23 0
      app/service/review_service/document_check.go
  46. 23 0
      app/service/review_service/document_check_info.go
  47. 34 0
      app/service/review_service/image_check.go
  48. 35 0
      app/service/review_service/video_check.go
  49. 23 0
      app/service/review_service/video_check_info.go
  50. 466 0
      app/service/selection_info_service.go
  51. 16 0
      app/util/encoding.go
  52. 26 0
      app/util/resp.go
  53. 25 0
      app/util/structFunc.go
  54. 129 0
      app/util/type.go
  55. 51 0
      app/util/uuid.go
  56. 13 0
      app/vo/content_check_param.go
  57. 8 0
      app/vo/get_all_product_param.go
  58. 23 0
      app/vo/product_create_param.go
  59. 10 0
      app/vo/project_create_param.go
  60. 17 0
      app/vo/project_search_param.go
  61. 45 0
      app/vo/project_update_param.go
  62. 45 0
      app/vo/re_project_detail.go
  63. 21 0
      app/vo/re_project_task_preview.go
  64. 43 0
      app/vo/re_selection_detail.go
  65. 23 0
      app/vo/re_selection_task_preview.go
  66. 14 0
      app/vo/re_task_product.go
  67. 16 0
      app/vo/re_workspace_takegoods.go
  68. 9 0
      app/vo/result_vo.go
  69. 8 0
      app/vo/selection_info_create_param.go
  70. 54 0
      app/vo/selection_info_update_param.go
  71. 16 0
      app/vo/selection_search_param.go
  72. 16 0
      route/init.go

+ 31 - 0
app/consts/product_type.go

@@ -0,0 +1,31 @@
+package consts
+
+var productTypeMap = map[int64]string{
+	1:  "3C及电器",
+	2:  "食品饮料",
+	3:  "服装配饰",
+	4:  "医疗",
+	5:  "房地产",
+	6:  "家居建材",
+	7:  "教育培训",
+	8:  "出行旅游",
+	9:  "游戏",
+	10: "互联网平台",
+	11: "汽车",
+	12: "文体娱乐",
+	13: "影视传媒",
+	14: "线下店铺",
+	15: "软件服务",
+	16: "美妆",
+	17: "母婴宠物",
+	18: "日化",
+	19: "其他",
+}
+
+func GetProductType(productType int64) string {
+	toast, contain := productTypeMap[productType]
+	if contain {
+		return toast
+	}
+	return "未知"
+}

+ 30 - 0
app/controller/common.go

@@ -0,0 +1,30 @@
+package controller
+
+import "github.com/gin-gonic/gin"
+
+type JsonStruct struct {
+	Code int         `json:"code"`
+	Msg  interface{} `json:"msg"`
+	Data interface{} `json:"data"`
+	//Count int64       `json:"count"`
+}
+
+type JsonErrStruct struct {
+	Code int         `json:"code"`
+	Msg  interface{} `json:"msg"`
+}
+
+func returnSuccess(c *gin.Context, code int, data interface{}) {
+	json := &JsonStruct{Code: code, Msg: "ok", Data: data}
+	c.JSON(200, json)
+}
+
+func returnError(c *gin.Context, code int, msg string) {
+	json := &JsonErrStruct{}
+	if msg == "" {
+		json = &JsonErrStruct{Code: code, Msg: "error"}
+	} else {
+		json = &JsonErrStruct{Code: code, Msg: msg}
+	}
+	c.JSON(400, json)
+}

+ 332 - 0
app/controller/task_controller.go

@@ -0,0 +1,332 @@
+package controller
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/sirupsen/logrus"
+	"youngee_b_api/app/service"
+	"youngee_b_api/app/service/review_service"
+	"youngee_b_api/app/vo"
+)
+
+type TaskController struct{}
+
+type SelectionDetailParam struct {
+	SelectionId string `json:"selection_id"`
+	//EnterpriseId string `json:"enterprise_id"`
+	//SubAccountId int    `json:"sub_account_id"`
+}
+
+type ProjectDetailParam struct {
+	ProjectId string `json:"project_id"`
+	//EnterpriseId string `json:"enterprise_id"`
+	//SubAccountId int    `json:"sub_account_id"`
+}
+
+// 关联商品-已有商品展示
+func (t TaskController) GetAllProduct(c *gin.Context) {
+	search := vo.GetAllProductParam{}
+	err := c.BindJSON(&search)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	var result vo.ResultVO
+	result, err = service.ProductService{}.GetTaskProductsByUserId(search)
+	if err != nil {
+		returnError(c, 40000, "error")
+		return
+	}
+	returnSuccess(c, 20000, result)
+	return
+}
+
+// 关联商品-新建商品
+func (t TaskController) CreateProduct(c *gin.Context) {
+	data := &vo.ProductCreateParam{}
+	err := c.BindJSON(data)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	productId, err := service.ProductService{}.CreateProduct(data)
+	resultMap := make(map[string]int64)
+	resultMap["productId"] = productId
+	returnSuccess(c, 20000, resultMap)
+}
+
+// 关联商品-完成关联创建带货任务
+func (t TaskController) CreateSelection(c *gin.Context) {
+	data := &vo.SelectionInfoCreateParam{}
+	err := c.BindJSON(data)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	selectionId, err := service.SelectionInfoService{}.CreateSelectionInfo(data)
+	if err != nil {
+		logrus.Errorf("[CreateSelection] call CreateSelection err:%+v\n", err)
+		returnError(c, 40000, "error")
+		return
+	}
+	resultMap := make(map[string]string)
+	resultMap["selectionId"] = *selectionId
+	returnSuccess(c, 20000, resultMap)
+}
+
+// 更新带货任务(样品奖励、补充信息)
+func (t TaskController) UpdateSelection(c *gin.Context) {
+	data := &vo.SelectionInfoUpdateParam{}
+	err := c.BindJSON(data)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	selectionId, err := service.SelectionInfoService{}.UpdateSelectionInfo(data)
+	if err != nil {
+		logrus.Errorf("[UpdateSelection] call UpdateSelection err:%+v\n", err)
+		returnError(c, 40000, "error")
+		return
+	}
+	resultMap := make(map[string]string)
+	resultMap["selectionId"] = *selectionId
+	returnSuccess(c, 20000, resultMap)
+}
+
+// 电商带货任务预览
+func (t TaskController) GetSelectionDetail(c *gin.Context) {
+	data := &SelectionDetailParam{}
+	err := c.BindJSON(data)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	res, err := service.SelectionInfoService{}.GetSelectionDetail(data.SelectionId)
+	if err != nil {
+		logrus.Errorf("[GetSelectionDetail] call Show err:%+v\n", err)
+		returnError(c, 40000, "error")
+		return
+	}
+
+	returnSuccess(c, 20000, res)
+}
+
+// 电商带货任务列表
+func (t TaskController) SelectionTaskList(c *gin.Context) {
+	param := &vo.SelectionSearchParam{}
+	err := c.BindJSON(param)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	res, err := service.SelectionInfoService{}.GetSelectionTaskList(param)
+	if err != nil {
+		logrus.Errorf("[SelectionTaskList] call Show err:%+v\n", err)
+		returnError(c, 40000, "error")
+		return
+	}
+
+	returnSuccess(c, 20000, res)
+}
+
+// 删除带货任务
+func (t TaskController) SelectionDel(c *gin.Context) {
+	param := &vo.SelectionSearchParam{}
+	err := c.BindJSON(param)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	selectionId, err := service.SelectionInfoService{}.DeleteSelection(param.SelectionId)
+	if err != nil {
+		logrus.Errorf("[SelectionDel] call Show err:%+v\n", err)
+		returnError(c, 40000, "error")
+		return
+	}
+	resultMap := make(map[string]string)
+	resultMap["selectionId"] = *selectionId
+	returnSuccess(c, 20000, resultMap)
+}
+
+// 电商带货任务审核
+func (t TaskController) CheckSelectionInfo(c *gin.Context) {
+	//data := &vo.ContentCheckParam{}
+	//err := c.BindJSON(data)
+	//if err != nil {
+	//	logrus.Errorf("Request bind err:%+v\n", err)
+	//	returnError(c, 40000, "error")
+	//	return
+	//}
+	//res, err := service.ContentService{}.CheckContent(data)
+	//if err != nil {
+	//	logrus.Errorf("[CheckSelectionInfo] call Show err:%+v\n", err)
+	//	returnError(c, 40000, "error")
+	//	return
+	//}
+	//
+	//returnSuccess(c, 20000, *res)
+	data := &vo.ContentCheckParam{}
+	err := c.BindJSON(data)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	sdk := review_service.Config(data.AK, data.SK, data.ProjectId)
+	res1, err1 := sdk.CheckContent(data.Text)
+	res2, err2 := sdk.CheckImage(data.Image)
+	res3, err3 := sdk.CheckDocument(data.Document, data.Format)
+	res4, err4 := sdk.CheckVideo(data.Video)
+	res5, err5 := sdk.CheckCredentials(data.Credentials)
+	if err1 != nil {
+		logrus.Errorf("[CheckSelectionInfo] call Show err:%+v\n", err)
+		returnError(c, 40000, res1)
+		return
+	}
+	if err2 != nil {
+		logrus.Errorf("[CheckSelectionInfo] call Show err:%+v\n", err)
+		returnError(c, 40000, res2)
+		return
+	}
+	if err3 != nil {
+		logrus.Errorf("[CheckSelectionInfo] call Show err:%+v\n", err)
+		returnError(c, 40000, res3)
+		return
+	}
+	if err4 != nil {
+		logrus.Errorf("[CheckSelectionInfo] call Show err:%+v\n", err)
+		returnError(c, 40000, res4)
+		return
+	}
+	if err5 != nil {
+		logrus.Errorf("[CheckSelectionInfo] call Show err:%+v\n", err)
+		returnError(c, 40000, res5)
+		return
+	}
+
+	returnSuccess(c, 20000, res3)
+}
+
+// 创建种草任务
+func (t TaskController) CreateProject(c *gin.Context) {
+	data := &vo.ProjectCreateParam{}
+	err := c.BindJSON(data)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	projectId, err := service.ProjectService{}.CreateProject(data)
+	if err != nil {
+		logrus.Errorf("[CreateProject] call CreateProject err:%+v\n", err)
+		returnError(c, 40000, "error")
+		return
+	}
+	resultMap := make(map[string]string)
+	resultMap["projectId"] = *projectId
+	returnSuccess(c, 20000, resultMap)
+}
+
+// 更新种草任务
+func (t TaskController) UpdateProject(c *gin.Context) {
+	data := &vo.ProjectUpdateParam{}
+	err := c.BindJSON(data)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	projectId, err := service.ProjectService{}.UpdateProject(data)
+	if err != nil {
+		logrus.Errorf("[UpdateProject] call UpdateProject err:%+v\n", err)
+		returnError(c, 40000, "error")
+		return
+	}
+	resultMap := make(map[string]string)
+	resultMap["projectId"] = *projectId
+	returnSuccess(c, 20000, resultMap)
+}
+
+// 更新定向种草任务
+func (t TaskController) UpdateProjectTarget(c *gin.Context) {
+	data := &vo.ProjectUpdateParam{}
+	err := c.BindJSON(data)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	projectId, err := service.ProjectService{}.UpdateProjectTarget(data)
+	if err != nil {
+		logrus.Errorf("[UpdateProject] call UpdateProject err:%+v\n", err)
+		returnError(c, 40000, "error")
+		return
+	}
+	resultMap := make(map[string]string)
+	resultMap["projectId"] = *projectId
+	returnSuccess(c, 20000, resultMap)
+}
+
+// 种草任务预览
+func (t TaskController) GetProjectDetail(c *gin.Context) {
+	data := &ProjectDetailParam{}
+	err := c.BindJSON(data)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	res, err := service.ProjectService{}.GetProjectDetail(data.ProjectId)
+	if err != nil {
+		logrus.Errorf("[GetProjectDetail] call Show err:%+v\n", err)
+		returnError(c, 40000, "error")
+		return
+	}
+
+	returnSuccess(c, 20000, res)
+}
+
+// 公开种草任务列表
+func (t TaskController) ProjectTaskList(c *gin.Context) {
+	param := &vo.ProjectSearchParam{}
+	err := c.BindJSON(param)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	res, err := service.ProjectService{}.GetProjectTaskList(param)
+	if err != nil {
+		logrus.Errorf("[ProjectTaskList] call Show err:%+v\n", err)
+		returnError(c, 40000, "error")
+		return
+	}
+
+	returnSuccess(c, 20000, res)
+}
+
+// 删除种草任务
+func (t TaskController) ProjectDel(c *gin.Context) {
+	param := &vo.ProjectSearchParam{}
+	err := c.BindJSON(param)
+	if err != nil {
+		logrus.Errorf("Request bind err:%+v\n", err)
+		returnError(c, 40000, "参数错误")
+		return
+	}
+	projectId, err := service.ProjectService{}.DeleteProject(param.ProjectId)
+	if err != nil {
+		logrus.Errorf("[ProjectDel] call Show err:%+v\n", err)
+		returnError(c, 40000, "error")
+		return
+	}
+	resultMap := make(map[string]string)
+	resultMap["projectId"] = *projectId
+	returnSuccess(c, 20000, resultMap)
+}

+ 25 - 0
app/controller/workspace_controller.go

@@ -0,0 +1,25 @@
+package controller
+
+import (
+	"github.com/gin-gonic/gin"
+	"youngee_b_api/app/service"
+)
+
+type WorkspaceController struct{}
+
+type GetTakegoodsInfoParam struct {
+	EnterpriseId string `json:"enterprise_id"`
+	DateRange    string `json:"days"`
+}
+
+func (w WorkspaceController) GetTakegoodsInfo(c *gin.Context) {
+	search := &GetTakegoodsInfoParam{}
+	err := c.BindJSON(&search)
+	if err != nil {
+		returnError(c, 40000, "error")
+		return
+	}
+	result := service.EnterpriseService{}.GetEnterpriseTakegoodsInfo(search.EnterpriseId, search.DateRange)
+
+	returnSuccess(c, 20000, result)
+}

+ 30 - 0
app/dao/dao.go

@@ -0,0 +1,30 @@
+package dao
+
+import (
+	"fmt"
+	"gorm.io/driver/mysql"
+
+	"gorm.io/gorm"
+	"youngee_b_api/model/system_model"
+)
+
+var (
+	Db  *gorm.DB
+	err error
+)
+
+func Init(config *system_model.Mysql) {
+	dsn := "%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local"
+	dsn = fmt.Sprintf(dsn, config.User, config.Password, config.Host, config.Port, config.Database)
+	Db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
+	if err != nil {
+		panic(err)
+	}
+	if Db.Error != nil {
+		panic(err)
+	}
+
+	//Db.DB().SetMaxIdleConns(10)
+	//Db.DB().SetMaxOpenConns(100)
+	//Db.DB().SetConnMaxLifetime(time.Hour)
+}

+ 14 - 0
app/dao/enterprise_dao.go

@@ -0,0 +1,14 @@
+package dao
+
+import "youngee_b_api/app/entity"
+
+type EnterpriseDao struct{}
+
+func (d EnterpriseDao) GetEnterprise(enterpriseId string) (*entity.Enterprise, error) {
+	var enterprise entity.Enterprise
+	err := Db.Model(&entity.Enterprise{}).Where("enterprise_id = ?", enterpriseId).Select("business_name, user_id").First(&enterprise).Error
+	if err != nil {
+		return nil, err
+	}
+	return &enterprise, nil
+}

+ 34 - 0
app/dao/free_strategy_dao.go

@@ -0,0 +1,34 @@
+package dao
+
+import (
+	"github.com/sirupsen/logrus"
+	"youngee_b_api/app/entity"
+)
+
+type FreeStrategyDao struct{}
+
+func (d FreeStrategyDao) DeleteFreeStrategyBySelectionId(selectionId string) error {
+	err := Db.Where("selection_id = ?", selectionId).Delete(&entity.FreeStrategy{}).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d FreeStrategyDao) CreateFreeStrategy(freeStrategys []entity.FreeStrategy) error {
+	err := Db.Create(&freeStrategys).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d FreeStrategyDao) GetFreeStrategyBySelectionId(selectionId string) ([]*entity.FreeStrategy, error) {
+	var freeStrategys []*entity.FreeStrategy
+	err := Db.Model(entity.FreeStrategy{}).Where("selection_id = ?", selectionId).Find(&freeStrategys).Error
+	if err != nil {
+		logrus.Errorf("[GetFreeStrategyBySelectionId] error query, err:%+v", err)
+		return nil, err
+	}
+	return freeStrategys, nil
+}

+ 43 - 0
app/dao/info_pricing_strategy_dao.go

@@ -0,0 +1,43 @@
+package dao
+
+import (
+	"fmt"
+	log "github.com/sirupsen/logrus"
+	"youngee_b_api/app/entity"
+)
+
+type InfoPricingStrategylDao struct{}
+
+func (d InfoPricingStrategylDao) GetPricingStrategy(fansLow int64, fansUp int64, feeForm int64, platForm int64) (*entity.InfoPricingStrategy, error) {
+	// fansLow粉丝量下限  fansUp粉丝量上限  feeForm稿费形式 1产品置换 2固定稿费 3自报价  platForm平台
+	var pricingStrategys []entity.InfoPricingStrategy
+	whereStr := fmt.Sprintf("fee_form = %d and platform = %d and fans_low <= %d and fans_up > %d", feeForm, platForm, fansLow, fansLow)
+	orStr := fmt.Sprintf("fee_form = %d and platform = %d and fans_low < %d and fans_up >= %d", feeForm, platForm, fansUp, fansUp)
+	orStr1 := fmt.Sprintf("fee_form = %d and platform = %d and fans_low >= %d and fans_up <= %d", feeForm, platForm, fansLow, fansUp)
+	orStr2 := fmt.Sprintf("fee_form = %d and platform = %d and fans_low <= %d and fans_up >= %d", feeForm, platForm, fansLow, fansUp)
+	err := Db.Model(entity.InfoPricingStrategy{}).Where(whereStr).Or(orStr).Or(orStr1).Or(orStr2).Scan(&pricingStrategys).Error
+	if err != nil {
+		log.Println("DB GetLastAutoDefaultID:", err)
+		return nil, err
+	}
+	fmt.Printf("PricingStrategys%+v \n", pricingStrategys)
+	pricingStrategy := entity.InfoPricingStrategy{}
+	if feeForm == 1 { // 如果是产品置换,则选取服务费最高时的定价策略
+		var maxCharge float64 = 0
+		for _, v := range pricingStrategys {
+			if v.ServiceCharge >= maxCharge {
+				maxCharge = v.ServiceCharge
+				pricingStrategy = v
+			}
+		}
+	} else { // 如果是固定稿费或自报价,则选取服务费率最高时的定价策略
+		var maxRate int64 = 0
+		for _, v := range pricingStrategys {
+			if v.ServiceRate >= maxRate {
+				maxRate = v.ServiceRate
+				pricingStrategy = v
+			}
+		}
+	}
+	return &pricingStrategy, nil
+}

+ 91 - 0
app/dao/product_dao.go

@@ -0,0 +1,91 @@
+package dao
+
+import (
+	"errors"
+	"github.com/sirupsen/logrus"
+	"gorm.io/gorm"
+	"youngee_b_api/app/entity"
+)
+
+type ProductDAO struct{}
+
+func (d ProductDAO) GetProductsByEnterpriseID(enterpriseId string, page int, pageSize int) ([]entity.Product, int64, error) {
+	var products []entity.Product
+	var total int64
+	Db.Model(&entity.Product{}).Where("enterprise_id = ?", enterpriseId).Count(&total)
+	// 计算偏移量
+	offset := (page - 1) * pageSize
+	// 分页查询
+	err := Db.Where("enterprise_id = ?", enterpriseId).Order("created_at desc").Offset(offset).Limit(pageSize).Find(&products).Error
+	if err != nil {
+		return nil, 0, err
+	}
+	return products, total, nil
+}
+
+func (d ProductDAO) GetProductsBySubAccountId(subAccountId int64, page int, pageSize int) ([]entity.Product, int64, error) {
+	var products []entity.Product
+	var total int64
+	Db.Model(&entity.Product{}).Where("sub_account_id = ?", subAccountId).Count(&total)
+	// 计算偏移量
+	offset := (page - 1) * pageSize
+	// 分页查询
+	err := Db.Where("sub_account_id = ?", subAccountId).Order("created_at desc").Offset(offset).Limit(pageSize).Find(&products).Error
+	if err != nil {
+		return nil, 0, err
+	}
+	return products, total, nil
+}
+
+func (d ProductDAO) CreateProduct(product entity.Product) (int64, error) {
+	err := Db.Create(&product).Error
+	if err != nil {
+		return 0, err
+	}
+	return product.ProductID, nil
+}
+
+func (d ProductDAO) GetProductByID(productId int64) (*entity.Product, error) {
+	var product entity.Product
+	err := Db.Where("product_id = ?", productId).First(&product).Error
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return nil, nil
+		} else {
+			return nil, err
+		}
+	}
+	return &product, nil
+}
+
+func (d ProductDAO) GetProductBySelectionId(selectionId string) (*entity.Product, error) {
+	productId := 0
+	err := Db.Model(entity.SelectionInfo{}).Select("product_id").Where("selection_id = ?", selectionId).Find(&productId).Error
+	if err != nil {
+		logrus.Errorf("[GetProductInfo] error query mysql, err:%+v", err)
+		return nil, err
+	}
+	productInfo := entity.Product{}
+	err = Db.Model(entity.Product{}).Where("product_id = ?", productId).Find(&productInfo).Error
+	if err != nil {
+		logrus.Errorf("[GetProductInfo] error query mysql, err:%+v", err)
+		return nil, err
+	}
+	return &productInfo, nil
+}
+
+func (d ProductDAO) GetProductByProjectId(projectId string) (*entity.Product, error) {
+	productId := 0
+	err := Db.Model(entity.Project{}).Select("product_id").Where("project_id = ?", projectId).Find(&productId).Error
+	if err != nil {
+		logrus.Errorf("[GetProductInfo] error query mysql, err:%+v", err)
+		return nil, err
+	}
+	productInfo := entity.Product{}
+	err = Db.Model(entity.Product{}).Where("product_id = ?", productId).Find(&productInfo).Error
+	if err != nil {
+		logrus.Errorf("[GetProductInfo] error query mysql, err:%+v", err)
+		return nil, err
+	}
+	return &productInfo, nil
+}

+ 66 - 0
app/dao/product_photo_dao.go

@@ -0,0 +1,66 @@
+package dao
+
+import (
+	"github.com/sirupsen/logrus"
+	"youngee_b_api/app/entity"
+)
+
+type ProductPhotoDAO struct{}
+
+func (d ProductPhotoDAO) GetMainPhotoByProductID(productId int64) (string, error) {
+	var productPhoto entity.ProductPhoto
+	err := Db.Where("product_id = ? AND symbol = ?", productId, 1).First(&productPhoto).Error
+	if err != nil {
+		return "", err
+	}
+	return productPhoto.PhotoUrl, nil
+}
+
+func (d ProductPhotoDAO) CreateProductPhoto(productPhotos []entity.ProductPhoto) error {
+	err := Db.Create(&productPhotos).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d ProductPhotoDAO) GetProductPhotoByProductID(productID int64) ([]entity.ProductPhoto, error) {
+	var productPhotos []entity.ProductPhoto
+	err := Db.Where("product_id = ?", productID).Find(&productPhotos).Error
+	if err != nil {
+		return nil, err
+	}
+	return productPhotos, nil
+}
+
+func (d ProductPhotoDAO) GetProductPhotosBySelectionId(selectionId string) ([]*entity.ProductPhoto, error) {
+	productId := 0
+	err := Db.Model(entity.SelectionInfo{}).Select("product_id").Where("selection_id = ?", selectionId).Find(&productId).Error
+	if err != nil {
+		logrus.Errorf("[GetProductInfo] error query mysql, err:%+v", err)
+		return nil, err
+	}
+	var productPhotos []*entity.ProductPhoto
+	err = Db.Model(entity.ProductPhoto{}).Where("product_id = ?", productId).Find(&productPhotos).Error
+	if err != nil {
+		logrus.Errorf("[GetProductInfo] error query mysql, err:%+v", err)
+		return nil, err
+	}
+	return productPhotos, nil
+}
+
+func (d ProductPhotoDAO) GetProductPhotosByProjectId(projectId string) ([]*entity.ProductPhoto, error) {
+	productId := 0
+	err := Db.Model(entity.Project{}).Select("product_id").Where("project_id = ?", projectId).Find(&productId).Error
+	if err != nil {
+		logrus.Errorf("[GetProductInfo] error query mysql, err:%+v", err)
+		return nil, err
+	}
+	var productPhotos []*entity.ProductPhoto
+	err = Db.Model(entity.ProductPhoto{}).Where("product_id = ?", productId).Find(&productPhotos).Error
+	if err != nil {
+		logrus.Errorf("[GetProductInfo] error query mysql, err:%+v", err)
+		return nil, err
+	}
+	return productPhotos, nil
+}

+ 34 - 0
app/dao/project_brief_dao.go

@@ -0,0 +1,34 @@
+package dao
+
+import (
+	"github.com/sirupsen/logrus"
+	"youngee_b_api/app/entity"
+)
+
+type ProjectBriefDao struct{}
+
+func (p ProjectBriefDao) DeleteSecBriefBySelectionId(projectId string) error {
+	err := Db.Where("project_id = ?", projectId).Delete(entity.ProjectBrief{}).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (p ProjectBriefDao) CreateProjectBrief(briefInfo entity.ProjectBrief) error {
+	err := Db.Create(&briefInfo).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (p ProjectBriefDao) GetProjectBriefInfo(projectId string) ([]*entity.ProjectBrief, error) {
+	var projectBriefInfos []*entity.ProjectBrief
+	err := Db.Model(entity.ProjectBrief{}).Where("project_id = ?", projectId).Order("created_at asc").Find(&projectBriefInfos).Error
+	if err != nil {
+		logrus.Errorf("[GetProjectBriefInfo] error query mysql, err:%+v", err)
+		return nil, err
+	}
+	return projectBriefInfos, nil
+}

+ 125 - 0
app/dao/project_dao.go

@@ -0,0 +1,125 @@
+package dao
+
+import (
+	"errors"
+	"gorm.io/gorm"
+	"time"
+	"youngee_b_api/app/entity"
+	"youngee_b_api/app/vo"
+)
+
+type ProjectDAO struct{}
+
+func (d ProjectDAO) GetProjectById(ProjectId string) (*entity.Project, error) {
+	var Project entity.Project
+	err := Db.Where("project_id = ?", ProjectId).First(&Project).Error
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return nil, nil
+		} else {
+			return nil, err
+		}
+	}
+	return &Project, err
+}
+
+// 根据enterpriseId查询指定某天的所有带货数据
+func (d ProjectDAO) GetProjectListOfDay(enterpriseId string, date time.Time) ([]entity.Project, error) {
+	var Projects []entity.Project
+	// 构建查询
+	query := Db.Model(&entity.Project{})
+	if enterpriseId != "" {
+		query = query.Where("enterprise_id = ?", enterpriseId)
+	}
+	// 将日期部分提取出来进行匹配
+	query = query.Where("DATE(created_at) = ?", date.Format("2006-01-02"))
+	err := query.Find(&Projects).Error
+	return Projects, err
+}
+
+// 创建种草任务
+func (d ProjectDAO) CreateProject(project entity.Project) error {
+	err := Db.Omit("recruit_ddl", "auto_fail_at", "auto_script_break_at", "auto_sketch_break_at", "pay_at", "pass_at", "finish_at", "submit_at").Create(&project).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// 更新种草任务
+func (d ProjectDAO) UpdateProject(project entity.Project) error {
+	err := Db.Model(&entity.Project{}).Where("project_id = ?", project.ProjectId).Updates(project).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// 获取种草任务列表
+func (d ProjectDAO) GetProjectPreviews(param *vo.ProjectSearchParam) ([]vo.ReProjectTaskPreview, int64, error) {
+	var reProjectTaskPreviews []vo.ReProjectTaskPreview
+	var projects []entity.Project
+	var total int64
+	query := Db.Model(&entity.Project{})
+	// 动态添加查询条件
+	if param.SubAccountId == 0 {
+		if param.EnterpriseId == "" {
+			return reProjectTaskPreviews, 0, errors.New("enterpriseId is empty")
+		}
+		query = query.Where("enterprise_id = ?", param.EnterpriseId)
+	} else {
+		query = query.Where("sub_account_id = ?", param.SubAccountId)
+	}
+	if param.ProjectType != 0 {
+		query = query.Where("project_type = ?", param.ProjectType)
+	}
+	if param.ProjectPlatform != 0 {
+		query = query.Where("project_platform = ?", param.ProjectPlatform)
+	}
+	if param.ProjectStatus != 0 {
+		query = query.Where("project_status = ?", param.ProjectStatus)
+	}
+	if param.ProjectForm != 0 {
+		query = query.Where("project_form = ?", param.ProjectForm)
+	}
+	if param.ContentType != 0 {
+		query = query.Where("content_type = ?", param.ContentType)
+	}
+	query.Count(&total)
+	query = query.Select("enterprise_id, sub_account_id, project_id, project_platform, project_status, estimated_cost, project_form, content_type, need_review, need_quality, need_calculate, product_id")
+	offset := (param.Page - 1) * param.PageSize
+	if err := query.Order("created_at asc").Offset(offset).Limit(param.PageSize).Find(&projects).Error; err != nil {
+		return nil, 0, err
+	}
+	for _, project := range projects {
+		reProjectTaskPreview := vo.ReProjectTaskPreview{
+			EnterpriseId:    project.EnterpriseID,
+			SubAccountId:    project.SubAccountId,
+			ProjectId:       project.ProjectId,
+			ProjectPlatform: project.ProjectPlatform,
+			ProjectStatus:   project.ProjectStatus,
+			EstimatedCost:   project.EstimatedCost,
+			ProjectForm:     project.ProjectForm,
+			ContentType:     project.ContentType,
+			NeedReview:      project.NeedReview,
+			NeedQuality:     project.NeedQuality,
+			NeedCalculate:   project.NeedCalculate,
+			ProductId:       project.ProductID,
+		}
+		reProjectTaskPreviews = append(reProjectTaskPreviews, reProjectTaskPreview)
+	}
+
+	return reProjectTaskPreviews, total, nil
+}
+
+// 删除种草任务
+func (d ProjectDAO) DeleteProject(projectId string) (*string, error) {
+	if projectId == "" {
+		return &projectId, nil
+	}
+	err := Db.Where("project_id = ?", projectId).Delete(&entity.Project{}).Error
+	if err != nil {
+		return nil, err
+	}
+	return &projectId, nil
+}

+ 34 - 0
app/dao/project_material_dao.go

@@ -0,0 +1,34 @@
+package dao
+
+import (
+	"github.com/sirupsen/logrus"
+	"youngee_b_api/app/entity"
+)
+
+type ProjectMaterialDao struct{}
+
+func (d ProjectMaterialDao) DeleteProjectMaterialByProjectId(projectId string) error {
+	err := Db.Where("project_id = ?", projectId).Delete(entity.ProjectMaterial{}).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d ProjectMaterialDao) CreateProjectMaterial(projectMaterial entity.ProjectMaterial) error {
+	err := Db.Create(&projectMaterial).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d ProjectMaterialDao) GetProjectMaterialInfo(projectId string) ([]*entity.ProjectMaterial, error) {
+	var projectMaterialInfos []*entity.ProjectMaterial
+	err := Db.Model(entity.ProjectMaterial{}).Where("project_id = ?", projectId).Order("created_at asc").Find(&projectMaterialInfos).Error
+	if err != nil {
+		logrus.Errorf("[GetProjectMaterialInfo] error query, err:%+v", err)
+		return nil, err
+	}
+	return projectMaterialInfos, nil
+}

+ 34 - 0
app/dao/recruit_strategy_dao.go

@@ -0,0 +1,34 @@
+package dao
+
+import (
+	"github.com/sirupsen/logrus"
+	"youngee_b_api/app/entity"
+)
+
+type RecruitStrategyDao struct{}
+
+func (d RecruitStrategyDao) DeleteRecruitStrategyByProjectID(projectId string) error {
+	err := Db.Where("project_id = ?", projectId).Delete(&entity.RecruitStrategy{}).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d RecruitStrategyDao) CreateRecruitStrategy(recruitStrategys []entity.RecruitStrategy) error {
+	err := Db.Create(&recruitStrategys).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d RecruitStrategyDao) GetRecruitStrategyByProjectId(projectId string) ([]*entity.RecruitStrategy, error) {
+	var recruitStrategys []*entity.RecruitStrategy
+	err := Db.Model(entity.RecruitStrategy{}).Where("project_id = ?", projectId).Order("strategy_id asc").Find(&recruitStrategys).Error
+	if err != nil {
+		logrus.Errorf("[GetRecruitStrategyByProjectId] error query, err:%+v", err)
+		return nil, err
+	}
+	return recruitStrategys, nil
+}

+ 34 - 0
app/dao/reward_strategy_dao.go

@@ -0,0 +1,34 @@
+package dao
+
+import (
+	"github.com/sirupsen/logrus"
+	"youngee_b_api/app/entity"
+)
+
+type RewardStrategyDao struct{}
+
+func (d RewardStrategyDao) DeleteRewardStrategyBySelectionId(selectionId string) error {
+	err := Db.Where("selection_id = ?", selectionId).Delete(&entity.RewardStrategy{}).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d RewardStrategyDao) CreateRewardStrategy(rewardStrategys []entity.RewardStrategy) error {
+	err := Db.Create(&rewardStrategys).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d RewardStrategyDao) GetRewardStrategyBySelectionId(selectionId string) ([]*entity.RewardStrategy, error) {
+	var rewardStrategys []*entity.RewardStrategy
+	err := Db.Model(entity.RewardStrategy{}).Where("selection_id = ?", selectionId).Find(&rewardStrategys).Error
+	if err != nil {
+		logrus.Errorf("[GetRewardStrategyBySelectionId] error query, err:%+v", err)
+		return nil, err
+	}
+	return rewardStrategys, nil
+}

+ 34 - 0
app/dao/sec_brief_dao.go

@@ -0,0 +1,34 @@
+package dao
+
+import (
+	"github.com/sirupsen/logrus"
+	"youngee_b_api/app/entity"
+)
+
+type SecBriefDao struct{}
+
+func (p SecBriefDao) DeleteSecBriefBySelectionId(selectionId string) error {
+	err := Db.Where("selection_id = ?", selectionId).Delete(entity.SecBrief{}).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (p SecBriefDao) CreateSecBrief(briefInfo entity.SecBrief) error {
+	err := Db.Create(&briefInfo).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (p SecBriefDao) GetSelectionBriefInfo(selectionId string) ([]*entity.SecBrief, error) {
+	var selectionBriefInfos []*entity.SecBrief
+	err := Db.Model(entity.SecBrief{}).Where("selection_id = ?", selectionId).Find(&selectionBriefInfos).Error
+	if err != nil {
+		logrus.Errorf("[GetSelectionBriefInfo] error query mysql, err:%+v", err)
+		return nil, err
+	}
+	return selectionBriefInfos, nil
+}

+ 34 - 0
app/dao/sec_material_dao.go

@@ -0,0 +1,34 @@
+package dao
+
+import (
+	"github.com/sirupsen/logrus"
+	"youngee_b_api/app/entity"
+)
+
+type SecMaterialDao struct{}
+
+func (d SecMaterialDao) DeleteSecMaterialBySelectionId(selectionId string) error {
+	err := Db.Where("selection_id = ?", selectionId).Delete(entity.SecMaterial{}).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d SecMaterialDao) CreateSecMaterial(secExample entity.SecMaterial) error {
+	err := Db.Create(&secExample).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (d SecMaterialDao) GetSelectionMaterialInfo(selectionId string) ([]*entity.SecMaterial, error) {
+	var selectionMaterialInfos []*entity.SecMaterial
+	err := Db.Model(entity.SecMaterial{}).Where("selection_id = ?", selectionId).Find(&selectionMaterialInfos).Error
+	if err != nil {
+		logrus.Errorf("[GetSelectionMaterialInfo] error query, err:%+v", err)
+		return nil, err
+	}
+	return selectionMaterialInfos, nil
+}

+ 11 - 0
app/dao/sec_task_info_dao.go

@@ -0,0 +1,11 @@
+package dao
+
+import "youngee_b_api/app/entity"
+
+type SecTaskInfoDao struct{}
+
+func (s SecTaskInfoDao) CountBySelectionId(selectionId string) (int64, error) {
+	var count int64
+	err := Db.Model(&entity.SecTaskInfo{}).Where("selection_id = ?", selectionId).Count(&count).Error
+	return count, err
+}

+ 127 - 0
app/dao/selection_info_dao.go

@@ -0,0 +1,127 @@
+package dao
+
+import (
+	"errors"
+	"gorm.io/gorm"
+	"time"
+	"youngee_b_api/app/entity"
+	"youngee_b_api/app/vo"
+)
+
+type SelectionInfoDAO struct{}
+
+func (d SelectionInfoDAO) GetSelectionInfoById(selectionId string) (*entity.SelectionInfo, error) {
+	var selectionInfo entity.SelectionInfo
+	err := Db.Where("selection_id = ?", selectionId).First(&selectionInfo).Error
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return nil, nil
+		} else {
+			return nil, err
+		}
+	}
+	return &selectionInfo, err
+}
+
+// 根据enterpriseId查询指定某天的所有带货数据
+func (d SelectionInfoDAO) GetSelectionInfoListOfDay(enterpriseId string, date time.Time) ([]entity.SelectionInfo, error) {
+	var selectionInfos []entity.SelectionInfo
+	// 构建查询
+	query := Db.Model(&entity.SelectionInfo{})
+	if enterpriseId != "" {
+		query = query.Where("enterprise_id = ?", enterpriseId)
+	}
+	// 将日期部分提取出来进行匹配
+	query = query.Where("DATE(created_at) = ?", date.Format("2006-01-02"))
+	err := query.Find(&selectionInfos).Error
+	return selectionInfos, err
+}
+
+// 创建带货任务
+func (d SelectionInfoDAO) CreateSelectionInfo(selectionInfo entity.SelectionInfo) error {
+	err := Db.Omit("task_ddl", "submit_at", "pass_at", "pay_at", "finish_at", "auto_fail_at").Create(&selectionInfo).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// 更新带货任务
+func (d SelectionInfoDAO) UpdateSelectionInfo(selectionInfo entity.SelectionInfo) error {
+	err := Db.Model(&entity.SelectionInfo{}).Where("selection_id = ?", selectionInfo.SelectionID).Updates(selectionInfo).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// 获取带货任务列表
+func (d ProjectDAO) GetSelectionPreviews(param *vo.SelectionSearchParam) ([]vo.ReSelectionTaskPreview, int64, error) {
+	var reSelectionTaskPreviews []vo.ReSelectionTaskPreview
+	var selectionInfos []entity.SelectionInfo
+	var total int64
+	query := Db.Model(&entity.SelectionInfo{})
+	// 动态添加查询条件
+	if param.SubAccountId == 0 {
+		if param.EnterpriseId == "" {
+			return reSelectionTaskPreviews, 0, errors.New("enterpriseId is empty")
+		}
+		query = query.Where("enterprise_id = ?", param.EnterpriseId)
+	} else {
+		query = query.Where("sub_account_id = ?", param.SubAccountId)
+	}
+	if param.SelectionPlatform != 0 {
+		query = query.Where("platform = ?", param.SelectionPlatform)
+	}
+	if param.SelectionStatus != 0 {
+		query = query.Where("selection_status = ?", param.SelectionStatus)
+	}
+	// sample_mode 1、2、3分别表示免费领样(有领样策略)、垫付领样(3.0不用)、不提供样品(无领样策略)
+	if param.FreeFlag == 1 {
+		query = query.Where("sample_mode = ?", 1)
+	} else if param.FreeFlag == 2 {
+		query = query.Where("sample_mode = ?", 3)
+	}
+	// task_mode  1、2分别表示悬赏任务(有悬赏策略)、纯佣带货(无悬赏策略)
+	if param.RewardFlag == 1 {
+		query = query.Where("task_mode = ?", 1)
+	} else if param.RewardFlag == 2 {
+		query = query.Where("task_mode = ?", 2)
+	}
+	query.Count(&total)
+	query = query.Select("enterprise_id, sub_account_id, selection_id, platform, selection_status, created_at, task_ddl, sample_num, enroll_num, choose_num, product_id")
+	offset := (param.Page - 1) * param.PageSize
+	if err := query.Order("created_at asc").Offset(offset).Limit(param.PageSize).Find(&selectionInfos).Error; err != nil {
+		return nil, 0, err
+	}
+	for _, selectionInfo := range selectionInfos {
+		reSelectionTaskPreview := vo.ReSelectionTaskPreview{
+			EnterpriseId:      selectionInfo.EnterpriseID,
+			SubAccountId:      selectionInfo.SubAccountId,
+			SelectionId:       selectionInfo.SelectionID,
+			SelectionPlatform: selectionInfo.Platform,
+			SelectionStatus:   selectionInfo.SelectionStatus,
+			CreatedAt:         selectionInfo.CreatedAt,
+			TaskDdl:           selectionInfo.TaskDdl,
+			SampleNum:         selectionInfo.SampleNum,
+			EnrollNum:         selectionInfo.EnrollNum,
+			ChooseNum:         selectionInfo.ChooseNum,
+			ProductId:         selectionInfo.ProductID,
+		}
+		reSelectionTaskPreviews = append(reSelectionTaskPreviews, reSelectionTaskPreview)
+	}
+
+	return reSelectionTaskPreviews, total, nil
+}
+
+// 删除带货任务
+func (d SelectionInfoDAO) DeleteSelection(selectionId string) (*string, error) {
+	if selectionId == "" {
+		return &selectionId, nil
+	}
+	err := Db.Where("selection_id = ?", selectionId).Delete(&entity.SelectionInfo{}).Error
+	if err != nil {
+		return nil, err
+	}
+	return &selectionId, nil
+}

+ 14 - 0
app/dao/sub_account_dao.go

@@ -0,0 +1,14 @@
+package dao
+
+import "youngee_b_api/app/entity"
+
+type SubAccountDao struct{}
+
+func (d SubAccountDao) GetSubAccount(subAccountId int64) (*entity.SubAccount, error) {
+	var subAccount entity.SubAccount
+	err := Db.Model(&entity.SubAccount{}).Where("sub_account_id = ?", subAccountId).Select("sub_account_name, user_id").First(&subAccount).Error
+	if err != nil {
+		return nil, err
+	}
+	return &subAccount, nil
+}

+ 14 - 0
app/dao/user_dao.go

@@ -0,0 +1,14 @@
+package dao
+
+import "youngee_b_api/app/entity"
+
+type UserDao struct{}
+
+func (d UserDao) GetPhoneByUserId(userId int64) (string, error) {
+	var user entity.User
+	err := Db.Model(&entity.User{}).Where("id = ?", userId).Select("phone").First(&user).Error
+	if err != nil {
+		return "", err
+	}
+	return user.Phone, nil
+}

+ 25 - 0
app/entity/enterprise.go

@@ -0,0 +1,25 @@
+// Code generated by sql2gorm. DO NOT EDIT.
+package entity
+
+import (
+	"time"
+)
+
+type Enterprise struct {
+	EnterpriseID     string    `gorm:"column:enterprise_id"`     // 企业id,用户ID的生成规则为:1(企业用户代码)+分秒数字+四位随机数字
+	Industry         int64     `gorm:"column:industry"`          // 行业,1-14分别代表能源、化工、材料、机械设备/军工、企业服务/造纸印刷、运输设备、旅游酒店、媒体/信息通信服务、批发/零售、消费品、卫生保健/医疗、金融、建材/建筑/房地产、公共事业
+	BusinessName     string    `gorm:"column:business_name"`     // 公司或组织名称
+	UserId           int64     `gorm:"column:user_id"`           // 对应用户id
+	Balance          float64   `gorm:"column:balance"`           // 账户余额
+	FrozenBalance    float64   `gorm:"column:frozen_balance"`    // 冻结余额
+	AvailableBalance float64   `gorm:"column:available_balance"` // 可用余额
+	BillableAmount   float64   `gorm:"column:billable_amount"`   // 可开票金额
+	Invoicing        float64   `gorm:"column:invoicing"`         // 开票中金额
+	Recharging       float64   `gorm:"column:recharging"`        // 充值中金额
+	CreatedAt        time.Time `gorm:"column:created_at"`        // 创建时间
+	UpdatedAt        time.Time `gorm:"column:updated_at"`        // 更新时间
+}
+
+func (m *Enterprise) TableName() string {
+	return "enterprise"
+}

+ 19 - 0
app/entity/free_strategy.go

@@ -0,0 +1,19 @@
+package entity
+
+type FreeStrategy struct {
+	FreeStrategyId    int64  `gorm:"column:free_strategy_id;primary_key;AUTO_INCREMENT"` // 免费领样策略id
+	StrategyId        int64  `gorm:"column:strategy_id"`                                 // 策略编号
+	SelectionId       string `gorm:"column:selection_id"`                                // 带货任务id
+	FansNum           int64  `gorm:"column:fans_num"`                                    // 粉丝数量
+	SaleNum           int64  `gorm:"column:sale_num"`                                    // 近30天橱窗销量
+	StrategyStatus    int64  `gorm:"column:strategy_status"`                             // 招募策略状态
+	EnrollNum         int    `gorm:"column:enroll_num"`                                  // 报名数量
+	ChooseNum         int    `gorm:"column:choose_num"`                                  // 已选数量
+	BeforeDeliveryNum int    `gorm:"column:before_delivery_num"`                         // 待发货数量
+	DeliveryNum       int    `gorm:"column:delivery_num"`                                // 已发货数量
+	AfterDeliveryNum  int    `gorm:"column:after_delivery_num"`                          // 已收货数量
+}
+
+func (m *FreeStrategy) TableName() string {
+	return "free_strategy"
+}

+ 27 - 0
app/entity/info_pricing_strategy.go

@@ -0,0 +1,27 @@
+// Code generated by sql2gorm. DO NOT EDIT.
+package entity
+
+import (
+	"time"
+)
+
+type InfoPricingStrategy struct {
+	ID            int64     `gorm:"column:id;primary_key;AUTO_INCREMENT"` //  id
+	ProjectType   int64     `gorm:"column:project_type;NOT NULL"`         // 项目类型,0表示不限,1为全流程项目
+	StrategyId    string    `gorm:"column:strategyId;NOT NULL"`           // 定价策略编号
+	FeeForm       int64     `gorm:"column:fee_form;NOT NULL"`             // 稿费形式,1,2,3分别代表产品置换、固定稿费、自报价
+	Platform      int64     `gorm:"column:platform;NOT NULL"`             // 项目平台,1-7分别代表红book、抖音、微博、快手、b站、大众点评、知乎
+	FansLow       int64     `gorm:"column:fans_low;NOT NULL"`             // 对应粉丝量下限
+	FansUp        int64     `gorm:"column:fans_up;NOT NULL"`              // 对应粉丝量上限
+	ServiceCharge float64   `gorm:"column:service_charge"`                // 服务费,稿费形式为产品置换时填写,可以为空
+	BaseOffer     float64   `gorm:"column:base_offer"`                    // 基础报价
+	Status        int64     `gorm:"column:status;NOT NULL"`               // 定价策略当前状态,0表示正常,1表示禁用
+	ServiceRate   int64     `gorm:"column:service_rate"`                  // 服务费率*1000,稿费形式为固定稿费和自报价时填写,可以为空
+	UpdateID      int64     `gorm:"column:update_id"`                     // 修改管理人员id,对应user表中主键
+	UpdateAt      time.Time `gorm:"column:update_at"`                     // 修改时间
+	CreateAt      time.Time `gorm:"column:create_at;NOT NULL"`            // 创建时间
+}
+
+func (m *InfoPricingStrategy) TableName() string {
+	return "info_pricing_strategy"
+}

+ 26 - 0
app/entity/product.go

@@ -0,0 +1,26 @@
+package entity
+
+import "time"
+
+type Product struct {
+	ProductID           int64     `gorm:"primaryKey;autoIncrement" json:"product_id"` // 商品id
+	ProductName         string    `gorm:"column:product_name"`                        // 商品名称
+	ProductType         int64     `gorm:"column:product_type"`                        // 商品类型
+	ProductCategory     string    `gorm:"column:product_category"`                    // 商品类目1--20
+	ProductUrl          string    `gorm:"column:product_url"`                         // 商品链接,可为电商网址、公司官网、大众点评的店铺地址等可以说明商品信息或者品牌信息的线上地址;
+	EnterpriseID        string    `gorm:"column:enterprise_id"`                       // 所属企业id
+	SubAccountID        int64     `gorm:"column:sub_account_id"`                      // 子账号id
+	ProductPrice        float64   `gorm:"column:product_price"`                       // 商品价值
+	PublicCommission    float64   `gorm:"column:public_commission"`                   // 公开佣金
+	ExclusiveCommission float64   `gorm:"column:exclusive_commission"`                // 专属佣金
+	CommissionPrice     float64   `gorm:"column:commission_price"`                    // 佣金金额
+	ProductDetail       string    `gorm:"column:product_detail"`                      // 卖点总结
+	KuaishouProductId   string    `gorm:"column:kuaishou_product_id"`                 // 快手商品ID
+	SalesCount          string    `gorm:"column:sales_count"`                         // 商品30天销量
+	CreatedAt           time.Time `gorm:"column:created_at"`                          // 创建时间
+	UpdatedAt           time.Time `gorm:"column:updated_at"`                          // 更新时间
+}
+
+func (m *Product) TableName() string {
+	return "younggee_product"
+}

+ 16 - 0
app/entity/product_photo.go

@@ -0,0 +1,16 @@
+package entity
+
+import "time"
+
+type ProductPhoto struct {
+	ProductPhotoID int64     `gorm:"column:product_photo_id;primary_key;AUTO_INCREMENT"` // 商品图片id
+	PhotoUrl       string    `gorm:"column:photo_url"`                                   // 图片或视频url
+	PhotoUid       string    `gorm:"column:photo_uid"`
+	Symbol         int64     `gorm:"column:symbol"`     // 图片为主图或详情图标志位,1为主图,2为详情图,3为视频
+	ProductID      int64     `gorm:"column:product_id"` // 所属商品id
+	CreatedAt      time.Time `gorm:"column:created_at"` // 创建时间
+}
+
+func (m *ProductPhoto) TableName() string {
+	return "younggee_product_photo"
+}

+ 54 - 0
app/entity/project.go

@@ -0,0 +1,54 @@
+// Code generated by sql2gorm. DO NOT EDIT.
+package entity
+
+import (
+	"time"
+)
+
+type Project struct {
+	ProjectId         string    `gorm:"column:project_id;primary_key;"`        // 项目id 项目ID生成规则:年(2位)+一年中的第几天(3位)+5位数随机数,雪花算法也可,生成10位订单号
+	ProjectName       string    `gorm:"column:project_name"`                   // 项目名称
+	ProjectStatus     int64     `gorm:"column:project_status"`                 // 项目状态,1-10分别代表创建中、待审核、审核通过、招募中、招募完毕、待支付、已支付、失效、执行中、已结案
+	ProjectType       int64     `gorm:"column:project_type"`                   // 项目类型,1代表全流程项目,2代表专项项目
+	ProjectPlatform   int64     `gorm:"column:project_platform"`               // 项目平台,1-7分别代表红book、抖音、微博、快手、b站、大众点评、知乎
+	ProjectForm       int64     `gorm:"column:project_form"`                   // 项目形式,1-4分别代表实体商品寄拍、虚拟产品测评、线下探店打卡、素材微原创
+	TalentType        string    `gorm:"column:talent_type"`                    // 达人类型
+	RecruitDdl        time.Time `gorm:"column:recruit_ddl"`                    // 招募截止时间
+	ContentType       int64     `gorm:"column:content_type"`                   // 内容形式,1代表图文,2代表视频
+	ProjectDetail     string    `gorm:"column:project_detail"`                 // 项目详情
+	ApplyNum          int64     `gorm:"column:apply_num;default:0;NOT NULL"`   // 报名人数
+	RecruitNum        int64     `gorm:"column:recruit_num;default:0;NOT NULL"` // 已招募人数
+	EnterpriseID      string    `gorm:"column:enterprise_id"`                  // 所属企业id
+	SubAccountId      int64     `gorm:"column:sub_account_id"`                 // 子账号id
+	ProductID         int64     `gorm:"column:product_id"`                     // 关联商品id
+	CreatedAt         time.Time `gorm:"column:created_at"`                     // 创建时间
+	UpdatedAt         time.Time `gorm:"column:updated_at"`                     // 修改时间
+	FeeForm           string    `gorm:"column:fee_form"`                       // 稿费形式列表
+	AutoFailAt        time.Time `gorm:"column:auto_fail_at"`                   // 失效自动处理时间
+	AutoTaskID        int64     `gorm:"column:auto_task_id;NOT NULL"`          // 定时任务id
+	AutoDefaultID     int64     `gorm:"column:auto_default_id;NOT NULL"`       // 违约状态id
+	PaymentAmount     float64   `gorm:"column:payment_amount"`                 // 支付金额
+	PayAt             time.Time `gorm:"column:pay_at"`                         // 支付时间
+	AutoScriptBreakAt time.Time `gorm:"column:auto_script_break_at"`           // 脚本违约自动处理时间
+	AutoSketchBreakAt time.Time `gorm:"column:auto_sketch_break_at"`           // 初稿违约自动处理时间
+	FailReason        int64     `gorm:"column:fail_reason"`                    // 失效原因,1、2分别表示逾期未支付、项目存在风险
+	PassAt            time.Time `gorm:"column:pass_at"`                        // 审核通过时间
+	FinishAt          time.Time `gorm:"column:finish_at"`                      // 结案时间
+	SubmitAt          time.Time `gorm:"column:submit_at"`                      // 结案时间
+	EstimatedCost     float64   `gorm:"column:estimated_cost"`                 // 预估成本
+	IsRead            int64     `gorm:"column:is_read"`                        // 是否已读
+	SettlementAmount  float64   `gorm:"column:settlement_amount"`              // 结算金额
+	ProductSnap       string    `gorm:"column:product_snap"`                   // 商品信息快照
+	ProductPhotoSnap  string    `gorm:"column:product_photo_snap"`             // 商品图片快照
+	NeedReview        int64     `gorm:"column:need_review"`                    // 待审稿
+	NeedQuality       int64     `gorm:"column:need_quality"`                   // 待质检
+	NeedCalculate     int64     `gorm:"column:need_calculate"`                 // 待结算
+	ServiceChargeRate float64   `gorm:"column:service_charge_rate"`            // 公开服务费率
+	OperatorType      int64     `gorm:"column:operator_type"`                  // 创建者类型,1商家主账号,2商家子账号
+	TotalRecruitNum   int64     `gorm:"column:total_recruit_num"`              // 各策略招募人数总和
+	Tools             string    `gorm:"column:tools"`                          // 工具选择,1邀约招募 2结算账单 3样品物流 4审稿工具 5作品审查 6数据巡检(,分隔)
+}
+
+func (m *Project) TableName() string {
+	return "project_info"
+}

+ 19 - 0
app/entity/project_brief.go

@@ -0,0 +1,19 @@
+// Code generated by sql2gorm. DO NOT EDIT.
+package entity
+
+import (
+	"time"
+)
+
+type ProjectBrief struct {
+	ProjectBriefID int64     `gorm:"column:project_brief_id;primary_key;AUTO_INCREMENT"` // 项目id
+	FileUrl        string    `gorm:"column:file_url"`                                    // 图片url
+	FileName       string    `gorm:"column:file_name"`                                   // 文件名称
+	FileUid        string    `gorm:"column:file_uid"`
+	ProjectID      string    `gorm:"column:project_id"` // 所属项目id
+	CreatedAt      time.Time `gorm:"column:created_at"` // 创建时间
+}
+
+func (m *ProjectBrief) TableName() string {
+	return "project_brief"
+}

+ 16 - 0
app/entity/project_material.go

@@ -0,0 +1,16 @@
+package entity
+
+import "time"
+
+type ProjectMaterial struct {
+	MaterialID int       `gorm:"column:material_id;primary_key;AUTO_INCREMENT"` // 种草任务素材id
+	FileUrl    string    `gorm:"column:file_url"`                               // 文件url
+	FileUid    string    `gorm:"column:file_uid"`                               // 文件uid
+	ProjectID  string    `gorm:"column:project_id"`                             // 所属项目id
+	CreatedAt  time.Time `gorm:"column:created_at"`                             // 创建时间
+	FileName   string    `gorm:"column:file_name"`                              // 文件名称
+}
+
+func (m *ProjectMaterial) TableName() string {
+	return "project_material"
+}

+ 32 - 0
app/entity/recruit_strategy.go

@@ -0,0 +1,32 @@
+// Code generated by sql2gorm. DO NOT EDIT.
+package entity
+
+type RecruitStrategy struct {
+	RecruitStrategyID int64   `gorm:"column:recruit_strategy_id;primary_key;AUTO_INCREMENT"` // 招募策略id
+	FeeForm           int64   `gorm:"column:fee_form"`                                       // 稿费形式,1-3分别代表产品置换、固定稿费、自报价
+	StrategyID        int64   `gorm:"column:strategy_id"`                                    // 策略id
+	FollowersLow      int64   `gorm:"column:followers_low"`                                  // 达人粉丝数下限
+	FollowersUp       int64   `gorm:"column:followers_up"`                                   // 达人粉丝数上限
+	RecruitNumber     int64   `gorm:"column:recruit_number"`                                 // 招募数量
+	Offer             float64 `gorm:"column:offer"`                                          // 报价
+	TOffer            float64 `gorm:"column:t_offer"`                                        // 达人所见报价
+	ProjectID         string  `gorm:"column:project_id"`                                     // 所属项目id
+	ServiceCharge     float64 `gorm:"column:service_charge"`                                 // 平台服务费,稿费形式为产品置换时必填
+	SelectedNumber    int64   `gorm:"column:selected_number;default:0"`                      // 已选数量,被企业选择的达人数量
+	WaitingNumber     int64   `gorm:"column:waiting_number;default:0"`                       // 待发货
+	DeliveredNumber   int64   `gorm:"column:delivered_number;default:0"`                     // 已发货
+	SignedNumber      int64   `gorm:"column:signed_number;default:0"`                        // 已签收
+	MaxOffer          int64   `gorm:"column:max_offer;default:0"`                            // 报价上限
+	MinOffer          int64   `gorm:"column:min_offer;default:0"`                            // 报价下限
+	FanNumber         int64   `gorm:"column:fan_number;default:0"`                           // 总粉丝量
+	PlayNumber        int64   `gorm:"column:play_number;default:0"`                          // 总播放量
+	LikeNumber        int64   `gorm:"column:like_number;default:0"`                          // 总点赞数
+	CollectNumber     int64   `gorm:"column:collect_number;default:0"`                       // 总收藏量
+	CommentNumber     int64   `gorm:"column:comment_number;default:0"`                       // 总评论数
+	FinishNumber      int64   `gorm:"column:finish_number;default:0"`                        // 结案数量
+	TotalOffer        float64 `gorm:"column:total_offer;default:0"`                          // 支付合计
+}
+
+func (m *RecruitStrategy) TableName() string {
+	return "recruit_strategy"
+}

+ 14 - 0
app/entity/reward_strategy.go

@@ -0,0 +1,14 @@
+package entity
+
+type RewardStrategy struct {
+	RewardStrategyId int64   `gorm:"column:reward_strategy_id;primary_key;AUTO_INCREMENT"` // 悬赏策略id
+	SelectionId      string  `gorm:"column:selection_id"`                                  // 带货任务id
+	Reward           float64 `gorm:"column:reward"`                                        // 悬赏池总金额
+	SaleActual       int64   `gorm:"column:sale_actual"`                                   // 实际带货销量
+	PerReward        float64 `gorm:"column:per_reward"`                                    // 每人可获得悬赏金
+	StrategyStatus   int64   `gorm:"column:strategy_status"`                               // 悬赏策略状态
+}
+
+func (m *RewardStrategy) TableName() string {
+	return "reward_strategy"
+}

+ 16 - 0
app/entity/sec_brief.go

@@ -0,0 +1,16 @@
+package entity
+
+import "time"
+
+type SecBrief struct {
+	SectionBriefID int       `gorm:"column:section_brief_id;primary_key;AUTO_INCREMENT"` // brief的Id
+	FileUrl        string    `gorm:"column:file_url"`                                    // 文件url
+	FileUid        string    `gorm:"column:file_uid"`                                    // 文件uid
+	SelectionID    string    `gorm:"column:selection_id"`                                // 所属选品id
+	CreatedAt      time.Time `gorm:"column:created_at"`                                  // 创建时间
+	FileName       string    `gorm:"column:file_name"`                                   // 文件名称
+}
+
+func (m *SecBrief) TableName() string {
+	return "younggee_sec_brief"
+}

+ 16 - 0
app/entity/sec_material.go

@@ -0,0 +1,16 @@
+package entity
+
+import "time"
+
+type SecMaterial struct {
+	MaterialID  int       `gorm:"column:material_id;primary_key;AUTO_INCREMENT"` // 带货任务素材id
+	FileUrl     string    `gorm:"column:file_url"`                               // 文件url
+	FileUid     string    `gorm:"column:file_uid"`                               // 文件uid
+	SelectionID string    `gorm:"column:selection_id"`                           // 所属项目id
+	CreatedAt   time.Time `gorm:"column:created_at"`                             // 创建时间
+	FileName    string    `gorm:"column:file_name"`                              // 文件名称
+}
+
+func (m *SecMaterial) TableName() string {
+	return "younggee_sec_material"
+}

+ 44 - 0
app/entity/sec_task_info.go

@@ -0,0 +1,44 @@
+package entity
+
+// Code generated by sql2gorm. DO NOT EDIT.
+
+import (
+	"time"
+)
+
+type SecTaskInfo struct {
+	ID                     int       `gorm:"column:id;primary_key"`              // 递增id
+	TaskID                 string    `gorm:"column:task_id"`                     // 选品任务id
+	SelectionID            string    `gorm:"column:selection_id"`                // 选品id
+	TalentID               string    `gorm:"column:talent_id"`                   // 达人id
+	AccountID              int       `gorm:"column:account_id"`                  // 账号id
+	TalentPlatformInfoSnap string    `gorm:"column:talent_platform_info_snap"`   // 达人平台信息快照
+	TalentPersonalInfoSnap string    `gorm:"column:talent_personal_info_snap"`   // 达人个人信息快照
+	TalentPostAddrSnap     string    `gorm:"column:talent_post_addr_snap"`       // 收货地址快照
+	TaskReward             string    `gorm:"column:task_reward"`                 //  达人赏金
+	TalentPayment          string    `gorm:"column:talent_payment"`              // 达人垫付金额
+	IsPayPayment           int       `gorm:"column:is_pay_payment"`              // 企业是否返样品钱
+	IsPayReward            int       `gorm:"column:is_pay_reward"`               // 企业是否结算悬赏
+	TaskMode               int       `gorm:"column:task_mode"`                   // 任务形式,1、2分别表示纯佣带货、悬赏任务
+	SampleMode             int       `gorm:"column:sample_mode"`                 // 领样形式,1-3分别表示免费领样、垫付买样、不提供样品
+	TaskStatus             int       `gorm:"column:task_status;default:1"`       // 任务状态 1待选 2已选 3落选
+	TaskStage              int       `gorm:"column:task_stage"`                  // 任务阶段,详情见info_sec_task_stage表
+	CreateDate             time.Time `gorm:"column:create_date"`                 // 创建时间
+	SelectDate             time.Time `gorm:"column:select_date"`                 // 反选时间
+	DeliveryDate           time.Time `gorm:"column:delivery_date"`               // 发货时间
+	CompleteDate           time.Time `gorm:"column:complete_date"`               // 结束时间
+	WithdrawDate           time.Time `gorm:"column:withdraw_date"`               // 提现时间
+	CompleteStatus         int       `gorm:"column:complete_status;default:1"`   // 结束方式 1未结束 2正常结束 3反选失败
+	LogisticsStatus        int       `gorm:"column:logistics_status;default:1"`  // 发货状态 1 待发货 2已发货 3 已签收
+	AssignmentStatus       uint      `gorm:"column:assignment_status;default:1"` // 作业上传状态 1-5分别代表待添加、已添加、待修改、已修改、已通过
+	UpdateAt               time.Time `gorm:"column:update_at"`                   // 更新时间
+	WithdrawStatus         int       `gorm:"column:withdraw_status;default:1"`   // 提现状态,1-4分别代表不可提现、可提现、提现中、已提现
+	LeadTeamID             string    `gorm:"column:lead_team_id"`                // 作为团长的young之团id,对应younggee_talent_team中的team_id字段
+	TeamID                 string    `gorm:"column:team_id"`                     // 作为团员的young之团id,对应younggee_talent_team中的team_id字段
+	TeamIncome             int       `gorm:"column:team_income"`                 // young之团团长现金收益
+	TeamPoint              int       `gorm:"column:team_point"`                  // young之团团长积分收益
+}
+
+func (m *SecTaskInfo) TableName() string {
+	return "younggee_sec_task_info"
+}

+ 50 - 0
app/entity/selection_info.go

@@ -0,0 +1,50 @@
+package entity
+
+// Code generated by sql2gorm. DO NOT EDIT.
+
+import (
+	"time"
+)
+
+type SelectionInfo struct {
+	SelectionID      string    `gorm:"column:selection_id;primary_key"` // 选品项目id
+	SelectionName    string    `gorm:"column:selection_name"`           // 任务名称
+	EnterpriseID     string    `gorm:"column:enterprise_id"`            // 所属企业id
+	SubAccountId     int64     `gorm:"column:sub_account_id"`           // 子账号id
+	ProductID        int64     `gorm:"column:product_id"`               // 关联商品id
+	SelectionStatus  int64     `gorm:"column:selection_status"`         // 选品项目状态,1-8分别代表创建中、待审核、审核通过、待支付、已支付、执行中、失效、已结案
+	Platform         int64     `gorm:"column:platform"`                 // 项目平台,1-7分别代表小红书、抖音、微博、快手、b站、大众点评、知乎
+	SampleNum        int64     `gorm:"column:sample_num"`               // 样品数量
+	TaskDdl          time.Time `gorm:"column:task_ddl"`                 // 招募截止时间
+	ContentType      int64     `gorm:"column:content_type"`             // 内容形式,1代表图文,2代表视频,3代表直播
+	TaskMode         int64     `gorm:"column:task_mode"`                // 任务形式,1、2分别表示悬赏任务、纯佣带货
+	SampleMode       int64     `gorm:"column:sample_mode"`              // 领样形式,1、2分别表示免费领样、垫付领样
+	ProductUrl       string    `gorm:"column:product_url"`              // 带货链接
+	RemainNum        int64     `gorm:"column:remain_num"`               // 剩余数量
+	CommissionRate   float64   `gorm:"column:commission_rate"`          // 佣金比例
+	EstimatedCost    float64   `gorm:"column:estimated_cost"`           // 预估成本
+	TaskReward       float64   `gorm:"column:task_reward"`              // 任务悬赏
+	SampleCondition  string    `gorm:"column:sample_condition"`         // 领样条件
+	RewardCondition  string    `gorm:"column:reward_condition"`         // 返现悬赏条件
+	SettlementAmount float64   `gorm:"column:settlement_amount"`        // 结算金额
+	Detail           string    `gorm:"column:detail"`                   // 卖点总结
+	ProductSnap      string    `gorm:"column:product_snap"`             // 商品信息快照
+	ProductPhotoSnap string    `gorm:"column:product_photo_snap"`       // 商品图片快照
+	CreatedAt        time.Time `gorm:"column:created_at"`               // 创建时间
+	UpdatedAt        time.Time `gorm:"column:updated_at"`               // 修改时间
+	SubmitAt         time.Time `gorm:"column:submit_at"`                // 提交审核时间
+	PassAt           time.Time `gorm:"column:pass_at"`                  // 审核通过时间
+	FailReason       int64     `gorm:"column:fail_reason"`              // 失效原因,1、2分别表示逾期未支付、项目存在风险
+	PayAt            time.Time `gorm:"column:pay_at"`                   // 支付时间
+	FinishAt         time.Time `gorm:"column:finish_at"`                // 结案时间
+	IsRead           int64     `gorm:"column:is_read"`                  // 是否已读
+	AutoTaskID       int64     `gorm:"column:auto_task_id"`             // 定时任务id
+	AutoFailAt       time.Time `gorm:"column:auto_fail_at"`             // 失效自动处理时间
+	Status           int64     `gorm:"column:status"`                   // 选品是否删除 2代表删除
+	EnrollNum        int64     `gorm:"column:enroll_num"`               // 报名数量
+	ChooseNum        int64     `gorm:"column:choose_num"`               // 已选数量
+}
+
+func (m *SelectionInfo) TableName() string {
+	return "younggee_selection_info"
+}

+ 19 - 0
app/entity/sub_account.go

@@ -0,0 +1,19 @@
+// Code generated by sql2gorm. DO NOT EDIT.
+package entity
+
+type SubAccount struct {
+	SubAccountId   int64  `gorm:"sub_account_id"`   // 子账号ID
+	PhoneNumber    string `gorm:"phone_number"`     // 手机号
+	SubAccountName string `gorm:"sub_account_name"` // 名称
+	JobId          int64  `gorm:"job_id"`           // 岗位ID
+	EnterpriseId   string `gorm:"enterprise_id"`    // 所属商家账号ID
+	AccountStatus  int64  `gorm:"account_status"`   // 账户状态,1为正常,2为已停用
+	SubAccountType int64  `gorm:"sub_account_type"` // 子账号类型,1为商家端子账号,2为管理后台子账号,3为服务商端子账号
+	SuperAdminId   int64  `gorm:"super_admin_id"`   // 管理后台子账号创建者ID
+	UserId         int64  `gorm:"user_id"`          // 用户表中ID
+	SupplierId     int64  `gorm:"supplier_id"`      // 所属服务商ID
+}
+
+func (m *SubAccount) TableName() string {
+	return "younggee_sub_account"
+}

+ 26 - 0
app/entity/user.go

@@ -0,0 +1,26 @@
+// Code generated by sql2gorm. DO NOT EDIT.
+package entity
+
+import (
+	"time"
+)
+
+type User struct {
+	ID            int64     `gorm:"column:id;primary_key;AUTO_INCREMENT"`  // 用户表id
+	User          string    `gorm:"column:user"`                           // 账号
+	Username      string    `gorm:"column:username"`                       // 后台用户名
+	Password      string    `gorm:"column:password"`                       // 用户密码
+	RealName      string    `gorm:"column:real_name"`                      // 真实姓名
+	Role          string    `gorm:"column:role"`                           // 角色 1,超级管理员; 2,管理员;3,企业用户
+	Phone         string    `gorm:"column:phone"`                          // 绑定手机
+	Email         string    `gorm:"column:email"`                          // 电子邮件
+	LastLoginTime time.Time `gorm:"column:last_login_time"`                // 最后一次登录时间
+	UserState     string    `gorm:"column:user_state;default:1;NOT NULL"`  // 0,禁用,1,正常
+	CreatedAt     time.Time `gorm:"column:created_at"`                     // 创建时间
+	UpdatedAt     time.Time `gorm:"column:updated_at"`                     // 更新时间
+	AuthStatus    int64     `gorm:"column:auth_status;default:1;NOT NULL"` // 商家认证状态,0未认证,1已认证
+}
+
+func (m *User) TableName() string {
+	return "younggee_user"
+}

+ 72 - 0
app/service/content_service.go

@@ -0,0 +1,72 @@
+package service
+
+import (
+	"fmt"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
+	//region "github.com/huaweicloud/huaweicloud-review_service-go-v3/core/region"
+	moderation "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/moderation/v3"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/moderation/v3/model"
+	moderationRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/moderation/v3/region"
+	"youngee_b_api/app/vo"
+)
+
+type ContentService struct{}
+
+// 内容审核
+func (s ContentService) CheckContent(contentCheckParam *vo.ContentCheckParam) (*string, error) {
+	// 认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;
+	// 本示例以ak和sk保存在环境变量中来实现身份验证为例,运行本示例前请先在本地环境中设置环境变量HUAWEICLOUD_SDK_AK和HUAWEICLOUD_SDK_SK。
+	ak := "CNN8MCCSJFGHL1MXCJRF"
+	sk := "91arFGHyO7RrzXnZIFSPcLSC6y4P4MTKtkq3qLIy"
+	projectId := "CNN8MCCSJFGHL1MXCJRF"
+	eventType := "article"
+
+	auth := basic.NewCredentialsBuilder().
+		WithAk(ak).
+		WithSk(sk).
+		WithProjectId(projectId).
+		Build()
+
+	client := moderation.NewModerationClient(
+		moderation.ModerationClientBuilder().
+			WithRegion(moderationRegion.ValueOf("cn-north-4")). //把xxx替换成服务所在的区域,例如北京四:cn-north-4。
+			WithCredential(auth).
+			Build())
+
+	//request := &model.RunTextModerationRequest{}
+	//request.EnterpriseProjectId = &projectId
+	//databody := &model.TextDetectionDataReq{
+	//	Text: contentCheckParam.Summary,
+	//}
+	//request.Body = &model.TextDetectionReq{
+	//	Data:      databody,
+	//	EventType: &eventType,
+	//}
+	//response, err := client.RunTextModeration(request)
+	//if err == nil {
+	//	fmt.Printf("%+v\n", response)
+	//} else {
+	//	fmt.Println(err)
+	//}
+	request := &model.CheckImageModerationRequest{}
+	var listCategoriesbody = []string{
+		"porn", "terrorism",
+	}
+	eventType = "head_image"
+	urlImageDetectionReq := "https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1oXRBY.img?w=640&h=360&m=6"
+	request.Body = &model.ImageDetectionReq{
+		Url:        &urlImageDetectionReq,
+		Categories: &listCategoriesbody,
+		EventType:  &eventType,
+	}
+	response, err := client.CheckImageModeration(request)
+	if err == nil {
+		fmt.Printf("%+v\n", response)
+	} else {
+		fmt.Println(err)
+	}
+	result := response.Result
+	fmt.Print(result)
+
+	return nil, nil
+}

+ 119 - 0
app/service/enterprise_service.go

@@ -0,0 +1,119 @@
+package service
+
+import (
+	"time"
+	"youngee_b_api/app/dao"
+	"youngee_b_api/app/vo"
+)
+
+type EnterpriseService struct{}
+
+func (e EnterpriseService) GetEnterpriseTakegoodsInfo(enterpriseId string, dateRange string) vo.ReWorkspaceTakegoods {
+	var result vo.ReWorkspaceTakegoods
+	//result.Pay = 1234.5
+	//result.PayList = []float64{4, 6, 9}
+	// 处理时间范围
+	switch dateRange {
+	case "7days":
+		dates := getLastNDays(7)
+		result = calcTakegoodsInfo(dates, enterpriseId)
+		break
+	case "30days":
+		dates := getLastNDays(30)
+		result = calcTakegoodsInfo(dates, enterpriseId)
+		break
+	case "90days":
+		dates := getLastNDays(90)
+		result = calcTakegoodsInfo(dates, enterpriseId)
+		break
+	case "monthly":
+		dates := getCurrentMonthDates()
+		result = calcTakegoodsInfo(dates, enterpriseId)
+		break
+	}
+
+	return result
+}
+
+func getLastNDays(n int) []time.Time {
+	var dates []time.Time
+	today := time.Now()
+	for i := 0; i < n; i++ {
+		date := today.AddDate(0, 0, -i)
+		dates = append(dates, date)
+	}
+	return dates
+}
+
+func getCurrentMonthDates() []time.Time {
+	var dates []time.Time
+	today := time.Now()
+	year, month, _ := today.Date()
+	location := today.Location()
+
+	firstOfMonth := time.Date(year, month, 1, 0, 0, 0, 0, location)
+	nextMonth := firstOfMonth.AddDate(0, 1, 0)
+
+	for current := firstOfMonth; current.Before(nextMonth); current = current.AddDate(0, 0, 1) {
+		dates = append(dates, current)
+	}
+	return dates
+}
+
+func calcTakegoodsInfo(dates []time.Time, enterpriseId string) vo.ReWorkspaceTakegoods {
+	var pay, finish, commission, commissionRate float64
+	var order, person int64
+	var payList, finishList, commissionList, commissionRateList []float64
+	var orderList, personList []int64
+
+	for _, date := range dates {
+		enterprises, _ := (&dao.SelectionInfoDAO{}).GetSelectionInfoListOfDay(enterpriseId, date)
+		if enterprises != nil {
+			var currentPay float64
+			var currentFinish float64
+			var currentCommission float64
+			var currentCommissionRate float64
+			var currentOrder int64
+			var currentPerson int64
+			for _, enterprise := range enterprises {
+				// 带货数据
+				currentPay += enterprise.EstimatedCost
+				currentFinish += enterprise.SettlementAmount
+				currentCommission += enterprise.EstimatedCost * enterprise.CommissionRate
+				currentOrder += enterprise.SampleNum - enterprise.RemainNum
+				// 出单数量
+				currentPerson, _ = (&dao.SecTaskInfoDao{}).CountBySelectionId(enterprise.SelectionID)
+				currentCommissionRate = enterprise.SettlementAmount / float64(currentPerson)
+			}
+			// 带货数据
+			pay += currentPay
+			payList = append(payList, currentPay)
+			finish += currentFinish
+			finishList = append(finishList, currentFinish)
+			commission += currentCommission
+			commissionList = append(commissionList, currentCommission)
+			order += currentOrder
+			orderList = append(orderList, currentOrder)
+			// 出单数量
+			person += currentPerson
+			personList = append(personList, person)
+			commissionRate += currentCommissionRate
+			commissionRateList = append(commissionRateList, currentCommissionRate)
+		}
+	}
+	res := vo.ReWorkspaceTakegoods{
+		Pay:                pay,
+		PayList:            payList,
+		Finish:             finish,
+		FinishList:         finishList,
+		Commission:         commission,
+		CommissionList:     commissionList,
+		Order:              order,
+		OrderList:          orderList,
+		Person:             person,
+		PersonList:         personList,
+		CommissionRate:     commissionRate,
+		CommissionRateList: commissionRateList,
+	}
+	return res
+}

+ 100 - 0
app/service/product_service.go

@@ -0,0 +1,100 @@
+package service
+
+import (
+	"errors"
+	"time"
+	"youngee_b_api/app/dao"
+	"youngee_b_api/app/entity"
+	"youngee_b_api/app/vo"
+)
+
+type ProductService struct{}
+
+func (p ProductService) GetTaskProductsByUserId(param vo.GetAllProductParam) (vo.ResultVO, error) {
+	if param.Page == 0 {
+		param.Page = 1
+	}
+	if param.PageSize == 0 {
+		param.PageSize = 10
+	}
+	var result vo.ResultVO
+	var products []entity.Product
+	var err error
+	var total int64
+	if param.SubAccountId == 0 {
+		enterpriseId := param.EnterpriseId
+		if enterpriseId == "" {
+			return result, errors.New("enterpriseId is empty")
+		}
+		products, total, err = (&dao.ProductDAO{}).GetProductsByEnterpriseID(enterpriseId, param.Page, param.PageSize)
+	} else {
+		products, total, err = (&dao.ProductDAO{}).GetProductsBySubAccountId(param.SubAccountId, param.Page, param.PageSize)
+	}
+	if err != nil {
+		// 数据库查询error
+		return result, err
+	}
+	var reProducts []vo.ReTaskProduct
+	for _, product := range products {
+		photoUrl, e := dao.ProductPhotoDAO{}.GetMainPhotoByProductID(product.ProductID)
+		if e != nil {
+			photoUrl = ""
+		}
+		reProduct := vo.ReTaskProduct{
+			ProductID:       product.ProductID,
+			ProductName:     product.ProductName,
+			ProductType:     product.ProductType,
+			ProductCategory: product.ProductCategory,
+			ProductPrice:    product.ProductPrice,
+			ProductDetail:   product.ProductDetail,
+			CreatedAt:       product.CreatedAt,
+			PhotoUrl:        photoUrl,
+		}
+		reProducts = append(reProducts, reProduct)
+	}
+	result = vo.ResultVO{
+		Page:     param.Page,
+		PageSize: param.PageSize,
+		Total:    total,
+		Data:     reProducts,
+	}
+	return result, nil
+}
+
+func (p ProductService) CreateProduct(productCreateParam *vo.ProductCreateParam) (int64, error) {
+	product := entity.Product{
+		KuaishouProductId:   productCreateParam.ProductId,
+		ProductName:         productCreateParam.ProductName,
+		ProductCategory:     productCreateParam.ProductCategory,
+		ProductPrice:        productCreateParam.ProductPrice,
+		ProductDetail:       productCreateParam.ProductDetail,
+		EnterpriseID:        productCreateParam.EnterpriseId,
+		SubAccountID:        productCreateParam.SubAccountId,
+		ExclusiveCommission: productCreateParam.ExclusiveCommission,
+		CommissionPrice:     productCreateParam.CommissionPrice,
+		PublicCommission:    productCreateParam.PublicCommission,
+		ProductUrl:          productCreateParam.ProductUrl,
+	}
+	productID, err := dao.ProductDAO{}.CreateProduct(product)
+	if err != nil {
+		return 0, err
+	}
+	if productCreateParam.ProductPhotos != nil {
+		productPhotos := []entity.ProductPhoto{}
+		for _, photo := range productCreateParam.ProductPhotos {
+			productPhoto := entity.ProductPhoto{
+				PhotoUrl:  photo.PhotoUrl,
+				PhotoUid:  photo.PhotoUid,
+				Symbol:    photo.Symbol,
+				ProductID: productID,
+				CreatedAt: time.Time{},
+			}
+			productPhotos = append(productPhotos, productPhoto)
+		}
+		err = dao.ProductPhotoDAO{}.CreateProductPhoto(productPhotos)
+		if err != nil {
+			return 0, err
+		}
+	}
+	return productID, nil
+}

+ 524 - 0
app/service/project_service.go

@@ -0,0 +1,524 @@
+package service
+
+import (
+	"encoding/json"
+	"errors"
+	"github.com/issue9/conv"
+	"github.com/sirupsen/logrus"
+	"reflect"
+	"time"
+	"youngee_b_api/app/dao"
+	"youngee_b_api/app/entity"
+	"youngee_b_api/app/util"
+	"youngee_b_api/app/vo"
+)
+
+type ProjectService struct{}
+
+// 创建种草任务
+func (s ProjectService) CreateProject(param *vo.ProjectCreateParam) (*string, error) {
+	// a) 生成种草项目id
+	projectId := util.GetProjectID()
+	// b) 查找关联商品信息
+	product, err := dao.ProductDAO{}.GetProductByID(conv.MustInt64(param.ProductId, 0))
+	if err != nil {
+		return nil, err
+	}
+	if product == nil {
+		return nil, errors.New("未找到关联商品")
+	}
+	productPhotos, err := dao.ProductPhotoDAO{}.GetProductPhotoByProductID(param.ProductId)
+	productInfoToJson, _ := json.Marshal(product)
+	productPhotosToJson, _ := json.Marshal(productPhotos)
+	// d)创建种草任务
+	var operatorType int64
+	if param.SubAccountId == 0 {
+		operatorType = 1
+	} else {
+		operatorType = 2
+	}
+	t := time.Now()
+	newProject := entity.Project{
+		ProjectStatus:    1,
+		ProjectType:      param.ProjectType,
+		ProjectId:        projectId,
+		ProductID:        param.ProductId,
+		EnterpriseID:     param.EnterpriseId,
+		SubAccountId:     param.SubAccountId,
+		ProjectPlatform:  param.Platform,
+		OperatorType:     operatorType,
+		ProductSnap:      string(productInfoToJson),
+		ProductPhotoSnap: string(productPhotosToJson),
+		CreatedAt:        t,
+	}
+	if param.ProjectType == 1 {
+		newProject.ServiceChargeRate = param.ServiceChargeRate
+	}
+	err = dao.ProjectDAO{}.CreateProject(newProject)
+	if err != nil {
+		return nil, err
+	}
+
+	return &projectId, nil
+}
+
+// 更新公开种草任务(招募要求、执行要求)
+func (s ProjectService) UpdateProject(projectUpdateParam *vo.ProjectUpdateParam) (*string, error) {
+	// 1. 检查该企业id和商品id有无种草任务
+	projectID := projectUpdateParam.ProjectID
+	project, err := dao.ProjectDAO{}.GetProjectById(projectID)
+	if err != nil {
+		return nil, err
+	}
+	if project == nil {
+		return nil, errors.New("种草项目不存在")
+	}
+	println("更新公开种草任务的招募策略")
+	// 更新公开种草任务的招募策略
+	var totalRecruitNum int64
+	if projectUpdateParam.RecruitStrategys != nil {
+		// 1. 删除已有的招募策略
+		err = dao.RecruitStrategyDao{}.DeleteRecruitStrategyByProjectID(projectUpdateParam.ProjectID)
+		if err != nil {
+			return nil, err
+		}
+		// 2. 接收并创建新的招募策略
+		if len(projectUpdateParam.RecruitStrategys) != 0 {
+			var recruits []entity.RecruitStrategy
+			for _, strategy := range projectUpdateParam.RecruitStrategys {
+				recruitStrategy := entity.RecruitStrategy{
+					FeeForm:       strategy.FeeForm,
+					StrategyID:    strategy.StrategyID,
+					FollowersLow:  strategy.FollowersLow,
+					FollowersUp:   strategy.FollowersUp,
+					RecruitNumber: strategy.RecruitNumber,
+					ProjectID:     project.ProjectId,
+				}
+				totalRecruitNum += strategy.RecruitNumber
+				if strategy.FeeForm == 2 {
+					recruitStrategy.Offer = strategy.Offer
+					recruitStrategy.ServiceCharge = strategy.Offer * projectUpdateParam.ServiceChargeRate
+					recruitStrategy.TOffer = strategy.Offer * (1 - projectUpdateParam.ServiceChargeRate)
+				}
+				recruits = append(recruits, recruitStrategy)
+			}
+			err = dao.RecruitStrategyDao{}.CreateRecruitStrategy(recruits)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+	// 2. 数据准备
+	// a) 查找关联商品信息
+	product, err := dao.ProductDAO{}.GetProductByID(project.ProductID)
+	if err != nil {
+		return nil, err
+	}
+	productPhotos, err := dao.ProductPhotoDAO{}.GetProductPhotoByProductID(project.ProductID)
+	productInfoToJson, _ := json.Marshal(product)
+	productPhotosToJson, _ := json.Marshal(productPhotos)
+	// d) 任务截止时间
+	recruitDdl := time.Time{} //赋零值
+	recruitDdl, _ = time.ParseInLocation("2006-01-02 15:04:05", projectUpdateParam.RecruitDdl, time.Local)
+	// f) 更新选品状态
+	if projectUpdateParam.ProjectStatus != 2 && projectUpdateParam.ProjectStatus != 8 {
+		projectUpdateParam.ProjectStatus = 1
+	}
+	t := time.Now()
+	updateProject := entity.Project{
+		EnterpriseID:     projectUpdateParam.EnterpriseId,
+		SubAccountId:     projectUpdateParam.SubAccountId,
+		ProjectId:        projectUpdateParam.ProjectID,
+		ProjectType:      projectUpdateParam.ProjectType,
+		ProjectStatus:    projectUpdateParam.ProjectStatus,
+		ProjectName:      projectUpdateParam.ProjectName,
+		ProductID:        projectUpdateParam.ProductId,
+		TalentType:       projectUpdateParam.TalentType,
+		RecruitDdl:       recruitDdl,
+		ProductSnap:      string(productInfoToJson),
+		ProductPhotoSnap: string(productPhotosToJson),
+		UpdatedAt:        t,
+		ProjectForm:      projectUpdateParam.ProjectForm,
+		ContentType:      projectUpdateParam.ContentType,
+		ProjectDetail:    projectUpdateParam.ProjectDetail,
+	}
+	if projectUpdateParam.ProjectStatus == 2 {
+		updateProject.SubmitAt = t
+	}
+	// 合并传入参数和数据表中原记录,若传入参数字段值为空,则将字段赋值为原记录中值
+	result := util.MergeStructValue(&updateProject, project)
+	// 利用反射机制将interface类型转换为结构体类型
+	v := reflect.ValueOf(&result).Elem()
+	if v.Kind() == reflect.Struct {
+		updateProject = v.Interface().(entity.Project)
+		//fmt.Println(p)
+	}
+	// c) 计算预估成本(如果有)
+	/*
+		var estimatedCost float64
+		if conv.MustInt(updateSelection.TaskMode, 0) == 1 {
+			estimatedCost = conv.MustFloat64(updateSelection.TaskReward, 0) * conv.MustFloat64(updateSelection.SampleNum, 0)
+		}
+		estimatedCostToString, _ := conv.String(estimatedCost)
+		updateSelection.EstimatedCost = estimatedCostToString
+	*/
+	// 3. 更新选品
+	err = dao.ProjectDAO{}.UpdateProject(updateProject)
+	if err != nil {
+		return nil, err
+	}
+	// 4. 更新选品brief和示例(种草任务补充信息)
+	if projectUpdateParam.ProjectBrief != nil {
+		// 删除已有brief
+		err = dao.ProjectBriefDao{}.DeleteSecBriefBySelectionId(project.ProjectId)
+		if err != nil {
+			return nil, err
+		}
+		// 插入新的brief
+		for _, v := range projectUpdateParam.ProjectBrief {
+			brief := entity.ProjectBrief{
+				ProjectID: project.ProjectId,
+				FileUid:   v.FileUid,
+				FileName:  v.Name,
+				FileUrl:   v.FileUrl,
+				CreatedAt: time.Now(),
+			}
+			err = dao.ProjectBriefDao{}.CreateProjectBrief(brief)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	if projectUpdateParam.ProjectMaterial != nil {
+		// 删除已有示例
+		err = dao.ProjectMaterialDao{}.DeleteProjectMaterialByProjectId(project.ProjectId)
+		if err != nil {
+			return nil, err
+		}
+		// 插入新的示例
+		for _, v := range projectUpdateParam.ProjectMaterial {
+			projectMaterial := entity.ProjectMaterial{
+				ProjectID: project.ProjectId,
+				FileUid:   v.FileUid,
+				FileName:  v.Name,
+				FileUrl:   v.FileUrl,
+				CreatedAt: time.Now(),
+			}
+			err = dao.ProjectMaterialDao{}.CreateProjectMaterial(projectMaterial)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	return &updateProject.ProjectId, nil
+}
+
+// 更新定向种草任务(招募要求、执行要求)
+func (s ProjectService) UpdateProjectTarget(projectUpdateParam *vo.ProjectUpdateParam) (*string, error) {
+	// 1. 检查该企业id和商品id有无种草任务
+	projectID := projectUpdateParam.ProjectID
+	project, err := dao.ProjectDAO{}.GetProjectById(projectID)
+	if err != nil {
+		return nil, err
+	}
+	if project == nil {
+		return nil, errors.New("种草项目不存在")
+	}
+	println("更新定向种草任务的招募策略")
+	// 更新定向种草任务的招募策略
+	var totalRecruitNum int64
+	if projectUpdateParam.RecruitStrategys != nil {
+		// 1. 删除已有的招募策略
+		err = dao.RecruitStrategyDao{}.DeleteRecruitStrategyByProjectID(projectUpdateParam.ProjectID)
+		if err != nil {
+			return nil, err
+		}
+		// 2. 接收并创建新的招募策略
+		if len(projectUpdateParam.RecruitStrategys) != 0 {
+			var recruits []entity.RecruitStrategy
+			for _, strategy := range projectUpdateParam.RecruitStrategys {
+				recruitStrategy := entity.RecruitStrategy{
+					FeeForm:       strategy.FeeForm,
+					StrategyID:    strategy.StrategyID,
+					FollowersLow:  strategy.FollowersLow,
+					FollowersUp:   strategy.FollowersUp,
+					RecruitNumber: strategy.RecruitNumber,
+					ProjectID:     project.ProjectId,
+				}
+				totalRecruitNum += strategy.RecruitNumber
+				if strategy.FeeForm == 2 {
+					recruitStrategy.Offer = strategy.Offer // 报价
+				}
+				recruits = append(recruits, recruitStrategy)
+			}
+			err = dao.RecruitStrategyDao{}.CreateRecruitStrategy(recruits)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+	// 2. 数据准备
+	// a) 查找关联商品信息
+	product, err := dao.ProductDAO{}.GetProductByID(project.ProductID)
+	if err != nil {
+		return nil, err
+	}
+	productPhotos, err := dao.ProductPhotoDAO{}.GetProductPhotoByProductID(project.ProductID)
+	productInfoToJson, _ := json.Marshal(product)
+	productPhotosToJson, _ := json.Marshal(productPhotos)
+	// d) 任务截止时间
+	recruitDdl := time.Time{} //赋零值
+	recruitDdl, _ = time.ParseInLocation("2006-01-02 15:04:05", projectUpdateParam.RecruitDdl, time.Local)
+	// f) 更新选品状态
+	if projectUpdateParam.ProjectStatus != 2 && projectUpdateParam.ProjectStatus != 8 {
+		projectUpdateParam.ProjectStatus = 1
+	}
+	t := time.Now()
+	updateProject := entity.Project{
+		EnterpriseID:     projectUpdateParam.EnterpriseId,
+		SubAccountId:     projectUpdateParam.SubAccountId,
+		ProjectId:        projectUpdateParam.ProjectID,
+		ProjectType:      projectUpdateParam.ProjectType,
+		ProjectStatus:    projectUpdateParam.ProjectStatus,
+		ProjectName:      projectUpdateParam.ProjectName,
+		ProductID:        projectUpdateParam.ProductId,
+		TalentType:       projectUpdateParam.TalentType,
+		RecruitDdl:       recruitDdl,
+		ProductSnap:      string(productInfoToJson),
+		ProductPhotoSnap: string(productPhotosToJson),
+		CreatedAt:        project.CreatedAt,
+		UpdatedAt:        t,
+		ProjectForm:      projectUpdateParam.ProjectForm,
+		ContentType:      projectUpdateParam.ContentType,
+		ProjectDetail:    projectUpdateParam.ProjectDetail,
+		Tools:            projectUpdateParam.Tools,
+	}
+	if projectUpdateParam.ProjectStatus == 2 {
+		updateProject.SubmitAt = t
+	}
+	// 合并传入参数和数据表中原记录,若传入参数字段值为空,则将字段赋值为原记录中值
+	result := util.MergeStructValue(&updateProject, project)
+	// 利用反射机制将interface类型转换为结构体类型
+	v := reflect.ValueOf(&result).Elem()
+	if v.Kind() == reflect.Struct {
+		updateProject = v.Interface().(entity.Project)
+		//fmt.Println(p)
+	}
+	// c) 计算预估成本(如果有)
+	/*
+		var estimatedCost float64
+		if conv.MustInt(updateSelection.TaskMode, 0) == 1 {
+			estimatedCost = conv.MustFloat64(updateSelection.TaskReward, 0) * conv.MustFloat64(updateSelection.SampleNum, 0)
+		}
+		estimatedCostToString, _ := conv.String(estimatedCost)
+		updateSelection.EstimatedCost = estimatedCostToString
+	*/
+	// 3. 更新选品
+	err = dao.ProjectDAO{}.UpdateProject(updateProject)
+	if err != nil {
+		return nil, err
+	}
+	// 4. 更新选品brief和示例(种草任务补充信息)
+	if projectUpdateParam.ProjectBrief != nil {
+		// 删除已有brief
+		err = dao.ProjectBriefDao{}.DeleteSecBriefBySelectionId(project.ProjectId)
+		if err != nil {
+			return nil, err
+		}
+		// 插入新的brief
+		for _, v := range projectUpdateParam.ProjectBrief {
+			brief := entity.ProjectBrief{
+				ProjectID: project.ProjectId,
+				FileUid:   v.FileUid,
+				FileName:  v.Name,
+				FileUrl:   v.FileUrl,
+				CreatedAt: time.Now(),
+			}
+			err = dao.ProjectBriefDao{}.CreateProjectBrief(brief)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+	if projectUpdateParam.ProjectMaterial != nil {
+		// 删除已有示例
+		err = dao.ProjectMaterialDao{}.DeleteProjectMaterialByProjectId(project.ProjectId)
+		if err != nil {
+			return nil, err
+		}
+		// 插入新的示例
+		for _, v := range projectUpdateParam.ProjectMaterial {
+			projectMaterial := entity.ProjectMaterial{
+				ProjectID: project.ProjectId,
+				FileUid:   v.FileUid,
+				FileName:  v.Name,
+				FileUrl:   v.FileUrl,
+				CreatedAt: time.Now(),
+			}
+			err = dao.ProjectMaterialDao{}.CreateProjectMaterial(projectMaterial)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	return &updateProject.ProjectId, nil
+}
+
+// 种草任务预览
+func (s ProjectService) GetProjectDetail(projectId string) (*vo.ReProjectDetail, error) {
+	reProjectDetail := vo.ReProjectDetail{}
+	project, err := dao.ProjectDAO{}.GetProjectById(projectId)
+	if err != nil {
+		logrus.Errorf("[projectDB service] call GetProject error,err:%+v", err)
+		return nil, err
+	}
+	// 系统信息
+	reProjectDetail.ProjectId = projectId
+	reProjectDetail.ProjectStatus = project.ProjectStatus
+	reProjectDetail.ProjectPlatform = project.ProjectPlatform
+	reProjectDetail.CreatedAt = project.CreatedAt
+	reProjectDetail.EstimatedCost = project.EstimatedCost
+	reProjectDetail.ServiceChargeRate = project.ServiceChargeRate
+	var creatorName, phone string
+	if project.SubAccountId == 0 {
+		enterprise, err := dao.EnterpriseDao{}.GetEnterprise(project.EnterpriseID)
+		if err == nil && enterprise != nil {
+			creatorName = enterprise.BusinessName
+			phone, err = dao.UserDao{}.GetPhoneByUserId(enterprise.UserId)
+		}
+	} else {
+		subAccount, err := dao.SubAccountDao{}.GetSubAccount(project.SubAccountId)
+		if err == nil && subAccount != nil {
+			creatorName = subAccount.SubAccountName
+			phone, err = dao.UserDao{}.GetPhoneByUserId(subAccount.UserId)
+		}
+	}
+	reProjectDetail.CreatorName = creatorName
+	reProjectDetail.Phone = phone
+	// 关联商品
+	var reProduct vo.ReTaskProduct
+	product, err := dao.ProductDAO{}.GetProductByID(project.ProductID)
+	if err == nil {
+		photoUrl, e := dao.ProductPhotoDAO{}.GetMainPhotoByProductID(product.ProductID)
+		if e != nil {
+			photoUrl = ""
+		}
+		reProduct = vo.ReTaskProduct{
+			ProductID:       product.ProductID,
+			ProductName:     product.ProductName,
+			ProductType:     product.ProductType,
+			ProductCategory: product.ProductCategory,
+			ProductPrice:    product.ProductPrice,
+			ProductDetail:   product.ProductDetail,
+			CreatedAt:       product.CreatedAt,
+			PhotoUrl:        photoUrl,
+		}
+	}
+	reProjectDetail.ProductInfo = &reProduct
+	// 招募要求
+	reProjectDetail.TalentType = project.TalentType
+	reProjectDetail.RecruitDdl = project.RecruitDdl
+	reProjectDetail.ProjectForm = project.ProjectForm
+	reProjectDetail.ContentType = project.ContentType
+	reProjectDetail.ProjectDetail = project.ProjectDetail
+	var recruitStrategysPreviews []*vo.RecruitStrategyPreview
+	recruitStrategys, err := dao.RecruitStrategyDao{}.GetRecruitStrategyByProjectId(projectId)
+	if err != nil {
+		logrus.Errorf("[projectDB service] call GetRecruitStrategy error,err:%+v", err)
+		return nil, err
+	}
+	for _, recruitStrategy := range recruitStrategys {
+		recruitStrategysPreview := &vo.RecruitStrategyPreview{
+			StrategyId:     recruitStrategy.StrategyID,
+			FeeForm:        recruitStrategy.FeeForm,
+			FollowersLow:   recruitStrategy.FollowersLow,
+			FollowersUp:    recruitStrategy.FollowersUp,
+			RecruitNumber:  recruitStrategy.RecruitNumber,
+			Offer:          recruitStrategy.Offer,
+			TOffer:         recruitStrategy.TOffer,
+			ServiceCharge:  recruitStrategy.ServiceCharge,
+			SelectedNumber: recruitStrategy.SelectedNumber,
+			TotalOffer:     recruitStrategy.TotalOffer,
+		}
+		recruitStrategysPreviews = append(recruitStrategysPreviews, recruitStrategysPreview)
+	}
+	reProjectDetail.RecruitStrategys = recruitStrategysPreviews
+	// 执行要求
+	projectBriefInfos, err := dao.ProjectBriefDao{}.GetProjectBriefInfo(projectId)
+	if err != nil {
+		logrus.Errorf("[projectDB service] call GetProjectBriefInfo error,err:%+v", err)
+		return nil, err
+	}
+	projectMaterials, err := dao.ProjectMaterialDao{}.GetProjectMaterialInfo(projectId)
+	if err != nil {
+		logrus.Errorf("[projectDB service] call GetprojectMaterialInfo error,err:%+v", err)
+		return nil, err
+	}
+	reProjectDetail.ProjectBriefs = projectBriefInfos
+	reProjectDetail.ProjectMaterials = projectMaterials
+	reProjectDetail.Tools = project.Tools
+
+	return &reProjectDetail, nil
+}
+
+// 公开种草任务列表
+func (s ProjectService) GetProjectTaskList(param *vo.ProjectSearchParam) (vo.ResultVO, error) {
+	if param.Page == 0 {
+		param.Page = 1
+	}
+	if param.PageSize == 0 {
+		param.PageSize = 10
+	}
+	var result vo.ResultVO
+	reProjectTaskPreviews, total, err := (&dao.ProjectDAO{}).GetProjectPreviews(param)
+	if err != nil {
+		return result, err
+	}
+	for i := range reProjectTaskPreviews {
+		var creatorName string
+		var productName string
+		var productPrice float64
+		var mainImage string
+		if reProjectTaskPreviews[i].SubAccountId == 0 {
+			enterprise, err := dao.EnterpriseDao{}.GetEnterprise(reProjectTaskPreviews[i].EnterpriseId)
+			if err == nil && enterprise != nil {
+				creatorName = enterprise.BusinessName
+			}
+		} else {
+			subAccount, err := dao.SubAccountDao{}.GetSubAccount(reProjectTaskPreviews[i].SubAccountId)
+			if err == nil && subAccount != nil {
+				creatorName = subAccount.SubAccountName
+			}
+		}
+		product, err := dao.ProductDAO{}.GetProductByID(reProjectTaskPreviews[i].ProductId)
+		if err == nil && product != nil {
+			productName = product.ProductName
+			productPrice = product.ProductPrice
+		}
+		mainImage, err = dao.ProductPhotoDAO{}.GetMainPhotoByProductID(reProjectTaskPreviews[i].ProductId)
+		reProjectTaskPreviews[i].CreatorName = creatorName
+		reProjectTaskPreviews[i].ProductName = productName
+		reProjectTaskPreviews[i].ProductPrice = productPrice
+		reProjectTaskPreviews[i].MainImage = mainImage
+	}
+	result = vo.ResultVO{
+		Page:     param.Page,
+		PageSize: param.PageSize,
+		Total:    total,
+		Data:     reProjectTaskPreviews,
+	}
+	return result, nil
+}
+
+// 删除种草任务
+func (s ProjectService) DeleteProject(projectId string) (*string, error) {
+	res, err := dao.ProjectDAO{}.DeleteProject(projectId)
+	if err != nil {
+		logrus.Errorf("[projectDB service] call DeleteProject error,err:%+v", err)
+		return res, err
+	}
+	return res, nil
+}

+ 41 - 0
app/service/review_service/config.go

@@ -0,0 +1,41 @@
+package review_service
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
+	moderation "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/moderation/v3"
+	moderationRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/moderation/v3/region"
+	ocr "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ocr/v1"
+	ocrRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ocr/v1/region"
+)
+
+type ReviewService struct {
+	client    *moderation.ModerationClient
+	ocrClient *ocr.OcrClient
+	projectId string
+}
+
+func Config(ak, sk, projectId string) *ReviewService {
+	auth := basic.NewCredentialsBuilder().
+		WithAk(ak).
+		WithSk(sk).
+		//WithProjectId(projectId).
+		Build()
+
+	client := moderation.NewModerationClient(
+		moderation.ModerationClientBuilder().
+			WithRegion(moderationRegion.ValueOf("cn-north-4")).
+			WithCredential(auth).
+			Build())
+
+	ocrClient := ocr.NewOcrClient(
+		ocr.OcrClientBuilder().
+			WithRegion(ocrRegion.ValueOf("cn-north-4")).
+			WithCredential(auth).
+			Build())
+
+	return &ReviewService{
+		client:    client,
+		ocrClient: ocrClient,
+		projectId: projectId,
+	}
+}

+ 38 - 0
app/service/review_service/content_check.go

@@ -0,0 +1,38 @@
+package review_service
+
+import (
+	"encoding/json"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/moderation/v3/model"
+)
+
+/*
+result.suggestion:
+
+	block:包含敏感信息,不通过
+	review:需要人工复检
+	pass:不包含敏感信息,通过
+*/
+func (s *ReviewService) CheckContent(text string) (string, error) {
+	request := &model.RunTextModerationRequest{}
+	request.EnterpriseProjectId = &s.projectId
+	eventType := "article"
+	listCategoriesbody := []string{
+		"terrorism", "porn", "ban", "abuse",
+	}
+	databody := model.TextDetectionDataReq{
+		Text: text,
+	}
+	request.Body = &model.TextDetectionReq{
+		Data:       &databody,
+		EventType:  &eventType,
+		Categories: &listCategoriesbody,
+	}
+	response, err := s.client.RunTextModeration(request)
+	if err != nil {
+		return "文本审核服务异常", err
+	}
+	result := response.Result
+	jsonData, err := json.Marshal(result)
+	jsonString := string(jsonData)
+	return jsonString, nil
+}

+ 36 - 0
app/service/review_service/credentials_check.go

@@ -0,0 +1,36 @@
+package review_service
+
+import (
+	"encoding/json"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ocr/v1/model"
+)
+
+func (s *ReviewService) CheckCredentials(credentialsUrl string) (string, error) {
+	request := &model.RecognizeBusinessLicenseRequest{}
+	request.Body = &model.BusinessLicenseRequestBody{
+		Url: &credentialsUrl,
+	}
+	response, err := s.ocrClient.RecognizeBusinessLicense(request)
+	if err != nil {
+		//if err.StatusCode == 400 {
+		//	return "false", err
+		//}
+		return "营业执照审核服务异常", err
+	}
+	result := response.Result
+	jsonData, err := json.Marshal(result)
+	jsonString := string(jsonData)
+	return jsonString, nil
+
+	//request := &model.CheckImageModerationRequest{}
+	//listCategoriesbody := []string{
+	//	"terrorism", "porn",
+	//}
+	//eventType := "head_image"
+	//request.Body = &model.ImageDetectionReq{
+	//	Url:        &imageUrl,
+	//	Categories: &listCategoriesbody,
+	//	EventType:  &eventType,
+	//}
+
+}

+ 23 - 0
app/service/review_service/document_check.go

@@ -0,0 +1,23 @@
+package review_service
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/moderation/v3/model"
+)
+
+func (s *ReviewService) CheckDocument(documentUrl, format string) (string, error) {
+	request := &model.RunCreateDocumentModerationJobRequest{}
+	databody := &model.DocumentCreateRequestData{
+		Url:    documentUrl,
+		Format: format,
+	}
+	request.Body = &model.DocumentCreateRequest{
+		EventType: "default",
+		Data:      databody,
+	}
+	response, err := s.client.RunCreateDocumentModerationJob(request)
+	if err != nil {
+		return "文档审核服务异常", err
+	}
+	jobId := *response.JobId
+	return jobId, nil
+}

+ 23 - 0
app/service/review_service/document_check_info.go

@@ -0,0 +1,23 @@
+package review_service
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/moderation/v3/model"
+)
+
+/*
+result.suggestion:
+
+	block:包含敏感信息,不通过
+	review:需要人工复检
+	pass:不包含敏感信息,通过
+*/
+func (s *ReviewService) CheckDocumentInfo(jobId string) (*model.DocumentQueryResponseResult, error) {
+	request := &model.RunQueryDocumentModerationJobRequest{}
+	request.JobId = jobId
+	response, err := s.client.RunQueryDocumentModerationJob(request)
+	if err != nil {
+		return nil, err
+	}
+	result := response.Result
+	return result, nil // 审核结果,当作业状态status为succeeded时存在。
+}

+ 34 - 0
app/service/review_service/image_check.go

@@ -0,0 +1,34 @@
+package review_service
+
+import (
+	"encoding/json"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/moderation/v3/model"
+)
+
+/*
+result.suggestion:
+
+	block:包含敏感信息,不通过
+	review:需要人工复检
+	pass:不包含敏感信息,通过
+*/
+func (s *ReviewService) CheckImage(imageUrl string) (string, error) {
+	request := &model.CheckImageModerationRequest{}
+	listCategoriesbody := []string{
+		"terrorism", "porn",
+	}
+	eventType := "head_image"
+	request.Body = &model.ImageDetectionReq{
+		Url:        &imageUrl,
+		Categories: &listCategoriesbody,
+		EventType:  &eventType,
+	}
+	response, err := s.client.CheckImageModeration(request)
+	if err != nil {
+		return "图片审核服务异常", err
+	}
+	result := response.Result
+	jsonData, err := json.Marshal(result)
+	jsonString := string(jsonData)
+	return jsonString, nil
+}

+ 35 - 0
app/service/review_service/video_check.go

@@ -0,0 +1,35 @@
+package review_service
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/moderation/v3/model"
+)
+
+func (s *ReviewService) CheckVideo(videoUrl string) (string, error) {
+	request := &model.RunCreateVideoModerationJobRequest{}
+	var listAudioCategoriesbody = []model.VideoCreateRequestAudioCategories{
+		model.GetVideoCreateRequestAudioCategoriesEnum().PORN, model.GetVideoCreateRequestAudioCategoriesEnum().MOAN, model.GetVideoCreateRequestAudioCategoriesEnum().ABUSE,
+	}
+	var listImageCategoriesbody = []model.VideoCreateRequestImageCategories{
+		model.GetVideoCreateRequestImageCategoriesEnum().PORN, model.GetVideoCreateRequestImageCategoriesEnum().TERRORISM,
+	}
+	var eventType = model.GetVideoCreateRequestEventTypeEnum().DEFAULT
+	frameIntervalData := int32(2)
+	databody := &model.VideoCreateRequestData{
+		Url:           videoUrl,
+		FrameInterval: &frameIntervalData, // 截帧频率间隔
+	}
+	//callbackVideoCreateRequest := "http://xxx.xx.xxxx"
+	request.Body = &model.VideoCreateRequest{
+		AudioCategories: &listAudioCategoriesbody, // 视频中音频需要检测的风险类型
+		ImageCategories: &listImageCategoriesbody, // 视频中画面需要检测的风险类型
+		EventType:       &eventType,
+		Data:            databody,
+		//Callback:        &callbackVideoCreateRequest,
+	}
+	response, err := s.client.RunCreateVideoModerationJob(request)
+	if err != nil {
+		return "视频审核服务异常", err
+	}
+	jobId := *response.JobId
+	return jobId, nil
+}

+ 23 - 0
app/service/review_service/video_check_info.go

@@ -0,0 +1,23 @@
+package review_service
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/moderation/v3/model"
+)
+
+/*
+result.suggestion:
+
+	block:包含敏感信息,不通过
+	review:需要人工复检
+	pass:不包含敏感信息,通过
+*/
+func (s *ReviewService) CheckVideoInfo(jobId string) (*model.VideoModerationResultResult, error) {
+	request := &model.RunQueryVideoModerationJobRequest{}
+	request.JobId = jobId
+	response, err := s.client.RunQueryVideoModerationJob(request)
+	if err != nil {
+		return nil, err
+	}
+	result := response.Result
+	return result, nil // 审核结果,当作业状态status为succeeded时存在。
+}

+ 466 - 0
app/service/selection_info_service.go

@@ -0,0 +1,466 @@
+package service
+
+import (
+	"encoding/json"
+	"errors"
+	"github.com/caixw/lib.go/conv"
+	"github.com/sirupsen/logrus"
+	"reflect"
+	"time"
+	"youngee_b_api/app/dao"
+	"youngee_b_api/app/entity"
+	"youngee_b_api/app/util"
+	"youngee_b_api/app/vo"
+)
+
+type SelectionInfoService struct{}
+
+//func (s *SelectionInfoService) GetSelectionInfo(ctx *gin.Context, selectionId string) (*http_model.SelectionDetail, error) {
+//	selectionDetail := http_model.SelectionDetail{}
+//	selectionInfo, err := db.GetSelectionById(ctx, selectionId)
+//
+//	if err != nil {
+//		logrus.WithContext(ctx).Errorf("[selectionDB service] call GetSelectionInfo error,err:%+v", err)
+//		return nil, err
+//	}
+//	selectionBriefInfo, err := db.GetSelectionBriefInfo(ctx, selectionId)
+//	if err != nil {
+//		logrus.WithContext(ctx).Errorf("[selectionDB service] call GetSelectionBriefInfo error,err:%+v", err)
+//		return nil, err
+//	}
+//	selectionExampleInfo, err := db.GetSelectionExampleInfo(ctx, selectionId)
+//	if err != nil {
+//		logrus.WithContext(ctx).Errorf("[selectionDB service] call GetSelectionExampleInfo error,err:%+v", err)
+//		return nil, err
+//	}
+//	productInfo, err := db.GetProductInfoBySelectionId(ctx, selectionId)
+//	if err != nil {
+//		logrus.WithContext(ctx).Errorf("[selectionDB service] call GetProductInfo error,err:%+v", err)
+//		return nil, err
+//	}
+//	productPhotoInfo, err := db.GetProductPhotoInfoBySelectionId(ctx, selectionId)
+//	if err != nil {
+//		logrus.WithContext(ctx).Errorf("[selectionDB service] call GetProductPhotoInfo error,err:%+v", err)
+//		return nil, err
+//	}
+//	selectionDetail.SelectionBrief = selectionBriefInfo
+//	selectionDetail.SelectionInfo = selectionInfo
+//	selectionDetail.SelectionExample = selectionExampleInfo
+//	selectionDetail.ProductInfo = productInfo
+//	selectionDetail.ProductPhotoInfo = productPhotoInfo
+//	return &selectionDetail, nil
+//}
+
+// 创建带货任务
+func (s SelectionInfoService) CreateSelectionInfo(param *vo.SelectionInfoCreateParam) (*string, error) {
+	// a) 生成选品id
+	selectionId := util.GetSelectionID()
+	// b) 查找关联商品信息
+	product, err := dao.ProductDAO{}.GetProductByID(conv.MustInt64(param.ProductId, 0))
+	if err != nil {
+		return nil, err
+	}
+	if product == nil {
+		return nil, errors.New("未找到关联商品")
+	}
+	productPhotos, err := dao.ProductPhotoDAO{}.GetProductPhotoByProductID(param.ProductId)
+	productInfoToJson, _ := json.Marshal(product)
+	productPhotosToJson, _ := json.Marshal(productPhotos)
+	// c) 选品名称
+	//selectionName := product.ProductName
+	// d)创建选品
+	t := time.Now()
+	newSelection := entity.SelectionInfo{
+		SelectionStatus:  1,
+		SelectionID:      selectionId,
+		ProductID:        param.ProductId,
+		EnterpriseID:     param.EnterpriseId,
+		SubAccountId:     param.SubAccountId,
+		Platform:         param.Platform,
+		ProductSnap:      string(productInfoToJson),
+		ProductPhotoSnap: string(productPhotosToJson),
+		CreatedAt:        t,
+		UpdatedAt:        t,
+		CommissionRate:   0,
+		EstimatedCost:    0,
+		TaskReward:       0,
+		SettlementAmount: 0,
+	}
+	err = dao.SelectionInfoDAO{}.CreateSelectionInfo(newSelection)
+	if err != nil {
+		return nil, err
+	}
+
+	return &selectionId, nil
+}
+
+// 更新带货任务(样品奖励、补充信息)
+func (s SelectionInfoService) UpdateSelectionInfo(selectionUpdateParam *vo.SelectionInfoUpdateParam) (*string, error) {
+	// 1. 检查该企业id和商品id有无选品
+	selectionID := selectionUpdateParam.SelectionID
+	selectionInfo, err := dao.SelectionInfoDAO{}.GetSelectionInfoById(selectionID)
+	if err != nil {
+		return nil, err
+	}
+	if selectionInfo == nil {
+		return nil, errors.New("选品不存在")
+	}
+	// 2. 数据准备
+	// a) 查找关联商品信息
+	product, err := dao.ProductDAO{}.GetProductByID(selectionInfo.ProductID)
+	if err != nil {
+		return nil, err
+	}
+	productPhotos, err := dao.ProductPhotoDAO{}.GetProductPhotoByProductID(selectionInfo.ProductID)
+	productInfoToJson, _ := json.Marshal(product)
+	productPhotosToJson, _ := json.Marshal(productPhotos)
+	// d) 任务截止时间
+	taskDdl := time.Time{} //赋零值
+	taskDdl, _ = time.ParseInLocation("2006-01-02 15:04:05", selectionUpdateParam.TaskDdl, time.Local)
+	// f) 更新选品状态
+	if selectionUpdateParam.SelectionStatus != 2 && selectionUpdateParam.SelectionStatus != 7 {
+		selectionUpdateParam.SelectionStatus = 1
+	}
+	t := time.Now()
+	var sampleMode, taskMode int64
+	if len(selectionUpdateParam.FreeStrategys) > 0 {
+		sampleMode = 1
+	} else {
+		sampleMode = 3
+	}
+	if len(selectionUpdateParam.RewardStrategys) > 0 {
+		taskMode = 1
+	} else {
+		taskMode = 2
+	}
+	updateSelection := entity.SelectionInfo{
+		SelectionID:      selectionUpdateParam.SelectionID,
+		SelectionStatus:  selectionUpdateParam.SelectionStatus,
+		SelectionName:    selectionUpdateParam.SelectionName,
+		EnterpriseID:     selectionUpdateParam.EnterpriseId,
+		SubAccountId:     selectionUpdateParam.SubAccountId,
+		ProductID:        selectionUpdateParam.ProductId,
+		ProductUrl:       selectionUpdateParam.ProductUrl,
+		TaskMode:         taskMode,
+		SampleMode:       sampleMode,
+		SampleNum:        selectionUpdateParam.SampleNum,
+		RemainNum:        selectionUpdateParam.SampleNum,
+		CommissionRate:   selectionUpdateParam.CommissionRate,
+		TaskReward:       selectionUpdateParam.TaskReward,
+		SettlementAmount: selectionUpdateParam.SettlementAmount,
+		EstimatedCost:    selectionInfo.EstimatedCost,
+		SampleCondition:  selectionUpdateParam.SampleCondition,
+		RewardCondition:  selectionUpdateParam.RewardCondition,
+		TaskDdl:          taskDdl,
+		Detail:           selectionUpdateParam.Detail,
+		ProductSnap:      string(productInfoToJson),
+		ProductPhotoSnap: string(productPhotosToJson),
+		CreatedAt:        selectionInfo.CreatedAt,
+		UpdatedAt:        t,
+	}
+	if selectionUpdateParam.SelectionStatus == 2 {
+		updateSelection.SubmitAt = t
+	}
+	if selectionUpdateParam.Status == 1 {
+		updateSelection.Status = 1
+	}
+	// 合并传入参数和数据表中原记录,若传入参数字段值为空,则将字段赋值为原记录中值
+	result := util.MergeStructValue(&updateSelection, selectionInfo)
+	// 利用反射机制将interface类型转换为结构体类型
+	v := reflect.ValueOf(&result).Elem()
+	if v.Kind() == reflect.Struct {
+		updateSelection = v.Interface().(entity.SelectionInfo)
+		//fmt.Println(p)
+	}
+	// c) 计算预估成本(如果有)
+	/*
+		var estimatedCost float64
+		if conv.MustInt(updateSelection.TaskMode, 0) == 1 {
+			estimatedCost = conv.MustFloat64(updateSelection.TaskReward, 0) * conv.MustFloat64(updateSelection.SampleNum, 0)
+		}
+		estimatedCostToString, _ := conv.String(estimatedCost)
+		updateSelection.EstimatedCost = estimatedCostToString
+	*/
+	// 3. 更新选品
+	err = dao.SelectionInfoDAO{}.UpdateSelectionInfo(updateSelection)
+	if err != nil {
+		return nil, err
+	}
+
+	// 4. 更新选品brief和示例(带货任务补充信息)
+	if selectionUpdateParam.SecBrief != nil {
+		// 删除已有brief
+		err = dao.SecBriefDao{}.DeleteSecBriefBySelectionId(selectionInfo.SelectionID)
+		if err != nil {
+			return nil, err
+		}
+		// 插入新的brief
+		for _, v := range selectionUpdateParam.SecBrief {
+			brief := entity.SecBrief{
+				SelectionID: selectionInfo.SelectionID,
+				FileUid:     v.FileUid,
+				FileName:    v.Name,
+				FileUrl:     v.FileUrl,
+				CreatedAt:   time.Now(),
+			}
+			err = dao.SecBriefDao{}.CreateSecBrief(brief)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	if selectionUpdateParam.SecMaterial != nil {
+		// 删除已有示例
+		err = dao.SecMaterialDao{}.DeleteSecMaterialBySelectionId(selectionInfo.SelectionID)
+		if err != nil {
+			return nil, err
+		}
+		// 插入新的示例
+		for _, v := range selectionUpdateParam.SecMaterial {
+			secMaterial := entity.SecMaterial{
+				SelectionID: selectionInfo.SelectionID,
+				FileUid:     v.FileUid,
+				FileName:    v.Name,
+				FileUrl:     v.FileUrl,
+				CreatedAt:   time.Now(),
+			}
+			err = dao.SecMaterialDao{}.CreateSecMaterial(secMaterial)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	println("更新带货任务的免费领样策略")
+	// 更新带货任务的免费领样策略
+	if selectionUpdateParam.FreeStrategys != nil {
+		// 1. 删除已有的免费领样策略
+		err = dao.FreeStrategyDao{}.DeleteFreeStrategyBySelectionId(selectionUpdateParam.SelectionID)
+		if err != nil {
+			return nil, err
+		}
+		// 2. 接收并创建新的免费领样策略
+		if sampleMode == 1 {
+			var frees []entity.FreeStrategy
+			for _, v := range selectionUpdateParam.FreeStrategys {
+				free := entity.FreeStrategy{
+					SelectionId:    selectionInfo.SelectionID,
+					StrategyId:     v.StrategyId,
+					FansNum:        v.FansNum,
+					SaleNum:        v.SaleNum,
+					StrategyStatus: 1,
+					EnrollNum:      0,
+					ChooseNum:      0,
+				}
+				frees = append(frees, free)
+			}
+			err = dao.FreeStrategyDao{}.CreateFreeStrategy(frees)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	println("更新带货任务的悬赏策略")
+	// 更新带货任务的悬赏策略
+	if selectionUpdateParam.RewardStrategys != nil {
+		// 1. 删除已有的悬赏策略
+		err = dao.RewardStrategyDao{}.DeleteRewardStrategyBySelectionId(selectionUpdateParam.SelectionID)
+		if err != nil {
+			return nil, err
+		}
+		if taskMode == 1 {
+			var rewards []entity.RewardStrategy
+			for _, v := range selectionUpdateParam.RewardStrategys {
+				reward := entity.RewardStrategy{
+					SelectionId:    selectionInfo.SelectionID,
+					Reward:         v.Reward,
+					SaleActual:     v.SaleActual,
+					PerReward:      v.PerReward,
+					StrategyStatus: 1,
+				}
+				rewards = append(rewards, reward)
+			}
+			err = dao.RewardStrategyDao{}.CreateRewardStrategy(rewards)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	return &updateSelection.SelectionID, nil
+}
+
+// 电商带货任务预览
+func (s SelectionInfoService) GetSelectionDetail(selectionId string) (*vo.ReSelectionDetail, error) {
+	reSelectionDetail := vo.ReSelectionDetail{}
+	selection, err := dao.SelectionInfoDAO{}.GetSelectionInfoById(selectionId)
+	if err != nil {
+		logrus.Errorf("[selectionInfoDB service] call GetSelection error,err:%+v", err)
+		return nil, err
+	}
+	// 系统信息
+	reSelectionDetail.SelectionId = selectionId
+	reSelectionDetail.SelectionStatus = selection.SelectionStatus
+	reSelectionDetail.SelectionPlatform = selection.Platform
+	reSelectionDetail.CreatedAt = selection.CreatedAt
+	reSelectionDetail.SubmitAt = selection.SubmitAt
+	var creatorName, phone string
+	var rewardSum float64
+	if selection.SubAccountId == 0 {
+		enterprise, err := dao.EnterpriseDao{}.GetEnterprise(selection.EnterpriseID)
+		if err == nil && enterprise != nil {
+			creatorName = enterprise.BusinessName
+			phone, err = dao.UserDao{}.GetPhoneByUserId(enterprise.UserId)
+		}
+	} else {
+		subAccount, err := dao.SubAccountDao{}.GetSubAccount(selection.SubAccountId)
+		if err == nil && subAccount != nil {
+			creatorName = subAccount.SubAccountName
+			phone, err = dao.UserDao{}.GetPhoneByUserId(subAccount.UserId)
+		}
+	}
+	reSelectionDetail.CreatorName = creatorName
+	reSelectionDetail.Phone = phone
+	// 关联商品
+	var reProduct vo.ReTaskProduct
+	product, err := dao.ProductDAO{}.GetProductByID(selection.ProductID)
+	if err == nil {
+		photoUrl, e := dao.ProductPhotoDAO{}.GetMainPhotoByProductID(product.ProductID)
+		if e != nil {
+			photoUrl = ""
+		}
+		reProduct = vo.ReTaskProduct{
+			ProductID:       product.ProductID,
+			ProductName:     product.ProductName,
+			ProductType:     product.ProductType,
+			ProductCategory: product.ProductCategory,
+			ProductPrice:    product.ProductPrice,
+			ProductDetail:   product.ProductDetail,
+			CreatedAt:       product.CreatedAt,
+			PhotoUrl:        photoUrl,
+		}
+	}
+	reSelectionDetail.ProductInfo = &reProduct
+	// 样品奖励
+	reSelectionDetail.TaskDdl = selection.TaskDdl
+	reSelectionDetail.SampleNum = selection.SampleNum
+	var freeStrategyPreviews []*vo.FreeStrategyPreview // 领样策略
+	freeStrategys, err := dao.FreeStrategyDao{}.GetFreeStrategyBySelectionId(selectionId)
+	if err != nil {
+		logrus.Errorf("[selectionInfoDB service] call GetFreeStrategy error,err:%+v", err)
+		return nil, err
+	}
+	for _, freeStrategy := range freeStrategys {
+		freeStrategyPreview := &vo.FreeStrategyPreview{
+			StrategyId:     freeStrategy.StrategyId,
+			FansNum:        freeStrategy.FansNum,
+			SaleNum:        freeStrategy.SaleNum,
+			StrategyStatus: freeStrategy.StrategyStatus,
+		}
+		freeStrategyPreviews = append(freeStrategyPreviews, freeStrategyPreview)
+	}
+	reSelectionDetail.FreeStrategys = freeStrategyPreviews
+	var rewardStrategyPreviews []*vo.RewardStrategyPreview // 悬赏策略
+	rewardStrategys, err := dao.RewardStrategyDao{}.GetRewardStrategyBySelectionId(selectionId)
+	if err != nil {
+		logrus.Errorf("[selectionInfoDB service] call GetRewardStrategy error,err:%+v", err)
+		return nil, err
+	}
+	for _, rewardStrategy := range rewardStrategys {
+		rewardStrategyPreview := &vo.RewardStrategyPreview{
+			Reward:         rewardStrategy.Reward,
+			SaleActual:     rewardStrategy.SaleActual,
+			PerReward:      rewardStrategy.PerReward,
+			StrategyStatus: rewardStrategy.StrategyStatus,
+		}
+		rewardStrategyPreviews = append(rewardStrategyPreviews, rewardStrategyPreview)
+	}
+	reSelectionDetail.FreeStrategys = freeStrategyPreviews
+	reSelectionDetail.RewardStrategys = rewardStrategyPreviews
+	for _, rewardStrategy := range rewardStrategys {
+		rewardSum += rewardStrategy.Reward
+	}
+	reSelectionDetail.RewardSum = rewardSum
+	// 补充信息
+	selectionBriefInfos, err := dao.SecBriefDao{}.GetSelectionBriefInfo(selectionId)
+	if err != nil {
+		logrus.Errorf("[selectionInfoDB service] call GetSelectionBriefInfo error,err:%+v", err)
+		return nil, err
+	}
+	selectionMaterials, err := dao.SecMaterialDao{}.GetSelectionMaterialInfo(selectionId)
+	if err != nil {
+		logrus.Errorf("[selectionInfoDB service] call GetSelectionMaterialInfo error,err:%+v", err)
+		return nil, err
+	}
+	reSelectionDetail.SelectionBriefs = selectionBriefInfos
+	reSelectionDetail.SelectionMaterials = selectionMaterials
+
+	return &reSelectionDetail, nil
+}
+
+// 电商带货任务列表
+func (s SelectionInfoService) GetSelectionTaskList(param *vo.SelectionSearchParam) (vo.ResultVO, error) {
+	if param.Page == 0 {
+		param.Page = 1
+	}
+	if param.PageSize == 0 {
+		param.PageSize = 10
+	}
+	var result vo.ResultVO
+	reSelectionTaskPreviews, total, err := (&dao.ProjectDAO{}).GetSelectionPreviews(param)
+	if err != nil {
+		return result, err
+	}
+	for i := range reSelectionTaskPreviews {
+		var creatorName string
+		var productName string
+		var productPrice float64
+		var mainImage string
+		var reward float64
+		if reSelectionTaskPreviews[i].SubAccountId == 0 {
+			enterprise, err := dao.EnterpriseDao{}.GetEnterprise(reSelectionTaskPreviews[i].EnterpriseId)
+			if err == nil && enterprise != nil {
+				creatorName = enterprise.BusinessName
+			}
+		} else {
+			subAccount, err := dao.SubAccountDao{}.GetSubAccount(reSelectionTaskPreviews[i].SubAccountId)
+			if err == nil && subAccount != nil {
+				creatorName = subAccount.SubAccountName
+			}
+		}
+		product, err := dao.ProductDAO{}.GetProductByID(reSelectionTaskPreviews[i].ProductId)
+		if err == nil && product != nil {
+			productName = product.ProductName
+			productPrice = product.ProductPrice
+		}
+		mainImage, err = dao.ProductPhotoDAO{}.GetMainPhotoByProductID(reSelectionTaskPreviews[i].ProductId)
+		rewardStrategys, err := dao.RewardStrategyDao{}.GetRewardStrategyBySelectionId(reSelectionTaskPreviews[i].SelectionId)
+		for _, rewardStrategy := range rewardStrategys {
+			reward += rewardStrategy.Reward
+		}
+		reSelectionTaskPreviews[i].CreatorName = creatorName
+		reSelectionTaskPreviews[i].ProductName = productName
+		reSelectionTaskPreviews[i].ProductPrice = productPrice
+		reSelectionTaskPreviews[i].MainImage = mainImage
+		reSelectionTaskPreviews[i].Reward = reward
+	}
+	result = vo.ResultVO{
+		Page:     param.Page,
+		PageSize: param.PageSize,
+		Total:    total,
+		Data:     reSelectionTaskPreviews,
+	}
+	return result, nil
+}
+
+// 删除带货任务
+func (s SelectionInfoService) DeleteSelection(selectionId string) (*string, error) {
+	res, err := dao.SelectionInfoDAO{}.DeleteSelection(selectionId)
+	if err != nil {
+		logrus.Errorf("[projectDB service] call DeleteSelection error,err:%+v", err)
+		return res, err
+	}
+	return res, nil
+}

+ 16 - 0
app/util/encoding.go

@@ -0,0 +1,16 @@
+package util
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+)
+
+func MD5(keys ...string) string {
+	finalKey := ""
+	for _, key := range keys {
+		finalKey += key
+	}
+	s := md5.New()
+	s.Write([]byte(finalKey))
+	return hex.EncodeToString(s.Sum(nil))
+}

+ 26 - 0
app/util/resp.go

@@ -0,0 +1,26 @@
+package util
+
+import (
+	"net/http"
+	"youngee_b_api/consts"
+	"youngee_b_api/model/http_model"
+
+	"github.com/gin-gonic/gin"
+)
+
+func PackErrorResp(c *gin.Context, status int32) {
+	resp := http_model.CommonResponse{
+		Status:  status,
+		Message: consts.GetErrorToast(status),
+		Data:    nil,
+	}
+	c.JSON(http.StatusOK, resp)
+}
+func HandlerPackErrorResp(resp *http_model.CommonResponse, status int32, message string) {
+	resp.Status = status
+	if message != consts.DefaultToast {
+		resp.Message = message
+	} else {
+		resp.Message = consts.GetErrorToast(status)
+	}
+}

+ 25 - 0
app/util/structFunc.go

@@ -0,0 +1,25 @@
+package util
+
+import (
+	"fmt"
+	"reflect"
+)
+
+/*
+	合并两个结构体的值,遍历结构体s1,若s1中某字段值为空,则将s2该字段的值赋给s1,否则不变
+	参数:interface{} -> &struct, 结构体指针
+	返回值:interface{} -> &struct, 结构体指针
+*/
+func MergeStructValue(s1 interface{}, s2 interface{}) interface{} {
+	v1 := reflect.ValueOf(s1).Elem()
+	v2 := reflect.ValueOf(s2).Elem()
+	for i := 0; i < v1.NumField(); i++ {
+		field := v1.Field(i)
+		name := v1.Type().Field(i).Name
+		if field.Interface() == reflect.Zero(field.Type()).Interface() {
+			fmt.Printf("%+v %+v", name, v1.Kind() == reflect.Ptr)
+			v1.FieldByName(name).Set(v2.FieldByName(name))
+		}
+	}
+	return v1
+}

+ 129 - 0
app/util/type.go

@@ -0,0 +1,129 @@
+package util
+
+import (
+	"fmt"
+	"math/rand"
+	"reflect"
+	"time"
+)
+
+// IsNull 判断是否为空字符串
+func IsNull(s string) string {
+	if s == "" {
+		return "0"
+	}
+	return s
+}
+
+// IsBlank 判断 reflect.Value 是否为空
+func IsBlank(value reflect.Value) bool {
+	switch value.Kind() {
+	case reflect.String:
+		return value.Len() == 0
+	case reflect.Bool:
+		return !value.Bool()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return value.Int() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return value.Uint() == 0
+	case reflect.Float32, reflect.Float64:
+		return value.Float() == 0
+	case reflect.Interface, reflect.Ptr:
+		return value.IsNil()
+	}
+	return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface())
+}
+
+func GetNumString(num int64) string {
+	if num < 10000 {
+		return fmt.Sprintf("%v.00", num)
+	} else if num >= 10000 && num < 100000000 {
+		mean := float32(num) / float32(10000)
+		str := fmt.Sprintf("%.1f", mean)
+		return str + "万"
+	} else {
+		mean := float32(num) / float32(100000000)
+		str := fmt.Sprintf("%.1f", mean)
+		return str + "亿"
+	}
+}
+
+func GetTimePoionter(t *time.Time) time.Time {
+	if t == nil {
+		return time.Now()
+	} else {
+		return *t
+	}
+}
+
+func GetRandomString(l int) string {
+	str := "0123456789"
+	bytes := []byte(str)
+	var result []byte
+	r := rand.New(rand.NewSource(time.Now().UnixNano()))
+	for i := 0; i < l; i++ {
+		result = append(result, bytes[r.Intn(len(bytes))])
+	}
+	return string(result)
+}
+
+func GetDayNum(inputType string, inputData int) (int, error) {
+	result := 0
+	switch inputType {
+	case "year":
+		if inputData < 1 {
+			fmt.Println("年份错误!")
+			break
+		}
+		result = inputData
+	case "month":
+		months := []int{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}
+		if (inputData <= 12) && (inputData < 0) {
+			fmt.Println("月份错误!")
+			break
+		}
+		result = months[inputData-1]
+	case "day":
+		if (inputData < 0) && (inputData > 31) {
+			fmt.Println("日期错误!")
+			break
+		}
+		result = inputData
+	default:
+		return 0, fmt.Errorf("输入参数非法:%s", inputType)
+	}
+	return result, nil
+}
+
+// RemoveRepByMap 通过map主键唯一的特性过滤重复元素
+func RemoveRepByMap(slc []int64) []int64 {
+	if len(slc) == 0 {
+		return slc
+	}
+	var result []int64
+	tempMap := map[int64]byte{} // 存放不重复主键
+	for _, e := range slc {
+		l := len(tempMap)
+		tempMap[e] = 0
+		if len(tempMap) != l { // 加入map后,map长度变化,则元素不重复
+			result = append(result, e)
+		}
+	}
+	return result
+}
+
+func RemoveStrRepByMap(slc []string) []string {
+	if len(slc) == 0 {
+		return slc
+	}
+	var result []string
+	tempMap := map[string]byte{} // 存放不重复主键
+	for _, e := range slc {
+		l := len(tempMap)
+		tempMap[e] = 0
+		if len(tempMap) != l { // 加入map后,map长度变化,则元素不重复
+			result = append(result, e)
+		}
+	}
+	return result
+}

+ 51 - 0
app/util/uuid.go

@@ -0,0 +1,51 @@
+package util
+
+import (
+	"github.com/GUAIK-ORG/go-snowflake/snowflake"
+	"github.com/google/uuid"
+	"github.com/issue9/conv"
+	"math/rand"
+	"time"
+)
+
+var snowflakeInstance *snowflake.Snowflake
+
+func init() {
+	s, err := snowflake.NewSnowflake(int64(0), int64(0))
+	if err != nil {
+		panic(err)
+	}
+	snowflakeInstance = s
+}
+func GetUUID() string {
+	return uuid.New().String()
+}
+func GetSnowflakeID() int64 {
+	return snowflakeInstance.NextVal()
+}
+
+func GetSelectionID() string {
+	rand.Seed(time.Now().UnixNano())
+	td := conv.MustString(time.Now().Day())
+	for {
+		if len(td) == 3 {
+			break
+		}
+		td = "0" + td
+	}
+	selectionId := conv.MustString(time.Now().Year())[2:] + td + conv.MustString(rand.Intn(100000-10000)+10000)
+	return selectionId
+}
+
+func GetProjectID() string {
+	rand.Seed(time.Now().UnixNano())
+	td := conv.MustString(time.Now().Day())
+	for {
+		if len(td) == 3 {
+			break
+		}
+		td = "0" + td
+	}
+	selectionId := conv.MustString(time.Now().Year())[2:] + td + conv.MustString(rand.Intn(100000-10000)+10000)
+	return selectionId
+}

+ 13 - 0
app/vo/content_check_param.go

@@ -0,0 +1,13 @@
+package vo
+
+type ContentCheckParam struct {
+	AK          string `json:"ak"`
+	SK          string `json:"sk"`
+	ProjectId   string `json:"project_id"`
+	Text        string `json:"text"`
+	Image       string `json:"image"`
+	Video       string `json:"video"`
+	Document    string `json:"document"`
+	Format      string `json:"format"`
+	Credentials string `json:"credentials"`
+}

+ 8 - 0
app/vo/get_all_product_param.go

@@ -0,0 +1,8 @@
+package vo
+
+type GetAllProductParam struct {
+	EnterpriseId string `json:"enterprise_id"`
+	SubAccountId int64  `json:"sub_account_id"`
+	Page         int    `json:"page"`
+	PageSize     int    `json:"page_size"`
+}

+ 23 - 0
app/vo/product_create_param.go

@@ -0,0 +1,23 @@
+package vo
+
+type ProductPhoto struct {
+	PhotoUrl string `json:"photo_url"` // 图片或视频url
+	PhotoUid string `json:"photo_uid"`
+	Symbol   int64  `json:"symbol"` // 图片为主图或详情图标志位,1为主图,2为轮播图,3为轮播视频. 4为详情图. 5为详情视频
+}
+
+type ProductCreateParam struct {
+	EnterpriseId        string         `json:"enterprise_id"`        // 要绑定的企业id
+	SubAccountId        int64          `json:"sub_account_id"`       // 子账号id
+	ProductName         string         `json:"product_name"`         // 商品标题
+	ProductId           string         `json:"product_id"`           // 快手商品ID
+	ProductCategory     string         `json:"product_category"`     // 商品类目
+	ProductDetail       string         `json:"product_detail"`       // 卖点总结
+	ProductPrice        float64        `json:"product_price"`        // 商品价值
+	ExclusiveCommission float64        `json:"exclusive_commission"` // 专属佣金
+	CommissionPrice     float64        `json:"commission_price"`     // 佣金金额
+	PublicCommission    float64        `json:"public_commission"`    // 公开佣金
+	ProductPhotos       []ProductPhoto `json:"product_photos"`       // 商品图片列表
+	SalesCount          string         `json:"column:sales_count"`   // 商品30天销量
+	ProductUrl          string         `json:"product_url"`          // 商品链接,可为电商网址、公司官网、大众点评的店铺地址等可以说明商品信息或者品牌信息的线上地址;
+}

+ 10 - 0
app/vo/project_create_param.go

@@ -0,0 +1,10 @@
+package vo
+
+type ProjectCreateParam struct {
+	EnterpriseId      string  `json:"enterprise_id"`
+	SubAccountId      int64   `json:"sub_account_id"`
+	Platform          int64   `json:"platform"`
+	ProductId         int64   `json:"product_id"`
+	ServiceChargeRate float64 `json:"service_charge_rate"`
+	ProjectType       int64   `json:"project_type"` // 项目类型,1代表全流程项目,2代表专项项目
+}

+ 17 - 0
app/vo/project_search_param.go

@@ -0,0 +1,17 @@
+package vo
+
+type ProjectSearchParam struct {
+	EnterpriseId    string `json:"enterprise_id"`
+	SubAccountId    int64  `json:"sub_account_id"`
+	Page            int    `json:"page"`
+	PageSize        int    `json:"page_size"`
+	ProjectType     int64  `json:"project_type"` // 项目类型,1全流程项目,2专项项目
+	ProjectPlatform int64  `json:"project_platform"`
+	ProjectStatus   int64  `json:"project_status"` // 任务状态,1-10代表创建中、待审核、审核通过、招募中、招募完毕、待支付、已支付、失效、执行中、已结案
+	ProjectForm     int64  `json:"project_form"`   // 任务形式,1-5代表商品寄拍、素材分发、虚拟产品测评、线下探店打卡、素材微原创
+	ContentType     int64  `json:"content_type"`   // 内容形式, 1图文 2视频
+
+	ProjectId string `json:"project_id"` // 任务ID
+	//ProjectName string `json:"project_name"` // 任务标题
+	//CreatorName string `json:"creator_name"` // 创建者
+}

+ 45 - 0
app/vo/project_update_param.go

@@ -0,0 +1,45 @@
+package vo
+
+type ProjectUpdateParam struct {
+	EnterpriseId      string                  `json:"enterprise_id"`
+	SubAccountId      int64                   `json:"sub_account_id"`
+	ProjectID         string                  `json:"project_id"`
+	ProductId         int64                   `json:"product_id"`
+	ServiceChargeRate float64                 `json:"service_charge_rate"`
+	ProjectType       int64                   `json:"project_type"`      // 项目类型,1代表全流程项目,2代表专项项目
+	ProjectStatus     int64                   `json:"project_status"`    // 项目状态,1-10分别代表创建中、待审核、审核通过、招募中、招募完毕、待支付、已支付、失效、执行中、已结案
+	ProjectName       string                  `json:"task_name"`         // 项目名称(任务标题)
+	TalentType        string                  `json:"talent_type"`       // 达人类型
+	RecruitDdl        string                  `json:"recruit_ddl"`       // 招募截止时间
+	RecruitStrategys  []CreateRecruitStrategy `json:"recruit_strategys"` // 招募策略
+
+	ProjectForm     int64                  `json:"project_form"`   // 项目形式,1-4分别代表实体商品寄拍、虚拟产品测评、线下探店打卡、素材微原创
+	ContentType     int64                  `json:"content_type"`   // 内容形式,1代表图文,2代表视频
+	ProjectDetail   string                 `json:"project_detail"` // 项目详情
+	Tools           string                 `json:"tools"`          // 工具选择 1邀约招募 2结算账单 3样品物流 4审稿工具 5作品审查 6数据巡检(,分隔)
+	ProjectBrief    []*ProjectBriefInfo    `json:"project_brief"`
+	ProjectMaterial []*ProjectMaterialInfo `json:"project_material"`
+}
+
+type ProjectBriefInfo struct {
+	FileUrl string `json:"file_url"`
+	FileUid string `json:"file_uid"`
+	Name    string `json:"name"`
+}
+
+type ProjectMaterialInfo struct {
+	FileUrl string `json:"file_url"`
+	FileUid string `json:"file_uid"`
+	Name    string `json:"name"`
+}
+
+// 招募策略
+type CreateRecruitStrategy struct {
+	StrategyID    int64   `json:"strategy_id"`    // 策略id
+	FeeForm       int64   `json:"fee_form"`       // 稿费形式,1-3分别代表无费置换、一口价、自报价
+	FollowersLow  int64   `json:"followers_low"`  // 达人粉丝数下限
+	FollowersUp   int64   `json:"followers_up"`   // 达人粉丝数上限
+	RecruitNumber int64   `json:"recruit_number"` // 招募数量
+	Offer         float64 `json:"offer"`          // 报价
+	ServiceCharge float64 `json:"service_charge"` // 服务费
+}

+ 45 - 0
app/vo/re_project_detail.go

@@ -0,0 +1,45 @@
+package vo
+
+import (
+	"time"
+	"youngee_b_api/app/entity"
+)
+
+type ReProjectDetail struct {
+	// 系统信息
+	ProjectId         string    `json:"projectId"`           // 项目id 生成规则:年(2位)+一年中的第几天(3位)+5位数随机数,雪花算法也可,生成10位订单号
+	ProjectStatus     int64     `json:"projectStatus"`       // 项目状态,1-10分别代表创建中、待审核、审核通过、招募中、招募完毕、待支付、已支付、失效、执行中、已结案
+	ProjectPlatform   int64     `json:"projectPlatform"`     //  项目平台,1-7分别代表红book、抖音、微博、快手、b站、大众点评、知乎
+	CreatedAt         time.Time `json:"createdAt"`           // 创建时间
+	CreatorName       string    `json:"creatorName"`         // 创建者
+	Phone             string    `json:"phone"`               // 联系方式
+	EstimatedCost     float64   `json:"estimatedCost"`       // 成本预估
+	ServiceChargeRate float64   `json:"service_charge_rate"` // 公开服务费率
+	// 支付方式参数待定
+	// 关联商品
+	ProductInfo *ReTaskProduct `json:"productInfo"`
+	// 招募要求
+	TalentType       string                    `json:"talentType"`
+	RecruitDdl       time.Time                 `json:"recruitDdl"`
+	ProjectForm      int64                     `json:"projectForm"`
+	ContentType      int64                     `json:"contentType"`
+	ProjectDetail    string                    `json:"projectDetail"`
+	RecruitStrategys []*RecruitStrategyPreview `json:"recruitStrategys"` // 招募策略
+	// 执行要求
+	ProjectBriefs    []*entity.ProjectBrief    `json:"projectBriefs"`    // 选品brief列表
+	ProjectMaterials []*entity.ProjectMaterial `json:"projectMaterials"` // 选品示例列表
+	Tools            string                    `json:"tools"`            // 工具选择
+}
+
+type RecruitStrategyPreview struct {
+	StrategyId     int64   `json:"strategyId"`
+	FeeForm        int64   `json:"feeForm"`
+	FollowersLow   int64   `json:"followersLow"`
+	FollowersUp    int64   `json:"followersUp"`
+	RecruitNumber  int64   `json:"recruitNumber"`
+	Offer          float64 `json:"offer"`
+	TOffer         float64 `json:"tOffer"` // 达人所见报价
+	ServiceCharge  float64 `json:"serviceCharge"`
+	SelectedNumber int64   `json:"selectedNumber"` // 确认合作数量
+	TotalOffer     float64 `json:"totalOffer"`     // 合计
+}

+ 21 - 0
app/vo/re_project_task_preview.go

@@ -0,0 +1,21 @@
+package vo
+
+type ReProjectTaskPreview struct {
+	ProductId    int64   `json:"productId"`
+	MainImage    string  `json:"mainImage"`
+	ProductName  string  `json:"productName"`
+	ProductPrice float64 `json:"productPrice"`
+
+	EnterpriseId    string  `json:"enterpriseId"`
+	SubAccountId    int64   `json:"subAccountId"`
+	ProjectId       string  `json:"projectId"`
+	ProjectPlatform int64   `json:"projectPlatform"`
+	ProjectStatus   int64   `json:"projectStatus"`
+	EstimatedCost   float64 `json:"estimatedCost"`
+	ProjectForm     int64   `json:"projectForm"`
+	ContentType     int64   `json:"contentType"`
+	NeedReview      int64   `json:"needReview"`
+	NeedQuality     int64   `json:"needQuality"`
+	NeedCalculate   int64   `json:"needCalculate"`
+	CreatorName     string  `json:"creatorName"`
+}

+ 43 - 0
app/vo/re_selection_detail.go

@@ -0,0 +1,43 @@
+package vo
+
+import (
+	"time"
+	"youngee_b_api/app/entity"
+)
+
+type ReSelectionDetail struct {
+	// 系统信息
+	SelectionId       string    `json:"selectionId"`       // 项目id 生成规则:年(2位)+一年中的第几天(3位)+5位数随机数,雪花算法也可,生成10位订单号
+	SelectionStatus   int64     `json:"selectionStatus"`   // 项目状态,1-8分别代表创建中、待审核、审核通过、待支付、已支付、执行中、失效、已结案
+	SelectionPlatform int64     `json:"selectionPlatform"` //  项目平台,1-7分别代表红book、抖音、微博、快手、b站、大众点评、知乎
+	CreatedAt         time.Time `json:"createdAt"`         // 创建时间
+	CreatorName       string    `json:"creatorName"`       // 创建者
+	Phone             string    `json:"phone"`             // 联系方式
+	RewardSum         float64   `json:"rewardSum"`         // 悬赏池总金额
+	SubmitAt          time.Time `json:"submitAt"`          // 提交审核时间
+	// 支付方式参数待定
+	// 关联商品
+	ProductInfo *ReTaskProduct `json:"productInfo"`
+	// 样品奖励
+	TaskDdl         time.Time                `json:"taskDdl"`
+	SampleNum       int64                    `json:"sampleNum"` // 样品数量
+	FreeStrategys   []*FreeStrategyPreview   // 领样策略
+	RewardStrategys []*RewardStrategyPreview // 悬赏策略
+	// 补充信息
+	SelectionBriefs    []*entity.SecBrief    `json:"selectionBriefs"`    // 选品brief列表
+	SelectionMaterials []*entity.SecMaterial `json:"selectionMaterials"` // 选品示例列表
+}
+
+type FreeStrategyPreview struct {
+	StrategyId     int64 `json:"strategyId"`
+	FansNum        int64 `json:"fansNum"`
+	SaleNum        int64 `json:"saleNum"`
+	StrategyStatus int64 `json:"strategyStatus"` // 策略状态,1-2分别代表未删除、已删除
+}
+
+type RewardStrategyPreview struct {
+	Reward         float64 `json:"reward"`
+	SaleActual     int64   `json:"saleActual"`
+	PerReward      float64 `json:"perReward"`
+	StrategyStatus int64   `json:"strategyStatus"` // 策略状态,1-2分别代表未删除、已删除
+}

+ 23 - 0
app/vo/re_selection_task_preview.go

@@ -0,0 +1,23 @@
+package vo
+
+import "time"
+
+type ReSelectionTaskPreview struct {
+	ProductId    int64   `json:"productId"`
+	MainImage    string  `json:"mainImage"`
+	ProductName  string  `json:"productName"`
+	ProductPrice float64 `json:"productPrice"`
+
+	EnterpriseId      string    `json:"enterpriseId"`
+	SubAccountId      int64     `json:"subAccountId"`
+	SelectionId       string    `json:"selectionId"`
+	SelectionPlatform int64     `json:"selectionPlatform"`
+	SelectionStatus   int64     `json:"selectionStatus"`
+	CreatedAt         time.Time `json:"createdAt"`
+	TaskDdl           time.Time `json:"taskDdl"`
+	SampleNum         int64     `json:"sampleNum"` // 样品数量
+	Reward            float64   `json:"reward"`    // 悬赏池总金额
+	EnrollNum         int64     `json:"enrollNum"` // 报名数量
+	ChooseNum         int64     `json:"chooseNum"` // 已选数量
+	CreatorName       string    `json:"creatorName"`
+}

+ 14 - 0
app/vo/re_task_product.go

@@ -0,0 +1,14 @@
+package vo
+
+import "time"
+
+type ReTaskProduct struct {
+	ProductID       int64     `json:"productId"`
+	ProductName     string    `json:"productName"`
+	ProductType     int64     `json:"productType"`
+	ProductCategory string    `json:"productCategory"`
+	ProductPrice    float64   `json:"productPrice"`
+	ProductDetail   string    `json:"productDetail"`
+	CreatedAt       time.Time `json:"createdAt"`
+	PhotoUrl        string    `json:"photoUrl"`
+}

+ 16 - 0
app/vo/re_workspace_takegoods.go

@@ -0,0 +1,16 @@
+package vo
+
+type ReWorkspaceTakegoods struct {
+	Pay                float64   `json:"pay"`
+	PayList            []float64 `json:"pay_list"`
+	Finish             float64   `json:"finish"`
+	FinishList         []float64 `json:"finish_list"`
+	Commission         float64   `json:"commission"`
+	CommissionList     []float64 `json:"commission_list"`
+	Order              int64     `json:"order"`
+	OrderList          []int64   `json:"order_list"`
+	Person             int64     `json:"person"`
+	PersonList         []int64   `json:"person_list"`
+	CommissionRate     float64   `json:"commissionRate"`
+	CommissionRateList []float64 `json:"commissionRate_list"`
+}

+ 9 - 0
app/vo/result_vo.go

@@ -0,0 +1,9 @@
+package vo
+
+// Result 封装响应给前端的数据
+type ResultVO struct {
+	Page     int         `json:"page"`
+	PageSize int         `json:"pageSize"`
+	Total    int64       `json:"total"`
+	Data     interface{} `json:"data"`
+}

+ 8 - 0
app/vo/selection_info_create_param.go

@@ -0,0 +1,8 @@
+package vo
+
+type SelectionInfoCreateParam struct {
+	EnterpriseId string `json:"enterprise_id"`
+	SubAccountId int64  `json:"sub_account_id"`
+	Platform     int64  `json:"platform"`
+	ProductId    int64  `json:"product_id"`
+}

+ 54 - 0
app/vo/selection_info_update_param.go

@@ -0,0 +1,54 @@
+package vo
+
+type SelectionInfoUpdateParam struct {
+	EnterpriseId    string                  `json:"enterprise_id"`
+	SubAccountId    int64                   `json:"sub_account_id"`
+	SelectionID     string                  `json:"selection_id"` // 选品id
+	ProductId       int64                   `json:"product_id"`
+	SelectionStatus int64                   `json:"selection_status"` // 选品项目状态,1-8分别代表创建中、待审核、审核通过、待支付、已支付、执行中、失效、已结案
+	SelectionName   string                  `json:"task_name"`        // 任务名称
+	TaskDdl         string                  `json:"task_ddl"`         // 招募截止时间
+	FreeStrategys   []UpdateFreeStrategys   `json:"free_strategys"`   // 免费领样策略
+	RewardStrategys []UpdateRewardStrategys `json:"reward_strategys"` // 悬赏策略
+	SampleNum       int64                   `json:"sample_num"`       // 样品数量
+	SecBrief        []*SecBriefInfo         `json:"sec_brief"`
+	SecMaterial     []*SecMaterialInfo      `json:"sec_material"`
+
+	ProductUrl       string  `json:"product_url"`       // 带货链接
+	RemainNum        int64   `json:"remain_num"`        // 剩余数量
+	CommissionRate   float64 `json:"commission_rate"`   // 佣金比例
+	TaskReward       float64 `json:"task_reward"`       // 任务悬赏
+	SampleCondition  string  `json:"sample_condition"`  // 领样条件
+	RewardCondition  string  `json:"reward_condition"`  // 返现悬赏条件
+	SettlementAmount float64 `json:"settlement_amount"` // 已结算金额
+	Detail           string  `json:"detail"`            // 卖点总结
+	Status           int64   `json:"status"`            // 是否删除
+}
+
+type SecBriefInfo struct {
+	FileUrl string `json:"file_url"`
+	FileUid string `json:"file_uid"`
+	Name    string `json:"name"`
+}
+
+type SecMaterialInfo struct {
+	FileUrl string `json:"file_url"`
+	FileUid string `json:"file_uid"`
+	Name    string `json:"name"`
+}
+
+// 领样策略
+type UpdateFreeStrategys struct {
+	StrategyId int64 `json:"strategy_id"` // 策略编号
+	FansNum    int64 `json:"fans_num"`    // 粉丝数目
+	SaleNum    int64 `json:"sale_num"`    // 近30天橱窗销量
+	EnrollNum  int64 `json:"enroll_num"`  // 报名人数
+	ChooseNum  int64 `json:"choose_num"`  // 已选人数
+}
+
+// 悬赏策略
+type UpdateRewardStrategys struct {
+	Reward     float64 `json:"reward"`      // 悬赏池总金额
+	SaleActual int64   `json:"sale_actual"` // 实际带货销量
+	PerReward  float64 `json:"per_reward"`  // 每人可获得悬赏金
+}

+ 16 - 0
app/vo/selection_search_param.go

@@ -0,0 +1,16 @@
+package vo
+
+type SelectionSearchParam struct {
+	EnterpriseId      string `json:"enterprise_id"`
+	SubAccountId      int64  `json:"sub_account_id"`
+	Page              int    `json:"page"`
+	PageSize          int    `json:"page_size"`
+	SelectionPlatform int64  `json:"selection_platform"` // 平台,1-7分别代表小红书、抖音、微博、快手、b站、大众点评、知乎
+	SelectionStatus   int64  `json:"selection_status"`   // 任务状态,1-8代表创建中、待审核、审核通过、待支付、已支付、执行中、失效、已结案
+	FreeFlag          int64  `json:"free_flag"`          // 领样策略  0全部 1有 2无
+	RewardFlag        int64  `json:"reward_flag"`        // 悬赏策略 0全部 1有 2无
+
+	SelectionId string `json:"selection_id"` // 任务ID
+	//SelectionName string `json:"selection_name"` // 任务标题
+	//CreatorName   string `json:"creator_name"`   // 创建者
+}

+ 16 - 0
route/init.go

@@ -1,5 +1,16 @@
 package route
 package route
 
 
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/sirupsen/logrus"
+	ginSwagger "github.com/swaggo/gin-swagger"
+	"youngee_b_api/app/controller"
+	"youngee_b_api/handler"
+	"youngee_b_api/middleware"
+	"youngee_b_api/model/http_model"
+)
+
+/*
 import (
 import (
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
@@ -9,6 +20,11 @@ import (
 	"youngee_b_api/middleware"
 	"youngee_b_api/middleware"
 	"youngee_b_api/model/http_model"
 	"youngee_b_api/model/http_model"
 )
 )
+*/
+
+import (
+	swaggerFiles "github.com/swaggo/files"
+)
 
 
 func InitRoute(r *gin.Engine) {
 func InitRoute(r *gin.Engine) {
 	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
 	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))