已完成用户APP首期功能开发

交付用户端首期页面、配套接口、后台资源及测试文档。用户APP构建、静态分析和三个管理后台构建通过;完整测试仍有2项失败,后端模型注释检查未通过,详见交付记录。
This commit is contained in:
czl231
2026-09-13 00:57:32 +08:00
parent a0a4bb1218
commit 3ef33b531d
793 changed files with 40959 additions and 1204 deletions

View File

@@ -0,0 +1,121 @@
// 功能描述:向用户本人提供隐私化配送轨迹与履约时间线;版本:1.0.0。
package user
import (
"math"
"strconv"
"git.apinb.com/bsm-sdk/core/infra"
"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/models"
"github.com/gin-gonic/gin"
)
// GetGasOrderDeliveryTrack 先限定本人订单,再将定位点约化到约百米精度后下发。
func GetGasOrderDeliveryTrack(ctx *gin.Context) {
account, ok := common.UserAccount(ctx)
if !ok {
return
}
var order models.GasorderBasic
if err := impl.DBService.Where("identity = ? AND user_account_id = ? AND status <> ?", ctx.Param("identity"), account.ID, common.StatusArchived).First(&order).Error; err != nil {
gasDetailError(ctx, err)
return
}
var station models.GasBasic
if order.GasBasicID != 0 {
if err := impl.DBService.Where("id = ? AND status = ?", order.GasBasicID, common.StatusEnable).Find(&station).Error; err != nil {
gasDetailError(ctx, err)
return
}
}
var staff models.StaffAccount
if order.StaffAccountID != 0 {
if err := impl.DBService.Where("id = ? AND role_code = ? AND status = ?", order.StaffAccountID, "delivery", common.StatusEnable).Find(&staff).Error; err != nil {
gasDetailError(ctx, err)
return
}
}
var track models.GasorderTrack
if err := impl.DBService.Where("gasorder_basic_id = ? AND status <> ?", order.ID, common.StatusArchived).Order("attempt_no desc, id desc").Limit(1).Find(&track).Error; err != nil {
gasDetailError(ctx, err)
return
}
var points []models.GasorderTrackPoint
if track.ID != 0 {
if err := impl.DBService.Where("gasorder_track_id = ? AND status = ?", track.ID, common.StatusEnable).Order("occurred_at asc, id asc").Limit(200).Find(&points).Error; err != nil {
gasDetailError(ctx, err)
return
}
}
var histories []models.GasorderStatus
if err := impl.DBService.Where("gasorder_basic_id = ? AND status <> ?", order.ID, common.StatusArchived).Order("occurred_at asc, id asc").Find(&histories).Error; err != nil {
gasDetailError(ctx, err)
return
}
publicPoints := make([]gin.H, 0, len(points))
for _, point := range points {
longitude, longitudeOK := approximateCoordinate(point.Longitude, -180, 180)
latitude, latitudeOK := approximateCoordinate(point.Latitude, -90, 90)
if longitudeOK && latitudeOK {
publicPoints = append(publicPoints, gin.H{"longitude": longitude, "latitude": latitude, "occurred_at": point.OccurredAt})
}
}
publicTimeline := make([]gin.H, 0, len(histories))
for _, history := range histories {
if title, detail, visible := deliveryTimelineText(history.ToStatus, station.Name); visible {
publicTimeline = append(publicTimeline, gin.H{
"status_code": history.ToStatus, "title": title, "detail": detail, "occurred_at": history.OccurredAt,
})
}
}
destinationLongitude, destinationLongitudeOK := approximateCoordinate(order.Longitude, -180, 180)
destinationLatitude, destinationLatitudeOK := approximateCoordinate(order.Latitude, -90, 90)
infra.Response.Success(ctx, gin.H{
"identity": order.Identity, "status_code": order.OrderStatus, "status_name": gasOrderStatusName(order.OrderStatus),
"status_message": deliveryStatusMessage(order.OrderStatus), "appointment_at": order.AppointmentAt,
"updated_at": nullableTrackTime(track.ID != 0, track.UpdatedAt), "station_name": station.Name,
"staff_name": staff.Name, "staff_avatar": "", "staff_phone_masked": common.MaskPhone(staff.Phone),
"controlled_call_available": false, "route_available": len(publicPoints) > 0,
"destination_available": destinationLongitudeOK && destinationLatitudeOK,
"destination_longitude": destinationLongitude, "destination_latitude": destinationLatitude,
"points": publicPoints, "timeline": publicTimeline,
})
}
// approximateCoordinate 仅返回三位小数,避免用户接口暴露服务人员的精确实时位置。
func approximateCoordinate(value string, min, max float64) (float64, bool) {
parsed, err := strconv.ParseFloat(value, 64)
if err != nil || parsed < min || parsed > max {
return 0, false
}
return math.Round(parsed*1000) / 1000, true
}
// deliveryTimelineText 将不可变订单状态转换为用户可理解的履约节点。
func deliveryTimelineText(status int, stationName string) (string, string, bool) {
switch status {
case 18:
return "气站已接单", namedStation(stationName) + "已接收您的订单", true
case 20:
return "商品装车完成", "商品已装车,准备出发", true
case 33:
return "配送员已出发", "配送员已从" + namedStation(stationName) + "出发", true
case 34:
return "商品已送达", "请核对商品并确认签收", true
case 23:
return "配送已完成", "本次配送已完成", true
case 21:
return "配送出现异常", "平台正在处理本次配送异常", true
default:
return "", "", false
}
}
func namedStation(name string) string {
if name == "" {
return "供气站"
}
return name
}