已完成用户APP首期功能开发
交付用户端首期页面、配套接口、后台资源及测试文档。用户APP构建、静态分析和三个管理后台构建通过;完整测试仍有2项失败,后端模型注释检查未通过,详见交付记录。
This commit is contained in:
99
backend/api/internal/logic/client/user/ticket_photo.go
Normal file
99
backend/api/internal/logic/client/user/ticket_photo.go
Normal file
@@ -0,0 +1,99 @@
|
||||
// 功能描述:报修现场照片关联与本人受保护读取;不公开照片文件目录。
|
||||
// 版本:1.0.0。
|
||||
package user
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
common "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/upload"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ticketPhotoRequest 记录添加时间,导入照片不冒充已验证的原始拍摄时间。
|
||||
type ticketPhotoRequest struct {
|
||||
URI string `json:"uri" binding:"required"`
|
||||
AddedAt time.Time `json:"added_at" binding:"required"`
|
||||
Source string `json:"source" binding:"required,oneof=camera gallery"`
|
||||
}
|
||||
|
||||
func UploadTicketPhoto(ctx *gin.Context) {
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
upload.UploadTicketPhoto(ctx, account.Identity)
|
||||
}
|
||||
|
||||
// UploadedTicketPhoto 恢复本人草稿照片,不接受其他账户或任意路径。
|
||||
func UploadedTicketPhoto(ctx *gin.Context) {
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
upload.ServeOwnedTicketPhoto(ctx, account.Identity, ctx.Param("name"))
|
||||
}
|
||||
|
||||
// saveTicketPhotos 与工单创建共用事务,任一图片不属于本人时全部回滚。
|
||||
func saveTicketPhotos(tx *gorm.DB, ticket models.CsTicket, owner string, photos []ticketPhotoRequest) error {
|
||||
seen := map[string]bool{}
|
||||
for index, photo := range photos {
|
||||
if seen[photo.URI] || !upload.OwnsTicketPhoto(owner, photo.URI) || photo.AddedAt.IsZero() || photo.AddedAt.After(time.Now().Add(5*time.Minute)) {
|
||||
return errcode.ErrInvalidArgument
|
||||
}
|
||||
seen[photo.URI] = true
|
||||
evidence := models.CsTicketEvidence{
|
||||
Entity: common.NewEntity(common.StatusEnable), CsTicketID: ticket.ID, EvidenceType: "reported", MediaType: "image", FileURI: photo.URI,
|
||||
CapturedAt: photo.AddedAt, ReceivedAt: time.Now(), Source: "user_" + photo.Source, IntegrityStatus: "capture_time_unknown", OperatorIdentity: owner,
|
||||
RequestNo: fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("user-photo:%s:%d", ticket.Identity, index)))),
|
||||
}
|
||||
if err := tx.Create(&evidence).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ticketPhotosForList 一次查询本人列表涉及的证据,只发布元数据与公开证据UUID。
|
||||
func ticketPhotosForList(tickets []models.CsTicket) (map[uint64][]gin.H, error) {
|
||||
result := map[uint64][]gin.H{}
|
||||
ids := make([]uint64, 0, len(tickets))
|
||||
for _, ticket := range tickets {
|
||||
ids = append(ids, ticket.ID)
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
var photos []models.CsTicketEvidence
|
||||
if err := impl.DBService.Where("cs_ticket_id IN ? AND evidence_type = ? AND status <> ?", ids, "reported", common.StatusArchived).Order("created_at asc").Find(&photos).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, photo := range photos {
|
||||
result[photo.CsTicketID] = append(result[photo.CsTicketID], gin.H{"identity": photo.Identity, "added_at": photo.CapturedAt, "source": photo.Source, "integrity_status": photo.IntegrityStatus})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// TicketPhoto 不允许借工单UUID读取其他工单照片,也不允许读取他人报修。
|
||||
func TicketPhoto(ctx *gin.Context) {
|
||||
account, ok := common.UserAccount(ctx)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var ticket models.CsTicket
|
||||
if impl.DBService.Where("identity = ? AND user_account_id = ? AND status <> ?", ctx.Param("identity"), account.ID, common.StatusArchived).First(&ticket).Error != nil {
|
||||
ctx.Status(404)
|
||||
return
|
||||
}
|
||||
var photo models.CsTicketEvidence
|
||||
if impl.DBService.Where("identity = ? AND cs_ticket_id = ? AND evidence_type = ? AND status <> ?", ctx.Param("photoIdentity"), ticket.ID, "reported", common.StatusArchived).First(&photo).Error != nil {
|
||||
ctx.Status(404)
|
||||
return
|
||||
}
|
||||
upload.ServeTicketPhoto(ctx, account.Identity, photo.FileURI)
|
||||
}
|
||||
Reference in New Issue
Block a user