diff --git a/server/backend/Dockerfile b/server/backend/Dockerfile deleted file mode 100755 index e30c6bed..00000000 --- a/server/backend/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -FROM alpine - -WORKDIR /www/fusenapi/ -COPY ./bin/api-backend-srv /www/fusenapi/ -COPY ./etc /www/fusenapi/etc -CMD ["/www/fusenapi/api-backend-srv"] diff --git a/server/backend/backend.go b/server/backend/backend.go deleted file mode 100644 index bec54a34..00000000 --- a/server/backend/backend.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "net/http" - - "fusenapi/server/backend/internal/config" - "fusenapi/server/backend/internal/handler" - "fusenapi/server/backend/internal/svc" - "fusenapi/utils/auth" - - "github.com/zeromicro/go-zero/core/conf" - "github.com/zeromicro/go-zero/rest" -) - -var configFile = flag.String("f", "etc/backend.yaml", "the config file") - -func main() { - flag.Parse() - - var c config.Config - conf.MustLoad(*configFile, &c) - - server := rest.MustNewServer(c.RestConf, rest.WithCustomCors(auth.FsCors, func(w http.ResponseWriter) { - })) - defer server.Stop() - - ctx := svc.NewServiceContext(c) - handler.RegisterHandlers(server, ctx) - - fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port) - server.Start() -} diff --git a/server/backend/etc/backend.yaml b/server/backend/etc/backend.yaml deleted file mode 100644 index b9a69dfe..00000000 --- a/server/backend/etc/backend.yaml +++ /dev/null @@ -1,11 +0,0 @@ -Name: backend -Host: localhost -Port: 9901 -Timeout: 15000 #服务超时时间 -SourceMysql: "fsreaderwriter:XErSYmLELKMnf3Dh@tcp(fusen.cdmigcvz3rle.us-east-2.rds.amazonaws.com:3306)/fusen" -Log: - Stat: false -Auth: - AccessSecret: fusen_backend_2023 - AccessExpire: 2592000 - RefreshAfter: 1592000 \ No newline at end of file diff --git a/server/backend/internal/config/config.go b/server/backend/internal/config/config.go deleted file mode 100644 index 7b0d28ab..00000000 --- a/server/backend/internal/config/config.go +++ /dev/null @@ -1,14 +0,0 @@ -package config - -import ( - "fusenapi/server/backend/internal/types" - - "github.com/zeromicro/go-zero/rest" -) - -type Config struct { - rest.RestConf - SourceMysql string - Auth types.Auth - ReplicaId uint64 -} diff --git a/server/backend/internal/handler/backenduserloginhandler.go b/server/backend/internal/handler/backenduserloginhandler.go deleted file mode 100644 index 640f36b6..00000000 --- a/server/backend/internal/handler/backenduserloginhandler.go +++ /dev/null @@ -1,40 +0,0 @@ -package handler - -import ( - "errors" - "fmt" - "net/http" - - "github.com/zeromicro/go-zero/core/logx" - "github.com/zeromicro/go-zero/rest/httpx" - - "fusenapi/utils/basic" - - "fusenapi/server/backend/internal/logic" - "fusenapi/server/backend/internal/svc" - "fusenapi/server/backend/internal/types" -) - -func BackendUserLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - - var req types.RequestUserLogin - - // 创建一个业务逻辑层实例 - l := logic.NewBackendUserLoginLogic(r.Context(), svcCtx) - resp, token := l.BackendUserLogin(&req) - if resp.Code == basic.CodeOK.Code { - w.Header().Add("Authorization", fmt.Sprintf("Bearer %s", token)) - } - - // 如果响应不为nil,则使用httpx.OkJsonCtx方法返回JSON响应; - // 否则,发送500内部服务器错误的JSON响应并记录错误消息logx.Error。 - if resp != nil { - httpx.OkJsonCtx(r.Context(), w, resp) - } else { - err := errors.New("server logic is error, resp must not be nil") - httpx.ErrorCtx(r.Context(), w, err) - logx.Error(err) - } - } -} diff --git a/server/backend/internal/handler/quotationdetailhandler.go b/server/backend/internal/handler/quotationdetailhandler.go deleted file mode 100644 index adbb9621..00000000 --- a/server/backend/internal/handler/quotationdetailhandler.go +++ /dev/null @@ -1,34 +0,0 @@ -package handler - -import ( - "net/http" - "reflect" - - "fusenapi/utils/basic" - - "fusenapi/server/backend/internal/logic" - "fusenapi/server/backend/internal/svc" - "fusenapi/server/backend/internal/types" -) - -func QuotationDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var req types.RequestQuotationId - userinfo, err := basic.RequestParseBackend(w, r, svcCtx, &req) - if err != nil { - return - } - - // 创建一个业务逻辑层实例 - l := logic.NewQuotationDetailLogic(r.Context(), svcCtx) - - rl := reflect.ValueOf(l) - basic.BeforeLogic(w, r, rl) - - resp := l.QuotationDetail(&req, userinfo) - - if !basic.AfterLogic(w, r, rl, resp) { - basic.NormalAfterLogic(w, r, resp) - } - } -} diff --git a/server/backend/internal/handler/routes.go b/server/backend/internal/handler/routes.go deleted file mode 100644 index d875e035..00000000 --- a/server/backend/internal/handler/routes.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by goctl. DO NOT EDIT. -package handler - -import ( - "net/http" - - "fusenapi/server/backend/internal/svc" - - "github.com/zeromicro/go-zero/rest" -) - -func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { - server.AddRoutes( - []rest.Route{ - { - Method: http.MethodGet, - Path: "/api/quotation/detail", - Handler: QuotationDetailHandler(serverCtx), - }, - { - Method: http.MethodPost, - Path: "/api/backend-user/login", - Handler: BackendUserLoginHandler(serverCtx), - }, - }, - ) -} diff --git a/server/backend/internal/logic/backenduserloginlogic.go b/server/backend/internal/logic/backenduserloginlogic.go deleted file mode 100644 index 627ce09f..00000000 --- a/server/backend/internal/logic/backenduserloginlogic.go +++ /dev/null @@ -1,70 +0,0 @@ -package logic - -import ( - "errors" - "fusenapi/utils/auth" - "fusenapi/utils/basic" - "time" - - "context" - - "fusenapi/server/backend/internal/svc" - "fusenapi/server/backend/internal/types" - - "github.com/zeromicro/go-zero/core/logx" - "gorm.io/gorm" -) - -type BackendUserLoginLogic struct { - logx.Logger - ctx context.Context - svcCtx *svc.ServiceContext -} - -func NewBackendUserLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BackendUserLoginLogic { - return &BackendUserLoginLogic{ - Logger: logx.WithContext(ctx), - ctx: ctx, - svcCtx: svcCtx, - } -} - -func (l *BackendUserLoginLogic) BackendUserLogin(req *types.RequestUserLogin) (resp *basic.Response, jwtToken string) { - // 创建一个 FsUserModel 对象 m 并实例化之,该对象用于操作 MySQL 数据库中的用户数据表。 - m := l.svcCtx.AllModels.FsBackendUser - - // 在用户数据表中根据登录名(email)查找用户记录,并返回 UserModel 类型的结构体对象 userModel。 - user, err := m.FindUserByEmail(l.ctx, req.Name) - if errors.Is(err, gorm.ErrRecordNotFound) { - return resp.SetStatus(basic.CodeEmailNotFoundErr), "" - } - - // 如果在用户数据表中找到了登录名匹配的用户记录,则判断密码是否匹配。 - if *user.PasswordHash != req.Password { - logx.Info("密码错误") - return resp.SetStatus(basic.CodePasswordErr), jwtToken - } - - // 如果密码匹配,则生成 JWT Token。 - nowSec := time.Now().UTC().Unix() - jwtToken, err = auth.GenerateBackendJwtToken(&l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire, nowSec, user.Id, 0) - - // 如果生成 JWT Token 失败,则抛出错误并返回未认证的状态码。 - if err != nil { - logx.Error(err) - return resp.SetStatus(basic.CodeUnAuth), jwtToken - } - - // 如果更新 VerificationToken 字段失败,则返回未认证的状态码。 - if err != nil { - return resp.SetStatus(basic.CodeUnAuth), jwtToken - } - - // 构造 DataUserLogin 类型的数据对象 data 并设置其属性值为生成的 JWT Token。 - data := &types.DataUserLogin{ - Token: jwtToken, - } - - // 返回认证成功的状态码以及数据对象 data 和 JWT Token。 - return resp.SetStatus(basic.CodeOK, data), jwtToken -} diff --git a/server/backend/internal/logic/init.go b/server/backend/internal/logic/init.go deleted file mode 100644 index 04b6be7f..00000000 --- a/server/backend/internal/logic/init.go +++ /dev/null @@ -1,17 +0,0 @@ -package logic - -import ( - "os" - "regexp" -) - -var templatePath string - -func init() { - d, err := os.Getwd() - if err != nil { - panic(err) - } - - templatePath = regexp.MustCompile(".+fusenapi/server").FindString(d) + "/backend/template" -} diff --git a/server/backend/internal/logic/quotationdetaillogic.go b/server/backend/internal/logic/quotationdetaillogic.go deleted file mode 100644 index 5edcecd9..00000000 --- a/server/backend/internal/logic/quotationdetaillogic.go +++ /dev/null @@ -1,322 +0,0 @@ -package logic - -import ( - "bytes" - "encoding/json" - "fusenapi/model/gmodel" - "fusenapi/utils/auth" - "fusenapi/utils/basic" - "fusenapi/utils/collect" - "fusenapi/utils/format" - "log" - "strings" - "text/template" - - "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 { - logx.Logger - ctx context.Context - svcCtx *svc.ServiceContext -} - -func NewQuotationDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QuotationDetailLogic { - return &QuotationDetailLogic{ - Logger: logx.WithContext(ctx), - ctx: ctx, - svcCtx: svcCtx, - } -} - -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 -} - -// GetDemoHtml 报价单 -func (l *QuotationDetailLogic) GetDemoHtml(quot *gmodel.FsQuotation, quotationProduct []*gmodel.FsQuotationProduct) (htmlcontent string, err error) { - - // htmlContent := "" - priceHtml := "" - // productNum := len(quotationProduct) - // page := 3 - // pageTotal := 3 + productNum - - for _, quotProduct := range quotationProduct { - - var priceInfo []map[string]interface{} - err := json.Unmarshal([]byte(*quotProduct.PriceInfo), &priceInfo) - if err != nil { - return "", err - } - priceHtmlTpl := ` - {{range $i, $parr := .priceInfo}} - {{if lt $i 3}} -
-

${{$parr.price}}

-

{{$parr.num}} Units

-
- {{else}} -
-

${{$parr.price}}

-

{{$parr.num}} Units

-
- {{end}} - {{end}}` - - tpl := template.Must(template.New("prCardTpl").Parse(priceHtmlTpl)) - buf := &bytes.Buffer{} - err = tpl.Execute(buf, map[string]interface{}{ - "priceInfo": priceInfo, - }) - if err != nil { - log.Println(err) - return "", err - } - priceHtml = buf.String() - } - - tpl := template.New("quto") - tpl = tpl.Funcs(format.TemplateFuncMap) - - tpl = template.Must(tpl.ParseFiles(templatePath + "/products.tpl")) - buf := &bytes.Buffer{} - - tpl.Execute(buf, map[string]interface{}{ - "products": collect.StructSliceJson2Maps(quotationProduct), - "price_html": priceHtml, - }) - htmlContent := buf.String() - // log.Println(htmlContent) - return htmlContent, nil -} - -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) - } - - quotationProduct, 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 = quotationProduct - if len(quotationProduct) == 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(quotationProduct) > 0 - - //获取备注模板 - // markList, err := l.svcCtx.AllModels.FsQuotationRemarkTemplate.GetAllSelectContent(l.ctx) - - var productIds = collect.ArrayColumnTag[int64](CanteenProduct, "product_id") - productList, err := l.svcCtx.AllModels.FsProduct.FindAllOnlyByIds(l.ctx, productIds) - if err != nil { - logx.Error(err) - return resp.SetStatus(basic.CodeDbSqlErr) - } - productListMap := collect.Array2MapByKeyTag[int64](productList, "id") - - //获取size信息 - var sizeIds = collect.ArrayColumnTag[int64](CanteenProduct, "size_id") - sizes, err := l.svcCtx.AllModels.FsProductSize.GetAllSelectIdAndCapacityByIds(l.ctx, sizeIds) - if err != nil { - logx.Error(err) - return resp.SetStatus(basic.CodeDbSqlErr) - } - sizesMap := collect.Array2MapByKeyTag[int64](sizes, "id") - - //获取价格信息 - productPrice, err := l.svcCtx.AllModels.FsProductPrice.GetAllSelectBySizeId(l.ctx, sizeIds) - if err != nil { - logx.Error(err) - return resp.SetStatus(basic.CodeDbSqlErr) - } - productPriceMap := collect.Array2MapByKeyTag[int64](productPrice, "size_id") - // product := []map[string]interface{}{} - - products := []map[string]interface{}{} - for _, parr := range list.Array() { - - var priceList []map[string]int64 - - if !qFlag { - - if price, ok := productPriceMap[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() - } - - product := productListMap[parr.Get("product_id").Int()] - name = product.Title - size = sizesMap[parr.Get("size_id").Int()].Capacity - cycle = *product.ProduceDays + *product.DeliveryDays - img = "" - mark = []string{} - priceInfo = priceList - num = 1 - } - - products = append(products, 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, - }) - - } - - htmlContent, err := l.GetDemoHtml(", quotationProduct) - if err != nil { - panic(err) - } - log.Println(htmlContent) - - saler, err := l.svcCtx.AllModels.FsQuotationSaler.GetOne(l.ctx, quot.Id) - if err != nil { - logx.Error(err) - if err == gorm.ErrRecordNotFound { - return resp.SetStatus(basic.CodeDbRecordNotFoundErr) - } - return resp.SetStatus(basic.CodeDbSqlErr) - } - - // log.Println(saler) - - tpl := template.New("quto") - tpl = tpl.Funcs(format.TemplateFuncMap) - - tpl = template.Must(tpl.ParseFiles(templatePath + "/return_html.tpl")) - buf := &bytes.Buffer{} - - err = tpl.Execute(buf, map[string]interface{}{ - "demoHtml": htmlContent, - "qutoInfo": collect.StructJson2Map(quot), - "salerInfo": collect.StructJson2Map(saler), - }) - if err != nil { - return resp.SetStatus(basic.CodeApiErr) - } - // returnHtmlContent := buf.String() - - return resp.SetStatus(basic.CodeOK) -} diff --git a/server/backend/internal/svc/servicecontext.go b/server/backend/internal/svc/servicecontext.go deleted file mode 100644 index 49689eb0..00000000 --- a/server/backend/internal/svc/servicecontext.go +++ /dev/null @@ -1,62 +0,0 @@ -package svc - -import ( - "errors" - "fmt" - "fusenapi/server/backend/internal/config" - "fusenapi/shared" - "net/http" - "time" - - "fusenapi/initalize" - "fusenapi/model/gmodel" - - "github.com/golang-jwt/jwt" - "gorm.io/gorm" -) - -type ServiceContext struct { - Config config.Config - SharedState *shared.SharedState - - MysqlConn *gorm.DB - AllModels *gmodel.AllModelsGen -} - -func NewServiceContext(c config.Config) *ServiceContext { - db := initalize.InitMysql(c.SourceMysql).Set("gorm:slow_query_time", time.Second*15) - return &ServiceContext{ - Config: c, - MysqlConn: initalize.InitMysql(c.SourceMysql), - AllModels: gmodel.NewAllModels(db), - } -} - -func (svcCtx *ServiceContext) ParseJwtToken(r *http.Request) (jwt.MapClaims, error) { - AuthKey := r.Header.Get("Authorization") - - if len(AuthKey) <= 50 { - return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey))) - } - - AuthKey = AuthKey[7:] - - token, err := jwt.Parse(AuthKey, func(token *jwt.Token) (interface{}, error) { - // 检查签名方法是否为 HS256 - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) - } - // 返回用于验证签名的密钥 - return []byte(svcCtx.Config.Auth.AccessSecret), nil - }) - if err != nil { - return nil, errors.New(fmt.Sprint("Error parsing token:", err)) - } - - // 验证成功返回 - if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { - return claims, nil - } - - return nil, errors.New(fmt.Sprint("Invalid token", err)) -} diff --git a/server/backend/internal/types/types.go b/server/backend/internal/types/types.go deleted file mode 100644 index 97129408..00000000 --- a/server/backend/internal/types/types.go +++ /dev/null @@ -1,88 +0,0 @@ -// Code generated by goctl. DO NOT EDIT. -package types - -import ( - "fusenapi/utils/basic" -) - -type RequestQuotationId struct { - QuotationId int64 `form:"id"` -} - -type RequestUserLogin struct { - Name string `json:"name"` - Password string `json:"pwd"` -} - -type DataUserLogin struct { - Token string `json:"token"` // 登录jwt token -} - -type Request struct { -} - -type Response struct { - Code int `json:"code"` - Message string `json:"msg"` - Data interface{} `json:"data"` -} - -type Auth struct { - AccessSecret string `json:"accessSecret"` - AccessExpire int64 `json:"accessExpire"` - RefreshAfter int64 `json:"refreshAfter"` -} - -type File struct { - Filename string `fsfile:"filename"` - Header map[string][]string `fsfile:"header"` - Size int64 `fsfile:"size"` - Data []byte `fsfile:"data"` -} - -type Meta struct { - TotalCount int64 `json:"totalCount"` - PageCount int64 `json:"pageCount"` - CurrentPage int `json:"currentPage"` - PerPage int `json:"perPage"` -} - -// Set 设置Response的Code和Message值 -func (resp *Response) Set(Code int, Message string) *Response { - return &Response{ - Code: Code, - Message: Message, - } -} - -// Set 设置整个Response -func (resp *Response) SetWithData(Code int, Message string, Data interface{}) *Response { - return &Response{ - Code: Code, - Message: Message, - Data: Data, - } -} - -// SetStatus 设置默认StatusResponse(内部自定义) 默认msg, 可以带data, data只使用一个参数 -func (resp *Response) SetStatus(sr *basic.StatusResponse, data ...interface{}) *Response { - newResp := &Response{ - Code: sr.Code, - } - if len(data) == 1 { - newResp.Data = data[0] - } - return newResp -} - -// SetStatusWithMessage 设置默认StatusResponse(内部自定义) 非默认msg, 可以带data, data只使用一个参数 -func (resp *Response) SetStatusWithMessage(sr *basic.StatusResponse, msg string, data ...interface{}) *Response { - newResp := &Response{ - Code: sr.Code, - Message: msg, - } - if len(data) == 1 { - newResp.Data = data[0] - } - return newResp -} diff --git a/server/backend/template/products.tpl b/server/backend/template/products.tpl deleted file mode 100644 index 8ebb418a..00000000 --- a/server/backend/template/products.tpl +++ /dev/null @@ -1,129 +0,0 @@ -{{$product_num := len .products}} -{{$page := 3}} -{{$page_total := add $page $product_num}} -{{range $arr := .products}} -{{$price := json_decode $arr.price_info}} -{{$price_html := .priceHtml}} - -{{$price_html}} - -{{if gt $arr.is_gift 0 }}{{/* 赠品 */}} - -
-
-

{{$arr.name}}

-

{{$arr.size}}

- -
-
-
-
-
-
-

FREE!

-

{{$arr.num}} Units

-
-
-
Lead Time
-
- {{$arr.cycle}}Days -
-
- FREE Design -
-
- FREE Storage -
-
- FREE Shipping -
-
-
-
-{{else}}{{/* 非赠品 */}} -{{if $arr.size}} -// 有尺寸的 -
-
-

{{$arr.name}}

-

{{$arr.size}}

- -
-
-
-
-
-
Unit Price (Tax included)
-
- Lead Time
- {{$price_html}} -
-
- {{$arr.cycle}}Days -
-
- FREE Design -
-
- FREE Storage -
-
- FREE Shipping -
-
-
-
- -{{else}} -
-
-

- {{$arr.name}}

- -
-
-
-
-
-
-
- Unit Price (Tax included)
-
- Lead Time
- {{$price_html}} -
-
- {{$arr.cycle}}Days -
-
- FREE Design -
-
- FREE Storage -
-
- FREE Shipping -
-
-
-
-{{end}} -{{end}} -
{{$page}}/{{$page_total}}
-{{$page = add $page 1}} -{{end}} \ No newline at end of file diff --git a/server/backend/template/return_html.tpl b/server/backend/template/return_html.tpl deleted file mode 100644 index cf2433a4..00000000 --- a/server/backend/template/return_html.tpl +++ /dev/null @@ -1,371 +0,0 @@ -{{$html := .demoHtml}} -{{$saler := .salerInfo}} -{{$info := .qutoInfo}} - - - - - - - - quotation - - - - -
- -
-
-

- Custom - Packaging For

-

{{$info.canteen_name}}

- -
-
-
-
-
-
-

- Hi, I\'m - Victor from Fusenpack.

-

We - offer simple custom packaging solutions for restaurants with a minimum order quantity that\'s 5X - lower than regular suppliers. Check out our custom designs and prices on the following pages. - Contact me at if you have any questions. Thanks!

-
-
- -
-

- {{$saler.phone}}

-
-
-
- -
-

- {{$saler.email}}

-
-
-
- - - -
-
-

- Why Custom Packaging?

- -
-
-
- -
-
-
- - - - - - - - - - - - {{$html}} - -
-
- -
-
-
-
-

- There\'s more! If you don\'t see what you need on these pages, please contact us to inquire about - additional items.

-

{{$saler.name}}

-
-
- -
-

- {{$saler.phone}}

-
-
-
- -
-

- {{$saler.email}}

-
-
-
- Our Customers:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - -
- - \ No newline at end of file diff --git a/server/backend/test/basic.go b/server/backend/test/basic.go deleted file mode 100644 index 61923cf4..00000000 --- a/server/backend/test/basic.go +++ /dev/null @@ -1,43 +0,0 @@ -package backendtest - -import ( - "fmt" - - authtest "fusenapi/server/auth/test" - "fusenapi/server/backend/internal/config" - "fusenapi/server/backend/internal/handler" - "fusenapi/server/backend/internal/svc" - "fusenapi/utils/fstests" - "log" - "runtime" - - "github.com/zeromicro/go-zero/core/conf" - "github.com/zeromicro/go-zero/rest" -) - -var cnf config.Config -var userver, gserver *rest.Server - -func init() { - log.SetFlags(log.Llongfile) - userver = authtest.GetTestServer() - gserver = GetTestServer() -} - -func GetTestServer() *rest.Server { - - conf.MustLoad(fstests.GetEtcYamlPathAuto(), &cnf) - - server := rest.MustNewServer(cnf.RestConf) - runtime.SetFinalizer(server, func(server *rest.Server) { - if server != nil { - server.Stop() - } - }) - - ctx := svc.NewServiceContext(cnf) - handler.RegisterHandlers(server, ctx) - - fmt.Printf("Starting server at %s:%d...\n", cnf.Host, cnf.Port) - return server -} diff --git a/server/backend/test/quotationdetaillogic_test.go b/server/backend/test/quotationdetaillogic_test.go deleted file mode 100644 index 3b8b1a1d..00000000 --- a/server/backend/test/quotationdetaillogic_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package backendtest - -import ( - "fmt" - fstests "fusenapi/utils/fstests" - "log" - "testing" -) - -func TestCaseQuotationDetail(t *testing.T) { - ses := fstests.GetBackendSessionWithUserToken(t, gserver, cnf.Host, cnf.Port) - - // 构建新增地址请求体 - // addrReq := types.RequestQuotationId{ - // QuotationId: 1003, - // } - - // 向服务器发送 POST 请求,新增用户地址 - tp := ses.Get(fmt.Sprintf("http://%s:%d/api//quotation/detail", cnf.Host, cnf.Port)) - tp.QueryParam("id").Set(1003) - resp, err := tp.TestExecute(gserver) - log.Println(resp.Json()) - if err != nil { - t.Error(err) - return - } - - log.Println(resp.Json()) -} diff --git a/server/backend/test/tpl_test.go b/server/backend/test/tpl_test.go deleted file mode 100644 index 03ccdc82..00000000 --- a/server/backend/test/tpl_test.go +++ /dev/null @@ -1,314 +0,0 @@ -package backendtest - -import ( - "bytes" - "fusenapi/model/gmodel" - "fusenapi/utils/collect" - "fusenapi/utils/format" - "html/template" - "log" - "testing" -) - -func TestCaseTpl(t *testing.T) { - - priceInfo := []map[string]interface{}{ - {"Price": "$10", "Num": 100}, - {"Price": "$20", "Num": 200}, - {"Price": "$30", "Num": 300}, - {"Price": "$40", "Num": 400}, - } - - priceHtml := ` - {{range $i, $parr := .}} - {{if lt $i 3}} -
-

${{$parr.Price}}

-

{{$parr.Num}} Units

-
- {{else}} -
-

${{$parr.Price}}

-

{{$parr.Num}} Units

-
- {{end}} - {{end}}` - - tpl := template.Must(template.New("demoHtml").Parse(priceHtml)) - buf := bytes.NewBufferString("") - tpl.Execute(buf, priceInfo) - html := buf.String() - log.Println(html) -} - -func Randomproduct() []*gmodel.FsQuotationProduct { - var quotationId1 int64 = 1 - name1 := "T恤" - size1 := "S,M,L,XL,XXL" - var cycle1 int64 = 7 - var isGift1 int64 = 0 - img1 := "https://xxx.jpg" - var status1 int64 = 1 - var ctime1 int64 = 1623311101 - var sort1 int64 = 1 - sid1 := "abcd1234" - priceInfo1 := `[{"num":500,"price":0.1},{"num":1000,"price":0.06},{"num":1500,"price":0.06}]` - remark1 := "" - var num1 int64 = 100 - - var quotationId2 int64 = 1 - name2 := "帽子" - size2 := "通用" - var cycle2 int64 = 3 - var isGift2 int64 = 1 - img2 := "https://xxx.jpg" - var status2 int64 = 1 - var ctime2 int64 = 1623311102 - var sort2 int64 = 2 - sid2 := "abcd1235" - priceInfo2 := `[{"num":500,"price":0.1},{"num":1000,"price":0.06},{"num":1500,"price":0.06}]` - remark2 := "" - var num2 int64 = 50 - - var quotationId3 int64 = 2 - name3 := "水壶" - size3 := "350ml,500ml,650ml" - var cycle3 int64 = 14 - var isGift3 int64 = 0 - img3 := "https://xxx.jpg" - var status3 int64 = 1 - var ctime3 int64 = 1623311103 - var sort3 int64 = 1 - sid3 := "abcd1236" - priceInfo3 := `[{"num":500,"price":0.1},{"num":1000,"price":0.06},{"num":1500,"price":0.06}]` - remark3 := "" - var num3 int64 = 200 - - var quotationId4 int64 = 2 - name4 := "手机壳" - size4 := "iPhoneX,iPhoneXS,iPhoneXR" - var cycle4 int64 = 5 - var isGift4 int64 = 1 - img4 := "https://xxx.jpg" - var status4 int64 = 1 - var ctime4 int64 = 1623311104 - var sort4 int64 = 2 - sid4 := "abcd1237" - priceInfo4 := `[{"num":500,"price":0.1},{"num":1000,"price":0.06},{"num":1500,"price":0.06}]` - remark4 := "可定制颜料颜色" - var num4 int64 = 150 - - products := []*gmodel.FsQuotationProduct{ - &gmodel.FsQuotationProduct{ - Id: 1, - QuotationId: "ationId1, - Name: &name1, - Size: &size1, - Cycle: &cycle1, - IsGift: &isGift1, - Img: &img1, - Status: &status1, - Ctime: &ctime1, - Sort: &sort1, - Sid: &sid1, - PriceInfo: &priceInfo1, - Remark: &remark1, - Num: &num1, - }, - &gmodel.FsQuotationProduct{ - Id: 2, - QuotationId: "ationId2, - Name: &name2, - Size: &size2, - Cycle: &cycle2, - IsGift: &isGift2, - Img: &img2, - Status: &status2, - Ctime: &ctime2, - Sort: &sort2, - Sid: &sid2, - PriceInfo: &priceInfo2, - Remark: &remark2, - Num: &num2, - }, - &gmodel.FsQuotationProduct{ - Id: 3, - QuotationId: "ationId3, - Name: &name3, - Size: &size3, - Cycle: &cycle3, - IsGift: &isGift3, - Img: &img3, - Status: &status3, - Ctime: &ctime3, - Sort: &sort3, - Sid: &sid3, - PriceInfo: &priceInfo3, - Remark: &remark3, - Num: &num3, - }, - &gmodel.FsQuotationProduct{ - Id: 4, - QuotationId: "ationId4, - Name: &name4, - Size: &size4, - Cycle: &cycle4, - IsGift: &isGift4, - Img: &img4, - Status: &status4, - Ctime: &ctime4, - Sort: &sort4, - Sid: &sid4, - PriceInfo: &priceInfo4, - Remark: &remark4, - Num: &num4, - }, - } - - return products -} - -func TestTpl2(t *testing.T) { - - products := Randomproduct() - - tplcontent := ` - - {{$product_num := len .products}} - {{$page := 3}} - {{$page_total := add $page $product_num}} - {{range $arr := .products}} - {{$price := json_decode $arr.price_info}} - {{$price_html := .priceHtml}} - - {{$price_html}} - - {{if gt $arr.is_gift 0 }}{{/* 赠品 */}} - // 赠品 -
-
-

{{$arr.name}}

-

{{$arr.size}}

- -
-
-
-
-
-
-

FREE!

-

{{$arr.num}} Units

-
-
-
Lead Time
-
- {{$arr.cycle}}Days -
-
- FREE Design -
-
- FREE Storage -
-
- FREE Shipping -
-
-
-
- {{else}}{{/* 非赠品 */}} - {{if $arr.size}} - // 有尺寸的 -
-
-

{{$arr.name}}

-

{{$arr.size}}

- -
-
-
-
-
-
Unit Price (Tax included)
-
- Lead Time
- {{$price_html}} -
-
- {{$arr.cycle}}Days -
-
- FREE Design -
-
- FREE Storage -
-
- FREE Shipping -
-
-
-
- - {{else}} -
-
-

- {{$arr.name}}

- -
-
-
-
-
-
-
- Unit Price (Tax included)
-
- Lead Time
- {{$price_html}} -
-
- {{$arr.cycle}}Days -
-
- FREE Design -
-
- FREE Storage -
-
- FREE Shipping -
-
-
-
- {{end}} - {{end}} -
{{$page}}/{{$page_total}}
- {{$page = add $page 1}} - {{end}} ` - tpl := template.New("demo") - tpl.Funcs(format.TemplateFuncMap) - tpl = template.Must(tpl.Parse(tplcontent)) - buf := bytes.NewBufferString("") - - tpl.Execute(buf, map[string]interface{}{"products": collect.StructSliceJson2Maps(products)}) - html := buf.String() - log.Println(html) -} diff --git a/server_api/backend.api b/server_api/backend.api deleted file mode 100644 index 0c641827..00000000 --- a/server_api/backend.api +++ /dev/null @@ -1,34 +0,0 @@ -syntax = "v1" - -info ( - title: // TODO: add title - desc: // TODO: add description - author: "" - email: "" -) - -import "basic.api" - -service backend { - // 报价单详情 - @handler QuotationDetailHandler - get /api/quotation/detail(RequestQuotationId) returns (response); - - @handler BackendUserLoginHandler - post /api/backend-user/login(RequestUserLogin) returns (response); -} - -type RequestQuotationId { - QuotationId int64 `form:"id"` -} - -// BackendUserLoginHandler 用户登录请求结构 -type RequestUserLogin { - Name string `json:"name"` - Password string `json:"pwd"` -} - -// BackendUserLoginHandler 用户登录请求结构 -type DataUserLogin { - Token string `json:"token"` // 登录jwt token -} \ No newline at end of file diff --git a/utils/basic/request_parse.go b/utils/basic/request_parse.go index 3b8a474c..0cbcfc34 100644 --- a/utils/basic/request_parse.go +++ b/utils/basic/request_parse.go @@ -70,8 +70,11 @@ func ParseJwtToken(r *http.Request, svcCtx any) (*auth.UserInfo, error) { if info != nil { if info.IsUser() { // us, err := state.GetUserState(info.UserId) //获取缓存的用户状态 - reflect.ValueOf(svcCtx) - ctxValue := reflect.ValueOf(svcCtx).FieldByName("MysqlConn") + rsvcCtx := reflect.ValueOf(svcCtx) + if rsvcCtx.Kind() == reflect.Ptr { + rsvcCtx = rsvcCtx.Elem() + } + ctxValue := rsvcCtx.FieldByName("MysqlConn") gdb := ctxValue.Interface().(*gorm.DB) us, err := shared.GetUserState(info.UserId, gdb)