🐛 适配新版ui
This commit is contained in:
+14
-7
@@ -1,17 +1,24 @@
|
||||
# ---- 前端构建 ----
|
||||
FROM node:22-alpine AS frontend-builder
|
||||
WORKDIR /build/new-web
|
||||
COPY new-web/package.json new-web/package-lock.json ./
|
||||
RUN npm ci
|
||||
COPY new-web/ .
|
||||
RUN npm run build
|
||||
|
||||
# ---- 后端构建 ----
|
||||
FROM golang:1.24-alpine AS backend-builder
|
||||
WORKDIR /build
|
||||
COPY . .
|
||||
|
||||
RUN go build -ldflags="-s -w" -o bin/server
|
||||
|
||||
RUN apk add --no-cache upx
|
||||
|
||||
RUN upx --best --lzma bin/server
|
||||
|
||||
# ---- 最终镜像 ----
|
||||
FROM alpine:latest
|
||||
COPY --from=backend-builder /build/bin/server /app/server
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=backend-builder /build/bin/server /app/server
|
||||
COPY --from=frontend-builder /build/new-web/dist /app/public
|
||||
|
||||
EXPOSE 8080
|
||||
RUN ls -a
|
||||
CMD ["./server"]
|
||||
CMD ["./server"]
|
||||
|
||||
@@ -1,8 +1,27 @@
|
||||
package v1
|
||||
|
||||
// TaskStatisticsItem 每日任务统计项
|
||||
// TaskStatisticsItem 每日任务统计项(旧版)
|
||||
type TaskStatisticsItem struct {
|
||||
Date string `json:"date"` // 日期 格式:2006-01-02
|
||||
PendingTask int `json:"pendingTask"` // 需要完成的任务数
|
||||
SuccessTask int `json:"successTask"` // 成功执行的任务数
|
||||
}
|
||||
|
||||
// TaskStatisticsV2Item 每日任务统计项(新版:从日志表按任务id去重)
|
||||
type TaskStatisticsV2Item struct {
|
||||
Date string `json:"date"` // 日期 格式:2006-01-02
|
||||
SuccessTask int `json:"successTask"` // 成功任务数(任务id去重)
|
||||
FailTask int `json:"failTask"` // 失败任务数(任务id去重)
|
||||
PendingTask int `json:"pendingTask"` // 待执行任务数(仅当天)
|
||||
}
|
||||
|
||||
// DashboardSummary 首页概览数据(新版)
|
||||
type DashboardSummary struct {
|
||||
Balance string `json:"balance"` // 当前余额
|
||||
TodayCost string `json:"todayCost"` // 今日消费
|
||||
YesterdayCost string `json:"yesterdayCost"` // 昨日消费
|
||||
Week1Cost string `json:"week1Cost"` // 近7日消费
|
||||
Week2Cost string `json:"week2Cost"` // 上7日消费
|
||||
TodayTaskCount int `json:"todayTaskCount"` // 今日任务数(成功+失败,任务id去重)
|
||||
YdayTaskCount int `json:"ydayTaskCount"` // 昨日任务数(成功+失败,任务id去重)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,19 @@ type UploadImageReq struct {
|
||||
TaskType cptask.TaskType `json:"taskType" v:"required#请指定任务类型"`
|
||||
}
|
||||
|
||||
type GetUploadPolicyReq struct {
|
||||
g.Meta `path:"/image/policy" method:"post" tags:"Image" summary:"获取图片上传策略"`
|
||||
CpUserId int64 `json:"cpUserId" v:"required#请指定今日校园用户"`
|
||||
TaskType cptask.TaskType `json:"taskType" v:"required#请指定任务类型"`
|
||||
}
|
||||
|
||||
type GetPreviewUrlReq struct {
|
||||
g.Meta `path:"/image/previewUrl" method:"post" tags:"Image" summary:"获取图片预览地址"`
|
||||
CpUserId int64 `json:"cpUserId" v:"required#请指定今日校园用户"`
|
||||
TaskType cptask.TaskType `json:"taskType" v:"required#请指定任务类型"`
|
||||
FileKey string `json:"fileKey" v:"required#请指定文件key"`
|
||||
}
|
||||
|
||||
type PreviewImageReq struct {
|
||||
g.Meta `path:"/image/preview" method:"get" tags:"Image" summary:"预览图片"`
|
||||
Key string `json:"key" v:"required#请指定图片key" in:"query"`
|
||||
|
||||
@@ -3,3 +3,15 @@ package v1
|
||||
type UploadImageRes struct {
|
||||
PreviewUrl string `json:"previewUrl"`
|
||||
}
|
||||
|
||||
type UploadPolicyRes struct {
|
||||
Host string `json:"host"`
|
||||
AccessId string `json:"accessId"`
|
||||
FileName string `json:"fileName"`
|
||||
Policy string `json:"policy"`
|
||||
Signature string `json:"signature"`
|
||||
}
|
||||
|
||||
type PreviewUrlRes struct {
|
||||
PreviewUrl string `json:"previewUrl"`
|
||||
}
|
||||
|
||||
@@ -77,3 +77,11 @@ type FindLocationReq struct {
|
||||
type GetTaskStatisticsReq struct {
|
||||
g.Meta `path:"/task/statistics" method:"get" tags:"CpTask" summary:"获取近七日任务统计数据"`
|
||||
}
|
||||
|
||||
type GetTaskStatisticsV2Req struct {
|
||||
g.Meta `path:"/task/statisticsV2" method:"get" tags:"CpTask" summary:"获取近七日任务统计数据V2"`
|
||||
}
|
||||
|
||||
type GetDashboardSummaryReq struct {
|
||||
g.Meta `path:"/task/dashboard" method:"get" tags:"CpTask" summary:"获取首页概览数据"`
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@ import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
type RefreshTokenReq struct {
|
||||
g.Meta `path:"/refreshToken" method:"GET" tags:"UserInfo" summary:"刷新Token"`
|
||||
}
|
||||
|
||||
type ResetPasswordReq struct {
|
||||
g.Meta `path:"/resetPassword" method:"POST" tags:"UserInfo" summary:"重置密码"`
|
||||
OldPassword string `json:"OldPassword"`
|
||||
|
||||
@@ -71,6 +71,16 @@ func (c CpTaskCtrlV1) GetTaskStatistics(ctx context.Context, req *v1.GetTaskStat
|
||||
return service.Global.CpTask.GetTaskStatistics(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpTaskCtrlV1) GetTaskStatisticsV2(ctx context.Context, req *v1.GetTaskStatisticsV2Req) (res *utils.Response[[]*v1.TaskStatisticsV2Item], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTask.GetTaskStatisticsV2(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpTaskCtrlV1) GetDashboardSummary(ctx context.Context, req *v1.GetDashboardSummaryReq) (res *utils.Response[*v1.DashboardSummary], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTask.GetDashboardSummary(ctx, req), nil
|
||||
}
|
||||
|
||||
func NewCpTaskCtrlV1() ICpTaskCtrlV1 {
|
||||
return &CpTaskCtrlV1{}
|
||||
}
|
||||
|
||||
@@ -20,4 +20,6 @@ type ICpTaskCtrlV1 interface {
|
||||
PauseTask(ctx context.Context, req *v1.PauseTaskReq) (res *utils.Response[any], err error)
|
||||
FindLocation(ctx context.Context, req *v1.FindLocationReq) (res *utils.Response[any], err error)
|
||||
GetTaskStatistics(ctx context.Context, req *v1.GetTaskStatisticsReq) (res *utils.Response[[]*v1.TaskStatisticsItem], err error)
|
||||
GetTaskStatisticsV2(ctx context.Context, req *v1.GetTaskStatisticsV2Req) (res *utils.Response[[]*v1.TaskStatisticsV2Item], err error)
|
||||
GetDashboardSummary(ctx context.Context, req *v1.GetDashboardSummaryReq) (res *utils.Response[*v1.DashboardSummary], err error)
|
||||
}
|
||||
|
||||
@@ -9,4 +9,6 @@ import (
|
||||
type ICpImageCtrlV1 interface {
|
||||
Upload(ctx context.Context, req *v1.UploadImageReq) (res *utils.Response[any], err error)
|
||||
Preview(ctx context.Context, req *v1.PreviewImageReq) (res *utils.Response[any], err error)
|
||||
GetUploadPolicy(ctx context.Context, req *v1.GetUploadPolicyReq) (res *utils.Response[any], err error)
|
||||
GetPreviewUrl(ctx context.Context, req *v1.GetPreviewUrlReq) (res *utils.Response[any], err error)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,16 @@ func (c CpImageCtrlV1) Preview(ctx context.Context, req *v1.PreviewImageReq) (re
|
||||
return service.Global.CpImage.Preview(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpImageCtrlV1) GetUploadPolicy(ctx context.Context, req *v1.GetUploadPolicyReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpImage.GetUploadPolicy(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpImageCtrlV1) GetPreviewUrl(ctx context.Context, req *v1.GetPreviewUrlReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpImage.GetPreviewUrl(ctx, req), nil
|
||||
}
|
||||
|
||||
func NewCpImageCtrlV1() ICpImageCtrlV1 {
|
||||
return &CpImageCtrlV1{}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
)
|
||||
|
||||
type IUserInfoV1 interface {
|
||||
// 刷新Token
|
||||
RefreshToken(ctx context.Context, req *v1.RefreshTokenReq) (*utils.Response[any], error)
|
||||
PermissionList(ctx context.Context, _ *v1.CommonReq) (*utils.Response[*v1.UserPermissionRes], error)
|
||||
//用户基础信息
|
||||
UserInfo(ctx context.Context, _ *v1.CommonReq) (*utils.Response[any], error)
|
||||
|
||||
@@ -3,6 +3,7 @@ package user_login
|
||||
import (
|
||||
"context"
|
||||
v1 "likedream-goframe/internal/api/v1"
|
||||
cst "likedream-goframe/internal/common/cst"
|
||||
"likedream-goframe/internal/ent"
|
||||
"likedream-goframe/internal/framework/captcha"
|
||||
"likedream-goframe/internal/framework/redis"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
"likedream-goframe/internal/utils"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
type UserInfoV1 struct {
|
||||
@@ -19,6 +21,15 @@ func NewUserInfoV1() IUserInfoV1 {
|
||||
return &UserInfoV1{}
|
||||
}
|
||||
|
||||
// 刷新Token(token有效期内可换取新token)
|
||||
func (c *UserInfoV1) RefreshToken(ctx context.Context, _ *v1.RefreshTokenReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
user := utils.GetUserInfoFromCtx(ctx)
|
||||
r := ghttp.RequestFromCtx(ctx)
|
||||
r.Response.Header().Set(cst.AuthorizationKey, utils.GenerateToken(user.ID))
|
||||
return utils.SuccessWithMsg("刷新成功"), nil
|
||||
}
|
||||
|
||||
// 获取用户权限列表
|
||||
func (c *UserInfoV1) PermissionList(ctx context.Context, _ *v1.CommonReq) (res *utils.Response[*v1.UserPermissionRes], err error) {
|
||||
defer utils.Pass(&err)
|
||||
|
||||
@@ -110,3 +110,63 @@ func convertTaskType(ctx context.Context, tt cptask.TaskType) types.TaskType {
|
||||
func NewCpImageServiceV1() *CpImageServiceV1 {
|
||||
return &CpImageServiceV1{}
|
||||
}
|
||||
|
||||
func (v CpImageServiceV1) GetUploadPolicy(ctx context.Context, req *v1.GetUploadPolicyReq) *utils.Response[any] {
|
||||
user := utils.GetUserInfoFromCtx(ctx)
|
||||
cpUser := db.Global.CpUser.Query().
|
||||
Where(cpuser.ID(req.CpUserId), cpuser.HasSysuserWith(sysuser.ID(user.ID))).
|
||||
WithSchool().
|
||||
OnlyX(ctx)
|
||||
if cpUser == nil {
|
||||
utils.OkOrPanic(errors2.NewBusinessError(400, "非法的今日校园账号"))
|
||||
}
|
||||
|
||||
schoolDetail := school.GetSchoolDetail(ctx, cpUser.SchoolID)
|
||||
refreshResult := login.EnsureCookieValid(ctx, &login.RefreshCookieParams{
|
||||
ID: cpUser.ID, Cookie: cpUser.Cookie, Tgc: cpUser.Tgc,
|
||||
LoginType: cpUser.LoginType, Username: cpUser.Username,
|
||||
Password: cpUser.Password, SchoolID: cpUser.SchoolID,
|
||||
}, &schoolDetail)
|
||||
if refreshResult.Cookie != cpUser.Cookie {
|
||||
db.Global.CpUser.UpdateOneID(cpUser.ID).SetCookie(refreshResult.Cookie).SetTgc(refreshResult.Tgc).ExecX(ctx)
|
||||
}
|
||||
|
||||
taskType := convertTaskType(ctx, req.TaskType)
|
||||
policy := imageuploader.GetUploadPolicyAsync(ctx, schoolDetail.WecloudUrl, taskType, refreshResult.Client)
|
||||
|
||||
return utils.SuccessWithData[any](v1.UploadPolicyRes{
|
||||
Host: policy.Host,
|
||||
AccessId: policy.AccessId,
|
||||
FileName: policy.FileName,
|
||||
Policy: policy.Policy,
|
||||
Signature: policy.Signature,
|
||||
})
|
||||
}
|
||||
|
||||
func (v CpImageServiceV1) GetPreviewUrl(ctx context.Context, req *v1.GetPreviewUrlReq) *utils.Response[any] {
|
||||
user := utils.GetUserInfoFromCtx(ctx)
|
||||
cpUser := db.Global.CpUser.Query().
|
||||
Where(cpuser.ID(req.CpUserId), cpuser.HasSysuserWith(sysuser.ID(user.ID))).
|
||||
WithSchool().
|
||||
OnlyX(ctx)
|
||||
if cpUser == nil {
|
||||
utils.OkOrPanic(errors2.NewBusinessError(400, "非法的今日校园账号"))
|
||||
}
|
||||
|
||||
schoolDetail := school.GetSchoolDetail(ctx, cpUser.SchoolID)
|
||||
refreshResult := login.EnsureCookieValid(ctx, &login.RefreshCookieParams{
|
||||
ID: cpUser.ID, Cookie: cpUser.Cookie, Tgc: cpUser.Tgc,
|
||||
LoginType: cpUser.LoginType, Username: cpUser.Username,
|
||||
Password: cpUser.Password, SchoolID: cpUser.SchoolID,
|
||||
}, &schoolDetail)
|
||||
if refreshResult.Cookie != cpUser.Cookie {
|
||||
db.Global.CpUser.UpdateOneID(cpUser.ID).SetCookie(refreshResult.Cookie).SetTgc(refreshResult.Tgc).ExecX(ctx)
|
||||
}
|
||||
|
||||
taskType := convertTaskType(ctx, req.TaskType)
|
||||
previewUrl := imageuploader.GetPreviewUrlAsync(ctx, schoolDetail.WecloudUrl, req.FileKey, taskType, refreshResult.Client)
|
||||
|
||||
return utils.SuccessWithData[any](v1.PreviewUrlRes{
|
||||
PreviewUrl: previewUrl,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -351,6 +351,149 @@ func (v CpTaskServiceV1) GetTaskStatistics(ctx context.Context, req *v1.GetTaskS
|
||||
return utils.SuccessWithData[[]*v1.TaskStatisticsItem](statistics)
|
||||
}
|
||||
|
||||
// GetTaskStatisticsV2 近七日统计(从日志表按任务id去重,当天额外查待执行数)
|
||||
func (v CpTaskServiceV1) GetTaskStatisticsV2(ctx context.Context, _ *v1.GetTaskStatisticsV2Req) *utils.Response[[]*v1.TaskStatisticsV2Item] {
|
||||
user := utils.GetUserInfoFromCtx(ctx)
|
||||
now := time.Now()
|
||||
today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||
statistics := make([]*v1.TaskStatisticsV2Item, 7)
|
||||
|
||||
for i := 6; i >= 0; i-- {
|
||||
date := now.AddDate(0, 0, -i)
|
||||
dateStr := date.Format("2006-01-02")
|
||||
startOfDay := time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location())
|
||||
endOfDay := startOfDay.AddDate(0, 0, 1)
|
||||
|
||||
// 成功任务数(按 cp_task_id 去重)
|
||||
var successIds []int64
|
||||
db2.Global.CpTaskLog.Query().
|
||||
Where(func(s *sql.Selector) {
|
||||
s.Where(sql.GTE(s.C("create_time"), startOfDay))
|
||||
s.Where(sql.LT(s.C("create_time"), endOfDay))
|
||||
s.Where(sql.EQ(s.C("is_success"), true))
|
||||
s.Where(sql.EQ(s.C("system_user_id"), user.ID))
|
||||
}).
|
||||
Unique(false).
|
||||
Select("cp_task_id").
|
||||
Modify(func(s *sql.Selector) {
|
||||
s.Distinct()
|
||||
}).
|
||||
ScanX(ctx, &successIds)
|
||||
|
||||
// 失败任务数(按 cp_task_id 去重)
|
||||
var failIds []int64
|
||||
db2.Global.CpTaskLog.Query().
|
||||
Where(func(s *sql.Selector) {
|
||||
s.Where(sql.GTE(s.C("create_time"), startOfDay))
|
||||
s.Where(sql.LT(s.C("create_time"), endOfDay))
|
||||
s.Where(sql.EQ(s.C("is_success"), false))
|
||||
s.Where(sql.EQ(s.C("system_user_id"), user.ID))
|
||||
}).
|
||||
Unique(false).
|
||||
Select("cp_task_id").
|
||||
Modify(func(s *sql.Selector) {
|
||||
s.Distinct()
|
||||
}).
|
||||
ScanX(ctx, &failIds)
|
||||
|
||||
item := &v1.TaskStatisticsV2Item{
|
||||
Date: dateStr,
|
||||
SuccessTask: len(successIds),
|
||||
FailTask: len(failIds),
|
||||
}
|
||||
|
||||
// 仅当天查待执行任务数
|
||||
if startOfDay.Equal(today) {
|
||||
item.PendingTask = db2.Global.CpTask.Query().
|
||||
Where(
|
||||
cptask.HasSysUserWith(sysuser.ID(user.ID)),
|
||||
cptask.TaskStatusNEQ(cptask.TaskStatusPause),
|
||||
cptask.FrequencyGT(0),
|
||||
).
|
||||
Where(func(s *sql.Selector) {
|
||||
s.Where(sql.ExprP("frequency > success_count"))
|
||||
}).
|
||||
CountX(ctx)
|
||||
}
|
||||
|
||||
statistics[6-i] = item
|
||||
}
|
||||
|
||||
return utils.SuccessWithData[[]*v1.TaskStatisticsV2Item](statistics)
|
||||
}
|
||||
|
||||
// GetDashboardSummary 首页概览:余额、消费对比、任务数对比
|
||||
func (v CpTaskServiceV1) GetDashboardSummary(ctx context.Context, _ *v1.GetDashboardSummaryReq) *utils.Response[*v1.DashboardSummary] {
|
||||
user := utils.GetUserInfoFromCtx(ctx)
|
||||
now := time.Now()
|
||||
today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||
yesterday := today.AddDate(0, 0, -1)
|
||||
week1Start := today.AddDate(0, 0, -7)
|
||||
week2Start := today.AddDate(0, 0, -14)
|
||||
|
||||
// 当前余额
|
||||
balanceStr := user.Balance.String()
|
||||
|
||||
// 查询某时间段内的消费总额(type=decrease)
|
||||
queryCost := func(start, end time.Time) string {
|
||||
type SumResult struct {
|
||||
Total *string `json:"total"`
|
||||
}
|
||||
var results []SumResult
|
||||
db2.Global.SysBalanceRecord.Query().
|
||||
Where(func(s *sql.Selector) {
|
||||
s.Where(sql.EQ(s.C("user_id"), user.ID))
|
||||
s.Where(sql.EQ(s.C("type"), "decrease"))
|
||||
s.Where(sql.GTE(s.C("create_time"), start))
|
||||
s.Where(sql.LT(s.C("create_time"), end))
|
||||
}).
|
||||
Modify(func(s *sql.Selector) {
|
||||
s.Select(sql.As(sql.Sum(s.C("amount")), "total"))
|
||||
}).
|
||||
ScanX(ctx, &results)
|
||||
if len(results) > 0 && results[0].Total != nil {
|
||||
return *results[0].Total
|
||||
}
|
||||
return "0"
|
||||
}
|
||||
|
||||
todayCost := queryCost(today, today.AddDate(0, 0, 1))
|
||||
yesterdayCost := queryCost(yesterday, today)
|
||||
week1Cost := queryCost(week1Start, today)
|
||||
week2Cost := queryCost(week2Start, week1Start)
|
||||
|
||||
// 查询某天的任务数(成功+失败,按任务id去重)
|
||||
queryTaskCount := func(start, end time.Time) int {
|
||||
var taskIds []int64
|
||||
db2.Global.CpTaskLog.Query().
|
||||
Where(func(s *sql.Selector) {
|
||||
s.Where(sql.GTE(s.C("create_time"), start))
|
||||
s.Where(sql.LT(s.C("create_time"), end))
|
||||
s.Where(sql.EQ(s.C("system_user_id"), user.ID))
|
||||
}).
|
||||
Unique(false).
|
||||
Select("cp_task_id").
|
||||
Modify(func(s *sql.Selector) {
|
||||
s.Distinct()
|
||||
}).
|
||||
ScanX(ctx, &taskIds)
|
||||
return len(taskIds)
|
||||
}
|
||||
|
||||
todayTaskCount := queryTaskCount(today, today.AddDate(0, 0, 1))
|
||||
ydayTaskCount := queryTaskCount(yesterday, today)
|
||||
|
||||
return utils.SuccessWithData[*v1.DashboardSummary](&v1.DashboardSummary{
|
||||
Balance: balanceStr,
|
||||
TodayCost: todayCost,
|
||||
YesterdayCost: yesterdayCost,
|
||||
Week1Cost: week1Cost,
|
||||
Week2Cost: week2Cost,
|
||||
TodayTaskCount: todayTaskCount,
|
||||
YdayTaskCount: ydayTaskCount,
|
||||
})
|
||||
}
|
||||
|
||||
func NewCpTaskServiceV1() *CpTaskServiceV1 {
|
||||
return &CpTaskServiceV1{}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user