diff --git a/model/gmodel/fs_map_library_logic.go b/model/gmodel/fs_map_library_logic.go index df7755bd..1248011a 100755 --- a/model/gmodel/fs_map_library_logic.go +++ b/model/gmodel/fs_map_library_logic.go @@ -2,10 +2,26 @@ package gmodel import "context" -func (ml *FsMapLibraryModel) GetAllEnabledList(ctx context.Context) (resp []FsMapLibrary, err error) { - err = ml.db.WithContext(ctx).Model(&FsMapLibrary{}).Where("`status` = ?", 0).Find(&resp).Error +func (ml *FsMapLibraryModel) GetAllEnabledList(ctx context.Context, fields string) (resp []FsMapLibrary, err error) { + db := ml.db.WithContext(ctx).Model(&FsMapLibrary{}).Where("`status` = ?", 0) + if fields != "" { + db = db.Select(fields) + } + err = db.Find(&resp).Error if err != nil { return nil, err } return } +func (ml *FsMapLibraryModel) Create(ctx context.Context, data *FsMapLibrary) error { + return ml.db.WithContext(ctx).Create(data).Error +} +func (ml *FsMapLibraryModel) Update(ctx context.Context, id int64, data *FsMapLibrary) error { + return ml.db.WithContext(ctx).Where("`id` = ? ", id).Updates(data).Error +} +func (ml *FsMapLibraryModel) ChangeStatusByIds(ctx context.Context, ids []int64, status int64) error { + if len(ids) == 0 { + return nil + } + return ml.db.WithContext(ctx).Where("`id` in (?) ", ids).Update("status", 0).Error +} diff --git a/server/map-library/internal/handler/routes.go b/server/map-library/internal/handler/routes.go index c45b9beb..b5128ec5 100644 --- a/server/map-library/internal/handler/routes.go +++ b/server/map-library/internal/handler/routes.go @@ -17,6 +17,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/map-library/list", Handler: GetMapLibraryListHandler(serverCtx), }, + { + Method: http.MethodPost, + Path: "/map-library/save", + Handler: SaveMapLibraryHandler(serverCtx), + }, }, ) } diff --git a/server/map-library/internal/handler/savemaplibraryhandler.go b/server/map-library/internal/handler/savemaplibraryhandler.go new file mode 100644 index 00000000..7f927456 --- /dev/null +++ b/server/map-library/internal/handler/savemaplibraryhandler.go @@ -0,0 +1,78 @@ +package handler + +import ( + "errors" + "net/http" + + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/rest/httpx" + + "fusenapi/utils/auth" + "fusenapi/utils/basic" + + "fusenapi/server/map-library/internal/logic" + "fusenapi/server/map-library/internal/svc" + "fusenapi/server/map-library/internal/types" +) + +func SaveMapLibraryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + + var ( + // 定义错误变量 + err error + // 定义用户信息变量 + userinfo *auth.UserInfo + ) + // 解析JWT token,并对空用户进行判断 + claims, err := svcCtx.ParseJwtToken(r) + // 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息 + if err != nil { + httpx.OkJsonCtx(r.Context(), w, &basic.Response{ + Code: 401, // 返回401状态码,表示未授权 + Message: "unauthorized", // 返回未授权信息 + }) + logx.Info("unauthorized:", err.Error()) // 记录错误日志 + return + } + + if claims != nil { + // 从token中获取对应的用户信息 + userinfo, err = auth.GetUserInfoFormMapClaims(claims) + // 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息 + if err != nil { + httpx.OkJsonCtx(r.Context(), w, &basic.Response{ + Code: 401, + Message: "unauthorized", + }) + logx.Info("unauthorized:", err.Error()) + return + } + } else { + // 如果claims为nil,则认为用户身份为白板用户 + userinfo = &auth.UserInfo{UserId: 0, GuestId: 0} + } + + var req types.SaveMapLibraryReq + // 如果端点有请求结构体,则使用httpx.Parse方法从HTTP请求体中解析请求数据 + if err := httpx.Parse(r, &req); err != nil { + httpx.OkJsonCtx(r.Context(), w, &basic.Response{ + Code: 510, + Message: "parameter error", + }) + logx.Info(err) + return + } + // 创建一个业务逻辑层实例 + l := logic.NewSaveMapLibraryLogic(r.Context(), svcCtx) + resp := l.SaveMapLibrary(&req, userinfo) + // 如果响应不为nil,则使用httpx.OkJsonCtx方法返回JSON响应; + 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/map-library/internal/logic/getmaplibrarylistlogic.go b/server/map-library/internal/logic/getmaplibrarylistlogic.go index 97eb8193..f5b5662c 100644 --- a/server/map-library/internal/logic/getmaplibrarylistlogic.go +++ b/server/map-library/internal/logic/getmaplibrarylistlogic.go @@ -1,6 +1,7 @@ package logic import ( + "encoding/json" "fusenapi/model/gmodel" "fusenapi/server/map-library/internal/svc" "fusenapi/server/map-library/internal/types" @@ -31,7 +32,7 @@ func (l *GetMapLibraryListLogic) GetMapLibraryList(userinfo *auth.UserInfo) (res return resp.SetStatusWithMessage(basic.CodeServiceErr, "please login first") } mapLibraryModel := gmodel.NewFsMapLibraryModel(l.svcCtx.MysqlConn) - mapLibraryList, err := mapLibraryModel.GetAllEnabledList(l.ctx) + mapLibraryList, err := mapLibraryModel.GetAllEnabledList(l.ctx, "") if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get map library list") @@ -59,7 +60,6 @@ func (l *GetMapLibraryListLogic) GetMapLibraryList(userinfo *auth.UserInfo) (res data := types.GetMapLibraryListRsp{ Mid: v.Id, Ctime: time.Unix(*v.Ctime, 0).Format("2006-01-02 15:04:05"), - Info: *v.Info, } //tag拼装 if tagIndex, ok := mapTag[*v.TagId]; ok { @@ -68,6 +68,13 @@ func (l *GetMapLibraryListLogic) GetMapLibraryList(userinfo *auth.UserInfo) (res Title: *templateTagList[tagIndex].Title, } } + //解析info + var info types.Info + if err = json.Unmarshal([]byte(*v.Info), &info); err != nil { + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeServiceErr, "json parse info err") + } + data.Info = info list = append(list, data) } return resp.SetStatusWithMessage(basic.CodeOK, "success", list) diff --git a/server/map-library/internal/logic/savemaplibrarylogic.go b/server/map-library/internal/logic/savemaplibrarylogic.go new file mode 100644 index 00000000..e5fb70f0 --- /dev/null +++ b/server/map-library/internal/logic/savemaplibrarylogic.go @@ -0,0 +1,98 @@ +package logic + +import ( + "context" + "encoding/json" + "fusenapi/model/gmodel" + "fusenapi/utils/auth" + "fusenapi/utils/basic" + "gorm.io/gorm" + "strconv" + "time" + + "fusenapi/server/map-library/internal/svc" + "fusenapi/server/map-library/internal/types" + + "github.com/zeromicro/go-zero/core/logx" +) + +type SaveMapLibraryLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewSaveMapLibraryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SaveMapLibraryLogic { + return &SaveMapLibraryLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *SaveMapLibraryLogic) SaveMapLibrary(req *types.SaveMapLibraryReq, userinfo *auth.UserInfo) (resp *basic.Response) { + if userinfo.GetIdType() != auth.IDTYPE_User { + return resp.SetStatusWithMessage(basic.CodeServiceErr, "please login first") + } + //获取所有贴图数据[获取id] + mapLibraryModel := gmodel.NewFsMapLibraryModel(l.svcCtx.MysqlConn) + maplibraryList, err := mapLibraryModel.GetAllEnabledList(l.ctx, "`id`") + if err != nil { + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get map library list") + } + + sort := int64(0) + status := int64(1) + now := time.Now().Unix() + needDeleteMid := make([]int64, 0, len(req.Data)) + mapPostMid := make(map[int64]struct{}) + //开启事务 + err = l.svcCtx.MysqlConn.Transaction(func(tx *gorm.DB) error { + for _, v := range req.Data { + infoByte, _ := json.Marshal(v.Info) + infoJsonStr := string(infoByte) + switch v.Mid { + case "": //新增 + err = mapLibraryModel.Create(l.ctx, &gmodel.FsMapLibrary{ + Title: &v.Info.Title, + Info: &infoJsonStr, + Sort: &sort, + Status: &status, + Ctime: &now, + TagId: &v.Tag.Id, + }) + if err != nil { + return err + } + default: //修改 + midInt, err := strconv.ParseInt(v.Mid, 10, 64) + if err != nil { + return err + } + mapPostMid[midInt] = struct{}{} + err = mapLibraryModel.Update(l.ctx, midInt, &gmodel.FsMapLibrary{ + Title: &v.Info.Title, + Info: &infoJsonStr, + TagId: &v.Tag.Id, + }) + if err != nil { + return err + } + } + } + //删除需要删除的 + for _, v := range maplibraryList { + //旧的不在新的里面则删除 + if _, ok := mapPostMid[v.Id]; !ok { + needDeleteMid = append(needDeleteMid, v.Id) + } + } + return mapLibraryModel.ChangeStatusByIds(l.ctx, needDeleteMid, 0) + }) + if err != nil { + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeSaveErr, "failed to save map library info") + } + return resp.SetStatusWithMessage(basic.CodeOK, "success") +} diff --git a/server/map-library/internal/types/types.go b/server/map-library/internal/types/types.go index 6ea4f440..ca2138d1 100644 --- a/server/map-library/internal/types/types.go +++ b/server/map-library/internal/types/types.go @@ -9,7 +9,7 @@ type GetMapLibraryListRsp struct { Mid int64 `json:"mid"` Ctime string `json:"ctime"` Tag MapLibraryListTag `json:"tag"` - Info string `json:"info"` + Info Info `json:"info"` } type MapLibraryListTag struct { @@ -17,6 +17,80 @@ type MapLibraryListTag struct { Title string `json:"title"` } +type SaveMapLibraryReq struct { + Data []SaveMapLibraryData `json:"-"` +} + +type SaveMapLibraryData struct { + Mid string `json:"mid"` + Tid string `json:"tid"` + Ctime string `json:"ctime"` + Tag Tag `json:"tag"` + Info Info `json:"info"` +} + +type Tag struct { + Id int64 `json:"id"` + Title string `json:"title"` +} + +type Info struct { + Id string `json:"id"` + Tag string `json:"tag"` + Title string `json:"title"` + Type string `json:"type"` + Text string `json:"text"` + Fill string `json:"fill"` + FontSize int64 `json:"fontSize"` + FontFamily string `json:"fontFamily"` + IfBr bool `json:"ifBr"` + IfShow bool `json:"ifShow"` + IfGroup bool `json:"ifGroup"` + MaxNum int64 `json:"maxNum"` + Rotation int64 `json:"rotation"` + Align string `json:"align"` + VerticalAlign string `json:"verticalAlign"` + Material string `json:"material"` + Width float64 `json:"width"` + Height float64 `json:"height"` + X float64 `json:"x"` + Y float64 `json:"Y"` + Opacity float64 `json:"opacity"` + OptionalColor []OptionalColor `json:"optionalColor"` + ZIndex int64 `json:"zIndex"` + SvgPath string `json:"svgPath"` + Follow Follow `json:"follow"` + Group []Group `json:"group"` + CameraStand CameraStand `json:"cameraStand"` +} + +type Group struct { + Tag string `json:"tag"` + Text string `json:"text"` + Title string `json:"title"` + IfBr bool `json:"ifBr"` + IfShow bool `json:"ifShow"` + MaxNum int64 `json:"maxNum"` +} + +type OptionalColor struct { + OptionalColor string `json:"color"` + Name string `json:"name"` + Default bool `json:"default"` +} + +type Follow struct { + Fill string `json:"fill"` + IfShow string `json:"ifShow"` + Content string `json:"content"` +} + +type CameraStand struct { + X int64 `json:"x"` + Y int64 `json:"y"` + Z int64 `json:"z"` +} + type Response struct { Code int `json:"code"` Message string `json:"msg"` diff --git a/server_api/map-library.api b/server_api/map-library.api index d182e68c..a6d4e8cc 100644 --- a/server_api/map-library.api +++ b/server_api/map-library.api @@ -12,6 +12,9 @@ service map-library { //获取贴图库列表 @handler GetMapLibraryListHandler get /map-library/list ( ) returns (response); + //保存贴图信息 + @handler SaveMapLibraryHandler + post /map-library/save (SaveMapLibraryReq) returns (response); } //获取贴图库列表 @@ -19,9 +22,78 @@ type GetMapLibraryListRsp { Mid int64 `json:"mid"` Ctime string `json:"ctime"` Tag MapLibraryListTag `json:"tag"` - Info string `json:"info"` + Info Info `json:"info"` } type MapLibraryListTag { Id int64 `json:"id"` Title string `json:"title"` +} + +//保存贴图信息 +type SaveMapLibraryReq { + Data []SaveMapLibraryData `json:"-"` +} +type SaveMapLibraryData { + Mid string `json:"mid"` + Tid string `json:"tid"` + Ctime string `json:"ctime"` + Tag Tag `json:"tag"` + Info Info `json:"info"` +} + +type Tag { + Id int64 `json:"id"` + Title string `json:"title"` +} +type Info { + Id string `json:"id"` + Tag string `json:"tag"` + Title string `json:"title"` + Type string `json:"type"` + Text string `json:"text"` + Fill string `json:"fill"` + FontSize int64 `json:"fontSize"` + FontFamily string `json:"fontFamily"` + IfBr bool `json:"ifBr"` + IfShow bool `json:"ifShow"` + IfGroup bool `json:"ifGroup"` + MaxNum int64 `json:"maxNum"` + Rotation int64 `json:"rotation"` + Align string `json:"align"` + VerticalAlign string `json:"verticalAlign"` + Material string `json:"material"` + Width float64 `json:"width"` + Height float64 `json:"height"` + X float64 `json:"x"` + Y float64 `json:"Y"` + Opacity float64 `json:"opacity"` + OptionalColor []OptionalColor `json:"optionalColor"` + ZIndex int64 `json:"zIndex"` + SvgPath string `json:"svgPath"` + Follow Follow `json:"follow"` + Group []Group `json:"group"` + CameraStand CameraStand `json:"cameraStand"` +} +type Group { + Tag string `json:"tag"` + Text string `json:"text"` + Title string `json:"title"` + IfBr bool `json:"ifBr"` + IfShow bool `json:"ifShow"` + MaxNum int64 `json:"maxNum"` +} +type OptionalColor { + OptionalColor string `json:"color"` + Name string `json:"name"` + Default bool `json:"default"` +} +type Follow { + Fill string `json:"fill"` + IfShow string `json:"ifShow"` + Content string `json:"content"` +} +type CameraStand { + X int64 `json:"x"` + Y int64 `json:"y"` + Z int64 `json:"z"` } \ No newline at end of file