Browse Source

2024-03-15

zoie 1 year ago
parent
commit
580e296f1d

+ 23 - 15
conf/app.conf

@@ -6,19 +6,19 @@ copyrequestbody = true
 EnableDocs = true
 
 # 数据库配置(Mysql)
-# mysqlUrlPort = "192.168.11.77:3306"
-# mysqlDB = "medical_erp"
-# mysqlUser = "medical_erp"
-# mysqlPass= "XMzTDthD4By3ArjG"
-# mysqlMaxConns = 100
-# MysqlMaxOpen = 200
-# 数据库配置(Mysql)
-mysqlUrlPort = "127.0.0.1:40306"
-mysqlDB = "godown"
-mysqlUser = "godown"
-mysqlPass= "wCHDXHL35kZGSD8r"
+mysqlUrlPort = "192.168.11.77:3306"
+mysqlDB = "medical_erp"
+mysqlUser = "medical_erp"
+mysqlPass= "XMzTDthD4By3ArjG"
 mysqlMaxConns = 100
 MysqlMaxOpen = 200
+# 数据库配置(Mysql)
+# mysqlUrlPort = "127.0.0.1:40306"
+# mysqlDB = "godown"
+# mysqlUser = "godown"
+# mysqlPass= "wCHDXHL35kZGSD8r"
+# mysqlMaxConns = 100
+# MysqlMaxOpen = 200
 
 # 日志配置
 # 0-控制台输出 1-文件输出 2-文件和控制台输出
@@ -35,8 +35,8 @@ slow_threshold = 200
 maxlines = 10000
 
 #redis
-# Redis_address = "192.168.11.77:6379"
-Redis_address = "127.0.0.1:43379"
+Redis_address = "192.168.11.77:6379"
+# Redis_address = "127.0.0.1:43379"
 Redis_password = ""
 Redis_dbNum = "3"
 
@@ -49,7 +49,7 @@ FilterNotEnterDeptURL = "/api/medicine-template/init"
 
 # 统一身份认证
 # OAuth_baseUrl = "http://192.168.11.77:8100"
-OAuth_baseUrl = "http://127.0.0.1:8000"
+OAuth_baseUrl = "http://127.0.0.1:6400"
 # 服务发现服务信息
 Service_number = "q9YeglML"
 Service_authCode = "3EDJRaagFTVVo2Ilo80nHJfLVN1O1234"
@@ -60,4 +60,12 @@ Service_RoleApiUrl = "/api/role-api"
 # 码上放心
 MSFX_baseUrl = "http://ykm.fjxtj.com/query.aspx"
 MSFX_user = "POCU9VN"
-MSFX_mock = false
+MSFX_mock = false
+
+# 七牛云静态资源
+Qiniu_AccessKey = "-8ezB_d-8-eUFTMvhOGbGzgeQRPeKQnaQ3DBcUxo"
+Qiniu_SecretKey = "KFhkYxTAJ2ZPN3ZS3euTsfWk8-C92rKgkhAMkDRN"
+Qiniu_BUCKET = "godownoss"
+Qiniu_Url = "https://godownoss.coldbaozhida.com/"
+
+BZD_pcodeUrl = "https://pcode.baozhida.cn/api/"

+ 72 - 0
conf/app2.conf

@@ -0,0 +1,72 @@
+appname = Medical_ERP
+httpport = 8083
+runmode = dev
+autorender = false
+copyrequestbody = true
+EnableDocs = true
+
+# 数据库配置(Mysql)
+# mysqlUrlPort = "192.168.11.77:3306"
+# mysqlDB = "medical_erp"
+# mysqlUser = "medical_erp"
+# mysqlPass= "XMzTDthD4By3ArjG"
+# mysqlMaxConns = 100
+# MysqlMaxOpen = 200
+# 数据库配置(Mysql)
+mysqlUrlPort = "127.0.0.1:40306"
+mysqlDB = "godown"
+mysqlUser = "godown"
+mysqlPass= "wCHDXHL35kZGSD8r"
+mysqlMaxConns = 100
+MysqlMaxOpen = 200
+
+# 日志配置
+# 0-控制台输出 1-文件输出 2-文件和控制台输出
+adapter_type = 2
+# 文件最多保存多少天
+maxdays = 7
+# 日志级别 (0-紧急 1-报警 2-严重错误 3-错误 4-警告 5-注意 6-信息 7-调试)
+level = 7
+# SQL日志级别 (1-静音 2-错误 3-警告 4-信息). 注意: sql日志只在level大于等于5级别才会输出。
+sqlloglevel = 4
+# 慢SQL阈值(毫秒)。慢SQL会在sqlloglevel大于等于3时输出。
+slow_threshold = 200
+# 每个文件保存的最大行数
+maxlines = 10000
+
+#redis
+# Redis_address = "192.168.11.77:6379"
+Redis_address = "127.0.0.1:43379"
+Redis_password = ""
+Redis_dbNum = "3"
+
+#不验证登录URL
+FilterExcludeURL = ""
+#只验证登录URL
+FilterOnlyLoginCheckURL = "/api/role-api"
+# 不进入公司的url
+FilterNotEnterDeptURL = "/api/medicine-template/init"
+
+# 统一身份认证
+# OAuth_baseUrl = "http://192.168.11.77:8100"
+OAuth_baseUrl = "http://127.0.0.1:8000"
+# 服务发现服务信息
+Service_number = "q9YeglML"
+Service_authCode = "3EDJRaagFTVVo2Ilo80nHJfLVN1O1234"
+Service_name = "医药进销存综合管理系统"
+Service_Host = "http://127.0.0.1:8110"
+Service_RoleApiUrl = "/api/role-api"
+
+# 码上放心
+MSFX_baseUrl = "http://ykm.fjxtj.com/query.aspx"
+MSFX_user = "POCU9VN"
+MSFX_mock = false
+
+# 七牛云静态资源
+Qiniu_AccessKey = "-8ezB_d-8-eUFTMvhOGbGzgeQRPeKQnaQ3DBcUxo"
+Qiniu_SecretKey = "KFhkYxTAJ2ZPN3ZS3euTsfWk8-C92rKgkhAMkDRN"
+Qiniu_BUCKET = "godownoss"
+Qiniu_Url = "https://godownoss.coldbaozhida.com/"
+
+# 宝智达溯码平台
+BZD_pcodeUrl = "https://pcode.baozhida.cn/api/"

+ 7 - 0
conf/conf.go

@@ -10,3 +10,10 @@ var Redis_password, _ = beego.AppConfig.String("Redis_password")
 var Redis_dbNum, _ = beego.AppConfig.String("Redis_dbNum")
 
 var OAuthBaseUrl, _ = beego.AppConfig.String("OAuth_baseUrl")
+
+var Qiniu_AccessKey, _ = beego.AppConfig.String("Qiniu_AccessKey")
+var Qiniu_SecretKey, _ = beego.AppConfig.String("Qiniu_SecretKey")
+var Qiniu_BUCKET, _ = beego.AppConfig.String("Qiniu_BUCKET")
+var OssQiniu = "https://coldoss.coldbaozhida.com"
+
+var BZD_pcodeUrl, _ = beego.AppConfig.String("BZD_pcodeUrl")

+ 39 - 0
controllers/medicine.go

@@ -4,6 +4,7 @@ import (
 	"Medical_ERP/common/global"
 	"Medical_ERP/common/redis"
 	_ "Medical_ERP/common/response"
+	"Medical_ERP/conf"
 	"Medical_ERP/dto"
 	"Medical_ERP/services"
 	"Medical_ERP/utils"
@@ -74,6 +75,44 @@ func (c MedicineController) MSFXQuery() {
 		c.Error(400, err, err.Error())
 		return
 	}
+
+	if strings.HasPrefix(code, "9") {
+		// 宝智达溯码平台
+		type Res struct {
+			Code int
+			Msg  string
+			Data struct {
+				CodeNum    string
+				CreateTime string
+				Data       map[string]interface{}
+			}
+		}
+		var res Res
+		client := resty.New()
+		resp, err := client.R().Get(conf.BZD_pcodeUrl + code)
+
+		if err != nil {
+			c.Error(400, err, err.Error())
+			return
+		}
+
+		if err = json.Unmarshal(resp.Body(), &res); err != nil {
+			c.Error(400, err, err.Error())
+			return
+		}
+		if res.Code != 200 {
+			err = errors.New(res.Msg)
+			c.Error(400, err, err.Error())
+			return
+		}
+
+		info_ := make([]map[string]interface{}, 0)
+		info_ = append(info_, res.Data.Data)
+		c.OK(info_, "查询成功")
+		return
+
+	}
+
 	MSFX_baseUrl, _ := beego.AppConfig.String("MSFX_baseUrl")
 	MSFX_user, _ := beego.AppConfig.String("MSFX_user")
 	MSFX_mock := beego.AppConfig.DefaultBool("MSFX_mock", true)

+ 75 - 0
controllers/medicine_img.go

@@ -0,0 +1,75 @@
+package controllers
+
+import (
+	"Medical_ERP/common/actions"
+	"Medical_ERP/common/global"
+	"Medical_ERP/dto"
+	"Medical_ERP/models"
+	"Medical_ERP/services"
+	context2 "github.com/beego/beego/v2/adapter/context"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/beegouser"
+)
+
+type MedicineImgController struct {
+	BaseController
+}
+
+// List 获取规格列表
+// @Summary 获取规格列表
+// @Description 获取规格列表
+// @Tags 规格
+// @Param body body dto.MedicineImgPageReq true "body"
+// @Success 200 {object} response.Page{list=[]models.MedicineImg} "{"code": 200, "data": [...]}"
+// @Router /spec/list [post]
+// @Security Bearer
+func (c MedicineImgController) List() {
+	s := services.MedicineImg{}
+	reqData := dto.MedicineImgPageReq{}
+	if err := c.ParseAndValidate(&c.Ctx.Input.RequestBody, &reqData); err != nil {
+		c.Error(global.ParseFormErr, err, err.Error())
+		return
+	}
+	p := actions.GetPermissionFromContext(c.Ctx)
+	rootId, err := s.GetRootID((*context2.Context)(c.Ctx), p.DeptId)
+	if err != nil {
+		c.Error(global.BadRequest, err, err.Error())
+		return
+	}
+	list := make([]models.MedicineImg, 0)
+	var count int64
+	//数据权限检查
+	err = s.GetPage(&reqData, &list, &count, rootId, p)
+	if err != nil {
+		c.Error(global.BadRequest, err, err.Error())
+		return
+	}
+
+	c.PageOK(list, int(count), reqData.GetPageIndex(), reqData.GetPageSize(), "查询成功")
+}
+
+// Edit 修改规格
+// @Summary 修改规格
+// @Description 修改规格
+// @Tags 规格
+// @Accept  application/json
+// @MedicineImg application/json
+// @Param data body dto.MedicineImgUpdateReq true "body"
+// @Success 200 {object} response.Response "{"code": 200, "data": [...]}"
+// @Router /spec/edit [post]
+// @Security Bearer
+func (c MedicineImgController) Edit() {
+	s := services.MedicineImg{}
+	reqData := dto.MedicineImgUpdateReq{}
+	if err := c.ParseAndValidate(&c.Ctx.Input.RequestBody, &reqData); err != nil {
+		c.Error(global.ParseFormErr, err, err.Error())
+		return
+	}
+	reqData.SetUpdateBy(beegouser.GetUserId(c.Ctx))
+
+	err := s.Update(&reqData)
+	if err != nil {
+		c.Error(500, err, err.Error())
+		return
+	}
+	c.OK(reqData.GetId(), "更新成功")
+}

+ 106 - 0
controllers/product_code.go

@@ -0,0 +1,106 @@
+package controllers
+
+import (
+	"Medical_ERP/common/actions"
+	"Medical_ERP/common/global"
+	_ "Medical_ERP/common/response"
+	"Medical_ERP/conf"
+	"Medical_ERP/dto"
+	"Medical_ERP/models"
+	"Medical_ERP/services"
+	"encoding/json"
+	"errors"
+	"github.com/go-resty/resty/v2"
+	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/beegouser"
+)
+
+type ProductCodeController struct {
+	BaseController
+}
+
+// Gen 生成条码
+// @Summary 生成条码
+// @Description 生成条码
+// @Tags 产品条码
+// @Param body body dto.BarcodePageReq true "body"
+// @Success 200 {object} response.Page "{"code": 200, "data": [...]}"
+// @Router /sales/list [post]
+// @Security Bearer
+func (c ProductCodeController) Gen() {
+	s := services.ProductCode{}
+	reqData := dto.GenProductCodePageReq{}
+	if err := c.ParseAndValidate(&c.Ctx.Input.RequestBody, &reqData); err != nil {
+		c.Error(global.ParseFormErr, err, err.Error())
+		return
+	}
+
+	deptId := beegouser.GetDeptId(c.Ctx)
+	err := s.CreateProductCode(&reqData, deptId)
+	if err != nil {
+		c.Error(500, err, err.Error())
+		return
+	}
+
+	client := resty.New()
+	resp, err := client.R().
+		SetBody(map[string]interface{}{
+			"product_name":    reqData.Product,
+			"enterprise_name": reqData.Enterprise,
+			"spec_name":       reqData.Spec,
+			"batch_number":    reqData.BatchNumber,
+			"quantity":        reqData.Quantity,
+		}).
+		Post(conf.BZD_pcodeUrl)
+
+	if err != nil {
+		c.Error(400, err, err.Error())
+		return
+	}
+
+	type Resp struct {
+		Code int    `json:"Code"`
+		Msg  string `json:"Msg"`
+		Data string `json:"Data"`
+	}
+
+	var res Resp
+	if err = json.Unmarshal(resp.Body(), &res); err != nil {
+		c.Error(400, err, err.Error())
+		return
+	}
+	if res.Code != 200 {
+		err = errors.New(res.Msg)
+		c.Error(400, err, err.Error())
+	}
+
+	c.OK(res.Data, "生成成功")
+}
+
+// List 通过关键字查询条码信息
+// @Summary 生成条码
+// @Description 生成条码
+// @Tags 产品条码
+// @Param body body dto.BarcodePageReq true "body"
+// @Success 200 {object} response.Page "{"code": 200, "data": [...]}"
+// @Router /sales/list [post]
+// @Security Bearer
+func (c ProductCodeController) List() {
+	s := services.ProductCode{}
+	reqData := dto.ProductCodePageReq{}
+	if err := c.ParseAndValidate(&c.Ctx.Input.RequestBody, &reqData); err != nil {
+		c.Error(global.ParseFormErr, err, err.Error())
+		return
+	}
+
+	list := make([]models.ProductCode, 0)
+	var count int64
+	//数据权限检查
+	p := actions.GetPermissionFromContext(c.Ctx)
+	err := s.GetPage(&reqData, &list, &count, p)
+	if err != nil {
+		c.Error(global.BadRequest, err, err.Error())
+		return
+	}
+
+	c.PageOK(list, int(count), reqData.GetPageIndex(), reqData.GetPageSize(), "查询成功")
+}

+ 2 - 2
controllers/sales.go

@@ -252,7 +252,7 @@ func (c SalesController) SalesReportExcel() {
 				{Type: "right", Color: "000000", Style: 1},
 			},
 		})
-	f.SetCellStyle("Sheet1", "A2", "J2", Style1)
+	f.SetCellStyle("Sheet1", "A2", "G2", Style1)
 	Style2, _ := f.NewStyle(
 		&excelize.Style{
 			Font:      &excelize.Font{Size: 12, Family: "宋体"},
@@ -264,7 +264,7 @@ func (c SalesController) SalesReportExcel() {
 				{Type: "right", Color: "000000", Style: 1},
 			},
 		})
-	f.SetCellStyle("Sheet1", "A3", fmt.Sprintf("J%d", line), Style2)
+	f.SetCellStyle("Sheet1", "A3", fmt.Sprintf("G%d", line), Style2)
 
 	filename := "销售报表" + time.Now().Format("20060102150405") + ".xlsx"
 	// 保存文件

+ 109 - 232
controllers/stock_template.go

@@ -1,6 +1,7 @@
 package controllers
 
 import (
+	"Medical_ERP/common/actions"
 	"Medical_ERP/common/global"
 	_ "Medical_ERP/common/response"
 	"Medical_ERP/dto"
@@ -13,12 +14,18 @@ import (
 	"baliance.com/gooxml/schema/soo/wml"
 	"errors"
 	"fmt"
+	context2 "github.com/beego/beego/v2/adapter/context"
 	"github.com/boombuler/barcode"
 	"github.com/boombuler/barcode/code128"
 	"github.com/ser163/png2j"
 	"github.com/signintech/gopdf"
 	"github.com/xuri/excelize/v2"
 	"gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/beegouser"
+	"image/jpeg"
+	"path"
+	"strings"
+
+	_ "image/jpeg"
 	"image/png"
 	"os"
 	"time"
@@ -650,7 +657,7 @@ func (c StockTemplateController) StockTemplateInventoryPdf(reqData dto.StockTemp
 
 	pdf.SetFont("simsun", "", 10)
 	x := 20.
-	for i := 0; i < 10; i++ {
+	for i := 0; i < 9; i++ {
 		x += cols1[i]
 	}
 	pdf.SetXY(x, 90)
@@ -1696,9 +1703,17 @@ func getImageBytes(filePath string) []byte {
 }
 func (c StockTemplateController) TransportRecordPdf(reqData models.TransportRecord) {
 	s := services.StockTemplate{}
+	imgSvc := services.MedicineImg{}
 	barcodeServ := services.Barcode{}
 	deptId := beegouser.GetDeptId(c.Ctx)
 
+	p := actions.GetPermissionFromContext(c.Ctx)
+	rootId, err := imgSvc.GetRootID((*context2.Context)(c.Ctx), p.DeptId)
+	if err != nil {
+		c.Error(global.BadRequest, err, err.Error())
+		return
+	}
+
 	list, err := s.StockTemplateTransportRecordWord(&reqData, deptId)
 	if err != nil {
 		c.Error(500, err, err.Error())
@@ -1718,7 +1733,7 @@ func (c StockTemplateController) TransportRecordPdf(reqData models.TransportReco
 	// 创建一个要输出数据的文件
 	imgPath := "ofile/img/" + code + ".png"
 	file, _ := os.Create(imgPath)
-	//defer file.Close()
+	defer file.Close()
 
 	// 设置图片像素大小
 	qrCode, _ := barcode.Scale(cs, 205, 50)
@@ -1729,28 +1744,31 @@ func (c StockTemplateController) TransportRecordPdf(reqData models.TransportReco
 
 	header := []string{"品种", "生产企业", "批准文号", "批签发合格编号", "规格(剂/支或粒)", "生产日期", "批号", "失效日期", "数量", "单位"}
 	rows := [][]string{}
+	imgList := []string{}
+
 	for _, row := range list {
 		temp := []string{}
-		temp = append(temp, fmt.Sprintf("%s", row[models.FieldProductName]))
-		temp = append(temp, fmt.Sprintf("%s", row[models.FieldEnterpriseName]))
-		if row[models.FieldApprovalNumber] == nil {
-			temp = append(temp, "")
-		} else {
-			temp = append(temp, fmt.Sprintf("%s", row[models.FieldApprovalNumber]))
-		}
-		if row[models.FieldQualificationNumber] == nil {
-			temp = append(temp, "")
-		} else {
-			temp = append(temp, fmt.Sprintf("%s", row[models.FieldQualificationNumber]))
-		}
-
-		temp = append(temp, fmt.Sprintf("%s", row[models.FieldSpecName]))
-		temp = append(temp, fmt.Sprintf("%s", utils.ToDate(row[models.FieldProducedDate])))
-		temp = append(temp, fmt.Sprintf("%s", row[models.FieldBatchNumber]))
-		temp = append(temp, fmt.Sprintf("%s", utils.ToDate(row[models.FieldExpiryDate])))
+		product := utils.ToString(row[models.FieldProductName])
+		enterprise := utils.ToString(row[models.FieldEnterpriseName])
+		spec := utils.ToString(row[models.FieldSpecName])
+		batchNumber := utils.ToString(row[models.FieldBatchNumber])
+		temp = append(temp, product)
+		temp = append(temp, fmt.Sprintf("%s", enterprise))
+		temp = append(temp, utils.ToString(row[models.FieldApprovalNumber]))
+		temp = append(temp, utils.ToString(row[models.FieldQualificationNumber]))
+		temp = append(temp, spec)
+		temp = append(temp, utils.ToDate(row[models.FieldProducedDate]))
+		temp = append(temp, batchNumber)
+		temp = append(temp, utils.ToDate(row[models.FieldExpiryDate]))
 		temp = append(temp, fmt.Sprintf("%d", utils.ToInt(row["quantity"])))
-		temp = append(temp, fmt.Sprintf("%s", row[models.FieldUnitName]))
+		temp = append(temp, utils.ToString(row[models.FieldUnitName]))
 		rows = append(rows, temp)
+
+		// 获取药品信息图片
+		img, err := imgSvc.Get(deptId, rootId, product, enterprise, spec, batchNumber)
+		if err == nil && img.Img != "" {
+			imgList = append(temp, img.Img)
+		}
 	}
 	if len(list) < 11 {
 		for i := 0; i < 11-len(list); i++ {
@@ -1992,11 +2010,70 @@ func (c StockTemplateController) TransportRecordPdf(reqData models.TransportReco
 	pdf.SetCharSpacing(0.5)
 	txt := "填表说明:本表供疫苗配送企业、疾病预防控制机构、接种单位疫苗运输时填写;出入库单号为单位编码+年月日+2位流水号;运输超过6小时需记录途中温度,间隔不超过6小时;使用无自动温度显示的冰排保冷设备时,只在启运和达到时填写冰排状态(冻结、冰水混合物、完全融化)。"
 	pdf.MultiCell(&gopdf.Rect{W: 555, H: 50}, txt)
+	imgList = append(imgList,
+		"https://bzdcdn.baozhida.cn/2024-02-18/9be06bd0aa654c4c80fa7ce858db73be.png,https://bzdcdn.baozhida.cn/2024-02-19/85219d304dc44d0ea4ce7f29bbc2c89e.jpg",
+		"https://pic17.997788.com/_pic_search/00/21/61/03/21610311.jpg",
+		"https://file2.renrendoc.com/fileroot_temp3/2021-8/16/599ee5c5-2f8a-4648-ba9b-cf0a663d7e89/599ee5c5-2f8a-4648-ba9b-cf0a663d7e891.gif",
+	)
+	for _, v := range imgList {
+		urlList := strings.Split(strings.Trim(v, ","), ",")
+		for _, url := range urlList {
+			pdf.AddPage()
+			imgH, errImg := utils.GetImage(url)
+			if errImg != nil {
+				err = errors.New("获取图片失败")
+				c.Error(500, err, err.Error())
+				return
+			}
+			imgWidth := float64(imgH.Bounds().Dx())
+			imgHeight := float64(imgH.Bounds().Dy())
+			W, H := imgWidth, imgHeight
+			if imgWidth > imgHeight && imgWidth > 555 {
+				W = 555
+				H = 555 * float64(imgHeight) / float64(imgWidth)
+			}
+
+			if imgWidth < imgHeight && imgWidth > 760 {
+				W = 760 * float64(imgWidth) / float64(imgHeight)
+				H = 760
+				if W > 555 {
+					H = 555 * 760 / W
+					W = 555
+				}
+
+			}
+
+			if strings.Contains(url, ".png") {
+				err = pdf.ImageFrom(imgH, (595-W)/2, (840-H)/2, &gopdf.Rect{W: W, H: H})
+				if err != nil {
+					err = errors.New("写入图片失败")
+					c.Error(500, err, err.Error())
+					return
+				}
+			} else {
+				fileName := "./ofile/" + path.Base(url)
+				f, _ := os.Create(fileName)
+				defer f.Close()
+				defer func() {
+					os.Remove(fileName)
+				}()
+				jpeg.Encode(f, imgH, &jpeg.Options{100})
+				err = pdf.Image(fileName, (595-W)/2, (840-H)/2, &gopdf.Rect{W: W, H: H})
+				if err != nil {
+					err = errors.New("写入图片失败")
+					c.Error(500, err, err.Error())
+					return
+				}
+			}
+
+		}
+
+	}
+
+	for i := 0; i < pdf.GetNumberOfPages(); i++ {
+
+	}
 
-	pdf.AddFooter(func() {
-		pdf.SetY(y + 15)
-		pdf.Cell(nil, fmt.Sprintf("第 %d 页 / 共 %d 页", pdf.GetNumberOfPages(), pdf.GetNumberOfPages()))
-	})
 	filename := "运输记录表" + time.Now().Format("20060102150405") + ".pdf"
 	// 保存文件
 	if err = pdf.WritePdf("ofile/" + filename); err != nil {
@@ -2144,7 +2221,7 @@ func (c StockTemplateController) StockInquiryExcel() {
 			Font:      &excelize.Font{Bold: true, Size: 20, Family: "宋体"},
 			Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"},
 		})
-	f.MergeCell("Sheet1", "A1", "L1")
+	f.MergeCell("Sheet1", "A1", "K1")
 	f.SetRowStyle("Sheet1", 1, 1, StyleTitle)
 	f.SetRowHeight("Sheet1", 1, 50)
 	f.SetCellValue("Sheet1", "A1", fmt.Sprintf("库存信息表(%s)", time.Now().Format("2006-01-02 15:04:05")))
@@ -2168,7 +2245,7 @@ func (c StockTemplateController) StockInquiryExcel() {
 	f.SetColWidth("Sheet1", "F", "G", 10)
 	f.SetColWidth("Sheet1", "G", "I", 15)
 	f.SetColWidth("Sheet1", "I", "J", 12)
-	f.SetColWidth("Sheet1", "J", "L", 15)
+	f.SetColWidth("Sheet1", "J", "K", 15)
 
 	line := 2
 
@@ -2184,10 +2261,10 @@ func (c StockTemplateController) StockInquiryExcel() {
 		f.SetCellValue("Sheet1", fmt.Sprintf("F%d", line), v["balance"])
 		f.SetCellValue("Sheet1", fmt.Sprintf("G%d", line), utils.ToFloat64(v["unit_price"]))
 		//f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), utils.ToFloat64(v["sales_unit_price"]))
-		f.SetCellValue("Sheet1", fmt.Sprintf("I%d", line), v["batch_number"])
-		f.SetCellValue("Sheet1", fmt.Sprintf("J%d", line), v[models.FieldExpiryDate])
-		f.SetCellValue("Sheet1", fmt.Sprintf("K%d", line), v["approval_number"])
-		f.SetCellValue("Sheet1", fmt.Sprintf("L%d", line), v["qualification_number"])
+		f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), v["batch_number"])
+		f.SetCellValue("Sheet1", fmt.Sprintf("I%d", line), v[models.FieldExpiryDate])
+		f.SetCellValue("Sheet1", fmt.Sprintf("J%d", line), v["approval_number"])
+		f.SetCellValue("Sheet1", fmt.Sprintf("K%d", line), v["qualification_number"])
 
 	}
 	Style1, _ := f.NewStyle(
@@ -2201,7 +2278,7 @@ func (c StockTemplateController) StockInquiryExcel() {
 				{Type: "right", Color: "000000", Style: 1},
 			},
 		})
-	f.SetCellStyle("Sheet1", "A2", "L2", Style1)
+	f.SetCellStyle("Sheet1", "A2", "K2", Style1)
 	Style2, _ := f.NewStyle(
 		&excelize.Style{
 			Font:      &excelize.Font{Size: 12, Family: "宋体"},
@@ -2213,7 +2290,7 @@ func (c StockTemplateController) StockInquiryExcel() {
 				{Type: "right", Color: "000000", Style: 1},
 			},
 		})
-	f.SetCellStyle("Sheet1", "A3", fmt.Sprintf("L%d", line), Style2)
+	f.SetCellStyle("Sheet1", "A3", fmt.Sprintf("K%d", line), Style2)
 
 	filename := "库存信息表" + time.Now().Format("20060102150405") + ".xlsx"
 	// 保存文件
@@ -2272,206 +2349,6 @@ func (c StockTemplateController) StockHomeStat() {
 	c.PageOK(list, int(cnt), 0, 0, "查询成功")
 }
 
-// 列表 - 接口
-func (c *StockTemplateController) InventoryPdf() {
-	//s := services.StockTemplate{}
-	//reqData := dto.StockTemplateInventoryPageReq{}
-	//if err := c.ParseAndValidate(&c.Ctx.Input.RequestBody, &reqData); err != nil {
-	//	c.Error(global.ParseFormErr, err, err.Error())
-	//	return
-	//}
-	//
-	//deptId := beegouser.GetDeptId(c.Ctx)
-	//list, _, err := s.StockTemplateInventoryList(&reqData, deptId)
-	//if err != nil {
-	//	c.Error(500, err, err.Error())
-	//	return
-	//}
-	pdf := gopdf.GoPdf{}
-	pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 841.89, H: 595.28}})
-
-	// 添加页面
-	pdf.AddPage()
-
-	// 设置字体
-	pdf.AddTTFFont("simsun", "static/fonts/MiSans-Medium.ttf")
-	pdf.SetFont("simsun", "", 20)
-	textw, _ := pdf.MeasureTextWidth("生物制品收发登记")
-	pdf.SetX((841 / 2) - (textw / 2))
-	pdf.SetY(40)
-	pdf.Text("生物制品收发登记")
-	// 添加文本内容
-	pdf.SetFont("simsun", "", 12)
-	pdf.SetX(500)
-	pdf.SetY(70)
-	pdf.Text("制品名称:脊灰疫苗")
-	pdf.SetX(500)
-	pdf.SetY(90)
-	pdf.Text("剂型: 规格:1g/粒/剂 单位:")
-
-	pdf.AddPage()
-	textw, _ = pdf.MeasureTextWidth("生物制品收发登记2")
-	pdf.SetFont("simsun", "", 20)
-
-	pdf.SetX((841 / 2) - (textw / 2))
-	pdf.SetY(40)
-	pdf.Text("生物制品收发登记2")
-	// 添加文本内容
-	pdf.SetFont("simsun", "", 12)
-	pdf.SetX(500)
-	pdf.SetY(70)
-	pdf.Text("制品名称:脊灰疫苗")
-	pdf.SetX(500)
-	pdf.SetY(90)
-	pdf.Text("剂型: 规格:1g/粒/剂 单位:")
-	// 保存 PDF 文件
-	pdf.WritePdf("生物制品收发登记.pdf")
-
-	// 返回生成的 PDF 文件
-	c.Ctx.Output.Download("生物制品收发登记.pdf")
-
-	//var err error
-	//pdf := &gopdf.GoPdf{}
-	//
-	//pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 841.89, H: 595.28}}) //595.28, 841.89 = A4
-	//
-	//err = pdf.AddTTFFont("simsun", "static/fonts/三极行楷简体-粗.ttf")
-	//if err != nil {
-	//	c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
-	//	c.ServeJSON()
-	//	return
-	//}
-	//err = pdf.SetFont("simsun", "", 24)
-	//if err != nil {
-	//	c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
-	//	c.ServeJSON()
-	//	return
-	//}
-	//
-	//pdf.SetGrayFill(0.5)
-	//
-	//pdf.SetMargins(0, 20, 0, 20)
-	//pdf.AddPage()
-	//
-	//company, _ := Account.Read_Company_ById(c.T_pid)
-	//
-	//textw, _ := pdf.MeasureTextWidth(company.T_name)
-	//pdf.SetX((595 / 2) - (textw / 2))
-	//pdf.SetY(40)
-	//pdf.Text(company.T_name)
-	//
-	//// 线
-	//pdf.SetLineWidth(2)
-	//pdf.SetLineType("dashed")
-	//pdf.Line(10, 60, 585, 60)
-	//
-	//err = pdf.AddTTFFont("wts", "static/fonts/MiSans-Medium.ttf")
-	//if err != nil {
-	//	c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
-	//	c.ServeJSON()
-	//	return
-	//}
-	//err = pdf.SetFont("wts", "", 12)
-	//if err != nil {
-	//	c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
-	//	c.ServeJSON()
-	//	return
-	//}
-	//
-	//var s_time, e_time string
-	//if len(DeviceSensor_data) > 0 {
-	//	s_time = fmt.Sprintf("%s", DeviceSensor_data[0].T_time)
-	//	e_time = fmt.Sprintf("%s", DeviceSensor_data[len(DeviceSensor_data)-1].T_time)
-	//}
-	////fmt.Sprintf(" %.1f ", v.T_t)
-	//lib.RectFillColor(pdf, "历史数据["+e_time+" / "+s_time+"]", 14, 22, 80, 550, 40, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//
-	//lib.RectFillColor(pdf, "序号", 12, 22, 120, 30, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//lib.RectFillColor(pdf, "传感器名称", 12, 52, 120, 100, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//lib.RectFillColor(pdf, "温度℃", 12, 152, 120, 50, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//
-	//lib.RectFillColor(pdf, "湿度%", 12, 202, 120, 50, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//
-	//lib.RectFillColor(pdf, "温度范围", 12, 252, 120, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//lib.RectFillColor(pdf, "湿度范围", 12, 332, 120, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//lib.RectFillColor(pdf, "记录时间", 12, 412, 120, 120, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//lib.RectFillColor(pdf, "备注", 12, 532, 120, 40, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//
-	//var y float64 = 140
-	//
-	//err = pdf.SetFont("wts", "", 10)
-	//if err != nil {
-	//	c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
-	//	c.ServeJSON()
-	//	return
-	//}
-	//for i, v := range DeviceSensor_data {
-	//	text := fmt.Sprintf(" %d ", i+1)
-	//	var textH float64 = 25 // if text height is 25px.
-	//	pdf.SetNewY(y, textH)
-	//	y = pdf.GetY()
-	//	//pdf.SetX(x) // must after pdf.SetNewY() called.
-	//	//err = pdf.Text(text)
-	//	//if err != nil {
-	//	//	log.Fatalln(err)
-	//	//}
-	//
-	//	T_t := fmt.Sprintf(" %.1f ", v.T_t)
-	//	T_rh := fmt.Sprintf(" %.1f ", v.T_rh)
-	//	T_Tlu := fmt.Sprintf(" %.1f ~ %.1f ", v.T_tl, v.T_tu)
-	//	T_Rlu := fmt.Sprintf(" %.1f ~ %.1f ", v.T_rhl, v.T_rhu)
-	//	T_time := fmt.Sprintf("%s", v.T_time)
-	//
-	//	if v.T_ist == 1 {
-	//		lib.RectFillColor(pdf, T_t, 10, 152, y, 50, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//		lib.RectFillColor(pdf, T_Tlu, 10, 252, y, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//	} else {
-	//		lib.RectFillColor(pdf, "", 10, 152, y, 50, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//		lib.RectFillColor(pdf, "", 10, 252, y, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//	}
-	//	if v.T_ish == 1 {
-	//		lib.RectFillColor(pdf, T_rh, 10, 202, y, 50, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//		lib.RectFillColor(pdf, T_Rlu, 10, 332, y, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//	} else {
-	//		lib.RectFillColor(pdf, "", 10, 202, y, 50, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//		lib.RectFillColor(pdf, "", 10, 332, y, 80, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//	}
-	//
-	//	lib.RectFillColor(pdf, text, 10, 22, y, 30, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//	lib.RectFillColor(pdf, v.T_name, 10, 52, y, 100, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//
-	//	lib.RectFillColor(pdf, T_time, 10, 412, y, 120, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//	lib.RectFillColor(pdf, v.T_remark, 10, 532, y, 40, 20, 255, 255, 255, lib.AlignCenter, lib.ValignMiddle)
-	//	y += 20
-	//}
-	//timeStr := "ofile/" + time.Now().Format("20060102150405") + ".pdf"
-	//
-	//err = pdf.WritePdf(timeStr)
-	//if err != nil {
-	//	c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
-	//	c.ServeJSON()
-	//	return
-	//}
-	//
-	//// 上传 OSS
-	//url, is := NatsServer.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/"+timeStr, timeStr)
-	//if !is {
-	//	c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"}
-	//	c.ServeJSON()
-	//	return
-	//}
-	////删除目录
-	//err = os.Remove(timeStr)
-	//if err != nil {
-	//	fmt.Println(err)
-	//}
-	//
-	//c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url}
-	//c.ServeJSON()
-	//return
-
-}
-
 // StockTemplateInScanBarCode 扫条码入库
 // @Summary 扫条码入库
 // @Description 扫条码入库

+ 41 - 0
controllers/upload.go

@@ -0,0 +1,41 @@
+package controllers
+
+import (
+	"Medical_ERP/conf"
+	"github.com/qiniu/go-sdk/v7/auth/qbox"
+	"github.com/qiniu/go-sdk/v7/storage"
+	uuid "github.com/satori/go.uuid"
+	"strconv"
+	"time"
+)
+
+type UpFileController struct {
+	BaseController
+}
+
+// 列表 -
+func (c *UpFileController) ConfigUpFileToken() {
+	var Qiniu *qbox.Mac
+	Qiniu = qbox.NewMac(conf.Qiniu_AccessKey, conf.Qiniu_SecretKey)
+
+	T_suffix := c.GetString("T_suffix")
+
+	Tokey := strconv.FormatInt(time.Now().Unix(), 10) + uuid.NewV4().String()
+	if len(T_suffix) == 0 {
+		T_suffix = "png"
+	}
+	putPolicy := storage.PutPolicy{
+		Scope:        conf.Qiniu_BUCKET,
+		InsertOnly:   1,    // 仅能以新增模式上传文件。
+		Expires:      7200, //示例2小时有效期
+		ReturnBody:   `{"key":"` + conf.OssQiniu + `/$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)"}`,
+		ForceSaveKey: true,
+		SaveKey:      "UpImage/" + Tokey + "." + T_suffix,
+		FsizeLimit:   1024 * 1024 * 100,
+		MimeLimit:    "image/*;application/pdf;application/octet-stream;application/zip;application/x-tar",
+	}
+
+	upToken := putPolicy.UploadToken(Qiniu)
+	c.OK(upToken, "")
+	return
+}

+ 41 - 0
dto/medicine_img.go

@@ -0,0 +1,41 @@
+package dto
+
+import (
+	"Medical_ERP/common/dto"
+	common "Medical_ERP/common/model"
+	"Medical_ERP/models"
+)
+
+// MedicineImgPageReq 列表或者搜索使用结构体
+type MedicineImgPageReq struct {
+	dto.Pagination `search:"-"`
+	Product        string `json:"product" search:"type:contains;column:product;table:medicine_img" example:""`          // 产品
+	Enterprise     string `json:"enterprise" search:"type:contains;column:enterprise;table:medicine_img" example:""`    // 生产企业
+	Spec           string `json:"spec" search:"type:contains;column:spec;table:medicine_img" example:""`                // 规格
+	BatchNumber    string `json:"batchNumber" search:"type:contains;column:batch_number;table:medicine_img" example:""` // 批号
+}
+
+func (m *MedicineImgPageReq) GetNeedSearch() interface{} {
+	return *m
+}
+
+// MedicineImgUpdateReq 改使用的结构体
+type MedicineImgUpdateReq struct {
+	Id               int    `json:"id"  example:"1"`
+	Img              string `json:"img"  example:"图片"` // 图片
+	common.ControlBy `swaggerignore:"true"`
+}
+
+func (s *MedicineImgUpdateReq) Generate(model *models.MedicineImg) {
+	model.Id = s.Id
+	model.Img = s.Img
+	if s.ControlBy.UpdateBy != 0 {
+		model.UpdateBy = s.UpdateBy
+	}
+	if s.ControlBy.CreateBy != 0 {
+		model.CreateBy = s.CreateBy
+	}
+}
+func (s *MedicineImgUpdateReq) GetId() interface{} {
+	return s.Id
+}

+ 18 - 0
dto/product_code.go

@@ -0,0 +1,18 @@
+package dto
+
+import "Medical_ERP/common/dto"
+
+// ProductCodePageReq 列表或者搜索使用结构体
+type ProductCodePageReq struct {
+	dto.Pagination `search:"-"`
+	Name           string `json:"name" search:"-"` // 收货单位
+}
+
+// GenProductCodePageReq 列表或者搜索使用结构体
+type GenProductCodePageReq struct {
+	Product     string `json:"product" valid:"MinSize(1)"`     // 产品
+	Enterprise  string `json:"enterprise" valid:"MinSize(1)"`  // 生产企业
+	Spec        string `json:"spec" valid:"MinSize(1)"`        // 规格
+	BatchNumber string `json:"batchNumber" valid:"MinSize(1)"` // 批号
+	Quantity    int    `json:"quantity"`                       // 数量
+}

+ 5 - 0
dto/stock_template.go

@@ -17,6 +17,8 @@ type StockTemplateInInsertReq struct {
 	ForwardingUnit string  `json:"forwardingUnit"` // 发货单位
 	Date           string  `json:"date"`           // 入库日期
 
+	Img string `json:"img"` // 药品图片
+
 	common.ControlBy `swaggerignore:"true"`
 }
 
@@ -64,6 +66,7 @@ type BatchStockTemplateInInsertReq struct {
 		Operator       string                 `json:"operator"`                // 经办人
 		ForwardingUnit string                 `json:"forwardingUnit"`          // 发货单位
 		Date           string                 `json:"date" valid:"MinSize(1)"` // 入库日期
+		Qrcode         string                 `json:"Qrcode"`                  // 追溯码
 	} `json:"stockInList"`
 
 	common.ControlBy `swaggerignore:"true"`
@@ -79,6 +82,8 @@ type BatchStockTemplateOutInsertReq struct {
 		Operator      string `json:"operator"`                // 经办人
 		ReceivingUnit string `json:"receivingUnit"`           // 收货单位
 		Date          string `json:"date" valid:"MinSize(1)"` // 出库日期
+		Qrcode        string `json:"Qrcode"`                  // 追溯码
+
 	} `json:"stockOutList"`
 	common.ControlBy `swaggerignore:"true"`
 }

+ 3 - 0
go.mod

@@ -14,6 +14,8 @@ require (
 	github.com/go-sql-driver/mysql v1.7.0
 	github.com/gobwas/glob v0.2.3
 	github.com/google/uuid v1.3.0
+	github.com/qiniu/go-sdk/v7 v7.19.0
+	github.com/satori/go.uuid v1.2.0
 	github.com/ser163/png2j v0.1.2-beta
 	github.com/signintech/gopdf v0.20.0
 	github.com/smartystreets/goconvey v1.8.1
@@ -101,6 +103,7 @@ require (
 	github.com/xuri/nfp v0.0.0-20230819163627-dc951e3ffe1a // indirect
 	golang.org/x/crypto v0.16.0 // indirect
 	golang.org/x/net v0.19.0 // indirect
+	golang.org/x/sync v0.1.0 // indirect
 	golang.org/x/sys v0.15.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	golang.org/x/tools v0.7.0 // indirect

+ 15 - 0
go.sum

@@ -191,10 +191,13 @@ github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyr
 github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
 github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
 github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
 github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
 github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
 github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
 github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
+github.com/go-playground/validator/v10 v10.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk=
 github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw=
 github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
 github.com/go-redis/redis/v7 v7.2.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
@@ -531,6 +534,10 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
 github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
 github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
+github.com/qiniu/dyn v1.3.0/go.mod h1:E8oERcm8TtwJiZvkQPbcAh0RL8jO1G0VXJMW3FAWdkk=
+github.com/qiniu/go-sdk/v7 v7.19.0 h1:k3AzDPil8QHIQnki6xXt4YRAjE52oRoBUXQ4bV+Wc5U=
+github.com/qiniu/go-sdk/v7 v7.19.0/go.mod h1:nqoYCNo53ZlGA521RvRethvxUDvXKt4gtYXOwye868w=
+github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
@@ -551,6 +558,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
+github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/ser163/png2j v0.1.2-beta h1:ri7e+tGw/Y1TV18x8O4uONqaHjyTv/L2rnI3Ft5bMeA=
 github.com/ser163/png2j v0.1.2-beta/go.mod h1:QusatApB4GgVnjdAL45Erna5GxAaAd7KsPv3mrswtp8=
@@ -662,10 +671,12 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
 golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
 golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
 golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
@@ -757,6 +768,7 @@ golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qx
 golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
 golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
 golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
@@ -784,6 +796,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -849,6 +862,7 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -860,6 +874,7 @@ golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
 golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=

+ 4 - 0
main.go

@@ -12,6 +12,8 @@ import (
 	"github.com/go-resty/resty/v2"
 	"github.com/tidwall/gjson"
 	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
+	_ "image/jpeg"
+	_ "image/png"
 	"log"
 	"net/http"
 	"os"
@@ -47,6 +49,8 @@ func main() {
 
 	go InitServiceDiscovery()
 
+	//models.BatchAlterMedicineTemplateTable()
+
 	fmt.Println(pkg.Green("Server run at:"))
 	fmt.Printf("-  Local:   http://127.0.0.1:%d/ \r\n", conf.Httpport)
 	fmt.Printf("-  Network: http://%s:%d/ \r\n", pkg.GetLocalHost(), conf.Httpport)

+ 3 - 0
models/init.go

@@ -10,6 +10,7 @@ import (
 
 func init() {
 	AutoMigrateDB()
+
 }
 
 func AutoMigrateDB() {
@@ -28,6 +29,8 @@ func AutoMigrateDB() {
 			&StockOut{},
 			&MedicineInventory{},
 			&Barcode{},
+			&MedicineImg{},
+			&ProductCode{},
 		)
 	if err != nil {
 		log.Fatalf("migrate db fail: %v", err)

+ 29 - 0
models/medicine_img.go

@@ -0,0 +1,29 @@
+package models
+
+import model2 "Medical_ERP/common/model"
+
+type MedicineImg struct {
+	model2.Model
+	Product             string `json:"product" gorm:"size:512;"`             // 药品名称
+	Enterprise          string `json:"enterprise" gorm:"size:512;"`          // 生产企业
+	Spec                string `json:"spec" gorm:"size:512;"`                // 规格
+	Unit                string `json:"unit" gorm:"size:512;"`                // 单位 非必填
+	DosageForm          string `json:"dosageForm" gorm:"size:512;"`          // 剂型 非必填
+	ApprovalNumber      string `json:"approvalNumber" gorm:"size:128;"`      // 批准文号
+	QualificationNumber string `json:"qualificationNumber" gorm:"size:128;"` // 批签发合格编号
+	ProductionDate      string `json:"productionDate" gorm:"size:128;"`      // 生产日期
+	ExpiryDate          string `json:"expiryDate" gorm:"size:128;"`          // 失效日期
+	BatchNumber         string `json:"batchNumber" gorm:"size:128;"`         // 批号
+	Qrcode              string `json:"qrcode" gorm:"size:256;"`              // 追溯码
+	Img                 string `json:"img" gorm:"type:longtext"`             // 图片 001.jpg,002.jpg,003.jpg
+	model2.ControlBy
+	model2.ModelTime
+}
+
+func (e *MedicineImg) TableName() string {
+	return "medicine_img"
+}
+
+func (e *MedicineImg) GetId() interface{} {
+	return e.Id
+}

+ 34 - 3
models/medicine_template.go

@@ -1,8 +1,10 @@
 package models
 
 import (
+	db "Medical_ERP/common/initialize"
 	model2 "Medical_ERP/common/model"
 	"github.com/beego/beego/v2/core/logs"
+	"github.com/go-sql-driver/mysql"
 	"strconv"
 )
 
@@ -11,7 +13,7 @@ const (
 	FieldEnterpriseID        = "enterprise_id"        // 生产企业ID
 	FieldSpecID              = "spec_id"              // 规格ID
 	FieldUnitID              = "unit_id"              // 单位id
-	FieldDosageFormID        = "dosage_form_id"       //  剂型id
+	FieldDosageFormID        = "dosage_form_id"       // 剂型id
 	FieldBatchNumber         = "batch_number"         // 批号
 	FieldExpiryDate          = "expiry_date"          // 失效日期
 	FieldProducedDate        = "produced_date"        // 生产日期
@@ -76,7 +78,8 @@ func GetInitMedicineTemplateSql(deptId int) string {
         produced_date DATE comment '生产日期',
         approval_number VARCHAR(256) comment '批准文号',
         qualification_number VARCHAR(256) comment '批签发编号',
-        unit_price DECIMAL(10,2) comment '单价'
+        unit_price DECIMAL(10,2) comment '单价',
+        qrcode VARCHAR(256) comment '追溯码'
     );`
 	return sqlStmt
 }
@@ -138,5 +141,33 @@ func GetDeleteMedicineTemplateSql(deptId int, columnName string) string {
 //	5		单位			UnitID
 //	6		文本
 //	7		数值(整数)
-//	7		数值(小数)
+//	8		数值(小数)
 //	9		日期
+
+// 批量修改药品信息表结构
+func BatchAlterMedicineTemplateTable() {
+	// 删除表内字段
+	var tableName []string
+	err := db.DB.Raw("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME LIKE 'medicine_info_%';\n").
+		Scan(&tableName).Error
+	if err != nil {
+		logs.Error("db error: %s", err)
+	}
+	tx := db.DB.Begin()
+
+	for _, v := range tableName {
+		sql := "ALTER TABLE " + v + " ADD COLUMN qrcode VARCHAR(256)"
+		err = tx.Exec(sql).Error
+		if err != nil {
+			if err.(*mysql.MySQLError).Message == "Duplicate column name 'qrcode'" {
+				continue
+			}
+			tx.Rollback()
+			logs.Error("修改表结构失败: %s", err.Error())
+			break
+		}
+	}
+
+	tx.Commit()
+
+}

+ 21 - 0
models/product_code.go

@@ -0,0 +1,21 @@
+package models
+
+import model2 "Medical_ERP/common/model"
+
+type ProductCode struct {
+	model2.Model
+	Product     string `json:"product" gorm:"size:512;"`     // 药品名称
+	Enterprise  string `json:"enterprise" gorm:"size:512;"`  // 生产企业
+	Spec        string `json:"spec" gorm:"size:512;"`        // 规格
+	BatchNumber string `json:"batchNumber" gorm:"size:128;"` // 批号
+	model2.ControlBy
+	model2.ModelTime
+}
+
+func (e *ProductCode) TableName() string {
+	return "product_code"
+}
+
+func (e *ProductCode) GetId() interface{} {
+	return e.Id
+}

+ 4 - 0
models/stock_in.go

@@ -4,6 +4,8 @@ import model2 "Medical_ERP/common/model"
 
 // 入库
 
+const TypeStockIn = "stock_in"
+
 type StockIn struct {
 	model2.Model
 	MedicineID     int     `json:"medicineId" gorm:"size:4;not null;comment:药品信息ID"` // 药品信息ID
@@ -12,6 +14,8 @@ type StockIn struct {
 	Operator       string  `json:"operator" gorm:"size:128;"`                        // 经办人
 	ForwardingUnit string  `json:"forwardingUnit" gorm:"size:128;"`                  // 发货单位
 	Date           string  `json:"date" gorm:"size:128;"`                            // 入库日期
+	Qrcode         string  `json:"qrcode" gorm:"size:128;"`                          // 条码
+	Number         string  `json:"number" gorm:"size:128;"`                          // 入库单号
 	model2.ControlBy
 	model2.ModelTime
 }

+ 5 - 0
models/stock_out.go

@@ -2,6 +2,8 @@ package models
 
 import model2 "Medical_ERP/common/model"
 
+const TypeStockOut = "stock_out"
+
 type StockOut struct {
 	model2.Model
 	MedicineID int `json:"medicineId" gorm:"size:4;not null;comment:药品信息ID"` // 药品信息ID
@@ -10,6 +12,9 @@ type StockOut struct {
 	Operator      string `json:"operator" gorm:"size:128;"`      // 经办人
 	ReceivingUnit string `json:"receivingUnit" gorm:"size:128;"` // 收货单位
 	Date          string `json:"date" gorm:"size:128;"`          // 入库日期
+	Qrcode        string `json:"qrcode" gorm:"size:128;"`        // 条码
+	Number        string `json:"number" gorm:"size:128;"`        // 出库入库单号
+
 	model2.ControlBy
 	model2.ModelTime
 }

+ 16 - 0
routers/medicine_img.go

@@ -0,0 +1,16 @@
+package routers
+
+import (
+	"Medical_ERP/controllers"
+	beego "github.com/beego/beego/v2/server/web"
+)
+
+func init() {
+
+	medicine := beego.NewNamespace("/api/medicine-img",
+		beego.NSRouter("/list", &controllers.MedicineImgController{}, "*:List"),
+		beego.NSRouter("/edit", &controllers.MedicineImgController{}, "*:Edit"),
+	)
+	//注册 namespace
+	beego.AddNamespace(medicine)
+}

+ 16 - 0
routers/product_code.go

@@ -0,0 +1,16 @@
+package routers
+
+import (
+	"Medical_ERP/controllers"
+	beego "github.com/beego/beego/v2/server/web"
+)
+
+func init() {
+	// 分组
+	productCode := beego.NewNamespace("/api/product-code",
+		beego.NSRouter("/list", &controllers.ProductCodeController{}, "*:List"),
+		beego.NSRouter("/gen", &controllers.ProductCodeController{}, "*:Gen"),
+	)
+	//注册 namespace
+	beego.AddNamespace(productCode)
+}

+ 3 - 0
routers/router.go

@@ -24,4 +24,7 @@ func init() {
 	// 更新权限
 	beego.Router("/api/role-api", &controllers.RoleApi{}, "*:UpdateRoleApi")
 
+	// 文件上传
+	beego.Router("/UpFileToken", &controllers.UpFileController{}, "*:ConfigUpFileToken")
+
 }

+ 0 - 1
routers/stock.go

@@ -20,7 +20,6 @@ func init() {
 		beego.NSRouter("/out/list", &controllers.StockTemplateController{}, "*:StockTemplateOutList"),                 // 出库列表
 		beego.NSRouter("/inventory/list", &controllers.StockTemplateController{}, "*:StockTemplateInventoryList"),     // 收发记录
 		beego.NSRouter("/inventory/export", &controllers.StockTemplateController{}, "*:StockTemplateInventoryExport"), // 库存 - excel
-		beego.NSRouter("/inventory/pdf", &controllers.StockTemplateController{}, "*:InventoryPdf"),
 		beego.NSRouter("/transport-record/export", &controllers.StockTemplateController{}, "*:TransportRecordExport"),
 		beego.NSRouter("/transport-record/barcode-info", &controllers.StockTemplateController{}, "*:GetBarCodeInfo"), // 获取条码信息
 		beego.NSRouter("/scan-code-in", &controllers.StockTemplateController{}, "*:StockTemplateInScanCode"),         // 扫码入库

+ 132 - 0
services/medicine_img.go

@@ -0,0 +1,132 @@
+package services
+
+import (
+	"Medical_ERP/common/actions"
+	cDto "Medical_ERP/common/dto"
+	"Medical_ERP/common/global"
+	db "Medical_ERP/common/initialize"
+	"Medical_ERP/conf"
+	"Medical_ERP/dto"
+	"Medical_ERP/models"
+	"Medical_ERP/utils"
+	"errors"
+	"fmt"
+	"github.com/beego/beego/v2/adapter/context"
+	"github.com/beego/beego/v2/core/logs"
+	"github.com/go-resty/resty/v2"
+	"github.com/tidwall/gjson"
+	"gorm.io/gorm"
+	"net/http"
+	"strings"
+)
+
+type MedicineImg struct {
+}
+
+// MedicineImg 通过名称、生产企业、规格、批号查询药品图片,
+// 如果未查询到,则查询根公司图片信息
+func (e *MedicineImg) Get(deptId, rootId int, product, enterprise, spec, batchNumber string) (medicineImg models.MedicineImg, err error) {
+	medicineImgList := make([]models.MedicineImg, 0)
+	err = db.DB.Where("product = ? AND enterprise = ? AND spec = ? AND batch_number = ? AND dept_id in ? AND img != ''",
+		product, enterprise, spec, batchNumber, []int{deptId, rootId}).Find(&medicineImgList).Error
+
+	if err != nil {
+		logs.Error("db error: %s ", err)
+		return medicineImg, global.GetFailedErr
+	}
+
+	if len(medicineImgList) == 0 {
+		return medicineImg, global.GetNotFoundErr
+	}
+
+	if len(medicineImgList) == 1 {
+		return medicineImgList[0], nil
+	}
+
+	if len(medicineImgList) == 2 {
+		for _, img := range medicineImgList {
+			if img.DeptId == deptId {
+				return img, nil
+			}
+		}
+	}
+
+	return medicineImg, nil
+
+}
+
+// GetPage 获取Spec列表
+func (e *MedicineImg) GetPage(c *dto.MedicineImgPageReq, list *[]models.MedicineImg, count *int64, rootId int, p *actions.DataPermission) error {
+	var err error
+	var data models.MedicineImg
+
+	err = db.DB.Model(&data).
+		Scopes(
+			cDto.MakeCondition(c.GetNeedSearch()),
+			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+			actions.Permission(data.TableName(), p),
+		).
+		Find(list).Limit(-1).Offset(-1).
+		Count(count).Error
+	if err != nil {
+		logs.Error("db error: %s ", err)
+		return global.GetFailedErr
+	}
+	for i := 0; i < len(*list); i++ {
+		if len((*list)[i].Img) == 0 {
+			img, _ := e.Get((*list)[i].DeptId, rootId, (*list)[i].Product, (*list)[i].Enterprise, (*list)[i].Spec, (*list)[i].BatchNumber)
+			(*list)[i].Img = img.Img
+		}
+	}
+	return nil
+}
+
+// Update 修改Spec对象
+func (e *MedicineImg) Update(c *dto.MedicineImgUpdateReq) error {
+	var medicineImg = models.MedicineImg{}
+	err := db.DB.First(&medicineImg, c.GetId()).Error
+	if err != nil {
+		logs.Error("db error: %s", err)
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return global.GetNotFoundErr
+		}
+		return global.GetFailedErr
+	}
+
+	c.Generate(&medicineImg)
+
+	err = db.DB.Save(&medicineImg).Error
+	if err != nil {
+		logs.Error("db error: %s", err)
+		return global.UpdateFailedErr
+	}
+	return nil
+}
+
+func (e *MedicineImg) GetRootID(c *context.Context, rootId int) (id int, err error) {
+
+	reqPath := fmt.Sprintf("/api/dept/%d", rootId)
+	url := conf.OAuthBaseUrl + reqPath
+
+	r, reqError := resty.New().R().SetHeaders(map[string]string{
+		"Authorization": c.Request.Header.Get("Authorization"),
+	}).Get(url)
+	if reqError != nil {
+		err = errors.New("获取根公司失败")
+		logs.Error(err.Error(), reqError)
+		return
+	}
+
+	code := gjson.GetBytes(r.Body(), "code").Int()
+	deptPath := gjson.GetBytes(r.Body(), "data.deptPath").String()
+	if code != http.StatusOK {
+		err = errors.New("获取根公司失败")
+		logs.Error(err.Error(), string(r.Body()))
+		return
+	}
+	list := strings.Split(strings.Trim(deptPath, "/"), "/")
+	if len(list) > 1 {
+		id = utils.ToInt(list[1])
+	}
+	return
+}

+ 75 - 0
services/product_code.go

@@ -0,0 +1,75 @@
+package services
+
+import (
+	"Medical_ERP/common/actions"
+	"Medical_ERP/common/global"
+	db "Medical_ERP/common/initialize"
+	model2 "Medical_ERP/common/model"
+	"Medical_ERP/dto"
+	"Medical_ERP/models"
+	"errors"
+	"github.com/beego/beego/v2/core/logs"
+	"gorm.io/gorm"
+)
+
+type ProductCode struct {
+}
+
+func ProductCodeNameScopes(name string) func(db *gorm.DB) *gorm.DB {
+
+	return func(db *gorm.DB) *gorm.DB {
+		if len(name) == 0 {
+			return db
+		}
+		return db.Where("product like ? OR enterprise like ?  OR batch_number like ?", "%"+name+"%", "%"+name+"%", "%"+name+"%")
+	}
+}
+
+// Insert 创建Enterprise对象
+func (e *ProductCode) CreateProductCode(c *dto.GenProductCodePageReq, deptId int) error {
+	var err error
+	var data models.ProductCode
+	err = db.DB.Where("product = ? AND enterprise = ? AND spec = ? AND batch_number = ? AND dept_id = ?",
+		c.Product, c.Enterprise, c.Spec, c.BatchNumber, deptId).First(&data).Error
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			err = db.DB.Create(&models.ProductCode{
+				Product:     c.Product,
+				Enterprise:  c.Enterprise,
+				Spec:        c.Spec,
+				BatchNumber: c.BatchNumber,
+				ControlBy: model2.ControlBy{
+					DeptId: deptId,
+				},
+			}).Error
+			if err != nil {
+				logs.Error("db error: %s", err)
+				return errors.New("创建产品条码信息失败")
+			}
+		} else {
+			logs.Error("db error: %s", err)
+			return errors.New("查询产品条码信息失败")
+		}
+	}
+
+	return nil
+}
+
+func (e *ProductCode) GetPage(c *dto.ProductCodePageReq, list *[]models.ProductCode, count *int64, p *actions.DataPermission) error {
+	var err error
+	var data models.ProductCode
+
+	err = db.DB.Model(&data).
+		Scopes(
+			ProductCodeNameScopes(c.Name),
+			//cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
+			actions.Permission(data.TableName(), p),
+		).
+		Find(list).
+		Count(count).Error
+	if err != nil {
+		logs.Error("db error: %s ", err)
+		return global.GetFailedErr
+	}
+	return nil
+}

+ 11 - 3
services/stock.go

@@ -58,6 +58,8 @@ func (e *Stock) StockIn(c *dto.StockInInsertReq) error {
 		ForwardingUnit: c.ForwardingUnit,
 		Date:           c.Date,
 	}
+	stockInRecord.SetDeptId(c.DeptId)
+	stockInRecord.SetCreateBy(c.CreateBy)
 	err = tx.Create(&stockInRecord).Error
 	if err != nil {
 		tx.Rollback()
@@ -67,7 +69,7 @@ func (e *Stock) StockIn(c *dto.StockInInsertReq) error {
 	c.Id = stockInRecord.Id
 
 	var inventory models.MedicineInventory
-	err = tx.First(&inventory, "medicine_id = ?", medicineInfo.Id).Error
+	err = tx.First(&inventory, "medicine_id = ? AND dept_id = ?", medicineInfo.Id, c.DeptId).Error
 	if err != nil {
 		tx.Rollback()
 		logs.Error("db error: %s", err)
@@ -84,6 +86,8 @@ func (e *Stock) StockIn(c *dto.StockInInsertReq) error {
 		Balance:        c.Quantity,
 		ForwardingUnit: c.ForwardingUnit,
 	}
+	inventory.SetDeptId(c.DeptId)
+	inventory.SetCreateBy(c.CreateBy)
 	inventory.Balance += c.Quantity
 	err = tx.Create(&inventory).Error
 	if err != nil {
@@ -138,6 +142,8 @@ func (e *Stock) StockInStockInList(c *dto.StockInInsertReq) error {
 		ForwardingUnit: c.ForwardingUnit,
 		Date:           c.Date,
 	}
+	stockInRecord.SetDeptId(c.DeptId)
+	stockInRecord.SetCreateBy(c.CreateBy)
 	err = tx.Create(&stockInRecord).Error
 	if err != nil {
 		tx.Rollback()
@@ -147,7 +153,7 @@ func (e *Stock) StockInStockInList(c *dto.StockInInsertReq) error {
 	c.Id = stockInRecord.Id
 
 	var inventory models.MedicineInventory
-	err = tx.First(&inventory, "medicine_id = ?", medicineInfo.Id).Error
+	err = tx.First(&inventory, "medicine_id = ? AND dept_id = ?", medicineInfo.Id, c.DeptId).Error
 	if err != nil {
 		tx.Rollback()
 		logs.Error("db error: %s", err)
@@ -164,6 +170,8 @@ func (e *Stock) StockInStockInList(c *dto.StockInInsertReq) error {
 		Balance:    c.Quantity,
 	}
 	inventory.Balance += c.Quantity
+	inventory.SetDeptId(c.DeptId)
+	inventory.SetCreateBy(c.CreateBy)
 	err = tx.Create(&inventory).Error
 	if err != nil {
 		tx.Rollback()
@@ -207,7 +215,7 @@ func (e *Stock) StockOut(c *dto.StockOutInsertReq) error {
 	c.Id = stockOutRecord.Id
 
 	var inventory models.MedicineInventory
-	err = tx.First(&inventory, "medicine_id = ?", medicineInfo.Id).Error
+	err = tx.First(&inventory, "medicine_id = ? AND dept_id = ?", medicineInfo.Id, c.DeptId).Error
 	if err != nil {
 		tx.Rollback()
 		logs.Error("db error: %s", err)

+ 321 - 41
services/stock_template.go

@@ -12,14 +12,72 @@ import (
 	"fmt"
 	"github.com/beego/beego/v2/core/logs"
 	"gorm.io/gorm"
+	"math/rand"
 	"sort"
 	"strconv"
 	"strings"
+	"time"
 )
 
 type StockTemplate struct {
 }
 
+func (e *StockTemplate) GetStockNumber(stock string) (number string, err error) {
+
+	switch stock {
+	case models.TypeStockIn:
+		var stockIn models.StockIn
+
+		for {
+			rand.New(rand.NewSource(time.Now().UnixNano()))
+			// 生成随机数后八位
+			randomSuffix := rand.Intn(99999999)
+
+			// 格式化年月日
+			date := time.Now().Format("20060102")
+
+			// 组合成16位随机数
+			randomNumber := fmt.Sprintf("%s%08d", date, randomSuffix)
+
+			// 查询数据库,检查随机数是否存在
+			if err = db.DB.Where("number = ?", randomNumber).First(&stockIn).Error; err != nil {
+				if err == gorm.ErrRecordNotFound {
+					return "RK" + randomNumber, nil
+				} else {
+					logs.Error("db error: %s", err)
+					return number, err
+				}
+			}
+		}
+
+	case models.TypeStockOut:
+		var stockOut models.StockOut
+		for {
+			rand.New(rand.NewSource(time.Now().UnixNano()))
+			// 生成随机数后八位
+			randomSuffix := rand.Intn(99999999)
+
+			// 格式化年月日
+			date := time.Now().Format("20060102")
+
+			// 组合成16位随机数
+			randomNumber := fmt.Sprintf("%s%08d", date, randomSuffix)
+
+			// 查询数据库,检查随机数是否存在
+			if err = db.DB.Where("number = ?", randomNumber).First(&stockOut).Error; err != nil {
+				if err == gorm.ErrRecordNotFound {
+					return "CK" + randomNumber, nil
+				} else {
+					logs.Error("db error: %s", err)
+					return number, err
+				}
+			}
+		}
+	}
+	return number, errors.New("生成随机数失败")
+
+}
+
 // GetMedicineInfo 通过名称、生产企业、规格、批号查询药品信息
 func (e *StockTemplate) GetMedicineInfo(deptId int, medicine map[string]interface{}) (medicineInfo map[string]interface{}, err error) {
 
@@ -31,6 +89,65 @@ func (e *StockTemplate) GetMedicineInfo(deptId int, medicine map[string]interfac
 	err = db.DB.Raw(sql, productID, enterpriseID, specID, batchNumber).Scan(&medicineInfo).Error
 	return
 }
+func (e *StockTemplate) GetMedicineInfoForImg(medicine map[string]interface{}) (medicineImg models.MedicineImg, err error) {
+	productID := utils.ToInt(medicine[models.FieldProductID])
+	enterpriseID := utils.ToInt(medicine[models.FieldEnterpriseID])
+	specID := utils.ToInt(medicine[models.FieldSpecID])
+	unitID := utils.ToInt(medicine[models.FieldUnitID])
+	dosageFormID := utils.ToInt(medicine[models.FieldDosageFormID])
+	batchNumber := utils.ToString(medicine[models.FieldBatchNumber])
+
+	medicineImg.BatchNumber = batchNumber
+	medicineImg.ApprovalNumber = utils.ToString(medicine[models.FieldApprovalNumber])
+	medicineImg.QualificationNumber = utils.ToString(medicine[models.FieldQualificationNumber])
+	medicineImg.ProductionDate = utils.ToString(medicine[models.FieldProducedDate])
+	medicineImg.ExpiryDate = utils.ToString(medicine[models.FieldExpiryDate])
+	product := models.Product{}
+	if err = db.DB.Model(&product).First(&product, productID).Error; err != nil {
+		medicineImg.Product = product.Name
+	}
+
+	enterprise := models.Enterprise{}
+	if err = db.DB.Model(&enterprise).First(&enterprise, enterpriseID).Error; err != nil {
+		medicineImg.Enterprise = enterprise.Name
+
+	}
+
+	spec := models.Spec{}
+	if err = db.DB.Model(&spec).First(&spec, specID).Error; err != nil {
+		medicineImg.Spec = spec.Name
+
+	}
+
+	unit := models.Unit{}
+	if unitID > 0 {
+		if err = db.DB.Model(&unit).First(&unit, unitID).Error; err != nil {
+			medicineImg.Unit = unit.Name
+		}
+	}
+
+	dosageForm := models.DosageForm{}
+	if dosageFormID > 0 {
+		if err = db.DB.Model(&dosageForm).First(&dosageForm, dosageFormID).Error; err != nil {
+			medicineImg.DosageForm = dosageForm.Name
+		}
+	}
+
+	return
+}
+func (e *StockTemplate) GetMedicineInfoScanCodeForImg(medicine map[string]interface{}) (medicineImg models.MedicineImg, err error) {
+	medicineImg.Product = utils.ToString(medicine[models.FieldProductName])
+	medicineImg.Enterprise = utils.ToString(medicine[models.FieldEnterpriseName])
+	medicineImg.Spec = utils.ToString(medicine[models.FieldSpecName])
+	medicineImg.Unit = utils.ToString(medicine[models.FieldUnitName])
+	medicineImg.DosageForm = utils.ToString(medicine[models.FieldDosageFormName])
+	medicineImg.BatchNumber = utils.ToString(medicine[models.FieldBatchNumber])
+	medicineImg.ApprovalNumber = utils.ToString(medicine[models.FieldApprovalNumber])
+	medicineImg.QualificationNumber = utils.ToString(medicine[models.FieldQualificationNumber])
+	medicineImg.ProductionDate = utils.ToString(medicine[models.FieldProducedDate])
+	medicineImg.ExpiryDate = utils.ToString(medicine[models.FieldExpiryDate])
+	return
+}
 
 // FirstOrCreateMedicineInfo 查询或创建 品名、生产企业、规格、单位、剂型
 func (e *StockTemplate) FirstOrCreateMedicineInfo(deptId, createBy int, medicine *map[string]interface{}) (err error) {
@@ -116,6 +233,13 @@ func (e *StockTemplate) FirstOrCreateMedicineInfo(deptId, createBy int, medicine
 
 // BatchStockTemplateIn 批量入库
 func (e *StockTemplate) BatchStockTemplateIn(req *dto.BatchStockTemplateInInsertReq) error {
+
+	number, err := e.GetStockNumber(models.TypeStockIn)
+	if err != nil {
+		logs.Error("获取: %s", err)
+		return err
+	}
+
 	//var err error
 	tx := db.DB.Begin()
 
@@ -135,7 +259,7 @@ func (e *StockTemplate) BatchStockTemplateIn(req *dto.BatchStockTemplateInInsert
 			for k, v := range c.MedicineInfo {
 				sql += fmt.Sprintf("`%s`='%v',", k, v)
 			}
-			sql += fmt.Sprintf("`%s`='%v',", "purchase_unit_price", c.UnitPrice)
+			sql += fmt.Sprintf("`%s`='%v',", "unit_price", c.UnitPrice)
 
 			sql = sql[:len(sql)-1]
 			err = tx.Exec(sql).Error
@@ -150,9 +274,32 @@ func (e *StockTemplate) BatchStockTemplateIn(req *dto.BatchStockTemplateInInsert
 				logs.Error("db error: %s", err)
 				return global.CreateFailedErr
 			}
+			// 添加药品图片信息
+			medicineImg, err := e.GetMedicineInfoForImg(c.MedicineInfo)
+			if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
+				tx.Rollback()
+				logs.Error("获取药品图片信息失败: %s", err)
+				return global.CreateFailedErr
+			}
+			medicineImg.DeptId = req.DeptId
+			medicineImg.CreateBy = req.CreateBy
+			err = tx.Where(models.MedicineImg{
+				Product:     medicineImg.Product,
+				Enterprise:  medicineImg.Enterprise,
+				Spec:        medicineImg.Spec,
+				BatchNumber: medicineImg.BatchNumber,
+				ControlBy: model2.ControlBy{
+					DeptId: req.DeptId,
+				}}).
+				Assign(medicineImg).FirstOrCreate(&medicineImg).Error
+			if err != nil {
+				tx.Rollback()
+				logs.Error("添加药品图片信息失败: %s", err)
+				return global.CreateFailedErr
+			}
 		} else {
 			medicineInfoId = utils.ToInt(medicineInfo["id"])
-			err = tx.Table(models.GetMedicineInfoTableName(req.DeptId)).Where("id = ?", medicineInfoId).Update("purchase_unit_price", c.UnitPrice).Error
+			err = tx.Table(models.GetMedicineInfoTableName(req.DeptId)).Where("id = ?", medicineInfoId).Update("unit_price", c.UnitPrice).Error
 			if err != nil {
 				tx.Rollback()
 				logs.Error("db error: %s", err)
@@ -168,6 +315,7 @@ func (e *StockTemplate) BatchStockTemplateIn(req *dto.BatchStockTemplateInInsert
 			Operator:       c.Operator,
 			ForwardingUnit: c.ForwardingUnit,
 			Date:           c.Date,
+			Number:         number,
 			ControlBy: model2.ControlBy{
 				DeptId:   req.DeptId,
 				CreateBy: req.CreateBy,
@@ -182,7 +330,7 @@ func (e *StockTemplate) BatchStockTemplateIn(req *dto.BatchStockTemplateInInsert
 		c.Id = stockInRecord.Id
 
 		var inventory models.MedicineInventory
-		err = tx.Last(&inventory, "medicine_id = ?", medicineInfoId).Error
+		err = tx.Last(&inventory, "medicine_id = ? and dept_id = ?", medicineInfoId, req.DeptId).Error
 		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
 			tx.Rollback()
 			logs.Error("db error: %s", err)
@@ -217,13 +365,59 @@ func (e *StockTemplate) BatchStockTemplateIn(req *dto.BatchStockTemplateInInsert
 	return nil
 }
 
+func (e *StockTemplate) CheckStockForQrcode(Qrcode string, stock string) error {
+	var err error
+	if !strings.HasPrefix(Qrcode, "9") {
+		return nil
+	}
+	switch stock {
+	case models.TypeStockIn:
+		var stockIn models.StockIn
+		err = db.DB.Where("qrcode = ?", Qrcode).First(&stockIn).Error
+		if err != nil {
+			if errors.Is(err, gorm.ErrRecordNotFound) {
+				return nil
+			}
+			return errors.New("通过条码信息查询入库记录失败")
+		}
+		return errors.New(fmt.Sprintf("条码[%s]已入库,禁止重复入库", Qrcode))
+	case models.TypeStockOut:
+		var stockOut models.StockOut
+		err = db.DB.Where("qrcode = ?", Qrcode).First(&stockOut).Error
+		if err != nil {
+			if errors.Is(err, gorm.ErrRecordNotFound) {
+				return nil
+			}
+			return errors.New("通过条码信息查询入库记录失败")
+		}
+		return errors.New(fmt.Sprintf("条码[%s]已出库,禁止重复出库", Qrcode))
+	}
+
+	return nil
+}
+
 // BatchStockTemplateIn 扫码入库
 func (e *StockTemplate) StockTemplateInScanCode(req *dto.BatchStockTemplateInInsertReq) error {
+	number, err := e.GetStockNumber(models.TypeStockIn)
+	if err != nil {
+		logs.Error("获取: %s", err)
+		return err
+	}
+	for _, s := range req.StockInList {
+		err := e.CheckStockForQrcode(s.Qrcode, models.TypeStockIn)
+		if err != nil {
+			return err
+		}
+	}
+
 	//var err error
 	tx := db.DB.Begin()
 
 	for _, c := range req.StockInList {
-
+		mi := make(map[string]interface{})
+		for k, v := range c.MedicineInfo {
+			mi[k] = v
+		}
 		// 检查药品信息是否已存在
 		err := e.FirstOrCreateMedicineInfo(req.DeptId, req.CreateBy, &c.MedicineInfo)
 		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
@@ -248,6 +442,7 @@ func (e *StockTemplate) StockTemplateInScanCode(req *dto.BatchStockTemplateInIns
 				sql += fmt.Sprintf("`%s`='%v',", k, v)
 			}
 			sql += fmt.Sprintf("`%s`='%v',", "unit_price", c.UnitPrice)
+			sql += fmt.Sprintf("`%s`='%v',", "qrcode", c.Qrcode)
 
 			sql = sql[:len(sql)-1]
 			err = tx.Exec(sql).Error
@@ -262,6 +457,30 @@ func (e *StockTemplate) StockTemplateInScanCode(req *dto.BatchStockTemplateInIns
 				logs.Error("db error: %s", err)
 				return global.CreateFailedErr
 			}
+			// 添加药品图片信息
+			medicineImg, err := e.GetMedicineInfoScanCodeForImg(mi)
+			if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
+				tx.Rollback()
+				logs.Error("获取药品图片信息失败: %s", err)
+				return global.CreateFailedErr
+			}
+			medicineImg.Qrcode = c.Qrcode
+			medicineImg.DeptId = req.DeptId
+			medicineImg.CreateBy = req.CreateBy
+			err = tx.Where(models.MedicineImg{
+				Product:     medicineImg.Product,
+				Enterprise:  medicineImg.Enterprise,
+				Spec:        medicineImg.Spec,
+				BatchNumber: medicineImg.BatchNumber,
+				ControlBy: model2.ControlBy{
+					DeptId: req.DeptId,
+				}}).
+				Assign(medicineImg).FirstOrCreate(&medicineImg).Error
+			if err != nil {
+				tx.Rollback()
+				logs.Error("添加药品图片信息失败: %s", err)
+				return global.CreateFailedErr
+			}
 		} else {
 			medicineInfoId = utils.ToInt(medicineInfo["id"])
 			err = tx.Table(models.GetMedicineInfoTableName(req.DeptId)).Where("id = ?", medicineInfoId).Update("unit_price", c.UnitPrice).Error
@@ -280,6 +499,8 @@ func (e *StockTemplate) StockTemplateInScanCode(req *dto.BatchStockTemplateInIns
 			Operator:       c.Operator,
 			ForwardingUnit: c.ForwardingUnit,
 			Date:           c.Date,
+			Qrcode:         c.Qrcode,
+			Number:         number,
 			ControlBy: model2.ControlBy{
 				DeptId:   req.DeptId,
 				CreateBy: req.CreateBy,
@@ -294,7 +515,7 @@ func (e *StockTemplate) StockTemplateInScanCode(req *dto.BatchStockTemplateInIns
 		c.Id = stockInRecord.Id
 
 		var inventory models.MedicineInventory
-		err = tx.Last(&inventory, "medicine_id = ?", medicineInfoId).Error
+		err = tx.Last(&inventory, "medicine_id = ? and dept_id = ?", medicineInfoId, req.DeptId).Error
 		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
 			tx.Rollback()
 			logs.Error("db error: %s", err)
@@ -332,6 +553,11 @@ func (e *StockTemplate) StockTemplateInScanCode(req *dto.BatchStockTemplateInIns
 // StockTemplateIn 入库
 func (e *StockTemplate) StockTemplateIn(c *dto.StockTemplateInInsertReq) error {
 	var err error
+	number, err := e.GetStockNumber(models.TypeStockIn)
+	if err != nil {
+		logs.Error("获取: %s", err)
+		return err
+	}
 	// 检查药品信息是否已存在
 	medicineInfo, err := e.GetMedicineInfo(c.DeptId, c.MedicineInfo)
 	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
@@ -362,9 +588,33 @@ func (e *StockTemplate) StockTemplateIn(c *dto.StockTemplateInInsertReq) error {
 			logs.Error("db error: %s", err)
 			return global.CreateFailedErr
 		}
+		// 添加药品图片信息
+		medicineImg, err := e.GetMedicineInfoForImg(c.MedicineInfo)
+		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
+			tx.Rollback()
+			logs.Error("获取药品图片信息失败: %s", err)
+			return global.CreateFailedErr
+		}
+		medicineImg.DeptId = c.DeptId
+		medicineImg.CreateBy = c.CreateBy
+		err = tx.Where(models.MedicineImg{
+			Product:     medicineImg.Product,
+			Enterprise:  medicineImg.Enterprise,
+			Spec:        medicineImg.Spec,
+			BatchNumber: medicineImg.BatchNumber,
+			ControlBy: model2.ControlBy{
+				DeptId: c.DeptId,
+			}}).
+			Assign(medicineImg).FirstOrCreate(&medicineImg).Error
+
+		if err != nil {
+			tx.Rollback()
+			logs.Error("添加药品图片信息失败: %s", err)
+			return global.CreateFailedErr
+		}
 	} else {
 		medicineInfoId = utils.ToInt(medicineInfo["id"])
-		err = tx.Table(models.GetMedicineInfoTableName(c.DeptId)).Where("id = ?", medicineInfoId).Update("purchase_unit_price", c.UnitPrice).Error
+		err = tx.Table(models.GetMedicineInfoTableName(c.DeptId)).Where("id = ?", medicineInfoId).Update("unit_price", c.UnitPrice).Error
 		if err != nil {
 			tx.Rollback()
 			logs.Error("db error: %s", err)
@@ -380,6 +630,7 @@ func (e *StockTemplate) StockTemplateIn(c *dto.StockTemplateInInsertReq) error {
 		Operator:       c.Operator,
 		ForwardingUnit: c.ForwardingUnit,
 		Date:           c.Date,
+		Number:         number,
 		ControlBy: model2.ControlBy{
 			DeptId:   c.DeptId,
 			CreateBy: c.CreateBy,
@@ -394,7 +645,7 @@ func (e *StockTemplate) StockTemplateIn(c *dto.StockTemplateInInsertReq) error {
 	c.Id = stockInRecord.Id
 
 	var inventory models.MedicineInventory
-	err = tx.Last(&inventory, "medicine_id = ?", medicineInfoId).Error
+	err = tx.Last(&inventory, "medicine_id = ? and dept_id = ?", medicineInfoId, c.DeptId).Error
 	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
 		tx.Rollback()
 		logs.Error("db error: %s", err)
@@ -461,7 +712,7 @@ func (e *StockTemplate) StockTemplateInEdit(c *dto.StockTemplateInEditReq) error
 		}
 	} else {
 		medicineInfoId = utils.ToInt(medicineInfo["id"])
-		c.MedicineInfo["purchase_unit_price"] = c.UnitPrice
+		c.MedicineInfo["unit_price"] = c.UnitPrice
 		err = tx.Table(models.GetMedicineInfoTableName(c.DeptId)).Where("id = ?", medicineInfoId).Updates(c.MedicineInfo).Error
 		if err != nil {
 			tx.Rollback()
@@ -532,7 +783,7 @@ func (e *StockTemplate) StockTemplateInEdit(c *dto.StockTemplateInEditReq) error
 			}
 
 			// 3、修改的数量差
-			err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id >= ?", medicineInfoId, medicineInventory.Id).
+			err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id >= ? AND dept_id = ?", medicineInfoId, medicineInventory.Id, c.DeptId).
 				UpdateColumn("balance", gorm.Expr("balance + ?", c.Quantity-medicineInventory.TotalIn)).Error
 			if err != nil {
 				tx.Rollback()
@@ -545,7 +796,7 @@ func (e *StockTemplate) StockTemplateInEdit(c *dto.StockTemplateInEditReq) error
 
 		// 2 查询收发记录
 		newMedicineInventory := models.MedicineInventory{}
-		err = tx.Model(models.MedicineInventory{}).Where("id < ? AND medicine_id = ?", medicineInventory.Id, medicineInfoId).Last(&newMedicineInventory).Error
+		err = tx.Model(models.MedicineInventory{}).Where("id < ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, medicineInfoId, c.DeptId).Last(&newMedicineInventory).Error
 		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
 			tx.Rollback()
 			logs.Error("db error: %s", err)
@@ -568,7 +819,7 @@ func (e *StockTemplate) StockTemplateInEdit(c *dto.StockTemplateInEditReq) error
 		// 查询原药品id当前收发记录结余最小值
 		var balance *int
 		err = tx.Model(&models.MedicineInventory{}).Select("MIN(balance)").
-			Where("id >= ? AND medicine_id = ?", medicineInventory.Id, StockInInfo.MedicineID).Scan(&balance).Error
+			Where("id >= ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, StockInInfo.MedicineID, c.DeptId).Scan(&balance).Error
 		if err != nil {
 			tx.Rollback()
 			logs.Error("db error: %s", err)
@@ -581,7 +832,7 @@ func (e *StockTemplate) StockTemplateInEdit(c *dto.StockTemplateInEditReq) error
 		}
 
 		// 3、修改原药品id的数量差
-		err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ?", medicineInventory.MedicineID, medicineInventory.Id).
+		err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ? AND dept_id = ?", medicineInventory.MedicineID, medicineInventory.Id, c.DeptId).
 			UpdateColumn("balance", gorm.Expr("balance - ?", c.Quantity)).Error
 		if err != nil {
 			tx.Rollback()
@@ -589,7 +840,7 @@ func (e *StockTemplate) StockTemplateInEdit(c *dto.StockTemplateInEditReq) error
 			return global.UpdateFailedErr
 		}
 		// 4、修改新药品id的数量差
-		err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ?", medicineInfoId, medicineInventory.Id).
+		err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ? AND dept_id = ?", medicineInfoId, medicineInventory.Id, c.DeptId).
 			UpdateColumn("balance", gorm.Expr("balance + ?", c.Quantity)).Error
 		if err != nil {
 			tx.Rollback()
@@ -626,7 +877,7 @@ func (e *StockTemplate) StockTemplateInDelete(c *dto.StockTemplateInDeleteReq) e
 	// 3 查询当前收发记录结余最小值
 	var balance *int
 	err = tx.Model(&models.MedicineInventory{}).Select("MIN(balance)").
-		Where("id > ? AND medicine_id = ?", medicineInventory.Id, StockInInfo.MedicineID).Scan(&balance).Error
+		Where("id > ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, StockInInfo.MedicineID, c.DeptId).Scan(&balance).Error
 	if err != nil {
 		tx.Rollback()
 		logs.Error("db error: %s", err)
@@ -655,7 +906,7 @@ func (e *StockTemplate) StockTemplateInDelete(c *dto.StockTemplateInDeleteReq) e
 	}
 
 	// 6 修改原药品id的数量差
-	err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ?", medicineInventory.MedicineID, medicineInventory.Id).
+	err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ? AND dept_id = ?", medicineInventory.MedicineID, medicineInventory.Id, c.DeptId).
 		UpdateColumn("balance", gorm.Expr("balance - ?", medicineInventory.TotalIn)).Error
 	if err != nil {
 		tx.Rollback()
@@ -670,7 +921,11 @@ func (e *StockTemplate) StockTemplateInDelete(c *dto.StockTemplateInDeleteReq) e
 // StockTemplateOut 出库
 func (e *StockTemplate) StockTemplateOut(c *dto.StockTemplateOutInsertReq) error {
 	var err error
-
+	number, err := e.GetStockNumber(models.TypeStockIn)
+	if err != nil {
+		logs.Error("获取: %s", err)
+		return err
+	}
 	// 检查药品信息是否已存在
 	medicineInfo, err := e.GetMedicineInfo(c.DeptId, c.MedicineInfo)
 	if err != nil {
@@ -710,6 +965,7 @@ func (e *StockTemplate) StockTemplateOut(c *dto.StockTemplateOutInsertReq) error
 		Operator:      c.Operator,
 		ReceivingUnit: c.ReceivingUnit,
 		Date:          c.Date,
+		Number:        number,
 		ControlBy: model2.ControlBy{
 			DeptId:   c.DeptId,
 			CreateBy: c.CreateBy,
@@ -724,7 +980,7 @@ func (e *StockTemplate) StockTemplateOut(c *dto.StockTemplateOutInsertReq) error
 	c.Id = stockOutRecord.Id
 
 	var inventory models.MedicineInventory
-	err = tx.Last(&inventory, "medicine_id = ?", medicineInfoId).Error
+	err = tx.Last(&inventory, "medicine_id = ? and dept_id = ?", medicineInfoId, c.DeptId).Error
 	if err != nil {
 		tx.Rollback()
 		logs.Error("db error: %s", err)
@@ -824,7 +1080,7 @@ func (e *StockTemplate) StockTemplateOutEdit(c *dto.StockTemplateOutEditReq) err
 
 			// 查询收发记录
 			lastMedicineInventory := models.MedicineInventory{}
-			err = tx.Model(models.MedicineInventory{}).Where("id < ? AND medicine_id = ?", medicineInventory.Id, medicineInfoId).Last(&lastMedicineInventory).Error
+			err = tx.Model(models.MedicineInventory{}).Where("id < ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, medicineInfoId, c.DeptId).Last(&lastMedicineInventory).Error
 			if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
 				tx.Rollback()
 				logs.Error("db error: %s", err)
@@ -838,7 +1094,7 @@ func (e *StockTemplate) StockTemplateOutEdit(c *dto.StockTemplateOutEditReq) err
 			// 查询新药品id当前收发记录结余最小值
 			var balance *int
 			err = tx.Model(&models.MedicineInventory{}).Select("MIN(balance)").
-				Where("id >= ? AND medicine_id = ?", medicineInventory.Id, medicineInfoId).Scan(&balance).Error
+				Where("id >= ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, medicineInfoId, c.DeptId).Scan(&balance).Error
 			if err != nil {
 				tx.Rollback()
 				logs.Error("db error: %s", err)
@@ -863,7 +1119,7 @@ func (e *StockTemplate) StockTemplateOutEdit(c *dto.StockTemplateOutEditReq) err
 			}
 
 			// 3、修改的数量差
-			err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id >= ?", medicineInfoId, medicineInventory.Id).
+			err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id >= ? AND dept_id = ?", medicineInfoId, medicineInventory.Id, c.DeptId).
 				UpdateColumn("balance", gorm.Expr("balance - ?", c.Quantity-medicineInventory.TotalOut)).Error
 			if err != nil {
 				tx.Rollback()
@@ -876,7 +1132,7 @@ func (e *StockTemplate) StockTemplateOutEdit(c *dto.StockTemplateOutEditReq) err
 
 		// 2 查询收发记录
 		newMedicineInventory := models.MedicineInventory{}
-		err = tx.Model(models.MedicineInventory{}).Where("id < ? AND medicine_id = ?", medicineInventory.Id, medicineInfoId).Last(&newMedicineInventory).Error
+		err = tx.Model(models.MedicineInventory{}).Where("id < ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, medicineInfoId, c.DeptId).Last(&newMedicineInventory).Error
 		if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
 			tx.Rollback()
 			logs.Error("db error: %s", err)
@@ -891,7 +1147,7 @@ func (e *StockTemplate) StockTemplateOutEdit(c *dto.StockTemplateOutEditReq) err
 		// 3 查询新药品id当前收发记录结余最小值
 		var balance *int
 		err = tx.Model(&models.MedicineInventory{}).Select("MIN(balance)").
-			Where("id >= ? AND medicine_id = ?", medicineInventory.Id, medicineInfoId).Scan(&balance).Error
+			Where("id >= ? AND medicine_id = ? AND dept_id = ?", medicineInventory.Id, medicineInfoId, c.DeptId).Scan(&balance).Error
 		if err != nil {
 			tx.Rollback()
 			logs.Error("db error: %s", err)
@@ -917,7 +1173,7 @@ func (e *StockTemplate) StockTemplateOutEdit(c *dto.StockTemplateOutEditReq) err
 		}
 
 		// 3、修改原药品id的数量差
-		err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ?", medicineInventory.MedicineID, medicineInventory.Id).
+		err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ? AND dept_id = ?", medicineInventory.MedicineID, medicineInventory.Id, c.DeptId).
 			UpdateColumn("balance", gorm.Expr("balance + ?", c.Quantity)).Error
 		if err != nil {
 			tx.Rollback()
@@ -925,7 +1181,7 @@ func (e *StockTemplate) StockTemplateOutEdit(c *dto.StockTemplateOutEditReq) err
 			return global.UpdateFailedErr
 		}
 		// 4、修改新药品id的数量差
-		err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ?", medicineInfoId, medicineInventory.Id).
+		err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ? AND dept_id = ?", medicineInfoId, medicineInventory.Id, c.DeptId).
 			UpdateColumn("balance", gorm.Expr("balance - ?", c.Quantity)).Error
 		if err != nil {
 			tx.Rollback()
@@ -978,7 +1234,7 @@ func (e *StockTemplate) StockTemplateOutDelete(c *dto.StockTemplateOutDeleteReq)
 	}
 
 	// 6 修改原药品id的数量差
-	err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ?", medicineInventory.MedicineID, medicineInventory.Id).
+	err = tx.Model(models.MedicineInventory{}).Where("medicine_id = ? AND id > ? AND dept_id = ?", medicineInventory.MedicineID, medicineInventory.Id, c.DeptId).
 		UpdateColumn("balance", gorm.Expr("balance + ?", medicineInventory.TotalOut)).Error
 	if err != nil {
 		tx.Rollback()
@@ -992,6 +1248,11 @@ func (e *StockTemplate) StockTemplateOutDelete(c *dto.StockTemplateOutDeleteReq)
 
 // BatchStockTemplateOut 批量出库
 func (e *StockTemplate) BatchStockTemplateOut(req *dto.BatchStockTemplateOutInsertReq) error {
+	number, err := e.GetStockNumber(models.TypeStockIn)
+	if err != nil {
+		logs.Error("获取: %s", err)
+		return err
+	}
 	tx := db.DB.Begin()
 	for _, c := range req.StockOutList {
 		// 检查药品信息是否已存在
@@ -1036,6 +1297,7 @@ func (e *StockTemplate) BatchStockTemplateOut(req *dto.BatchStockTemplateOutInse
 			Operator:      c.Operator,
 			ReceivingUnit: c.ReceivingUnit,
 			Date:          c.Date,
+			Number:        number,
 			ControlBy: model2.ControlBy{
 				DeptId:   req.DeptId,
 				CreateBy: req.CreateBy,
@@ -1050,7 +1312,7 @@ func (e *StockTemplate) BatchStockTemplateOut(req *dto.BatchStockTemplateOutInse
 		c.Id = stockOutRecord.Id
 
 		var inventory models.MedicineInventory
-		err = tx.Last(&inventory, "medicine_id = ?", medicineInfoId).Error
+		err = tx.Last(&inventory, "medicine_id = ? and dept_id = ?", medicineInfoId, req.DeptId).Error
 		if err != nil {
 			tx.Rollback()
 			logs.Error("db error: %s", err)
@@ -1087,6 +1349,18 @@ func (e *StockTemplate) BatchStockTemplateOut(req *dto.BatchStockTemplateOutInse
 
 // StockTemplateOutScanCode 扫码出库
 func (e *StockTemplate) StockTemplateOutScanCode(req *dto.BatchStockTemplateOutInsertReq) error {
+	number, err := e.GetStockNumber(models.TypeStockIn)
+	if err != nil {
+		logs.Error("获取: %s", err)
+		return err
+	}
+	for _, s := range req.StockOutList {
+		err := e.CheckStockForQrcode(s.Qrcode, models.TypeStockOut)
+		if err != nil {
+			return err
+		}
+	}
+
 	tx := db.DB.Begin()
 	for _, c := range req.StockOutList {
 		medicineName := c.MedicineInfo[models.FieldProductName]
@@ -1139,6 +1413,8 @@ func (e *StockTemplate) StockTemplateOutScanCode(req *dto.BatchStockTemplateOutI
 			Operator:      c.Operator,
 			ReceivingUnit: c.ReceivingUnit,
 			Date:          c.Date,
+			Qrcode:        c.Qrcode,
+			Number:        number,
 			ControlBy: model2.ControlBy{
 				DeptId:   req.DeptId,
 				CreateBy: req.CreateBy,
@@ -1153,7 +1429,7 @@ func (e *StockTemplate) StockTemplateOutScanCode(req *dto.BatchStockTemplateOutI
 		c.Id = stockOutRecord.Id
 
 		var inventory models.MedicineInventory
-		err = tx.Last(&inventory, "medicine_id = ?", medicineInfoId).Error
+		err = tx.Last(&inventory, "medicine_id = ? and dept_id = ?", medicineInfoId, req.DeptId).Error
 		if err != nil {
 			tx.Rollback()
 			logs.Error("db error: %s", err)
@@ -1513,7 +1789,7 @@ func (e *StockTemplate) StockOperatorList(c *dto.StockOperatorListReq, deptId in
 func (e *StockTemplate) StockInquiryList(c *dto.StockStatListReq, deptId int) (list []map[string]interface{}, count int64, err error) {
 
 	mtable := models.GetMedicineInfoTableName(deptId)
-	whereSql := " WHERE mi.dept_id = " + strconv.Itoa(deptId)
+	whereSql := ""
 	if c.ProductID > 0 {
 		whereSql += " AND m_info.product_id = " + strconv.Itoa(c.ProductID)
 	}
@@ -1529,16 +1805,16 @@ func (e *StockTemplate) StockInquiryList(c *dto.StockStatListReq, deptId int) (l
 	if len(c.EndDate) > 0 {
 		whereSql += " AND m_info.expiry_date <= '" + c.EndDate + "'"
 	}
-
+	if len(whereSql) > 0 {
+		whereSql = " WHERE " + strings.TrimLeft(whereSql, " AND ")
+	}
 	offset := (c.Page - 1) * c.PageSize
-	//sql := "SELECT * FROM (SELECT a.* FROM (SELECT * FROM medicine_inventory ORDER BY id DESC LIMIT 100) a GROUP BY a.medicine_id) b " +
-	//	"LEFT JOIN " + mtable + " ON b.medicine_id=" + mtable + ".id WHERE " + whereSql
 
-	sql := "SELECT mi.*,m_info.* FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory WHERE deleted_at is null GROUP BY medicine_id) AS mi_latest " +
+	sql := "SELECT mi.*,m_info.* FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory WHERE dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null GROUP BY medicine_id) AS mi_latest " +
 		"JOIN medicine_inventory AS mi ON mi.medicine_id=mi_latest.medicine_id AND mi.id=mi_latest.latest_id " +
 		"LEFT JOIN " + mtable + " AS m_info ON mi.medicine_id=m_info.id" + whereSql + " order by m_info.expiry_date limit ? offset ?;"
 
-	sqlWhereCount := "SELECT COUNT(1) FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory WHERE deleted_at is null GROUP BY medicine_id) AS mi_latest " +
+	sqlWhereCount := "SELECT COUNT(1) FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory WHERE dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null GROUP BY medicine_id) AS mi_latest " +
 		"JOIN medicine_inventory AS mi ON mi.medicine_id=mi_latest.medicine_id AND mi.id=mi_latest.latest_id " +
 		"LEFT JOIN " + mtable + " AS m_info ON mi.medicine_id=m_info.id" + whereSql
 
@@ -1581,7 +1857,7 @@ func (e *StockTemplate) StockInquiryList(c *dto.StockStatListReq, deptId int) (l
 func (e *StockTemplate) StockInquiryExcel(c *dto.StockStatListReq, deptId int) (list []map[string]interface{}, err error) {
 
 	mtable := models.GetMedicineInfoTableName(deptId)
-	whereSql := " WHERE mi.dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null"
+	whereSql := ""
 	if c.ProductID > 0 {
 		whereSql += " AND m_info.product_id = " + strconv.Itoa(c.ProductID)
 	}
@@ -1597,8 +1873,10 @@ func (e *StockTemplate) StockInquiryExcel(c *dto.StockStatListReq, deptId int) (
 	if len(c.EndDate) > 0 {
 		whereSql += " AND m_info.expiry_date <= '" + c.EndDate + "'"
 	}
-
-	sql := "SELECT mi.*,m_info.* FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory GROUP BY medicine_id) AS mi_latest " +
+	if len(whereSql) > 0 {
+		whereSql = " WHERE " + strings.TrimLeft(whereSql, " AND ")
+	}
+	sql := "SELECT mi.*,m_info.* FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory WHERE dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null GROUP BY medicine_id) AS mi_latest " +
 		"JOIN medicine_inventory AS mi ON mi.medicine_id=mi_latest.medicine_id AND mi.id=mi_latest.latest_id " +
 		"LEFT JOIN " + mtable + " AS m_info ON mi.medicine_id=m_info.id" + whereSql + " order by m_info.expiry_date"
 
@@ -1633,15 +1911,18 @@ func (e *StockTemplate) StockInquiryExcel(c *dto.StockStatListReq, deptId int) (
 func (e *StockTemplate) StockStat(c *dto.StockStatReq, deptId int) (list []map[string]interface{}, count int64, err error) {
 
 	mtable := models.GetMedicineInfoTableName(deptId)
-	whereSql := " WHERE mi.dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null"
+	whereSql := ""
 	if c.ProductID > 0 {
 		whereSql += " AND m_info.product_id = " + strconv.Itoa(c.ProductID)
 	}
 	if c.SpecID > 0 {
 		whereSql += " AND m_info.spec_id = " + strconv.Itoa(c.SpecID)
 	}
+	if len(whereSql) > 0 {
+		whereSql = " WHERE " + strings.TrimLeft(whereSql, " AND ")
+	}
 	var result []map[string]interface{}
-	sql := "SELECT mi.balance,m_info.product_id,m_info.spec_id,m_info.unit_id FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory GROUP BY medicine_id) AS mi_latest " +
+	sql := "SELECT mi.balance,m_info.product_id,m_info.spec_id,m_info.unit_id FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory WHERE dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null GROUP BY medicine_id) AS mi_latest " +
 		"JOIN medicine_inventory AS mi ON mi.medicine_id=mi_latest.medicine_id AND mi.id=mi_latest.latest_id " +
 		"LEFT JOIN " + mtable + " AS m_info ON mi.medicine_id=m_info.id" + whereSql
 
@@ -1712,11 +1993,10 @@ func (e *StockTemplate) StockStat(c *dto.StockStatReq, deptId int) (list []map[s
 func (e *StockTemplate) StockHomeStat(deptId int) (list map[string]interface{}, count int64, err error) {
 
 	mtable := models.GetMedicineInfoTableName(deptId)
-	whereSql := " WHERE mi.dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null"
 	var result []map[string]interface{}
-	sql := "SELECT mi.balance,m_info.unit_price FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory GROUP BY medicine_id) AS mi_latest " +
+	sql := "SELECT mi.balance,m_info.unit_price FROM (SELECT medicine_id,MAX(id) AS latest_id FROM medicine_inventory WHERE dept_id = " + strconv.Itoa(deptId) + " AND deleted_at is null GROUP BY medicine_id) AS mi_latest " +
 		"JOIN medicine_inventory AS mi ON mi.medicine_id=mi_latest.medicine_id AND mi.id=mi_latest.latest_id " +
-		"LEFT JOIN " + mtable + " AS m_info ON mi.medicine_id=m_info.id" + whereSql
+		"LEFT JOIN " + mtable + " AS m_info ON mi.medicine_id=m_info.id"
 
 	err = db.DB.Raw(sql).Scan(&result).Error
 	if err != nil {

+ 31 - 0
utils/comm.go

@@ -253,6 +253,37 @@ func ToDate(value interface{}) string {
 	return key
 }
 
+func ToString(value interface{}) string {
+	if value == nil {
+		return ""
+	}
+	switch v := value.(type) {
+	case string:
+		return v
+	case int:
+		return strconv.FormatInt(int64(v), 10)
+	case int8:
+		return strconv.FormatInt(int64(v), 10)
+	case int16:
+		return strconv.FormatInt(int64(v), 10)
+	case int32:
+		return strconv.FormatInt(int64(v), 10)
+	case int64:
+		return strconv.FormatInt(v, 10)
+	case uint:
+		return strconv.FormatUint(uint64(v), 10)
+	case uint8:
+		return strconv.FormatUint(uint64(v), 10)
+	case uint16:
+		return strconv.FormatUint(uint64(v), 10)
+	case uint32:
+		return strconv.FormatUint(uint64(v), 10)
+	case uint64:
+		return strconv.FormatUint(v, 10)
+	}
+	return ""
+}
+
 // IsChineseOnly 判断字符串是否只包含中文字符
 func IsChineseOnly(s string) bool {
 	chineseRegexp := regexp.MustCompile("^[\\p{Han}]+$")

+ 64 - 0
utils/comm_test.go

@@ -5,9 +5,15 @@ import (
 	"github.com/beego/beego/v2/core/logs"
 	"github.com/boombuler/barcode"
 	"github.com/boombuler/barcode/code128"
+	"github.com/signintech/gopdf"
+	"image"
+	"image/color"
+	"image/jpeg"
 	"image/png"
+	"net/http"
 	"os"
 	"testing"
+	"time"
 )
 
 // TestGet is a sample to run an endpoint test
@@ -42,3 +48,61 @@ func TestGetQRCode(t *testing.T) {
 	png.Encode(file, qrCode)
 
 }
+
+func TestDownloadImage(t *testing.T) {
+	resp, err := http.Get("https://bzdcdn.baozhida.cn/2024-02-18/9be06bd0aa654c4c80fa7ce858db73be.png")
+	//resp, err := http.Get("https://bzdcdn.baozhida.cn/2024-02-19/85219d304dc44d0ea4ce7f29bbc2c89e.jpg")
+	if err != nil {
+		fmt.Println(err)
+	}
+	defer resp.Body.Close()
+	//imageBytes, err := io.ReadAll(resp.Body)
+	// 解码图片
+	imgH, _, err := image.Decode(resp.Body)
+	if err != nil {
+		fmt.Println("解码图片失败", err)
+	}
+	// 检查图像的 Bounds 是否为 16 位深度
+	bounds := imgH.Bounds()
+	if _, ok := imgH.At(bounds.Min.X, bounds.Min.Y).(color.Gray16); !ok {
+		fmt.Println("Image does not have 16-bit depth.")
+	} else {
+		fmt.Println("Image has 16-bit depth.")
+	}
+	pdf := &gopdf.GoPdf{}
+	pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}})
+	pdf.SetMarginTop(40)
+	pdf.SetMarginBottom(40)
+
+	pdf.AddPage()
+	imgWidth := float64(imgH.Bounds().Dx())
+	imgHeight := float64(imgH.Bounds().Dy())
+	W, H := imgWidth, imgHeight
+	if imgWidth > imgHeight && imgWidth > 555 {
+		W = 555
+		H = 555 * float64(imgHeight) / float64(imgWidth)
+	}
+
+	if imgWidth < imgHeight && imgWidth > 760 {
+		W = 760 * float64(imgWidth) / float64(imgHeight)
+		H = 760
+		if W > 555 {
+			H = 555 * 760 / W
+			W = 555
+		}
+
+	}
+	file, _ := os.Create("./test.jpg")
+	defer file.Close()
+	jpeg.Encode(file, imgH, &jpeg.Options{100})
+	//err = pdf.ImageFrom(imgH, (595-W)/2, (840-H)/2, &gopdf.Rect{W: W, H: H})
+	err = pdf.Image("./test.jpg", (595-W)/2, (840-H)/2, &gopdf.Rect{W: W, H: H})
+	if err != nil {
+		fmt.Println(err)
+	}
+	filename := "运输记录表" + time.Now().Format("20060102150405") + ".pdf"
+	// 保存文件
+	if err = pdf.WritePdf("./" + filename); err != nil {
+		fmt.Println(err)
+	}
+}

+ 42 - 0
utils/download.go

@@ -0,0 +1,42 @@
+package utils
+
+import (
+	"image"
+	_ "image/jpeg"
+	"io"
+	"net/http"
+	"os"
+)
+
+func DownloadImage(url, filepath string) error {
+	// 发送 HTTP GET 请求
+	resp, err := http.Get(url)
+	if err != nil {
+		return err
+	}
+	defer resp.Body.Close()
+
+	// 创建文件
+	file, err := os.Create(filepath)
+	if err != nil {
+		return err
+	}
+	defer file.Close()
+
+	// 将响应流中的数据写入文件
+	_, err = io.Copy(file, resp.Body)
+	return err
+}
+
+func GetImage(url string) (image.Image, error) {
+	resp, err := http.Get(url)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	img, _, err := image.Decode(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+	return img, nil
+}