diff --git a/api/core/types/chat.go b/api/core/types/chat.go index 70333339..f1692da5 100644 --- a/api/core/types/chat.go +++ b/api/core/types/chat.go @@ -56,6 +56,7 @@ type ChatSession struct { type ChatModel struct { Id uint `json:"id"` Platform Platform `json:"platform"` + Name string `json:"name"` Value string `json:"value"` Power int `json:"power"` MaxTokens int `json:"max_tokens"` // 最大响应长度 @@ -86,6 +87,21 @@ const ( PowerReward = PowerType(5) // 众筹 ) +func (t PowerType) String() string { + switch t { + case PowerRecharge: + return "充值" + case PowerConsume: + return "消费" + case PowerRefund: + return "退款" + case PowerReward: + return "众筹" + + } + return "其他" +} + type PowerMark int const ( diff --git a/api/handler/chat_role_handler.go b/api/handler/chat_role_handler.go index 35dd0a5d..4e48a60b 100644 --- a/api/handler/chat_role_handler.go +++ b/api/handler/chat_role_handler.go @@ -22,6 +22,7 @@ func NewChatRoleHandler(app *core.AppServer, db *gorm.DB) *ChatRoleHandler { // List 获取用户聊天应用列表 func (h *ChatRoleHandler) List(c *gin.Context) { + all := h.GetBool(c, "all") userId := h.GetLoginUserId(c) var roles []model.ChatRole res := h.DB.Where("enable", true).Order("sort_num ASC").Find(&roles) @@ -31,7 +32,7 @@ func (h *ChatRoleHandler) List(c *gin.Context) { } // 获取所有角色 - if userId == 0 { + if userId == 0 || all { // 转成 vo var roleVos = make([]vo.ChatRole, 0) for _, r := range roles { diff --git a/api/handler/chatimpl/chat_handler.go b/api/handler/chatimpl/chat_handler.go index d73bb598..11e10ebe 100644 --- a/api/handler/chatimpl/chat_handler.go +++ b/api/handler/chatimpl/chat_handler.go @@ -105,6 +105,7 @@ func (h *ChatHandler) ChatHandle(c *gin.Context) { session.ChatId = chatId session.Model = types.ChatModel{ Id: chatModel.Id, + Name: chatModel.Name, Value: chatModel.Value, Power: chatModel.Power, MaxTokens: chatModel.MaxTokens, @@ -535,7 +536,7 @@ func (h *ChatHandler) subUserPower(userVo vo.User, session *types.ChatSession, p Mark: types.PowerSub, Balance: userVo.Power - power, Model: session.Model.Value, - Remark: fmt.Sprintf("提问长度:%d,回复长度:%d", promptTokens, replyTokens), + Remark: fmt.Sprintf("模型名称:%s, 提问长度:%d,回复长度:%d", session.Model.Name, promptTokens, replyTokens), CreatedAt: time.Now(), }) } diff --git a/api/handler/power_log_handler.go b/api/handler/power_log_handler.go new file mode 100644 index 00000000..9bfa3219 --- /dev/null +++ b/api/handler/power_log_handler.go @@ -0,0 +1,65 @@ +package handler + +import ( + "chatplus/core" + "chatplus/core/types" + "chatplus/store/model" + "chatplus/store/vo" + "chatplus/utils" + "chatplus/utils/resp" + + "github.com/gin-gonic/gin" + "gorm.io/gorm" +) + +type PowerLogHandler struct { + BaseHandler +} + +func NewPowerLogHandler(app *core.AppServer, db *gorm.DB) *PowerLogHandler { + return &PowerLogHandler{BaseHandler: BaseHandler{App: app, DB: db}} +} + +func (h *PowerLogHandler) List(c *gin.Context) { + var data struct { + Model string `json:"model"` + Date []string `json:"date"` + Page int `json:"page"` + PageSize int `json:"page_size"` + } + if err := c.ShouldBindJSON(&data); err != nil { + resp.ERROR(c, types.InvalidArgs) + return + } + + session := h.DB.Session(&gorm.Session{}) + if data.Model != "" { + session = session.Where("model", data.Model) + } + if len(data.Date) == 2 { + start := data.Date[0] + " 00:00:00" + end := data.Date[1] + " 00:00:00" + session = session.Where("created_at >= ? AND created_at <= ?", start, end) + } + + var total int64 + session.Model(&model.PowerLog{}).Count(&total) + var items []model.PowerLog + var list = make([]vo.PowerLog, 0) + offset := (data.Page - 1) * data.PageSize + res := session.Debug().Order("id DESC").Offset(offset).Limit(data.PageSize).Find(&items) + if res.Error == nil { + for _, item := range items { + var log vo.PowerLog + err := utils.CopyObject(item, &log) + if err != nil { + continue + } + log.Id = item.Id + log.CreatedAt = item.CreatedAt.Unix() + log.TypeStr = item.Type.String() + list = append(list, log) + } + } + resp.SUCCESS(c, vo.NewPage(total, data.Page, data.PageSize, list)) +} diff --git a/api/handler/user_handler.go b/api/handler/user_handler.go index b8b47f13..f3e60305 100644 --- a/api/handler/user_handler.go +++ b/api/handler/user_handler.go @@ -108,6 +108,20 @@ func (h *UserHandler) Register(c *gin.Context) { h.DB.Model(&model.InviteCode{}).Where("code = ?", data.InviteCode).UpdateColumn("reg_num", gorm.Expr("reg_num + ?", 1)) if h.App.SysConfig.InvitePower > 0 { h.DB.Model(&model.User{}).Where("id = ?", inviteCode.UserId).UpdateColumn("power", gorm.Expr("power + ?", h.App.SysConfig.InvitePower)) + // 记录邀请算力充值日志 + var inviter model.User + h.DB.Where("id", inviteCode.UserId).First(&inviter) + h.DB.Create(&model.PowerLog{ + UserId: inviter.Id, + Username: inviter.Username, + Type: types.PowerInvite, + Amount: h.App.SysConfig.InvitePower, + Balance: inviter.Power, + Mark: types.PowerAdd, + Model: "", + Remark: fmt.Sprintf("邀请用户注册奖励,金额:%d,邀请码:%s,新用户:%s", h.App.SysConfig.InvitePower, inviteCode.Code, user.Username), + CreatedAt: time.Now(), + }) } // 添加邀请记录 diff --git a/api/main.go b/api/main.go index 20b48404..19d549e4 100644 --- a/api/main.go +++ b/api/main.go @@ -126,6 +126,7 @@ func main() { fx.Provide(handler.NewOrderHandler), fx.Provide(handler.NewProductHandler), fx.Provide(handler.NewConfigHandler), + fx.Provide(handler.NewPowerLogHandler), fx.Provide(admin.NewConfigHandler), fx.Provide(admin.NewAdminHandler), @@ -401,8 +402,9 @@ func main() { group.GET("remove", h.RemoveChat) group.GET("message/remove", h.RemoveMessage) }), - fx.Provide(handler.NewTestHandler), - fx.Invoke(func(s *core.AppServer, h *handler.TestHandler) { + fx.Invoke(func(s *core.AppServer, h *handler.PowerLogHandler) { + group := s.Engine.Group("/api/powerLog/") + group.POST("list", h.List) }), fx.Invoke(func(s *core.AppServer, db *gorm.DB) { err := s.Run(db) diff --git a/api/store/vo/power_log.go b/api/store/vo/power_log.go index ebe48c65..f0e598b7 100644 --- a/api/store/vo/power_log.go +++ b/api/store/vo/power_log.go @@ -6,9 +6,10 @@ type PowerLog struct { Id uint `json:"id"` UserId uint `json:"user_id"` Username string `json:"username"` - Type types.PowerType `json:"name"` + Type types.PowerType `json:"type"` + TypeStr string `json:"type_str"` Amount int `json:"amount"` - Mark types.PowerMark `json:"fund_type"` + Mark types.PowerMark `json:"mark"` Balance int `json:"balance"` Model string `json:"model"` Remark string `json:"remark"` diff --git a/web/src/assets/css/image-mj.css b/web/src/assets/css/image-mj.css index e7f6c922..346f198c 100644 --- a/web/src/assets/css/image-mj.css +++ b/web/src/assets/css/image-mj.css @@ -1,5 +1,6 @@ .page-mj { background-color: #282c34; + height: 100vh; } .page-mj .inner { display: flex; @@ -396,6 +397,10 @@ width: auto; height: auto; } +.page-mj .inner .task-list-box .no-more-data { + text-align: center; + padding: 20px; +} .mj-list-item-prompt .el-icon { margin-left: 10px; cursor: pointer; diff --git a/web/src/assets/css/image-mj.styl b/web/src/assets/css/image-mj.styl index 47ad2fe6..4d16d2f5 100644 --- a/web/src/assets/css/image-mj.styl +++ b/web/src/assets/css/image-mj.styl @@ -1,5 +1,6 @@ .page-mj { background-color: #282c34; + height 100vh .inner { display: flex; diff --git a/web/src/assets/css/image-sd.css b/web/src/assets/css/image-sd.css index 4528c832..5ac1d564 100644 --- a/web/src/assets/css/image-sd.css +++ b/web/src/assets/css/image-sd.css @@ -281,6 +281,10 @@ width: auto; height: auto; } +.page-sd .inner .task-list-box .no-more-data { + text-align: center; + padding: 20px; +} .page-sd .el-overlay-dialog .el-dialog { background-color: #1a1b1e; } diff --git a/web/src/assets/css/main.css b/web/src/assets/css/main.css index bb1d2c16..d1e800f8 100644 --- a/web/src/assets/css/main.css +++ b/web/src/assets/css/main.css @@ -2,137 +2,114 @@ html, body, #app, .wrapper { - width: 100%; - height: 100%; - overflow: hidden; + width: 100%; + height: 100%; + overflow: hidden; } - body { - font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; - -webkit-font-smoothing: antialiased; - text-rendering: optimizeLegibility; + font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; } - .admin-home a { - text-decoration: none; + text-decoration: none; } - .admin-home .content-box { - position: absolute; - left: 250px; - right: 0; - top: 0; - bottom: 0; - /*padding-bottom: 30px;*/ - -webkit-transition: left 0.3s ease-in-out; - transition: left 0.3s ease-in-out; - background: #f0f0f0; - overflow-y: scroll; + position: absolute; + left: 250px; + right: 0; + top: 0; + bottom: 0; + padding-bottom: 30px; + -webkit-transition: left 0.3s ease-in-out; + transition: left 0.3s ease-in-out; + background: #f0f0f0; } - .admin-home .content-box .content { - width: auto; - padding: 10px; - box-sizing: border-box; - /*BaseForm*/ + width: auto; + height: 100vh; + overflow-y: scroll; + box-sizing: border-box; +/*BaseForm*/ } - .admin-home .content-box .content .container { - padding: 30px; - background: #fff; - border: 1px solid #ddd; - border-radius: 5px; + padding: 30px; + background: #fff; + border: 1px solid #ddd; + border-radius: 5px; } - .admin-home .content-box .content .container .handle-box { - margin-bottom: 20px; + margin-bottom: 20px; } - .admin-home .content-box .content .crumbs { - margin: 10px 0; + margin: 10px 0; } - .admin-home .content-box .content .el-table th { - background-color: #f5f7fa !important; + background-color: #f5f7fa !important; } - .admin-home .content-box .content .pagination { - margin: 20px 0; - display: flex; - justify-content: center; - width: 100%; + margin: 20px 0; + display: flex; + justify-content: center; + width: 100%; } - .admin-home .content-box .content .plugins-tips { - padding: 20px 10px; - margin-bottom: 20px; + padding: 20px 10px; + margin-bottom: 20px; } - .admin-home .content-box .content .el-button + .el-tooltip { - margin-left: 10px; + margin-left: 10px; } - .admin-home .content-box .content .el-table tr:hover { - background: #f6faff; + background: #f6faff; } - .admin-home .content-box .content .mgb20 { - margin-bottom: 20px; + margin-bottom: 20px; } - .admin-home .content-box .content .move-enter-active, .admin-home .content-box .content .move-leave-active { - transition: opacity 0.1s ease; + transition: opacity 0.1s ease; } - .admin-home .content-box .content .move-enter-from, .admin-home .content-box .content .move-leave-to { - opacity: 0; + opacity: 0; } - .admin-home .content-box .content .form-box { - width: 600px; + width: 600px; } - .admin-home .content-box .content .form-box .line { - text-align: center; + text-align: center; } - .admin-home .content-box .content .el-time-panel__content::after, .admin-home .content-box .content .el-time-panel__content::before { - margin-top: -7px; + margin-top: -7px; } - .admin-home .content-box .content .el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default) { - padding-bottom: 0; + padding-bottom: 0; } - .admin-home .content-box .content [class*=" el-icon-"], .admin-home .content-box .content [class^=el-icon-] { - speak: none; - font-style: normal; - font-weight: 400; - font-variant: normal; - text-transform: none; - line-height: 1; - vertical-align: baseline; - display: inline-block; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + speak: none; + font-style: normal; + font-weight: 400; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: baseline; + display: inline-block; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } - .admin-home .content-box .content .el-sub-menu [class^=el-icon-] { - vertical-align: middle; - margin-right: 5px; - width: 24px; - text-align: center; - font-size: 18px; + vertical-align: middle; + margin-right: 5px; + width: 24px; + text-align: center; + font-size: 18px; } - .admin-home .content-box .content [hidden] { - display: none !important; + display: none !important; } - .admin-home .content-collapse { - left: 65px; + left: 65px; } diff --git a/web/src/assets/css/main.styl b/web/src/assets/css/main.styl index 09984f5f..3351cf1a 100644 --- a/web/src/assets/css/main.styl +++ b/web/src/assets/css/main.styl @@ -36,8 +36,7 @@ body { .content { width: auto; - height: 100%; - padding: 10px; + height: 100vh; overflow-y: scroll; box-sizing: border-box; diff --git a/web/src/assets/css/task-list.styl b/web/src/assets/css/task-list.styl index af045ffa..b836f26f 100644 --- a/web/src/assets/css/task-list.styl +++ b/web/src/assets/css/task-list.styl @@ -292,4 +292,9 @@ } } } + + .no-more-data { + text-align center + padding 20px + } } \ No newline at end of file diff --git a/web/src/components/LoginDialog.vue b/web/src/components/LoginDialog.vue index 0b30325c..8f22d466 100644 --- a/web/src/components/LoginDialog.vue +++ b/web/src/components/LoginDialog.vue @@ -69,6 +69,7 @@