1
This commit is contained in:
		| @ -70,6 +70,60 @@ func (e LineSymbol) GetPage(c *gin.Context) { | ||||
| 	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") | ||||
| } | ||||
|  | ||||
| // Export 导出交易对列表 | ||||
| // @Summary 导出交易对列表 | ||||
| // @Description 导出交易对列表 | ||||
| // @Tags 交易对列表 | ||||
| // @Param type query string false "类型:1=现货,2=合约" | ||||
| // @Success 200 {object} response.Response "{"code": 200, "data": [...]}" | ||||
| // @Router /api/v1/line-symbol-group/export [get] | ||||
| func (e LineSymbol) Export(c *gin.Context) { | ||||
| 	req := dto.LineSymbolGetPageReq{} | ||||
| 	s := service.LineSymbol{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
| 	err = s.ExportExcel(c, p, &req) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("导出交易对列表失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // GetAll 获取所有交易对名 | ||||
| func (e LineSymbol) GetAll(c *gin.Context) { | ||||
| 	req := dto.LineSymbolGetListReq{} | ||||
| 	s := service.LineSymbol{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	datas, err := s.GetAll(&req) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	e.OK(datas, "查询成功") | ||||
| } | ||||
|  | ||||
| // Get 获取交易对管理 | ||||
| // @Summary 获取交易对管理 | ||||
| // @Description 获取交易对管理 | ||||
|  | ||||
| @ -39,6 +39,7 @@ func registerLinePreOrderRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTM | ||||
| 		r.POST("aiCoinPrice", actions.PermissionAction(), api.QueryAiCoinPrice)      //获取aiCoin买入点 | ||||
|  | ||||
| 		r.POST("/calculate", api.CalculateBreakEevenRatio) //计算亏损后止盈百分比 | ||||
|  | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -28,5 +28,8 @@ func registerLineSymbolRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMid | ||||
| 		r.POST("syncSpotSymbol", api.SyncSpotSymbol) //同步现货交易对 | ||||
| 		r.POST("syncFutSymbol", api.SyncFutSymbol)   //同步合约交易对 | ||||
| 		r.POST("getSymbol", api.GetSymbol)           //获取现货和合约都有的交易对 | ||||
| 		r.GET("/export", api.Export)                 //导出交易对 | ||||
|  | ||||
| 		r.GET("/all", api.GetAll) //获取所有交易对 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -13,7 +13,8 @@ import ( | ||||
|  | ||||
| type LinePreOrderGetPageReq struct { | ||||
| 	dto.Pagination    `search:"-"` | ||||
| 	ExchangeType      string `json:"exchangeType" search:"type:exact;column:exchange_type;table:line_pre_order" comment:"交易所类型 字典exchange_type"` | ||||
| 	ExchangeType      string `json:"exchangeType" form:"exchangeType" search:"type:exact;column:exchange_type;table:line_pre_order" comment:"交易所类型 字典exchange_type"` | ||||
| 	SymbolType        int    `json:"symbolType" form:"symbolType" search:"type:exact;column:symbol_type;table:line_pre_order"` | ||||
| 	ApiId             string `form:"apiId"  search:"type:exact;column:api_id;table:line_pre_order" comment:"api用户"` | ||||
| 	Symbol            string `form:"symbol"  search:"type:exact;column:symbol;table:line_pre_order" comment:"交易对"` | ||||
| 	QuoteSymbol       string `form:"quoteSymbol"  search:"type:exact;column:quote_symbol;table:line_pre_order" comment:"计较货币"` | ||||
|  | ||||
| @ -17,6 +17,13 @@ type LineSymbolGetPageReq struct { | ||||
| 	LineSymbolOrder | ||||
| } | ||||
|  | ||||
| type LineSymbolExportResp struct { | ||||
| 	Symbol     string `json:"symbol" excel:"交易对"` | ||||
| 	Coin       string `json:"coin" excel:"基础货币"` | ||||
| 	Currency   string `json:"currency" excel:"计价货币"` | ||||
| 	SymbolType string `json:"symbolType" excel:"交易对类型"` | ||||
| } | ||||
|  | ||||
| type LineSymbolOrder struct { | ||||
| 	Id         string `form:"idOrder"  search:"type:order;column:id;table:line_symbol"` | ||||
| 	ApiId      string `form:"apiIdOrder"  search:"type:order;column:api_id;table:line_symbol"` | ||||
| @ -34,6 +41,7 @@ type LineSymbolOrder struct { | ||||
|  | ||||
| type LineSymbolGetListReq struct { | ||||
| 	ExchangeType string `json:"exchangeType" form:"exchangeType"` | ||||
| 	Type         string `json:"type" form:"type"` | ||||
| } | ||||
|  | ||||
| func (req *LineSymbolGetListReq) Valid() error { | ||||
|  | ||||
| @ -4,6 +4,7 @@ import ( | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/common/dto" | ||||
| 	common "go-admin/common/models" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type LineSymbolGroupGetPageReq struct { | ||||
| @ -46,8 +47,11 @@ func (s *LineSymbolGroupInsertReq) Generate(model *models.LineSymbolGroup) { | ||||
| 		model.Model = common.Model{Id: s.Id} | ||||
| 	} | ||||
| 	// model.ExchangeType = s.ExchangeType | ||||
| 	model.ExchangeType = s.ExchangeType | ||||
| 	model.GroupName = s.GroupName | ||||
| 	model.Symbol = s.Symbol | ||||
| 	model.Symbol = strings.ReplaceAll(strings.ReplaceAll(s.Symbol, ",", ","), " ", "") | ||||
| 	model.Symbol = strings.ReplaceAll(model.Symbol, "\r\n", ",") | ||||
| 	model.Symbol = strings.ReplaceAll(model.Symbol, "\n", ",") | ||||
| 	model.GroupType = s.GroupType | ||||
| 	model.Type = s.Type | ||||
| 	model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 | ||||
| @ -73,8 +77,11 @@ func (s *LineSymbolGroupUpdateReq) Generate(model *models.LineSymbolGroup) { | ||||
| 	} | ||||
| 	// model.ExchangeType = s.ExchangeType | ||||
| 	model.GroupName = s.GroupName | ||||
| 	model.Symbol = s.Symbol | ||||
| 	model.Symbol = strings.ReplaceAll(strings.ReplaceAll(s.Symbol, ",", ","), " ", "") | ||||
| 	model.Symbol = strings.ReplaceAll(model.Symbol, "\r\n", ",") | ||||
| 	model.Symbol = strings.ReplaceAll(model.Symbol, "\n", ",") | ||||
| 	model.GroupType = s.GroupType | ||||
| 	model.ExchangeType = s.ExchangeType | ||||
| 	model.Type = s.Type | ||||
| 	model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 | ||||
| } | ||||
|  | ||||
| @ -509,18 +509,14 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP | ||||
| 			//加仓、减仓状态 | ||||
| 			tx.Model(&models.LinePreOrderStatus{}).Create(&preOrderStatus) | ||||
|  | ||||
| 			for index := range preOrderExts { | ||||
| 				if index == 0 { | ||||
| 					preOrderExts[index].OrderId = AddOrder.Id | ||||
| 				} | ||||
| 			// for index := range preOrderExts { | ||||
| 			// 	if index == 0 { | ||||
| 			// 		preOrderExts[index].OrderId = AddOrder.Id | ||||
| 			// 	} | ||||
|  | ||||
| 				preOrderExts[index].MainOrderId = AddOrder.Id | ||||
| 			} | ||||
| 			// 	preOrderExts[index].MainOrderId = AddOrder.Id | ||||
| 			// } | ||||
|  | ||||
| 			err = tx.Model(&models.LinePreOrderExt{}).Create(&preOrderExts).Error | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			list := dto.PreOrderRedisList{ | ||||
| 				Id:          AddOrder.Id, | ||||
| 				Symbol:      AddOrder.Symbol, | ||||
| @ -605,12 +601,12 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP | ||||
| 					continue | ||||
| 				} | ||||
|  | ||||
| 				preOrderExts[index].OrderId = addPosition.Id | ||||
| 				if err := e.Orm.Create(&addPosition).Error; err != nil { | ||||
| 					logger.Error("保存加仓单失败") | ||||
| 					return err | ||||
| 				} | ||||
|  | ||||
| 				preOrderExts[index].OrderId = addPosition.Id | ||||
| 				//止盈、减仓 | ||||
| 				orders, err := makeFuturesTakeAndReduce(&addPosition, v, tradeSet) | ||||
|  | ||||
| @ -645,6 +641,11 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			err = tx.Model(&models.LinePreOrderExt{}).Create(&preOrderExts).Error | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			return nil | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| @ -6,6 +6,7 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/bytedance/sonic" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/go-admin-team/go-admin-core/logger" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/service" | ||||
| 	"github.com/shopspring/decimal" | ||||
| @ -115,6 +116,66 @@ func (e *LineSymbol) GetSamePage(c *dto.LineSymbolGetPageReq, p *actions.DataPer | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // 导出excel | ||||
| func (e *LineSymbol) ExportExcel(c *gin.Context, p *actions.DataPermission, req *dto.LineSymbolGetPageReq) error { | ||||
| 	list := make([]models.LineSymbol, 0) | ||||
| 	datas := make([]dto.LineSymbolExportResp, 0) | ||||
| 	var data models.LineSymbol | ||||
| 	var fileName string | ||||
|  | ||||
| 	err := e.Orm.Model(&data). | ||||
| 		Scopes( | ||||
| 			cDto.MakeCondition(req.GetNeedSearch()), | ||||
| 			actions.Permission(data.TableName(), p), | ||||
| 		). | ||||
| 		Find(&list).Error | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for _, v := range list { | ||||
| 		item := dto.LineSymbolExportResp{ | ||||
| 			Symbol:   v.Symbol, | ||||
| 			Coin:     v.BaseAsset, | ||||
| 			Currency: v.QuoteAsset, | ||||
| 		} | ||||
|  | ||||
| 		if v.Type == "1" { | ||||
| 			item.SymbolType = "现货" | ||||
| 		} else { | ||||
| 			item.SymbolType = "合约" | ||||
| 		} | ||||
|  | ||||
| 		datas = append(datas, item) | ||||
| 	} | ||||
|  | ||||
| 	if len(datas) == 0 { | ||||
| 		return errors.New("无数据") | ||||
| 	} | ||||
|  | ||||
| 	if req.Type == "1" { | ||||
| 		fileName = "现货交易对" | ||||
| 	} else { | ||||
| 		fileName = "合约交易对" | ||||
| 	} | ||||
|  | ||||
| 	err = helper.ExportExcel(c, fileName, datas, []string{}) | ||||
|  | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // 获取所有交易对 | ||||
| func (e *LineSymbol) GetAll(req *dto.LineSymbolGetListReq) ([]string, error) { | ||||
| 	result := make([]string, 0) | ||||
|  | ||||
| 	if err := e.Orm.Model(&models.LineSymbol{}).Where("type = ? AND exchange_type =?", req.Type, req.ExchangeType).Pluck("symbol", &result).Error; err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return result, nil | ||||
| } | ||||
|  | ||||
| // Get 获取LineSymbol对象 | ||||
| func (e *LineSymbol) Get(d *dto.LineSymbolGetReq, p *actions.DataPermission, model *models.LineSymbol) error { | ||||
| 	var data models.LineSymbol | ||||
|  | ||||
| @ -11,6 +11,7 @@ import ( | ||||
| 	"go-admin/app/admin/service/dto" | ||||
| 	"go-admin/common/actions" | ||||
| 	cDto "go-admin/common/dto" | ||||
| 	"go-admin/pkg/utility" | ||||
| ) | ||||
|  | ||||
| type LineSymbolGroup struct { | ||||
| @ -73,6 +74,14 @@ func (e *LineSymbolGroup) Insert(c *dto.LineSymbolGroupInsertReq) error { | ||||
| 	var err error | ||||
| 	var data models.LineSymbolGroup | ||||
| 	c.Generate(&data) | ||||
|  | ||||
| 	symbols := availableSymbols(data.Symbol, c.Type, e) | ||||
|  | ||||
| 	if len(symbols) == 0 { | ||||
| 		return errors.New("全部交易对不可用") | ||||
| 	} | ||||
|  | ||||
| 	data.Symbol = strings.Join(symbols, ",") | ||||
| 	err = e.Orm.Create(&data).Error | ||||
| 	if err != nil { | ||||
| 		e.Log.Errorf("LineSymbolGroupService Insert error:%s \r\n", err) | ||||
| @ -81,6 +90,25 @@ func (e *LineSymbolGroup) Insert(c *dto.LineSymbolGroupInsertReq) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // 可用交易对 | ||||
| func availableSymbols(symbols, symbolType string, e *LineSymbolGroup) []string { | ||||
| 	blacks := make([]string, 0) | ||||
| 	newSymbols := make([]string, 0) | ||||
| 	reqSymbols := strings.Split(symbols, ",") | ||||
| 	e.Orm.Model(&models.LineSymbolBlack{}).Where("type=?", symbolType).Select("symbol").Find(&blacks) | ||||
| 	for _, v := range reqSymbols { | ||||
| 		symbol := strings.ToUpper(v) | ||||
|  | ||||
| 		//黑名单跳过 | ||||
| 		if utility.ContainsStr(blacks, symbol) { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		newSymbols = append(newSymbols, symbol) | ||||
| 	} | ||||
| 	return newSymbols | ||||
| } | ||||
|  | ||||
| // Update 修改LineSymbolGroup对象 | ||||
| func (e *LineSymbolGroup) Update(c *dto.LineSymbolGroupUpdateReq, p *actions.DataPermission) error { | ||||
| 	var err error | ||||
| @ -89,7 +117,13 @@ func (e *LineSymbolGroup) Update(c *dto.LineSymbolGroupUpdateReq, p *actions.Dat | ||||
| 		actions.Permission(data.TableName(), p), | ||||
| 	).First(&data, c.GetId()) | ||||
| 	c.Generate(&data) | ||||
| 	symbols := availableSymbols(data.Symbol, c.Type, e) | ||||
|  | ||||
| 	if len(symbols) == 0 { | ||||
| 		return errors.New("全部交易对不可用") | ||||
| 	} | ||||
|  | ||||
| 	data.Symbol = strings.Join(symbols, ",") | ||||
| 	db := e.Orm.Save(&data) | ||||
| 	if err = db.Error; err != nil { | ||||
| 		e.Log.Errorf("LineSymbolGroupService Save error:%s \r\n", err) | ||||
|  | ||||
							
								
								
									
										168
									
								
								common/helper/excel_helper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								common/helper/excel_helper.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,168 @@ | ||||
| package helper | ||||
|  | ||||
| import ( | ||||
| 	"encoding/csv" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/xuri/excelize/v2" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| /* | ||||
| 导出csv文件 | ||||
|  | ||||
|   - @fileName 文件名 不带拓展名 | ||||
|   - @header 文件头 | ||||
|   - @records 内容 | ||||
| */ | ||||
| func ExportCSV(c *gin.Context, fileName string, header []string, records [][]string) error { | ||||
| 	disposition := fmt.Sprintf("attachment; filename=%s.csv", fileName) | ||||
|  | ||||
| 	// Set headers | ||||
| 	c.Header("Content-Description", "File Transfer") | ||||
| 	c.Header("Content-Disposition", disposition) | ||||
| 	c.Header("Content-Type", "text/csv") | ||||
|  | ||||
| 	// Create a CSV writer using the response writer | ||||
| 	writer := csv.NewWriter(c.Writer) | ||||
| 	defer writer.Flush() | ||||
|  | ||||
| 	// Write CSV header | ||||
| 	writer.Write(header) | ||||
|  | ||||
| 	for _, record := range records { | ||||
| 		writer.Write(record) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| /* | ||||
| 导出excel | ||||
|  | ||||
|   - @fileName 文件名称 | ||||
|   - @data 数据源 | ||||
|   - @ingore 忽略header | ||||
| */ | ||||
| func ExportExcel[T any](c *gin.Context, fileName string, data []T, ingore []string) error { | ||||
| 	if len(data) == 0 { | ||||
| 		return errors.New("无导出记录") | ||||
| 	} | ||||
| 	// Create a new Excel file | ||||
| 	f := excelize.NewFile() | ||||
| 	// Use reflection to get the header from struct tags | ||||
| 	t := reflect.TypeOf(data[0]) | ||||
| 	headers := []string{} | ||||
| 	for i := 0; i < t.NumField(); i++ { | ||||
| 		field := t.Field(i) | ||||
| 		excelTag := field.Tag.Get("excel") | ||||
| 		if excelTag != "" && !ArrayAny(ingore, excelTag) { | ||||
| 			headers = append(headers, excelTag) | ||||
| 		} | ||||
| 	} | ||||
| 	// Set headers | ||||
| 	for i, header := range headers { | ||||
| 		col := string('A' + i) | ||||
| 		cell := fmt.Sprintf("%s1", col) | ||||
| 		f.SetCellValue("Sheet1", cell, header) | ||||
| 	} | ||||
|  | ||||
| 	// Fill rows with data | ||||
| 	for rowIndex, item := range data { | ||||
| 		rowValue := reflect.ValueOf(item) | ||||
| 		rowType := rowValue.Type() | ||||
| 		for colIndex, header := range headers { | ||||
| 			col := string('A' + colIndex) | ||||
| 			cell := fmt.Sprintf("%s%d", col, rowIndex+2) | ||||
| 			var fieldValue reflect.Value | ||||
|  | ||||
| 			for i := 0; i < rowType.NumField(); i++ { | ||||
| 				field := rowType.Field(i) | ||||
| 				if strings.EqualFold(field.Tag.Get("excel"), header) { | ||||
| 					fieldValue = rowValue.Field(i) | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// Check if the fieldValue is valid before accessing it | ||||
| 			if fieldValue.IsValid() && fieldValue.CanInterface() { | ||||
| 				//f.SetCellValue("Sheet1", cell, fieldValue.Interface()) | ||||
| 				value := fieldValue.Interface() | ||||
|  | ||||
| 				// Ensure the value is a string, convert it if necessary | ||||
| 				var stringValue string | ||||
| 				if v, ok := value.(string); ok { | ||||
| 					stringValue = v // If it's a string, use it directly | ||||
| 				} else { | ||||
| 					stringValue = fmt.Sprintf("%v", value) // Otherwise, convert to string | ||||
| 				} | ||||
| 				f.SetCellValue("Sheet1", cell, stringValue) | ||||
| 			} else { | ||||
| 				// Handle the case where fieldValue is invalid or nil | ||||
| 				f.SetCellValue("Sheet1", cell, "") | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	// Set response headers and send the file to the client | ||||
|  | ||||
| 	// c.Writer.Header().Set("Content-Disposition", "attachment; filename=test.xlsx") | ||||
| 	// c.Writer.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=binary") | ||||
| 	// c.Writer.Header().Set("Content-Transfer-Encoding", "binary") | ||||
| 	// c.Writer.Header().Set("Expires", "0") | ||||
| 	// c.Writer.Header().Set("Cache-Control", "must-revalidate") | ||||
| 	// c.Writer.Header().Set("Pragma", "public") | ||||
| 	c.Header("Content-Description", "File Transfer") | ||||
| 	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s.xlsx", fileName)) | ||||
| 	c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") | ||||
| 	c.Header("Content-Transfer-Encoding", "binary") | ||||
| 	c.Header("Expires", "0") | ||||
| 	c.Header("Cache-Control", "must-revalidate") | ||||
| 	c.Header("Pragma", "public") | ||||
| 	c.Header("Content-Encoding", "") | ||||
| 	//fmt.Println("c.Writer.Header():", c.Writer.Header()) | ||||
| 	if _, err := f.WriteTo(c.Writer); err != nil { | ||||
| 		log.Println("Error writing file:", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| 	//return f.WriteTo(c.Writer) | ||||
| } | ||||
|  | ||||
| func MapExcelToStruct[T any](rows [][]string, headers []string) ([]T, error) { | ||||
| 	var results []T | ||||
| 	if len(rows) == 0 { | ||||
| 		return results, nil | ||||
| 	} | ||||
|  | ||||
| 	for _, row := range rows { | ||||
| 		var result T | ||||
| 		v := reflect.ValueOf(&result).Elem() | ||||
|  | ||||
| 		for i, header := range headers { | ||||
| 			fieldName := "" | ||||
| 			for j := 0; j < v.NumField(); j++ { | ||||
| 				field := v.Type().Field(j) | ||||
| 				tag := field.Tag.Get("excel") | ||||
| 				if strings.EqualFold(tag, header) { | ||||
| 					fieldName = field.Name | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if fieldName != "" && i < len(row) { | ||||
| 				field := v.FieldByName(fieldName) | ||||
| 				if field.IsValid() && field.CanSet() { | ||||
| 					field.Set(reflect.ValueOf(row[i]).Convert(field.Type())) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		results = append(results, result) | ||||
| 	} | ||||
|  | ||||
| 	return results, nil | ||||
| } | ||||
							
								
								
									
										52
									
								
								common/helper/extension_helper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								common/helper/extension_helper.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| package helper | ||||
|  | ||||
| /* | ||||
| 判断是否存在 | ||||
|  | ||||
|   - @arr 数组 | ||||
|   - @value 值 | ||||
| */ | ||||
| func ArrayAny[T comparable](arr []T, value T) bool { | ||||
| 	for _, v := range arr { | ||||
| 		if v == value { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // 定义一个条件函数类型 | ||||
| type ConditionFunc[T any] func(T) bool | ||||
|  | ||||
| /* | ||||
| 判断是否存在 | ||||
|  | ||||
|   - @arr 数组 | ||||
|  | ||||
|   - @condition 判断函数 | ||||
|  | ||||
|     @return 对象指针 | ||||
| */ | ||||
| func ArrayAnyExtension[T any](arr *[]T, condition ConditionFunc[T]) *T { | ||||
| 	for _, v := range *arr { | ||||
| 		if condition(v) { | ||||
| 			return &v | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func RemoveDuplicates(nums []int64) []int64 { | ||||
| 	m := make(map[int64]bool) | ||||
| 	result := []int64{} | ||||
|  | ||||
| 	for _, num := range nums { | ||||
| 		if !m[num] { | ||||
| 			m[num] = true | ||||
| 			result = append(result, num) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return result | ||||
| } | ||||
							
								
								
									
										8
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								go.mod
									
									
									
									
									
								
							| @ -134,6 +134,7 @@ require ( | ||||
| 	github.com/mitchellh/reflectwalk v1.0.0 // indirect | ||||
| 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect | ||||
| 	github.com/modern-go/reflect2 v1.0.2 // indirect | ||||
| 	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect | ||||
| 	github.com/mojocn/base64Captcha v1.3.5 // indirect | ||||
| 	github.com/nsqio/go-nsq v1.1.0 // indirect | ||||
| 	github.com/nyaruka/phonenumbers v1.0.55 // indirect | ||||
| @ -143,6 +144,8 @@ require ( | ||||
| 	github.com/prometheus/common v0.45.0 // indirect | ||||
| 	github.com/prometheus/procfs v0.12.0 // indirect | ||||
| 	github.com/redis/go-redis/v9 v9.3.0 // indirect | ||||
| 	github.com/richardlehane/mscfb v1.0.4 // indirect | ||||
| 	github.com/richardlehane/msoleps v1.0.4 // indirect | ||||
| 	github.com/russross/blackfriday/v2 v2.1.0 // indirect | ||||
| 	github.com/shamsher31/goimgext v1.0.0 // indirect | ||||
| 	github.com/shoenig/go-m1cpu v0.1.6 // indirect | ||||
| @ -161,10 +164,13 @@ require ( | ||||
| 	github.com/valyala/bytebufferpool v1.0.0 // indirect | ||||
| 	github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect | ||||
| 	github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect | ||||
| 	github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect | ||||
| 	github.com/xuri/excelize/v2 v2.9.0 // indirect | ||||
| 	github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect | ||||
| 	github.com/yusufpapurcu/wmi v1.2.3 // indirect | ||||
| 	go.uber.org/multierr v1.10.0 // indirect | ||||
| 	golang.org/x/arch v0.3.0 // indirect | ||||
| 	golang.org/x/image v0.13.0 // indirect | ||||
| 	golang.org/x/image v0.18.0 // indirect | ||||
| 	golang.org/x/mod v0.17.0 // indirect | ||||
| 	golang.org/x/sync v0.9.0 // indirect | ||||
| 	golang.org/x/sys v0.27.0 // indirect | ||||
|  | ||||
		Reference in New Issue
	
	Block a user