🐛 适配新版ui

This commit is contained in:
sugarBecomer
2026-03-24 19:36:16 +08:00
parent 4c7bc950c7
commit a6babba00d
14 changed files with 311 additions and 8 deletions
+14 -7
View File
@@ -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"]
+20 -1
View File
@@ -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去重)
}
+13
View File
@@ -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"`
+12
View File
@@ -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"`
}
+8
View File
@@ -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
View File
@@ -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)
+60
View File
@@ -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,
})
}
+143
View File
@@ -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{}
}