| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- package handlers
- import (
- "bytes"
- "context"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "github.com/nfnt/resize"
- "image"
- "image/jpeg"
- "image/png"
- "os"
- "path/filepath"
- "strings"
- )
- const (
- cameraMachineUrl = "http://127.0.0.1:7074"
- // GetPhotoRecordUrl 获取照片记录
- GetPhotoRecordUrl = "/get_photo_records"
- // RemoveBackground 移除背景
- RemoveBackground = "/remove_background"
- )
- type CameraMachineHandler struct {
- ctx context.Context
- handlerRequest *HandlerRequests
- token string
- }
- func NewCameraMachineHandler(ctx context.Context, token string) *CameraMachineHandler {
- return &CameraMachineHandler{
- token: token,
- ctx: ctx,
- }
- }
- // PhotoRecord 表示单个照片记录
- type PhotoRecord struct {
- ID int `json:"id"`
- ImagePath string `json:"image_path"`
- ImageDealMode int `json:"image_deal_mode"`
- UpdateTime string `json:"update_time"`
- DeleteTime *string `json:"delete_time"`
- ActionID int `json:"action_id"`
- GoodsArtNo string `json:"goods_art_no"`
- ImageIndex int `json:"image_index"`
- PhotoCreateTime string `json:"photo_create_time"`
- CreateTime string `json:"create_time"`
- }
- // PhotoRecordItem 表示包含照片记录和动作名称的项目
- type PhotoRecordItem struct {
- PhotoRecord PhotoRecord `json:"PhotoRecord"`
- ActionName string `json:"action_name"`
- }
- // PhotoRecordList 表示单个货号的照片记录列表
- type PhotoRecordList struct {
- GoodsArtNo string `json:"goods_art_no"`
- ActionTime string `json:"action_time"`
- Items []string `json:"items"`
- }
- // PhotoRecordResponse 表示完整的API响应
- type PhotoRecordResponse struct {
- List []PhotoRecordList `json:"list"`
- CurrentPage int `json:"current_page"`
- Size int `json:"size"`
- TotalCount int `json:"total_count"`
- TotalPages int `json:"total_pages"`
- HasPrev bool `json:"has_prev"`
- HasNext bool `json:"has_next"`
- }
- // convertImageToBase64 将图片文件转换为 base64 编码
- // compressAndEncodeImage 压缩图片并转换为 base64 编码
- func (t *CameraMachineHandler) compressAndEncodeImage(imagePath string, maxWidth uint) (string, error) {
- // 检查文件是否存在
- if _, err := os.Stat(imagePath); os.IsNotExist(err) {
- return "", fmt.Errorf("图片文件不存在: %s", imagePath)
- }
- // 读取图片文件
- file, err := os.Open(imagePath)
- if err != nil {
- return "", fmt.Errorf("打开图片文件失败: %v", err)
- }
- defer file.Close()
- // 根据文件扩展名确定图片类型
- ext := strings.ToLower(filepath.Ext(imagePath))
- var img image.Image
- switch ext {
- case ".jpg", ".jpeg":
- img, err = jpeg.Decode(file)
- case ".png":
- img, err = png.Decode(file)
- default:
- return "", fmt.Errorf("不支持的图片格式: %s", ext)
- }
- if err != nil {
- return "", fmt.Errorf("解码图片失败: %v", err)
- }
- // 获取原始图片尺寸
- originalBounds := img.Bounds()
- originalWidth := uint(originalBounds.Dx())
- originalHeight := uint(originalBounds.Dy())
- // 如果原始宽度小于等于最大宽度,则不需要压缩
- var resizedImg image.Image
- if originalWidth <= maxWidth {
- resizedImg = img
- } else {
- // 按比例计算新高度
- newHeight := uint(float64(originalHeight) * float64(maxWidth) / float64(originalWidth))
- // 调整图片大小
- resizedImg = resize.Resize(maxWidth, newHeight, img, resize.Lanczos3)
- }
- // 将压缩后的图片编码为 JPEG 格式
- var buf bytes.Buffer
- err = jpeg.Encode(&buf, resizedImg, &jpeg.Options{Quality: 80})
- if err != nil {
- return "", fmt.Errorf("编码压缩后的图片失败: %v", err)
- }
- // 将图片数据转换为 base64 编码
- base64Data := base64.StdEncoding.EncodeToString(buf.Bytes())
- return base64Data, nil
- }
- // GetPhotoList 获取拍照记录列表
- func (t *CameraMachineHandler) GetPhotoList(page string) (*PhotoRecordResponse, error) {
- t.handlerRequest = NewHandlerRequests(t.ctx, t.token, cameraMachineUrl)
- request, err := t.handlerRequest.MakeGetRequest(GetPhotoRecordUrl + "?page=" + page)
- if err != nil {
- return nil, err
- }
- // 将返回结果转换为 map 以提取 data 字段
- resultMap, ok := request.(map[string]interface{})
- if !ok {
- return nil, fmt.Errorf("无法将响应转换为 map")
- }
- // 提取 data 字段
- dataValue, exists := resultMap["data"]
- if !exists {
- return nil, fmt.Errorf("响应中不存在 data 字段")
- }
- // 将 data 字段序列化为 JSON
- dataJson, err := json.Marshal(dataValue)
- if err != nil {
- return nil, fmt.Errorf("序列化 data 字段失败: %v", err)
- }
- // 先解析为原始响应结构
- var originalResponse struct {
- List []struct {
- GoodsArtNo string `json:"goods_art_no"`
- ActionTime string `json:"action_time"`
- Items []PhotoRecordItem `json:"items"`
- } `json:"list"`
- CurrentPage int `json:"current_page"`
- Size int `json:"size"`
- TotalCount int `json:"total_count"`
- TotalPages int `json:"total_pages"`
- HasPrev bool `json:"has_prev"`
- HasNext bool `json:"has_next"`
- }
- // 解析为 PhotoRecordResponse 结构
- if err := json.Unmarshal(dataJson, &originalResponse); err != nil {
- return nil, fmt.Errorf("解析原始数据失败: %v", err)
- }
- // 创建新的响应结构,将图片路径转换为 base64
- response := &PhotoRecordResponse{
- CurrentPage: originalResponse.CurrentPage,
- Size: originalResponse.Size,
- TotalCount: originalResponse.TotalCount,
- TotalPages: originalResponse.TotalPages,
- HasPrev: originalResponse.HasPrev,
- HasNext: originalResponse.HasNext,
- }
- for _, list := range originalResponse.List {
- var base64Items []string
- for idx, item := range list.Items {
- if idx >= 1 {
- break
- }
- // 将图片路径转换为 base64
- base64Image, err := t.compressAndEncodeImage(item.PhotoRecord.ImagePath, 400)
- if err != nil {
- fmt.Printf("转换图片失败 %s: %v\n", item.PhotoRecord.ImagePath, err)
- continue
- }
- base64Items = append(base64Items, base64Image)
- }
- photoRecordList := PhotoRecordList{
- GoodsArtNo: list.GoodsArtNo,
- ActionTime: list.ActionTime,
- Items: base64Items,
- }
- response.List = append(response.List, photoRecordList)
- }
- fmt.Printf("数据列表获取成功,共 %d 条记录\n", len(response.List))
- return response, nil
- }
- // RemoveBackground 批量处理抠图操作
- func (t *CameraMachineHandler) RemoveBackground(goodsArtNos []string) (string, error) {
- t.handlerRequest = NewHandlerRequests(t.ctx, t.token, cameraMachineUrl)
- postData := map[string]interface{}{}
- postData["goods_art_nos"] = goodsArtNos
- postData["token"] = t.token
- request, err := t.handlerRequest.MakePostRequest(RemoveBackground, postData)
- if err != nil {
- return "", err
- }
- // 将返回结果转换为 map 以提取 data 字段
- resultMap, ok := request.(map[string]interface{})
- if !ok {
- return "", fmt.Errorf("无法将响应转换为 map")
- }
- // 提取 data 字段
- dataValue, exists := resultMap["data"]
- if !exists {
- return "", fmt.Errorf("响应中不存在 data 字段")
- }
- // 解析 data 字段为 map
- dataMap, ok := dataValue.(map[string]interface{})
- if !ok {
- return "", fmt.Errorf("data 字段不是有效的 map 类型")
- }
- // 获取 output_folder 值
- outputFolder, exists := dataMap["output_folder"]
- if !exists {
- return "", fmt.Errorf("data 字段中不存在 output_folder")
- }
- outputFolderPath, ok := outputFolder.(string)
- if !ok {
- return "", fmt.Errorf("output_folder 不是字符串类型")
- }
- fmt.Printf("输出文件夹路径: %s\n", outputFolderPath)
- return outputFolderPath, nil
- }
|