mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-04 23:16:37 +08:00
裁剪
swagger 移除 merchant swagger 改造首页内容为通用后台管理系统定位 - 修改首页标题从 'LINUX DO Credit' 改为 'Modern Platform' - 更新副标题为 '为二次开发而生' - 更新首页描述为通用平台的特点 - 更新首页特性标签为 '开箱即用、高度可扩展、工业级基建' - 修改展示卡片为技术栈和二次开发相关 - 更新开发者示例代码为通用的注册和 API Key 获取示例 - 更新页脚品牌名为 'Modern Platform' - 调整页脚导航链接为通用平台相关内容 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> 去除遗留 裁剪 移除 /api/v1/user/pay-key 相关代码 - 删除后端 UpdatePayKey 处理器函数和 UpdatePayKeyRequest 结构体 - 删除 User 模型中的 PayKey 字段 - 删除 User.VerifyPayKey 方法 - 删除 EncryptPayKeyFailed 错误常量 - 删除 /api/v1/user/pay-key PUT 路由 - 删除 OAuth 返回中的 IsPayKey 字段 - 删除前端 UserService.updatePayKey 方法 - 删除前端所有支付密钥 UI 和逻辑 - 更新相关的导出和注释 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> 去除遗留 api 修正 系统配置 前端裁剪 后端裁剪 init
This commit is contained in:
@@ -31,6 +31,7 @@ import (
|
||||
type CreateSystemConfigRequest struct {
|
||||
Key string `json:"key" binding:"required,max=64"`
|
||||
Value string `json:"value" binding:"required,max=255"`
|
||||
Type string `json:"type" binding:"required,oneof=system business"`
|
||||
Description string `json:"description" binding:"max=255"`
|
||||
}
|
||||
|
||||
@@ -41,10 +42,12 @@ type UpdateSystemConfigRequest struct {
|
||||
}
|
||||
|
||||
// CreateSystemConfig 创建系统配置
|
||||
// @Summary 创建系统配置
|
||||
// @Description 创建一条新的系统配置项,配置键不可重复,同时将新配置同步到 Redis,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body CreateSystemConfigRequest true "request body"
|
||||
// @Param request body CreateSystemConfigRequest true "创建请求参数"
|
||||
// @Success 200 {object} util.ResponseAny
|
||||
// @Router /api/v1/admin/system-configs [post]
|
||||
func CreateSystemConfig(c *gin.Context) {
|
||||
@@ -67,6 +70,7 @@ func CreateSystemConfig(c *gin.Context) {
|
||||
config := model.SystemConfig{
|
||||
Key: req.Key,
|
||||
Value: req.Value,
|
||||
Type: req.Type,
|
||||
Description: req.Description,
|
||||
}
|
||||
|
||||
@@ -90,15 +94,22 @@ func CreateSystemConfig(c *gin.Context) {
|
||||
}
|
||||
|
||||
// ListSystemConfigs 获取系统配置列表
|
||||
// @Summary 获取系统配置列表
|
||||
// @Description 返回所有系统配置列表,支持按配置类型(system/business)过滤,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Param type query string false "配置类型(system/business)"
|
||||
// @Success 200 {object} util.ResponseAny
|
||||
// @Router /api/v1/admin/system-configs [get]
|
||||
func ListSystemConfigs(c *gin.Context) {
|
||||
configType := c.Query("type")
|
||||
query := db.DB(c.Request.Context()).Order("created_at DESC")
|
||||
if configType != "" {
|
||||
query = query.Where("type = ?", configType)
|
||||
}
|
||||
|
||||
var configs []model.SystemConfig
|
||||
if err := db.DB(c.Request.Context()).
|
||||
Order("created_at DESC").
|
||||
Find(&configs).Error; err != nil {
|
||||
if err := query.Find(&configs).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
@@ -107,6 +118,8 @@ func ListSystemConfigs(c *gin.Context) {
|
||||
}
|
||||
|
||||
// GetSystemConfig 获取单个系统配置
|
||||
// @Summary 获取单个系统配置
|
||||
// @Description 根据配置键获取对应的系统配置详情,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Param key path string true "配置键"
|
||||
@@ -127,11 +140,13 @@ func GetSystemConfig(c *gin.Context) {
|
||||
}
|
||||
|
||||
// UpdateSystemConfig 更新系统配置
|
||||
// @Summary 更新系统配置
|
||||
// @Description 根据配置键更新对应的配置内容,同时将更新同步到 Redis,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param key path string true "配置键"
|
||||
// @Param request body UpdateSystemConfigRequest true "request body"
|
||||
// @Param request body UpdateSystemConfigRequest true "更新请求参数"
|
||||
// @Success 200 {object} util.ResponseAny
|
||||
// @Router /api/v1/admin/system-configs/{key} [put]
|
||||
func UpdateSystemConfig(c *gin.Context) {
|
||||
@@ -178,6 +193,8 @@ func UpdateSystemConfig(c *gin.Context) {
|
||||
}
|
||||
|
||||
// DeleteSystemConfig 删除系统配置
|
||||
// @Summary 删除系统配置
|
||||
// @Description 根据配置键删除对应配置,同时从 Redis 中移除对应缓存,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Param key path string true "配置键"
|
||||
|
||||
@@ -17,7 +17,6 @@ limitations under the License.
|
||||
package task
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
@@ -30,6 +29,8 @@ import (
|
||||
)
|
||||
|
||||
// ListTaskTypes 获取支持的任务类型列表
|
||||
// @Summary 获取支持的任务类型
|
||||
// @Description 返回系统支持的所有可调度任务类型列表,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Success 200 {object} util.ResponseAny
|
||||
@@ -47,10 +48,12 @@ type DispatchTaskRequest struct {
|
||||
}
|
||||
|
||||
// DispatchTask 下发任务
|
||||
// @Summary 下发异步任务
|
||||
// @Description 手动触发指定类型的异步任务,支持指定时间范围和用户,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body DispatchTaskRequest true "request body"
|
||||
// @Param request body DispatchTaskRequest true "任务请求参数"
|
||||
// @Success 200 {object} util.ResponseAny
|
||||
// @Router /api/v1/admin/tasks/dispatch [post]
|
||||
func DispatchTask(c *gin.Context) {
|
||||
@@ -69,41 +72,8 @@ func DispatchTask(c *gin.Context) {
|
||||
var taskInfo *asynq.Task
|
||||
var taskID string
|
||||
|
||||
switch req.TaskType {
|
||||
case task.TaskTypeOrderSync:
|
||||
if req.StartTime != nil && req.EndTime != nil {
|
||||
if req.EndTime.Before(*req.StartTime) {
|
||||
c.JSON(http.StatusBadRequest, util.Err(InvalidTimeRange))
|
||||
return
|
||||
}
|
||||
payload, _ := json.Marshal(map[string]interface{}{
|
||||
"start_time": req.StartTime,
|
||||
"end_time": req.EndTime,
|
||||
})
|
||||
taskInfo = asynq.NewTask(meta.AsynqTask, payload)
|
||||
taskID = fmt.Sprintf("manual_%s_%s_%s", req.TaskType,
|
||||
req.StartTime.Format("20060102150405"),
|
||||
req.EndTime.Format("20060102150405"))
|
||||
} else {
|
||||
taskInfo = asynq.NewTask(meta.AsynqTask, nil)
|
||||
taskID = fmt.Sprintf("manual_%s", req.TaskType)
|
||||
}
|
||||
|
||||
case task.TaskTypeUserGamification:
|
||||
if req.UserID == nil || *req.UserID == 0 {
|
||||
taskInfo = asynq.NewTask(task.UpdateUserGamificationScoresTask, nil)
|
||||
taskID = fmt.Sprintf("manual_%s", req.TaskType)
|
||||
} else {
|
||||
payload, _ := json.Marshal(map[string]interface{}{
|
||||
"user_id": *req.UserID,
|
||||
})
|
||||
taskInfo = asynq.NewTask(meta.AsynqTask, payload)
|
||||
taskID = fmt.Sprintf("manual_%s_user_%d", req.TaskType, *req.UserID)
|
||||
}
|
||||
default:
|
||||
taskInfo = asynq.NewTask(meta.AsynqTask, nil)
|
||||
taskID = fmt.Sprintf("manual_%s", req.TaskType)
|
||||
}
|
||||
taskInfo = asynq.NewTask(meta.AsynqTask, nil)
|
||||
taskID = fmt.Sprintf("manual_%s", req.TaskType)
|
||||
|
||||
_, err := scheduler.AsynqClient.Enqueue(
|
||||
taskInfo,
|
||||
|
||||
@@ -64,6 +64,8 @@ type listUsersResponse struct {
|
||||
}
|
||||
|
||||
// ListUsers 获取用户列表
|
||||
// @Summary 获取用户列表
|
||||
// @Description 分页返回用户列表,支持按用户 ID 和用户名筛选,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Param request query listUsersRequest true "查询参数"
|
||||
@@ -122,10 +124,13 @@ type updateUserStatusRequest struct {
|
||||
}
|
||||
|
||||
// UpdateUserStatus 更新用户状态(启用/禁用)
|
||||
// @Summary 更新用户状态
|
||||
// @Description 启用或禁用指定用户,管理员账号无法被禁用,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "用户ID"
|
||||
// @Param request body updateUserStatusRequest true "状态"
|
||||
// @Param request body updateUserStatusRequest true "状态参数"
|
||||
// @Success 200 {object} util.ResponseAny
|
||||
// @Router /api/v1/admin/users/{id}/status [put]
|
||||
func UpdateUserStatus(c *gin.Context) {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
Copyright 2025 linux.do
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package user_pay_config
|
||||
|
||||
const (
|
||||
UserPayConfigNotFound = "支付配置不存在"
|
||||
LevelRequired = "等级不能为空"
|
||||
MinScoreRequired = "最小分数不能为空"
|
||||
ScoreRangeInvalid = "分数范围无效:最大分数必须大于最小分数"
|
||||
LevelExists = "等级已存在"
|
||||
)
|
||||
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
Copyright 2025 linux.do
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package user_pay_config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/linux-do/credit/internal/db"
|
||||
"github.com/linux-do/credit/internal/model"
|
||||
"github.com/linux-do/credit/internal/util"
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// CreateUserPayConfigRequest 创建支付配置请求
|
||||
type CreateUserPayConfigRequest struct {
|
||||
Level model.PayLevel `json:"level"`
|
||||
MinScore int64 `json:"min_score"`
|
||||
MaxScore *int64 `json:"max_score" binding:"omitempty,gtfield=MinScore"`
|
||||
DailyLimit *int64 `json:"daily_limit"`
|
||||
FeeRate decimal.Decimal `json:"fee_rate" binding:"required"`
|
||||
ScoreRate decimal.Decimal `json:"score_rate" binding:"required"`
|
||||
DistributeRate decimal.Decimal `json:"distribute_rate" binding:"required"`
|
||||
}
|
||||
|
||||
// UpdateUserPayConfigRequest 更新支付配置请求
|
||||
type UpdateUserPayConfigRequest struct {
|
||||
MinScore int64 `json:"min_score"`
|
||||
MaxScore *int64 `json:"max_score" binding:"omitempty,gtfield=MinScore"`
|
||||
DailyLimit *int64 `json:"daily_limit"`
|
||||
FeeRate decimal.Decimal `json:"fee_rate" binding:"required"`
|
||||
ScoreRate decimal.Decimal `json:"score_rate" binding:"required"`
|
||||
DistributeRate decimal.Decimal `json:"distribute_rate" binding:"required"`
|
||||
}
|
||||
|
||||
// CreateUserPayConfig 创建支付配置
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body CreateUserPayConfigRequest true "request body"
|
||||
// @Success 200 {object} util.ResponseAny
|
||||
// @Router /api/v1/admin/user-pay-configs [post]
|
||||
func CreateUserPayConfig(c *gin.Context) {
|
||||
var req CreateUserPayConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, util.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 验证费率和积分倍率
|
||||
if err := util.ValidateRates(req.FeeRate, req.ScoreRate, req.DistributeRate); err != nil {
|
||||
c.JSON(http.StatusBadRequest, util.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查等级是否已存在
|
||||
var existing model.UserPayConfig
|
||||
if err := db.DB(c.Request.Context()).Where("level = ?", req.Level).First(&existing).Error; err == nil {
|
||||
c.JSON(http.StatusBadRequest, util.Err(LevelExists))
|
||||
return
|
||||
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
config := model.UserPayConfig{
|
||||
Level: req.Level,
|
||||
MinScore: req.MinScore,
|
||||
MaxScore: req.MaxScore,
|
||||
DailyLimit: req.DailyLimit,
|
||||
FeeRate: req.FeeRate,
|
||||
ScoreRate: req.ScoreRate,
|
||||
DistributeRate: req.DistributeRate,
|
||||
}
|
||||
|
||||
if err := db.DB(c.Request.Context()).Create(&config).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, util.OK(config))
|
||||
}
|
||||
|
||||
// ListUserPayConfigs 获取支付配置列表
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Success 200 {object} util.ResponseAny
|
||||
// @Router /api/v1/admin/user-pay-configs [get]
|
||||
func ListUserPayConfigs(c *gin.Context) {
|
||||
var configs []model.UserPayConfig
|
||||
if err := db.DB(c.Request.Context()).
|
||||
Order("min_score ASC").
|
||||
Find(&configs).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, util.OK(configs))
|
||||
}
|
||||
|
||||
// GetUserPayConfig 获取单个支付配置
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Param id path string true "配置ID"
|
||||
// @Success 200 {object} util.ResponseAny
|
||||
// @Router /api/v1/admin/user-pay-configs/{id} [get]
|
||||
func GetUserPayConfig(c *gin.Context) {
|
||||
var config model.UserPayConfig
|
||||
if err := db.DB(c.Request.Context()).Where("id = ?", c.Param("id")).First(&config).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, util.Err(UserPayConfigNotFound))
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, util.OK(config))
|
||||
}
|
||||
|
||||
// UpdateUserPayConfig 更新支付配置
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "配置ID"
|
||||
// @Param request body UpdateUserPayConfigRequest true "request body"
|
||||
// @Success 200 {object} util.ResponseAny
|
||||
// @Router /api/v1/admin/user-pay-configs/{id} [put]
|
||||
func UpdateUserPayConfig(c *gin.Context) {
|
||||
var req UpdateUserPayConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, util.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 验证费率和积分倍率
|
||||
if err := util.ValidateRates(req.FeeRate, req.ScoreRate); err != nil {
|
||||
c.JSON(http.StatusBadRequest, util.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 检查配置是否存在
|
||||
var config model.UserPayConfig
|
||||
if err := db.DB(c.Request.Context()).Where("id = ?", c.Param("id")).First(&config).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, util.Err(UserPayConfigNotFound))
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 更新配置
|
||||
if err := db.DB(c.Request.Context()).
|
||||
Model(&config).
|
||||
Updates(map[string]interface{}{
|
||||
"min_score": req.MinScore,
|
||||
"max_score": req.MaxScore,
|
||||
"fee_rate": req.FeeRate,
|
||||
"score_rate": req.ScoreRate,
|
||||
"daily_limit": req.DailyLimit,
|
||||
"distribute_rate": req.DistributeRate,
|
||||
}).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, util.OKNil())
|
||||
}
|
||||
|
||||
// DeleteUserPayConfig 删除支付配置
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Param id path string true "配置ID"
|
||||
// @Success 200 {object} util.ResponseAny
|
||||
// @Router /api/v1/admin/user-pay-configs/{id} [delete]
|
||||
func DeleteUserPayConfig(c *gin.Context) {
|
||||
// 检查配置是否存在
|
||||
var config model.UserPayConfig
|
||||
if err := db.DB(c.Request.Context()).Where("id = ?", c.Param("id")).First(&config).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, util.Err(UserPayConfigNotFound))
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DB(c.Request.Context()).Delete(&config).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, util.OKNil())
|
||||
}
|
||||
Reference in New Issue
Block a user