1
This commit is contained in:
parent
49ea44c65b
commit
96793c3e9c
@ -1,4 +1,4 @@
|
|||||||
FROM node:16 as builder
|
FROM node:18 as builder
|
||||||
|
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
COPY web/package.json .
|
COPY web/package.json .
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
docker pull woodchen/czloapi
|
docker pull woodchen/czloapi
|
||||||
```
|
```
|
||||||
|
|
||||||
- [x] 当用户充值达到5刀时,自动提升为vip分组,具体金额可在`web\src\pages\TopUp\index.js`调整;
|
- [x] 当用户充值达到5刀时,自动提升为vip分组;
|
||||||
- [x] 修改颜色
|
- [x] 修改颜色
|
||||||
- [x] 日志页面新增快速筛选日期、修复渠道ID查询、自动更新消耗额度、删除日志详情(因为没有太大意义);
|
- [x] 日志页面新增快速筛选日期、修复渠道ID查询、自动更新消耗额度、修改日志详情(因为没有太大意义);
|
||||||
- [x] 用户管理界面,支持快速设置用户组,在`web\src\components\UsersTable.js`处修改相关值;
|
- [x] 用户管理界面,支持快速设置用户组,在`web\src\components\UsersTable.js`处修改相关值;
|
||||||
- [x] 令牌界面,删除无用的多种复制、聊天等按钮;
|
- [x] 令牌界面,删除无用的多种复制、聊天等按钮;
|
||||||
- [x] 删除系统访问令牌;
|
- [x] 删除系统访问令牌;
|
||||||
|
@ -435,14 +435,11 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
|
|||||||
common.LogError(ctx, "error update user quota cache: "+err.Error())
|
common.LogError(ctx, "error update user quota cache: "+err.Error())
|
||||||
}
|
}
|
||||||
if quota != 0 {
|
if quota != 0 {
|
||||||
// 对modelRatio进行计算
|
logContent := fmt.Sprintf("模型倍率 %.4f", modelRatio)
|
||||||
modelRatio = modelRatio * 0.002
|
|
||||||
logContent := fmt.Sprintf("单价 $%.4f/1k tokens,补全与官方一致", modelRatio)
|
|
||||||
model.RecordConsumeLog(ctx, userId, channelId, promptTokens, completionTokens, textRequest.Model, tokenName, quota, logContent)
|
model.RecordConsumeLog(ctx, userId, channelId, promptTokens, completionTokens, textRequest.Model, tokenName, quota, logContent)
|
||||||
model.UpdateUserUsedQuotaAndRequestCount(userId, quota)
|
model.UpdateUserUsedQuotaAndRequestCount(userId, quota)
|
||||||
model.UpdateChannelUsedQuota(channelId, quota)
|
model.UpdateChannelUsedQuota(channelId, quota)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}(c.Request.Context())
|
}(c.Request.Context())
|
||||||
|
@ -557,124 +557,6 @@ type ManageRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ManageUser Only admin user can do this
|
// ManageUser Only admin user can do this
|
||||||
// func ManageUser(c *gin.Context) {
|
|
||||||
// var req ManageRequest
|
|
||||||
// err := json.NewDecoder(c.Request.Body).Decode(&req)
|
|
||||||
|
|
||||||
// if err != nil {
|
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
|
||||||
// "success": false,
|
|
||||||
// "message": "无效的参数",
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// user := model.User{
|
|
||||||
// Username: req.Username,
|
|
||||||
// }
|
|
||||||
// // Fill attributes
|
|
||||||
// model.DB.Where(&user).First(&user)
|
|
||||||
// if user.Id == 0 {
|
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
|
||||||
// "success": false,
|
|
||||||
// "message": "用户不存在",
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// myRole := c.GetInt("role")
|
|
||||||
// if myRole <= user.Role && myRole != common.RoleRootUser {
|
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
|
||||||
// "success": false,
|
|
||||||
// "message": "无权更新同权限等级或更高权限等级的用户信息",
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// switch req.Action {
|
|
||||||
// case "disable":
|
|
||||||
// user.Status = common.UserStatusDisabled
|
|
||||||
// if user.Role == common.RoleRootUser {
|
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
|
||||||
// "success": false,
|
|
||||||
// "message": "无法禁用超级管理员用户",
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// case "enable":
|
|
||||||
// user.Status = common.UserStatusEnabled
|
|
||||||
// case "delete":
|
|
||||||
// if user.Role == common.RoleRootUser {
|
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
|
||||||
// "success": false,
|
|
||||||
// "message": "无法删除超级管理员用户",
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if err := user.Delete(); err != nil {
|
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
|
||||||
// "success": false,
|
|
||||||
// "message": err.Error(),
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// case "promote":
|
|
||||||
// if myRole != common.RoleRootUser {
|
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
|
||||||
// "success": false,
|
|
||||||
// "message": "普通管理员用户无法提升其他用户为管理员",
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if user.Role >= common.RoleAdminUser {
|
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
|
||||||
// "success": false,
|
|
||||||
// "message": "该用户已经是管理员",
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// user.Role = common.RoleAdminUser
|
|
||||||
// case "demote":
|
|
||||||
// if user.Role == common.RoleRootUser {
|
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
|
||||||
// "success": false,
|
|
||||||
// "message": "无法降级超级管理员用户",
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if user.Role == common.RoleCommonUser {
|
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
|
||||||
// "success": false,
|
|
||||||
// "message": "该用户已经是普通用户",
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// user.Role = common.RoleCommonUser
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if err := user.Update(false); err != nil {
|
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
|
||||||
// "success": false,
|
|
||||||
// "message": err.Error(),
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// user.Group = req.NewGroup
|
|
||||||
|
|
||||||
|
|
||||||
// clearUser := model.User{
|
|
||||||
// Group: user.Group,
|
|
||||||
// Role: user.Role,
|
|
||||||
// Status: user.Status,
|
|
||||||
// }
|
|
||||||
// c.JSON(http.StatusOK, gin.H{
|
|
||||||
// "success": true,
|
|
||||||
// "message": "",
|
|
||||||
// "data": clearUser,
|
|
||||||
// })
|
|
||||||
// return
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// }
|
|
||||||
func ManageUser(c *gin.Context) {
|
func ManageUser(c *gin.Context) {
|
||||||
var req ManageRequest
|
var req ManageRequest
|
||||||
err := json.NewDecoder(c.Request.Body).Decode(&req)
|
err := json.NewDecoder(c.Request.Body).Decode(&req)
|
||||||
@ -792,7 +674,7 @@ func TopUp(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
id := c.GetInt("id")
|
id := c.GetInt("id")
|
||||||
quota, err := model.Redeem(req.Key, id)
|
quota, upgradedToVIP, err := model.Redeem(req.Key, id) // 调用合并了升级逻辑的 Redeem
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
@ -804,6 +686,7 @@ func TopUp(c *gin.Context) {
|
|||||||
"success": true,
|
"success": true,
|
||||||
"message": "",
|
"message": "",
|
||||||
"data": quota,
|
"data": quota,
|
||||||
|
"upgradedToVIP": upgradedToVIP, // 返回升级信息
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -41,12 +41,13 @@ func GetRedemptionById(id int) (*Redemption, error) {
|
|||||||
return &redemption, err
|
return &redemption, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Redeem(key string, userId int) (quota int, err error) {
|
func Redeem(key string, userId int) (quota int, upgradedToVIP bool, err error) {
|
||||||
|
upgradedToVIP = false // 初始化升级状态为 false(注意:这里不需要使用 var)
|
||||||
if key == "" {
|
if key == "" {
|
||||||
return 0, errors.New("未提供兑换码")
|
return 0, false, errors.New("未提供兑换码")
|
||||||
}
|
}
|
||||||
if userId == 0 {
|
if userId == 0 {
|
||||||
return 0, errors.New("无效的 user id")
|
return 0, false, errors.New("无效的 user id")
|
||||||
}
|
}
|
||||||
redemption := &Redemption{}
|
redemption := &Redemption{}
|
||||||
|
|
||||||
@ -73,10 +74,28 @@ func Redeem(key string, userId int) (quota int, err error) {
|
|||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.New("兑换失败," + err.Error())
|
return 0, false, errors.New("兑换失败," + err.Error())
|
||||||
}
|
}
|
||||||
RecordLog(userId, LogTypeTopup, fmt.Sprintf("通过兑换码充值 %s", common.LogQuota(redemption.Quota)))
|
RecordLog(userId, LogTypeTopup, fmt.Sprintf("通过兑换码充值 %s", common.LogQuota(redemption.Quota)))
|
||||||
return redemption.Quota, nil
|
|
||||||
|
// 获取用户信息
|
||||||
|
user := &User{}
|
||||||
|
err = DB.Where("id = ?", userId).First(user).Error
|
||||||
|
if err != nil {
|
||||||
|
return redemption.Quota, upgradedToVIP, errors.New("查询用户信息失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否需要升级为 VIP
|
||||||
|
if user.Group != "vip" && user.Quota >= 5*500000 {
|
||||||
|
// 升级用户到 VIP
|
||||||
|
err = DB.Model(&User{}).Where("id = ?", userId).Update("group", "vip").Error
|
||||||
|
if err != nil {
|
||||||
|
return redemption.Quota, upgradedToVIP, errors.New("升级 VIP 失败")
|
||||||
|
}
|
||||||
|
upgradedToVIP = true // 设置升级状态为 true
|
||||||
|
}
|
||||||
|
|
||||||
|
return redemption.Quota, upgradedToVIP, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (redemption *Redemption) Insert() error {
|
func (redemption *Redemption) Insert() error {
|
||||||
|
@ -327,7 +327,7 @@ const LogsTable = () => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
sortLog('created_time');
|
sortLog('created_time');
|
||||||
}}
|
}}
|
||||||
width={3}
|
width={2}
|
||||||
>
|
>
|
||||||
时间
|
时间
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
@ -412,9 +412,9 @@ const LogsTable = () => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
sortLog('content');
|
sortLog('content');
|
||||||
}}
|
}}
|
||||||
width={isAdminUser ? 3 : 5}
|
width={isAdminUser ? 4 : 6}
|
||||||
>
|
>
|
||||||
详情
|
详情(1=$0.002/1K tokens)
|
||||||
</Table.HeaderCell>
|
</Table.HeaderCell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
</Table.Header>
|
</Table.Header>
|
||||||
|
@ -7,31 +7,8 @@ const TopUp = () => {
|
|||||||
const [redemptionCode, setRedemptionCode] = useState('');
|
const [redemptionCode, setRedemptionCode] = useState('');
|
||||||
const [topUpLink, setTopUpLink] = useState('');
|
const [topUpLink, setTopUpLink] = useState('');
|
||||||
const [userQuota, setUserQuota] = useState(0);
|
const [userQuota, setUserQuota] = useState(0);
|
||||||
const [userGroup, setUserGroup] = useState('');
|
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
|
|
||||||
// 升级用户组
|
|
||||||
const updateUserGroupIfNecessary = async (quota) => {
|
|
||||||
if (userGroup === 'vip') return; // 添加这一行
|
|
||||||
|
|
||||||
if (quota >= 5*500000) {
|
|
||||||
try {
|
|
||||||
const res = await API.post('/api/user/manage', {
|
|
||||||
username: localStorage.getItem('username'),
|
|
||||||
newGroup: 'vip'
|
|
||||||
});
|
|
||||||
const { success, message } = res.data;
|
|
||||||
if (success) {
|
|
||||||
showSuccess('已成功升级为 VIP 会员!');
|
|
||||||
} else {
|
|
||||||
showError('请右下角联系客服');
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
showError('请右下角联系客服');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const topUp = async () => {
|
const topUp = async () => {
|
||||||
if (redemptionCode === '') {
|
if (redemptionCode === '') {
|
||||||
showInfo('请输入充值码!')
|
showInfo('请输入充值码!')
|
||||||
@ -42,12 +19,15 @@ const TopUp = () => {
|
|||||||
const res = await API.post('/api/user/topup', {
|
const res = await API.post('/api/user/topup', {
|
||||||
key: redemptionCode
|
key: redemptionCode
|
||||||
});
|
});
|
||||||
const { success, message, data } = res.data;
|
const { success, message, data ,upgradedToVIP } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
showSuccess('充值成功!');
|
if (upgradedToVIP) { // 如果用户成功升级为 VIP
|
||||||
|
showSuccess('充值成功,升级为 VIP 会员');
|
||||||
|
} else {
|
||||||
|
showSuccess('充值成功');
|
||||||
|
}
|
||||||
setUserQuota((quota) => {
|
setUserQuota((quota) => {
|
||||||
const newQuota = quota + data;
|
const newQuota = quota + data;
|
||||||
updateUserGroupIfNecessary(newQuota);
|
|
||||||
return newQuota;
|
return newQuota;
|
||||||
});
|
});
|
||||||
setRedemptionCode('');
|
setRedemptionCode('');
|
||||||
@ -55,7 +35,7 @@ const TopUp = () => {
|
|||||||
showError(message);
|
showError(message);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showError('请右下角联系客服');
|
showError('失败,请右下角联系客服');
|
||||||
} finally {
|
} finally {
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
}
|
}
|
||||||
@ -74,7 +54,7 @@ const TopUp = () => {
|
|||||||
const { success, message, data } = res.data;
|
const { success, message, data } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
setUserQuota(data.quota);
|
setUserQuota(data.quota);
|
||||||
setUserGroup(data.group); // 添加这一行
|
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(message);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user