|
@@ -9,9 +9,7 @@ import (
|
|
|
"mime/multipart"
|
|
|
"os"
|
|
|
"path/filepath"
|
|
|
- "reflect"
|
|
|
"strconv"
|
|
|
- "strings"
|
|
|
"time"
|
|
|
|
|
|
"gorm.io/gorm"
|
|
@@ -199,189 +197,167 @@ func (s *StoreEntry) ImportExcel(ctx context.Context, data [][]string) error {
|
|
|
return s.ExecExcelData(ctx, pastureId, eventEnterList)
|
|
|
}
|
|
|
|
|
|
-func (s *StoreEntry) ImportExcel2(ctx context.Context, data [][]string, excelHeader []string) error {
|
|
|
+func (s *StoreEntry) ImportExcel2(ctx context.Context, data [][]string, excelHeader []string, headOfField []string) error {
|
|
|
// 获取当前用户信息
|
|
|
userModel, err := s.GetUserModel(ctx)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
+ // excelHeader ["序号","牛号","性别","出生日期","栏舍名称","牛只类型","牛只品种","牛只来源","入场日期","当前体重(KG)","用途","胎次","配种日期","孕检日期","孕检结果","产犊日期","流产日期","是否禁配",
|
|
|
|
|
|
- penMap := s.PenMap2(ctx, userModel.AppPasture.Id)
|
|
|
+ pastureId := userModel.AppPasture.Id
|
|
|
if userModel.AppPasture.Id <= 0 {
|
|
|
return xerr.Custom("无效的牧场ID")
|
|
|
}
|
|
|
+ penMap := s.PenMap2(ctx, pastureId)
|
|
|
+ if len(penMap) <= 0 {
|
|
|
+ return xerr.Custom("当前牧场没有配置栏舍信息")
|
|
|
+ }
|
|
|
+
|
|
|
+ cowTypeMap := s.CowTypeMap2(userModel)
|
|
|
+ cowKindMap := s.CowKindMap2(userModel)
|
|
|
+ cowSourceMap := s.CowSourceMap2(userModel)
|
|
|
+ purposeMap := s.PurposeMap2(userModel)
|
|
|
+
|
|
|
// 处理Excel数据
|
|
|
- //headers := data[0]
|
|
|
eventEnterList := make([]*pasturePb.EventEnterRequest, 0)
|
|
|
- /*for _, row := range data[1:] {
|
|
|
- if len(row) <= 0 {
|
|
|
+ // 遍历数据行(跳过表头)
|
|
|
+ for _, rows := range data[1:] {
|
|
|
+ if len(rows) == 0 { // [1 HS10034 母 08-12-22 东区1号 成母牛 西门塔尔牛 产犊 09-12-23 500 繁育 1 12-05-24 01-15-25 有胎 否 2 789]
|
|
|
continue
|
|
|
}
|
|
|
+
|
|
|
ts := &pasturePb.EventEnterRequest{
|
|
|
OperationId: int32(userModel.SystemUser.Id),
|
|
|
OperationName: userModel.SystemUser.Name,
|
|
|
MessengerId: int32(userModel.SystemUser.Id),
|
|
|
MessengerName: userModel.SystemUser.Name,
|
|
|
}
|
|
|
- for j, d := range row {
|
|
|
- switch j {
|
|
|
- case 0:
|
|
|
+
|
|
|
+ for j, _ := range rows {
|
|
|
+ if j == 0 {
|
|
|
continue
|
|
|
+ }
|
|
|
+ value := rows[j]
|
|
|
+ switch j {
|
|
|
case 1:
|
|
|
- continue
|
|
|
+ ts.EarNumber = value
|
|
|
case 2:
|
|
|
- ts.EarNumber = d
|
|
|
- case 3:
|
|
|
- if pn, ok := penMap[d]; ok {
|
|
|
- ts.PenId = pn.Id
|
|
|
- ts.PenName = pn.Name
|
|
|
- }
|
|
|
- case 4:
|
|
|
ts.Sex = pasturePb.Genders_Female
|
|
|
- if d == "公" {
|
|
|
+ if value == "公" {
|
|
|
ts.Sex = pasturePb.Genders_Male
|
|
|
}
|
|
|
- case 5:
|
|
|
- if d == "成母牛" {
|
|
|
- ts.CowType = pasturePb.CowType_Breeding_Calf
|
|
|
- } else if d == "犊牛" {
|
|
|
- ts.CowType = pasturePb.CowType_Lactating_Calf
|
|
|
- } else if d == "青年牛" {
|
|
|
- ts.CowType = pasturePb.CowType_Youth_Calf
|
|
|
- } else if d == "育成牛" {
|
|
|
- ts.CowType = pasturePb.CowType_Reserve_Calf
|
|
|
+ case 3:
|
|
|
+ bat, _ := util.TimeParseLocal(model.LayoutTime2, value+" 00:00:00")
|
|
|
+ if !bat.IsZero() {
|
|
|
+ ts.BirthAt = int32(bat.Unix())
|
|
|
+ } else {
|
|
|
+ ts.BirthAt = 0
|
|
|
}
|
|
|
+ case 4:
|
|
|
+ ts.PenName = value
|
|
|
+ case 5:
|
|
|
+ ts.CowTypeName = value
|
|
|
case 6:
|
|
|
- continue
|
|
|
+ ts.CowKindName = value
|
|
|
case 7:
|
|
|
- bat, _ := util.TimeParseLocal(model.LayoutTime2, d)
|
|
|
- if !bat.IsZero() {
|
|
|
- ts.BirthAt = int32(bat.Local().Unix())
|
|
|
+ if cs, ok := cowSourceMap[value]; ok {
|
|
|
+ ts.CowSource = cs
|
|
|
}
|
|
|
case 8:
|
|
|
- lact, _ := strconv.Atoi(d)
|
|
|
- ts.Lact = int32(lact)
|
|
|
- case 9:
|
|
|
- eat, _ := util.TimeParseLocal(model.LayoutTime2, d)
|
|
|
- if !eat.IsZero() {
|
|
|
- ts.EnterAt = int32(eat.Local().Unix())
|
|
|
+ bat, _ := util.TimeParseLocal(model.LayoutTime2, value+" 00:00:00")
|
|
|
+ if !bat.IsZero() {
|
|
|
+ ts.EnterAt = int32(bat.Unix())
|
|
|
+ } else {
|
|
|
+ ts.EnterAt = 0
|
|
|
}
|
|
|
+ case 9:
|
|
|
+ ct, _ := strconv.ParseFloat(value, 64)
|
|
|
+ ts.Weight = float32(ct)
|
|
|
case 10:
|
|
|
- ts.FatherNumber = d
|
|
|
+ ts.PurposeName = value
|
|
|
case 11:
|
|
|
- ts.MotherNumber = d
|
|
|
+ lact, _ := strconv.Atoi(value)
|
|
|
+ ts.Lact = int32(lact)
|
|
|
case 12:
|
|
|
- mat, _ := util.TimeParseLocal(model.LayoutTime2, d)
|
|
|
- if !mat.IsZero() {
|
|
|
- ts.MatingAt = int32(mat.Local().Unix())
|
|
|
+ bat, _ := util.TimeParseLocal(model.LayoutTime2, value+" 00:00:00")
|
|
|
+ if !bat.IsZero() {
|
|
|
+ ts.MatingAt = int32(bat.Unix())
|
|
|
+ } else {
|
|
|
+ ts.MatingAt = 0
|
|
|
}
|
|
|
case 13:
|
|
|
- continue
|
|
|
+ bat, _ := util.TimeParseLocal(model.LayoutTime2, value+" 00:00:00")
|
|
|
+ if !bat.IsZero() {
|
|
|
+ ts.PregnancyCheckAt = int32(bat.Unix())
|
|
|
+ } else {
|
|
|
+ ts.PregnancyCheckAt = 0
|
|
|
+ }
|
|
|
case 14:
|
|
|
- continue
|
|
|
+ ts.PregnantCheckResult = pasturePb.PregnantCheckResult_Pregnant
|
|
|
+ if value == "无胎" {
|
|
|
+ ts.PregnantCheckResult = pasturePb.PregnantCheckResult_UnPregnant
|
|
|
+ }
|
|
|
case 15:
|
|
|
- mt, _ := strconv.Atoi(d)
|
|
|
- ts.MatingTimes = int32(mt)
|
|
|
+ bat, _ := util.TimeParseLocal(model.LayoutTime2, value+" 00:00:00")
|
|
|
+ if !bat.IsZero() {
|
|
|
+ ts.CalvingAt = int32(bat.Unix())
|
|
|
+ } else {
|
|
|
+ ts.CalvingAt = 0
|
|
|
+ }
|
|
|
case 16:
|
|
|
- continue
|
|
|
+ bat, _ := util.TimeParseLocal(model.LayoutTime2, value+" 00:00:00")
|
|
|
+ if !bat.IsZero() {
|
|
|
+ ts.AbortionAt = int32(bat.Unix())
|
|
|
+ } else {
|
|
|
+ ts.AbortionAt = 0
|
|
|
+ }
|
|
|
case 17:
|
|
|
- pat, _ := util.TimeParseLocal(model.LayoutTime2, d)
|
|
|
- if !pat.IsZero() {
|
|
|
- ts.PregnancyCheckAt = int32(pat.Local().Unix())
|
|
|
+ if value == "是" {
|
|
|
+ ts.BreedStatus = pasturePb.BreedStatus_No_Mating
|
|
|
}
|
|
|
case 18:
|
|
|
- continue
|
|
|
+ mts, _ := strconv.Atoi(value)
|
|
|
+ ts.MatingTimes = int32(mts)
|
|
|
+
|
|
|
case 19:
|
|
|
- continue
|
|
|
+ ts.BullNumber = value
|
|
|
case 20:
|
|
|
- cat, _ := util.TimeParseLocal(model.LayoutTime2, d)
|
|
|
- if !cat.IsZero() {
|
|
|
- ts.CalvingAt = int32(cat.Local().Unix())
|
|
|
- }
|
|
|
+ ts.NeckRingNumber = value
|
|
|
case 21:
|
|
|
- continue
|
|
|
+ ts.MotherNumber = value
|
|
|
case 22:
|
|
|
- continue
|
|
|
+ ts.FatherNumber = value
|
|
|
case 23:
|
|
|
- continue
|
|
|
+ ts.BatchNumber = value
|
|
|
case 24:
|
|
|
- ts.CowKind = pasturePb.CowKind_AGSN
|
|
|
+ price, _ := strconv.ParseFloat(value, 64)
|
|
|
+ ts.Price = float32(price)
|
|
|
}
|
|
|
}
|
|
|
- eventEnterList = append(eventEnterList, ts)
|
|
|
- }*/
|
|
|
- // 遍历数据行(跳过表头)
|
|
|
- for _, row := range data[1:] {
|
|
|
- if len(row) == 0 {
|
|
|
- continue
|
|
|
- }
|
|
|
|
|
|
- ts := &pasturePb.EventEnterRequest{
|
|
|
- OperationId: int32(userModel.SystemUser.Id),
|
|
|
- OperationName: userModel.SystemUser.Name,
|
|
|
- MessengerId: int32(userModel.SystemUser.Id),
|
|
|
- MessengerName: userModel.SystemUser.Name,
|
|
|
- }
|
|
|
-
|
|
|
- // 使用反射动态匹配字段
|
|
|
- val := reflect.ValueOf(ts).Elem()
|
|
|
- typ := val.Type()
|
|
|
-
|
|
|
- for i := 0; i < val.NumField(); i++ {
|
|
|
- field := typ.Field(i)
|
|
|
- fieldVal := val.Field(i)
|
|
|
-
|
|
|
- // 获取字段的 excel 标签(如 excel:"耳标号")
|
|
|
- excelTag := strings.ReplaceAll(field.Tag.Get("json"), ",omitempty", "")
|
|
|
- if excelTag == "" {
|
|
|
- continue // 没有 excel 标签的字段跳过
|
|
|
- }
|
|
|
-
|
|
|
- // 查找 excelHeader 中匹配的列索引
|
|
|
- colIndex := -1
|
|
|
- for j, colName := range excelHeader {
|
|
|
- if colName == "" {
|
|
|
- continue // 跳过空列名
|
|
|
- }
|
|
|
- if colName == excelTag {
|
|
|
- colIndex = j
|
|
|
- break
|
|
|
- }
|
|
|
+ // 特殊处理 PenId 和 PenName(依赖 penMap)
|
|
|
+ if ts.PenName != "" {
|
|
|
+ if pen, ok := penMap[ts.PenName]; ok {
|
|
|
+ ts.PenId = pen.Id
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- if colIndex == -1 || colIndex >= len(row) {
|
|
|
- continue // 列名不匹配或数据越界
|
|
|
+ if ts.CowTypeName != "" {
|
|
|
+ if ct, ok := cowTypeMap[ts.CowTypeName]; ok {
|
|
|
+ ts.CowType = ct
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- cellValue := row[colIndex]
|
|
|
- if cellValue == "" {
|
|
|
- continue // 空值跳过
|
|
|
- }
|
|
|
- // 根据字段类型设置值
|
|
|
- switch fieldVal.Kind() {
|
|
|
- case reflect.String:
|
|
|
- fieldVal.SetString(cellValue)
|
|
|
- case reflect.Int32:
|
|
|
- if num, err := strconv.ParseInt(cellValue, 10, 32); err == nil {
|
|
|
- fieldVal.SetInt(num)
|
|
|
- }
|
|
|
- case reflect.Struct: // 处理枚举或时间类型
|
|
|
- switch field.Type {
|
|
|
- case reflect.TypeOf(pasturePb.Genders_Female):
|
|
|
- if cellValue == "公" {
|
|
|
- fieldVal.Set(reflect.ValueOf(pasturePb.Genders_Male))
|
|
|
- } else {
|
|
|
- fieldVal.Set(reflect.ValueOf(pasturePb.Genders_Female))
|
|
|
- }
|
|
|
- // 添加其他自定义类型的处理...
|
|
|
- }
|
|
|
+ if ts.CowKindName != "" {
|
|
|
+ if ck, ok := cowKindMap[ts.CowKindName]; ok {
|
|
|
+ ts.CowKind = ck
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 特殊处理 PenId 和 PenName(依赖 penMap)
|
|
|
- if ts.PenName != "" {
|
|
|
- if pen, ok := penMap[ts.PenName]; ok {
|
|
|
- ts.PenId = pen.Id
|
|
|
+ if ts.PurposeName != "" {
|
|
|
+ if p, ok := purposeMap[ts.PurposeName]; ok {
|
|
|
+ ts.PurposeKind = p
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -390,9 +366,7 @@ func (s *StoreEntry) ImportExcel2(ctx context.Context, data [][]string, excelHea
|
|
|
if len(eventEnterList) <= 0 {
|
|
|
return nil
|
|
|
}
|
|
|
-
|
|
|
- return nil
|
|
|
- return s.ExecExcelData(ctx, userModel.AppPasture.Id, eventEnterList)
|
|
|
+ return s.ExecExcelData(ctx, pastureId, eventEnterList)
|
|
|
}
|
|
|
|
|
|
func (s *StoreEntry) ExecExcelData(ctx context.Context, pastureId int64, dataList []*pasturePb.EventEnterRequest) error {
|