低空智控平台 后端go
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

190 lines
5.2 KiB

package service
import (
"errors"
"time"
"gorm.io/gorm"
"laic-backend/common"
"laic-backend/logger"
"laic-backend/model"
"laic-backend/tool"
"laic-backend/vo"
)
type RouteService struct{}
var DefaultRouteService = &RouteService{}
// GetPage 航线分页列表
func (s *RouteService) GetPage(userID int64, isAdmin bool, req *vo.RoutePageReq) (*common.PageResponse[model.Route], *common.BusiError) {
db := common.DB.Model(&model.Route{}).Scopes(withUserFilter(userID, isAdmin))
if req.Keyword != "" {
kw := "%" + req.Keyword + "%"
db = db.Where("name LIKE ? OR description LIKE ?", kw, kw)
}
var total int64
if err := db.Count(&total).Error; err != nil {
logger.ERROR("统计航线失败", err)
return nil, common.ErrInternal
}
var list []model.Route
if err := db.Scopes(req.Paginate).Order("id DESC").Find(&list).Error; err != nil {
logger.ERROR("查询航线列表失败", err)
return nil, common.ErrInternal
}
return common.Page(req.Pagination, total, list), nil
}
// GetDetail 航线详情(含航点)
func (s *RouteService) GetDetail(userID int64, isAdmin bool, id int64) (*vo.RouteVO, *common.BusiError) {
var route model.Route
if err := common.DB.Scopes(withUserFilter(userID, isAdmin)).First(&route, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, common.ErrRouteNotFound
}
return nil, common.ErrInternal
}
waypoints, err := s.waypoints(id)
if err != nil {
logger.ERROR("查询航点失败", err)
return nil, common.ErrInternal
}
return &vo.RouteVO{Route: &route, Waypoints: waypoints}, nil
}
// Create 新增航线(含航点)
func (s *RouteService) Create(userID int64, req *vo.RouteCreateReq) (*vo.RouteVO, *common.BusiError) {
id, err := tool.NextID()
if err != nil {
return nil, common.ErrInternal
}
now := time.Now()
route := &model.Route{
ID: id,
UserID: userID,
Name: req.Name,
Description: req.Description,
CreatedAt: now,
UpdatedAt: now,
}
waypoints, err := buildWaypoints(id, req.Waypoints)
if err != nil {
return nil, common.ErrInternal
}
err = common.DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(route).Error; err != nil {
return err
}
if len(waypoints) > 0 {
return tx.Create(&waypoints).Error
}
return nil
})
if err != nil {
logger.ERROR("新增航线失败", err)
return nil, common.ErrInternal
}
return &vo.RouteVO{Route: route, Waypoints: waypoints}, nil
}
// Update 编辑航线(提供 waypoints 则整体替换航点)
func (s *RouteService) Update(userID int64, isAdmin bool, id int64, req *vo.RouteUpdateReq) (*vo.RouteVO, *common.BusiError) {
var route model.Route
if err := common.DB.Scopes(withUserFilter(userID, isAdmin)).First(&route, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, common.ErrRouteNotFound
}
return nil, common.ErrInternal
}
err := common.DB.Transaction(func(tx *gorm.DB) error {
updates := map[string]any{"updated_at": time.Now()}
if req.Name != "" {
updates["name"] = req.Name
}
if req.Description != "" {
updates["description"] = req.Description
}
if err := tx.Model(&route).Updates(updates).Error; err != nil {
return err
}
if req.Waypoints != nil {
if err := tx.Where("route_id = ?", id).Delete(&model.RouteWaypoint{}).Error; err != nil {
return err
}
waypoints, err := buildWaypoints(id, *req.Waypoints)
if err != nil {
return err
}
if len(waypoints) > 0 {
return tx.Create(&waypoints).Error
}
}
return nil
})
if err != nil {
logger.ERROR("更新航线失败", err)
return nil, common.ErrInternal
}
common.DB.First(&route, id)
waypoints, _ := s.waypoints(id)
return &vo.RouteVO{Route: &route, Waypoints: waypoints}, nil
}
// Delete 删除航线(含航点)
func (s *RouteService) Delete(userID int64, isAdmin bool, id int64) *common.BusiError {
err := common.DB.Transaction(func(tx *gorm.DB) error {
res := tx.Scopes(withUserFilter(userID, isAdmin)).Delete(&model.Route{}, id)
if res.Error != nil {
return res.Error
}
if res.RowsAffected == 0 {
return gorm.ErrRecordNotFound
}
return tx.Where("route_id = ?", id).Delete(&model.RouteWaypoint{}).Error
})
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return common.ErrRouteNotFound
}
logger.ERROR("删除航线失败", err)
return common.ErrInternal
}
return nil
}
func (s *RouteService) waypoints(routeID int64) ([]model.RouteWaypoint, error) {
var waypoints []model.RouteWaypoint
err := common.DB.Where("route_id = ?", routeID).Order("seq ASC").Find(&waypoints).Error
return waypoints, err
}
// buildWaypoints 将航点请求转换为模型,Seq 从 1 递增
func buildWaypoints(routeID int64, reqs []vo.RouteWaypointReq) ([]model.RouteWaypoint, error) {
out := make([]model.RouteWaypoint, 0, len(reqs))
now := time.Now()
for i, w := range reqs {
id, err := tool.NextID()
if err != nil {
return nil, err
}
out = append(out, model.RouteWaypoint{
ID: id,
RouteID: routeID,
Seq: i + 1,
Longitude: w.Longitude,
Latitude: w.Latitude,
Altitude: w.Altitude,
Speed: w.Speed,
Yaw: w.Yaw,
HoldSec: w.HoldSec,
CreatedAt: now,
})
}
return out, nil
}