diff --git a/fs_gen_api.sh b/fs_gen_api.sh index 6d35a29e..a699c2fc 100755 --- a/fs_gen_api.sh +++ b/fs_gen_api.sh @@ -1,5 +1,14 @@ #! /bin/bash name=${1%%\\*} + +options=("backend") +for option in "${options[@]}"; do + if [ "$name" = "$option" ]; then + echo "不能在"$name"里使用" + exit + fi +done + echo $name goctl api go -api server_api/$name.api -dir server/$name --home ./goctl_template/ # ctxName=server/$name/internal/svc/servicecontext.go diff --git a/fs_gen_api_backend.sh b/fs_gen_api_backend.sh index d051a688..cf83b8b9 100755 --- a/fs_gen_api_backend.sh +++ b/fs_gen_api_backend.sh @@ -1,6 +1,6 @@ #! /bin/bash name=${1%%\\*} -options=("backend" "backend1" "backend2") +options=("backend") for option in "${options[@]}"; do if [ "$name" = "$option" ]; then echo $name diff --git a/goctl_template_backend/api/handler.tpl b/goctl_template_backend/api/handler.tpl index 5bd709a9..7ca8f282 100644 --- a/goctl_template_backend/api/handler.tpl +++ b/goctl_template_backend/api/handler.tpl @@ -20,7 +20,7 @@ func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc { // 定义错误变量 err error // 定义用户信息变量 - userinfo *auth.UserInfo + userinfo *auth.BackendUserInfo ) // 解析JWT token,并对空用户进行判断 claims, err := svcCtx.ParseJwtToken(r) diff --git a/model/gmodel/fs_canteen_product_logic.go b/model/gmodel/fs_canteen_product_logic.go index 0795284f..44dc16f6 100755 --- a/model/gmodel/fs_canteen_product_logic.go +++ b/model/gmodel/fs_canteen_product_logic.go @@ -27,8 +27,5 @@ func (c *FsCanteenProductModel) Create(ctx context.Context, data *FsCanteenProdu func (c *FsCanteenProductModel) GetAllByCanteenTypeIdOrderAsc(ctx context.Context, typeId int64) (resp []FsCanteenProduct, err error) { err = c.db.WithContext(ctx).Model(&FsCanteenProduct{}).Where("`canteen_type` = ? and `status` = ?", typeId, 1).Order("sort asc").Find(&resp).Error - if err != nil { - return nil, err - } - return + return resp, err } diff --git a/model/gmodel/fs_product_logic.go b/model/gmodel/fs_product_logic.go index b162d634..255a2e82 100755 --- a/model/gmodel/fs_product_logic.go +++ b/model/gmodel/fs_product_logic.go @@ -49,3 +49,8 @@ func (p *FsProductModel) GetRandomProductList(ctx context.Context, limit int) (r } return } + +func (p *FsProductModel) FindAllOnlyByIds(ctx context.Context, ids []int64) (resp []*FsProduct, err error) { + err = p.db.WithContext(ctx).Model(&FsProduct{}).Where("`id` IN (?)", ids).Find(&resp).Error + return resp, err +} diff --git a/model/gmodel/fs_product_price_logic.go b/model/gmodel/fs_product_price_logic.go index f890b324..6a299b56 100755 --- a/model/gmodel/fs_product_price_logic.go +++ b/model/gmodel/fs_product_price_logic.go @@ -71,3 +71,20 @@ func (p *FsProductPriceModel) GetPriceListByProductIds(ctx context.Context, prod } return } + +// 产品价格 +type ProductPrice struct { + Id int64 `json:"id"` + MinBuyNum int64 `json:"min_buy_num"` + StepNum interface{} `json:"step_num"` + StepPrice interface{} `json:"step_price"` + ProductId int64 `json:"product_id"` + SizeId int64 `json:"size_id"` + EachBoxNum int64 `json:"each_box_num"` +} + +func (c *FsProductPriceModel) GetAllSelectBySizeId(ctx context.Context, sizeIds []int64) (prices []*ProductPrice, err error) { + + err = c.db.WithContext(ctx).Model(&ProductPrice{}).Where("size_id IN (?) AND status = ?", sizeIds, 1).Select("id, min_buy_num, step_num, step_price, product_id, size_id, each_box_num").Find(&prices).Error + return prices, err +} diff --git a/model/gmodel/fs_product_size_logic.go b/model/gmodel/fs_product_size_logic.go index aa8576f1..bf008f69 100755 --- a/model/gmodel/fs_product_size_logic.go +++ b/model/gmodel/fs_product_size_logic.go @@ -45,3 +45,13 @@ func (s *FsProductSizeModel) GetAllByProductIds(ctx context.Context, productIds } return } + +type CapacityId struct { + Id int64 `json:"id"` + Capacity string `json:"capacity"` +} + +func (c *FsProductSizeModel) GetAllSelectIdAndCapacityByIds(ctx context.Context, sizeIds []int64) (sizes []CapacityId, err error) { + err = c.db.WithContext(ctx).Where("id IN ?", sizeIds).Select("id, capacity").Find(&sizes).Error + return sizes, err +} diff --git a/model/gmodel/fs_quotation_logic.go b/model/gmodel/fs_quotation_logic.go index e68225aa..27a9fbdc 100644 --- a/model/gmodel/fs_quotation_logic.go +++ b/model/gmodel/fs_quotation_logic.go @@ -1,2 +1,10 @@ package gmodel -// TODO: 使用model的属性做你想做的 \ No newline at end of file + +import "context" + +// TODO: 使用model的属性做你想做的 + +func (m *FsQuotationModel) FindOneOnlyById(ctx context.Context, quotationId int64) (resp FsQuotation, err error) { + err = m.db.WithContext(ctx).Model(&resp).Where("`quotation_id` = ?", quotationId).Take(&resp).Error + return resp, err +} diff --git a/model/gmodel/fs_quotation_product_logic.go b/model/gmodel/fs_quotation_product_logic.go index e68225aa..a230f11f 100644 --- a/model/gmodel/fs_quotation_product_logic.go +++ b/model/gmodel/fs_quotation_product_logic.go @@ -1,2 +1,10 @@ package gmodel -// TODO: 使用model的属性做你想做的 \ No newline at end of file + +import "context" + +// TODO: 使用model的属性做你想做的 + +func (c *FsQuotationProductModel) GetAllByQuotationIdOrderAsc(ctx context.Context, quotationId int64) (resp []FsQuotationProduct, err error) { + err = c.db.WithContext(ctx).Model(&FsQuotationProduct{}).Where("`quotation_id` = ? and `status` = ?", quotationId, 1).Order("sort asc").Find(&resp).Error + return resp, err +} diff --git a/model/gmodel/fs_quotation_remark_template_logic.go b/model/gmodel/fs_quotation_remark_template_logic.go index e68225aa..fff0c296 100644 --- a/model/gmodel/fs_quotation_remark_template_logic.go +++ b/model/gmodel/fs_quotation_remark_template_logic.go @@ -1,2 +1,10 @@ package gmodel -// TODO: 使用model的属性做你想做的 \ No newline at end of file + +import "context" + +// TODO: 使用model的属性做你想做的 + +func (c *FsQuotationRemarkTemplateModel) GetAllSelectContent(ctx context.Context) (content []string, err error) { + err = c.db.WithContext(ctx).Model(&FsQuotationRemarkTemplate{}).Where("status = ?", 1).Select("content").Find(&content).Error + return content, err +} diff --git a/server/backend/internal/handler/quotationdetailhandler.go b/server/backend/internal/handler/quotationdetailhandler.go index 6585222e..59640c7b 100644 --- a/server/backend/internal/handler/quotationdetailhandler.go +++ b/server/backend/internal/handler/quotationdetailhandler.go @@ -48,7 +48,7 @@ func QuotationDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return } - var req types.Request + var req types.RequestQuotationId // 如果端点有请求结构体,则使用httpx.Parse方法从HTTP请求体中解析请求数据 if err := httpx.Parse(r, &req); err != nil { httpx.OkJsonCtx(r.Context(), w, &basic.Response{ diff --git a/server/backend/internal/logic/quotationdetaillogic.go b/server/backend/internal/logic/quotationdetaillogic.go index 8eb3b01b..17cf4ee6 100644 --- a/server/backend/internal/logic/quotationdetaillogic.go +++ b/server/backend/internal/logic/quotationdetaillogic.go @@ -1,15 +1,20 @@ package logic import ( + "encoding/json" "fusenapi/utils/auth" "fusenapi/utils/basic" + "fusenapi/utils/collect" + "strings" "context" "fusenapi/server/backend/internal/svc" "fusenapi/server/backend/internal/types" + "github.com/tidwall/gjson" "github.com/zeromicro/go-zero/core/logx" + "gorm.io/gorm" ) type QuotationDetailLogic struct { @@ -26,9 +31,193 @@ func NewQuotationDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Q } } -func (l *QuotationDetailLogic) QuotationDetail(req *types.Request, userinfo *auth.BackendUserInfo) (resp *basic.Response) { +func GetPrice(num int64, stepNum []int64, stepPrice []int64) int64 { + //阶梯价计算 + if num > stepNum[len(stepNum)-1] { + return stepPrice[len(stepPrice)-1] + } + for k, v := range stepNum { + if num <= v { + return stepPrice[k] + } + } + return 0 +} + +func (l *QuotationDetailLogic) QuotationDetail(req *types.RequestQuotationId, userinfo *auth.BackendUserInfo) (resp *basic.Response) { // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) // userinfo 传入值时, 一定不为null + quot, err := l.svcCtx.AllModels.FsQuotation.FindOneOnlyById(l.ctx, req.QuotationId) + if err != nil { + if err == gorm.ErrRecordNotFound { + return resp.SetStatus(basic.CodeDbRecordNotFoundErr) + } + return resp.SetStatus(basic.CodeDbSqlErr) + } + + CanteenProduct, err := l.svcCtx.AllModels.FsCanteenProduct.GetAllByCanteenTypeIdOrderAsc(l.ctx, *quot.CanteenType) + if err != nil { + if err == gorm.ErrRecordNotFound { + return resp.SetStatus(basic.CodeDbRecordNotFoundErr) + } + return resp.SetStatus(basic.CodeDbSqlErr) + } + + quotation, err := l.svcCtx.AllModels.FsQuotationProduct.GetAllByQuotationIdOrderAsc(l.ctx, req.QuotationId) + if err != nil { + if err != gorm.ErrRecordNotFound { + return resp.SetStatus(basic.CodeDbSqlErr) + } + } + + var target any = quotation + if len(quotation) == 0 { + target = CanteenProduct + } + + jdata, err := json.Marshal(target) + if err != nil { + logx.Error(err) + return resp.SetStatus(basic.CodeJsonErr) + } + + list := gjson.ParseBytes(jdata) + + qFlag := len(quotation) > 0 + + //获取备注模板 + markList, err := l.svcCtx.AllModels.FsQuotationRemarkTemplate.GetAllSelectContent(l.ctx) + + var productIds = collect.ArrayColumn[int64](CanteenProduct, "product_id") + productList, err := l.svcCtx.AllModels.FsProduct.FindAllOnlyByIds(l.ctx, productIds) + collect.Array2MapByKeyTag[int64](productList, "id") + + //获取size信息 + var sizeIds = collect.ArrayColumn[int64](CanteenProduct, "SizeId") + sizes, err := l.svcCtx.AllModels.FsProductSize.GetAllSelectIdAndCapacityByIds(l.ctx, sizeIds) + + //获取价格信息 + productPrice, err := l.svcCtx.AllModels.FsProductPrice.GetAllSelectBySizeId(l.ctx, sizeIds) + // product := []map[string]interface{}{} + + product := []map[string]interface{}{} + for _, parr := range list.Array() { + + var priceList []map[string]int64 + + if !qFlag { + + if price, ok := productPrice[parr.Get("size_id").Int()]; !ok { + priceList = []map[string]int64{ + {"num": 1, "price": 0}, + {"num": 1, "price": 0}, + {"num": 1, "price": 0}, + } + } else { + + i := 0 + price.StepNum = collect.ArrayString2Int(strings.Split(price.StepNum.(string), ",")) + price.StepPrice = collect.ArrayString2Int(strings.Split(price.StepPrice.(string), ",")) + for price.MinBuyNum < int64(len(price.StepNum.([]string))+5) && i < 3 { + priceList = append(priceList, map[string]int64{ + "num": int64(price.MinBuyNum * price.EachBoxNum), + "price": GetPrice(price.MinBuyNum, price.StepNum.([]int64), price.StepPrice.([]int64)) / 100, + }) + price.MinBuyNum++ + i++ + } + if len(priceList) < 3 { + for j := 0; j < 3-len(priceList); j++ { + priceList = append(priceList, map[string]int64{"num": 1, "price": 0}) + } + } + } + } + + + + var ( + Id any + priceInfo any + mark any + sid any + + isGift bool + name any + size any + cycle any + img any + + num any + ) + if qFlag { + + Id = parr.Get("id") + + err = json.Unmarshal([]byte(parr.Get("price_info").String()), &priceInfo) + if err != nil { + logx.Error(err) + return resp.SetStatus(basic.CodeJsonErr) + } + + if parr.Get("sid").Exists() { + sid = parr.Get("sid").Int() + } + + name = parr.Get("name").String() + size = parr.Get("size").Int() + cycle = parr.Get("cycle").Int() + img = parr.Get("img").String() + + if parr.Get("remark").Exists() { + err = json.Unmarshal([]byte(parr.Get("remark").String()), &mark) + if err != nil { + logx.Error(err) + return resp.SetStatus(basic.CodeJsonErr) + } + } + + num = parr.Get("num").Int() + + } else { + + if parr.Get("sid").Exists() { + sid = parr.Get("sid").Int() + } + + productList + + $productList[$parr['product_id']]['title'] + + + } + + product = append(product, map[string]interface{}{ + "id": Id, + "s_id": sid, + "is_gift": isGift, + "name": name, + "size": size, + "cycle": cycle, + "img": img, + "mark": mark, + "price_list": priceInfo, + "num": num, + }) + + // product = append(product, map[string]interface{}{ + // "id": qFlag ? parr.ID : nil, + // "sId": parr.SID ? parr.SID : nil, + // "isGift": qFlag && parr.IsGift, + // "name": qFlag ? parr.Name : productList[parr.ProductID].Title, + // "size": qFlag ? parr.Size : sizes[parr.SizeId].Capacity, + // "cycle": qFlag ? parr.Cycle : productList[parr.ProductID].ProduceDays + productList[parr.ProductID].DeliveryDays, + // "img": qFlag ? parr.Img : "", + // "mark": qFlag && parr.Remark ? json.Unmarshal(parr.Remark) : nil, + // "priceList": qFlag ? json.Unmarshal(parr.PriceInfo) : priceList, + // "num": qFlag ? parr.Num : 1, + // }) + } return resp.SetStatus(basic.CodeOK) } diff --git a/server_api/backend.api b/server_api/backend.api index 06c4f53e..35bd82b1 100644 --- a/server_api/backend.api +++ b/server_api/backend.api @@ -12,7 +12,7 @@ import "basic.api" service backend { // 报价单详情 @handler QuotationDetailHandler - get /quotation/detail(request) returns (response); + get /quotation/detail(RequestQuotationId) returns (response); @handler BackendUserLoginHandler post /backend-user/login(RequestUserLogin) returns (response); diff --git a/utils/collect/collect.go b/utils/collect/collect.go new file mode 100644 index 00000000..af25cb3a --- /dev/null +++ b/utils/collect/collect.go @@ -0,0 +1,82 @@ +package collect + +import ( + "reflect" + "strconv" +) + +func ArrayColumn[R any, T any](arr []T, column string) []R { + var result []R + s := reflect.ValueOf(arr) + + for i := 0; i < s.Len(); i++ { + e := s.Index(i) + k := e.FieldByName(column) + result = append(result, k.Interface().(R)) + } + + return result +} + +func ArrayIndex[T any](arr []T, index int) (result T, ok bool) { + if index < len(arr) { + result = arr[index] + ok = true + return + } + ok = false + return +} + +func ArrayString2Int(arr interface{}) (result []int64) { + for _, a := range arr.([]string) { + v, err := strconv.ParseInt(a, 10, 64) + if err != nil { + panic(err) + } + result = append(result, v) + } + return result +} + +func Array2MapByKey[KEY comparable, VALUE any](arrSrc []VALUE, fieldName string) (result map[KEY]VALUE) { + result = make(map[KEY]VALUE) + arr := reflect.ValueOf(arrSrc) + + for i := 0; i < arr.Len(); i++ { + srcv := arr.Index(i) + fv := srcv.Elem().FieldByName(fieldName) + k := fv.Interface().(KEY) + result[k] = srcv.Interface().(VALUE) + } + + return result +} + +func Array2MapByKeyTag[KEY comparable, VALUE any](arrSrc []VALUE, tag string) (result map[KEY]VALUE) { + + arr := reflect.ValueOf(arrSrc) + + if arr.Len() == 0 { + return result + } + result = make(map[KEY]VALUE) + + eleType := arr.Index(0).Elem().Type() + + for j := 0; j < eleType.NumField(); j++ { + if value, ok := eleType.Field(j).Tag.Lookup("json"); ok && value == tag { + + for i := 0; i < arr.Len(); i++ { + srcv := arr.Index(i) + fv := srcv.Elem().Field(j) + k := fv.Interface().(KEY) + result[k] = srcv.Interface().(VALUE) + } + + return + } + } + + return result +} diff --git a/utils/collect/collect_test.go b/utils/collect/collect_test.go new file mode 100644 index 00000000..a1ff745d --- /dev/null +++ b/utils/collect/collect_test.go @@ -0,0 +1,32 @@ +package collect + +import ( + "log" + "testing" +) + +type ABC struct { + A int64 `json:"a"` + B string `json:"b"` + C interface{} `json:"c"` +} + +func TestArray2MapByKey(t *testing.T) { + var abcs []*ABC = []*ABC{ + {1, "2", 3}, + {3, "1", 2}, + } + a := Array2MapByKey[string](abcs, "B") + log.Printf("%##v", a) + log.Println(len(a)) +} + +func TestArray2MapByKeyTag(t *testing.T) { + var abcs []*ABC = []*ABC{ + {1, "2", 3}, + {3, "1", 2}, + } + a := Array2MapByKeyTag[int64](abcs, "a") + log.Printf("%##v", a) + log.Println(len(a)) +}