package sandbox import ( "encoding/json" "errors" "fmt" "hongze/hz_eta_api/models" "hongze/hz_eta_api/models/company" "hongze/hz_eta_api/models/sandbox" "hongze/hz_eta_api/models/sandbox/request" "hongze/hz_eta_api/models/system" "hongze/hz_eta_api/utils" "strconv" "time" ) // AddSandbox 新增沙盘 func AddSandbox(req request.AddAndEditSandbox, opUserId int, opUserName string) (sandboxInfo *sandbox.Sandbox, err error) { // 获取产品权限详情 chartPermissionInfo, err := company.GetChartPermissionListById(req.ChartPermissionId) if err != nil { return } //沙盘主表信息 sandboxInfo = &sandbox.Sandbox{ Name: utils.TrimStr(req.Name), ChartPermissionId: req.ChartPermissionId, ChartPermissionName: chartPermissionInfo.PermissionName, CurrVersion: 1, Code: GenerateCode(), Content: req.Content, PicUrl: utils.TrimStr(req.PicUrl), OpUserId: opUserId, OpUserName: opUserName, IsDelete: 0, ModifyTime: time.Now(), CreateTime: time.Now(), } //沙盘版本表信息 sandboxVersionInfo := &sandbox.SandboxVersion{ Name: sandboxInfo.Name, ChartPermissionId: sandboxInfo.ChartPermissionId, ChartPermissionName: sandboxInfo.ChartPermissionName, CurrVersion: sandboxInfo.CurrVersion, Content: sandboxInfo.Content, PicUrl: sandboxInfo.PicUrl, OpUserId: sandboxInfo.OpUserId, OpUserName: sandboxInfo.OpUserName, VersionCode: GenerateVersionCode(sandboxInfo.SandboxId, sandboxInfo.CurrVersion), IsDelete: sandboxInfo.IsDelete, CreateTime: sandboxInfo.CreateTime, } //沙盘草稿表信息 sandboxDraftInfo := &sandbox.SandboxDraft{ Name: sandboxInfo.Name, ChartPermissionId: sandboxInfo.ChartPermissionId, ChartPermissionName: sandboxInfo.ChartPermissionName, CurrVersion: sandboxInfo.CurrVersion, Content: sandboxInfo.Content, OpUserId: sandboxInfo.OpUserId, OpUserName: sandboxInfo.OpUserName, CreateTime: sandboxInfo.CreateTime, } //新增沙盘 err = sandbox.AddNewSandbox(sandboxInfo, sandboxVersionInfo, sandboxDraftInfo) return } // UpdateSandbox 更新沙盘 func UpdateSandbox(req request.AddAndEditSandbox, opUserId int, opUserName string) (sandboxInfo *sandbox.Sandbox, err error, errMsg string) { // 获取沙盘版本信息 sandboxVersion, err := sandbox.GetSandboxVersionBySandboxVersionCode(req.SandboxVersionCode) if err != nil { if err.Error() == utils.ErrNoRow() { errMsg = "找不到该版本" err = errors.New(errMsg) } return } // 获取沙盘主表信息 sandboxInfo, err = sandbox.GetSandboxById(sandboxVersion.SandboxId) if err != nil { if err.Error() == utils.ErrNoRow() { errMsg = "找不到该沙盘" err = errors.New(errMsg) } return } //沙盘名称是否更改校验 var isUpdateName, isUpdateContent bool if sandboxInfo.Name != utils.TrimStr(req.Name) { isUpdateName = true } // 沙盘内容md5比对,不一致则代表有做更改 //if utils.MD5(sandboxInfo.Content) != utils.MD5(req.Content) { // isUpdateContent = true //} if checkoutContent(sandboxInfo.Content, req.Content) { isUpdateContent = true } //如果沙盘名称和沙盘内容都没有做过修改,那么就不做保存 if isUpdateName == false && isUpdateContent == false { return } // 获取产品权限详情 chartPermissionInfo, err := company.GetChartPermissionListById(req.ChartPermissionId) if err != nil { return } //如果只更新了沙盘名称,那么只去修改最新版本的沙盘名称,而不去累计版本 if isUpdateName == true && isUpdateContent == false { sandboxInfo.Name = utils.TrimStr(req.Name) sandboxInfo.ChartPermissionId = req.ChartPermissionId sandboxInfo.ChartPermissionName = chartPermissionInfo.PermissionName sandboxInfo.Content = req.Content sandboxInfo.PicUrl = utils.TrimStr(req.PicUrl) sandboxInfo.OpUserId = opUserId sandboxInfo.OpUserName = opUserName sandboxInfo.ModifyTime = time.Now() var updateSandboxColumn = []string{"Name", "ChartPermissionId", "ChartPermissionName", "PicUrl", "OpUserId", "OpUserName", "ModifyTime"} //沙盘版本表信息 sandboxVersionInfo, tmpErr := sandbox.GetSandboxVersionBySandbox2VersionId(sandboxInfo.SandboxId, sandboxInfo.CurrVersion) if tmpErr != nil { err = tmpErr return } sandboxVersionInfo.Name = sandboxInfo.Name sandboxVersionInfo.ChartPermissionId = sandboxInfo.ChartPermissionId sandboxVersionInfo.ChartPermissionName = sandboxInfo.ChartPermissionName sandboxVersionInfo.PicUrl = sandboxInfo.PicUrl sandboxVersionInfo.OpUserId = sandboxInfo.OpUserId sandboxVersionInfo.OpUserName = sandboxInfo.OpUserName var updateSandboxVersionColumn = []string{"Name", "ChartPermissionId", "ChartPermissionName", "PicUrl", "OpUserId", "OpUserName"} //沙盘草稿表信息 sandboxDraftInfo := &sandbox.SandboxDraft{ Name: sandboxInfo.Name, ChartPermissionId: sandboxInfo.ChartPermissionId, ChartPermissionName: sandboxInfo.ChartPermissionName, CurrVersion: sandboxInfo.CurrVersion, Content: sandboxInfo.Content, OpUserId: sandboxInfo.OpUserId, OpUserName: sandboxInfo.OpUserName, CreateTime: time.Now(), } //修改沙盘 err = sandbox.UpdateSandboxName(sandboxInfo, sandboxVersionInfo, sandboxDraftInfo, updateSandboxColumn, updateSandboxVersionColumn) } else { sandboxInfo.Name = utils.TrimStr(req.Name) sandboxInfo.ChartPermissionId = req.ChartPermissionId sandboxInfo.ChartPermissionName = chartPermissionInfo.PermissionName sandboxInfo.CurrVersion = sandboxInfo.CurrVersion + 1 sandboxInfo.Content = req.Content sandboxInfo.PicUrl = utils.TrimStr(req.PicUrl) sandboxInfo.OpUserId = opUserId sandboxInfo.OpUserName = opUserName sandboxInfo.ModifyTime = time.Now() var updateSandbox = []string{"Name", "ChartPermissionId", "ChartPermissionName", "CurrVersion", "Content", "PicUrl", "OpUserId", "OpUserName", "ModifyTime"} //沙盘版本表信息 sandboxVersionInfo := &sandbox.SandboxVersion{ Name: sandboxInfo.Name, ChartPermissionId: sandboxInfo.ChartPermissionId, ChartPermissionName: sandboxInfo.ChartPermissionName, CurrVersion: sandboxInfo.CurrVersion, Content: sandboxInfo.Content, SvgData: req.SvgData, PicUrl: sandboxInfo.PicUrl, OpUserId: sandboxInfo.OpUserId, OpUserName: sandboxInfo.OpUserName, VersionCode: GenerateVersionCode(sandboxInfo.SandboxId, sandboxInfo.CurrVersion), IsDelete: sandboxInfo.IsDelete, CreateTime: time.Now(), } //沙盘草稿表信息 sandboxDraftInfo := &sandbox.SandboxDraft{ Name: sandboxInfo.Name, ChartPermissionId: sandboxInfo.ChartPermissionId, ChartPermissionName: sandboxInfo.ChartPermissionName, CurrVersion: sandboxInfo.CurrVersion, Content: sandboxInfo.Content, OpUserId: sandboxInfo.OpUserId, OpUserName: sandboxInfo.OpUserName, CreateTime: time.Now(), } //修改沙盘 err = sandbox.UpdateSandbox(sandboxInfo, updateSandbox, sandboxVersionInfo, sandboxDraftInfo) } return } // AddSandboxDraft 新增沙盘草稿 func AddSandboxDraft(sandboxId int, req request.AddAndEditSandbox, opUserId int, opUserName string) (sandboxDraftInfo *sandbox.SandboxDraft, err error) { //获取最近一条草稿箱的数据 lastSandboxDraft, err := sandbox.GetLastSandboxDraftById(sandboxId) if err != nil && err.Error() != utils.ErrNoRow() { return } //如果最近一条沙盘草稿数据不为空的话,那么需要校验下最近一次的图表数据是否与提交的这次一致 if lastSandboxDraft != nil { //沙盘名称是否更改校验 var isUpdateName, isUpdateContent bool if lastSandboxDraft.Name != utils.TrimStr(req.Name) { isUpdateName = true } // 沙盘内容md5比对,不一致则代表有做更改 //if utils.MD5(lastSandboxDraft.Content) != utils.MD5(req.Content) { // isUpdateContent = true //} if checkoutContent(lastSandboxDraft.Content, req.Content) { isUpdateContent = true } //如果沙盘名称和沙盘内容都没有做过修改,那么就不做保存 if isUpdateName == false && isUpdateContent == false { return } } // 获取产品权限详情 chartPermissionInfo, err := company.GetChartPermissionListById(req.ChartPermissionId) if err != nil { return } //沙盘草稿表信息 sandboxDraftInfo = &sandbox.SandboxDraft{ SandboxId: sandboxId, Name: utils.TrimStr(req.Name), ChartPermissionId: req.ChartPermissionId, ChartPermissionName: chartPermissionInfo.PermissionName, Content: req.Content, OpUserId: opUserId, OpUserName: opUserName, CreateTime: time.Now(), } //新增沙盘草稿 err = sandbox.AddSandboxDraft(sandboxDraftInfo) return } // UpdateSandboxEditMark 更新沙盘当前更新状态 // status 枚举值 1:编辑中,0:完成编辑, 2:只做查询 func UpdateSandboxEditMark(sandboxId, nowUserId, status int, nowUserName string) (ret models.MarkReportResp, err error) { //更新标记key key := fmt.Sprint(`crm:sandbox:edit:`, sandboxId) opUserId, e := utils.Rc.RedisInt(key) var opUser models.MarkReportItem if e != nil { opUserInfoStr, tErr := utils.Rc.RedisString(key) if tErr == nil { tErr = json.Unmarshal([]byte(opUserInfoStr), &opUser) if tErr == nil { opUserId = opUser.AdminId } } } if opUserId > 0 && opUserId != nowUserId { editor := opUser.Editor if editor == "" { //查询账号的用户姓名 otherInfo, e := system.GetSysAdminById(opUserId) if e != nil { err = fmt.Errorf("查询其他编辑者信息失败") return } editor = otherInfo.RealName } ret.Status = 1 ret.Msg = fmt.Sprintf("当前%s正在编辑中", editor) ret.Editor = editor return } if status == 1 { nowUser := &models.MarkReportItem{AdminId: nowUserId, Editor: nowUserName} bt, e := json.Marshal(nowUser) if e != nil { err = fmt.Errorf("格式化编辑者信息失败") return } if opUserId > 0 { utils.Rc.Do("SETEX", key, int64(300), string(bt)) //3分钟缓存 } else { utils.Rc.SetNX(key, string(bt), time.Second*60*5) //3分钟缓存 } } else if status == 0 { //清除编辑缓存 _ = utils.Rc.Delete(key) } return } // ResetDraftToLastVersion 重置沙盘草稿至最新版本 func ResetDraftToLastVersion(sandboxId, opUserId int, opUserName string) (sandboxDraftInfo *sandbox.SandboxDraft, err error) { // 获取沙盘主表信息 sandboxInfo, err := sandbox.GetSandboxById(sandboxId) if err != nil { return } //沙盘草稿表信息 sandboxDraftInfo = &sandbox.SandboxDraft{ SandboxId: sandboxInfo.SandboxId, Name: sandboxInfo.Name, ChartPermissionId: sandboxInfo.ChartPermissionId, ChartPermissionName: sandboxInfo.ChartPermissionName, Content: sandboxInfo.Content, OpUserId: opUserId, OpUserName: opUserName, CreateTime: time.Now(), } //新增沙盘草稿 err = sandbox.AddSandboxDraft(sandboxDraftInfo) return } // DeleteSandbox 删除沙盘 func DeleteSandbox(sandboxId int) (err error) { // 获取沙盘主表信息 sandboxInfo, err := sandbox.GetSandboxById(sandboxId) if err != nil { return } sandboxInfo.IsDelete = 1 var updateSandboxColumn = []string{"IsDelete"} err = sandboxInfo.Update(updateSandboxColumn) return } // DeleteSandboxVersion 删除沙盘版本 func DeleteSandboxVersion(sandboxVersionCode string, opUserId int) (err error, errMsg string) { // 获取沙盘版本信息 sandboxVersion, err := sandbox.GetSandboxVersionBySandboxVersionCode(sandboxVersionCode) if err != nil { if err.Error() == utils.ErrNoRow() { errMsg = "找不到该版本" err = errors.New(errMsg) } return } /*key := fmt.Sprint(`crm:sandbox:edit:`, sandboxVersion.SandboxId) nowOpUserId, _ := utils.Rc.RedisInt(key) //如果当前有人操作,且获取当前操作人不是本人,那么不允许删除 if nowOpUserId > 0 && nowOpUserId != opUserId { errMsg = "当前有其他人正在编辑,不允许删除该沙盘" err = errors.New(errMsg) return }*/ markStatus, err := UpdateSandboxEditMark(sandboxVersion.SandboxId, opUserId, 2, "") if err != nil { errMsg = "查询标记状态失败" err = errors.New("查询标记状态失败,Err:" + err.Error()) return } if markStatus.Status == 1 { errMsg = fmt.Sprintf("当前%s正在编辑,不允许删除该沙盘", markStatus.Editor) err = errors.New(errMsg) return } // 获取沙盘主表信息 sandboxInfo, err := sandbox.GetSandboxById(sandboxVersion.SandboxId) if err != nil { return } // 删除最新版本,需要将上一个版本的给找出来覆盖 if sandboxVersion.CurrVersion == sandboxInfo.CurrVersion { lastSandboxVersion, tmpErr := sandbox.GetLastSandboxVersionBySandbox2VersionId(sandboxInfo.SandboxId, sandboxVersion.CurrVersion) if tmpErr != nil { // 如果找不到,说明是删除整个沙盘,不仅仅是某个版本 if tmpErr.Error() == utils.ErrNoRow() { sandboxInfo.IsDelete = 1 var updateSandboxColumn = []string{"IsDelete"} err = sandboxInfo.Update(updateSandboxColumn) return } err = tmpErr return } else { //将当前沙盘信息修复到上一个版本 sandboxInfo.Content = lastSandboxVersion.Content sandboxInfo.CurrVersion = lastSandboxVersion.CurrVersion sandboxInfo.PicUrl = lastSandboxVersion.PicUrl err = sandboxInfo.Update([]string{"Content", "CurrVersion", "PicUrl"}) if err != nil { return } } } //将原来的版本标记删除 sandboxVersion.IsDelete = 1 err = sandboxVersion.Update([]string{"IsDelete"}) return } // GetSandboxVersionDetailByCode 获取沙盘的版本数据 func GetSandboxVersionDetailByCode(sandboxVersionCode string) (sandboxVersionInfo *sandbox.SandboxVersion, err error) { // 获取沙盘版本信息 sandboxVersionInfo, err = sandbox.GetSandboxVersionBySandboxVersionCode(sandboxVersionCode) return } // GetLastSandboxInfo 获取最后一次操作的沙盘数据 func GetLastSandboxInfo(sandboxId int) (sandboxInfo *sandbox.Sandbox, err error) { // 获取沙盘主表信息 sandboxInfo, err = sandbox.GetSandboxById(sandboxId) return //if err != nil { // return //} // ////获取最近一条草稿箱的数据(写到一半没有保存,然后退出去了) //lastSandboxDraft, err := sandbox.GetLastSandboxDraftById(sandboxId) //if err != nil && err.Error() != utils.ErrNoRow() { // return //} ////如果最近一条沙盘草稿数据不为空的话,那么需要校验下最近一次的图表数据是否与提交的这次一致 //if lastSandboxDraft != nil { // sandboxInfo = &sandbox.Sandbox{ // SandboxId: sandboxId, // Name: lastSandboxDraft.Name, // ChartPermissionId: lastSandboxDraft.ChartPermissionId, // ChartPermissionName: lastSandboxDraft.ChartPermissionName, // CurrVersion: lastSandboxDraft.CurrVersion, // Content: lastSandboxDraft.Content, // OpUserId: lastSandboxDraft.OpUserId, // OpUserName: lastSandboxDraft.OpUserName, // IsDelete: 0, // ModifyTime: lastSandboxDraft.CreateTime, // CreateTime: lastSandboxDraft.CreateTime, // } //} return } // GenerateCode 生成沙盘code func GenerateCode() string { timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) return utils.MD5(fmt.Sprint("sandbox_") + timestamp) } // GenerateVersionCode 生成沙盘版本code func GenerateVersionCode(sandboxId, sandboxVersion int) string { timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) return utils.MD5(fmt.Sprint("sandbox_version_", sandboxId, "_", sandboxVersion) + timestamp) } // ContentStruct 沙盘内容结构体 type ContentStruct struct { Cells []struct { Attrs struct { Line struct { SourceMarker bool `json:"sourceMarker"` Stroke string `json:"stroke"` StrokeDasharray string `json:"strokeDasharray"` } `json:"line"` Rect struct { Fill string `json:"fill"` Stroke string `json:"stroke"` StrokeDasharray interface{} `json:"strokeDasharray"` StrokeWidth int64 `json:"strokeWidth"` } `json:"rect"` Text struct { Fill string `json:"fill"` FontSize float64 `json:"fontSize"` FontWeight string `json:"fontWeight"` LineHeight float64 `json:"lineHeight"` Text string `json:"text"` TextWrap struct { Text string `json:"text"` Width int64 `json:"width"` } `json:"textWrap"` } `json:"text"` } `json:"attrs"` Data struct { Key string `json:"key"` } `json:"data"` ID string `json:"id"` Ports struct { Groups struct { Port_bottom struct { Attrs struct { Circle struct { Fill string `json:"fill"` Magnet bool `json:"magnet"` R int64 `json:"r"` Stroke string `json:"stroke"` StrokeWidth int64 `json:"strokeWidth"` } `json:"circle"` } `json:"attrs"` Position string `json:"position"` ZIndex int64 `json:"zIndex"` } `json:"port-bottom"` Port_left struct { Attrs struct { Circle struct { Fill string `json:"fill"` Magnet bool `json:"magnet"` R int64 `json:"r"` Stroke string `json:"stroke"` StrokeWidth int64 `json:"strokeWidth"` } `json:"circle"` } `json:"attrs"` Position string `json:"position"` ZIndex int64 `json:"zIndex"` } `json:"port-left"` Port_right struct { Attrs struct { Circle struct { Fill string `json:"fill"` Magnet bool `json:"magnet"` R int64 `json:"r"` Stroke string `json:"stroke"` StrokeWidth int64 `json:"strokeWidth"` } `json:"circle"` } `json:"attrs"` Position string `json:"position"` ZIndex int64 `json:"zIndex"` } `json:"port-right"` Port_top struct { Attrs struct { Circle struct { Fill string `json:"fill"` Magnet bool `json:"magnet"` R int64 `json:"r"` Stroke string `json:"stroke"` StrokeWidth int64 `json:"strokeWidth"` } `json:"circle"` } `json:"attrs"` Position string `json:"position"` ZIndex int64 `json:"zIndex"` } `json:"port-top"` } `json:"groups"` Items []struct { Group string `json:"group"` ID string `json:"id"` } `json:"items"` } `json:"ports"` Position struct { X float64 `json:"x"` Y float64 `json:"y"` } `json:"position"` Shape string `json:"shape"` Size struct { Height float64 `json:"height"` Width float64 `json:"width"` } `json:"size"` Source struct { Cell string `json:"cell"` Port string `json:"port"` } `json:"source"` Target struct { Cell string `json:"cell"` Port string `json:"port"` } `json:"target"` ZIndex int64 `json:"zIndex"` } `json:"cells"` } // checkoutContent 校验内容是否变更 func checkoutContent(oldContent, reqContent string) (isUpdate bool) { defer func() { // 沙盘内容md5比对,不一致则代表有做更改 if utils.MD5(oldContent) != utils.MD5(reqContent) { isUpdate = true } }() var oldContentInfo, reqContentInfo ContentStruct err := json.Unmarshal([]byte(oldContent), &oldContentInfo) if err != nil { fmt.Println("old json.Unmarshal err:", err) return } oldContentInfoByte, err := json.Marshal(oldContentInfo) if err != nil { fmt.Println("old json.Marshal err:", err) return } oldContent = string(oldContentInfoByte) err = json.Unmarshal([]byte(reqContent), &reqContentInfo) if err != nil { fmt.Println("req json.Unmarshal err:", err) return } reqContentInfoByte, err := json.Marshal(reqContentInfo) if err != nil { fmt.Println("req json.Marshal err:", err) return } reqContent = string(reqContentInfoByte) return }