API/controller/server.go
2025-10-09 10:44:22 +08:00

469 lines
9.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package controller
import (
"fmt"
"net/http"
"one-api/common"
"one-api/model"
"strconv"
"time"
"github.com/gin-gonic/gin"
"github.com/shopspring/decimal"
)
// GetAllServers 获取所有服务器配置(管理员)
func GetAllServers(c *gin.Context) {
p, _ := strconv.Atoi(c.Query("p"))
if p < 0 {
p = 0
}
pageSize, _ := strconv.Atoi(c.Query("page_size"))
if pageSize <= 0 {
pageSize = common.ItemsPerPage
}
pageInfo := &common.PageInfo{
Page: p,
PageSize: pageSize,
}
servers, total, err := model.GetAllServers(pageInfo)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": servers,
"total": total,
})
}
// SearchServers 搜索服务器配置(管理员)
func SearchServers(c *gin.Context) {
keyword := c.Query("keyword")
p, _ := strconv.Atoi(c.Query("p"))
if p < 0 {
p = 0
}
pageSize, _ := strconv.Atoi(c.Query("page_size"))
if pageSize <= 0 {
pageSize = common.ItemsPerPage
}
servers, total, err := model.SearchServers(keyword, p*pageSize, pageSize)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": servers,
"total": total,
})
}
// GetServer 获取单个服务器配置(管理员)
func GetServer(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
server, err := model.GetServerById(id)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": server,
})
}
// AddServer 添加服务器配置(管理员)
func AddServer(c *gin.Context) {
server := model.Server{}
err := c.ShouldBindJSON(&server)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
err = server.Insert()
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": server,
})
}
// UpdateServer 更新服务器配置(管理员)
func UpdateServer(c *gin.Context) {
server := model.Server{}
err := c.ShouldBindJSON(&server)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
err = server.Update()
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": server,
})
}
// DeleteServer 删除服务器配置(管理员)
func DeleteServer(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
err = model.DeleteServerById(id)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
})
}
// GetEnabledServers 获取启用的服务器列表(用户)
func GetEnabledServers(c *gin.Context) {
servers, err := model.GetEnabledServers()
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": servers,
})
}
// GetAllPurchasedServers 获取所有已购服务器(管理员)
func GetAllPurchasedServers(c *gin.Context) {
p, _ := strconv.Atoi(c.Query("p"))
if p < 0 {
p = 0
}
pageSize, _ := strconv.Atoi(c.Query("page_size"))
if pageSize <= 0 {
pageSize = common.ItemsPerPage
}
pageInfo := &common.PageInfo{
Page: p,
PageSize: pageSize,
}
servers, total, err := model.GetAllPurchasedServers(pageInfo)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
// 获取用户名
type PurchasedServerWithUsername struct {
model.PurchasedServer
Username string `json:"username"`
}
serversWithUsername := make([]PurchasedServerWithUsername, len(servers))
for i, server := range servers {
username, _ := model.GetUsernameById(server.UserId, false)
serversWithUsername[i] = PurchasedServerWithUsername{
PurchasedServer: *server,
Username: username,
}
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": serversWithUsername,
"total": total,
})
}
// SearchPurchasedServers 搜索已购服务器(管理员)
func SearchPurchasedServers(c *gin.Context) {
keyword := c.Query("keyword")
p, _ := strconv.Atoi(c.Query("p"))
if p < 0 {
p = 0
}
pageSize, _ := strconv.Atoi(c.Query("page_size"))
if pageSize <= 0 {
pageSize = common.ItemsPerPage
}
servers, total, err := model.SearchPurchasedServers(keyword, p*pageSize, pageSize)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
// 获取用户名
type PurchasedServerWithUsername struct {
model.PurchasedServer
Username string `json:"username"`
}
serversWithUsername := make([]PurchasedServerWithUsername, len(servers))
for i, server := range servers {
username, _ := model.GetUsernameById(server.UserId, false)
serversWithUsername[i] = PurchasedServerWithUsername{
PurchasedServer: *server,
Username: username,
}
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": serversWithUsername,
"total": total,
})
}
// GetUserPurchasedServers 获取用户已购服务器列表
func GetUserPurchasedServers(c *gin.Context) {
userId := c.GetInt("id")
p, _ := strconv.Atoi(c.Query("p"))
if p < 0 {
p = 0
}
pageSize, _ := strconv.Atoi(c.Query("page_size"))
if pageSize <= 0 {
pageSize = common.ItemsPerPage
}
pageInfo := &common.PageInfo{
Page: p,
PageSize: pageSize,
}
servers, total, err := model.GetUserPurchasedServers(userId, pageInfo)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": servers,
"total": total,
})
}
type PurchaseServerRequest struct {
ServerId int `json:"server_id" binding:"required"`
TradeNo string `json:"trade_no"`
}
// PurchaseServer 购买服务器
func PurchaseServer(c *gin.Context) {
var req PurchaseServerRequest
err := c.ShouldBindJSON(&req)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "参数错误",
})
return
}
userId := c.GetInt("id")
// 获取服务器配置
server, err := model.GetServerById(req.ServerId)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "服务器配置不存在",
})
return
}
if server.Status != 1 {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "服务器已下架",
})
return
}
// 检查库存
if server.Stock == 0 {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "服务器库存不足",
})
return
}
// 计算需要扣除的额度
dPrice := decimal.NewFromFloat(server.Price)
dQuotaPerUnit := decimal.NewFromFloat(common.QuotaPerUnit)
quotaNeeded := int(dPrice.Mul(dQuotaPerUnit).IntPart())
// 检查用户额度
userQuota, err := model.GetUserQuota(userId, true)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "获取用户额度失败",
})
return
}
if userQuota < quotaNeeded {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": fmt.Sprintf("额度不足,需要 %s,当前额度 %s", common.LogQuota(quotaNeeded), common.LogQuota(userQuota)),
})
return
}
// 扣除用户额度
err = model.DecreaseUserQuota(userId, quotaNeeded)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "扣除额度失败",
})
return
}
// 创建已购服务器记录
now := time.Now().Unix()
expireTime := now + int64(server.Duration*24*3600)
tradeNo := req.TradeNo
if tradeNo == "" {
tradeNo = fmt.Sprintf("SRV%dNO%s", userId, fmt.Sprintf("%s%d", common.GetRandomString(6), time.Now().Unix()))
}
purchasedServer := &model.PurchasedServer{
UserId: userId,
ServerId: server.Id,
ServerTitle: server.Title,
ServerConfig: server.Config,
Price: server.Price,
Duration: server.Duration,
PurchaseTime: now,
ExpireTime: expireTime,
Status: 1,
TradeNo: tradeNo,
}
err = purchasedServer.Insert()
if err != nil {
// 回滚额度
_ = model.IncreaseUserQuota(userId, quotaNeeded, true)
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "创建订单失败",
})
return
}
// 更新库存
if server.Stock > 0 {
server.Stock--
_ = server.Update()
}
// 记录日志
model.RecordLog(userId, model.LogTypeSystem, fmt.Sprintf("购买服务器 %s,消耗额度 %s,有效期 %d 天", server.Title, common.LogQuota(quotaNeeded), server.Duration))
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "购买成功",
"data": purchasedServer,
})
}
// DeletePurchasedServer 删除已购服务器记录(管理员)
func DeletePurchasedServer(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
err = model.DeletePurchasedServerById(id)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
})
}